From 54cc95c0e54a389aa600988568d19cbac4fe3c34 Mon Sep 17 00:00:00 2001 From: Matthew Pharr Date: Wed, 12 Aug 2026 15:18:22 -0400 Subject: [PATCH 1/5] TEST - enable formatting - Update pre-commit trigger for pull requests in workflow --- .github/workflows/format.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml index d41c83bba..68b3111e2 100644 --- a/.github/workflows/format.yaml +++ b/.github/workflows/format.yaml @@ -3,18 +3,18 @@ name: Format and Hygiene # Runs the repository's pre-commit suite (JuliaFormatter + file hygiene) so that # contributors who have not run `pre-commit install` locally are still caught. # -# DISABLED as a pull request gate for now: the repository has pre-existing -# formatting drift that has to be cleaned up first. Until then, run this -# manually from the Actions tab ("Run workflow") to see the current damage. +# The `pre-commit` job fails whenever the hooks rewrite a tracked file, so it +# reports whether the repository is currently clean under the formatter. It is +# expected to fail until the one-off `pre-commit run --all-files` sweep lands. # -# To enable it as a gate, uncomment the `pull_request` trigger below. If the -# test suite's `Tests` job is a required status check, add `pre-commit` too. +# Make `pre-commit` a required status check only after that sweep, otherwise it +# blocks every pull request on pre-existing drift. on: workflow_dispatch: - # pull_request: - # branches: - # - main - # - develop + pull_request: + branches: + - main + - develop permissions: contents: read From 9e57323f9221755140cb818a03e033dc7a42a4b2 Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 19:50:44 -0500 Subject: [PATCH 2/5] Repo - MINOR - Format the repository with the pinned pre-commit hooks Output of `pre-commit run --all-files` with JuliaFormatter 1.0.62 (the version .pre-commit-config.yaml and the format workflow pin) on develop at 961484b92: Julia formatting, trailing whitespace and end-of-file fixes. Nothing else. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- Project.toml | 2 - benchmarks/benchmark_against_fortran_run.jl | 50 +- ...hmark_coil_ForcingTerms_against_fortran.jl | 121 ++-- .../benchmark_diiid_ideal_ntv_torque.jl | 26 +- .../benchmark_diiid_kinetic_stability.jl | 16 +- benchmarks/benchmark_legendre_2007.jl | 2 +- .../benchmark_solovev_kinetic_stability.jl | 46 +- benchmarks/benchmark_threads.jl | 2 +- benchmarks/equil_method_comparison.jl | 36 +- benchmarks/equil_numerical_params.jl | 26 +- benchmarks/equil_psihigh_scan.jl | 37 +- benchmarks/equil_psilow_scan.jl | 12 +- benchmarks/equil_spline_comparison.jl | 366 +++++----- .../analyze_example.jl | 2 +- .../run_imas_example.jl | 8 +- examples/LAR_beta_scan/run_scan.jl | 51 +- examples/LAR_epsilon_scan/run_scan.jl | 51 +- .../Solovev_ideal_example/analyze_example.jl | 9 +- .../analyze_example.jl | 17 +- examples/fourier_transform_usage.jl | 2 +- regression-harness/src/types.jl | 5 +- regression-harness/src/utils.jl | 2 +- src/Analysis/Equilibrium.jl | 19 +- src/Analysis/PerturbedEquilibrium.jl | 56 +- src/Analysis/PerturbedEquilibriumModes.jl | 53 +- src/Deck.jl | 25 +- src/Equilibrium/Axisymmetric/Inverse.jl | 22 +- src/Equilibrium/Derived/GeometryProfiles.jl | 4 +- src/Equilibrium/Grid/GridRefinement.jl | 4 +- src/ForceFreeStates/EulerLagrange.jl | 10 +- src/ForceFreeStates/Galerkin/GalerkinSolve.jl | 8 +- src/ForceFreeStates/Matching/MatchProblem.jl | 2 +- src/ForceFreeStates/Riccati/DeltaPrimeBVP.jl | 10 +- src/ForceFreeStates/Riccati/Propagators.jl | 47 +- src/ForceFreeStates/Surfaces/Asymptotics.jl | 4 +- src/ForceFreeStates/Surfaces/Finding.jl | 8 +- src/ForcingTerms/ForcingTerms.jl | 5 +- .../coil_geometries/jet_ex_mid.dat | 338 ++++----- src/ForcingTerms/coil_geometries/jtext_l.dat | 162 ++--- src/ForcingTerms/coil_geometries/jtext_m.dat | 162 ++--- src/ForcingTerms/coil_geometries/jtext_u.dat | 162 ++--- .../coil_geometries/mastu_efcc.dat | 338 ++++----- .../coil_geometries/mastu_rmpl.dat | 674 +++++++++--------- .../coil_geometries/mastu_rmpu.dat | 338 ++++----- src/InnerLayer/GGJ/Galerkin.jl | 2 +- src/InnerLayer/GGJ/Ray.jl | 6 +- src/InnerLayer/SLAYER/LayerInputs.jl | 2 +- src/InnerLayer/SLAYER/LayerParameters.jl | 18 +- src/KineticForces/KineticForces.jl | 4 +- src/KineticForces/Output.jl | 7 +- src/KineticForces/Torque.jl | 1 - src/KineticForces/Utils.jl | 11 +- src/LocalStability/Ballooning.jl | 54 +- .../PerturbedEquilibrium.jl | 6 +- src/PerturbedEquilibrium/ResonantCoupling.jl | 10 +- src/PerturbedEquilibrium/Response.jl | 2 +- src/PerturbedEquilibrium/SingularCoupling.jl | 4 +- .../CriticalResonantField/TorqueBalance.jl | 2 +- src/Tearing/Dispersion/BruteForceScan.jl | 24 +- src/Tearing/Dispersion/ContourSearchAMR.jl | 10 +- src/Tearing/GGJTearing.jl | 2 +- src/Tearing/HDF5Output.jl | 3 +- src/Tearing/Result.jl | 1 + src/Tearing/SLAYERTearing.jl | 19 +- src/Tearing/TearingProblem.jl | 4 +- src/Utilities/FourierTransforms.jl | 6 +- src/Utilities/HDF5Annotations.jl | 3 +- src/Utilities/HDF5Schema.jl | 12 +- src/Utilities/PhysicalConstants.jl | 8 +- src/Vacuum/DataTypes.jl | 16 +- src/Vacuum/Kernel2D.jl | 28 +- src/Vacuum/Kernel3D.jl | 4 +- src/Vacuum/Utilities.jl | 8 +- test/runtests.jl | 2 +- test/runtests_analysis_plots.jl | 15 +- test/runtests_coils.jl | 2 +- test/runtests_coordinate_invariant.jl | 4 +- test/runtests_core_capped_knots.jl | 2 +- test/runtests_critical_resonant_field.jl | 5 +- test/runtests_dispersion_amr.jl | 3 +- test/runtests_dispersion_ggj.jl | 2 +- test/runtests_dispersion_polish.jl | 4 +- test/runtests_dispersion_residual.jl | 46 +- test/runtests_dispersion_scan.jl | 50 +- test/runtests_equil.jl | 8 +- test/runtests_fouriertransforms.jl | 8 +- test/runtests_galerkin_cholesky.jl | 8 +- test/runtests_imas.jl | 54 +- test/runtests_kinetic.jl | 5 +- test/runtests_layer_overlap_fitzpatrick.jl | 7 +- test/runtests_multiion.jl | 5 +- test/runtests_parallel_integration.jl | 16 +- test/runtests_riccati.jl | 16 +- test/runtests_sfl_sampling.jl | 16 +- test/runtests_sing.jl | 3 +- test/runtests_slayer_inputs.jl | 2 +- test/runtests_slayer_runner.jl | 3 +- test/runtests_solve_api.jl | 16 +- test/runtests_vacuum.jl | 23 +- 99 files changed, 2059 insertions(+), 1883 deletions(-) diff --git a/Project.toml b/Project.toml index f3a49b5c9..f61b337b4 100644 --- a/Project.toml +++ b/Project.toml @@ -73,5 +73,3 @@ Statistics = "1" TOML = "1" Test = "1" julia = "1.11" - - diff --git a/benchmarks/benchmark_against_fortran_run.jl b/benchmarks/benchmark_against_fortran_run.jl index 138fc91fb..87464dc8b 100644 --- a/benchmarks/benchmark_against_fortran_run.jl +++ b/benchmarks/benchmark_against_fortran_run.jl @@ -538,8 +538,8 @@ function compare_phix( grid = ForcingTerms.sample_boundary_grid(equil, p.mtheta_coil, p.nzeta_coil; psi=psilim) nobs = p.mtheta_coil * p.nzeta_coil - obs_R = zeros(nobs); - obs_phi = zeros(nobs); + obs_R = zeros(nobs) + obs_phi = zeros(nobs) obs_Z = zeros(nobs) for j in 1:p.nzeta_coil, i in 1:p.mtheta_coil idx = i + (j - 1) * p.mtheta_coil @@ -547,8 +547,8 @@ function compare_phix( obs_phi[idx] = grid.phi_grid[j] + grid.phi_offset[i] obs_Z[idx] = grid.Z[i] end - B_R = zeros(nobs); - B_phi = zeros(nobs); + B_R = zeros(nobs) + B_phi = zeros(nobs) B_Z = zeros(nobs) ForcingTerms.compute_biot_savart_boundary!(B_R, B_phi, B_Z, obs_R, obs_phi, obs_Z, coil_sets) bn = zeros(p.mtheta_coil, p.nzeta_coil) @@ -584,9 +584,9 @@ end function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) lines = String[] - push!(lines, "=" ^ 72) + push!(lines, "="^72) push!(lines, "GPEC FORTRAN vs JULIA COMPARISON") - push!(lines, "=" ^ 72) + push!(lines, "="^72) push!(lines, "Fortran : $fortran_dir") push!(lines, "Julia : $(joinpath(bench_dir, "gpec.h5"))") push!(lines, "Date : $(Dates.format(Dates.now(), "yyyy-mm-dd HH:MM"))") @@ -629,9 +629,9 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) push!(lines, "") push!(lines, "--- Mercier Criterion ---") - fdi = fort["di"]; + fdi = fort["di"] fdr = fort["dr"] - jdi = julia["di"]; + jdi = julia["di"] jdr = julia["dr"] if !isempty(jdi) && !isempty(fdi) jdi_on_fg = [_interp1(jq_psi, jdi, p) for p in fq_psi] @@ -705,7 +705,7 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) m = i <= length(m_ctrl) ? m_ctrl[i] : i fl = abs(f_L[i, i]) jl = abs(j_L[i, i]) - ratio = fl > 0 ? jl/fl : NaN + ratio = fl > 0 ? jl / fl : NaN push!(lines, @sprintf("%-5d %14.4e %14.4e %-6s %10.3f", m, fl, jl, rel_pct(fl, jl), ratio)) end else @@ -724,7 +724,7 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) m = i <= length(m_ctrl) ? m_ctrl[i] : i fl = abs(f_LS[i, i]) jl = abs(j_LS[i, i]) - ratio = fl > 0 ? jl/fl : NaN + ratio = fl > 0 ? jl / fl : NaN push!(lines, @sprintf("%-5d %14.4e %14.4e %-6s %10.3f", m, fl, jl, rel_pct(fl, jl), ratio)) end else @@ -753,7 +753,7 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) jp_r = (row > 0 && !isempty(julia["rational_psi"])) ? julia["rational_psi"][row] : NaN j_phi = (row > 0 && !isempty(julia["resonant_area_weighted_field"])) ? abs(julia["resonant_area_weighted_field"][row]) : NaN - j_wisl = (row > 0 && !isempty(julia["island_half_width"])) ? 2*julia["island_half_width"][row] : NaN + j_wisl = (row > 0 && !isempty(julia["island_half_width"])) ? 2 * julia["island_half_width"][row] : NaN j_kch = (row > 0 && !isempty(julia["chirikov_parameter"])) ? julia["chirikov_parameter"][row] : NaN push!( @@ -842,16 +842,16 @@ function build_comparison_table(fort, julia, fortran_dir, bench_dir, nn) ) end - push!(lines, "=" ^ 72) + push!(lines, "="^72) return lines end function _interp1(x::AbstractVector, y::AbstractVector, xi::Real) - n = length(x); + n = length(x) n < 2 && return y[1] xi <= x[1] && return y[1] xi >= x[end] && return y[end] - i = clamp(searchsortedlast(x, xi), 1, n-1) + i = clamp(searchsortedlast(x, xi), 1, n - 1) t = (xi - x[i]) / (x[i+1] - x[i]) return y[i] + t * (y[i+1] - y[i]) end @@ -924,12 +924,12 @@ function generate_plots(fort, julia, bench_dir, nn) p6 = plot(; xlabel="m", ylabel="|b̄| [T]", title="Phi_x & Phi_tot spectrum (n=$nn)", legend=:topright) if !isempty(j_fvec) && !isempty(f_phi_x) - jfx_amps = [abs(get(Dict(zip(j_mmodes, j_fvec)), m, NaN+0im)) for m in m_ctrl] - jft_amps = [abs(get(Dict(zip(j_mmodes, j_rvec)), m, NaN+0im)) for m in m_ctrl] + jfx_amps = [abs(get(Dict(zip(j_mmodes, j_fvec)), m, NaN + 0im)) for m in m_ctrl] + jft_amps = [abs(get(Dict(zip(j_mmodes, j_rvec)), m, NaN + 0im)) for m in m_ctrl] ffx_amps = abs.(f_phi_x) fft_amps = abs.(f_phi_tot) - me, jfe = step_series(m_ctrl, replace(jfx_amps, NaN=>0.0)) - _, jte = step_series(m_ctrl, replace(jft_amps, NaN=>0.0)) + me, jfe = step_series(m_ctrl, replace(jfx_amps, NaN => 0.0)) + _, jte = step_series(m_ctrl, replace(jft_amps, NaN => 0.0)) _, ffe = step_series(m_ctrl, ffx_amps) _, fte = step_series(m_ctrl, fft_amps) plot!(p6, me, ffe; seriestype=:steppre, lw=2, color=:steelblue, label="Φ_x Fortran") @@ -1200,7 +1200,7 @@ function generate_plots(fort, julia, bench_dir, nn) j_theta_data, _, _ = PerturbedEquilibriumModes.modes_to_theta(h5_path, h5_var; keep_sfl_phi=false) j_fun = j_theta_data[:, :, 1] # (npsi, ntheta) for n=1 catch e - @warn "modes_to_theta failed for $h5_var" exception=e + @warn "modes_to_theta failed for $h5_var" exception = e end end @@ -1349,11 +1349,11 @@ function main(argv=ARGS) coil_dat_dir = joinpath(@__DIR__, "..", "src", "ForcingTerms", "coil_geometries") forcing_mode = use_file_forcing ? "file (Fortran Phi_coil)" : "coil (Julia Biot-Savart)" - println("=" ^ 72) + println("="^72) println("GPEC Fortran vs Julia Benchmark") println(" Fortran dir : $fortran_dir") println(" Forcing mode : $forcing_mode") - println("=" ^ 72) + println("="^72) println("\n[1/5] Parsing Fortran inputs ...") p = parse_fortran_run(fortran_dir) @@ -1441,15 +1441,15 @@ function main(argv=ARGS) println() table_lines = build_comparison_table(fort, julia, fortran_dir, bench_dir, p.nn) for line in table_lines - ; - println(line); + + println(line) end table_path = joinpath(bench_dir, "comparison_table.txt") open(table_path, "w") do io for line in table_lines - ; - println(io, line); + + println(io, line) end end println("\nComparison table saved to: ", abspath(table_path)) diff --git a/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl b/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl index ceea29e31..6b5456de7 100644 --- a/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl +++ b/benchmarks/benchmark_coil_ForcingTerms_against_fortran.jl @@ -25,7 +25,7 @@ using NCDatasets using Plots using Printf -const OUTPUT_DIR = joinpath(@__DIR__, "coil_pipeline") +const OUTPUT_DIR = joinpath(@__DIR__, "coil_pipeline") const COIL_DAT_DIR = joinpath(@__DIR__, "..", "src", "ForcingTerms", "coil_geometries") # --------------------------------------------------------------------------- @@ -89,38 +89,38 @@ end function parse_fortran_run(dir::String)::FortranRunParams equil_file = joinpath(dir, "equil.in") - dcon_file = joinpath(dir, "dcon.in") - coil_file = joinpath(dir, "coil.in") + dcon_file = joinpath(dir, "dcon.in") + coil_file = joinpath(dir, "coil.in") isfile(equil_file) || error("equil.in not found in $dir") - isfile(dcon_file) || error("dcon.in not found in $dir") - isfile(coil_file) || error("coil.in not found in $dir") + isfile(dcon_file) || error("dcon.in not found in $dir") + isfile(coil_file) || error("coil.in not found in $dir") - eq_text = _strip_fortran_comments(read(equil_file, String)) - dcon_text = _strip_fortran_comments(read(dcon_file, String)) - coil_text = _strip_fortran_comments(read(coil_file, String)) + eq_text = _strip_fortran_comments(read(equil_file, String)) + dcon_text = _strip_fortran_comments(read(dcon_file, String)) + coil_text = _strip_fortran_comments(read(coil_file, String)) # Equilibrium parameters - eq_type = _find_string(eq_text, "eq_type"; default="efit") - eq_file = _find_string(eq_text, "eq_filename"; default="") - jac_type = _find_string(eq_text, "jac_type"; default="hamada") - psilow = _find_scalar(eq_text, "psilow"; default=1e-4) - psihigh = _find_scalar(eq_text, "psihigh"; default=0.99) - mtheta_eq = _find_int(eq_text, "mtheta"; default=256) + eq_type = _find_string(eq_text, "eq_type"; default="efit") + eq_file = _find_string(eq_text, "eq_filename"; default="") + jac_type = _find_string(eq_text, "jac_type"; default="hamada") + psilow = _find_scalar(eq_text, "psilow"; default=1e-4) + psihigh = _find_scalar(eq_text, "psihigh"; default=0.99) + mtheta_eq = _find_int(eq_text, "mtheta"; default=256) grid_type = _find_string(eq_text, "grid_type"; default="ldp") # Toroidal mode number and m-range expansion - nn = _find_int(dcon_text, "nn"; default=1) - delta_mlow = _find_int(dcon_text, "delta_mlow"; default=8) + nn = _find_int(dcon_text, "nn"; default=1) + delta_mlow = _find_int(dcon_text, "delta_mlow"; default=8) delta_mhigh = _find_int(dcon_text, "delta_mhigh"; default=8) # Coil grid parameters mtheta_coil = _find_int(coil_text, "cmtheta"; default=480) - nzeta_coil = _find_int(coil_text, "cmzeta"; default=40) - machine = _find_string(coil_text, "machine"; default="d3d") - coil_num = _find_int(coil_text, "coil_num"; default=1) + nzeta_coil = _find_int(coil_text, "cmzeta"; default=40) + machine = _find_string(coil_text, "machine"; default="d3d") + coil_num = _find_int(coil_text, "coil_num"; default=1) - coil_names = String[] + coil_names = String[] coil_currents = Vector{Float64}[] for ci in 1:coil_num name = _find_indexed_string(coil_text, "coil_name", ci; default="coil$ci") @@ -135,9 +135,9 @@ function parse_fortran_run(dir::String)::FortranRunParams end return FortranRunParams(eq_type, eq_file, jac_type, psilow, psihigh, mtheta_eq, - grid_type, nn, delta_mlow, delta_mhigh, - mtheta_coil, nzeta_coil, machine, - coil_names, coil_currents) + grid_type, nn, delta_mlow, delta_mhigh, + mtheta_coil, nzeta_coil, machine, + coil_names, coil_currents) end function find_output_nc(dir::String, nn::Int) @@ -177,16 +177,16 @@ end nc_path = find_output_nc(run_dir, p.nn) # Read Fortran output (psilim and Phi_x spectrum) -fortran_m = Int[] -fortran_Phix = Float64[] +fortran_m = Int[] +fortran_Phix = Float64[] fortran_psilim = NaN NCDatasets.Dataset(nc_path, "r") do ds - global fortran_m = Int.(ds["m"][:]) + global fortran_m = Int.(ds["m"][:]) global fortran_psilim = Float64(ds.attrib["psilim"]) phi_x_raw = ds["Phi_x"][:, :] # (mpert, 2); col 1=cos, col 2=sin - global fortran_Phix = sqrt.(phi_x_raw[:, 1].^2 .+ phi_x_raw[:, 2].^2) + global fortran_Phix = sqrt.(phi_x_raw[:, 1] .^ 2 .+ phi_x_raw[:, 2] .^ 2) end -mlow = minimum(fortran_m) +mlow = minimum(fortran_m) mhigh = maximum(fortran_m) @printf " Fortran psilim=%.6f, m=%d:%d\n" fortran_psilim mlow mhigh @@ -196,15 +196,15 @@ mhigh = maximum(fortran_m) println("\n[2/4] Loading equilibrium ...") t_equil = @elapsed begin eq_dict = Dict{String,Any}( - "eq_type" => p.eq_type, - "eq_filename" => p.eq_filename, - "jac_type" => p.jac_type, - "psilow" => p.psilow, - "psihigh" => p.psihigh, - "mtheta" => p.mtheta_equil, - "grid_type" => p.grid_type, + "eq_type" => p.eq_type, + "eq_filename" => p.eq_filename, + "jac_type" => p.jac_type, + "psilow" => p.psilow, + "psihigh" => p.psihigh, + "mtheta" => p.mtheta_equil, + "grid_type" => p.grid_type, "psi_accuracy" => 0.001, - "flux_surface_rtol" => 1e-7, + "flux_surface_rtol" => 1e-7 ) eq_config = GeneralizedPerturbedEquilibrium.equilibrium_config(Dict{String,Any}("Equilibrium" => eq_dict), run_dir) equil = Equilibrium.PlasmaEquilibrium(eq_config) @@ -223,7 +223,7 @@ for (name, currents) in zip(p.coil_names, p.coil_currents) isfile(dat_path) || error("Coil geometry file not found: $dat_path") raw = read_coil_dat(dat_path) push!(coil_sets, CoilSet(raw.name, raw.ncoil, raw.s, raw.nw, raw.nsec, - raw.x, raw.y, raw.z, Float64.(currents[1:raw.ncoil]))) + raw.x, raw.y, raw.z, Float64.(currents[1:raw.ncoil]))) end for cs in coil_sets @printf " %-10s %d conductors currents: %s A\n" cs.name cs.ncoil string(round.(cs.currents; digits=1)) @@ -231,18 +231,22 @@ end julia_modes = ForcingMode[] bnd_grid = nothing -bn = nothing -t_biot = @elapsed begin +bn = nothing +t_biot = @elapsed begin bnd_grid = sample_boundary_grid(equil, p.mtheta_coil, p.nzeta_coil; psi=fortran_psilim) nobs = p.mtheta_coil * p.nzeta_coil - obs_R = zeros(nobs); obs_phi = zeros(nobs); obs_Z = zeros(nobs) + obs_R = zeros(nobs) + obs_phi = zeros(nobs) + obs_Z = zeros(nobs) for j in 1:p.nzeta_coil, i in 1:p.mtheta_coil idx = i + (j - 1) * p.mtheta_coil - obs_R[idx] = bnd_grid.R[i] + obs_R[idx] = bnd_grid.R[i] obs_phi[idx] = bnd_grid.phi_grid[j] + bnd_grid.phi_offset[i] - obs_Z[idx] = bnd_grid.Z[i] + obs_Z[idx] = bnd_grid.Z[i] end - B_R = zeros(nobs); B_phi = zeros(nobs); B_Z = zeros(nobs) + B_R = zeros(nobs) + B_phi = zeros(nobs) + B_Z = zeros(nobs) compute_biot_savart_boundary!(B_R, B_phi, B_Z, obs_R, obs_phi, obs_Z, coil_sets) bn = zeros(p.mtheta_coil, p.nzeta_coil) project_normal_flux!(bn, B_R, B_Z, bnd_grid) @@ -250,7 +254,7 @@ t_biot = @elapsed begin end @printf " Done in %.1f s, max|Phi_x| = %.3e T·m²\n" t_biot maximum(abs, bn) -julia_m = [md.m for md in sort(julia_modes; by=md -> md.m)] +julia_m = [md.m for md in sort(julia_modes; by=md -> md.m)] julia_amps = abs.([md.amplitude for md in sort(julia_modes; by=md -> md.m)]) # Print comparison table @@ -259,7 +263,7 @@ println(" " * "-"^55) for (jm, ja) in zip(julia_m, julia_amps) k = findfirst(==(jm), fortran_m) if !isnothing(k) - fp = fortran_Phix[k] + fp = fortran_Phix[k] ratio = ja > 1e-40 ? fp / ja : NaN @printf " %3d %12.4e %12.4e %.4f\n" jm ja fp ratio end @@ -272,7 +276,7 @@ println(" Expected ratio ≈ 1.000 for all modes.") println("\n[4/4] Generating figure ...") function step_series(m_vals, amps) - m_ext = [m_vals[1] - 1; m_vals; m_vals[end] + 1] + m_ext = [m_vals[1] - 1; m_vals; m_vals[end] + 1] amp_ext = [0.0; amps; 0.0] return m_ext, amp_ext end @@ -286,19 +290,20 @@ p2 = plot_bn_contour(bn, p.mtheta_coil, p.nzeta_coil; n=p.nn) title!(p2, "Normal flux Φₓ(θ, ζ) at ψ=$(round(fortran_psilim; digits=4))") # Panel 3: Julia vs Fortran Phi_x spectrum -jm_ext, ja_ext = step_series(julia_m, julia_amps) -fm_ext, fa_ext = step_series(fortran_m, fortran_Phix) +jm_ext, ja_ext = step_series(julia_m, julia_amps) +fm_ext, fa_ext = step_series(fortran_m, fortran_Phix) p3 = plot(; xlabel="Poloidal mode m", ylabel="|Phi_x| [T·m²]", - title="Spectrum: Julia vs Fortran (n=$(p.nn))", - legend=:topright) + title="Spectrum: Julia vs Fortran (n=$(p.nn))", + legend=:topright) plot!(p3, jm_ext, ja_ext; seriestype=:steppre, lw=2, color=:blue, - label="Julia ψ=$(round(fortran_psilim; digits=4))") + label="Julia ψ=$(round(fortran_psilim; digits=4))") plot!(p3, fm_ext, fa_ext; seriestype=:steppre, lw=2, color=:orange, - linestyle=:dash, label="Fortran Phi_x") -ylims!(p3, (0, Inf)); xlims!(p3, mlow - 2, mhigh + 2) + linestyle=:dash, label="Fortran Phi_x") +ylims!(p3, (0, Inf)); +xlims!(p3, mlow - 2, mhigh + 2); # Panel 4: Phi_x / Julia ratio -ratio_m = Int[] +ratio_m = Int[] ratio_vals = Float64[] for (jm, ja) in zip(julia_m, julia_amps) k = findfirst(==(jm), fortran_m) @@ -308,8 +313,8 @@ for (jm, ja) in zip(julia_m, julia_amps) end end p4 = plot(; xlabel="Poloidal mode m", ylabel="Phi_x / Julia", - title="Ratio (flat at 1.0 → correct)", - legend=:topright) + title="Ratio (flat at 1.0 → correct)", + legend=:topright) if !isempty(ratio_m) scatter!(p4, ratio_m, ratio_vals; color=:blue, label="ratio", markersize=5) hline!(p4, [1.0]; color=:red, linestyle=:dash, label="expected = 1.0") @@ -318,8 +323,8 @@ xlims!(p4, mlow - 2, mhigh + 2) run_label = basename(run_dir) fig = plot(p1, p2, p3, p4; - layout=(2, 2), size=(1400, 900), - plot_title="$run_label | $(p.machine) n=$(p.nn) psilim=$(round(fortran_psilim; digits=4))") + layout=(2, 2), size=(1400, 900), + plot_title="$run_label | $(p.machine) n=$(p.nn) psilim=$(round(fortran_psilim; digits=4))") out_png = joinpath(OUTPUT_DIR, "coil_pipeline_$(run_label)_n$(p.nn).png") savefig(fig, out_png) diff --git a/benchmarks/benchmark_diiid_ideal_ntv_torque.jl b/benchmarks/benchmark_diiid_ideal_ntv_torque.jl index 5b14c41b5..3b2ae96fe 100644 --- a/benchmarks/benchmark_diiid_ideal_ntv_torque.jl +++ b/benchmarks/benchmark_diiid_ideal_ntv_torque.jl @@ -35,7 +35,9 @@ const KF = GPE.KineticForces const Eq = GPE.Equilibrium const PE = GPE.PerturbedEquilibrium -"Fortran GPEC DIII-D ideal example run directory, from the environment (no on-disk default)." +""" +Fortran GPEC DIII-D ideal example run directory, from the environment (no on-disk default). +""" default_fortran_dir() = get(() -> error("Set GPEC_FORTRAN_DIIID, or pass the Fortran run directory as the first argument"), ENV, "GPEC_FORTRAN_DIIID") @@ -214,10 +216,10 @@ _p(args...) = (println(stderr, args...); flush(stderr)) _pf(fmt, args...) = (print(stderr, Printf.format(Printf.Format(fmt), args...)); flush(stderr)) function run_benchmark(fortran_dir::String=default_fortran_dir()) - _p("=" ^ 70) + _p("="^70) _p(" DIIID Kinetic Benchmark: Julia KineticForces vs Fortran PENTRC") _p(" Fortran example: $fortran_dir") - _p("=" ^ 70) + _p("="^70) inputs = discover_inputs(fortran_dir) ref = read_pentrc_reference(inputs.pentrc_nc) @@ -318,9 +320,9 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) end # Compare results - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) _p(" Results Comparison") - _p("=" ^ 70) + _p("="^70) results = Dict{String,NamedTuple}() @@ -346,13 +348,13 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) end end - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) # Check pass/fail all_pass = true for (method_key, r) in results if r.T_err > 5.0 || r.dW_err > 5.0 - @warn "$(uppercase(method_key)) exceeds 5% threshold" T_err=r.T_err dW_err=r.dW_err + @warn "$(uppercase(method_key)) exceeds 5% threshold" T_err = r.T_err dW_err = r.dW_err all_pass = false end end @@ -366,9 +368,9 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) end # Plot dT/dψ and T(ψ) overlay vs Fortran PENTRC reference - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) _p(" Plotting dT/dψ and T(ψ) overlay vs Fortran") - _p("=" ^ 70) + _p("="^70) pentrc_nc = inputs.pentrc_nc @@ -383,7 +385,7 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) dt_var = "dTdpsi_$method_key" T_var = "T_$method_key" if !(haskey(ds, psi_var) && haskey(ds, dt_var) && haskey(ds, T_var)) - @warn "Fortran NetCDF missing variables for method" method=method_key + @warn "Fortran NetCDF missing variables for method" method = method_key continue end psi_f = Array(ds[psi_var][:]) @@ -445,7 +447,7 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) savefig(p1, path1) _p(" Saved dT/dψ panel → $path1") catch err - @warn "dT/dψ panel savefig failed" method=mkey err + @warn "dT/dψ panel savefig failed" method = mkey err end # Cumulative T panel @@ -461,7 +463,7 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) savefig(p2, path2) _p(" Saved cumulative T panel → $path2") catch err - @warn "cumulative T panel savefig failed" method=mkey err + @warn "cumulative T panel savefig failed" method = mkey err end end diff --git a/benchmarks/benchmark_diiid_kinetic_stability.jl b/benchmarks/benchmark_diiid_kinetic_stability.jl index d9e77e1e5..46d970b37 100644 --- a/benchmarks/benchmark_diiid_kinetic_stability.jl +++ b/benchmarks/benchmark_diiid_kinetic_stability.jl @@ -36,7 +36,9 @@ using GeneralizedPerturbedEquilibrium const GPE = GeneralizedPerturbedEquilibrium const AnalysisFFS = GPE.Analysis.ForceFreeStates -"Fortran GPEC DIII-D kinetic example run directory, from the environment (no on-disk default)." +""" +Fortran GPEC DIII-D kinetic example run directory, from the environment (no on-disk default). +""" default_fortran_dir() = get(() -> error("Set GPEC_FORTRAN_DIIID_DCON, or pass the Fortran run directory as the first argument"), ENV, "GPEC_FORTRAN_DIIID_DCON") @@ -167,10 +169,10 @@ _p(args...) = (println(stderr, args...); flush(stderr)) _pf(fmt, args...) = (print(stderr, Printf.format(Printf.Format(fmt), args...)); flush(stderr)) function run_benchmark(fortran_dir::String=default_fortran_dir()) - _p("=" ^ 70) + _p("="^70) _p(" DIIID Kinetic-DCON Benchmark: Julia KF→FFS vs Fortran DCON") _p(" Fortran example: $fortran_dir") - _p("=" ^ 70) + _p("="^70) inputs = discover_inputs(fortran_dir) ref = read_dcon_reference(inputs.dcon_nc) @@ -204,9 +206,9 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) re_err = abs(julia_re - ref.W_t_re) / abs(ref.W_t_re) * 100 im_err = abs(julia_im - ref.W_t_im) / abs(ref.W_t_im) * 100 - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) _p(" Results Comparison (kinetic-DCON least-stable eigenvalue)") - _p("=" ^ 70) + _p("="^70) _pf(" Re(et[1]): Julia = %12.6f Fortran = %12.6f err = %6.2f%%\n", julia_re, ref.W_t_re, re_err) _pf(" Im(et[1]): Julia = %12.6f Fortran = %12.6f err = %6.2f%%\n", @@ -220,7 +222,7 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) im_pass = im_err <= 20.0 im_stretch = im_err <= 5.0 - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) if re_pass && im_pass _p(" PASS — Re within 5 %, Im within 20 %" * (im_stretch ? " (stretch: Im within 5 %)" : "")) @@ -229,7 +231,7 @@ function run_benchmark(fortran_dir::String=default_fortran_dir()) re_pass || _pf(" Re err %.2f%% > 5%%\n", re_err) im_pass || _pf(" Im err %.2f%% > 20%%\n", im_err) end - _p("=" ^ 70) + _p("="^70) # cond(F̄) vs ψ diagnostic — shows whether kinetic singular surfaces # (det(F̄)=0) were found and why peaks were/weren't accepted. diff --git a/benchmarks/benchmark_legendre_2007.jl b/benchmarks/benchmark_legendre_2007.jl index 6827d1d95..184fbe354 100644 --- a/benchmarks/benchmark_legendre_2007.jl +++ b/benchmarks/benchmark_legendre_2007.jl @@ -104,7 +104,7 @@ for (s, n) in test_cases speedup = time_1997 / time_2007 println(@sprintf("%-8.2f %-8d %-20.6f %-20.6f %-15.2fx", - s, n, time_1997*1000, time_2007*1000, speedup)) + s, n, time_1997 * 1000, time_2007 * 1000, speedup)) end println("\n3. VISUAL CHECK: rhohat parameter and integration method selection") diff --git a/benchmarks/benchmark_solovev_kinetic_stability.jl b/benchmarks/benchmark_solovev_kinetic_stability.jl index 9d0fa5629..0485951be 100644 --- a/benchmarks/benchmark_solovev_kinetic_stability.jl +++ b/benchmarks/benchmark_solovev_kinetic_stability.jl @@ -43,10 +43,10 @@ using HDF5 using GeneralizedPerturbedEquilibrium const GPE = GeneralizedPerturbedEquilibrium -const REPO = normpath(joinpath(@__DIR__, "..")) -const JULIA_FIXTURE = joinpath(REPO, "test", "test_data", "regression_solovev_kinetic_calculated") -const FORTRAN_DCON = get(ENV, "GPEC_FORTRAN_DCON", "") -const FORTRAN_SOLDIR = get(ENV, "GPEC_FORTRAN_SOLDIR", "") +const REPO = normpath(joinpath(@__DIR__, "..")) +const JULIA_FIXTURE = joinpath(REPO, "test", "test_data", "regression_solovev_kinetic_calculated") +const FORTRAN_DCON = get(ENV, "GPEC_FORTRAN_DCON", "") +const FORTRAN_SOLDIR = get(ENV, "GPEC_FORTRAN_SOLDIR", "") _p(args...) = (println(stderr, args...); flush(stderr)) @@ -90,35 +90,35 @@ function build_matched_fortran_deck(workdir::String) end gpec = TOML.parsefile(joinpath(JULIA_FIXTURE, "gpec.toml")) - eq = gpec["Equilibrium"] - ffs = gpec["ForceFreeStates"] - kf = get(gpec, "KineticForces", Dict{String,Any}()) + eq = gpec["Equilibrium"] + ffs = gpec["ForceFreeStates"] + kf = get(gpec, "KineticForces", Dict{String,Any}()) # equil.in — grid + coordinate settings to match the Julia [Equilibrium] block. eqin = joinpath(workdir, "equil.in") - replace_namelist_value!(eqin, "psilow", string(eq["psilow"])) + replace_namelist_value!(eqin, "psilow", string(eq["psilow"])) replace_namelist_value!(eqin, "psihigh", string(eq["psihigh"])) - replace_namelist_value!(eqin, "mpsi", string(eq["mpsi"])) - replace_namelist_value!(eqin, "mtheta", string(eq["mtheta"])) + replace_namelist_value!(eqin, "mpsi", string(eq["mpsi"])) + replace_namelist_value!(eqin, "mtheta", string(eq["mtheta"])) # dcon.in — kinetic flags already match; align mode band, edge truncation, n. dconin = joinpath(workdir, "dcon.in") - replace_namelist_value!(dconin, "nn", string(first(ffs["nn"]))) - replace_namelist_value!(dconin, "delta_mlow", string(get(ffs, "delta_mlow", 0))) + replace_namelist_value!(dconin, "nn", string(first(ffs["nn"]))) + replace_namelist_value!(dconin, "delta_mlow", string(get(ffs, "delta_mlow", 0))) replace_namelist_value!(dconin, "delta_mhigh", string(get(ffs, "delta_mhigh", 0))) - replace_namelist_value!(dconin, "qlow", string(ffs["qlow"])) - replace_namelist_value!(dconin, "qhigh", string(ffs["qhigh"])) + replace_namelist_value!(dconin, "qlow", string(ffs["qlow"])) + replace_namelist_value!(dconin, "qhigh", string(ffs["qhigh"])) replace_namelist_value!(dconin, "singfac_min", string(ffs["singfac_min"])) # Julia truncate_at_rational_offset defaults true (sas_flag) with rational_offset_fraction 0.2. replace_namelist_value!(dconin, "sas_flag", "t") - replace_namelist_value!(dconin, "dmlim", "0.2") + replace_namelist_value!(dconin, "dmlim", "0.2") # pentrc.in — bounce harmonics + species; defaults mirror KineticForcesControl. pentin = joinpath(workdir, "pentrc.in") - replace_namelist_value!(pentin, "nl", string(get(kf, "nl", 1))) + replace_namelist_value!(pentin, "nl", string(get(kf, "nl", 1))) replace_namelist_value!(pentin, "nutype", "\"" * string(get(kf, "nutype", "harmonic")) * "\"") replace_namelist_value!(pentin, "f0type", "\"" * string(get(kf, "f0type", "maxwellian")) * "\"") - replace_namelist_value!(pentin, "nufac", string(get(kf, "collisionality_factor", 1))) + replace_namelist_value!(pentin, "nufac", string(get(kf, "collisionality_factor", 1))) replace_namelist_value!(pentin, "kinetic_file", "\"kinetic.txt\"") # kinetic.txt — Fortran readtable wants a title line then numeric rows; the @@ -161,9 +161,9 @@ function run_julia_reference() end function run_benchmark() - _p("=" ^ 70) + _p("="^70) _p(" Solovev Kinetic-DCON Benchmark: Julia KF→FFS vs Fortran DCON") - _p("=" ^ 70) + _p("="^70) workdir = mktempdir(; prefix="solovev_kinetic_fortran_") build_matched_fortran_deck(workdir) @@ -178,15 +178,15 @@ function run_benchmark() re_err = abs(jul_re - fort_re) / abs(fort_re) * 100 im_err = abs(jul_im - fort_im) / abs(fort_im) * 100 - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) _p(" Least-stable total-energy eigenvalue (mpert matched)") - _p("=" ^ 70) + _p("="^70) _p(@sprintf(" Re(et[1]): Julia = %12.6f Fortran = %12.6f err = %6.2f%%", jul_re, fort_re, re_err)) _p(@sprintf(" Im(et[1]): Julia = %12.6f Fortran = %12.6f err = %6.2f%%", jul_im, fort_im, im_err)) re_pass = re_err <= 5.0 im_pass = im_err <= 20.0 - _p("\n" * "=" ^ 70) + _p("\n" * "="^70) if re_pass && im_pass _p(" PASS — Re within 5 %, Im within 20 %") else @@ -194,7 +194,7 @@ function run_benchmark() re_pass || _p(@sprintf(" Re err %.2f%% > 5%%", re_err)) im_pass || _p(@sprintf(" Im err %.2f%% > 20%%", im_err)) end - _p("=" ^ 70) + _p("="^70) return (; jul_re, jul_im, fort_re, fort_im, re_err, im_err, wall) end diff --git a/benchmarks/benchmark_threads.jl b/benchmarks/benchmark_threads.jl index a757a8546..2dc54c30d 100644 --- a/benchmarks/benchmark_threads.jl +++ b/benchmarks/benchmark_threads.jl @@ -49,6 +49,6 @@ for (label, ex) in [("Solovev", sol_ex), ("DIIID-like", diiid_ex)] println("$label (N=$N, nthreads=$nthreads)") @printf(" forward et[1]=%.5f t=%.2fs speedup=1.00×\n", et_fwd, t_fwd) @printf(" riccati et[1]=%.5f t=%.2fs speedup=%.2f× err=%.4f%%\n", - et_ric, t_ric, t_fwd/t_ric, err_ric) + et_ric, t_ric, t_fwd / t_ric, err_ric) println() end diff --git a/benchmarks/equil_method_comparison.jl b/benchmarks/equil_method_comparison.jl index 5f8314600..bd6faab8d 100644 --- a/benchmarks/equil_method_comparison.jl +++ b/benchmarks/equil_method_comparison.jl @@ -21,13 +21,13 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") psihigh_override = length(ARGS) > 1 ? parse(Float64, ARGS[2]) : nothing -println("=" ^ 65) +println("="^65) println("Equilibrium Method Comparison") println("Example: $example_path") -println("=" ^ 65) +println("="^65) methods = ["efit", "efit_arclength", "efit_by_inversion"] results = Dict{String,Any}() @@ -58,18 +58,18 @@ for method in methods success = false end results[method] = Dict( - "success" => success, - "pe" => pe, - "runtime" => (t1 + t2) / 2.0, - "config" => cfg + "success" => success, + "pe" => pe, + "runtime" => (t1 + t2) / 2.0, + "config" => cfg ) success && @printf(" Runtime (avg 2 warm): %.3f s\n", (t1 + t2) / 2.0) end # ─── Profile comparison ─────────────────────────────────────────────────────── -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("q(ψ) cross-method comparison") -println("=" ^ 65) +println("="^65) # Reference from the first successful method at shared psi_nodes ref_method = first(m for m in methods if results[m]["success"]) @@ -105,13 +105,13 @@ for method in methods results[method]["success"] || continue Δq = abs.([q_vals[method][i] - efit_q_interp(psi_nodes[i]) for i in 1:length(psi_nodes)]) @printf(" |q_%s - q_efit| (ψ<0.95): max=%.2e rms=%.2e\n", - method, maximum(Δq[mask_mid]), sqrt(mean(Δq[mask_mid].^2))) + method, maximum(Δq[mask_mid]), sqrt(mean(Δq[mask_mid] .^ 2))) end # ─── Roundtrip error ───────────────────────────────────────────────────────── -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("Roundtrip error: (ψ,θ)→(R,Z)→ψ_spline(R,Z)−ψ_target") -println("=" ^ 65) +println("="^65) for method in methods results[method]["success"] || continue @@ -123,7 +123,7 @@ for method in methods psio = pe.psio psi_xs = pe.rzphi_xs psi_ys = pe.rzphi_ys - mpsi = length(psi_xs) - 1 + mpsi = length(psi_xs) - 1 mtheta = length(psi_ys) - 1 errors = Float64[] @@ -131,7 +131,7 @@ for method in methods ψ_target = psi_xs[ipsi] for itheta in 1:8:mtheta+1 θ = psi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ_target, θ)) + r2 = pe.rzphi_rsquared((ψ_target, θ)) off = pe.rzphi_offset((ψ_target, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) @@ -148,10 +148,10 @@ for method in methods end # ─── GSE residual summary ───────────────────────────────────────────────────── -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("Grad-Shafranov residual (from equilibrium_gse! output — see gsec.h5 if diagnose_src=true)") println("(Showing q-monotonicity near edge as proxy since GSE requires diagnose_src=true)") -println("=" ^ 65) +println("="^65) for method in methods results[method]["success"] || continue @@ -167,9 +167,9 @@ for method in methods end # ─── Runtime summary ───────────────────────────────────────────────────────── -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("Runtime summary") -println("=" ^ 65) +println("="^65) for method in methods if results[method]["success"] @printf(" %-22s %.3f s\n", method, results[method]["runtime"]) diff --git a/benchmarks/equil_numerical_params.jl b/benchmarks/equil_numerical_params.jl index 42c2e45fd..93cff33b3 100644 --- a/benchmarks/equil_numerical_params.jl +++ b/benchmarks/equil_numerical_params.jl @@ -21,26 +21,26 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") function make_config(path, eq_type, mpsi, mtheta) raw = TOML.parsefile(path) raw["Equilibrium"]["eq_type"] = eq_type - raw["Equilibrium"]["mpsi"] = mpsi - raw["Equilibrium"]["mtheta"] = mtheta + raw["Equilibrium"]["mpsi"] = mpsi + raw["Equilibrium"]["mtheta"] = mtheta return GeneralizedPerturbedEquilibrium.equilibrium_config(raw, dirname(path)) end function roundtrip_error(pe, raw_profile) psi_xs = pe.rzphi_xs - psio = pe.psio + psio = pe.psio mtheta = length(pe.rzphi_ys) - 1 errors = Float64[] for ipsi in 1:4:length(psi_xs) ψ = psi_xs[ipsi] for itheta in 1:8:mtheta+1 θ = pe.rzphi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ, θ)) + r2 = pe.rzphi_rsquared((ψ, θ)) off = pe.rzphi_offset((ψ, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) @@ -61,9 +61,9 @@ PlasmaEquilibrium(warmup_cfg) rows = [] # ── mpsi scan ────────────────────────────────────────────────────────────────── -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("mpsi scan (mtheta=256, default reltol)") -println("=" ^ 65) +println("="^65) for method in ["efit", "efit_arclength", "efit_by_inversion"] for mpsi in [64, 128, 256] cfg = make_config(config_path, method, mpsi, 256) @@ -87,9 +87,9 @@ for method in ["efit", "efit_arclength", "efit_by_inversion"] end # ── mtheta scan ──────────────────────────────────────────────────────────────── -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("mtheta scan (mpsi=128, default reltol)") -println("=" ^ 65) +println("="^65) for method in ["efit", "efit_arclength", "efit_by_inversion"] for mtheta in [128, 256, 512] cfg = make_config(config_path, method, 128, mtheta) @@ -116,17 +116,17 @@ end # Note: reltol is not exposed through EquilibriumConfig yet. # This scan patches it by temporarily modifying the solver call. # TODO: expose etol/reltol as a config parameter when needed. -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("ODE reltol scan — NOTE: not yet exposed via config; using default reltol") println("(Add reltol to EquilibriumConfig and threading to enable this scan)") -println("=" ^ 65) +println("="^65) # ── Contour grid resolution scan (efit_by_inversion only) ───────────────────── # resolution_factor scales the adaptive contour grid of equilibrium_solver_by_inversion. # We call it directly here, bypassing the PlasmaEquilibrium constructor. -println("\n" * "=" ^ 65) +println("\n" * "="^65) println("Contour grid resolution scan (efit_by_inversion only, mpsi=128, mtheta=256)") -println("=" ^ 65) +println("="^65) for resolution_factor in [2.0, 4.0, 8.0] cfg = make_config(config_path, "efit_by_inversion", 128, 256) raw_input = Equilibrium.read_efit(cfg) diff --git a/benchmarks/equil_psihigh_scan.jl b/benchmarks/equil_psihigh_scan.jl index 9a8c9dc78..2df1356d3 100644 --- a/benchmarks/equil_psihigh_scan.jl +++ b/benchmarks/equil_psihigh_scan.jl @@ -29,7 +29,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics, HDF5 example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") psihigh_values = [0.980, 0.985, 0.990, 0.993, 0.995, 0.996, 0.997, 0.998, 0.999, 0.9995, 0.9999, 1.0] methods = ["efit", "efit_arclength", "efit_by_inversion"] @@ -81,9 +81,9 @@ end println("JIT warmup (equilibrium + FFS)...") run_ffs_et1(config_path, "efit", 0.990) -println("=" ^ 70) +println("="^70) println("psihigh robustness scan (equilibrium + stability)") -println("=" ^ 70) +println("="^70) rows = [] @@ -122,7 +122,7 @@ for method in methods ψ = psi_xs[ipsi] for itheta in 1:8:mtheta+1 θ = pe.rzphi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ, θ)) + r2 = pe.rzphi_rsquared((ψ, θ)) off = pe.rzphi_offset((ψ, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) @@ -160,13 +160,16 @@ for method in methods isnan(q_at_psihigh) ? -1.0 : q_at_psihigh, et1_str) - push!(rows, ( - method=method, psihigh=psihigh, success=success, runtime=runtime, - roundtrip_max_edge=roundtrip_max_edge, - q_mono_violations_edge=q_mono_violations_edge, - q_at_psihigh=q_at_psihigh, q_edge_slope=q_edge_slope, - et1=et1, error_msg=err_msg - )) + push!( + rows, + ( + method=method, psihigh=psihigh, success=success, runtime=runtime, + roundtrip_max_edge=roundtrip_max_edge, + q_mono_violations_edge=q_mono_violations_edge, + q_at_psihigh=q_at_psihigh, q_edge_slope=q_edge_slope, + et1=et1, error_msg=err_msg + ) + ) end end @@ -180,7 +183,7 @@ end println("\nResults saved to: $output_csv") # Summary -println("\n" * "=" ^ 70) +println("\n" * "="^70) println("Last successful psihigh per method:") for method in methods method_rows = filter(r -> r.method == method && r.success, rows) @@ -192,14 +195,16 @@ for method in methods end end -println("\n" * "=" ^ 70) +println("\n" * "="^70) println("et[1] vs psihigh (free-boundary stability eigenvalue):") println(" (positive = stable, negative = unstable)") @printf(" %-22s %s\n", "psihigh", join([@sprintf("%-22s", m) for m in methods])) for psihigh in psihigh_values - vals = [let r = findfirst(x -> x.method == m && x.psihigh == psihigh, rows) - r === nothing || isnan(rows[r].et1) ? " -" : @sprintf("%+.4f", rows[r].et1) - end for m in methods] + vals = [ + let r = findfirst(x -> x.method == m && x.psihigh == psihigh, rows) + r === nothing || isnan(rows[r].et1) ? " -" : @sprintf("%+.4f", rows[r].et1) + end for m in methods + ] @printf(" %-22.4f %s\n", psihigh, join([@sprintf("%-22s", v) for v in vals])) end println() diff --git a/benchmarks/equil_psilow_scan.jl b/benchmarks/equil_psilow_scan.jl index c7288949c..f93476c68 100644 --- a/benchmarks/equil_psilow_scan.jl +++ b/benchmarks/equil_psilow_scan.jl @@ -19,7 +19,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium using TOML, Printf, Statistics example_path = length(ARGS) > 0 ? ARGS[1] : joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") psilow_values = [1e-1, 5e-2, 1e-2, 5e-3, 1e-3, 5e-4, 1e-4] methods = ["efit", "efit_arclength", "efit_by_inversion"] @@ -42,7 +42,7 @@ function read_efit_header_qaxis(eq_filename) lines_per_block = cld(nw, 5) # q-profile starts after 4 header lines + 4 data blocks (fpol,pres,ffprime,pprime) + psi 2D block nh = parse(Int, header_parts[end]) - q_start = 6 + (4 + cld(nw*nh, 5)) * lines_per_block # rough; parse all blocks + q_start = 6 + (4 + cld(nw * nh, 5)) * lines_per_block # rough; parse all blocks # Simpler: just extrapolate from the first two q-values returned by our config return nothing # will use profile extrapolation below end @@ -52,9 +52,9 @@ println("JIT warmup...") warmup_cfg = make_config(config_path, "efit", 1e-2) PlasmaEquilibrium(warmup_cfg) -println("=" ^ 70) +println("="^70) println("psilow near-axis accuracy scan") -println("=" ^ 70) +println("="^70) rows = [] @@ -82,7 +82,7 @@ for method in methods raw_profile = Equilibrium.read_efit(cfg) psi_xs = pe.rzphi_xs mtheta = length(pe.rzphi_ys) - 1 - psio = pe.psio + psio = pe.psio # q0 extrapolated to axis (linear from innermost two grid points) q1 = pe.profiles.q_spline.y[1] @@ -96,7 +96,7 @@ for method in methods ψ = psi_xs[ipsi] for itheta in 1:8:mtheta+1 θ = pe.rzphi_ys[itheta] - r2 = pe.rzphi_rsquared((ψ, θ)) + r2 = pe.rzphi_rsquared((ψ, θ)) off = pe.rzphi_offset((ψ, θ)) rfac = sqrt(max(r2, 0.0)) η = 2π * (θ + off) diff --git a/benchmarks/equil_spline_comparison.jl b/benchmarks/equil_spline_comparison.jl index 8dbbb521b..19f906c55 100644 --- a/benchmarks/equil_spline_comparison.jl +++ b/benchmarks/equil_spline_comparison.jl @@ -27,15 +27,15 @@ using TOML, Printf, Statistics, Plots # ─── CLI arguments ───────────────────────────────────────────────────────────── example_path = length(ARGS) > 0 ? ARGS[1] : - joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") + joinpath(@__DIR__, "../examples/DIIID-like_ideal_example") psihigh_arg = length(ARGS) > 1 ? parse(Float64, ARGS[2]) : 0.997 -config_path = joinpath(example_path, "gpec.toml") +config_path = joinpath(example_path, "gpec.toml") -println("=" ^ 70) +println("="^70) println("Equilibrium Spline Comparison: efit / efit_arclength / efit_by_inversion") println("Example : $example_path") println("psihigh : $psihigh_arg") -println("=" ^ 70) +println("="^70) # ─── Output directory ────────────────────────────────────────────────────────── psihigh_tag = replace(string(psihigh_arg), "." => "p") @@ -46,38 +46,38 @@ println("Output : $outdir\n") # ─── Config factory ──────────────────────────────────────────────────────────── function make_config(path::String, eq_type::String, psihigh::Float64) raw = TOML.parsefile(path) - raw["Equilibrium"]["eq_type"] = eq_type + raw["Equilibrium"]["eq_type"] = eq_type raw["Equilibrium"]["psihigh"] = psihigh return GeneralizedPerturbedEquilibrium.equilibrium_config(raw, dirname(path)) end # ─── Load all three equilibria ───────────────────────────────────────────────── # efit is the reference; efit_arclength and efit_by_inversion are compared to it. -ref_method = "efit" -compare_methods = ["efit_arclength", "efit_by_inversion"] -all_methods = vcat(ref_method, compare_methods) +ref_method = "efit" +compare_methods = ["efit_arclength", "efit_by_inversion"] +all_methods = vcat(ref_method, compare_methods) method_color = Dict( - "efit" => :blue, - "efit_arclength" => :darkorange, - "efit_by_inversion" => :red, + "efit" => :blue, + "efit_arclength" => :darkorange, + "efit_by_inversion" => :red ) method_style = Dict( - "efit" => :solid, - "efit_arclength" => :dash, - "efit_by_inversion" => :dot, + "efit" => :solid, + "efit_arclength" => :dash, + "efit_by_inversion" => :dot ) method_label = Dict( - "efit" => "efit", - "efit_arclength" => "efit_arclength", - "efit_by_inversion" => "efit_by_inv", + "efit" => "efit", + "efit_arclength" => "efit_arclength", + "efit_by_inversion" => "efit_by_inv" ) diff_color = Dict( - "efit_arclength" => :darkorange, - "efit_by_inversion" => :red, + "efit_arclength" => :darkorange, + "efit_by_inversion" => :red ) -pes = Dict{String, Any}() +pes = Dict{String,Any}() for m in all_methods println("--- Running: $m ---") cfg = make_config(config_path, m, psihigh_arg) @@ -94,22 +94,26 @@ isempty(failed) || println("Skipping failed methods in comparisons: $(join(faile haskey(pes, ref_method) || error("Reference method '$ref_method' failed — cannot continue.") pe_ref = pes[ref_method] -all_methods = filter(m -> haskey(pes, m), all_methods) +all_methods = filter(m -> haskey(pes, m), all_methods) compare_methods_active = filter(m -> haskey(pes, m), compare_methods) # ─── Helpers ─────────────────────────────────────────────────────────────────── -"Convert (ψ, θ) straight-field-line coordinates → (R, Z) physical coordinates." +""" +Convert (ψ, θ) straight-field-line coordinates → (R, Z) physical coordinates. +""" function psi_theta_to_RZ(pe, psi, theta) - r2 = pe.rzphi_rsquared((psi, theta)) - off = pe.rzphi_offset((psi, theta)) + r2 = pe.rzphi_rsquared((psi, theta)) + off = pe.rzphi_offset((psi, theta)) rfac = sqrt(max(r2, 0.0)) - η = 2π * (theta + off) - R = pe.ro + rfac * cos(η) - Z = pe.zo + rfac * sin(η) + η = 2π * (theta + off) + R = pe.ro + rfac * cos(η) + Z = pe.zo + rfac * sin(η) return R, Z end -"Compute the full (R, Z) trace of each flux surface in psi_vals." +""" +Compute the full (R, Z) trace of each flux surface in psi_vals. +""" function flux_surface_RZ(pe, psi_vals, theta_range) R_all = [Float64[] for _ in 1:length(psi_vals)] Z_all = [Float64[] for _ in 1:length(psi_vals)] @@ -130,7 +134,7 @@ end psi_lo = pe_ref.rzphi_xs[1] psi_hi = pe_ref.rzphi_xs[end] mpsi_eval = 8 * (length(pe_ref.rzphi_xs) - 1) -psi_full = psi_lo .+ (psi_hi - psi_lo) .* sin.(range(0.0, 1.0; length=mpsi_eval+1) .* (π/2)).^2 +psi_full = psi_lo .+ (psi_hi - psi_lo) .* sin.(range(0.0, 1.0; length=mpsi_eval + 1) .* (π / 2)) .^ 2 mask_core = psi_full .< 0.10 mask_edge = psi_full .> 0.98 @@ -143,21 +147,21 @@ theta_colors = [:blue, :green, :darkorange, :purple] # ═══════════════════════════════════════════════════════════════════════════════ # 1. 1D PROFILE COMPARISONS # ═══════════════════════════════════════════════════════════════════════════════ -println("=" ^ 70) +println("="^70) println("1. 1D Profile Comparisons") -println("=" ^ 70) +println("="^70) profile_specs = [ - ("F (2π·R·Bₜ)", pe -> pe.profiles.F_spline), - ("μ₀·P", pe -> pe.profiles.P_spline), - ("dV/dψ", pe -> pe.profiles.dVdpsi_spline), - ("q", pe -> pe.profiles.q_spline), + ("F (2π·R·Bₜ)", pe -> pe.profiles.F_spline), + ("μ₀·P", pe -> pe.profiles.P_spline), + ("dV/dψ", pe -> pe.profiles.dVdpsi_spline), + ("q", pe -> pe.profiles.q_spline) ] profile_fnames = ["profile_F", "profile_P", "profile_dVdpsi", "profile_q"] for (idx, (pname, spl_getter)) in enumerate(profile_specs) spl_ref = spl_getter(pe_ref) - y_ref = [spl_ref(ψ) for ψ in psi_full] + y_ref = [spl_ref(ψ) for ψ in psi_full] p_full = plot(psi_full, y_ref; lw=2, color=method_color[ref_method], ls=method_style[ref_method], label=method_label[ref_method], @@ -187,8 +191,8 @@ for (idx, (pname, spl_getter)) in enumerate(profile_specs) for m in compare_methods_active spl_m = spl_getter(pes[m]) - y_m = [spl_m(ψ) for ψ in psi_full] - Δy = y_ref .- y_m + y_m = [spl_m(ψ) for ψ in psi_full] + Δy = y_ref .- y_m plot!(p_full, psi_full, y_m; lw=1.5, color=method_color[m], ls=method_style[m], label=method_label[m]) @@ -227,76 +231,76 @@ z_global_grid = Float64[] r_zoom_grid_vis = Float64[] z_zoom_grid_vis = Float64[] if haskey(pes, "efit_by_inversion") -let - global r_global_grid, z_global_grid, r_zoom_grid_vis, z_zoom_grid_vis - cfg_inv = make_config(config_path, "efit_by_inversion", psihigh_arg) - raw_inv = Equilibrium.read_efit(cfg_inv) - ro_g, zo_g = pes["efit_by_inversion"].ro, pes["efit_by_inversion"].zo - psio_g = raw_inv.psio - psilow_g = cfg_inv.psilow - topology_g = Equilibrium.classify_topology(raw_inv, psio_g) - - ψ_RR = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(2, 0))) - ψ_ZZ = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(0, 2))) - a_low_g = min(sqrt(2 * psilow_g * psio_g / ψ_RR), sqrt(2 * psilow_g * psio_g / ψ_ZZ)) - - nw_g = length(raw_inv.psi_in_xs) - nh_g = length(raw_inv.psi_in_ys) - β_r_g, β_z_g = 2.0, 2.0 - refine_g = 5 - - nr_g = max(4, round(Int, refine_g * nw_g)) - nz_g = max(4, round(Int, refine_g * nh_g)) - r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) - z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) - - iro_g = clamp(searchsortedfirst(r_g, ro_g), 2, length(r_g)) - izo_g = clamp(searchsortedfirst(z_g, zo_g), 2, length(z_g)) - dR_ax = r_g[iro_g] - r_g[iro_g - 1] - dZ_ax = z_g[izo_g] - z_g[izo_g - 1] - sc_r = max(1, ceil(Int, dR_ax / (0.2 * a_low_g))) - sc_z = max(1, ceil(Int, dZ_ax / (0.2 * a_low_g))) - if sc_r > 1 - nr_g = (nr_g - 1) * sc_r + 1 - r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) + let + global r_global_grid, z_global_grid, r_zoom_grid_vis, z_zoom_grid_vis + cfg_inv = make_config(config_path, "efit_by_inversion", psihigh_arg) + raw_inv = Equilibrium.read_efit(cfg_inv) + ro_g, zo_g = pes["efit_by_inversion"].ro, pes["efit_by_inversion"].zo + psio_g = raw_inv.psio + psilow_g = cfg_inv.psilow + topology_g = Equilibrium.classify_topology(raw_inv, psio_g) + + ψ_RR = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(2, 0))) + ψ_ZZ = abs(raw_inv.psi_in((ro_g, zo_g); deriv=DerivOp(0, 2))) + a_low_g = min(sqrt(2 * psilow_g * psio_g / ψ_RR), sqrt(2 * psilow_g * psio_g / ψ_ZZ)) + + nw_g = length(raw_inv.psi_in_xs) + nh_g = length(raw_inv.psi_in_ys) + β_r_g, β_z_g = 2.0, 2.0 + refine_g = 5 + + nr_g = max(4, round(Int, refine_g * nw_g)) + nz_g = max(4, round(Int, refine_g * nh_g)) + r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) + z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) + iro_g = clamp(searchsortedfirst(r_g, ro_g), 2, length(r_g)) - dR_ax = r_g[iro_g] - r_g[iro_g - 1] - end - if sc_z > 1 - nz_g = (nz_g - 1) * sc_z + 1 - z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) izo_g = clamp(searchsortedfirst(z_g, zo_g), 2, length(z_g)) - dZ_ax = z_g[izo_g] - z_g[izo_g - 1] + dR_ax = r_g[iro_g] - r_g[iro_g-1] + dZ_ax = z_g[izo_g] - z_g[izo_g-1] + sc_r = max(1, ceil(Int, dR_ax / (0.2 * a_low_g))) + sc_z = max(1, ceil(Int, dZ_ax / (0.2 * a_low_g))) + if sc_r > 1 + nr_g = (nr_g - 1) * sc_r + 1 + r_g = Equilibrium.make_stretched_r_grid(raw_inv.rmin, raw_inv.rmax, ro_g, nr_g, β_r_g) + iro_g = clamp(searchsortedfirst(r_g, ro_g), 2, length(r_g)) + dR_ax = r_g[iro_g] - r_g[iro_g-1] + end + if sc_z > 1 + nz_g = (nz_g - 1) * sc_z + 1 + z_g = Equilibrium.make_stretched_z_grid(raw_inv.zmin, raw_inv.zmax, zo_g, nz_g, topology_g, β_z_g) + izo_g = clamp(searchsortedfirst(z_g, zo_g), 2, length(z_g)) + dZ_ax = z_g[izo_g] - z_g[izo_g-1] + end + r_global_grid = r_g + z_global_grid = z_g + + d_max_g = max(dR_ax, dZ_ax) + threshold_g = (10 * d_max_g)^2 * max(ψ_RR, ψ_ZZ) / (2 * psio_g) + psi_zoom_max = 9 * threshold_g + a_zoom_r = sqrt(2 * psi_zoom_max * psio_g / ψ_RR) * 1.2 + a_zoom_z = sqrt(2 * psi_zoom_max * psio_g / ψ_ZZ) * 1.2 + sinh_β = sinh(β_r_g) + nr_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_r * 10 / (sinh_β * a_low_g))) + nz_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_z * 10 / (sinh_β * a_low_g))) + r_zoom_grid_vis = Equilibrium.make_stretched_r_grid( + max(raw_inv.rmin, ro_g - a_zoom_r), min(raw_inv.rmax, ro_g + a_zoom_r), + ro_g, nr_z, β_r_g) + z_zoom_grid_vis = Equilibrium.make_stretched_r_grid( + max(raw_inv.zmin, zo_g - a_zoom_z), min(raw_inv.zmax, zo_g + a_zoom_z), + zo_g, nz_z, β_r_g) + println(" Grid vis: global $(nr_g)×$(nz_g), zoom $(nr_z)×$(nz_z)") end - r_global_grid = r_g - z_global_grid = z_g - - d_max_g = max(dR_ax, dZ_ax) - threshold_g = (10 * d_max_g)^2 * max(ψ_RR, ψ_ZZ) / (2 * psio_g) - psi_zoom_max = 9 * threshold_g - a_zoom_r = sqrt(2 * psi_zoom_max * psio_g / ψ_RR) * 1.2 - a_zoom_z = sqrt(2 * psi_zoom_max * psio_g / ψ_ZZ) * 1.2 - sinh_β = sinh(β_r_g) - nr_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_r * 10 / (sinh_β * a_low_g))) - nz_z = max(200, ceil(Int, 8 * β_r_g * a_zoom_z * 10 / (sinh_β * a_low_g))) - r_zoom_grid_vis = Equilibrium.make_stretched_r_grid( - max(raw_inv.rmin, ro_g - a_zoom_r), min(raw_inv.rmax, ro_g + a_zoom_r), - ro_g, nr_z, β_r_g) - z_zoom_grid_vis = Equilibrium.make_stretched_r_grid( - max(raw_inv.zmin, zo_g - a_zoom_z), min(raw_inv.zmax, zo_g + a_zoom_z), - zo_g, nz_z, β_r_g) - println(" Grid vis: global $(nr_g)×$(nz_g), zoom $(nr_z)×$(nz_z)") -end end # haskey(pes, "efit_by_inversion") # ═══════════════════════════════════════════════════════════════════════════════ # 2. FLUX SURFACE CONTOUR OVERLAYS # ═══════════════════════════════════════════════════════════════════════════════ -println("\n" * "=" ^ 70) +println("\n" * "="^70) println("2. Flux Surface Contour Overlays") -println("=" ^ 70) +println("="^70) -psi_contours = collect(range(psi_lo, psi_hi; length=20)) +psi_contours = collect(range(psi_lo, psi_hi; length=20)) theta_contour = range(0.0, 1.0; length=256) R_fs = Dict(m => flux_surface_RZ(pes[m], psi_contours, theta_contour) for m in all_methods) @@ -305,7 +309,7 @@ p_ctr_full = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Flux surfaces: all methods (psihigh=$psihigh_arg)") p_ctr_core = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Deep core zoom (innermost 4 surfaces)") -p_ctr_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", +p_ctr_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Far edge / x-point zoom (outermost 3 surfaces)") for m in all_methods @@ -322,7 +326,7 @@ for m in all_methods ls=method_style[m], lw=1.5, label=lbl) end n_outer = length(psi_contours) - for k in (n_outer - 2):n_outer + for k in (n_outer-2):n_outer lbl = k == n_outer - 2 ? method_label[m] : "" plot!(p_ctr_xpt, Rs[k], Zs[k]; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) @@ -332,45 +336,47 @@ end # Grid overplots: scatter subsampled grid points on each panel (only if efit_by_inversion ran). # Global grid: every 20th R × 12th Z (grey). Zoom grid: every 3rd R × 3rd Z (darkgrey). if !isempty(r_global_grid) -let - step_rg, step_zg = 20, 12 - Rg = [r_global_grid[ir] for ir in 1:step_rg:length(r_global_grid) - for _ in 1:step_zg:length(z_global_grid)] - Zg = [z_global_grid[iz] for _ in 1:step_rg:length(r_global_grid) - for iz in 1:step_zg:length(z_global_grid)] - scatter!(p_ctr_full, Rg, Zg; ms=0.8, color=:grey, alpha=0.25, - markerstrokewidth=0, label="global grid") - - step_rz, step_zz = 3, 3 - Rz = [r_zoom_grid_vis[ir] for ir in 1:step_rz:length(r_zoom_grid_vis) - for _ in 1:step_zz:length(z_zoom_grid_vis)] - Zz = [z_zoom_grid_vis[iz] for _ in 1:step_rz:length(r_zoom_grid_vis) - for iz in 1:step_zz:length(z_zoom_grid_vis)] - scatter!(p_ctr_full, Rz, Zz; ms=0.8, color=:darkgrey, alpha=0.4, - markerstrokewidth=0, label="zoom grid") - - # Core panel: show both grids at full density within the core zoom region - scatter!(p_ctr_core, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, - markerstrokewidth=0, label="global grid") - scatter!(p_ctr_core, Rz, Zz; ms=1.2, color=:darkgrey, alpha=0.5, - markerstrokewidth=0, label="zoom grid") - - # X-point panel: global grid only (zoom doesn't extend there) - scatter!(p_ctr_xpt, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, - markerstrokewidth=0, label="global grid") -end + let + step_rg, step_zg = 20, 12 + Rg = [r_global_grid[ir] for ir in 1:step_rg:length(r_global_grid) + for _ in 1:step_zg:length(z_global_grid)] + Zg = [z_global_grid[iz] for _ in 1:step_rg:length(r_global_grid) + for iz in 1:step_zg:length(z_global_grid)] + scatter!(p_ctr_full, Rg, Zg; ms=0.8, color=:grey, alpha=0.25, + markerstrokewidth=0, label="global grid") + + step_rz, step_zz = 3, 3 + Rz = [r_zoom_grid_vis[ir] for ir in 1:step_rz:length(r_zoom_grid_vis) + for _ in 1:step_zz:length(z_zoom_grid_vis)] + Zz = [z_zoom_grid_vis[iz] for _ in 1:step_rz:length(r_zoom_grid_vis) + for iz in 1:step_zz:length(z_zoom_grid_vis)] + scatter!(p_ctr_full, Rz, Zz; ms=0.8, color=:darkgrey, alpha=0.4, + markerstrokewidth=0, label="zoom grid") + + # Core panel: show both grids at full density within the core zoom region + scatter!(p_ctr_core, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, + markerstrokewidth=0, label="global grid") + scatter!(p_ctr_core, Rz, Zz; ms=1.2, color=:darkgrey, alpha=0.5, + markerstrokewidth=0, label="zoom grid") + + # X-point panel: global grid only (zoom doesn't extend there) + scatter!(p_ctr_xpt, Rg, Zg; ms=1.2, color=:grey, alpha=0.3, + markerstrokewidth=0, label="global grid") + end end # !isempty(r_global_grid) # Set zoom limits for core and x-point panels using the reference method Rc, Zc = R_fs[ref_method] n_core = 4 -all_R_c = vcat(Rc[1:n_core]...); all_Z_c = vcat(Zc[1:n_core]...) +all_R_c = vcat(Rc[1:n_core]...); +all_Z_c = vcat(Zc[1:n_core]...); pad = 0.03 xlims!(p_ctr_core, minimum(all_R_c) - pad, maximum(all_R_c) + pad) ylims!(p_ctr_core, minimum(all_Z_c) - pad, maximum(all_Z_c) + pad) n_outer = length(psi_contours) -all_R_e = vcat(Rc[(n_outer-2):n_outer]...); all_Z_e = vcat(Zc[(n_outer-2):n_outer]...) +all_R_e = vcat(Rc[(n_outer-2):n_outer]...); +all_Z_e = vcat(Zc[(n_outer-2):n_outer]...); xpt_idx = argmin(all_Z_e) xlims!(p_ctr_xpt, all_R_e[xpt_idx] - 0.20, all_R_e[xpt_idx] + 0.20) ylims!(p_ctr_xpt, all_Z_e[xpt_idx] - 0.05, all_Z_e[xpt_idx] + 0.40) @@ -388,7 +394,7 @@ p_tht_full = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="θ = const lines: all methods (psihigh=$psihigh_arg)") p_tht_core = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Deep core zoom") -p_tht_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", +p_tht_xpt = plot(; aspect_ratio=:equal, xlabel="R [m]", ylabel="Z [m]", title="Far edge / x-point zoom") for m in all_methods @@ -402,14 +408,14 @@ for m in all_methods Zs = [psi_theta_to_RZ(pe, ψ, θ)[2] for ψ in psi_dense] plot!(p_tht_full, Rs, Zs; color=method_color[m], ls=method_style[m], lw=0.9, alpha=0.7, label=lbl) plot!(p_tht_core, Rs, Zs; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) - plot!(p_tht_xpt, Rs, Zs; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) + plot!(p_tht_xpt, Rs, Zs; color=method_color[m], ls=method_style[m], lw=1.5, label=lbl) end # Grid dots at every (ψ_i, θ_j) intersection — by construction on the lines above Rg = [psi_theta_to_RZ(pe, ψ, θ)[1] for ψ in pe.rzphi_xs for θ in θ_sub] Zg = [psi_theta_to_RZ(pe, ψ, θ)[2] for ψ in pe.rzphi_xs for θ in θ_sub] scatter!(p_tht_full, Rg, Zg; ms=1.5, color=method_color[m], alpha=0.5, markerstrokewidth=0, label="") scatter!(p_tht_core, Rg, Zg; ms=2.0, color=method_color[m], alpha=0.6, markerstrokewidth=0, label="") - scatter!(p_tht_xpt, Rg, Zg; ms=2.0, color=method_color[m], alpha=0.6, markerstrokewidth=0, label="") + scatter!(p_tht_xpt, Rg, Zg; ms=2.0, color=method_color[m], alpha=0.6, markerstrokewidth=0, label="") end xlims!(p_tht_core, minimum(all_R_c) - pad, maximum(all_R_c) + pad) @@ -425,21 +431,21 @@ println(" Saved flux contour figures.") # ═══════════════════════════════════════════════════════════════════════════════ # 3. 2D RZPHI GEOMETRIC SPLINES AT SELECT THETA SLICES # ═══════════════════════════════════════════════════════════════════════════════ -println("\n" * "=" ^ 70) +println("\n" * "="^70) println("3. 2D rzphi Geometric Spline Profiles at Select θ Values") -println("=" ^ 70) +println("="^70) rzphi_specs = [ - ("r²=(R-R₀)²+(Z-Z₀)²", pe -> ((ψ, θ) -> pe.rzphi_rsquared((ψ, θ)))), + ("r²=(R-R₀)²+(Z-Z₀)²", pe -> ((ψ, θ) -> pe.rzphi_rsquared((ψ, θ)))), ("angle offset η/2π−θ", pe -> ((ψ, θ) -> pe.rzphi_offset((ψ, θ)))), - ("ν (toroidal shift)", pe -> ((ψ, θ) -> pe.rzphi_nu((ψ, θ)))), - ("Jacobian", pe -> ((ψ, θ) -> pe.rzphi_jac((ψ, θ)))), + ("ν (toroidal shift)", pe -> ((ψ, θ) -> pe.rzphi_nu((ψ, θ)))), + ("Jacobian", pe -> ((ψ, θ) -> pe.rzphi_jac((ψ, θ)))) ] rzphi_fnames = ["rzphi_rsquared", "rzphi_angle_offset", "rzphi_nu", "rzphi_jacobian"] for (sidx, (sname, fn_getter)) in enumerate(rzphi_specs) - fn_ref = fn_getter(pe_ref) - yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] + fn_ref = fn_getter(pe_ref) + yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] p_full = plot(; xlabel="ψ", ylabel=sname, legend=:best, xlims=(0, 1), title="$sname — full domain (psihigh=$psihigh_arg)") @@ -454,20 +460,25 @@ for (sidx, (sname, fn_getter)) in enumerate(rzphi_specs) plot!(p_full, psi_full, yd; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_core, psi_full[mask_core], yd[mask_core]; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_edge, t_edge_full, yd[mask_edge]; color=tc, lw=2, label="efit θ=$(θ)") - xs = pe_ref.rzphi_xs; ys = [fn_ref(ψ, θ) for ψ in xs] + xs = pe_ref.rzphi_xs + ys = [fn_ref(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end end println(" $sname:") for m in compare_methods_active - fn_m = fn_getter(pes[m]) + fn_m = fn_getter(pes[m]) yi_all = [[fn_m(ψ, θ) for ψ in psi_full] for θ in theta_select] for (tidx, θ) in enumerate(theta_select) tc = theta_colors[tidx] yi = yi_all[tidx] - Δ = yd_all[tidx] .- yi + Δ = yd_all[tidx] .- yi plot!(p_full, psi_full, yi; color=tc, lw=1.2, ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_core, psi_full[mask_core], yi[mask_core]; color=tc, lw=1.2, @@ -476,10 +487,15 @@ for (sidx, (sname, fn_getter)) in enumerate(rzphi_specs) ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_diff, psi_full, Δ; color=tc, lw=1.2, ls=method_style[m], label="(efit−$(method_label[m])) θ=$(θ)") - xs = pes[m].rzphi_xs; ys = [fn_m(ψ, θ) for ψ in xs] + xs = pes[m].rzphi_xs + ys = [fn_m(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end Δc = any(mask_core) ? Δ[mask_core] : [0.0] Δe = any(mask_edge) ? Δ[mask_edge] : [0.0] @@ -496,20 +512,20 @@ end # ═══════════════════════════════════════════════════════════════════════════════ # 4. EQFUN PHYSICS SPLINES AT SELECT THETA SLICES # ═══════════════════════════════════════════════════════════════════════════════ -println("\n" * "=" ^ 70) +println("\n" * "="^70) println("4. Physics (eqfun) Spline Profiles at Select θ Values") -println("=" ^ 70) +println("="^70) eqfun_specs = [ - ("|B| (total field [T])", pe -> ((ψ, θ) -> pe.eqfun_B((ψ, θ)))), + ("|B| (total field [T])", pe -> ((ψ, θ) -> pe.eqfun_B((ψ, θ)))), ("metric1 (e₁·e₂+q·e₃·e₁)/JB²", pe -> ((ψ, θ) -> pe.eqfun_metric1((ψ, θ)))), - ("metric2 (e₂·e₃+q·e₃²)/JB²", pe -> ((ψ, θ) -> pe.eqfun_metric2((ψ, θ)))), + ("metric2 (e₂·e₃+q·e₃²)/JB²", pe -> ((ψ, θ) -> pe.eqfun_metric2((ψ, θ)))) ] eqfun_fnames = ["eqfun_Bmag", "eqfun_metric1", "eqfun_metric2"] for (eidx, (ename, fn_getter)) in enumerate(eqfun_specs) - fn_ref = fn_getter(pe_ref) - yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] + fn_ref = fn_getter(pe_ref) + yd_all = [[fn_ref(ψ, θ) for ψ in psi_full] for θ in theta_select] p_full = plot(; xlabel="ψ", ylabel=ename, legend=:best, xlims=(0, 1), title="$ename — full domain (psihigh=$psihigh_arg)") @@ -524,20 +540,25 @@ for (eidx, (ename, fn_getter)) in enumerate(eqfun_specs) plot!(p_full, psi_full, yd; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_core, psi_full[mask_core], yd[mask_core]; color=tc, lw=2, label="efit θ=$(θ)") plot!(p_edge, t_edge_full, yd[mask_edge]; color=tc, lw=2, label="efit θ=$(θ)") - xs = pe_ref.rzphi_xs; ys = [fn_ref(ψ, θ) for ψ in xs] + xs = pe_ref.rzphi_xs + ys = [fn_ref(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end end println(" $ename:") for m in compare_methods_active - fn_m = fn_getter(pes[m]) + fn_m = fn_getter(pes[m]) yi_all = [[fn_m(ψ, θ) for ψ in psi_full] for θ in theta_select] for (tidx, θ) in enumerate(theta_select) tc = theta_colors[tidx] yi = yi_all[tidx] - Δ = yd_all[tidx] .- yi + Δ = yd_all[tidx] .- yi plot!(p_full, psi_full, yi; color=tc, lw=1.2, ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_core, psi_full[mask_core], yi[mask_core]; color=tc, lw=1.2, @@ -546,10 +567,15 @@ for (eidx, (ename, fn_getter)) in enumerate(eqfun_specs) ls=method_style[m], label="$(method_label[m]) θ=$(θ)") plot!(p_diff, psi_full, Δ; color=tc, lw=1.2, ls=method_style[m], label="(efit−$(method_label[m])) θ=$(θ)") - xs = pes[m].rzphi_xs; ys = [fn_m(ψ, θ) for ψ in xs] + xs = pes[m].rzphi_xs + ys = [fn_m(ψ, θ) for ψ in xs] scatter!(p_full, xs, ys; ms=3, markerstrokewidth=0, color=tc, label="") - let mask = xs .< 0.10; scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end - let mask = xs .> 0.98; scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") end + let mask = xs .< 0.10 + scatter!(p_core, xs[mask], ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end + let mask = xs .> 0.98 + scatter!(p_edge, -log.(1.0 .- xs[mask]), ys[mask]; ms=3, markerstrokewidth=0, color=tc, label="") + end Δc = any(mask_core) ? Δ[mask_core] : [0.0] Δe = any(mask_edge) ? Δ[mask_edge] : [0.0] @@ -566,9 +592,9 @@ end # ═══════════════════════════════════════════════════════════════════════════════ # 5. SUMMARY # ═══════════════════════════════════════════════════════════════════════════════ -println("\n" * "=" ^ 70) +println("\n" * "="^70) println("Summary: axis / edge parameter comparison") -println("=" ^ 70) +println("="^70) col_labels = [method_label[m] for m in all_methods] @printf(" %-22s %s\n", "Parameter", join([@sprintf("%18s", l) for l in col_labels])) @@ -580,13 +606,13 @@ function row_int(label, vals) @printf(" %-22s %s\n", label, join([@sprintf("%18d", v) for v in vals])) end -row("ro [m]", [pes[m].ro for m in all_methods]) -row("zo [m]", [pes[m].zo for m in all_methods]) -row("psio [Wb/rad]",[pes[m].psio for m in all_methods]) -row("psilow", [pes[m].rzphi_xs[1] for m in all_methods]) -row("psihigh", [pes[m].rzphi_xs[end] for m in all_methods]) -row("q(psilow)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[1]) for m in all_methods]) -row("q(psihigh)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[end]) for m in all_methods]) +row("ro [m]", [pes[m].ro for m in all_methods]) +row("zo [m]", [pes[m].zo for m in all_methods]) +row("psio [Wb/rad]", [pes[m].psio for m in all_methods]) +row("psilow", [pes[m].rzphi_xs[1] for m in all_methods]) +row("psihigh", [pes[m].rzphi_xs[end] for m in all_methods]) +row("q(psilow)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[1]) for m in all_methods]) +row("q(psihigh)", [pes[m].profiles.q_spline(pes[m].rzphi_xs[end]) for m in all_methods]) q_profiles = Dict(m => [pes[m].profiles.q_spline(ψ) for ψ in psi_full] for m in all_methods) row_int("q non-mono (edge)", diff --git a/examples/DIIID-like_ideal_example/analyze_example.jl b/examples/DIIID-like_ideal_example/analyze_example.jl index a3dc74bd2..1a3db2eb1 100644 --- a/examples/DIIID-like_ideal_example/analyze_example.jl +++ b/examples/DIIID-like_ideal_example/analyze_example.jl @@ -41,7 +41,7 @@ function symmetric_clims(z) end geqdsk_cases = [ - "TkMkr_D3Dlike_Hmode.geqdsk", + "TkMkr_D3Dlike_Hmode.geqdsk" ] base_toml = TOML.parsefile(joinpath(@__DIR__, "gpec.toml")) diff --git a/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl b/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl index eea4c4bbe..9671b0bfa 100644 --- a/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl +++ b/examples/DIIID-like_ideal_example_IMAS/run_imas_example.jl @@ -52,8 +52,8 @@ try config_imas = merge(SHARED_CONFIG, Dict("Equilibrium" => merge(EQ_COMMON, Dict("eq_type" => "imas", "eq_filename" => "from_dd", "imas_cocos" => 11)))) open(joinpath(tmpdir_imas, "gpec.toml"), "w") do io - ; - TOML.print(io, config_imas); + + TOML.print(io, config_imas) end result_imas = GPEC.main([tmpdir_imas]; dd=dd) global et_imas = real(result_imas.ffs.free_boundary.et[1]) @@ -71,8 +71,8 @@ try config_gfile = merge(SHARED_CONFIG, Dict("Equilibrium" => merge(EQ_COMMON, Dict("eq_type" => "efit", "eq_filename" => GEQDSK)))) open(joinpath(tmpdir_gfile, "gpec.toml"), "w") do io - ; - TOML.print(io, config_gfile); + + TOML.print(io, config_gfile) end result_gfile = GPEC.main([tmpdir_gfile]) global et_gfile = real(result_gfile.ffs.free_boundary.et[1]) diff --git a/examples/LAR_beta_scan/run_scan.jl b/examples/LAR_beta_scan/run_scan.jl index 12eb1c2fd..f0faf52fd 100644 --- a/examples/LAR_beta_scan/run_scan.jl +++ b/examples/LAR_beta_scan/run_scan.jl @@ -30,11 +30,11 @@ using Printf # is approximately uniform over most of the range and smoothly tightens as # the pole is approached, giving an even visual cadence without wasting # points on the flat-slope region far from the pole. -function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64 = 2.0) +function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64=2.0) return [x_start + (x_end - x_start) * (1 - (1 - i / (N - 1))^p) for i in 0:N-1] end -const PC_FULL = _warped_grid(0.001, 0.1735, 40; p = 2.0) +const PC_FULL = _warped_grid(0.001, 0.1735, 40; p=2.0) const PC_TEST = [0.001, 0.10, 0.17] @@ -57,12 +57,14 @@ function run_single(pc::Float64) # Per-point gpec.toml = baseline gpec.toml with TJAnalytic.p0 overridden. config = deepcopy(GPEC_BASE) config["TJAnalytic"]["p0"] = pc - open(joinpath(run_dir, "gpec.toml"), "w") do io; TOML.print(io, config); end + open(joinpath(run_dir, "gpec.toml"), "w") do io + TOML.print(io, config) + end GeneralizedPerturbedEquilibrium.main([run_dir]) return extract_results(joinpath(run_dir, "gpec.h5")) catch e - @warn "Failed for pc=$pc" exception=(e, catch_backtrace()) + @warn "Failed for pc=$pc" exception = (e, catch_backtrace()) return nothing finally rm(run_dir; force=true, recursive=true) @@ -72,24 +74,32 @@ end function extract_results(h5_path::String) h5open(h5_path, "r") do f fbs = "ForceFreeStates/FreeBoundaryStability" - ep = read(f, "$fbs/eigenmode_plasma_energies"); ev = read(f, "$fbs/eigenmode_vacuum_energies"); et = read(f, "$fbs/eigenmode_energies") + ep = read(f, "$fbs/eigenmode_plasma_energies") + ev = read(f, "$fbs/eigenmode_vacuum_energies") + et = read(f, "$fbs/eigenmode_energies") msing = read(f, "SingularSurfaces/rational_count") m_sing = read(f, "SingularSurfaces/rational_m") dp_mat = haskey(f, "SingularSurfaces/Delta_prime_matrix") ? read(f, "SingularSurfaces/Delta_prime_matrix") : nothing qlim = haskey(f, "Info/qlim") ? read(f, "Info/qlim") : read(f, "Equilibrium/q_max") - q0 = read(f, "Equilibrium/q_axis"); qmax = read(f, "Equilibrium/q_max") + q0 = read(f, "Equilibrium/q_axis") + qmax = read(f, "Equilibrium/q_max") - dp_21 = NaN + NaN*im; dp_31 = NaN + NaN*im + dp_21 = NaN + NaN * im + dp_31 = NaN + NaN * im if dp_mat !== nothing && msing > 0 for s in 1:min(msing, size(dp_mat, 1)) m_val = size(m_sing, 1) == msing ? m_sing[s, 1] : m_sing[1, s] - if m_val == 2; dp_21 = dp_mat[s, s]; end - if m_val == 3; dp_31 = dp_mat[s, s]; end + if m_val == 2 + dp_21 = dp_mat[s, s] + end + if m_val == 3 + dp_31 = dp_mat[s, s] + end end end return (dp_21=dp_21, dp_31=dp_31, - dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), - q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) + dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), + q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) end end @@ -116,11 +126,20 @@ function main() haskey(f, gname) && delete_object(f, gname) g = create_group(f, gname) g["pressure_factor"] = pc - g["dp_21_real"] = real(result.dp_21); g["dp_21_imag"] = imag(result.dp_21) - g["dp_31_real"] = real(result.dp_31); g["dp_31_imag"] = imag(result.dp_31) - g["dW_plasma"] = result.dW_plasma; g["dW_vacuum"] = result.dW_vacuum; g["dW_total"] = result.dW_total - g["q0"] = result.q0; g["qmax"] = result.qmax; g["qlim"] = result.qlim; g["msing"] = result.msing - if result.dp_matrix !== nothing; g["dp_matrix"] = result.dp_matrix; end + g["dp_21_real"] = real(result.dp_21) + g["dp_21_imag"] = imag(result.dp_21) + g["dp_31_real"] = real(result.dp_31) + g["dp_31_imag"] = imag(result.dp_31) + g["dW_plasma"] = result.dW_plasma + g["dW_vacuum"] = result.dW_vacuum + g["dW_total"] = result.dW_total + g["q0"] = result.q0 + g["qmax"] = result.qmax + g["qlim"] = result.qlim + g["msing"] = result.msing + if result.dp_matrix !== nothing + g["dp_matrix"] = result.dp_matrix + end end @printf(" dp21=%+.4f%+.4fi dp31=%+.4f%+.4fi dW_t=%+.6f qa=%.3f\n", real(result.dp_21), imag(result.dp_21), real(result.dp_31), imag(result.dp_31), diff --git a/examples/LAR_epsilon_scan/run_scan.jl b/examples/LAR_epsilon_scan/run_scan.jl index 1f920ba4b..f02e249ff 100644 --- a/examples/LAR_epsilon_scan/run_scan.jl +++ b/examples/LAR_epsilon_scan/run_scan.jl @@ -29,11 +29,11 @@ using Printf # spacing tightens smoothly as the pole is approached — the flat low-ε # region is covered with even cadence, and more points land in the final # few percent where Δ' rises by orders of magnitude. -function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64 = 2.0) +function _warped_grid(x_start::Float64, x_end::Float64, N::Int; p::Float64=2.0) return [x_start + (x_end - x_start) * (1 - (1 - i / (N - 1))^p) for i in 0:N-1] end -const EPSILONS_FULL = _warped_grid(0.125, 0.660, 56; p = 2.0) +const EPSILONS_FULL = _warped_grid(0.125, 0.660, 56; p=2.0) const EPSILONS_TEST = [0.2495, 0.4072, 0.5510] @@ -63,12 +63,14 @@ function run_single(epsilon::Float64) config = deepcopy(GPEC_BASE) config["TJAnalytic"]["r0"] = GPEC_BASE["TJAnalytic"]["a"] / epsilon config["TJAnalytic"]["solver"] = "direct" - open(joinpath(run_dir, "gpec.toml"), "w") do io; TOML.print(io, config); end + open(joinpath(run_dir, "gpec.toml"), "w") do io + TOML.print(io, config) + end GeneralizedPerturbedEquilibrium.main([run_dir]) return extract_results(joinpath(run_dir, "gpec.h5")) catch e - @warn "Failed for ε=$epsilon" exception=(e, catch_backtrace()) + @warn "Failed for ε=$epsilon" exception = (e, catch_backtrace()) return nothing finally rm(run_dir; force=true, recursive=true) @@ -78,24 +80,32 @@ end function extract_results(h5_path::String) h5open(h5_path, "r") do f fbs = "ForceFreeStates/FreeBoundaryStability" - ep = read(f, "$fbs/eigenmode_plasma_energies"); ev = read(f, "$fbs/eigenmode_vacuum_energies"); et = read(f, "$fbs/eigenmode_energies") + ep = read(f, "$fbs/eigenmode_plasma_energies") + ev = read(f, "$fbs/eigenmode_vacuum_energies") + et = read(f, "$fbs/eigenmode_energies") msing = read(f, "SingularSurfaces/rational_count") m_sing = read(f, "SingularSurfaces/rational_m") dp_mat = haskey(f, "SingularSurfaces/Delta_prime_matrix") ? read(f, "SingularSurfaces/Delta_prime_matrix") : nothing qlim = haskey(f, "Info/qlim") ? read(f, "Info/qlim") : read(f, "Equilibrium/q_max") - q0 = read(f, "Equilibrium/q_axis"); qmax = read(f, "Equilibrium/q_max") + q0 = read(f, "Equilibrium/q_axis") + qmax = read(f, "Equilibrium/q_max") - dp_21 = NaN + NaN*im; dp_31 = NaN + NaN*im + dp_21 = NaN + NaN * im + dp_31 = NaN + NaN * im if dp_mat !== nothing && msing > 0 for s in 1:min(msing, size(dp_mat, 1)) m_val = size(m_sing, 1) == msing ? m_sing[s, 1] : m_sing[1, s] - if m_val == 2; dp_21 = dp_mat[s, s]; end - if m_val == 3; dp_31 = dp_mat[s, s]; end + if m_val == 2 + dp_21 = dp_mat[s, s] + end + if m_val == 3 + dp_31 = dp_mat[s, s] + end end end return (dp_21=dp_21, dp_31=dp_31, - dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), - q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) + dW_plasma=real(ep[1]), dW_vacuum=real(ev[1]), dW_total=real(et[1]), + q0=q0, qmax=qmax, qlim=qlim, msing=msing, dp_matrix=dp_mat) end end @@ -123,11 +133,20 @@ function main() haskey(f, gname) && delete_object(f, gname) g = create_group(f, gname) g["epsilon"] = eps - g["dp_21_real"] = real(result.dp_21); g["dp_21_imag"] = imag(result.dp_21) - g["dp_31_real"] = real(result.dp_31); g["dp_31_imag"] = imag(result.dp_31) - g["dW_plasma"] = result.dW_plasma; g["dW_vacuum"] = result.dW_vacuum; g["dW_total"] = result.dW_total - g["q0"] = result.q0; g["qmax"] = result.qmax; g["qlim"] = result.qlim; g["msing"] = result.msing - if result.dp_matrix !== nothing; g["dp_matrix"] = result.dp_matrix; end + g["dp_21_real"] = real(result.dp_21) + g["dp_21_imag"] = imag(result.dp_21) + g["dp_31_real"] = real(result.dp_31) + g["dp_31_imag"] = imag(result.dp_31) + g["dW_plasma"] = result.dW_plasma + g["dW_vacuum"] = result.dW_vacuum + g["dW_total"] = result.dW_total + g["q0"] = result.q0 + g["qmax"] = result.qmax + g["qlim"] = result.qlim + g["msing"] = result.msing + if result.dp_matrix !== nothing + g["dp_matrix"] = result.dp_matrix + end end @printf(" dp21=%+.4f%+.4fi dp31=%+.4f%+.4fi dW_t=%+.6f qa=%.3f\n", real(result.dp_21), imag(result.dp_21), real(result.dp_31), imag(result.dp_31), diff --git a/examples/Solovev_ideal_example/analyze_example.jl b/examples/Solovev_ideal_example/analyze_example.jl index 9f08e1469..62178b316 100644 --- a/examples/Solovev_ideal_example/analyze_example.jl +++ b/examples/Solovev_ideal_example/analyze_example.jl @@ -10,6 +10,9 @@ h5path = joinpath(@__DIR__, "gpec.h5") p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path) p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path) -display(p_eq); Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")) -display(p_ffs); Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")) -display(p_pe); Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")) \ No newline at end of file +display(p_eq); +Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")); +display(p_ffs); +Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")); +display(p_pe); +Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")); diff --git a/examples/Solovev_ideal_example_multi_n/analyze_example.jl b/examples/Solovev_ideal_example_multi_n/analyze_example.jl index 3a1e46134..10edafd6e 100644 --- a/examples/Solovev_ideal_example_multi_n/analyze_example.jl +++ b/examples/Solovev_ideal_example_multi_n/analyze_example.jl @@ -9,11 +9,14 @@ h5path = joinpath(@__DIR__, "gpec.h5") # Summary plots p_eq = Analysis.Equilibrium.plot_equilibrium_summary(h5path) p_ffs = Analysis.ForceFreeStates.plot_ffs_summary(h5path) -p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path) +p_pe = Analysis.PerturbedEquilibrium.plot_perturbed_equilibrium_summary(h5path) -display(p_eq); Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")) -display(p_ffs); Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")) -display(p_pe); Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")) +display(p_eq); +Plots.savefig(p_eq, joinpath(@__DIR__, "equilibrium_summary.png")); +display(p_ffs); +Plots.savefig(p_ffs, joinpath(@__DIR__, "ffs_summary.png")); +display(p_pe); +Plots.savefig(p_pe, joinpath(@__DIR__, "pe_summary.png")); # Analyze the single-n runs h5path_n1 = joinpath(@__DIR__, "single_n_1", "euler_n1.h5") @@ -21,5 +24,7 @@ h5path_n2 = joinpath(@__DIR__, "single_n_2", "euler_n2.h5") p_n1 = Analysis.ForceFreeStates.plot_ffs_summary(h5path_n1) p_n2 = Analysis.ForceFreeStates.plot_ffs_summary(h5path_n2) -display(p_n1); Plots.savefig(p_n1, joinpath(@__DIR__, "single_n_1", "ffs_summary.png")) -display(p_n2); Plots.savefig(p_n2, joinpath(@__DIR__, "single_n_2", "ffs_summary.png")) +display(p_n1); +Plots.savefig(p_n1, joinpath(@__DIR__, "single_n_1", "ffs_summary.png")); +display(p_n2); +Plots.savefig(p_n2, joinpath(@__DIR__, "single_n_2", "ffs_summary.png")); diff --git a/examples/fourier_transform_usage.jl b/examples/fourier_transform_usage.jl index 3c0890734..19539f7d3 100644 --- a/examples/fourier_transform_usage.jl +++ b/examples/fourier_transform_usage.jl @@ -33,7 +33,7 @@ println(" mlow = $mlow (lowest mode: m ∈ [$mlow, $(mlow+mpert-1)])") println("\nBasis functions: cos(m*θ), sin(m*θ) with m = $mlow:$(mlow+mpert-1)") # Create test data: a simple function in theta space -theta = range(0, 2π; length=mtheta+1)[1:(end-1)] +theta = range(0, 2π; length=mtheta + 1)[1:(end-1)] f_theta = sin.(5 .* theta) .+ 0.5 .* cos.(8 .* theta) # Forward transform: theta → modes diff --git a/regression-harness/src/types.jl b/regression-harness/src/types.jl index a3ee164a7..f31cc55db 100644 --- a/regression-harness/src/types.jl +++ b/regression-harness/src/types.jl @@ -19,10 +19,11 @@ end Specification for a test case: what to run and what to extract. `kind` selects the runner backend: + - "gpec_run" (default) — run GPEC end-to-end on `example_dir`, extract from `gpec.h5` - "computed" — run a self-contained Julia computation that writes a small h5 - (no `example_dir` required); used for analytic/reference cases - like the GGJ inner-layer benchmark. + (no `example_dir` required); used for analytic/reference cases + like the GGJ inner-layer benchmark. `precompile_workload` sets GPEC's PrecompileTools workload preference for the run. It defaults to `false` so every case compares code compiled on first use; a case sets it `true` to track the diff --git a/regression-harness/src/utils.jl b/regression-harness/src/utils.jl index 01afbd40a..d1110f8ef 100644 --- a/regression-harness/src/utils.jl +++ b/regression-harness/src/utils.jl @@ -130,7 +130,7 @@ newest. Without it, two refs are compared across two different package sets and differences surface as physics regressions. """ function create_worktree(commit_hash::String, repo_root::String; - pin_manifest_from::Union{String,Nothing}=nothing)::String + pin_manifest_from::Union{String,Nothing}=nothing)::String short = commit_hash[1:min(8, length(commit_hash))] worktree_path = tempname() * "_gpec_$(short)" try diff --git a/src/Analysis/Equilibrium.jl b/src/Analysis/Equilibrium.jl index 6dbfede40..f00a406cd 100644 --- a/src/Analysis/Equilibrium.jl +++ b/src/Analysis/Equilibrium.jl @@ -219,7 +219,7 @@ function plot_flux_surfaces(h5path; n_psi=11, n_theta=18, save_path=nothing) for s in 1:msing idx = argmin(abs.(xs_rz .- psi_sing[s])) q_label = abs(q_sing[s] - round(q_sing[s])) < 0.05 ? - "q=$(round(Int, q_sing[s]))" : "q=$(round(q_sing[s], digits=2))" + "q=$(round(Int, q_sing[s]))" : "q=$(round(q_sing[s], digits=2))" plot!(p, [R_grid[idx, :]; R_grid[idx, 1]], [Z_grid[idx, :]; Z_grid[idx, 1]]; color=:red, linewidth=1.5, label=s == 1 ? "Rational surface" : "") @@ -368,23 +368,26 @@ function plot_equilibrium_summary(h5path; save_path=nothing) title_str = "q0=$(round(q0,digits=2)) q95=$(round(q95,digits=2)) βₜ=$(round(betat,digits=3)) βₙ=$(round(betan,digits=3)) κ=$(round(kappa,digits=2)) li1=$(round(li1,digits=3))" - p_rz = plot_flux_surfaces(h5path) - p_q = plot_qprofile(h5path; show_singular=true) + p_rz = plot_flux_surfaces(h5path) + p_q = plot_qprofile(h5path; show_singular=true) p_pres = plot_pressure_profile(h5path) - p_f = plot_f_profile(h5path) - p_gse = plot_gse_by_theta(h5path) # includes integrated overplot; nothing if absent + p_f = plot_f_profile(h5path) + p_gse = plot_gse_by_theta(h5path) # includes integrated overplot; nothing if absent # Suppress x-axis labels/ticks on all but the bottom profile panel — they share the # same ψ_N axis and labeling every panel wastes vertical space. - hide_xaxis!(p) = plot!(p; xlabel="", xformatter=_->"", bottom_margin=1Plots.mm) + hide_xaxis!(p) = plot!(p; xlabel="", xformatter=_ -> "", bottom_margin=1Plots.mm) if isnothing(p_gse) - hide_xaxis!(p_q); hide_xaxis!(p_pres) + hide_xaxis!(p_q) + hide_xaxis!(p_pres) l = @layout [a{0.38w} [b; c; d]] p = plot(p_rz, p_q, p_pres, p_f; layout=l, size=(1300, 750), plot_title=title_str, plot_titlefontsize=10, top_margin=8Plots.mm) else - hide_xaxis!(p_q); hide_xaxis!(p_pres); hide_xaxis!(p_f) + hide_xaxis!(p_q) + hide_xaxis!(p_pres) + hide_xaxis!(p_f) l = @layout [a{0.38w} [b; c; d; e]] p = plot(p_rz, p_q, p_pres, p_f, p_gse; layout=l, size=(1300, 1000), plot_title=title_str, plot_titlefontsize=10, top_margin=8Plots.mm) diff --git a/src/Analysis/PerturbedEquilibrium.jl b/src/Analysis/PerturbedEquilibrium.jl index 03f269660..83d5cde7b 100644 --- a/src/Analysis/PerturbedEquilibrium.jl +++ b/src/Analysis/PerturbedEquilibrium.jl @@ -45,10 +45,10 @@ function plot_resonant_area_weighted_field_amplitude(h5path; save_path=nothing) return plot(; title="No resonant area-weighted field data — run with perturbed equilibrium enabled", legend=false) resonant_area_weighted_field, rational_psi, rational_q, rational_n = h5open(h5path, "r") do fid - read(fid[base * "resonant_area_weighted_field"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]), - read(fid[base * "rational_n"]) + read(fid[base*"resonant_area_weighted_field"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]), + read(fid[base*"rational_n"]) end p = plot(; xlabel="Norm. Poloidal Flux", ylabel="|b^r| [T]", @@ -96,9 +96,9 @@ function plot_island_widths(h5path; save_path=nothing) return plot(; title="No island width data — run with perturbed equilibrium enabled", legend=false) island_hw, rational_psi, rational_q = h5open(h5path, "r") do fid - read(fid[base * "island_half_width"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]) + read(fid[base*"island_half_width"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]) end p = scatter( @@ -150,9 +150,9 @@ function plot_chirikov_parameter(h5path; save_path=nothing) return plot(; title="No Chirikov data — run with perturbed equilibrium enabled", legend=false) chirikov, rational_psi, rational_q = h5open(h5path, "r") do fid - read(fid[base * "chirikov_parameter"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]) + read(fid[base*"chirikov_parameter"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]) end colors = [k > 1.0 ? :red : :steelblue for k in chirikov] @@ -212,10 +212,10 @@ function plot_driven_delta_prime(h5path; save_path=nothing) return plot(; title="No PE Δ' data — run with perturbed equilibrium enabled", legend=false) delta_prime, rational_psi, rational_q, rational_n = h5open(h5path, "r") do fid - read(fid[base * "Delta_prime"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]), - read(fid[base * "rational_n"]) + read(fid[base*"Delta_prime"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]), + read(fid[base*"rational_n"]) end p = plot(; xlabel="Norm. Poloidal Flux", ylabel="Re(Δ')", @@ -280,7 +280,7 @@ function plot_resonant_area_weighted_field(h5path; save_path=nothing) plot!(p; title="") end - hide_xaxis!(p) = plot!(p; xlabel="", xformatter=_->"", bottom_margin=1Plots.mm) + hide_xaxis!(p) = plot!(p; xlabel="", xformatter=_ -> "", bottom_margin=1Plots.mm) for p in (p1, p2, p3, p4) hide_xaxis!(p) end @@ -298,10 +298,10 @@ function _plot_resonant_current(h5path) return plot(; title="No resonant current data", legend=false) resonant_current, rational_psi, rational_q, rational_n = h5open(h5path, "r") do fid - read(fid[base * "resonant_current"]), - read(fid[base * "rational_psi"]), - read(fid[base * "rational_q"]), - read(fid[base * "rational_n"]) + read(fid[base*"resonant_current"]), + read(fid[base*"rational_psi"]), + read(fid[base*"rational_q"]), + read(fid[base*"rational_n"]) end p = plot(; xlabel="Norm. Poloidal Flux", ylabel="|I_res|", @@ -353,10 +353,10 @@ A `Plots.jl` plot object. """ function plot_mode_spectrogram(h5path; component=:xi_psi, save_path=nothing) comp_map = Dict( - :xi_psi => "xi_psi", - :b_psi => "b_psi_area_weighted", # area-normalized b^ψ + :xi_psi => "xi_psi", + :b_psi => "b_psi_area_weighted", # area-normalized b^ψ :Jb_theta => "Jb_theta", - :Jb_zeta => "Jb_zeta", + :Jb_zeta => "Jb_zeta" ) haskey(comp_map, component) || error("component must be one of :xi_psi, :b_psi, :Jb_theta, :Jb_zeta") @@ -369,7 +369,7 @@ function plot_mode_spectrogram(h5path; component=:xi_psi, save_path=nothing) data, psi_response, mlow, mhigh, nhigh, q95, rational_psi = h5open(h5path, "r") do fid read(fid[dataset_path]), - read(fid[base * "psi"]), + read(fid[base*"psi"]), read(fid["Info/mlow"]), read(fid["Info/mhigh"]), read(fid["Info/nhigh"]), read(fid["Equilibrium/q_95"]), read(fid["PerturbedEquilibrium/SingularCoupling/rational_psi"]) @@ -440,9 +440,9 @@ Three-panel composite summary of perturbed equilibrium results: A `Plots.jl` plot object. """ function plot_perturbed_equilibrium_summary(h5path; save_path=nothing) - p_islands = plot_resonant_area_weighted_field_amplitude(h5path) - p_bpsi = _plot_bpsi_edge_spectrum(h5path) - p_spectro = plot_mode_spectrogram(h5path; component=:xi_psi) + p_islands = plot_resonant_area_weighted_field_amplitude(h5path) + p_bpsi = _plot_bpsi_edge_spectrum(h5path) + p_spectro = plot_mode_spectrogram(h5path; component=:xi_psi) l = @layout [grid(1, 2){0.35h}; b] p = plot(p_islands, p_bpsi, p_spectro; layout=l, size=(1100, 1100)) @@ -458,11 +458,11 @@ function _plot_bpsi_edge_spectrum(h5path) return plot(; title="No b_psi data — run with perturbed equilibrium enabled", legend=false) data, mlow, mhigh = h5open(h5path, "r") do fid - read(fid[base * "b_psi_area_weighted"]), + read(fid[base*"b_psi_area_weighted"]), read(fid["Info/mlow"]), read(fid["Info/mhigh"]) end - mpert = mhigh - mlow + 1 + mpert = mhigh - mlow + 1 m_vals = mlow:mhigh bpsi_edge = abs.(data[end, 1:mpert]) diff --git a/src/Analysis/PerturbedEquilibriumModes.jl b/src/Analysis/PerturbedEquilibriumModes.jl index 58aacdaf9..a4dc52174 100644 --- a/src/Analysis/PerturbedEquilibriumModes.jl +++ b/src/Analysis/PerturbedEquilibriumModes.jl @@ -20,33 +20,37 @@ Reads all required metadata (mlow, nlow, mpert, npert) and spline data (ν) from the HDF5 file. # Arguments -- `h5_file::String`: Path to gpec.h5 output file -- `variable::String`: HDF5 dataset path, e.g. `"PerturbedEquilibrium/Response/xi_R"` + + - `h5_file::String`: Path to gpec.h5 output file + - `variable::String`: HDF5 dataset path, e.g. `"PerturbedEquilibrium/Response/xi_R"` # Keyword arguments -- `mtheta::Int`: theta grid resolution (default: `max(2*(|mlow|+mpert), 512)`) -- `keep_sfl_phi::Bool`: if `true` (default), output in SFL toroidal angle; - if `false`, apply `exp(i*n*ν(ψ,θ))` to convert to machine toroidal angle - and conjugate if `helicity > 0` (matches Fortran `gpout_xbrzphifun`) + + - `mtheta::Int`: theta grid resolution (default: `max(2*(|mlow|+mpert), 512)`) + - `keep_sfl_phi::Bool`: if `true` (default), output in SFL toroidal angle; + if `false`, apply `exp(i*n*ν(ψ,θ))` to convert to machine toroidal angle + and conjugate if `helicity > 0` (matches Fortran `gpout_xbrzphifun`) # Returns -- `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` -- `theta_grid::Vector{Float64}`: `[mtheta]` SFL theta ∈ [0, 1) -- `n_vals::Vector{Int}`: `[npert]` toroidal mode numbers + + - `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` + - `theta_grid::Vector{Float64}`: `[mtheta]` SFL theta ∈ [0, 1) + - `n_vals::Vector{Int}`: `[npert]` toroidal mode numbers !!! note + When used on the cylindrical components `xi_R`, `xi_Z`, `xi_phi`, `b_R`, `b_Z`, `b_phi` these are currently in beta and show up to ~20% discrepancies vs Fortran. """ function modes_to_theta(h5_file::String, variable::String; - mtheta::Union{Int,Nothing}=nothing, - keep_sfl_phi::Bool=true) + mtheta::Union{Int,Nothing}=nothing, + keep_sfl_phi::Bool=true) h5open(h5_file, "r") do f modes = read(f, variable) # (npsi, numpert_total) npsi, numpert_total = size(modes) - mlow = read(f, "Info/mlow") - nlow = read(f, "Info/nlow") + mlow = read(f, "Info/mlow") + nlow = read(f, "Info/nlow") mpert = read(f, "Info/mpert") npert = read(f, "Info/npert") @assert numpert_total == mpert * npert "Expected numpert_total=$(mpert*npert), got $numpert_total" @@ -58,7 +62,7 @@ function modes_to_theta(h5_file::String, variable::String; theta_data = zeros(ComplexF64, npsi, mth, npert) for k in 1:npert - col_range = (k-1)*mpert+1 : k*mpert + col_range = (k-1)*mpert+1:k*mpert for ipsi in 1:npsi theta_data[ipsi, :, k] .= inverse(ft, view(modes, ipsi, col_range)) end @@ -68,7 +72,7 @@ function modes_to_theta(h5_file::String, variable::String; # Reconstruct ν spline from stored grid + nodal values (FastInterpolations v0.4 API) rzphi_xs = read(f, "Equilibrium/Geometry/psi") rzphi_ys = read(f, "Equilibrium/Geometry/theta") - nu_vals = read(f, "Equilibrium/Geometry/nu") + nu_vals = read(f, "Equilibrium/Geometry/nu") nu_spline = cubic_interp( (rzphi_xs, rzphi_ys), nu_vals; bc=(CubicFit(), PeriodicBC()), @@ -77,8 +81,8 @@ function modes_to_theta(h5_file::String, variable::String; psi_grid = read(f, "ForceFreeStates/Solutions/ForwardIntegration/psi") - bt_sign = haskey(f, "Equilibrium/B_T_sign") ? read(f, "Equilibrium/B_T_sign") : 1 - crnt = haskey(f, "Equilibrium/I_p") ? read(f, "Equilibrium/I_p") : 1.0 + bt_sign = haskey(f, "Equilibrium/B_T_sign") ? read(f, "Equilibrium/B_T_sign") : 1 + crnt = haskey(f, "Equilibrium/I_p") ? read(f, "Equilibrium/I_p") : 1.0 helicity = bt_sign * Int(sign(crnt)) hint = (Ref(1), Ref(1)) @@ -110,18 +114,21 @@ Extend theta-space data to a `(θ, φ)` grid via toroidal inverse DFT. f(θ, φ) = Σₙ fₙ(θ) exp(i·n·φ) # Arguments -- `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` from `modes_to_theta` -- `n_vals::Vector{Int}`: toroidal mode numbers + + - `theta_data::Array{ComplexF64,3}`: `[npsi × mtheta × npert]` from `modes_to_theta` + - `n_vals::Vector{Int}`: toroidal mode numbers # Keyword arguments -- `nphi::Int`: toroidal grid points (default: `max(4*maximum(abs.(n_vals)), 64)`) + + - `nphi::Int`: toroidal grid points (default: `max(4*maximum(abs.(n_vals)), 64)`) # Returns -- `full_data::Array{ComplexF64,3}`: `[npsi × mtheta × nphi]` -- `phi_grid::Vector{Float64}`: `[nphi]` in radians ∈ [0, 2π) + + - `full_data::Array{ComplexF64,3}`: `[npsi × mtheta × nphi]` + - `phi_grid::Vector{Float64}`: `[nphi]` in radians ∈ [0, 2π) """ function theta_to_thetaphi(theta_data::Array{ComplexF64,3}, n_vals::Vector{Int}; - nphi::Union{Int,Nothing}=nothing) + nphi::Union{Int,Nothing}=nothing) npsi, mth, npert = size(theta_data) np = isnothing(nphi) ? max(4 * maximum(abs.(n_vals)), 64) : nphi phi_grid = [(j - 1) * 2π / np for j in 1:np] diff --git a/src/Deck.jl b/src/Deck.jl index af593faa0..361cd183a 100644 --- a/src/Deck.jl +++ b/src/Deck.jl @@ -38,7 +38,7 @@ const _MOVED_KEYS = Dict{String,Dict{String,String}}( ("gal_$k" => "moved to [Match] as $k" for k in ("eta", "rho", "rotation", "gamma"))..., ("gal_inner_$k" => "moved to [GGJ] as $k" for k in ("xfac", "nx", "nq", "cutoff", "kmax"))..., ("gal_$k" => "moved to [Galerkin] as $k" for k in ("nx", "nq", "pfac", "dx0", "dx1", "dx2", "cutoff", "tol", "gnstep", - "dx1dx2_flag", "rpec_flag", "edge_onesided"))..., + "dx1dx2_flag", "rpec_flag", "edge_onesided"))..., "gal_sing_order_ceiling" => "moved to [Galerkin] as frobenius_order_ceiling"), "LocalStability" => Dict{String,String}( k => "moved to [Ballooning]" for k in ("ode_tol", "n_scan", "max_alpha_scale", "alpha_tol", "psi_window")), @@ -215,8 +215,10 @@ function equilibrium_config(inputs::AbstractDict, path::AbstractString) elseif eq_type === nothing error("Missing required key in [Equilibrium]: eq_type") elseif haskey(Equilibrium.ANALYTIC_EQ, eq_type) - error("[Equilibrium] eq_type = \"$eq_type\" is not a deck value: state the analytic equilibrium as a " * - "[$(Equilibrium.ANALYTIC_EQ[eq_type].section)] section and remove eq_type") + error( + "[Equilibrium] eq_type = \"$eq_type\" is not a deck value: state the analytic equilibrium as a " * + "[$(Equilibrium.ANALYTIC_EQ[eq_type].section)] section and remove eq_type" + ) end fields = _struct_fields(Equilibrium.EquilibriumConfig, (:power_bp, :power_b, :power_r, :power_rc)) kwargs = section_keywords(_deck_paths(table, path, ("eq_filename", "kinetic_file")), "Equilibrium", fields) @@ -365,8 +367,10 @@ function tearing_from_deck(inputs::AbstractDict) inner_model = _selector(table, "Tearing", "inner_model", ("SLAYER", "GGJ")) delete!(problem, :inner_model) crf = get(table, "CriticalResonantField", nothing) - crf === nothing || (problem[:critical_resonant_field] = CriticalResonantFieldControl(; - section_keywords(crf, "Tearing.CriticalResonantField", _struct_fields(CriticalResonantFieldControl))...)) + crf === nothing || ( + problem[:critical_resonant_field] = CriticalResonantFieldControl(; + section_keywords(crf, "Tearing.CriticalResonantField", _struct_fields(CriticalResonantFieldControl))...) + ) config = TearingConfig(; section_keywords(get(table, "search", Dict{String,Any}()), "Tearing.search", _struct_fields(TearingConfig))...) return (; problem, model=inner_model == "SLAYER" ? slayer_model(inputs) : ggj_model(inputs), config) end @@ -413,8 +417,10 @@ function error_fields_from_deck(inputs::AbstractDict, path::AbstractString) haskey(inputs, "ErrorFields") || return nothing table = _deck_paths(inputs["ErrorFields"], path, ("tolerance_file",)) sub(name, T) = T(; section_keywords(get(table, name, Dict{String,Any}()), "ErrorFields.$name", _struct_fields(T))...) - ctrl = ErrorFields.ErrorFieldsControl(; section_keywords(_without(table, "MonteCarlo", "Risk", "scenario", "NTV", "tolerance_file"), - "ErrorFields", _struct_fields(ErrorFields.ErrorFieldsControl))...) + ctrl = ErrorFields.ErrorFieldsControl(; + section_keywords(_without(table, "MonteCarlo", "Risk", "scenario", "NTV", "tolerance_file"), + "ErrorFields", _struct_fields(ErrorFields.ErrorFieldsControl))... + ) file = get(table, "tolerance_file", "") isempty(file) || isfile(file) || error("[ErrorFields] tolerance_file not found: $file") scenario = haskey(table, "scenario") ? section_keywords(table["scenario"], "ErrorFields.scenario", _struct_fields(ErrorFields.ScenarioParameters)) : nothing @@ -637,7 +643,8 @@ function deck_sections(pe::PerturbedEquilibrium.PerturbedEquilibriumState) "compute_torque_response" => resp.compute_torque_response, "regularization_width" => pe.regularization_width) sections = Dict{String,Any}("PerturbedEquilibrium" => table) forcing === nothing && return sections - sections["ForcingTerms"] = forcing isa ForcingTerms.RMPSource && forcing.scale == 1 ? _forcing_table(forcing.ctrl) : - Dict{String,Any}("forcing_data_format" => "hdf5", "forcing_data_file" => _RECORDED_FORCING) + sections["ForcingTerms"] = + forcing isa ForcingTerms.RMPSource && forcing.scale == 1 ? _forcing_table(forcing.ctrl) : + Dict{String,Any}("forcing_data_format" => "hdf5", "forcing_data_file" => _RECORDED_FORCING) return sections end diff --git a/src/Equilibrium/Axisymmetric/Inverse.jl b/src/Equilibrium/Axisymmetric/Inverse.jl index 4f246126a..e8cec7ddb 100644 --- a/src/Equilibrium/Axisymmetric/Inverse.jl +++ b/src/Equilibrium/Axisymmetric/Inverse.jl @@ -83,7 +83,7 @@ function equilibrium_solver(input::InverseRunInput; override_psi_nodes::Union{No twopi = 2 * π - deta = zeros(Float64, mx+1, my+1) + deta = zeros(Float64, mx + 1, my + 1) for ipsi in 0:mx, itheta in 0:my if r2[ipsi+1, itheta+1] == 0.0 deta[ipsi+1, itheta+1] = 0.0 @@ -149,7 +149,7 @@ function equilibrium_solver(input::InverseRunInput; override_psi_nodes::Union{No if mpsi == 0 mpsi = 128 end - sq_xs = psilow .+ (psihigh - psilow) .* (sin.(range(0.0, 1.0; length=mpsi+1) .* (π/2))) .^ 2 + sq_xs = psilow .+ (psihigh - psilow) .* (sin.(range(0.0, 1.0; length=mpsi + 1) .* (π / 2))) .^ 2 elseif grid_type == "pow1" if mpsi == 0 mpsi = 128 @@ -180,7 +180,7 @@ function equilibrium_solver(input::InverseRunInput; override_psi_nodes::Union{No sq_xs = enforce_min_spacing(sq_xs, MIN_KNOT_SPACING) mpsi = length(sq_xs) - 1 end - sq_fs = zeros(Float64, mpsi+1, 4) + sq_fs = zeros(Float64, mpsi + 1, 4) sq = cubic_interp(sq_xs, Series(sq_fs); extrap=ExtendExtrap()) # Coordinate grids @@ -188,21 +188,21 @@ function equilibrium_solver(input::InverseRunInput; override_psi_nodes::Union{No mtheta = my end - theta_range = range(0.0, 1.0; length=mtheta+1) + theta_range = range(0.0, 1.0; length=mtheta + 1) # rzphi components: r², deta, dphi, jac - rzphi_fs = zeros(Float64, mpsi+1, mtheta+1, 4) + rzphi_fs = zeros(Float64, mpsi + 1, mtheta + 1, 4) rzphi_xs = copy(sq_xs) # Vector copy stored in PlasmaEquilibrium; interpolants use the faster Range theta_range (equal to machine precision). rzphi_ys = collect(theta_range) # eqfun components: |B|, metric1, metric2 - eqfun_fs = zeros(Float64, mpsi+1, mtheta+1, 3) + eqfun_fs = zeros(Float64, mpsi + 1, mtheta + 1, 3) eqfun_xs = copy(sq_xs) # Preallocate arrays for periodic spline fitting in the loop - spl_xs = zeros(Float64, mtheta+1) - spl_fs = zeros(Float64, mtheta+1, 5) + spl_xs = zeros(Float64, mtheta + 1) + spl_fs = zeros(Float64, mtheta + 1, 5) spl_post_buf = Vector{Float64}(undef, 5) # scratch for post-SFL spline evaluation # q: i-files use the field-line integral, as Fortran `inverse_run`; a tabulated q splined in ψ is @@ -234,11 +234,11 @@ function equilibrium_solver(input::InverseRunInput; override_psi_nodes::Union{No rfac = sqrt(f_rsq) r = ro + rfac * cos(twopi * (theta + f_deta)) jacfac = fx_rsq * (1 + fy_deta) - fy_rsq * fx_deta - w11 = (1 + fy_deta) * twopi ^ 2 * rfac / jacfac + w11 = (1 + fy_deta) * twopi^2 * rfac / jacfac w12 = -fy_rsq * pi / (rfac * jacfac) - bp = psio * sqrt(w11*w11 + w12*w12) / r + bp = psio * sqrt(w11 * w11 + w12 * w12) / r bt = f_sq_in_buf[1] / r - b = sqrt(bp*bp + bt*bt) + b = sqrt(bp * bp + bt * bt) spl_fs[itheta+1, 1] = f_rsq spl_fs[itheta+1, 2] = f_deta diff --git a/src/Equilibrium/Derived/GeometryProfiles.jl b/src/Equilibrium/Derived/GeometryProfiles.jl index e62c1977a..171a4ad1c 100644 --- a/src/Equilibrium/Derived/GeometryProfiles.jl +++ b/src/Equilibrium/Derived/GeometryProfiles.jl @@ -19,7 +19,7 @@ function compute_geometry_profiles( rzphi_rsquared::FastInterpolations.CubicInterpolantND, rzphi_offset::FastInterpolations.CubicInterpolantND, rzphi_jac::FastInterpolations.CubicInterpolantND, - ro::Float64, + ro::Float64 ) npsi = length(rzphi_xs) mthsurf = length(rzphi_ys) - 1 # skip the periodic duplicate at θ = 1 @@ -60,6 +60,6 @@ function compute_geometry_profiles(pe::PlasmaEquilibrium) return compute_geometry_profiles( pe.rzphi_xs, pe.rzphi_ys, pe.rzphi_rsquared, pe.rzphi_offset, pe.rzphi_jac, - pe.ro, + pe.ro ) end diff --git a/src/Equilibrium/Grid/GridRefinement.jl b/src/Equilibrium/Grid/GridRefinement.jl index 40ff91d9a..772635b8c 100644 --- a/src/Equilibrium/Grid/GridRefinement.jl +++ b/src/Equilibrium/Grid/GridRefinement.jl @@ -408,8 +408,8 @@ function bracket_mandatory_nodes(grid::Vector{Float64}, centers::Vector{Float64} right < hi && push!(kept, (right, true)) end isempty(capped) || @warn "$(length(capped)) rational surface(s) have grid bracket half-widths capped below their Δ′ stencil " * - "(neighboring surface or domain edge too close, or a near-tangent surface with q′ ≈ 0); Δ′ there is less accurate. " * - "(ψ, half-width, stencil): $(join(capped, ", "))" + "(neighboring surface or domain edge too close, or a near-tangent surface with q′ ≈ 0); Δ′ there is less accurate. " * + "(ψ, half-width, stencil): $(join(capped, ", "))" sort!(kept; by=first) merged = Float64[] for (v, _) in kept diff --git a/src/ForceFreeStates/EulerLagrange.jl b/src/ForceFreeStates/EulerLagrange.jl index 6e3b8be63..0c259db9e 100644 --- a/src/ForceFreeStates/EulerLagrange.jl +++ b/src/ForceFreeStates/EulerLagrange.jl @@ -706,8 +706,10 @@ Errors when the solver stops short of the interval's end (e.g. the step size und function solve_el(prob, rtol; callback=COLUMN_ABSTOL_CALLBACK) sol = solve(prob, Vern9(); reltol=rtol, abstol=column_abstol(prob.u0, rtol), callback, save_everystep=false, save_end=true) SciMLBase.successful_retcode(sol) || - error("Euler-Lagrange integration aborted at ψ = $(@sprintf("%.6f", sol.t[end])) before ψ = $(@sprintf("%.6f", prob.tspan[2])) " * - "(retcode $(sol.retcode)). Loosen eulerlagrange_tolerance or refine the ψ grid; for kinetic runs, lower kinetic_factor.") + error( + "Euler-Lagrange integration aborted at ψ = $(@sprintf("%.6f", sol.t[end])) before ψ = $(@sprintf("%.6f", prob.tspan[2])) " * + "(retcode $(sol.retcode)). Loosen eulerlagrange_tolerance or refine the ψ grid; for kinetic runs, lower kinetic_factor." + ) return sol end @@ -962,7 +964,7 @@ function transform_u!(odet::OdeState, intr::ForceFreeStatesInternal) temp[ksol, jsol] = odet.fixfac[ksol, jsol, ifix] end end - mul!(gauss_buffer, view(gauss,:,:,ifix), temp) + mul!(gauss_buffer, view(gauss, :, :, ifix), temp) gauss[:, :, ifix] .= gauss_buffer end # Drop the resonant solutions zeroed at an ideal crossing @@ -976,7 +978,7 @@ function transform_u!(odet::OdeState, intr::ForceFreeStatesInternal) # Region i lies between fixups i-1 and i; its transform is the product of all later reductions transforms[:, :, end] .= identity for ifix in odet.ifix:-1:1 - mul!(view(transforms,:,:,ifix), view(gauss,:,:,ifix), view(transforms,:,:,(ifix+1))) + mul!(view(transforms, :, :, ifix), view(gauss, :, :, ifix), view(transforms, :, :, (ifix + 1))) end jfix = 1 diff --git a/src/ForceFreeStates/Galerkin/GalerkinSolve.jl b/src/ForceFreeStates/Galerkin/GalerkinSolve.jl index ca367e91f..5d4f6d2df 100644 --- a/src/ForceFreeStates/Galerkin/GalerkinSolve.jl +++ b/src/ForceFreeStates/Galerkin/GalerkinSolve.jl @@ -194,7 +194,7 @@ function gal_scaled_lu_solve!(mat::Matrix{ComplexF64}, sol::AbstractVecOrMat{Com n = size(mat, 2) off = kl + ku + 1 # band row holding the diagonal d = [iszero(mat[off, j]) ? 1.0 : 1 / sqrt(abs(mat[off, j])) for j in 1:n] - for j in 1:n, i in max(1, j-ku):min(n, j+kl) + for j in 1:n, i in max(1, j - ku):min(n, j + kl) mat[off+i-j, j] *= d[i] * d[j] end sol .*= d @@ -362,18 +362,18 @@ function gal_cholesky_solve!(mat::Matrix{ComplexF64}, sol::AbstractVecOrMat{Comp n = size(mat, 2) off = 2kl + 1 a(i, j) = mat[off+i-j, j] - band(i) = max(1, i-kl):min(n, i+kl) + band(i) = max(1, i - kl):min(n, i + kl) fixed = [all(j == i ? a(i, j) == 1 : iszero(a(i, j)) for j in band(i)) for i in 1:n] for j in 1:n isfinite(a(j, j)) || return false - for i in (j+1):min(n, j+kl) + for i in (j+1):min(n, j + kl) isfinite(a(i, j)) && isfinite(a(j, i)) || return false fixed[i] || fixed[j] || abs(a(i, j) - conj(a(j, i))) <= 1e-10 * sqrt(abs(a(i, i))) * sqrt(abs(a(j, j))) || return false end end ab = zeros(ComplexF64, kl + 1, n) - for j in 1:n, i in j:min(n, j+kl) + for j in 1:n, i in j:min(n, j + kl) ab[1+i-j, j] = fixed[i] || fixed[j] ? (i == j ? one(ComplexF64) : zero(ComplexF64)) : a(i, j) end gal_zpbtrf!(ab, kl) || return false diff --git a/src/ForceFreeStates/Matching/MatchProblem.jl b/src/ForceFreeStates/Matching/MatchProblem.jl index 494539926..f80f52eb4 100644 --- a/src/ForceFreeStates/Matching/MatchProblem.jl +++ b/src/ForceFreeStates/Matching/MatchProblem.jl @@ -222,7 +222,7 @@ function _compute_match(prob::MatchProblem, model::InnerLayer.GGJModel) sols_cut = gal_sol.xi_cut if isempty(sols_cut) @warn "MatchProblem: the solve retained no cut solution (set cut_solution=true on Galerkin), " * - "so the composite inner-region profiles are skipped; bpen and the matched outer ξ are unaffected" maxlog=1 + "so the composite inner-region profiles are skipped; bpen and the matched outer ξ are unaffected" maxlog = 1 empty!(inner_psi) empty!(inner_xi) empty!(inner_b) diff --git a/src/ForceFreeStates/Riccati/DeltaPrimeBVP.jl b/src/ForceFreeStates/Riccati/DeltaPrimeBVP.jl index a0ac6743b..fcac7b115 100644 --- a/src/ForceFreeStates/Riccati/DeltaPrimeBVP.jl +++ b/src/ForceFreeStates/Riccati/DeltaPrimeBVP.jl @@ -367,7 +367,7 @@ function _assemble_bvp_S_axis(uShootR::Vector{Matrix{ComplexF64}}, if j < msing # Midpoint matching between consecutive surfaces M[junc_rows, _col_right(j, N)] .= -uShootR[j] - M[junc_rows, _col_left(j+1, N)] .= uShootL[j+1] + M[junc_rows, _col_left(j + 1, N)] .= uShootL[j+1] else # Edge junction M[junc_rows, _col_right(msing, N)] .= uShootR[msing] @@ -431,12 +431,12 @@ function _assemble_bvp_FM_axis(Phi_L_mats::Vector{Matrix{ComplexF64}}, M[1:2N, (N+1):(N+2N)] .= Phi_L_mats[1] M[1:2N, col_axis] .= -view(Phi_R_mats[1], :, (N+1):2N) - row_drive_base = 2N + (4N-2)*msing + row_drive_base = 2N + (4N - 2) * msing for j in 1:msing ipert_j = ipert_all[j] cl = _col_left(j, N) cr = _col_right(j, N) - row_cont = 2N + (4N-2)*(j-1) + row_cont = 2N + (4N - 2) * (j - 1) for i in 1:2N if i != ipert_j && i != ipert_j + N row_cont += 1 @@ -447,7 +447,7 @@ function _assemble_bvp_FM_axis(Phi_L_mats::Vector{Matrix{ComplexF64}}, junc_rows = (row_cont+1):(2N+(4N-2)*j) if j < msing M[junc_rows, cr] .= Phi_R_mats[j+1] - M[junc_rows, _col_left(j+1, N)] .= -Phi_L_mats[j+1] + M[junc_rows, _col_left(j + 1, N)] .= -Phi_L_mats[j+1] else M[junc_rows, cr] .= Phi_R_mats[msing+1] if wv !== nothing @@ -487,7 +487,7 @@ function _solve_bvp_and_combine_pest3(M::Matrix{ComplexF64}, msing::Int, N::Int, for jsing in 1:msing, side in 1:2 dRow = 2jsing - (2 - side) fill!(b, 0) - drive_row = use_S_axis ? (nMat - s2 + dRow) : (2N + (4N-2)*msing + dRow) + drive_row = use_S_axis ? (nMat - s2 + dRow) : (2N + (4N - 2) * msing + dRow) b[drive_row] = 1 x = use_lu ? (M_lu \ b) : (M_pinv * b) diff --git a/src/ForceFreeStates/Riccati/Propagators.jl b/src/ForceFreeStates/Riccati/Propagators.jl index 3c0ce25d4..81bd3d831 100644 --- a/src/ForceFreeStates/Riccati/Propagators.jl +++ b/src/ForceFreeStates/Riccati/Propagators.jl @@ -3,7 +3,7 @@ # `riccati_integrator_callback!` saves every step within this fraction of the span (or absolute ψ # floor, for short chunks) of a segment's right end; elsewhere every `save_interval`-th step. const SAVE_NEAR_END_FRAC = 0.05 -const SAVE_NEAR_END_PSI = 1e-4 +const SAVE_NEAR_END_PSI = 1e-4 """ assemble_fm_matrix(propagators, idx_range; condition=false, T_init=nothing) -> Matrix{ComplexF64} @@ -13,6 +13,7 @@ mapping the IC at the start of `idx_range[1]` to the state at the end of `idx_ra (`T_init` defaults to the identity). Each `ChunkPropagator` stores the 2N columns of Φ split into two N×N×2 blocks: + ``` block_upper_ic[:,:,1:2] ↔ Φ[:,1:N] (result from IC=(I,0)) block_lower_ic[:,:,1:2] ↔ Φ[:,N+1:2N] (result from IC=(0,I)) @@ -23,8 +24,8 @@ the N U₂ columns survive. Use it only for the axis→first-surface segment, wh needs only U₂ ICs; never for inter-surface segments, where both halves carry information. """ function assemble_fm_matrix(propagators::Vector{ChunkPropagator}, idx_range; - condition::Bool=false, - T_init::Union{Nothing,Matrix{ComplexF64}}=nothing) + condition::Bool=false, + T_init::Union{Nothing,Matrix{ComplexF64}}=nothing) # Take N from T_init when given, so an empty idx_range (or propagator list) still works. N = if T_init !== nothing size(T_init, 1) ÷ 2 @@ -110,7 +111,7 @@ end riccati_der!(du, u, params, psieval) Evaluate the explicit dual Riccati ODE right-hand side: - dS/dψ = w†·F̄⁻¹·w - S·Ḡ·S, w = Q - K̄·S +dS/dψ = w†·F̄⁻¹·w - S·Ḡ·S, w = Q - K̄·S where Q = diag(1/(m - n·q)) is the diagonal singular factor matrix. The identity slice u[:,:,2] = I does not evolve (du[:,:,2] = 0). @@ -132,7 +133,7 @@ See: Glasser (2018) Phys. Plasmas 25, 032507 — Eq. 19 (dual Riccati form) _, equil, mats, intr, odet, _ = params Npert = intr.numpert_total - S = @view u[:, :, 1] + S = @view u[:, :, 1] dS = @view du[:, :, 1] @view(du[:, :, 2]) .= 0 # identity does not evolve @@ -146,9 +147,9 @@ See: Glasser (2018) Phys. Plasmas 25, 032507 — Eq. 19 (dual Riccati form) fmat_lower = acquire!(pool, ComplexF64, Npert, Npert) kmat = similar!(pool, fmat_lower) gmat = similar!(pool, fmat_lower) - w = similar!(pool, fmat_lower) # w = Q - K̄·S - v = similar!(pool, fmat_lower) # v = F̄⁻¹·w (then reused for S·Ḡ·S) - tmp = similar!(pool, fmat_lower) # scratch + w = similar!(pool, fmat_lower) # w = Q - K̄·S + v = similar!(pool, fmat_lower) # v = F̄⁻¹·w (then reused for S·Ḡ·S) + tmp = similar!(pool, fmat_lower) # scratch # Evaluate F̄ (Cholesky factor), K̄, Ḡ splines at current ψ mats.ideal.F_spline_lower(vec(fmat_lower), psieval; hint=mats._hint) @@ -225,7 +226,7 @@ function riccati_integrate_chunk!( cb = DiscreteCallback((u, t, integrator) -> true, riccati_integrator_callback!) rtol = ctrl.algorithm.eulerlagrange_tolerance prob = ODEProblem(sing_der!, odet.u, (chunk.psi_start, chunk.psi_end), - (ctrl, equil, mats, intr, odet, chunk)) + (ctrl, equil, mats, intr, odet, chunk)) sol = solve_el(prob, rtol; callback=cb) odet.u .= sol.u[end] odet.psifac = sol.t[end] @@ -239,8 +240,8 @@ end renormalize_riccati_inplace!(u, N) In-place Riccati renormalization on an arbitrary N×N×2 array: - u[:,:,1] = U₁ · U₂⁻¹ (new S) - u[:,:,2] = I +u[:,:,1] = U₁ · U₂⁻¹ (new S) +u[:,:,2] = I The Riccati analogue of Gaussian reduction: keeps the inputs to `sing_der!` bounded. """ @@ -282,8 +283,8 @@ function integrate_propagator_chunk!( N = intr.numpert_total # Backward chunks integrate psi_end → psi_start, where forward-growing solutions decay. tspan = chunk.direction == 1 ? - (chunk.psi_start, chunk.psi_end) : - (chunk.psi_end, chunk.psi_start) + (chunk.psi_start, chunk.psi_end) : + (chunk.psi_end, chunk.psi_start) rtol = ctrl.algorithm.eulerlagrange_tolerance params = (ctrl, equil, mats, intr, odet_proxy, chunk) @@ -331,12 +332,12 @@ function integrate_fm_with_ua_ic( equil::Equilibrium.PlasmaEquilibrium, mats::MatrixSplines, intr::ForceFreeStatesInternal; - backward::Bool = false, - psi_ua::Float64 = NaN + backward::Bool=false, + psi_ua::Float64=NaN ) N = intr.numpert_total psi_start = chunks[first(chunk_range)].psi_start - psi_end = chunks[last(chunk_range)].psi_end + psi_end = chunks[last(chunk_range)].psi_end # ua lives at the inner-layer boundary psi_ua, which may differ slightly from the chunk boundary. if backward && !isnan(psi_ua) psi_end = psi_ua @@ -359,8 +360,8 @@ function integrate_fm_with_ua_ic( odet_proxy.mats_hint[] = 1 prob = ODEProblem(sing_der!, u0, tspan, params) sol = solve_el(prob, rtol) - result[1:N, 1:N] .= sol.u[end][:, :, 1] - result[N+1:2N, 1:N] .= sol.u[end][:, :, 2] + result[1:N, 1:N] .= sol.u[end][:, :, 1] + result[N+1:2N, 1:N] .= sol.u[end][:, :, 2] # Batch 2: columns N+1:2N of T (small solutions) u0[:, :, 1] .= ua[:, N+1:2N, 1] @@ -369,8 +370,8 @@ function integrate_fm_with_ua_ic( odet_proxy.mats_hint[] = 1 prob = ODEProblem(sing_der!, u0, tspan, params) sol = solve_el(prob, rtol) - result[1:N, N+1:2N] .= sol.u[end][:, :, 1] - result[N+1:2N, N+1:2N] .= sol.u[end][:, :, 2] + result[1:N, N+1:2N] .= sol.u[end][:, :, 1] + result[N+1:2N, N+1:2N] .= sol.u[end][:, :, 2] return result end @@ -422,8 +423,8 @@ function apply_propagator_inverse!(odet::OdeState, prop::ChunkPropagator) prop.block_upper_ic[:,:,2] prop.block_lower_ic[:,:,2]] #! format: on # x = Φ_bwd⁻¹ · [U₁_old; U₂_old] advances psi_start → psi_end. - u_old = [odet.u[:,:,1]; odet.u[:,:,2]] # 2N × N + u_old = [odet.u[:, :, 1]; odet.u[:, :, 2]] # 2N × N u_new = Φ \ u_old # LU solve, 2N × N - odet.u[:,:,1] .= u_new[1:N, :] - odet.u[:,:,2] .= u_new[N+1:2N, :] + odet.u[:, :, 1] .= u_new[1:N, :] + odet.u[:, :, 2] .= u_new[N+1:2N, :] end diff --git a/src/ForceFreeStates/Surfaces/Asymptotics.jl b/src/ForceFreeStates/Surfaces/Asymptotics.jl index 6f7345c79..0d3f3af24 100644 --- a/src/ForceFreeStates/Surfaces/Asymptotics.jl +++ b/src/ForceFreeStates/Surfaces/Asymptotics.jl @@ -97,7 +97,7 @@ function compute_sing_asymptotics( trace_floor = 64 * Base.eps(Float64) * opnorm(m0mat_block, Inf) sig > 0 && abs(block_tr) / 2 > max(1e-3 * abs(alpha_i), trace_floor) && @warn @sprintf("Resonant M₀ block at ψ=%.6f, m=%d (sig=%+.0f): |tr|/2 = %.3e is not small against |α| = %.3e", - singp.psifac, singp.m[i], sig, abs(block_tr) / 2, abs(alpha_i)) _id=(:resonant_trace, objectid(intr), singp.psifac, singp.m[i]) maxlog=1 + singp.psifac, singp.m[i], sig, abs(block_tr) / 2, abs(alpha_i)) _id = (:resonant_trace, objectid(intr), singp.psifac, singp.m[i]) maxlog = 1 r1_i = r1[i] power[r1_i] = p_big power[r1_i+intr.numpert_total] = p_small @@ -124,7 +124,7 @@ function compute_sing_asymptotics( msg *= @sprintf(" m0mat(1,2)= %+.12e %+.12ei\n", real(m0mat[1, 2]), imag(m0mat[1, 2])) msg *= @sprintf(" m0mat(2,1)= %+.12e %+.12ei\n", real(m0mat[2, 1]), imag(m0mat[2, 1])) msg *= @sprintf(" m0mat(2,2)= %+.12e %+.12ei\n", real(m0mat[2, 2]), imag(m0mat[2, 2])) - block_det = m0mat[1, 1]*m0mat[2, 2] - m0mat[2, 1]*m0mat[1, 2] + block_det = m0mat[1, 1] * m0mat[2, 2] - m0mat[2, 1] * m0mat[1, 2] block_tr = m0mat[1, 1] + m0mat[2, 2] msg *= @sprintf(" det= %+.12e, tr= %+.12e %+.12ei\n", real(block_det), real(block_tr), imag(block_tr)) msg *= @sprintf(" alpha= %+.12e %+.12ei\n", real(alpha[1]), imag(alpha[1])) diff --git a/src/ForceFreeStates/Surfaces/Finding.jl b/src/ForceFreeStates/Surfaces/Finding.jl index 61e8ec11b..389e7c543 100644 --- a/src/ForceFreeStates/Surfaces/Finding.jl +++ b/src/ForceFreeStates/Surfaces/Finding.jl @@ -131,9 +131,11 @@ function sing_lim!(intr::ForceFreeStatesInternal, ctrl::ForceFreeStatesControl, # Rational-offset cutoff needs the resolved single-n range on `intr`; multi-n falls back to qhigh / psihigh. if ctrl.truncate_at_rational_offset && intr.nlow <= 0 - error("sing_lim!: truncate_at_rational_offset = true requires a resolved toroidal range, but got intr.nlow=$(intr.nlow). " * - "Assign intr.nlow / intr.nhigh (resolve_mode_space!) before calling sing_lim!, " * - "or set truncate_at_rational_offset = false to truncate via qhigh / psihigh instead.") + error( + "sing_lim!: truncate_at_rational_offset = true requires a resolved toroidal range, but got intr.nlow=$(intr.nlow). " * + "Assign intr.nlow / intr.nhigh (resolve_mode_space!) before calling sing_lim!, " * + "or set truncate_at_rational_offset = false to truncate via qhigh / psihigh instead." + ) elseif ctrl.truncate_at_rational_offset && intr.nlow != intr.nhigh @warn "truncate_at_rational_offset = true is ignored for multi-n runs (n = $(intr.nlow):$(intr.nhigh)); falling back to qhigh / psihigh truncation." elseif ctrl.truncate_at_rational_offset diff --git a/src/ForcingTerms/ForcingTerms.jl b/src/ForcingTerms/ForcingTerms.jl index eae14b038..98738ad6a 100644 --- a/src/ForcingTerms/ForcingTerms.jl +++ b/src/ForcingTerms/ForcingTerms.jl @@ -53,7 +53,6 @@ Data structure for a single forcing mode. - `n::Int` - Toroidal mode number - `m::Int` - Poloidal mode number - - `amplitude::ComplexF64` - Complex amplitude in unit-norm convention (= Fortran Phi_x, T·m² per unit-norm cell) after loading. File inputs are tagged by their input convention: @@ -367,7 +366,9 @@ end RMPField(modes::Vector{ForcingMode}; scale::Number=1.0) = RMPSpectrum([ForcingMode(; n=mode.n, m=mode.m, amplitude=mode.amplitude) for mode in modes], ComplexF64(scale)) -"Flattened weighted-leaf list of any [`RMPField`](@ref)." +""" +Flattened weighted-leaf list of any [`RMPField`](@ref). +""" _rmp_terms(f::Union{RMPSource,RMPSpectrum}) = Union{RMPSource,RMPSpectrum}[f] _rmp_terms(f::RMPFieldSum) = f.terms diff --git a/src/ForcingTerms/coil_geometries/jet_ex_mid.dat b/src/ForcingTerms/coil_geometries/jet_ex_mid.dat index ea2549ad3..639e8ca41 100644 --- a/src/ForcingTerms/coil_geometries/jet_ex_mid.dat +++ b/src/ForcingTerms/coil_geometries/jet_ex_mid.dat @@ -1,169 +1,169 @@ - 4 1 42 1.00 - 5.5000e+00 0.0000e+00 3.0900e+00 - 5.4795e+00 4.7404e-01 3.0900e+00 - 5.4183e+00 9.4456e-01 3.0900e+00 - 5.3167e+00 1.4080e+00 3.0900e+00 - 5.1756e+00 1.8611e+00 3.0900e+00 - 4.9959e+00 2.3002e+00 3.0900e+00 - 4.7791e+00 2.7222e+00 3.0900e+00 - 4.5266e+00 3.1240e+00 3.0900e+00 - 4.2405e+00 3.5025e+00 3.0900e+00 - 3.9229e+00 3.8550e+00 3.0900e+00 - 3.5760e+00 4.1788e+00 3.0900e+00 - 3.2025e+00 4.4714e+00 3.0900e+00 - 2.8052e+00 4.7308e+00 3.0900e+00 - 2.3870e+00 4.9550e+00 3.0900e+00 - 1.9511e+00 5.1423e+00 3.0900e+00 - 1.5006e+00 5.2913e+00 3.0900e+00 - 1.0390e+00 5.4010e+00 3.0900e+00 - 5.6960e-01 5.4704e+00 3.0900e+00 - 9.5988e-02 5.4992e+00 3.0900e+00 - 9.5988e-02 5.4992e+00 3.0900e+00 - 9.5988e-02 5.4992e+00 1.5700e+00 - 9.5988e-02 5.4992e+00 5.0000e-02 - 9.5988e-02 5.4992e+00 -1.4700e+00 - 9.5988e-02 5.4992e+00 -2.9900e+00 - 7.0430e-01 5.4547e+00 -2.9900e+00 - 1.3039e+00 5.3432e+00 -2.9900e+00 - 1.8876e+00 5.1660e+00 -2.9900e+00 - 2.4479e+00 4.9252e+00 -2.9900e+00 - 2.9782e+00 4.6239e+00 -2.9900e+00 - 3.4719e+00 4.2657e+00 -2.9900e+00 - 3.9229e+00 3.8550e+00 -2.9900e+00 - 4.3256e+00 3.3969e+00 -2.9900e+00 - 4.6751e+00 2.8971e+00 -2.9900e+00 - 4.9672e+00 2.3616e+00 -2.9900e+00 - 5.1981e+00 1.7971e+00 -2.9900e+00 - 5.3651e+00 1.2105e+00 -2.9900e+00 - 5.4662e+00 6.0899e-01 -2.9900e+00 - 5.5000e+00 0.0000e+00 -2.9900e+00 - 5.5000e+00 0.0000e+00 -1.4700e+00 - 5.5000e+00 0.0000e+00 5.0000e-02 - 5.5000e+00 0.0000e+00 1.5700e+00 - 5.5000e+00 0.0000e+00 3.0900e+00 - 3.3678e-16 5.5000e+00 3.0900e+00 - -4.7404e-01 5.4795e+00 3.0900e+00 - -9.4456e-01 5.4183e+00 3.0900e+00 - -1.4080e+00 5.3167e+00 3.0900e+00 - -1.8611e+00 5.1756e+00 3.0900e+00 - -2.3002e+00 4.9959e+00 3.0900e+00 - -2.7222e+00 4.7791e+00 3.0900e+00 - -3.1240e+00 4.5266e+00 3.0900e+00 - -3.5025e+00 4.2405e+00 3.0900e+00 - -3.8550e+00 3.9229e+00 3.0900e+00 - -4.1788e+00 3.5760e+00 3.0900e+00 - -4.4714e+00 3.2025e+00 3.0900e+00 - -4.7308e+00 2.8052e+00 3.0900e+00 - -4.9550e+00 2.3870e+00 3.0900e+00 - -5.1423e+00 1.9511e+00 3.0900e+00 - -5.2913e+00 1.5006e+00 3.0900e+00 - -5.4010e+00 1.0390e+00 3.0900e+00 - -5.4704e+00 5.6960e-01 3.0900e+00 - -5.4992e+00 9.5988e-02 3.0900e+00 - -5.4992e+00 9.5988e-02 3.0900e+00 - -5.4992e+00 9.5988e-02 1.5700e+00 - -5.4992e+00 9.5988e-02 5.0000e-02 - -5.4992e+00 9.5988e-02 -1.4700e+00 - -5.4992e+00 9.5988e-02 -2.9900e+00 - -5.4547e+00 7.0430e-01 -2.9900e+00 - -5.3432e+00 1.3039e+00 -2.9900e+00 - -5.1660e+00 1.8876e+00 -2.9900e+00 - -4.9252e+00 2.4479e+00 -2.9900e+00 - -4.6239e+00 2.9782e+00 -2.9900e+00 - -4.2657e+00 3.4719e+00 -2.9900e+00 - -3.8550e+00 3.9229e+00 -2.9900e+00 - -3.3969e+00 4.3256e+00 -2.9900e+00 - -2.8971e+00 4.6751e+00 -2.9900e+00 - -2.3616e+00 4.9672e+00 -2.9900e+00 - -1.7971e+00 5.1981e+00 -2.9900e+00 - -1.2105e+00 5.3651e+00 -2.9900e+00 - -6.0899e-01 5.4662e+00 -2.9900e+00 - 3.3678e-16 5.5000e+00 -2.9900e+00 - 3.3678e-16 5.5000e+00 -1.4700e+00 - 3.3678e-16 5.5000e+00 5.0000e-02 - 3.3678e-16 5.5000e+00 1.5700e+00 - 3.3678e-16 5.5000e+00 3.0900e+00 - -5.5000e+00 6.7356e-16 3.0900e+00 - -5.4795e+00 -4.7404e-01 3.0900e+00 - -5.4183e+00 -9.4456e-01 3.0900e+00 - -5.3167e+00 -1.4080e+00 3.0900e+00 - -5.1756e+00 -1.8611e+00 3.0900e+00 - -4.9959e+00 -2.3002e+00 3.0900e+00 - -4.7791e+00 -2.7222e+00 3.0900e+00 - -4.5266e+00 -3.1240e+00 3.0900e+00 - -4.2405e+00 -3.5025e+00 3.0900e+00 - -3.9229e+00 -3.8550e+00 3.0900e+00 - -3.5760e+00 -4.1788e+00 3.0900e+00 - -3.2025e+00 -4.4714e+00 3.0900e+00 - -2.8052e+00 -4.7308e+00 3.0900e+00 - -2.3870e+00 -4.9550e+00 3.0900e+00 - -1.9511e+00 -5.1423e+00 3.0900e+00 - -1.5006e+00 -5.2913e+00 3.0900e+00 - -1.0390e+00 -5.4010e+00 3.0900e+00 - -5.6960e-01 -5.4704e+00 3.0900e+00 - -9.5988e-02 -5.4992e+00 3.0900e+00 - -9.5988e-02 -5.4992e+00 3.0900e+00 - -9.5988e-02 -5.4992e+00 1.5700e+00 - -9.5988e-02 -5.4992e+00 5.0000e-02 - -9.5988e-02 -5.4992e+00 -1.4700e+00 - -9.5988e-02 -5.4992e+00 -2.9900e+00 - -7.0430e-01 -5.4547e+00 -2.9900e+00 - -1.3039e+00 -5.3432e+00 -2.9900e+00 - -1.8876e+00 -5.1660e+00 -2.9900e+00 - -2.4479e+00 -4.9252e+00 -2.9900e+00 - -2.9782e+00 -4.6239e+00 -2.9900e+00 - -3.4719e+00 -4.2657e+00 -2.9900e+00 - -3.9229e+00 -3.8550e+00 -2.9900e+00 - -4.3256e+00 -3.3969e+00 -2.9900e+00 - -4.6751e+00 -2.8971e+00 -2.9900e+00 - -4.9672e+00 -2.3616e+00 -2.9900e+00 - -5.1981e+00 -1.7971e+00 -2.9900e+00 - -5.3651e+00 -1.2105e+00 -2.9900e+00 - -5.4662e+00 -6.0899e-01 -2.9900e+00 - -5.5000e+00 6.7356e-16 -2.9900e+00 - -5.5000e+00 6.7356e-16 -1.4700e+00 - -5.5000e+00 6.7356e-16 5.0000e-02 - -5.5000e+00 6.7356e-16 1.5700e+00 - -5.5000e+00 6.7356e-16 3.0900e+00 - -1.0103e-15 -5.5000e+00 3.0900e+00 - 4.7404e-01 -5.4795e+00 3.0900e+00 - 9.4456e-01 -5.4183e+00 3.0900e+00 - 1.4080e+00 -5.3167e+00 3.0900e+00 - 1.8611e+00 -5.1756e+00 3.0900e+00 - 2.3002e+00 -4.9959e+00 3.0900e+00 - 2.7222e+00 -4.7791e+00 3.0900e+00 - 3.1240e+00 -4.5266e+00 3.0900e+00 - 3.5025e+00 -4.2405e+00 3.0900e+00 - 3.8550e+00 -3.9229e+00 3.0900e+00 - 4.1788e+00 -3.5760e+00 3.0900e+00 - 4.4714e+00 -3.2025e+00 3.0900e+00 - 4.7308e+00 -2.8052e+00 3.0900e+00 - 4.9550e+00 -2.3870e+00 3.0900e+00 - 5.1423e+00 -1.9511e+00 3.0900e+00 - 5.2913e+00 -1.5006e+00 3.0900e+00 - 5.4010e+00 -1.0390e+00 3.0900e+00 - 5.4704e+00 -5.6960e-01 3.0900e+00 - 5.4992e+00 -9.5988e-02 3.0900e+00 - 5.4992e+00 -9.5988e-02 3.0900e+00 - 5.4992e+00 -9.5988e-02 1.5700e+00 - 5.4992e+00 -9.5988e-02 5.0000e-02 - 5.4992e+00 -9.5988e-02 -1.4700e+00 - 5.4992e+00 -9.5988e-02 -2.9900e+00 - 5.4547e+00 -7.0430e-01 -2.9900e+00 - 5.3432e+00 -1.3039e+00 -2.9900e+00 - 5.1660e+00 -1.8876e+00 -2.9900e+00 - 4.9252e+00 -2.4479e+00 -2.9900e+00 - 4.6239e+00 -2.9782e+00 -2.9900e+00 - 4.2657e+00 -3.4719e+00 -2.9900e+00 - 3.8550e+00 -3.9229e+00 -2.9900e+00 - 3.3969e+00 -4.3256e+00 -2.9900e+00 - 2.8971e+00 -4.6751e+00 -2.9900e+00 - 2.3616e+00 -4.9672e+00 -2.9900e+00 - 1.7971e+00 -5.1981e+00 -2.9900e+00 - 1.2105e+00 -5.3651e+00 -2.9900e+00 - 6.0899e-01 -5.4662e+00 -2.9900e+00 - -1.0103e-15 -5.5000e+00 -2.9900e+00 - -1.0103e-15 -5.5000e+00 -1.4700e+00 - -1.0103e-15 -5.5000e+00 5.0000e-02 - -1.0103e-15 -5.5000e+00 1.5700e+00 - -1.0103e-15 -5.5000e+00 3.0900e+00 + 4 1 42 1.00 + 5.5000e+00 0.0000e+00 3.0900e+00 + 5.4795e+00 4.7404e-01 3.0900e+00 + 5.4183e+00 9.4456e-01 3.0900e+00 + 5.3167e+00 1.4080e+00 3.0900e+00 + 5.1756e+00 1.8611e+00 3.0900e+00 + 4.9959e+00 2.3002e+00 3.0900e+00 + 4.7791e+00 2.7222e+00 3.0900e+00 + 4.5266e+00 3.1240e+00 3.0900e+00 + 4.2405e+00 3.5025e+00 3.0900e+00 + 3.9229e+00 3.8550e+00 3.0900e+00 + 3.5760e+00 4.1788e+00 3.0900e+00 + 3.2025e+00 4.4714e+00 3.0900e+00 + 2.8052e+00 4.7308e+00 3.0900e+00 + 2.3870e+00 4.9550e+00 3.0900e+00 + 1.9511e+00 5.1423e+00 3.0900e+00 + 1.5006e+00 5.2913e+00 3.0900e+00 + 1.0390e+00 5.4010e+00 3.0900e+00 + 5.6960e-01 5.4704e+00 3.0900e+00 + 9.5988e-02 5.4992e+00 3.0900e+00 + 9.5988e-02 5.4992e+00 3.0900e+00 + 9.5988e-02 5.4992e+00 1.5700e+00 + 9.5988e-02 5.4992e+00 5.0000e-02 + 9.5988e-02 5.4992e+00 -1.4700e+00 + 9.5988e-02 5.4992e+00 -2.9900e+00 + 7.0430e-01 5.4547e+00 -2.9900e+00 + 1.3039e+00 5.3432e+00 -2.9900e+00 + 1.8876e+00 5.1660e+00 -2.9900e+00 + 2.4479e+00 4.9252e+00 -2.9900e+00 + 2.9782e+00 4.6239e+00 -2.9900e+00 + 3.4719e+00 4.2657e+00 -2.9900e+00 + 3.9229e+00 3.8550e+00 -2.9900e+00 + 4.3256e+00 3.3969e+00 -2.9900e+00 + 4.6751e+00 2.8971e+00 -2.9900e+00 + 4.9672e+00 2.3616e+00 -2.9900e+00 + 5.1981e+00 1.7971e+00 -2.9900e+00 + 5.3651e+00 1.2105e+00 -2.9900e+00 + 5.4662e+00 6.0899e-01 -2.9900e+00 + 5.5000e+00 0.0000e+00 -2.9900e+00 + 5.5000e+00 0.0000e+00 -1.4700e+00 + 5.5000e+00 0.0000e+00 5.0000e-02 + 5.5000e+00 0.0000e+00 1.5700e+00 + 5.5000e+00 0.0000e+00 3.0900e+00 + 3.3678e-16 5.5000e+00 3.0900e+00 + -4.7404e-01 5.4795e+00 3.0900e+00 + -9.4456e-01 5.4183e+00 3.0900e+00 + -1.4080e+00 5.3167e+00 3.0900e+00 + -1.8611e+00 5.1756e+00 3.0900e+00 + -2.3002e+00 4.9959e+00 3.0900e+00 + -2.7222e+00 4.7791e+00 3.0900e+00 + -3.1240e+00 4.5266e+00 3.0900e+00 + -3.5025e+00 4.2405e+00 3.0900e+00 + -3.8550e+00 3.9229e+00 3.0900e+00 + -4.1788e+00 3.5760e+00 3.0900e+00 + -4.4714e+00 3.2025e+00 3.0900e+00 + -4.7308e+00 2.8052e+00 3.0900e+00 + -4.9550e+00 2.3870e+00 3.0900e+00 + -5.1423e+00 1.9511e+00 3.0900e+00 + -5.2913e+00 1.5006e+00 3.0900e+00 + -5.4010e+00 1.0390e+00 3.0900e+00 + -5.4704e+00 5.6960e-01 3.0900e+00 + -5.4992e+00 9.5988e-02 3.0900e+00 + -5.4992e+00 9.5988e-02 3.0900e+00 + -5.4992e+00 9.5988e-02 1.5700e+00 + -5.4992e+00 9.5988e-02 5.0000e-02 + -5.4992e+00 9.5988e-02 -1.4700e+00 + -5.4992e+00 9.5988e-02 -2.9900e+00 + -5.4547e+00 7.0430e-01 -2.9900e+00 + -5.3432e+00 1.3039e+00 -2.9900e+00 + -5.1660e+00 1.8876e+00 -2.9900e+00 + -4.9252e+00 2.4479e+00 -2.9900e+00 + -4.6239e+00 2.9782e+00 -2.9900e+00 + -4.2657e+00 3.4719e+00 -2.9900e+00 + -3.8550e+00 3.9229e+00 -2.9900e+00 + -3.3969e+00 4.3256e+00 -2.9900e+00 + -2.8971e+00 4.6751e+00 -2.9900e+00 + -2.3616e+00 4.9672e+00 -2.9900e+00 + -1.7971e+00 5.1981e+00 -2.9900e+00 + -1.2105e+00 5.3651e+00 -2.9900e+00 + -6.0899e-01 5.4662e+00 -2.9900e+00 + 3.3678e-16 5.5000e+00 -2.9900e+00 + 3.3678e-16 5.5000e+00 -1.4700e+00 + 3.3678e-16 5.5000e+00 5.0000e-02 + 3.3678e-16 5.5000e+00 1.5700e+00 + 3.3678e-16 5.5000e+00 3.0900e+00 + -5.5000e+00 6.7356e-16 3.0900e+00 + -5.4795e+00 -4.7404e-01 3.0900e+00 + -5.4183e+00 -9.4456e-01 3.0900e+00 + -5.3167e+00 -1.4080e+00 3.0900e+00 + -5.1756e+00 -1.8611e+00 3.0900e+00 + -4.9959e+00 -2.3002e+00 3.0900e+00 + -4.7791e+00 -2.7222e+00 3.0900e+00 + -4.5266e+00 -3.1240e+00 3.0900e+00 + -4.2405e+00 -3.5025e+00 3.0900e+00 + -3.9229e+00 -3.8550e+00 3.0900e+00 + -3.5760e+00 -4.1788e+00 3.0900e+00 + -3.2025e+00 -4.4714e+00 3.0900e+00 + -2.8052e+00 -4.7308e+00 3.0900e+00 + -2.3870e+00 -4.9550e+00 3.0900e+00 + -1.9511e+00 -5.1423e+00 3.0900e+00 + -1.5006e+00 -5.2913e+00 3.0900e+00 + -1.0390e+00 -5.4010e+00 3.0900e+00 + -5.6960e-01 -5.4704e+00 3.0900e+00 + -9.5988e-02 -5.4992e+00 3.0900e+00 + -9.5988e-02 -5.4992e+00 3.0900e+00 + -9.5988e-02 -5.4992e+00 1.5700e+00 + -9.5988e-02 -5.4992e+00 5.0000e-02 + -9.5988e-02 -5.4992e+00 -1.4700e+00 + -9.5988e-02 -5.4992e+00 -2.9900e+00 + -7.0430e-01 -5.4547e+00 -2.9900e+00 + -1.3039e+00 -5.3432e+00 -2.9900e+00 + -1.8876e+00 -5.1660e+00 -2.9900e+00 + -2.4479e+00 -4.9252e+00 -2.9900e+00 + -2.9782e+00 -4.6239e+00 -2.9900e+00 + -3.4719e+00 -4.2657e+00 -2.9900e+00 + -3.9229e+00 -3.8550e+00 -2.9900e+00 + -4.3256e+00 -3.3969e+00 -2.9900e+00 + -4.6751e+00 -2.8971e+00 -2.9900e+00 + -4.9672e+00 -2.3616e+00 -2.9900e+00 + -5.1981e+00 -1.7971e+00 -2.9900e+00 + -5.3651e+00 -1.2105e+00 -2.9900e+00 + -5.4662e+00 -6.0899e-01 -2.9900e+00 + -5.5000e+00 6.7356e-16 -2.9900e+00 + -5.5000e+00 6.7356e-16 -1.4700e+00 + -5.5000e+00 6.7356e-16 5.0000e-02 + -5.5000e+00 6.7356e-16 1.5700e+00 + -5.5000e+00 6.7356e-16 3.0900e+00 + -1.0103e-15 -5.5000e+00 3.0900e+00 + 4.7404e-01 -5.4795e+00 3.0900e+00 + 9.4456e-01 -5.4183e+00 3.0900e+00 + 1.4080e+00 -5.3167e+00 3.0900e+00 + 1.8611e+00 -5.1756e+00 3.0900e+00 + 2.3002e+00 -4.9959e+00 3.0900e+00 + 2.7222e+00 -4.7791e+00 3.0900e+00 + 3.1240e+00 -4.5266e+00 3.0900e+00 + 3.5025e+00 -4.2405e+00 3.0900e+00 + 3.8550e+00 -3.9229e+00 3.0900e+00 + 4.1788e+00 -3.5760e+00 3.0900e+00 + 4.4714e+00 -3.2025e+00 3.0900e+00 + 4.7308e+00 -2.8052e+00 3.0900e+00 + 4.9550e+00 -2.3870e+00 3.0900e+00 + 5.1423e+00 -1.9511e+00 3.0900e+00 + 5.2913e+00 -1.5006e+00 3.0900e+00 + 5.4010e+00 -1.0390e+00 3.0900e+00 + 5.4704e+00 -5.6960e-01 3.0900e+00 + 5.4992e+00 -9.5988e-02 3.0900e+00 + 5.4992e+00 -9.5988e-02 3.0900e+00 + 5.4992e+00 -9.5988e-02 1.5700e+00 + 5.4992e+00 -9.5988e-02 5.0000e-02 + 5.4992e+00 -9.5988e-02 -1.4700e+00 + 5.4992e+00 -9.5988e-02 -2.9900e+00 + 5.4547e+00 -7.0430e-01 -2.9900e+00 + 5.3432e+00 -1.3039e+00 -2.9900e+00 + 5.1660e+00 -1.8876e+00 -2.9900e+00 + 4.9252e+00 -2.4479e+00 -2.9900e+00 + 4.6239e+00 -2.9782e+00 -2.9900e+00 + 4.2657e+00 -3.4719e+00 -2.9900e+00 + 3.8550e+00 -3.9229e+00 -2.9900e+00 + 3.3969e+00 -4.3256e+00 -2.9900e+00 + 2.8971e+00 -4.6751e+00 -2.9900e+00 + 2.3616e+00 -4.9672e+00 -2.9900e+00 + 1.7971e+00 -5.1981e+00 -2.9900e+00 + 1.2105e+00 -5.3651e+00 -2.9900e+00 + 6.0899e-01 -5.4662e+00 -2.9900e+00 + -1.0103e-15 -5.5000e+00 -2.9900e+00 + -1.0103e-15 -5.5000e+00 -1.4700e+00 + -1.0103e-15 -5.5000e+00 5.0000e-02 + -1.0103e-15 -5.5000e+00 1.5700e+00 + -1.0103e-15 -5.5000e+00 3.0900e+00 diff --git a/src/ForcingTerms/coil_geometries/jtext_l.dat b/src/ForcingTerms/coil_geometries/jtext_l.dat index b744bedd8..476b55451 100644 --- a/src/ForcingTerms/coil_geometries/jtext_l.dat +++ b/src/ForcingTerms/coil_geometries/jtext_l.dat @@ -1,81 +1,81 @@ - 4 1 20 1.00 - 1.2000e+00 1.6000e-02 -3.9800e-01 - 1.2000e+00 1.6000e-02 -3.3300e-01 - 1.2000e+00 2.5370e-02 -3.1000e-01 - 1.2000e+00 4.8000e-02 -3.0100e-01 - 1.2000e+00 1.3200e-01 -3.0100e-01 - 1.1880e+00 1.5800e-01 -3.0100e-01 - 1.1620e+00 1.6300e-01 -3.0100e-01 - 7.9400e-01 9.0000e-02 -3.0100e-01 - 7.7500e-01 7.9000e-02 -3.0100e-01 - 7.6800e-01 5.8000e-02 -3.0100e-01 - 7.6800e-01 -6.2000e-02 -3.0100e-01 - 7.7500e-01 -8.3000e-02 -3.0100e-01 - 7.9500e-01 -9.4000e-02 -3.0100e-01 - 1.1620e+00 -1.6700e-01 -3.0100e-01 - 1.1880e+00 -1.6000e-01 -3.0100e-01 - 1.2000e+00 -1.3500e-01 -3.0100e-01 - 1.2000e+00 -5.0000e-02 -3.0100e-01 - 1.2000e+00 -2.5370e-02 -3.1000e-01 - 1.2000e+00 -1.6000e-02 -3.3300e-01 - 1.2000e+00 -1.6000e-02 -3.9800e-01 - 1.6000e-02 1.2000e+00 -3.9800e-01 - 1.6000e-02 1.2000e+00 -3.3300e-01 - 2.5370e-02 1.2000e+00 -3.1000e-01 - 4.8000e-02 1.2000e+00 -3.0100e-01 - 1.3200e-01 1.2000e+00 -3.0100e-01 - 1.5800e-01 1.1880e+00 -3.0100e-01 - 1.6300e-01 1.1620e+00 -3.0100e-01 - 9.0000e-02 7.9400e-01 -3.0100e-01 - 7.9000e-02 7.7500e-01 -3.0100e-01 - 5.8000e-02 7.6800e-01 -3.0100e-01 - -6.2000e-02 7.6800e-01 -3.0100e-01 - -8.3000e-02 7.7500e-01 -3.0100e-01 - -9.4000e-02 7.9500e-01 -3.0100e-01 - -1.6700e-01 1.1620e+00 -3.0100e-01 - -1.6000e-01 1.1880e+00 -3.0100e-01 - -1.3500e-01 1.2000e+00 -3.0100e-01 - -5.0000e-02 1.2000e+00 -3.0100e-01 - -2.5370e-02 1.2000e+00 -3.1000e-01 - -1.6000e-02 1.2000e+00 -3.3300e-01 - -1.6000e-02 1.2000e+00 -3.9800e-01 - -7.7650e-01 1.6000e-02 -3.9800e-01 - -7.7650e-01 1.6000e-02 -3.3300e-01 - -7.7650e-01 2.5370e-02 -3.1000e-01 - -7.7650e-01 4.8000e-02 -3.0100e-01 - -7.7650e-01 6.1000e-02 -3.0100e-01 - -7.8350e-01 8.2000e-02 -3.0100e-01 - -8.0250e-01 9.3000e-02 -3.0100e-01 - -1.2015e+00 1.7100e-01 -3.0100e-01 - -1.2275e+00 1.6500e-01 -3.0100e-01 - -1.2395e+00 1.4100e-01 -3.0100e-01 - -1.2395e+00 -1.4100e-01 -3.0100e-01 - -1.2275e+00 -1.6600e-01 -3.0100e-01 - -1.2015e+00 -1.7200e-01 -3.0100e-01 - -8.0250e-01 -9.3000e-02 -3.0100e-01 - -7.8350e-01 -8.2000e-02 -3.0100e-01 - -7.7650e-01 -6.2000e-02 -3.0100e-01 - -7.7650e-01 -4.9000e-02 -3.0100e-01 - -7.7650e-01 -2.5370e-02 -3.1000e-01 - -7.7650e-01 -1.6000e-02 -3.3300e-01 - -7.7650e-01 -1.6000e-02 -3.9800e-01 - 1.6000e-02 -7.7650e-01 -3.9800e-01 - 1.6000e-02 -7.7650e-01 -3.3300e-01 - 2.5370e-02 -7.7650e-01 -3.1000e-01 - 4.8000e-02 -7.7650e-01 -3.0100e-01 - 6.1000e-02 -7.7650e-01 -3.0100e-01 - 8.2000e-02 -7.8350e-01 -3.0100e-01 - 9.3000e-02 -8.0250e-01 -3.0100e-01 - 1.7100e-01 -1.2015e+00 -3.0100e-01 - 1.6500e-01 -1.2275e+00 -3.0100e-01 - 1.4100e-01 -1.2395e+00 -3.0100e-01 - -1.4100e-01 -1.2395e+00 -3.0100e-01 - -1.6600e-01 -1.2275e+00 -3.0100e-01 - -1.7200e-01 -1.2015e+00 -3.0100e-01 - -9.3000e-02 -8.0250e-01 -3.0100e-01 - -8.2000e-02 -7.8350e-01 -3.0100e-01 - -6.2000e-02 -7.7650e-01 -3.0100e-01 - -4.9000e-02 -7.7650e-01 -3.0100e-01 - -2.5370e-02 -7.7650e-01 -3.1000e-01 - -1.6000e-02 -7.7650e-01 -3.3300e-01 - -1.6000e-02 -7.7650e-01 -3.9800e-01 + 4 1 20 1.00 + 1.2000e+00 1.6000e-02 -3.9800e-01 + 1.2000e+00 1.6000e-02 -3.3300e-01 + 1.2000e+00 2.5370e-02 -3.1000e-01 + 1.2000e+00 4.8000e-02 -3.0100e-01 + 1.2000e+00 1.3200e-01 -3.0100e-01 + 1.1880e+00 1.5800e-01 -3.0100e-01 + 1.1620e+00 1.6300e-01 -3.0100e-01 + 7.9400e-01 9.0000e-02 -3.0100e-01 + 7.7500e-01 7.9000e-02 -3.0100e-01 + 7.6800e-01 5.8000e-02 -3.0100e-01 + 7.6800e-01 -6.2000e-02 -3.0100e-01 + 7.7500e-01 -8.3000e-02 -3.0100e-01 + 7.9500e-01 -9.4000e-02 -3.0100e-01 + 1.1620e+00 -1.6700e-01 -3.0100e-01 + 1.1880e+00 -1.6000e-01 -3.0100e-01 + 1.2000e+00 -1.3500e-01 -3.0100e-01 + 1.2000e+00 -5.0000e-02 -3.0100e-01 + 1.2000e+00 -2.5370e-02 -3.1000e-01 + 1.2000e+00 -1.6000e-02 -3.3300e-01 + 1.2000e+00 -1.6000e-02 -3.9800e-01 + 1.6000e-02 1.2000e+00 -3.9800e-01 + 1.6000e-02 1.2000e+00 -3.3300e-01 + 2.5370e-02 1.2000e+00 -3.1000e-01 + 4.8000e-02 1.2000e+00 -3.0100e-01 + 1.3200e-01 1.2000e+00 -3.0100e-01 + 1.5800e-01 1.1880e+00 -3.0100e-01 + 1.6300e-01 1.1620e+00 -3.0100e-01 + 9.0000e-02 7.9400e-01 -3.0100e-01 + 7.9000e-02 7.7500e-01 -3.0100e-01 + 5.8000e-02 7.6800e-01 -3.0100e-01 + -6.2000e-02 7.6800e-01 -3.0100e-01 + -8.3000e-02 7.7500e-01 -3.0100e-01 + -9.4000e-02 7.9500e-01 -3.0100e-01 + -1.6700e-01 1.1620e+00 -3.0100e-01 + -1.6000e-01 1.1880e+00 -3.0100e-01 + -1.3500e-01 1.2000e+00 -3.0100e-01 + -5.0000e-02 1.2000e+00 -3.0100e-01 + -2.5370e-02 1.2000e+00 -3.1000e-01 + -1.6000e-02 1.2000e+00 -3.3300e-01 + -1.6000e-02 1.2000e+00 -3.9800e-01 + -7.7650e-01 1.6000e-02 -3.9800e-01 + -7.7650e-01 1.6000e-02 -3.3300e-01 + -7.7650e-01 2.5370e-02 -3.1000e-01 + -7.7650e-01 4.8000e-02 -3.0100e-01 + -7.7650e-01 6.1000e-02 -3.0100e-01 + -7.8350e-01 8.2000e-02 -3.0100e-01 + -8.0250e-01 9.3000e-02 -3.0100e-01 + -1.2015e+00 1.7100e-01 -3.0100e-01 + -1.2275e+00 1.6500e-01 -3.0100e-01 + -1.2395e+00 1.4100e-01 -3.0100e-01 + -1.2395e+00 -1.4100e-01 -3.0100e-01 + -1.2275e+00 -1.6600e-01 -3.0100e-01 + -1.2015e+00 -1.7200e-01 -3.0100e-01 + -8.0250e-01 -9.3000e-02 -3.0100e-01 + -7.8350e-01 -8.2000e-02 -3.0100e-01 + -7.7650e-01 -6.2000e-02 -3.0100e-01 + -7.7650e-01 -4.9000e-02 -3.0100e-01 + -7.7650e-01 -2.5370e-02 -3.1000e-01 + -7.7650e-01 -1.6000e-02 -3.3300e-01 + -7.7650e-01 -1.6000e-02 -3.9800e-01 + 1.6000e-02 -7.7650e-01 -3.9800e-01 + 1.6000e-02 -7.7650e-01 -3.3300e-01 + 2.5370e-02 -7.7650e-01 -3.1000e-01 + 4.8000e-02 -7.7650e-01 -3.0100e-01 + 6.1000e-02 -7.7650e-01 -3.0100e-01 + 8.2000e-02 -7.8350e-01 -3.0100e-01 + 9.3000e-02 -8.0250e-01 -3.0100e-01 + 1.7100e-01 -1.2015e+00 -3.0100e-01 + 1.6500e-01 -1.2275e+00 -3.0100e-01 + 1.4100e-01 -1.2395e+00 -3.0100e-01 + -1.4100e-01 -1.2395e+00 -3.0100e-01 + -1.6600e-01 -1.2275e+00 -3.0100e-01 + -1.7200e-01 -1.2015e+00 -3.0100e-01 + -9.3000e-02 -8.0250e-01 -3.0100e-01 + -8.2000e-02 -7.8350e-01 -3.0100e-01 + -6.2000e-02 -7.7650e-01 -3.0100e-01 + -4.9000e-02 -7.7650e-01 -3.0100e-01 + -2.5370e-02 -7.7650e-01 -3.1000e-01 + -1.6000e-02 -7.7650e-01 -3.3300e-01 + -1.6000e-02 -7.7650e-01 -3.9800e-01 diff --git a/src/ForcingTerms/coil_geometries/jtext_m.dat b/src/ForcingTerms/coil_geometries/jtext_m.dat index f211a2d1e..9defc821f 100644 --- a/src/ForcingTerms/coil_geometries/jtext_m.dat +++ b/src/ForcingTerms/coil_geometries/jtext_m.dat @@ -1,81 +1,81 @@ - 4 1 20 1.00 - 1.3300e+00 1.6000e-02 3.5600e-01 - 1.2830e+00 1.6000e-02 2.6500e-01 - 1.3065e+00 2.5370e-02 2.4300e-01 - 1.3300e+00 4.8000e-02 2.1100e-01 - 1.3300e+00 1.3200e-01 2.1100e-01 - 1.3300e+00 1.5800e-01 2.0200e-01 - 1.3300e+00 1.6300e-01 1.7900e-01 - 1.3300e+00 9.0000e-02 -2.0600e-01 - 1.3300e+00 7.9000e-02 -2.2900e-01 - 1.3300e+00 5.8000e-02 -2.3800e-01 - 1.3300e+00 -6.2000e-02 -2.3800e-01 - 1.3300e+00 -8.3000e-02 -2.2900e-01 - 1.3300e+00 -9.4000e-02 -2.0600e-01 - 1.3300e+00 -1.6700e-01 1.7900e-01 - 1.3300e+00 -1.6000e-01 2.0200e-01 - 1.3300e+00 -1.3500e-01 2.1100e-01 - 1.3300e+00 -5.0000e-02 2.1100e-01 - 1.3065e+00 -2.5370e-02 2.4300e-01 - 1.2830e+00 -1.6000e-02 2.6500e-01 - 1.3300e+00 -1.6000e-02 3.5600e-01 - -8.7000e-02 1.2000e+00 -3.5600e-01 - -8.7000e-02 1.2000e+00 -2.6500e-01 - -7.1000e-02 1.2000e+00 -2.4300e-01 - -5.5000e-02 1.2000e+00 -2.1100e-01 - 1.6900e-01 1.2000e+00 -2.1100e-01 - 1.9100e-01 1.1880e+00 -2.0200e-01 - 2.0100e-01 1.1620e+00 -1.7900e-01 - 2.0100e-01 7.9400e-01 2.0600e-01 - 1.9100e-01 7.7500e-01 2.2900e-01 - 1.6900e-01 7.6800e-01 2.3800e-01 - -1.6800e-01 7.6800e-01 2.3800e-01 - -1.9100e-01 7.7500e-01 2.2900e-01 - -2.0000e-01 7.9500e-01 2.0600e-01 - -2.0000e-01 1.1620e+00 -1.7900e-01 - -1.9100e-01 1.1880e+00 -2.0200e-01 - -1.6800e-01 1.2000e+00 -2.1100e-01 - -1.5100e-01 1.2000e+00 -2.1100e-01 - -1.3500e-01 1.2000e+00 -2.4300e-01 - -1.1900e-01 1.2000e+00 -2.6500e-01 - -1.1900e-01 1.2000e+00 -3.5600e-01 - -1.3300e+00 1.6000e-02 3.5600e-01 - -1.2830e+00 1.6000e-02 2.6500e-01 - -1.3065e+00 2.5370e-02 2.4300e-01 - -1.3300e+00 4.8000e-02 2.1100e-01 - -1.3300e+00 6.1000e-02 2.1100e-01 - -1.3300e+00 8.2000e-02 2.0200e-01 - -1.3300e+00 9.3000e-02 1.7900e-01 - -1.3300e+00 1.7100e-01 -2.0600e-01 - -1.3300e+00 1.6500e-01 -2.2900e-01 - -1.3300e+00 1.4100e-01 -2.3800e-01 - -1.3300e+00 -1.4100e-01 -2.3800e-01 - -1.3300e+00 -1.6600e-01 -2.2900e-01 - -1.3300e+00 -1.7200e-01 -2.0600e-01 - -1.3300e+00 -9.3000e-02 1.7900e-01 - -1.3300e+00 -8.2000e-02 2.0200e-01 - -1.3300e+00 -6.2000e-02 2.1100e-01 - -1.3300e+00 -4.9000e-02 2.1100e-01 - -1.3065e+00 -2.5370e-02 2.4300e-01 - -1.2830e+00 -1.6000e-02 2.6500e-01 - -1.3300e+00 -1.6000e-02 3.5600e-01 - 8.7000e-02 -7.7650e-01 -3.5600e-01 - 8.7000e-02 -7.7650e-01 -2.6500e-01 - 7.1000e-02 -7.7650e-01 -2.4300e-01 - 5.5000e-02 -7.7650e-01 -2.1100e-01 - 5.5000e-02 -7.7650e-01 -2.1100e-01 - 3.2600e-02 -7.8350e-01 -2.0200e-01 - 2.2600e-02 -8.0250e-01 -1.7900e-01 - 2.2600e-02 -1.2015e+00 2.0600e-01 - 3.2600e-02 -1.2275e+00 2.2900e-01 - 5.4600e-02 -1.2395e+00 2.3800e-01 - 1.6800e-01 -1.2395e+00 2.3800e-01 - 1.9100e-01 -1.2275e+00 2.2900e-01 - 2.0000e-01 -1.2015e+00 2.0600e-01 - 2.0000e-01 -8.0250e-01 -1.7900e-01 - 1.9100e-01 -7.8350e-01 -2.0200e-01 - 1.6800e-01 -7.7650e-01 -2.1100e-01 - 1.5100e-01 -7.7650e-01 -2.1100e-01 - 1.3500e-01 -7.7650e-01 -2.4300e-01 - 1.1900e-01 -7.7650e-01 -2.6500e-01 - 1.1900e-01 -7.7650e-01 -3.5600e-01 + 4 1 20 1.00 + 1.3300e+00 1.6000e-02 3.5600e-01 + 1.2830e+00 1.6000e-02 2.6500e-01 + 1.3065e+00 2.5370e-02 2.4300e-01 + 1.3300e+00 4.8000e-02 2.1100e-01 + 1.3300e+00 1.3200e-01 2.1100e-01 + 1.3300e+00 1.5800e-01 2.0200e-01 + 1.3300e+00 1.6300e-01 1.7900e-01 + 1.3300e+00 9.0000e-02 -2.0600e-01 + 1.3300e+00 7.9000e-02 -2.2900e-01 + 1.3300e+00 5.8000e-02 -2.3800e-01 + 1.3300e+00 -6.2000e-02 -2.3800e-01 + 1.3300e+00 -8.3000e-02 -2.2900e-01 + 1.3300e+00 -9.4000e-02 -2.0600e-01 + 1.3300e+00 -1.6700e-01 1.7900e-01 + 1.3300e+00 -1.6000e-01 2.0200e-01 + 1.3300e+00 -1.3500e-01 2.1100e-01 + 1.3300e+00 -5.0000e-02 2.1100e-01 + 1.3065e+00 -2.5370e-02 2.4300e-01 + 1.2830e+00 -1.6000e-02 2.6500e-01 + 1.3300e+00 -1.6000e-02 3.5600e-01 + -8.7000e-02 1.2000e+00 -3.5600e-01 + -8.7000e-02 1.2000e+00 -2.6500e-01 + -7.1000e-02 1.2000e+00 -2.4300e-01 + -5.5000e-02 1.2000e+00 -2.1100e-01 + 1.6900e-01 1.2000e+00 -2.1100e-01 + 1.9100e-01 1.1880e+00 -2.0200e-01 + 2.0100e-01 1.1620e+00 -1.7900e-01 + 2.0100e-01 7.9400e-01 2.0600e-01 + 1.9100e-01 7.7500e-01 2.2900e-01 + 1.6900e-01 7.6800e-01 2.3800e-01 + -1.6800e-01 7.6800e-01 2.3800e-01 + -1.9100e-01 7.7500e-01 2.2900e-01 + -2.0000e-01 7.9500e-01 2.0600e-01 + -2.0000e-01 1.1620e+00 -1.7900e-01 + -1.9100e-01 1.1880e+00 -2.0200e-01 + -1.6800e-01 1.2000e+00 -2.1100e-01 + -1.5100e-01 1.2000e+00 -2.1100e-01 + -1.3500e-01 1.2000e+00 -2.4300e-01 + -1.1900e-01 1.2000e+00 -2.6500e-01 + -1.1900e-01 1.2000e+00 -3.5600e-01 + -1.3300e+00 1.6000e-02 3.5600e-01 + -1.2830e+00 1.6000e-02 2.6500e-01 + -1.3065e+00 2.5370e-02 2.4300e-01 + -1.3300e+00 4.8000e-02 2.1100e-01 + -1.3300e+00 6.1000e-02 2.1100e-01 + -1.3300e+00 8.2000e-02 2.0200e-01 + -1.3300e+00 9.3000e-02 1.7900e-01 + -1.3300e+00 1.7100e-01 -2.0600e-01 + -1.3300e+00 1.6500e-01 -2.2900e-01 + -1.3300e+00 1.4100e-01 -2.3800e-01 + -1.3300e+00 -1.4100e-01 -2.3800e-01 + -1.3300e+00 -1.6600e-01 -2.2900e-01 + -1.3300e+00 -1.7200e-01 -2.0600e-01 + -1.3300e+00 -9.3000e-02 1.7900e-01 + -1.3300e+00 -8.2000e-02 2.0200e-01 + -1.3300e+00 -6.2000e-02 2.1100e-01 + -1.3300e+00 -4.9000e-02 2.1100e-01 + -1.3065e+00 -2.5370e-02 2.4300e-01 + -1.2830e+00 -1.6000e-02 2.6500e-01 + -1.3300e+00 -1.6000e-02 3.5600e-01 + 8.7000e-02 -7.7650e-01 -3.5600e-01 + 8.7000e-02 -7.7650e-01 -2.6500e-01 + 7.1000e-02 -7.7650e-01 -2.4300e-01 + 5.5000e-02 -7.7650e-01 -2.1100e-01 + 5.5000e-02 -7.7650e-01 -2.1100e-01 + 3.2600e-02 -7.8350e-01 -2.0200e-01 + 2.2600e-02 -8.0250e-01 -1.7900e-01 + 2.2600e-02 -1.2015e+00 2.0600e-01 + 3.2600e-02 -1.2275e+00 2.2900e-01 + 5.4600e-02 -1.2395e+00 2.3800e-01 + 1.6800e-01 -1.2395e+00 2.3800e-01 + 1.9100e-01 -1.2275e+00 2.2900e-01 + 2.0000e-01 -1.2015e+00 2.0600e-01 + 2.0000e-01 -8.0250e-01 -1.7900e-01 + 1.9100e-01 -7.8350e-01 -2.0200e-01 + 1.6800e-01 -7.7650e-01 -2.1100e-01 + 1.5100e-01 -7.7650e-01 -2.1100e-01 + 1.3500e-01 -7.7650e-01 -2.4300e-01 + 1.1900e-01 -7.7650e-01 -2.6500e-01 + 1.1900e-01 -7.7650e-01 -3.5600e-01 diff --git a/src/ForcingTerms/coil_geometries/jtext_u.dat b/src/ForcingTerms/coil_geometries/jtext_u.dat index 45404b00f..b70ef435f 100644 --- a/src/ForcingTerms/coil_geometries/jtext_u.dat +++ b/src/ForcingTerms/coil_geometries/jtext_u.dat @@ -1,81 +1,81 @@ - 4 1 20 1.00 - 1.2000e+00 1.6000e-02 3.9800e-01 - 1.2000e+00 1.6000e-02 3.3300e-01 - 1.2000e+00 2.5370e-02 3.1000e-01 - 1.2000e+00 4.8000e-02 3.0100e-01 - 1.2000e+00 1.3200e-01 3.0100e-01 - 1.1880e+00 1.5800e-01 3.0100e-01 - 1.1620e+00 1.6300e-01 3.0100e-01 - 7.9400e-01 9.0000e-02 3.0100e-01 - 7.7500e-01 7.9000e-02 3.0100e-01 - 7.6800e-01 5.8000e-02 3.0100e-01 - 7.6800e-01 -6.2000e-02 3.0100e-01 - 7.7500e-01 -8.3000e-02 3.0100e-01 - 7.9500e-01 -9.4000e-02 3.0100e-01 - 1.1620e+00 -1.6700e-01 3.0100e-01 - 1.1880e+00 -1.6000e-01 3.0100e-01 - 1.2000e+00 -1.3500e-01 3.0100e-01 - 1.2000e+00 -5.0000e-02 3.0100e-01 - 1.2000e+00 -2.5370e-02 3.1000e-01 - 1.2000e+00 -1.6000e-02 3.3300e-01 - 1.2000e+00 -1.6000e-02 3.9800e-01 - 1.6000e-02 1.2000e+00 3.9800e-01 - 1.6000e-02 1.2000e+00 3.3300e-01 - 2.5370e-02 1.2000e+00 3.1000e-01 - 4.8000e-02 1.2000e+00 3.0100e-01 - 1.3200e-01 1.2000e+00 3.0100e-01 - 1.5800e-01 1.1880e+00 3.0100e-01 - 1.6300e-01 1.1620e+00 3.0100e-01 - 9.0000e-02 7.9400e-01 3.0100e-01 - 7.9000e-02 7.7500e-01 3.0100e-01 - 5.8000e-02 7.6800e-01 3.0100e-01 - -6.2000e-02 7.6800e-01 3.0100e-01 - -8.3000e-02 7.7500e-01 3.0100e-01 - -9.4000e-02 7.9500e-01 3.0100e-01 - -1.6700e-01 1.1620e+00 3.0100e-01 - -1.6000e-01 1.1880e+00 3.0100e-01 - -1.3500e-01 1.2000e+00 3.0100e-01 - -5.0000e-02 1.2000e+00 3.0100e-01 - -2.5370e-02 1.2000e+00 3.1000e-01 - -1.6000e-02 1.2000e+00 3.3300e-01 - -1.6000e-02 1.2000e+00 3.9800e-01 - -7.7650e-01 1.6000e-02 3.9800e-01 - -7.7650e-01 1.6000e-02 3.3300e-01 - -7.7650e-01 2.5370e-02 3.1000e-01 - -7.7650e-01 4.8000e-02 3.0100e-01 - -7.7650e-01 6.1000e-02 3.0100e-01 - -7.8350e-01 8.2000e-02 3.0100e-01 - -8.0250e-01 9.3000e-02 3.0100e-01 - -1.2015e+00 1.7100e-01 3.0100e-01 - -1.2275e+00 1.6500e-01 3.0100e-01 - -1.2395e+00 1.4100e-01 3.0100e-01 - -1.2395e+00 -1.4100e-01 3.0100e-01 - -1.2275e+00 -1.6600e-01 3.0100e-01 - -1.2015e+00 -1.7200e-01 3.0100e-01 - -8.0250e-01 -9.3000e-02 3.0100e-01 - -7.8350e-01 -8.2000e-02 3.0100e-01 - -7.7650e-01 -6.2000e-02 3.0100e-01 - -7.7650e-01 -4.9000e-02 3.0100e-01 - -7.7650e-01 -2.5370e-02 3.1000e-01 - -7.7650e-01 -1.6000e-02 3.3300e-01 - -7.7650e-01 -1.6000e-02 3.9800e-01 - 1.6000e-02 -7.7650e-01 3.9800e-01 - 1.6000e-02 -7.7650e-01 3.3300e-01 - 2.5370e-02 -7.7650e-01 3.1000e-01 - 4.8000e-02 -7.7650e-01 3.0100e-01 - 6.1000e-02 -7.7650e-01 3.0100e-01 - 8.2000e-02 -7.8350e-01 3.0100e-01 - 9.3000e-02 -8.0250e-01 3.0100e-01 - 1.7100e-01 -1.2015e+00 3.0100e-01 - 1.6500e-01 -1.2275e+00 3.0100e-01 - 1.4100e-01 -1.2395e+00 3.0100e-01 - -1.4100e-01 -1.2395e+00 3.0100e-01 - -1.6600e-01 -1.2275e+00 3.0100e-01 - -1.7200e-01 -1.2015e+00 3.0100e-01 - -9.3000e-02 -8.0250e-01 3.0100e-01 - -8.2000e-02 -7.8350e-01 3.0100e-01 - -6.2000e-02 -7.7650e-01 3.0100e-01 - -4.9000e-02 -7.7650e-01 3.0100e-01 - -2.5370e-02 -7.7650e-01 3.1000e-01 - -1.6000e-02 -7.7650e-01 3.3300e-01 - -1.6000e-02 -7.7650e-01 3.9800e-01 + 4 1 20 1.00 + 1.2000e+00 1.6000e-02 3.9800e-01 + 1.2000e+00 1.6000e-02 3.3300e-01 + 1.2000e+00 2.5370e-02 3.1000e-01 + 1.2000e+00 4.8000e-02 3.0100e-01 + 1.2000e+00 1.3200e-01 3.0100e-01 + 1.1880e+00 1.5800e-01 3.0100e-01 + 1.1620e+00 1.6300e-01 3.0100e-01 + 7.9400e-01 9.0000e-02 3.0100e-01 + 7.7500e-01 7.9000e-02 3.0100e-01 + 7.6800e-01 5.8000e-02 3.0100e-01 + 7.6800e-01 -6.2000e-02 3.0100e-01 + 7.7500e-01 -8.3000e-02 3.0100e-01 + 7.9500e-01 -9.4000e-02 3.0100e-01 + 1.1620e+00 -1.6700e-01 3.0100e-01 + 1.1880e+00 -1.6000e-01 3.0100e-01 + 1.2000e+00 -1.3500e-01 3.0100e-01 + 1.2000e+00 -5.0000e-02 3.0100e-01 + 1.2000e+00 -2.5370e-02 3.1000e-01 + 1.2000e+00 -1.6000e-02 3.3300e-01 + 1.2000e+00 -1.6000e-02 3.9800e-01 + 1.6000e-02 1.2000e+00 3.9800e-01 + 1.6000e-02 1.2000e+00 3.3300e-01 + 2.5370e-02 1.2000e+00 3.1000e-01 + 4.8000e-02 1.2000e+00 3.0100e-01 + 1.3200e-01 1.2000e+00 3.0100e-01 + 1.5800e-01 1.1880e+00 3.0100e-01 + 1.6300e-01 1.1620e+00 3.0100e-01 + 9.0000e-02 7.9400e-01 3.0100e-01 + 7.9000e-02 7.7500e-01 3.0100e-01 + 5.8000e-02 7.6800e-01 3.0100e-01 + -6.2000e-02 7.6800e-01 3.0100e-01 + -8.3000e-02 7.7500e-01 3.0100e-01 + -9.4000e-02 7.9500e-01 3.0100e-01 + -1.6700e-01 1.1620e+00 3.0100e-01 + -1.6000e-01 1.1880e+00 3.0100e-01 + -1.3500e-01 1.2000e+00 3.0100e-01 + -5.0000e-02 1.2000e+00 3.0100e-01 + -2.5370e-02 1.2000e+00 3.1000e-01 + -1.6000e-02 1.2000e+00 3.3300e-01 + -1.6000e-02 1.2000e+00 3.9800e-01 + -7.7650e-01 1.6000e-02 3.9800e-01 + -7.7650e-01 1.6000e-02 3.3300e-01 + -7.7650e-01 2.5370e-02 3.1000e-01 + -7.7650e-01 4.8000e-02 3.0100e-01 + -7.7650e-01 6.1000e-02 3.0100e-01 + -7.8350e-01 8.2000e-02 3.0100e-01 + -8.0250e-01 9.3000e-02 3.0100e-01 + -1.2015e+00 1.7100e-01 3.0100e-01 + -1.2275e+00 1.6500e-01 3.0100e-01 + -1.2395e+00 1.4100e-01 3.0100e-01 + -1.2395e+00 -1.4100e-01 3.0100e-01 + -1.2275e+00 -1.6600e-01 3.0100e-01 + -1.2015e+00 -1.7200e-01 3.0100e-01 + -8.0250e-01 -9.3000e-02 3.0100e-01 + -7.8350e-01 -8.2000e-02 3.0100e-01 + -7.7650e-01 -6.2000e-02 3.0100e-01 + -7.7650e-01 -4.9000e-02 3.0100e-01 + -7.7650e-01 -2.5370e-02 3.1000e-01 + -7.7650e-01 -1.6000e-02 3.3300e-01 + -7.7650e-01 -1.6000e-02 3.9800e-01 + 1.6000e-02 -7.7650e-01 3.9800e-01 + 1.6000e-02 -7.7650e-01 3.3300e-01 + 2.5370e-02 -7.7650e-01 3.1000e-01 + 4.8000e-02 -7.7650e-01 3.0100e-01 + 6.1000e-02 -7.7650e-01 3.0100e-01 + 8.2000e-02 -7.8350e-01 3.0100e-01 + 9.3000e-02 -8.0250e-01 3.0100e-01 + 1.7100e-01 -1.2015e+00 3.0100e-01 + 1.6500e-01 -1.2275e+00 3.0100e-01 + 1.4100e-01 -1.2395e+00 3.0100e-01 + -1.4100e-01 -1.2395e+00 3.0100e-01 + -1.6600e-01 -1.2275e+00 3.0100e-01 + -1.7200e-01 -1.2015e+00 3.0100e-01 + -9.3000e-02 -8.0250e-01 3.0100e-01 + -8.2000e-02 -7.8350e-01 3.0100e-01 + -6.2000e-02 -7.7650e-01 3.0100e-01 + -4.9000e-02 -7.7650e-01 3.0100e-01 + -2.5370e-02 -7.7650e-01 3.1000e-01 + -1.6000e-02 -7.7650e-01 3.3300e-01 + -1.6000e-02 -7.7650e-01 3.9800e-01 diff --git a/src/ForcingTerms/coil_geometries/mastu_efcc.dat b/src/ForcingTerms/coil_geometries/mastu_efcc.dat index e94da889f..5259e11cc 100644 --- a/src/ForcingTerms/coil_geometries/mastu_efcc.dat +++ b/src/ForcingTerms/coil_geometries/mastu_efcc.dat @@ -1,169 +1,169 @@ - 4 1 42 1.00 - 2.9319e+00 0.0000e+00 1.6550e+00 - 2.9213e+00 2.4953e-01 1.6550e+00 - 2.8894e+00 4.9726e-01 1.6550e+00 - 2.8366e+00 7.4137e-01 1.6550e+00 - 2.7632e+00 9.8011e-01 1.6550e+00 - 2.6698e+00 1.2117e+00 1.6550e+00 - 2.5570e+00 1.4346e+00 1.6550e+00 - 2.4256e+00 1.6470e+00 1.6550e+00 - 2.2766e+00 1.8474e+00 1.6550e+00 - 2.1111e+00 2.0345e+00 1.6550e+00 - 1.9303e+00 2.2068e+00 1.6550e+00 - 1.7355e+00 2.3631e+00 1.6550e+00 - 1.5281e+00 2.5022e+00 1.6550e+00 - 1.3096e+00 2.6232e+00 1.6550e+00 - 1.0815e+00 2.7251e+00 1.6550e+00 - 8.4568e-01 2.8073e+00 1.6550e+00 - 6.0369e-01 2.8691e+00 1.6550e+00 - 3.5731e-01 2.9100e+00 1.6550e+00 - 3.5731e-01 2.9100e+00 1.6550e+00 - 3.5729e-01 2.9099e+00 9.1800e-01 - 3.5727e-01 2.9097e+00 1.8100e-01 - 3.5725e-01 2.9096e+00 -5.5600e-01 - 3.5723e-01 2.9094e+00 -1.2930e+00 - 3.5721e-01 2.9093e+00 -2.0300e+00 - 6.7851e-01 2.8515e+00 -2.0300e+00 - 9.9139e-01 2.7583e+00 -2.0300e+00 - 1.2920e+00 2.6310e+00 -2.0300e+00 - 1.5765e+00 2.4710e+00 -2.0300e+00 - 1.8415e+00 2.2804e+00 -2.0300e+00 - 2.0837e+00 2.0614e+00 -2.0300e+00 - 2.3000e+00 1.8169e+00 -2.0300e+00 - 2.4878e+00 1.5499e+00 -2.0300e+00 - 2.6447e+00 1.2636e+00 -2.0300e+00 - 2.7688e+00 9.6171e-01 -2.0300e+00 - 2.8586e+00 6.4785e-01 -2.0300e+00 - 2.9129e+00 3.2594e-01 -2.0300e+00 - 2.9311e+00 0.0000e+00 -2.0300e+00 - 2.9313e+00 0.0000e+00 -1.2930e+00 - 2.9314e+00 0.0000e+00 -5.5600e-01 - 2.9316e+00 0.0000e+00 1.8100e-01 - 2.9317e+00 0.0000e+00 9.1800e-01 - 2.9319e+00 0.0000e+00 1.6550e+00 - 1.7953e-16 2.9319e+00 1.6550e+00 - -2.4953e-01 2.9213e+00 1.6550e+00 - -4.9726e-01 2.8894e+00 1.6550e+00 - -7.4137e-01 2.8366e+00 1.6550e+00 - -9.8011e-01 2.7632e+00 1.6550e+00 - -1.2117e+00 2.6698e+00 1.6550e+00 - -1.4346e+00 2.5570e+00 1.6550e+00 - -1.6470e+00 2.4256e+00 1.6550e+00 - -1.8474e+00 2.2766e+00 1.6550e+00 - -2.0345e+00 2.1111e+00 1.6550e+00 - -2.2068e+00 1.9303e+00 1.6550e+00 - -2.3631e+00 1.7355e+00 1.6550e+00 - -2.5022e+00 1.5281e+00 1.6550e+00 - -2.6232e+00 1.3096e+00 1.6550e+00 - -2.7251e+00 1.0815e+00 1.6550e+00 - -2.8073e+00 8.4568e-01 1.6550e+00 - -2.8691e+00 6.0369e-01 1.6550e+00 - -2.9100e+00 3.5731e-01 1.6550e+00 - -2.9100e+00 3.5731e-01 1.6550e+00 - -2.9099e+00 3.5729e-01 9.1800e-01 - -2.9097e+00 3.5727e-01 1.8100e-01 - -2.9096e+00 3.5725e-01 -5.5600e-01 - -2.9094e+00 3.5723e-01 -1.2930e+00 - -2.9093e+00 3.5721e-01 -2.0300e+00 - -2.8515e+00 6.7851e-01 -2.0300e+00 - -2.7583e+00 9.9139e-01 -2.0300e+00 - -2.6310e+00 1.2920e+00 -2.0300e+00 - -2.4710e+00 1.5765e+00 -2.0300e+00 - -2.2804e+00 1.8415e+00 -2.0300e+00 - -2.0614e+00 2.0837e+00 -2.0300e+00 - -1.8169e+00 2.3000e+00 -2.0300e+00 - -1.5499e+00 2.4878e+00 -2.0300e+00 - -1.2636e+00 2.6447e+00 -2.0300e+00 - -9.6171e-01 2.7688e+00 -2.0300e+00 - -6.4785e-01 2.8586e+00 -2.0300e+00 - -3.2594e-01 2.9129e+00 -2.0300e+00 - 1.7948e-16 2.9311e+00 -2.0300e+00 - 1.7949e-16 2.9313e+00 -1.2930e+00 - 1.7950e-16 2.9314e+00 -5.5600e-01 - 1.7951e-16 2.9316e+00 1.8100e-01 - 1.7952e-16 2.9317e+00 9.1800e-01 - 1.7953e-16 2.9319e+00 1.6550e+00 - -2.9319e+00 3.5905e-16 1.6550e+00 - -2.9213e+00 -2.4953e-01 1.6550e+00 - -2.8894e+00 -4.9726e-01 1.6550e+00 - -2.8366e+00 -7.4137e-01 1.6550e+00 - -2.7632e+00 -9.8011e-01 1.6550e+00 - -2.6698e+00 -1.2117e+00 1.6550e+00 - -2.5570e+00 -1.4346e+00 1.6550e+00 - -2.4256e+00 -1.6470e+00 1.6550e+00 - -2.2766e+00 -1.8474e+00 1.6550e+00 - -2.1111e+00 -2.0345e+00 1.6550e+00 - -1.9303e+00 -2.2068e+00 1.6550e+00 - -1.7355e+00 -2.3631e+00 1.6550e+00 - -1.5281e+00 -2.5022e+00 1.6550e+00 - -1.3096e+00 -2.6232e+00 1.6550e+00 - -1.0815e+00 -2.7251e+00 1.6550e+00 - -8.4568e-01 -2.8073e+00 1.6550e+00 - -6.0369e-01 -2.8691e+00 1.6550e+00 - -3.5731e-01 -2.9100e+00 1.6550e+00 - -3.5731e-01 -2.9100e+00 1.6550e+00 - -3.5729e-01 -2.9099e+00 9.1800e-01 - -3.5727e-01 -2.9097e+00 1.8100e-01 - -3.5725e-01 -2.9096e+00 -5.5600e-01 - -3.5723e-01 -2.9094e+00 -1.2930e+00 - -3.5721e-01 -2.9093e+00 -2.0300e+00 - -6.7851e-01 -2.8515e+00 -2.0300e+00 - -9.9139e-01 -2.7583e+00 -2.0300e+00 - -1.2920e+00 -2.6310e+00 -2.0300e+00 - -1.5765e+00 -2.4710e+00 -2.0300e+00 - -1.8415e+00 -2.2804e+00 -2.0300e+00 - -2.0837e+00 -2.0614e+00 -2.0300e+00 - -2.3000e+00 -1.8169e+00 -2.0300e+00 - -2.4878e+00 -1.5499e+00 -2.0300e+00 - -2.6447e+00 -1.2636e+00 -2.0300e+00 - -2.7688e+00 -9.6171e-01 -2.0300e+00 - -2.8586e+00 -6.4785e-01 -2.0300e+00 - -2.9129e+00 -3.2594e-01 -2.0300e+00 - -2.9311e+00 3.5896e-16 -2.0300e+00 - -2.9313e+00 3.5898e-16 -1.2930e+00 - -2.9314e+00 3.5900e-16 -5.5600e-01 - -2.9316e+00 3.5902e-16 1.8100e-01 - -2.9317e+00 3.5903e-16 9.1800e-01 - -2.9319e+00 3.5905e-16 1.6550e+00 - -5.3858e-16 -2.9319e+00 1.6550e+00 - 2.4953e-01 -2.9213e+00 1.6550e+00 - 4.9726e-01 -2.8894e+00 1.6550e+00 - 7.4137e-01 -2.8366e+00 1.6550e+00 - 9.8011e-01 -2.7632e+00 1.6550e+00 - 1.2117e+00 -2.6698e+00 1.6550e+00 - 1.4346e+00 -2.5570e+00 1.6550e+00 - 1.6470e+00 -2.4256e+00 1.6550e+00 - 1.8474e+00 -2.2766e+00 1.6550e+00 - 2.0345e+00 -2.1111e+00 1.6550e+00 - 2.2068e+00 -1.9303e+00 1.6550e+00 - 2.3631e+00 -1.7355e+00 1.6550e+00 - 2.5022e+00 -1.5281e+00 1.6550e+00 - 2.6232e+00 -1.3096e+00 1.6550e+00 - 2.7251e+00 -1.0815e+00 1.6550e+00 - 2.8073e+00 -8.4568e-01 1.6550e+00 - 2.8691e+00 -6.0369e-01 1.6550e+00 - 2.9100e+00 -3.5731e-01 1.6550e+00 - 2.9100e+00 -3.5731e-01 1.6550e+00 - 2.9099e+00 -3.5729e-01 9.1800e-01 - 2.9097e+00 -3.5727e-01 1.8100e-01 - 2.9096e+00 -3.5725e-01 -5.5600e-01 - 2.9094e+00 -3.5723e-01 -1.2930e+00 - 2.9093e+00 -3.5721e-01 -2.0300e+00 - 2.8515e+00 -6.7851e-01 -2.0300e+00 - 2.7583e+00 -9.9139e-01 -2.0300e+00 - 2.6310e+00 -1.2920e+00 -2.0300e+00 - 2.4710e+00 -1.5765e+00 -2.0300e+00 - 2.2804e+00 -1.8415e+00 -2.0300e+00 - 2.0614e+00 -2.0837e+00 -2.0300e+00 - 1.8169e+00 -2.3000e+00 -2.0300e+00 - 1.5499e+00 -2.4878e+00 -2.0300e+00 - 1.2636e+00 -2.6447e+00 -2.0300e+00 - 9.6171e-01 -2.7688e+00 -2.0300e+00 - 6.4785e-01 -2.8586e+00 -2.0300e+00 - 3.2594e-01 -2.9129e+00 -2.0300e+00 - -5.3843e-16 -2.9311e+00 -2.0300e+00 - -5.3846e-16 -2.9313e+00 -1.2930e+00 - -5.3849e-16 -2.9314e+00 -5.5600e-01 - -5.3852e-16 -2.9316e+00 1.8100e-01 - -5.3855e-16 -2.9317e+00 9.1800e-01 - -5.3858e-16 -2.9319e+00 1.6550e+00 + 4 1 42 1.00 + 2.9319e+00 0.0000e+00 1.6550e+00 + 2.9213e+00 2.4953e-01 1.6550e+00 + 2.8894e+00 4.9726e-01 1.6550e+00 + 2.8366e+00 7.4137e-01 1.6550e+00 + 2.7632e+00 9.8011e-01 1.6550e+00 + 2.6698e+00 1.2117e+00 1.6550e+00 + 2.5570e+00 1.4346e+00 1.6550e+00 + 2.4256e+00 1.6470e+00 1.6550e+00 + 2.2766e+00 1.8474e+00 1.6550e+00 + 2.1111e+00 2.0345e+00 1.6550e+00 + 1.9303e+00 2.2068e+00 1.6550e+00 + 1.7355e+00 2.3631e+00 1.6550e+00 + 1.5281e+00 2.5022e+00 1.6550e+00 + 1.3096e+00 2.6232e+00 1.6550e+00 + 1.0815e+00 2.7251e+00 1.6550e+00 + 8.4568e-01 2.8073e+00 1.6550e+00 + 6.0369e-01 2.8691e+00 1.6550e+00 + 3.5731e-01 2.9100e+00 1.6550e+00 + 3.5731e-01 2.9100e+00 1.6550e+00 + 3.5729e-01 2.9099e+00 9.1800e-01 + 3.5727e-01 2.9097e+00 1.8100e-01 + 3.5725e-01 2.9096e+00 -5.5600e-01 + 3.5723e-01 2.9094e+00 -1.2930e+00 + 3.5721e-01 2.9093e+00 -2.0300e+00 + 6.7851e-01 2.8515e+00 -2.0300e+00 + 9.9139e-01 2.7583e+00 -2.0300e+00 + 1.2920e+00 2.6310e+00 -2.0300e+00 + 1.5765e+00 2.4710e+00 -2.0300e+00 + 1.8415e+00 2.2804e+00 -2.0300e+00 + 2.0837e+00 2.0614e+00 -2.0300e+00 + 2.3000e+00 1.8169e+00 -2.0300e+00 + 2.4878e+00 1.5499e+00 -2.0300e+00 + 2.6447e+00 1.2636e+00 -2.0300e+00 + 2.7688e+00 9.6171e-01 -2.0300e+00 + 2.8586e+00 6.4785e-01 -2.0300e+00 + 2.9129e+00 3.2594e-01 -2.0300e+00 + 2.9311e+00 0.0000e+00 -2.0300e+00 + 2.9313e+00 0.0000e+00 -1.2930e+00 + 2.9314e+00 0.0000e+00 -5.5600e-01 + 2.9316e+00 0.0000e+00 1.8100e-01 + 2.9317e+00 0.0000e+00 9.1800e-01 + 2.9319e+00 0.0000e+00 1.6550e+00 + 1.7953e-16 2.9319e+00 1.6550e+00 + -2.4953e-01 2.9213e+00 1.6550e+00 + -4.9726e-01 2.8894e+00 1.6550e+00 + -7.4137e-01 2.8366e+00 1.6550e+00 + -9.8011e-01 2.7632e+00 1.6550e+00 + -1.2117e+00 2.6698e+00 1.6550e+00 + -1.4346e+00 2.5570e+00 1.6550e+00 + -1.6470e+00 2.4256e+00 1.6550e+00 + -1.8474e+00 2.2766e+00 1.6550e+00 + -2.0345e+00 2.1111e+00 1.6550e+00 + -2.2068e+00 1.9303e+00 1.6550e+00 + -2.3631e+00 1.7355e+00 1.6550e+00 + -2.5022e+00 1.5281e+00 1.6550e+00 + -2.6232e+00 1.3096e+00 1.6550e+00 + -2.7251e+00 1.0815e+00 1.6550e+00 + -2.8073e+00 8.4568e-01 1.6550e+00 + -2.8691e+00 6.0369e-01 1.6550e+00 + -2.9100e+00 3.5731e-01 1.6550e+00 + -2.9100e+00 3.5731e-01 1.6550e+00 + -2.9099e+00 3.5729e-01 9.1800e-01 + -2.9097e+00 3.5727e-01 1.8100e-01 + -2.9096e+00 3.5725e-01 -5.5600e-01 + -2.9094e+00 3.5723e-01 -1.2930e+00 + -2.9093e+00 3.5721e-01 -2.0300e+00 + -2.8515e+00 6.7851e-01 -2.0300e+00 + -2.7583e+00 9.9139e-01 -2.0300e+00 + -2.6310e+00 1.2920e+00 -2.0300e+00 + -2.4710e+00 1.5765e+00 -2.0300e+00 + -2.2804e+00 1.8415e+00 -2.0300e+00 + -2.0614e+00 2.0837e+00 -2.0300e+00 + -1.8169e+00 2.3000e+00 -2.0300e+00 + -1.5499e+00 2.4878e+00 -2.0300e+00 + -1.2636e+00 2.6447e+00 -2.0300e+00 + -9.6171e-01 2.7688e+00 -2.0300e+00 + -6.4785e-01 2.8586e+00 -2.0300e+00 + -3.2594e-01 2.9129e+00 -2.0300e+00 + 1.7948e-16 2.9311e+00 -2.0300e+00 + 1.7949e-16 2.9313e+00 -1.2930e+00 + 1.7950e-16 2.9314e+00 -5.5600e-01 + 1.7951e-16 2.9316e+00 1.8100e-01 + 1.7952e-16 2.9317e+00 9.1800e-01 + 1.7953e-16 2.9319e+00 1.6550e+00 + -2.9319e+00 3.5905e-16 1.6550e+00 + -2.9213e+00 -2.4953e-01 1.6550e+00 + -2.8894e+00 -4.9726e-01 1.6550e+00 + -2.8366e+00 -7.4137e-01 1.6550e+00 + -2.7632e+00 -9.8011e-01 1.6550e+00 + -2.6698e+00 -1.2117e+00 1.6550e+00 + -2.5570e+00 -1.4346e+00 1.6550e+00 + -2.4256e+00 -1.6470e+00 1.6550e+00 + -2.2766e+00 -1.8474e+00 1.6550e+00 + -2.1111e+00 -2.0345e+00 1.6550e+00 + -1.9303e+00 -2.2068e+00 1.6550e+00 + -1.7355e+00 -2.3631e+00 1.6550e+00 + -1.5281e+00 -2.5022e+00 1.6550e+00 + -1.3096e+00 -2.6232e+00 1.6550e+00 + -1.0815e+00 -2.7251e+00 1.6550e+00 + -8.4568e-01 -2.8073e+00 1.6550e+00 + -6.0369e-01 -2.8691e+00 1.6550e+00 + -3.5731e-01 -2.9100e+00 1.6550e+00 + -3.5731e-01 -2.9100e+00 1.6550e+00 + -3.5729e-01 -2.9099e+00 9.1800e-01 + -3.5727e-01 -2.9097e+00 1.8100e-01 + -3.5725e-01 -2.9096e+00 -5.5600e-01 + -3.5723e-01 -2.9094e+00 -1.2930e+00 + -3.5721e-01 -2.9093e+00 -2.0300e+00 + -6.7851e-01 -2.8515e+00 -2.0300e+00 + -9.9139e-01 -2.7583e+00 -2.0300e+00 + -1.2920e+00 -2.6310e+00 -2.0300e+00 + -1.5765e+00 -2.4710e+00 -2.0300e+00 + -1.8415e+00 -2.2804e+00 -2.0300e+00 + -2.0837e+00 -2.0614e+00 -2.0300e+00 + -2.3000e+00 -1.8169e+00 -2.0300e+00 + -2.4878e+00 -1.5499e+00 -2.0300e+00 + -2.6447e+00 -1.2636e+00 -2.0300e+00 + -2.7688e+00 -9.6171e-01 -2.0300e+00 + -2.8586e+00 -6.4785e-01 -2.0300e+00 + -2.9129e+00 -3.2594e-01 -2.0300e+00 + -2.9311e+00 3.5896e-16 -2.0300e+00 + -2.9313e+00 3.5898e-16 -1.2930e+00 + -2.9314e+00 3.5900e-16 -5.5600e-01 + -2.9316e+00 3.5902e-16 1.8100e-01 + -2.9317e+00 3.5903e-16 9.1800e-01 + -2.9319e+00 3.5905e-16 1.6550e+00 + -5.3858e-16 -2.9319e+00 1.6550e+00 + 2.4953e-01 -2.9213e+00 1.6550e+00 + 4.9726e-01 -2.8894e+00 1.6550e+00 + 7.4137e-01 -2.8366e+00 1.6550e+00 + 9.8011e-01 -2.7632e+00 1.6550e+00 + 1.2117e+00 -2.6698e+00 1.6550e+00 + 1.4346e+00 -2.5570e+00 1.6550e+00 + 1.6470e+00 -2.4256e+00 1.6550e+00 + 1.8474e+00 -2.2766e+00 1.6550e+00 + 2.0345e+00 -2.1111e+00 1.6550e+00 + 2.2068e+00 -1.9303e+00 1.6550e+00 + 2.3631e+00 -1.7355e+00 1.6550e+00 + 2.5022e+00 -1.5281e+00 1.6550e+00 + 2.6232e+00 -1.3096e+00 1.6550e+00 + 2.7251e+00 -1.0815e+00 1.6550e+00 + 2.8073e+00 -8.4568e-01 1.6550e+00 + 2.8691e+00 -6.0369e-01 1.6550e+00 + 2.9100e+00 -3.5731e-01 1.6550e+00 + 2.9100e+00 -3.5731e-01 1.6550e+00 + 2.9099e+00 -3.5729e-01 9.1800e-01 + 2.9097e+00 -3.5727e-01 1.8100e-01 + 2.9096e+00 -3.5725e-01 -5.5600e-01 + 2.9094e+00 -3.5723e-01 -1.2930e+00 + 2.9093e+00 -3.5721e-01 -2.0300e+00 + 2.8515e+00 -6.7851e-01 -2.0300e+00 + 2.7583e+00 -9.9139e-01 -2.0300e+00 + 2.6310e+00 -1.2920e+00 -2.0300e+00 + 2.4710e+00 -1.5765e+00 -2.0300e+00 + 2.2804e+00 -1.8415e+00 -2.0300e+00 + 2.0614e+00 -2.0837e+00 -2.0300e+00 + 1.8169e+00 -2.3000e+00 -2.0300e+00 + 1.5499e+00 -2.4878e+00 -2.0300e+00 + 1.2636e+00 -2.6447e+00 -2.0300e+00 + 9.6171e-01 -2.7688e+00 -2.0300e+00 + 6.4785e-01 -2.8586e+00 -2.0300e+00 + 3.2594e-01 -2.9129e+00 -2.0300e+00 + -5.3843e-16 -2.9311e+00 -2.0300e+00 + -5.3846e-16 -2.9313e+00 -1.2930e+00 + -5.3849e-16 -2.9314e+00 -5.5600e-01 + -5.3852e-16 -2.9316e+00 1.8100e-01 + -5.3855e-16 -2.9317e+00 9.1800e-01 + -5.3858e-16 -2.9319e+00 1.6550e+00 diff --git a/src/ForcingTerms/coil_geometries/mastu_rmpl.dat b/src/ForcingTerms/coil_geometries/mastu_rmpl.dat index 7d3a798d3..1bb9ca785 100644 --- a/src/ForcingTerms/coil_geometries/mastu_rmpl.dat +++ b/src/ForcingTerms/coil_geometries/mastu_rmpl.dat @@ -1,337 +1,337 @@ - 8 1 42 1.00 - 1.3110e+00 0.0000e+00 -7.9100e-01 - 1.3107e+00 2.6300e-02 -7.9100e-01 - 1.3099e+00 5.2589e-02 -7.9100e-01 - 1.3086e+00 7.8857e-02 -7.9100e-01 - 1.3068e+00 1.0509e-01 -7.9100e-01 - 1.3044e+00 1.3129e-01 -7.9100e-01 - 1.3015e+00 1.5743e-01 -7.9100e-01 - 1.2981e+00 1.8351e-01 -7.9100e-01 - 1.2942e+00 2.0951e-01 -7.9100e-01 - 1.2897e+00 2.3543e-01 -7.9100e-01 - 1.2847e+00 2.6125e-01 -7.9100e-01 - 1.2792e+00 2.8697e-01 -7.9100e-01 - 1.2732e+00 3.1258e-01 -7.9100e-01 - 1.2667e+00 3.3806e-01 -7.9100e-01 - 1.2596e+00 3.6340e-01 -7.9100e-01 - 1.2521e+00 3.8859e-01 -7.9100e-01 - 1.2440e+00 4.1363e-01 -7.9100e-01 - 1.2355e+00 4.3851e-01 -7.9100e-01 - 1.2264e+00 4.6320e-01 -7.9100e-01 - 1.2169e+00 4.8771e-01 -7.9100e-01 - 1.2169e+00 4.8771e-01 -7.9100e-01 - 1.2703e+00 5.0910e-01 -6.9100e-01 - 1.3237e+00 5.3049e-01 -5.9100e-01 - 1.3352e+00 5.0068e-01 -5.9100e-01 - 1.3461e+00 4.7062e-01 -5.9100e-01 - 1.3563e+00 4.4032e-01 -5.9100e-01 - 1.3658e+00 4.0980e-01 -5.9100e-01 - 1.3747e+00 3.7908e-01 -5.9100e-01 - 1.3828e+00 3.4816e-01 -5.9100e-01 - 1.3903e+00 3.1707e-01 -5.9100e-01 - 1.3971e+00 2.8582e-01 -5.9100e-01 - 1.4031e+00 2.5442e-01 -5.9100e-01 - 1.4085e+00 2.2290e-01 -5.9100e-01 - 1.4131e+00 1.9127e-01 -5.9100e-01 - 1.4170e+00 1.5954e-01 -5.9100e-01 - 1.4203e+00 1.2773e-01 -5.9100e-01 - 1.4228e+00 9.5850e-02 -5.9100e-01 - 1.4246e+00 6.3927e-02 -5.9100e-01 - 1.4256e+00 3.1972e-02 -5.9100e-01 - 1.4260e+00 0.0000e+00 -5.9100e-01 - 1.3685e+00 0.0000e+00 -6.9100e-01 - 1.3110e+00 0.0000e+00 -7.9100e-01 - 9.2702e-01 9.2702e-01 -7.9100e-01 - 9.0823e-01 9.4543e-01 -7.9100e-01 - 8.8909e-01 9.6346e-01 -7.9100e-01 - 8.6958e-01 9.8110e-01 -7.9100e-01 - 8.4972e-01 9.9835e-01 -7.9100e-01 - 8.2952e-01 1.0152e+00 -7.9100e-01 - 8.0899e-01 1.0316e+00 -7.9100e-01 - 7.8813e-01 1.0476e+00 -7.9100e-01 - 7.6696e-01 1.0632e+00 -7.9100e-01 - 7.4547e-01 1.0784e+00 -7.9100e-01 - 7.2369e-01 1.0932e+00 -7.9100e-01 - 7.0161e-01 1.1075e+00 -7.9100e-01 - 6.7926e-01 1.1213e+00 -7.9100e-01 - 6.5663e-01 1.1347e+00 -7.9100e-01 - 6.3373e-01 1.1477e+00 -7.9100e-01 - 6.1058e-01 1.1601e+00 -7.9100e-01 - 5.8718e-01 1.1721e+00 -7.9100e-01 - 5.6355e-01 1.1837e+00 -7.9100e-01 - 5.3969e-01 1.1948e+00 -7.9100e-01 - 5.1562e-01 1.2053e+00 -7.9100e-01 - 5.1562e-01 1.2053e+00 -7.9100e-01 - 5.3823e-01 1.2582e+00 -6.9100e-01 - 5.6085e-01 1.3111e+00 -5.9100e-01 - 5.9010e-01 1.2982e+00 -5.9100e-01 - 6.1906e-01 1.2846e+00 -5.9100e-01 - 6.4770e-01 1.2704e+00 -5.9100e-01 - 6.7602e-01 1.2556e+00 -5.9100e-01 - 7.0400e-01 1.2401e+00 -5.9100e-01 - 7.3163e-01 1.2240e+00 -5.9100e-01 - 7.5889e-01 1.2073e+00 -5.9100e-01 - 7.8577e-01 1.1900e+00 -5.9100e-01 - 8.1225e-01 1.1721e+00 -5.9100e-01 - 8.3832e-01 1.1536e+00 -5.9100e-01 - 8.6398e-01 1.1345e+00 -5.9100e-01 - 8.8919e-01 1.1148e+00 -5.9100e-01 - 9.1397e-01 1.0946e+00 -5.9100e-01 - 9.3828e-01 1.0738e+00 -5.9100e-01 - 9.6212e-01 1.0525e+00 -5.9100e-01 - 9.8547e-01 1.0307e+00 -5.9100e-01 - 1.0083e+00 1.0083e+00 -5.9100e-01 - 9.6768e-01 9.6768e-01 -6.9100e-01 - 9.2702e-01 9.2702e-01 -7.9100e-01 - 8.0276e-17 1.3110e+00 -7.9100e-01 - -2.6300e-02 1.3107e+00 -7.9100e-01 - -5.2589e-02 1.3099e+00 -7.9100e-01 - -7.8857e-02 1.3086e+00 -7.9100e-01 - -1.0509e-01 1.3068e+00 -7.9100e-01 - -1.3129e-01 1.3044e+00 -7.9100e-01 - -1.5743e-01 1.3015e+00 -7.9100e-01 - -1.8351e-01 1.2981e+00 -7.9100e-01 - -2.0951e-01 1.2942e+00 -7.9100e-01 - -2.3543e-01 1.2897e+00 -7.9100e-01 - -2.6125e-01 1.2847e+00 -7.9100e-01 - -2.8697e-01 1.2792e+00 -7.9100e-01 - -3.1258e-01 1.2732e+00 -7.9100e-01 - -3.3806e-01 1.2667e+00 -7.9100e-01 - -3.6340e-01 1.2596e+00 -7.9100e-01 - -3.8859e-01 1.2521e+00 -7.9100e-01 - -4.1363e-01 1.2440e+00 -7.9100e-01 - -4.3851e-01 1.2355e+00 -7.9100e-01 - -4.6320e-01 1.2264e+00 -7.9100e-01 - -4.8771e-01 1.2169e+00 -7.9100e-01 - -4.8771e-01 1.2169e+00 -7.9100e-01 - -5.0910e-01 1.2703e+00 -6.9100e-01 - -5.3049e-01 1.3237e+00 -5.9100e-01 - -5.0068e-01 1.3352e+00 -5.9100e-01 - -4.7062e-01 1.3461e+00 -5.9100e-01 - -4.4032e-01 1.3563e+00 -5.9100e-01 - -4.0980e-01 1.3658e+00 -5.9100e-01 - -3.7908e-01 1.3747e+00 -5.9100e-01 - -3.4816e-01 1.3828e+00 -5.9100e-01 - -3.1707e-01 1.3903e+00 -5.9100e-01 - -2.8582e-01 1.3971e+00 -5.9100e-01 - -2.5442e-01 1.4031e+00 -5.9100e-01 - -2.2290e-01 1.4085e+00 -5.9100e-01 - -1.9127e-01 1.4131e+00 -5.9100e-01 - -1.5954e-01 1.4170e+00 -5.9100e-01 - -1.2773e-01 1.4203e+00 -5.9100e-01 - -9.5850e-02 1.4228e+00 -5.9100e-01 - -6.3927e-02 1.4246e+00 -5.9100e-01 - -3.1972e-02 1.4256e+00 -5.9100e-01 - 8.7317e-17 1.4260e+00 -5.9100e-01 - 8.3796e-17 1.3685e+00 -6.9100e-01 - 8.0276e-17 1.3110e+00 -7.9100e-01 - -9.2702e-01 9.2702e-01 -7.9100e-01 - -9.4543e-01 9.0823e-01 -7.9100e-01 - -9.6346e-01 8.8909e-01 -7.9100e-01 - -9.8110e-01 8.6958e-01 -7.9100e-01 - -9.9835e-01 8.4972e-01 -7.9100e-01 - -1.0152e+00 8.2952e-01 -7.9100e-01 - -1.0316e+00 8.0899e-01 -7.9100e-01 - -1.0476e+00 7.8813e-01 -7.9100e-01 - -1.0632e+00 7.6696e-01 -7.9100e-01 - -1.0784e+00 7.4547e-01 -7.9100e-01 - -1.0932e+00 7.2369e-01 -7.9100e-01 - -1.1075e+00 7.0161e-01 -7.9100e-01 - -1.1213e+00 6.7926e-01 -7.9100e-01 - -1.1347e+00 6.5663e-01 -7.9100e-01 - -1.1477e+00 6.3373e-01 -7.9100e-01 - -1.1601e+00 6.1058e-01 -7.9100e-01 - -1.1721e+00 5.8718e-01 -7.9100e-01 - -1.1837e+00 5.6355e-01 -7.9100e-01 - -1.1948e+00 5.3969e-01 -7.9100e-01 - -1.2053e+00 5.1562e-01 -7.9100e-01 - -1.2053e+00 5.1562e-01 -7.9100e-01 - -1.2582e+00 5.3823e-01 -6.9100e-01 - -1.3111e+00 5.6085e-01 -5.9100e-01 - -1.2982e+00 5.9010e-01 -5.9100e-01 - -1.2846e+00 6.1906e-01 -5.9100e-01 - -1.2704e+00 6.4770e-01 -5.9100e-01 - -1.2556e+00 6.7602e-01 -5.9100e-01 - -1.2401e+00 7.0400e-01 -5.9100e-01 - -1.2240e+00 7.3163e-01 -5.9100e-01 - -1.2073e+00 7.5889e-01 -5.9100e-01 - -1.1900e+00 7.8577e-01 -5.9100e-01 - -1.1721e+00 8.1225e-01 -5.9100e-01 - -1.1536e+00 8.3832e-01 -5.9100e-01 - -1.1345e+00 8.6398e-01 -5.9100e-01 - -1.1148e+00 8.8919e-01 -5.9100e-01 - -1.0946e+00 9.1397e-01 -5.9100e-01 - -1.0738e+00 9.3828e-01 -5.9100e-01 - -1.0525e+00 9.6212e-01 -5.9100e-01 - -1.0307e+00 9.8547e-01 -5.9100e-01 - -1.0083e+00 1.0083e+00 -5.9100e-01 - -9.6768e-01 9.6768e-01 -6.9100e-01 - -9.2702e-01 9.2702e-01 -7.9100e-01 - -1.3110e+00 1.6055e-16 -7.9100e-01 - -1.3107e+00 -2.6300e-02 -7.9100e-01 - -1.3099e+00 -5.2589e-02 -7.9100e-01 - -1.3086e+00 -7.8857e-02 -7.9100e-01 - -1.3068e+00 -1.0509e-01 -7.9100e-01 - -1.3044e+00 -1.3129e-01 -7.9100e-01 - -1.3015e+00 -1.5743e-01 -7.9100e-01 - -1.2981e+00 -1.8351e-01 -7.9100e-01 - -1.2942e+00 -2.0951e-01 -7.9100e-01 - -1.2897e+00 -2.3543e-01 -7.9100e-01 - -1.2847e+00 -2.6125e-01 -7.9100e-01 - -1.2792e+00 -2.8697e-01 -7.9100e-01 - -1.2732e+00 -3.1258e-01 -7.9100e-01 - -1.2667e+00 -3.3806e-01 -7.9100e-01 - -1.2596e+00 -3.6340e-01 -7.9100e-01 - -1.2521e+00 -3.8859e-01 -7.9100e-01 - -1.2440e+00 -4.1363e-01 -7.9100e-01 - -1.2355e+00 -4.3851e-01 -7.9100e-01 - -1.2264e+00 -4.6320e-01 -7.9100e-01 - -1.2169e+00 -4.8771e-01 -7.9100e-01 - -1.2169e+00 -4.8771e-01 -7.9100e-01 - -1.2703e+00 -5.0910e-01 -6.9100e-01 - -1.3237e+00 -5.3049e-01 -5.9100e-01 - -1.3352e+00 -5.0068e-01 -5.9100e-01 - -1.3461e+00 -4.7062e-01 -5.9100e-01 - -1.3563e+00 -4.4032e-01 -5.9100e-01 - -1.3658e+00 -4.0980e-01 -5.9100e-01 - -1.3747e+00 -3.7908e-01 -5.9100e-01 - -1.3828e+00 -3.4816e-01 -5.9100e-01 - -1.3903e+00 -3.1707e-01 -5.9100e-01 - -1.3971e+00 -2.8582e-01 -5.9100e-01 - -1.4031e+00 -2.5442e-01 -5.9100e-01 - -1.4085e+00 -2.2290e-01 -5.9100e-01 - -1.4131e+00 -1.9127e-01 -5.9100e-01 - -1.4170e+00 -1.5954e-01 -5.9100e-01 - -1.4203e+00 -1.2773e-01 -5.9100e-01 - -1.4228e+00 -9.5850e-02 -5.9100e-01 - -1.4246e+00 -6.3927e-02 -5.9100e-01 - -1.4256e+00 -3.1972e-02 -5.9100e-01 - -1.4260e+00 1.7463e-16 -5.9100e-01 - -1.3685e+00 1.6759e-16 -6.9100e-01 - -1.3110e+00 1.6055e-16 -7.9100e-01 - -9.2702e-01 -9.2702e-01 -7.9100e-01 - -9.0823e-01 -9.4543e-01 -7.9100e-01 - -8.8909e-01 -9.6346e-01 -7.9100e-01 - -8.6958e-01 -9.8110e-01 -7.9100e-01 - -8.4972e-01 -9.9835e-01 -7.9100e-01 - -8.2952e-01 -1.0152e+00 -7.9100e-01 - -8.0899e-01 -1.0316e+00 -7.9100e-01 - -7.8813e-01 -1.0476e+00 -7.9100e-01 - -7.6696e-01 -1.0632e+00 -7.9100e-01 - -7.4547e-01 -1.0784e+00 -7.9100e-01 - -7.2369e-01 -1.0932e+00 -7.9100e-01 - -7.0161e-01 -1.1075e+00 -7.9100e-01 - -6.7926e-01 -1.1213e+00 -7.9100e-01 - -6.5663e-01 -1.1347e+00 -7.9100e-01 - -6.3373e-01 -1.1477e+00 -7.9100e-01 - -6.1058e-01 -1.1601e+00 -7.9100e-01 - -5.8718e-01 -1.1721e+00 -7.9100e-01 - -5.6355e-01 -1.1837e+00 -7.9100e-01 - -5.3969e-01 -1.1948e+00 -7.9100e-01 - -5.1562e-01 -1.2053e+00 -7.9100e-01 - -5.1562e-01 -1.2053e+00 -7.9100e-01 - -5.3823e-01 -1.2582e+00 -6.9100e-01 - -5.6085e-01 -1.3111e+00 -5.9100e-01 - -5.9010e-01 -1.2982e+00 -5.9100e-01 - -6.1906e-01 -1.2846e+00 -5.9100e-01 - -6.4770e-01 -1.2704e+00 -5.9100e-01 - -6.7602e-01 -1.2556e+00 -5.9100e-01 - -7.0400e-01 -1.2401e+00 -5.9100e-01 - -7.3163e-01 -1.2240e+00 -5.9100e-01 - -7.5889e-01 -1.2073e+00 -5.9100e-01 - -7.8577e-01 -1.1900e+00 -5.9100e-01 - -8.1225e-01 -1.1721e+00 -5.9100e-01 - -8.3832e-01 -1.1536e+00 -5.9100e-01 - -8.6398e-01 -1.1345e+00 -5.9100e-01 - -8.8919e-01 -1.1148e+00 -5.9100e-01 - -9.1397e-01 -1.0946e+00 -5.9100e-01 - -9.3828e-01 -1.0738e+00 -5.9100e-01 - -9.6212e-01 -1.0525e+00 -5.9100e-01 - -9.8547e-01 -1.0307e+00 -5.9100e-01 - -1.0083e+00 -1.0083e+00 -5.9100e-01 - -9.6768e-01 -9.6768e-01 -6.9100e-01 - -9.2702e-01 -9.2702e-01 -7.9100e-01 - -2.4083e-16 -1.3110e+00 -7.9100e-01 - 2.6300e-02 -1.3107e+00 -7.9100e-01 - 5.2589e-02 -1.3099e+00 -7.9100e-01 - 7.8857e-02 -1.3086e+00 -7.9100e-01 - 1.0509e-01 -1.3068e+00 -7.9100e-01 - 1.3129e-01 -1.3044e+00 -7.9100e-01 - 1.5743e-01 -1.3015e+00 -7.9100e-01 - 1.8351e-01 -1.2981e+00 -7.9100e-01 - 2.0951e-01 -1.2942e+00 -7.9100e-01 - 2.3543e-01 -1.2897e+00 -7.9100e-01 - 2.6125e-01 -1.2847e+00 -7.9100e-01 - 2.8697e-01 -1.2792e+00 -7.9100e-01 - 3.1258e-01 -1.2732e+00 -7.9100e-01 - 3.3806e-01 -1.2667e+00 -7.9100e-01 - 3.6340e-01 -1.2596e+00 -7.9100e-01 - 3.8859e-01 -1.2521e+00 -7.9100e-01 - 4.1363e-01 -1.2440e+00 -7.9100e-01 - 4.3851e-01 -1.2355e+00 -7.9100e-01 - 4.6320e-01 -1.2264e+00 -7.9100e-01 - 4.8771e-01 -1.2169e+00 -7.9100e-01 - 4.8771e-01 -1.2169e+00 -7.9100e-01 - 5.0910e-01 -1.2703e+00 -6.9100e-01 - 5.3049e-01 -1.3237e+00 -5.9100e-01 - 5.0068e-01 -1.3352e+00 -5.9100e-01 - 4.7062e-01 -1.3461e+00 -5.9100e-01 - 4.4032e-01 -1.3563e+00 -5.9100e-01 - 4.0980e-01 -1.3658e+00 -5.9100e-01 - 3.7908e-01 -1.3747e+00 -5.9100e-01 - 3.4816e-01 -1.3828e+00 -5.9100e-01 - 3.1707e-01 -1.3903e+00 -5.9100e-01 - 2.8582e-01 -1.3971e+00 -5.9100e-01 - 2.5442e-01 -1.4031e+00 -5.9100e-01 - 2.2290e-01 -1.4085e+00 -5.9100e-01 - 1.9127e-01 -1.4131e+00 -5.9100e-01 - 1.5954e-01 -1.4170e+00 -5.9100e-01 - 1.2773e-01 -1.4203e+00 -5.9100e-01 - 9.5850e-02 -1.4228e+00 -5.9100e-01 - 6.3927e-02 -1.4246e+00 -5.9100e-01 - 3.1972e-02 -1.4256e+00 -5.9100e-01 - -2.6195e-16 -1.4260e+00 -5.9100e-01 - -2.5139e-16 -1.3685e+00 -6.9100e-01 - -2.4083e-16 -1.3110e+00 -7.9100e-01 - 9.2702e-01 -9.2702e-01 -7.9100e-01 - 9.4543e-01 -9.0823e-01 -7.9100e-01 - 9.6346e-01 -8.8909e-01 -7.9100e-01 - 9.8110e-01 -8.6958e-01 -7.9100e-01 - 9.9835e-01 -8.4972e-01 -7.9100e-01 - 1.0152e+00 -8.2952e-01 -7.9100e-01 - 1.0316e+00 -8.0899e-01 -7.9100e-01 - 1.0476e+00 -7.8813e-01 -7.9100e-01 - 1.0632e+00 -7.6696e-01 -7.9100e-01 - 1.0784e+00 -7.4547e-01 -7.9100e-01 - 1.0932e+00 -7.2369e-01 -7.9100e-01 - 1.1075e+00 -7.0161e-01 -7.9100e-01 - 1.1213e+00 -6.7926e-01 -7.9100e-01 - 1.1347e+00 -6.5663e-01 -7.9100e-01 - 1.1477e+00 -6.3373e-01 -7.9100e-01 - 1.1601e+00 -6.1058e-01 -7.9100e-01 - 1.1721e+00 -5.8718e-01 -7.9100e-01 - 1.1837e+00 -5.6355e-01 -7.9100e-01 - 1.1948e+00 -5.3969e-01 -7.9100e-01 - 1.2053e+00 -5.1562e-01 -7.9100e-01 - 1.2053e+00 -5.1562e-01 -7.9100e-01 - 1.2582e+00 -5.3823e-01 -6.9100e-01 - 1.3111e+00 -5.6085e-01 -5.9100e-01 - 1.2982e+00 -5.9010e-01 -5.9100e-01 - 1.2846e+00 -6.1906e-01 -5.9100e-01 - 1.2704e+00 -6.4770e-01 -5.9100e-01 - 1.2556e+00 -6.7602e-01 -5.9100e-01 - 1.2401e+00 -7.0400e-01 -5.9100e-01 - 1.2240e+00 -7.3163e-01 -5.9100e-01 - 1.2073e+00 -7.5889e-01 -5.9100e-01 - 1.1900e+00 -7.8577e-01 -5.9100e-01 - 1.1721e+00 -8.1225e-01 -5.9100e-01 - 1.1536e+00 -8.3832e-01 -5.9100e-01 - 1.1345e+00 -8.6398e-01 -5.9100e-01 - 1.1148e+00 -8.8919e-01 -5.9100e-01 - 1.0946e+00 -9.1397e-01 -5.9100e-01 - 1.0738e+00 -9.3828e-01 -5.9100e-01 - 1.0525e+00 -9.6212e-01 -5.9100e-01 - 1.0307e+00 -9.8547e-01 -5.9100e-01 - 1.0083e+00 -1.0083e+00 -5.9100e-01 - 9.6768e-01 -9.6768e-01 -6.9100e-01 - 9.2702e-01 -9.2702e-01 -7.9100e-01 + 8 1 42 1.00 + 1.3110e+00 0.0000e+00 -7.9100e-01 + 1.3107e+00 2.6300e-02 -7.9100e-01 + 1.3099e+00 5.2589e-02 -7.9100e-01 + 1.3086e+00 7.8857e-02 -7.9100e-01 + 1.3068e+00 1.0509e-01 -7.9100e-01 + 1.3044e+00 1.3129e-01 -7.9100e-01 + 1.3015e+00 1.5743e-01 -7.9100e-01 + 1.2981e+00 1.8351e-01 -7.9100e-01 + 1.2942e+00 2.0951e-01 -7.9100e-01 + 1.2897e+00 2.3543e-01 -7.9100e-01 + 1.2847e+00 2.6125e-01 -7.9100e-01 + 1.2792e+00 2.8697e-01 -7.9100e-01 + 1.2732e+00 3.1258e-01 -7.9100e-01 + 1.2667e+00 3.3806e-01 -7.9100e-01 + 1.2596e+00 3.6340e-01 -7.9100e-01 + 1.2521e+00 3.8859e-01 -7.9100e-01 + 1.2440e+00 4.1363e-01 -7.9100e-01 + 1.2355e+00 4.3851e-01 -7.9100e-01 + 1.2264e+00 4.6320e-01 -7.9100e-01 + 1.2169e+00 4.8771e-01 -7.9100e-01 + 1.2169e+00 4.8771e-01 -7.9100e-01 + 1.2703e+00 5.0910e-01 -6.9100e-01 + 1.3237e+00 5.3049e-01 -5.9100e-01 + 1.3352e+00 5.0068e-01 -5.9100e-01 + 1.3461e+00 4.7062e-01 -5.9100e-01 + 1.3563e+00 4.4032e-01 -5.9100e-01 + 1.3658e+00 4.0980e-01 -5.9100e-01 + 1.3747e+00 3.7908e-01 -5.9100e-01 + 1.3828e+00 3.4816e-01 -5.9100e-01 + 1.3903e+00 3.1707e-01 -5.9100e-01 + 1.3971e+00 2.8582e-01 -5.9100e-01 + 1.4031e+00 2.5442e-01 -5.9100e-01 + 1.4085e+00 2.2290e-01 -5.9100e-01 + 1.4131e+00 1.9127e-01 -5.9100e-01 + 1.4170e+00 1.5954e-01 -5.9100e-01 + 1.4203e+00 1.2773e-01 -5.9100e-01 + 1.4228e+00 9.5850e-02 -5.9100e-01 + 1.4246e+00 6.3927e-02 -5.9100e-01 + 1.4256e+00 3.1972e-02 -5.9100e-01 + 1.4260e+00 0.0000e+00 -5.9100e-01 + 1.3685e+00 0.0000e+00 -6.9100e-01 + 1.3110e+00 0.0000e+00 -7.9100e-01 + 9.2702e-01 9.2702e-01 -7.9100e-01 + 9.0823e-01 9.4543e-01 -7.9100e-01 + 8.8909e-01 9.6346e-01 -7.9100e-01 + 8.6958e-01 9.8110e-01 -7.9100e-01 + 8.4972e-01 9.9835e-01 -7.9100e-01 + 8.2952e-01 1.0152e+00 -7.9100e-01 + 8.0899e-01 1.0316e+00 -7.9100e-01 + 7.8813e-01 1.0476e+00 -7.9100e-01 + 7.6696e-01 1.0632e+00 -7.9100e-01 + 7.4547e-01 1.0784e+00 -7.9100e-01 + 7.2369e-01 1.0932e+00 -7.9100e-01 + 7.0161e-01 1.1075e+00 -7.9100e-01 + 6.7926e-01 1.1213e+00 -7.9100e-01 + 6.5663e-01 1.1347e+00 -7.9100e-01 + 6.3373e-01 1.1477e+00 -7.9100e-01 + 6.1058e-01 1.1601e+00 -7.9100e-01 + 5.8718e-01 1.1721e+00 -7.9100e-01 + 5.6355e-01 1.1837e+00 -7.9100e-01 + 5.3969e-01 1.1948e+00 -7.9100e-01 + 5.1562e-01 1.2053e+00 -7.9100e-01 + 5.1562e-01 1.2053e+00 -7.9100e-01 + 5.3823e-01 1.2582e+00 -6.9100e-01 + 5.6085e-01 1.3111e+00 -5.9100e-01 + 5.9010e-01 1.2982e+00 -5.9100e-01 + 6.1906e-01 1.2846e+00 -5.9100e-01 + 6.4770e-01 1.2704e+00 -5.9100e-01 + 6.7602e-01 1.2556e+00 -5.9100e-01 + 7.0400e-01 1.2401e+00 -5.9100e-01 + 7.3163e-01 1.2240e+00 -5.9100e-01 + 7.5889e-01 1.2073e+00 -5.9100e-01 + 7.8577e-01 1.1900e+00 -5.9100e-01 + 8.1225e-01 1.1721e+00 -5.9100e-01 + 8.3832e-01 1.1536e+00 -5.9100e-01 + 8.6398e-01 1.1345e+00 -5.9100e-01 + 8.8919e-01 1.1148e+00 -5.9100e-01 + 9.1397e-01 1.0946e+00 -5.9100e-01 + 9.3828e-01 1.0738e+00 -5.9100e-01 + 9.6212e-01 1.0525e+00 -5.9100e-01 + 9.8547e-01 1.0307e+00 -5.9100e-01 + 1.0083e+00 1.0083e+00 -5.9100e-01 + 9.6768e-01 9.6768e-01 -6.9100e-01 + 9.2702e-01 9.2702e-01 -7.9100e-01 + 8.0276e-17 1.3110e+00 -7.9100e-01 + -2.6300e-02 1.3107e+00 -7.9100e-01 + -5.2589e-02 1.3099e+00 -7.9100e-01 + -7.8857e-02 1.3086e+00 -7.9100e-01 + -1.0509e-01 1.3068e+00 -7.9100e-01 + -1.3129e-01 1.3044e+00 -7.9100e-01 + -1.5743e-01 1.3015e+00 -7.9100e-01 + -1.8351e-01 1.2981e+00 -7.9100e-01 + -2.0951e-01 1.2942e+00 -7.9100e-01 + -2.3543e-01 1.2897e+00 -7.9100e-01 + -2.6125e-01 1.2847e+00 -7.9100e-01 + -2.8697e-01 1.2792e+00 -7.9100e-01 + -3.1258e-01 1.2732e+00 -7.9100e-01 + -3.3806e-01 1.2667e+00 -7.9100e-01 + -3.6340e-01 1.2596e+00 -7.9100e-01 + -3.8859e-01 1.2521e+00 -7.9100e-01 + -4.1363e-01 1.2440e+00 -7.9100e-01 + -4.3851e-01 1.2355e+00 -7.9100e-01 + -4.6320e-01 1.2264e+00 -7.9100e-01 + -4.8771e-01 1.2169e+00 -7.9100e-01 + -4.8771e-01 1.2169e+00 -7.9100e-01 + -5.0910e-01 1.2703e+00 -6.9100e-01 + -5.3049e-01 1.3237e+00 -5.9100e-01 + -5.0068e-01 1.3352e+00 -5.9100e-01 + -4.7062e-01 1.3461e+00 -5.9100e-01 + -4.4032e-01 1.3563e+00 -5.9100e-01 + -4.0980e-01 1.3658e+00 -5.9100e-01 + -3.7908e-01 1.3747e+00 -5.9100e-01 + -3.4816e-01 1.3828e+00 -5.9100e-01 + -3.1707e-01 1.3903e+00 -5.9100e-01 + -2.8582e-01 1.3971e+00 -5.9100e-01 + -2.5442e-01 1.4031e+00 -5.9100e-01 + -2.2290e-01 1.4085e+00 -5.9100e-01 + -1.9127e-01 1.4131e+00 -5.9100e-01 + -1.5954e-01 1.4170e+00 -5.9100e-01 + -1.2773e-01 1.4203e+00 -5.9100e-01 + -9.5850e-02 1.4228e+00 -5.9100e-01 + -6.3927e-02 1.4246e+00 -5.9100e-01 + -3.1972e-02 1.4256e+00 -5.9100e-01 + 8.7317e-17 1.4260e+00 -5.9100e-01 + 8.3796e-17 1.3685e+00 -6.9100e-01 + 8.0276e-17 1.3110e+00 -7.9100e-01 + -9.2702e-01 9.2702e-01 -7.9100e-01 + -9.4543e-01 9.0823e-01 -7.9100e-01 + -9.6346e-01 8.8909e-01 -7.9100e-01 + -9.8110e-01 8.6958e-01 -7.9100e-01 + -9.9835e-01 8.4972e-01 -7.9100e-01 + -1.0152e+00 8.2952e-01 -7.9100e-01 + -1.0316e+00 8.0899e-01 -7.9100e-01 + -1.0476e+00 7.8813e-01 -7.9100e-01 + -1.0632e+00 7.6696e-01 -7.9100e-01 + -1.0784e+00 7.4547e-01 -7.9100e-01 + -1.0932e+00 7.2369e-01 -7.9100e-01 + -1.1075e+00 7.0161e-01 -7.9100e-01 + -1.1213e+00 6.7926e-01 -7.9100e-01 + -1.1347e+00 6.5663e-01 -7.9100e-01 + -1.1477e+00 6.3373e-01 -7.9100e-01 + -1.1601e+00 6.1058e-01 -7.9100e-01 + -1.1721e+00 5.8718e-01 -7.9100e-01 + -1.1837e+00 5.6355e-01 -7.9100e-01 + -1.1948e+00 5.3969e-01 -7.9100e-01 + -1.2053e+00 5.1562e-01 -7.9100e-01 + -1.2053e+00 5.1562e-01 -7.9100e-01 + -1.2582e+00 5.3823e-01 -6.9100e-01 + -1.3111e+00 5.6085e-01 -5.9100e-01 + -1.2982e+00 5.9010e-01 -5.9100e-01 + -1.2846e+00 6.1906e-01 -5.9100e-01 + -1.2704e+00 6.4770e-01 -5.9100e-01 + -1.2556e+00 6.7602e-01 -5.9100e-01 + -1.2401e+00 7.0400e-01 -5.9100e-01 + -1.2240e+00 7.3163e-01 -5.9100e-01 + -1.2073e+00 7.5889e-01 -5.9100e-01 + -1.1900e+00 7.8577e-01 -5.9100e-01 + -1.1721e+00 8.1225e-01 -5.9100e-01 + -1.1536e+00 8.3832e-01 -5.9100e-01 + -1.1345e+00 8.6398e-01 -5.9100e-01 + -1.1148e+00 8.8919e-01 -5.9100e-01 + -1.0946e+00 9.1397e-01 -5.9100e-01 + -1.0738e+00 9.3828e-01 -5.9100e-01 + -1.0525e+00 9.6212e-01 -5.9100e-01 + -1.0307e+00 9.8547e-01 -5.9100e-01 + -1.0083e+00 1.0083e+00 -5.9100e-01 + -9.6768e-01 9.6768e-01 -6.9100e-01 + -9.2702e-01 9.2702e-01 -7.9100e-01 + -1.3110e+00 1.6055e-16 -7.9100e-01 + -1.3107e+00 -2.6300e-02 -7.9100e-01 + -1.3099e+00 -5.2589e-02 -7.9100e-01 + -1.3086e+00 -7.8857e-02 -7.9100e-01 + -1.3068e+00 -1.0509e-01 -7.9100e-01 + -1.3044e+00 -1.3129e-01 -7.9100e-01 + -1.3015e+00 -1.5743e-01 -7.9100e-01 + -1.2981e+00 -1.8351e-01 -7.9100e-01 + -1.2942e+00 -2.0951e-01 -7.9100e-01 + -1.2897e+00 -2.3543e-01 -7.9100e-01 + -1.2847e+00 -2.6125e-01 -7.9100e-01 + -1.2792e+00 -2.8697e-01 -7.9100e-01 + -1.2732e+00 -3.1258e-01 -7.9100e-01 + -1.2667e+00 -3.3806e-01 -7.9100e-01 + -1.2596e+00 -3.6340e-01 -7.9100e-01 + -1.2521e+00 -3.8859e-01 -7.9100e-01 + -1.2440e+00 -4.1363e-01 -7.9100e-01 + -1.2355e+00 -4.3851e-01 -7.9100e-01 + -1.2264e+00 -4.6320e-01 -7.9100e-01 + -1.2169e+00 -4.8771e-01 -7.9100e-01 + -1.2169e+00 -4.8771e-01 -7.9100e-01 + -1.2703e+00 -5.0910e-01 -6.9100e-01 + -1.3237e+00 -5.3049e-01 -5.9100e-01 + -1.3352e+00 -5.0068e-01 -5.9100e-01 + -1.3461e+00 -4.7062e-01 -5.9100e-01 + -1.3563e+00 -4.4032e-01 -5.9100e-01 + -1.3658e+00 -4.0980e-01 -5.9100e-01 + -1.3747e+00 -3.7908e-01 -5.9100e-01 + -1.3828e+00 -3.4816e-01 -5.9100e-01 + -1.3903e+00 -3.1707e-01 -5.9100e-01 + -1.3971e+00 -2.8582e-01 -5.9100e-01 + -1.4031e+00 -2.5442e-01 -5.9100e-01 + -1.4085e+00 -2.2290e-01 -5.9100e-01 + -1.4131e+00 -1.9127e-01 -5.9100e-01 + -1.4170e+00 -1.5954e-01 -5.9100e-01 + -1.4203e+00 -1.2773e-01 -5.9100e-01 + -1.4228e+00 -9.5850e-02 -5.9100e-01 + -1.4246e+00 -6.3927e-02 -5.9100e-01 + -1.4256e+00 -3.1972e-02 -5.9100e-01 + -1.4260e+00 1.7463e-16 -5.9100e-01 + -1.3685e+00 1.6759e-16 -6.9100e-01 + -1.3110e+00 1.6055e-16 -7.9100e-01 + -9.2702e-01 -9.2702e-01 -7.9100e-01 + -9.0823e-01 -9.4543e-01 -7.9100e-01 + -8.8909e-01 -9.6346e-01 -7.9100e-01 + -8.6958e-01 -9.8110e-01 -7.9100e-01 + -8.4972e-01 -9.9835e-01 -7.9100e-01 + -8.2952e-01 -1.0152e+00 -7.9100e-01 + -8.0899e-01 -1.0316e+00 -7.9100e-01 + -7.8813e-01 -1.0476e+00 -7.9100e-01 + -7.6696e-01 -1.0632e+00 -7.9100e-01 + -7.4547e-01 -1.0784e+00 -7.9100e-01 + -7.2369e-01 -1.0932e+00 -7.9100e-01 + -7.0161e-01 -1.1075e+00 -7.9100e-01 + -6.7926e-01 -1.1213e+00 -7.9100e-01 + -6.5663e-01 -1.1347e+00 -7.9100e-01 + -6.3373e-01 -1.1477e+00 -7.9100e-01 + -6.1058e-01 -1.1601e+00 -7.9100e-01 + -5.8718e-01 -1.1721e+00 -7.9100e-01 + -5.6355e-01 -1.1837e+00 -7.9100e-01 + -5.3969e-01 -1.1948e+00 -7.9100e-01 + -5.1562e-01 -1.2053e+00 -7.9100e-01 + -5.1562e-01 -1.2053e+00 -7.9100e-01 + -5.3823e-01 -1.2582e+00 -6.9100e-01 + -5.6085e-01 -1.3111e+00 -5.9100e-01 + -5.9010e-01 -1.2982e+00 -5.9100e-01 + -6.1906e-01 -1.2846e+00 -5.9100e-01 + -6.4770e-01 -1.2704e+00 -5.9100e-01 + -6.7602e-01 -1.2556e+00 -5.9100e-01 + -7.0400e-01 -1.2401e+00 -5.9100e-01 + -7.3163e-01 -1.2240e+00 -5.9100e-01 + -7.5889e-01 -1.2073e+00 -5.9100e-01 + -7.8577e-01 -1.1900e+00 -5.9100e-01 + -8.1225e-01 -1.1721e+00 -5.9100e-01 + -8.3832e-01 -1.1536e+00 -5.9100e-01 + -8.6398e-01 -1.1345e+00 -5.9100e-01 + -8.8919e-01 -1.1148e+00 -5.9100e-01 + -9.1397e-01 -1.0946e+00 -5.9100e-01 + -9.3828e-01 -1.0738e+00 -5.9100e-01 + -9.6212e-01 -1.0525e+00 -5.9100e-01 + -9.8547e-01 -1.0307e+00 -5.9100e-01 + -1.0083e+00 -1.0083e+00 -5.9100e-01 + -9.6768e-01 -9.6768e-01 -6.9100e-01 + -9.2702e-01 -9.2702e-01 -7.9100e-01 + -2.4083e-16 -1.3110e+00 -7.9100e-01 + 2.6300e-02 -1.3107e+00 -7.9100e-01 + 5.2589e-02 -1.3099e+00 -7.9100e-01 + 7.8857e-02 -1.3086e+00 -7.9100e-01 + 1.0509e-01 -1.3068e+00 -7.9100e-01 + 1.3129e-01 -1.3044e+00 -7.9100e-01 + 1.5743e-01 -1.3015e+00 -7.9100e-01 + 1.8351e-01 -1.2981e+00 -7.9100e-01 + 2.0951e-01 -1.2942e+00 -7.9100e-01 + 2.3543e-01 -1.2897e+00 -7.9100e-01 + 2.6125e-01 -1.2847e+00 -7.9100e-01 + 2.8697e-01 -1.2792e+00 -7.9100e-01 + 3.1258e-01 -1.2732e+00 -7.9100e-01 + 3.3806e-01 -1.2667e+00 -7.9100e-01 + 3.6340e-01 -1.2596e+00 -7.9100e-01 + 3.8859e-01 -1.2521e+00 -7.9100e-01 + 4.1363e-01 -1.2440e+00 -7.9100e-01 + 4.3851e-01 -1.2355e+00 -7.9100e-01 + 4.6320e-01 -1.2264e+00 -7.9100e-01 + 4.8771e-01 -1.2169e+00 -7.9100e-01 + 4.8771e-01 -1.2169e+00 -7.9100e-01 + 5.0910e-01 -1.2703e+00 -6.9100e-01 + 5.3049e-01 -1.3237e+00 -5.9100e-01 + 5.0068e-01 -1.3352e+00 -5.9100e-01 + 4.7062e-01 -1.3461e+00 -5.9100e-01 + 4.4032e-01 -1.3563e+00 -5.9100e-01 + 4.0980e-01 -1.3658e+00 -5.9100e-01 + 3.7908e-01 -1.3747e+00 -5.9100e-01 + 3.4816e-01 -1.3828e+00 -5.9100e-01 + 3.1707e-01 -1.3903e+00 -5.9100e-01 + 2.8582e-01 -1.3971e+00 -5.9100e-01 + 2.5442e-01 -1.4031e+00 -5.9100e-01 + 2.2290e-01 -1.4085e+00 -5.9100e-01 + 1.9127e-01 -1.4131e+00 -5.9100e-01 + 1.5954e-01 -1.4170e+00 -5.9100e-01 + 1.2773e-01 -1.4203e+00 -5.9100e-01 + 9.5850e-02 -1.4228e+00 -5.9100e-01 + 6.3927e-02 -1.4246e+00 -5.9100e-01 + 3.1972e-02 -1.4256e+00 -5.9100e-01 + -2.6195e-16 -1.4260e+00 -5.9100e-01 + -2.5139e-16 -1.3685e+00 -6.9100e-01 + -2.4083e-16 -1.3110e+00 -7.9100e-01 + 9.2702e-01 -9.2702e-01 -7.9100e-01 + 9.4543e-01 -9.0823e-01 -7.9100e-01 + 9.6346e-01 -8.8909e-01 -7.9100e-01 + 9.8110e-01 -8.6958e-01 -7.9100e-01 + 9.9835e-01 -8.4972e-01 -7.9100e-01 + 1.0152e+00 -8.2952e-01 -7.9100e-01 + 1.0316e+00 -8.0899e-01 -7.9100e-01 + 1.0476e+00 -7.8813e-01 -7.9100e-01 + 1.0632e+00 -7.6696e-01 -7.9100e-01 + 1.0784e+00 -7.4547e-01 -7.9100e-01 + 1.0932e+00 -7.2369e-01 -7.9100e-01 + 1.1075e+00 -7.0161e-01 -7.9100e-01 + 1.1213e+00 -6.7926e-01 -7.9100e-01 + 1.1347e+00 -6.5663e-01 -7.9100e-01 + 1.1477e+00 -6.3373e-01 -7.9100e-01 + 1.1601e+00 -6.1058e-01 -7.9100e-01 + 1.1721e+00 -5.8718e-01 -7.9100e-01 + 1.1837e+00 -5.6355e-01 -7.9100e-01 + 1.1948e+00 -5.3969e-01 -7.9100e-01 + 1.2053e+00 -5.1562e-01 -7.9100e-01 + 1.2053e+00 -5.1562e-01 -7.9100e-01 + 1.2582e+00 -5.3823e-01 -6.9100e-01 + 1.3111e+00 -5.6085e-01 -5.9100e-01 + 1.2982e+00 -5.9010e-01 -5.9100e-01 + 1.2846e+00 -6.1906e-01 -5.9100e-01 + 1.2704e+00 -6.4770e-01 -5.9100e-01 + 1.2556e+00 -6.7602e-01 -5.9100e-01 + 1.2401e+00 -7.0400e-01 -5.9100e-01 + 1.2240e+00 -7.3163e-01 -5.9100e-01 + 1.2073e+00 -7.5889e-01 -5.9100e-01 + 1.1900e+00 -7.8577e-01 -5.9100e-01 + 1.1721e+00 -8.1225e-01 -5.9100e-01 + 1.1536e+00 -8.3832e-01 -5.9100e-01 + 1.1345e+00 -8.6398e-01 -5.9100e-01 + 1.1148e+00 -8.8919e-01 -5.9100e-01 + 1.0946e+00 -9.1397e-01 -5.9100e-01 + 1.0738e+00 -9.3828e-01 -5.9100e-01 + 1.0525e+00 -9.6212e-01 -5.9100e-01 + 1.0307e+00 -9.8547e-01 -5.9100e-01 + 1.0083e+00 -1.0083e+00 -5.9100e-01 + 9.6768e-01 -9.6768e-01 -6.9100e-01 + 9.2702e-01 -9.2702e-01 -7.9100e-01 diff --git a/src/ForcingTerms/coil_geometries/mastu_rmpu.dat b/src/ForcingTerms/coil_geometries/mastu_rmpu.dat index 59d20c96d..ba2a4e14f 100644 --- a/src/ForcingTerms/coil_geometries/mastu_rmpu.dat +++ b/src/ForcingTerms/coil_geometries/mastu_rmpu.dat @@ -1,169 +1,169 @@ - 4 1 42 1.00 - 1.4180e+00 0.0000e+00 7.6000e-01 - 1.4177e+00 3.0026e-02 7.6000e-01 - 1.4167e+00 6.0039e-02 7.6000e-01 - 1.4151e+00 9.0025e-02 7.6000e-01 - 1.4129e+00 1.1997e-01 7.6000e-01 - 1.4101e+00 1.4986e-01 7.6000e-01 - 1.4066e+00 1.7969e-01 7.6000e-01 - 1.4024e+00 2.0943e-01 7.6000e-01 - 1.3977e+00 2.3908e-01 7.6000e-01 - 1.3923e+00 2.6862e-01 7.6000e-01 - 1.3863e+00 2.9805e-01 7.6000e-01 - 1.3797e+00 3.2733e-01 7.6000e-01 - 1.3725e+00 3.5648e-01 7.6000e-01 - 1.3646e+00 3.8546e-01 7.6000e-01 - 1.3561e+00 4.1427e-01 7.6000e-01 - 1.3471e+00 4.4289e-01 7.6000e-01 - 1.3374e+00 4.7132e-01 7.6000e-01 - 1.3271e+00 4.9953e-01 7.6000e-01 - 1.3162e+00 5.2752e-01 7.6000e-01 - 1.3162e+00 5.2752e-01 7.6000e-01 - 1.3487e+00 5.4054e-01 6.2950e-01 - 1.3812e+00 5.5356e-01 4.9900e-01 - 1.3926e+00 5.2419e-01 4.9900e-01 - 1.4034e+00 4.9458e-01 4.9900e-01 - 1.4136e+00 4.6475e-01 4.9900e-01 - 1.4231e+00 4.3472e-01 4.9900e-01 - 1.4320e+00 4.0449e-01 4.9900e-01 - 1.4402e+00 3.7407e-01 4.9900e-01 - 1.4478e+00 3.4349e-01 4.9900e-01 - 1.4548e+00 3.1276e-01 4.9900e-01 - 1.4611e+00 2.8188e-01 4.9900e-01 - 1.4667e+00 2.5088e-01 4.9900e-01 - 1.4717e+00 2.1977e-01 4.9900e-01 - 1.4760e+00 1.8856e-01 4.9900e-01 - 1.4797e+00 1.5726e-01 4.9900e-01 - 1.4827e+00 1.2589e-01 4.9900e-01 - 1.4850e+00 9.4469e-02 4.9900e-01 - 1.4867e+00 6.3003e-02 4.9900e-01 - 1.4877e+00 3.1509e-02 4.9900e-01 - 1.4880e+00 0.0000e+00 4.9900e-01 - 1.4530e+00 0.0000e+00 6.2950e-01 - 1.4180e+00 0.0000e+00 7.6000e-01 - 8.6827e-17 1.4180e+00 7.6000e-01 - -3.0026e-02 1.4177e+00 7.6000e-01 - -6.0039e-02 1.4167e+00 7.6000e-01 - -9.0025e-02 1.4151e+00 7.6000e-01 - -1.1997e-01 1.4129e+00 7.6000e-01 - -1.4986e-01 1.4101e+00 7.6000e-01 - -1.7969e-01 1.4066e+00 7.6000e-01 - -2.0943e-01 1.4024e+00 7.6000e-01 - -2.3908e-01 1.3977e+00 7.6000e-01 - -2.6862e-01 1.3923e+00 7.6000e-01 - -2.9805e-01 1.3863e+00 7.6000e-01 - -3.2733e-01 1.3797e+00 7.6000e-01 - -3.5648e-01 1.3725e+00 7.6000e-01 - -3.8546e-01 1.3646e+00 7.6000e-01 - -4.1427e-01 1.3561e+00 7.6000e-01 - -4.4289e-01 1.3471e+00 7.6000e-01 - -4.7132e-01 1.3374e+00 7.6000e-01 - -4.9953e-01 1.3271e+00 7.6000e-01 - -5.2752e-01 1.3162e+00 7.6000e-01 - -5.2752e-01 1.3162e+00 7.6000e-01 - -5.4054e-01 1.3487e+00 6.2950e-01 - -5.5356e-01 1.3812e+00 4.9900e-01 - -5.2419e-01 1.3926e+00 4.9900e-01 - -4.9458e-01 1.4034e+00 4.9900e-01 - -4.6475e-01 1.4136e+00 4.9900e-01 - -4.3472e-01 1.4231e+00 4.9900e-01 - -4.0449e-01 1.4320e+00 4.9900e-01 - -3.7407e-01 1.4402e+00 4.9900e-01 - -3.4349e-01 1.4478e+00 4.9900e-01 - -3.1276e-01 1.4548e+00 4.9900e-01 - -2.8188e-01 1.4611e+00 4.9900e-01 - -2.5088e-01 1.4667e+00 4.9900e-01 - -2.1977e-01 1.4717e+00 4.9900e-01 - -1.8856e-01 1.4760e+00 4.9900e-01 - -1.5726e-01 1.4797e+00 4.9900e-01 - -1.2589e-01 1.4827e+00 4.9900e-01 - -9.4469e-02 1.4850e+00 4.9900e-01 - -6.3003e-02 1.4867e+00 4.9900e-01 - -3.1509e-02 1.4877e+00 4.9900e-01 - 9.1114e-17 1.4880e+00 4.9900e-01 - 8.8971e-17 1.4530e+00 6.2950e-01 - 8.6827e-17 1.4180e+00 7.6000e-01 - -1.4180e+00 1.7365e-16 7.6000e-01 - -1.4177e+00 -3.0026e-02 7.6000e-01 - -1.4167e+00 -6.0039e-02 7.6000e-01 - -1.4151e+00 -9.0025e-02 7.6000e-01 - -1.4129e+00 -1.1997e-01 7.6000e-01 - -1.4101e+00 -1.4986e-01 7.6000e-01 - -1.4066e+00 -1.7969e-01 7.6000e-01 - -1.4024e+00 -2.0943e-01 7.6000e-01 - -1.3977e+00 -2.3908e-01 7.6000e-01 - -1.3923e+00 -2.6862e-01 7.6000e-01 - -1.3863e+00 -2.9805e-01 7.6000e-01 - -1.3797e+00 -3.2733e-01 7.6000e-01 - -1.3725e+00 -3.5648e-01 7.6000e-01 - -1.3646e+00 -3.8546e-01 7.6000e-01 - -1.3561e+00 -4.1427e-01 7.6000e-01 - -1.3471e+00 -4.4289e-01 7.6000e-01 - -1.3374e+00 -4.7132e-01 7.6000e-01 - -1.3271e+00 -4.9953e-01 7.6000e-01 - -1.3162e+00 -5.2752e-01 7.6000e-01 - -1.3162e+00 -5.2752e-01 7.6000e-01 - -1.3487e+00 -5.4054e-01 6.2950e-01 - -1.3812e+00 -5.5356e-01 4.9900e-01 - -1.3926e+00 -5.2419e-01 4.9900e-01 - -1.4034e+00 -4.9458e-01 4.9900e-01 - -1.4136e+00 -4.6475e-01 4.9900e-01 - -1.4231e+00 -4.3472e-01 4.9900e-01 - -1.4320e+00 -4.0449e-01 4.9900e-01 - -1.4402e+00 -3.7407e-01 4.9900e-01 - -1.4478e+00 -3.4349e-01 4.9900e-01 - -1.4548e+00 -3.1276e-01 4.9900e-01 - -1.4611e+00 -2.8188e-01 4.9900e-01 - -1.4667e+00 -2.5088e-01 4.9900e-01 - -1.4717e+00 -2.1977e-01 4.9900e-01 - -1.4760e+00 -1.8856e-01 4.9900e-01 - -1.4797e+00 -1.5726e-01 4.9900e-01 - -1.4827e+00 -1.2589e-01 4.9900e-01 - -1.4850e+00 -9.4469e-02 4.9900e-01 - -1.4867e+00 -6.3003e-02 4.9900e-01 - -1.4877e+00 -3.1509e-02 4.9900e-01 - -1.4880e+00 1.8223e-16 4.9900e-01 - -1.4530e+00 1.7794e-16 6.2950e-01 - -1.4180e+00 1.7365e-16 7.6000e-01 - -2.6048e-16 -1.4180e+00 7.6000e-01 - 3.0026e-02 -1.4177e+00 7.6000e-01 - 6.0039e-02 -1.4167e+00 7.6000e-01 - 9.0025e-02 -1.4151e+00 7.6000e-01 - 1.1997e-01 -1.4129e+00 7.6000e-01 - 1.4986e-01 -1.4101e+00 7.6000e-01 - 1.7969e-01 -1.4066e+00 7.6000e-01 - 2.0943e-01 -1.4024e+00 7.6000e-01 - 2.3908e-01 -1.3977e+00 7.6000e-01 - 2.6862e-01 -1.3923e+00 7.6000e-01 - 2.9805e-01 -1.3863e+00 7.6000e-01 - 3.2733e-01 -1.3797e+00 7.6000e-01 - 3.5648e-01 -1.3725e+00 7.6000e-01 - 3.8546e-01 -1.3646e+00 7.6000e-01 - 4.1427e-01 -1.3561e+00 7.6000e-01 - 4.4289e-01 -1.3471e+00 7.6000e-01 - 4.7132e-01 -1.3374e+00 7.6000e-01 - 4.9953e-01 -1.3271e+00 7.6000e-01 - 5.2752e-01 -1.3162e+00 7.6000e-01 - 5.2752e-01 -1.3162e+00 7.6000e-01 - 5.4054e-01 -1.3487e+00 6.2950e-01 - 5.5356e-01 -1.3812e+00 4.9900e-01 - 5.2419e-01 -1.3926e+00 4.9900e-01 - 4.9458e-01 -1.4034e+00 4.9900e-01 - 4.6475e-01 -1.4136e+00 4.9900e-01 - 4.3472e-01 -1.4231e+00 4.9900e-01 - 4.0449e-01 -1.4320e+00 4.9900e-01 - 3.7407e-01 -1.4402e+00 4.9900e-01 - 3.4349e-01 -1.4478e+00 4.9900e-01 - 3.1276e-01 -1.4548e+00 4.9900e-01 - 2.8188e-01 -1.4611e+00 4.9900e-01 - 2.5088e-01 -1.4667e+00 4.9900e-01 - 2.1977e-01 -1.4717e+00 4.9900e-01 - 1.8856e-01 -1.4760e+00 4.9900e-01 - 1.5726e-01 -1.4797e+00 4.9900e-01 - 1.2589e-01 -1.4827e+00 4.9900e-01 - 9.4469e-02 -1.4850e+00 4.9900e-01 - 6.3003e-02 -1.4867e+00 4.9900e-01 - 3.1509e-02 -1.4877e+00 4.9900e-01 - -2.7334e-16 -1.4880e+00 4.9900e-01 - -2.6691e-16 -1.4530e+00 6.2950e-01 - -2.6048e-16 -1.4180e+00 7.6000e-01 + 4 1 42 1.00 + 1.4180e+00 0.0000e+00 7.6000e-01 + 1.4177e+00 3.0026e-02 7.6000e-01 + 1.4167e+00 6.0039e-02 7.6000e-01 + 1.4151e+00 9.0025e-02 7.6000e-01 + 1.4129e+00 1.1997e-01 7.6000e-01 + 1.4101e+00 1.4986e-01 7.6000e-01 + 1.4066e+00 1.7969e-01 7.6000e-01 + 1.4024e+00 2.0943e-01 7.6000e-01 + 1.3977e+00 2.3908e-01 7.6000e-01 + 1.3923e+00 2.6862e-01 7.6000e-01 + 1.3863e+00 2.9805e-01 7.6000e-01 + 1.3797e+00 3.2733e-01 7.6000e-01 + 1.3725e+00 3.5648e-01 7.6000e-01 + 1.3646e+00 3.8546e-01 7.6000e-01 + 1.3561e+00 4.1427e-01 7.6000e-01 + 1.3471e+00 4.4289e-01 7.6000e-01 + 1.3374e+00 4.7132e-01 7.6000e-01 + 1.3271e+00 4.9953e-01 7.6000e-01 + 1.3162e+00 5.2752e-01 7.6000e-01 + 1.3162e+00 5.2752e-01 7.6000e-01 + 1.3487e+00 5.4054e-01 6.2950e-01 + 1.3812e+00 5.5356e-01 4.9900e-01 + 1.3926e+00 5.2419e-01 4.9900e-01 + 1.4034e+00 4.9458e-01 4.9900e-01 + 1.4136e+00 4.6475e-01 4.9900e-01 + 1.4231e+00 4.3472e-01 4.9900e-01 + 1.4320e+00 4.0449e-01 4.9900e-01 + 1.4402e+00 3.7407e-01 4.9900e-01 + 1.4478e+00 3.4349e-01 4.9900e-01 + 1.4548e+00 3.1276e-01 4.9900e-01 + 1.4611e+00 2.8188e-01 4.9900e-01 + 1.4667e+00 2.5088e-01 4.9900e-01 + 1.4717e+00 2.1977e-01 4.9900e-01 + 1.4760e+00 1.8856e-01 4.9900e-01 + 1.4797e+00 1.5726e-01 4.9900e-01 + 1.4827e+00 1.2589e-01 4.9900e-01 + 1.4850e+00 9.4469e-02 4.9900e-01 + 1.4867e+00 6.3003e-02 4.9900e-01 + 1.4877e+00 3.1509e-02 4.9900e-01 + 1.4880e+00 0.0000e+00 4.9900e-01 + 1.4530e+00 0.0000e+00 6.2950e-01 + 1.4180e+00 0.0000e+00 7.6000e-01 + 8.6827e-17 1.4180e+00 7.6000e-01 + -3.0026e-02 1.4177e+00 7.6000e-01 + -6.0039e-02 1.4167e+00 7.6000e-01 + -9.0025e-02 1.4151e+00 7.6000e-01 + -1.1997e-01 1.4129e+00 7.6000e-01 + -1.4986e-01 1.4101e+00 7.6000e-01 + -1.7969e-01 1.4066e+00 7.6000e-01 + -2.0943e-01 1.4024e+00 7.6000e-01 + -2.3908e-01 1.3977e+00 7.6000e-01 + -2.6862e-01 1.3923e+00 7.6000e-01 + -2.9805e-01 1.3863e+00 7.6000e-01 + -3.2733e-01 1.3797e+00 7.6000e-01 + -3.5648e-01 1.3725e+00 7.6000e-01 + -3.8546e-01 1.3646e+00 7.6000e-01 + -4.1427e-01 1.3561e+00 7.6000e-01 + -4.4289e-01 1.3471e+00 7.6000e-01 + -4.7132e-01 1.3374e+00 7.6000e-01 + -4.9953e-01 1.3271e+00 7.6000e-01 + -5.2752e-01 1.3162e+00 7.6000e-01 + -5.2752e-01 1.3162e+00 7.6000e-01 + -5.4054e-01 1.3487e+00 6.2950e-01 + -5.5356e-01 1.3812e+00 4.9900e-01 + -5.2419e-01 1.3926e+00 4.9900e-01 + -4.9458e-01 1.4034e+00 4.9900e-01 + -4.6475e-01 1.4136e+00 4.9900e-01 + -4.3472e-01 1.4231e+00 4.9900e-01 + -4.0449e-01 1.4320e+00 4.9900e-01 + -3.7407e-01 1.4402e+00 4.9900e-01 + -3.4349e-01 1.4478e+00 4.9900e-01 + -3.1276e-01 1.4548e+00 4.9900e-01 + -2.8188e-01 1.4611e+00 4.9900e-01 + -2.5088e-01 1.4667e+00 4.9900e-01 + -2.1977e-01 1.4717e+00 4.9900e-01 + -1.8856e-01 1.4760e+00 4.9900e-01 + -1.5726e-01 1.4797e+00 4.9900e-01 + -1.2589e-01 1.4827e+00 4.9900e-01 + -9.4469e-02 1.4850e+00 4.9900e-01 + -6.3003e-02 1.4867e+00 4.9900e-01 + -3.1509e-02 1.4877e+00 4.9900e-01 + 9.1114e-17 1.4880e+00 4.9900e-01 + 8.8971e-17 1.4530e+00 6.2950e-01 + 8.6827e-17 1.4180e+00 7.6000e-01 + -1.4180e+00 1.7365e-16 7.6000e-01 + -1.4177e+00 -3.0026e-02 7.6000e-01 + -1.4167e+00 -6.0039e-02 7.6000e-01 + -1.4151e+00 -9.0025e-02 7.6000e-01 + -1.4129e+00 -1.1997e-01 7.6000e-01 + -1.4101e+00 -1.4986e-01 7.6000e-01 + -1.4066e+00 -1.7969e-01 7.6000e-01 + -1.4024e+00 -2.0943e-01 7.6000e-01 + -1.3977e+00 -2.3908e-01 7.6000e-01 + -1.3923e+00 -2.6862e-01 7.6000e-01 + -1.3863e+00 -2.9805e-01 7.6000e-01 + -1.3797e+00 -3.2733e-01 7.6000e-01 + -1.3725e+00 -3.5648e-01 7.6000e-01 + -1.3646e+00 -3.8546e-01 7.6000e-01 + -1.3561e+00 -4.1427e-01 7.6000e-01 + -1.3471e+00 -4.4289e-01 7.6000e-01 + -1.3374e+00 -4.7132e-01 7.6000e-01 + -1.3271e+00 -4.9953e-01 7.6000e-01 + -1.3162e+00 -5.2752e-01 7.6000e-01 + -1.3162e+00 -5.2752e-01 7.6000e-01 + -1.3487e+00 -5.4054e-01 6.2950e-01 + -1.3812e+00 -5.5356e-01 4.9900e-01 + -1.3926e+00 -5.2419e-01 4.9900e-01 + -1.4034e+00 -4.9458e-01 4.9900e-01 + -1.4136e+00 -4.6475e-01 4.9900e-01 + -1.4231e+00 -4.3472e-01 4.9900e-01 + -1.4320e+00 -4.0449e-01 4.9900e-01 + -1.4402e+00 -3.7407e-01 4.9900e-01 + -1.4478e+00 -3.4349e-01 4.9900e-01 + -1.4548e+00 -3.1276e-01 4.9900e-01 + -1.4611e+00 -2.8188e-01 4.9900e-01 + -1.4667e+00 -2.5088e-01 4.9900e-01 + -1.4717e+00 -2.1977e-01 4.9900e-01 + -1.4760e+00 -1.8856e-01 4.9900e-01 + -1.4797e+00 -1.5726e-01 4.9900e-01 + -1.4827e+00 -1.2589e-01 4.9900e-01 + -1.4850e+00 -9.4469e-02 4.9900e-01 + -1.4867e+00 -6.3003e-02 4.9900e-01 + -1.4877e+00 -3.1509e-02 4.9900e-01 + -1.4880e+00 1.8223e-16 4.9900e-01 + -1.4530e+00 1.7794e-16 6.2950e-01 + -1.4180e+00 1.7365e-16 7.6000e-01 + -2.6048e-16 -1.4180e+00 7.6000e-01 + 3.0026e-02 -1.4177e+00 7.6000e-01 + 6.0039e-02 -1.4167e+00 7.6000e-01 + 9.0025e-02 -1.4151e+00 7.6000e-01 + 1.1997e-01 -1.4129e+00 7.6000e-01 + 1.4986e-01 -1.4101e+00 7.6000e-01 + 1.7969e-01 -1.4066e+00 7.6000e-01 + 2.0943e-01 -1.4024e+00 7.6000e-01 + 2.3908e-01 -1.3977e+00 7.6000e-01 + 2.6862e-01 -1.3923e+00 7.6000e-01 + 2.9805e-01 -1.3863e+00 7.6000e-01 + 3.2733e-01 -1.3797e+00 7.6000e-01 + 3.5648e-01 -1.3725e+00 7.6000e-01 + 3.8546e-01 -1.3646e+00 7.6000e-01 + 4.1427e-01 -1.3561e+00 7.6000e-01 + 4.4289e-01 -1.3471e+00 7.6000e-01 + 4.7132e-01 -1.3374e+00 7.6000e-01 + 4.9953e-01 -1.3271e+00 7.6000e-01 + 5.2752e-01 -1.3162e+00 7.6000e-01 + 5.2752e-01 -1.3162e+00 7.6000e-01 + 5.4054e-01 -1.3487e+00 6.2950e-01 + 5.5356e-01 -1.3812e+00 4.9900e-01 + 5.2419e-01 -1.3926e+00 4.9900e-01 + 4.9458e-01 -1.4034e+00 4.9900e-01 + 4.6475e-01 -1.4136e+00 4.9900e-01 + 4.3472e-01 -1.4231e+00 4.9900e-01 + 4.0449e-01 -1.4320e+00 4.9900e-01 + 3.7407e-01 -1.4402e+00 4.9900e-01 + 3.4349e-01 -1.4478e+00 4.9900e-01 + 3.1276e-01 -1.4548e+00 4.9900e-01 + 2.8188e-01 -1.4611e+00 4.9900e-01 + 2.5088e-01 -1.4667e+00 4.9900e-01 + 2.1977e-01 -1.4717e+00 4.9900e-01 + 1.8856e-01 -1.4760e+00 4.9900e-01 + 1.5726e-01 -1.4797e+00 4.9900e-01 + 1.2589e-01 -1.4827e+00 4.9900e-01 + 9.4469e-02 -1.4850e+00 4.9900e-01 + 6.3003e-02 -1.4867e+00 4.9900e-01 + 3.1509e-02 -1.4877e+00 4.9900e-01 + -2.7334e-16 -1.4880e+00 4.9900e-01 + -2.6691e-16 -1.4530e+00 6.2950e-01 + -2.6048e-16 -1.4180e+00 7.6000e-01 diff --git a/src/InnerLayer/GGJ/Galerkin.jl b/src/InnerLayer/GGJ/Galerkin.jl index 7cd422f40..1fa75c240 100644 --- a/src/InnerLayer/GGJ/Galerkin.jl +++ b/src/InnerLayer/GGJ/Galerkin.jl @@ -604,7 +604,7 @@ function _parity_bcs_and_solve!(ws::GalerkinWorkspace, params::GGJParameters, Q: if i > ws.ndim continue end - for jj in max(1, i-ws.kl):min(ws.ndim, i+ws.kl) + for jj in max(1, i - ws.kl):min(ws.ndim, i + ws.kl) ws.mat[offset+i-jj, jj, isol] = 0 end end diff --git a/src/InnerLayer/GGJ/Ray.jl b/src/InnerLayer/GGJ/Ray.jl index 0abe74451..32136da91 100644 --- a/src/InnerLayer/GGJ/Ray.jl +++ b/src/InnerLayer/GGJ/Ray.jl @@ -355,7 +355,7 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; local Us, Ub, E, bc_cond, Sbvp if s_m < 0.98 * Sv - UsS, UbS = handoff === nothing ? _power_states(cache, cis(θ) * Sv) : handoff + UsS, UbS = handoff === nothing ? _power_states(cache, cis(θ) * Sv) : handoff Us, Ub, E = march_boundary(params, Q, θ, Sv, s_m, UsS, UbS; rtol=march_rtol, growth=growth, seed=seed, ztrk=ztrk, purge_budget=purge_budget, dp_res=dp_res) @@ -370,7 +370,9 @@ function solve_ray(params::GGJParameters, Q::ComplexF64; bc_cond < 1e12 || @warn "boundary basis poorly conditioned (cond ≈ $bc_cond)" breaks = ray_breaks(params, Q, θ, Sbvp; cfl=cfl, min_cells=min_cells) - length(breaks) - 1 > warn_cells && @warn "GGJ ray: $(length(breaks) - 1) Hermite cells exceed warn_cells = $warn_cells, so the solve is slow; the grid follows cfl = $cfl, min_cells = $min_cells and the local rates at this Q" Q maxlog = 1 _id = (:ggj_ray_cells, warn_cells) + length(breaks) - 1 > warn_cells && + @warn "GGJ ray: $(length(breaks) - 1) Hermite cells exceed warn_cells = $warn_cells, so the solve is slow; the grid follows cfl = $cfl, min_cells = $min_cells and the local rates at this Q" Q maxlog = + 1 _id = (:ggj_ray_cells, warn_cells) ws = _galerkin_workspace(breaks, fill(CT_NONE, length(breaks) - 1)) Δraw, cexp = _assemble_and_solve_point!(ws, params, Q, θ, Us, Ub, E; nq=nq) verbose && @printf(" BVP: %d Hermite cells on [0, %.4g], Δraw[1] = %.6e %+.6eim\n", diff --git a/src/InnerLayer/SLAYER/LayerInputs.jl b/src/InnerLayer/SLAYER/LayerInputs.jl index 2cfef836b..3a77f7fd8 100644 --- a/src/InnerLayer/SLAYER/LayerInputs.jl +++ b/src/InnerLayer/SLAYER/LayerInputs.jl @@ -395,7 +395,7 @@ function build_slayer_inputs(equil, sings, profiles::KineticProfiles; @warn( "build_slayer_inputs: sing.restype not populated; using the " * "slab Mercier exponent α = 1/2 for the Δ' reference-length " * - "conversion at all such surfaces.", maxlog=1) + "conversion at all such surfaces.", maxlog = 1) 0.5 else sqrt(max(-(rg.E + rg.F + rg.H - 0.25), 0.0)) diff --git a/src/InnerLayer/SLAYER/LayerParameters.jl b/src/InnerLayer/SLAYER/LayerParameters.jl index a48b88b19..639d4fd8f 100644 --- a/src/InnerLayer/SLAYER/LayerParameters.jl +++ b/src/InnerLayer/SLAYER/LayerParameters.jl @@ -218,6 +218,7 @@ model does not use may be left `nothing`; one it uses must be given, positive an # Arguments - `n_e` -- electron density in m⁻³ + - `t_e`, `t_i` -- electron and ion temperatures in eV - `omega_e`, `omega_i` -- electron and ion diamagnetic frequencies in rad/s - `qval` -- safety factor at the surface @@ -234,6 +235,7 @@ model does not use may be left `nothing`; one it uses must be given, positive an - `a_minor` -- plasma minor radius `a` in m; needed by `:tau_E` - `dlnn`, `dlnTe`, `dlnTi` -- radial log-gradients of n, T_e, T_i in any common radial variable (only ratios enter); needed by `:D_perp` - `P_perp_model` -- how `P_perp` is built (default `:D_perp`, as in the `[SLAYER]` deck): + + `:D_perp` -- τ_R/τ_⊥ with τ_⊥ = r_s²/D_⊥, Fitzpatrick, Phys. Plasmas 29, 032507 (2022), Eq. 16 (with Eqs. 4-6 and η_⊥ = η_∥); its τ = (T_e/T_i)(1+η_e)/(1+η_i) is the inverse of the `tau` field; flat temperatures give the `:c_beta` value + `:chi_perp_e`, `:chi_perp_i` -- τ_R·χ⊥/r_s² with the electron or ion χ⊥ @@ -363,8 +365,12 @@ function slayer_parameters(; all(x -> x !== nothing && isfinite(x), (dlnn, dlnTe, dlnTi)) || throw(ArgumentError("slayer_parameters: P_perp_model=:D_perp needs finite dlnn, dlnTe and dlnTi; got $dlnn, $dlnTe, $dlnTi")) dp = t_e * (dlnn + dlnTe) + t_i * (dlnn + dlnTi) - dp != 0 || throw(ArgumentError("slayer_parameters: P_perp_model=:D_perp is undefined where the pressure gradient vanishes " * - "(t_e(dlnn+dlnTe) + t_i(dlnn+dlnTi) = 0); choose another P_perp_model for this surface")) + dp != 0 || throw( + ArgumentError( + "slayer_parameters: P_perp_model=:D_perp is undefined where the pressure gradient vanishes " * + "(t_e(dlnn+dlnTe) + t_i(dlnn+dlnTi) = 0); choose another P_perp_model for this surface" + ) + ) D_perp = c_beta^2 * eta / MU_0 + (2 / 3) * (1 - c_beta^2) * (t_e * dlnTe * chi_perp_e + t_i * dlnTi * chi_perp_i) / dp tau_r / (rs^2 / D_perp) @@ -375,8 +381,12 @@ function slayer_parameters(; "Allowed: $(ALLOWED_P_PERP_MODELS)")) end isfinite(P_perp) && P_perp > 0 || - throw(ArgumentError("slayer_parameters: P_perp_model=:$P_perp_model gave P_perp=$P_perp; check its inputs " * - "(chi_perp_e=$chi_perp_e, chi_perp_i=$chi_perp_i, dlnn=$dlnn, dlnTe=$dlnTe, dlnTi=$dlnTi)")) + throw( + ArgumentError( + "slayer_parameters: P_perp_model=:$P_perp_model gave P_perp=$P_perp; check its inputs " * + "(chi_perp_e=$chi_perp_e, chi_perp_i=$chi_perp_i, dlnn=$dlnn, dlnTe=$dlnTe, dlnTi=$dlnTi)" + ) + ) # Normalized beta-related width and Δ-normalization d_beta = c_beta * d_i diff --git a/src/KineticForces/KineticForces.jl b/src/KineticForces/KineticForces.jl index 154975ca8..26b2c4c4e 100644 --- a/src/KineticForces/KineticForces.jl +++ b/src/KineticForces/KineticForces.jl @@ -41,11 +41,11 @@ include("CalculatedKineticMatrices.jl") # Global constants const mp = 1.672_614e-27 # proton mass (kg) const me = 9.109_1e-31 # electron mass (kg) -const e = 1.602_191_7e-19 # elementary charge (C) +const e = 1.602_191_7e-19 # elementary charge (C) const eV = e # joules per electron-volt const twopi = 2π -const μ₀ = 4e-7 * π +const μ₀ = 4e-7 * π const rad2deg = 180 / π const deg2rad = π / 180 diff --git a/src/KineticForces/Output.jl b/src/KineticForces/Output.jl index 10b55dcb3..4810d1d8a 100644 --- a/src/KineticForces/Output.jl +++ b/src/KineticForces/Output.jl @@ -119,7 +119,12 @@ const KF_METHOD_H5_ANNOTATIONS = [ "dTdpsi" => (; long_name="complex torque density dT/dψ_N = dT_φ/dψ_N + 2i·n·dδW_k/dψ_N; divide by dVdpsi for dT/dV", units="N*m", dims=("psi",), attach=(1 => "psi",)), "T" => (; long_name="cumulative complex torque T(ψ_N) = T_φ + 2i·n·δW_k (trapezoidal)", units="N*m", dims=("psi",), attach=(1 => "psi",)), "ell" => (; long_name="bounce harmonic ℓ ∈ -nl:nl of the per-harmonic torque density", scale="ell"), - "dTdpsi_ell" => (; long_name="complex torque density dT/dψ_N resolved by bounce harmonic ℓ; summing over ℓ reproduces dTdpsi", units="N*m", dims=("psi", "ell"), attach=(1 => "psi", 2 => "ell")), + "dTdpsi_ell" => (; + long_name="complex torque density dT/dψ_N resolved by bounce harmonic ℓ; summing over ℓ reproduces dTdpsi", + units="N*m", + dims=("psi", "ell"), + attach=(1 => "psi", 2 => "ell") + ), "dVdpsi" => (; long_name="flux-surface volume derivative dV/dψ_N at quadrature points", units="m^3", dims=("psi",), attach=(1 => "psi",)), "KineticMatrices/A" => (; long_name="Logan 2015 drift-kinetic coefficient matrix A = W_Z†W_Z (energy normalization)", dims=("mode_row", "mode_col")), "KineticMatrices/B" => (; long_name="Logan 2015 drift-kinetic coefficient matrix B = W_Z†W_X (energy normalization)", dims=("mode_row", "mode_col")), diff --git a/src/KineticForces/Torque.jl b/src/KineticForces/Torque.jl index 597b9fc9b..ff3b38aaf 100644 --- a/src/KineticForces/Torque.jl +++ b/src/KineticForces/Torque.jl @@ -28,7 +28,6 @@ Toroidal torque from nonambipolar transport at one ψ and bounce harmonic `l`, w - `op_wmats::Array{ComplexF64,3}`: Store ForceFreeStates matrix elements - `surface`: Per-surface bundle from `_torque_surface`, shared across the bounce harmonics of one ψ; built here when not given - """ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int, zi::Int, mi::Int, wdfac::Float64, divxfac::Float64, diff --git a/src/KineticForces/Utils.jl b/src/KineticForces/Utils.jl index 2d760e406..0f17f7925 100644 --- a/src/KineticForces/Utils.jl +++ b/src/KineticForces/Utils.jl @@ -136,7 +136,7 @@ function kinetic_axis_validity_psi(kinetic_profiles::Equilibrium.KineticProfileS end end psi_outer > 0 && @warn "kinetic_axis_validity_psi: orbit widths also reach ⟨r⟩ out to ψ=$(round(psi_outer; sigdigits=3)), " * - "outside the axis-contiguous region ending at ψ_c=$(round(psi_c; sigdigits=3)); only the latter is suppressed" maxlog = 1 + "outside the axis-contiguous region ending at ψ_c=$(round(psi_c; sigdigits=3)); only the latter is suppressed" maxlog = 1 return psi_c end @@ -354,9 +354,12 @@ function resonance_grid_nodes(ctrl, kf_ctrl::KineticForcesControl, kinetic_profi (ForceFreeStates.kinetic_source(ctrl.kinetic) isa KineticForcesControl && kinetic_profiles !== nothing) || return nodes for n_res in intr.nlow:intr.nhigh n_res == 0 && continue - append!(nodes, kinetic_resonance_psi_nodes(kinetic_profiles, equil; - n=n_res, nl=kf_ctrl.bounce_harmonic_max, zi=main_ion(equil)[1], mi=main_ion(equil)[2], - electron=kf_ctrl.electron, wdfac=kf_ctrl.magnetic_drift_factor)) + append!( + nodes, + kinetic_resonance_psi_nodes(kinetic_profiles, equil; + n=n_res, nl=kf_ctrl.bounce_harmonic_max, zi=main_ion(equil)[1], mi=main_ion(equil)[2], + electron=kf_ctrl.electron, wdfac=kf_ctrl.magnetic_drift_factor) + ) end psi_c = axis_validity_boundary(kf_ctrl, species, kinetic_profiles, equil, rationals) psi_c > 0 && filter!(p -> p > psi_c, nodes) diff --git a/src/LocalStability/Ballooning.jl b/src/LocalStability/Ballooning.jl index 6b989a705..2c8470f00 100644 --- a/src/LocalStability/Ballooning.jl +++ b/src/LocalStability/Ballooning.jl @@ -714,17 +714,18 @@ function ballooning_alpha_crossings( ref = salpha_reference(psi_idx, plasma_eq) # Δ' vs α scaling at fixed shear; a failed evaluation (extreme corrections) returns NaN and is not a crossing. - delta_at(scale) = try - ballooning_delta_prime( - psi_idx, - plasma_eq; - corr_qprime=0.0, - corr_pprime=ref.pprime_norm_ref * (scale - 1.0), - theta_k=theta_k - ).delta_prime - catch - NaN - end + delta_at(scale) = + try + ballooning_delta_prime( + psi_idx, + plasma_eq; + corr_qprime=0.0, + corr_pprime=ref.pprime_norm_ref * (scale - 1.0), + theta_k=theta_k + ).delta_prime + catch + NaN + end samples = collect(range(0.0, max_alpha_scale; length=n_scan + 1)) scales = _ballooning_marginal_crossings(delta_at, samples, tol; max_crossings=max_crossings) @@ -896,7 +897,7 @@ function ballooning_alpha_boundaries( length(cr.alphas) >= 2 && (alpha_critical2[i] = cr.alphas[2]) catch err if verbose - @warn "ballooning alpha boundaries failed" psi_idx=i exception=err + @warn "ballooning alpha boundaries failed" psi_idx = i exception = err end end end @@ -930,17 +931,18 @@ function ballooning_qprime_crossings( ref = salpha_reference(psi_idx, plasma_eq) # Δ' vs q' scaling at the experimental pressure gradient; a failed evaluation returns NaN and is not a crossing. - delta_at(scale) = try - ballooning_delta_prime( - psi_idx, - plasma_eq; - corr_qprime=ref.qprime_norm_ref * (scale - 1.0), - corr_pprime=0.0, - theta_k=theta_k - ).delta_prime - catch - NaN - end + delta_at(scale) = + try + ballooning_delta_prime( + psi_idx, + plasma_eq; + corr_qprime=ref.qprime_norm_ref * (scale - 1.0), + corr_pprime=0.0, + theta_k=theta_k + ).delta_prime + catch + NaN + end samples = collect(range(max_qprime_scale, min_qprime_scale; length=n_scan + 1)) scales = _ballooning_marginal_crossings(delta_at, samples, tol) @@ -985,7 +987,7 @@ function ballooning_qprime_boundaries( length(cr.qprimes) >= 2 && (qprime_critical2[i] = cr.qprimes[2]) catch err if verbose - @warn "ballooning qprime boundaries failed" psi_idx=i exception=err + @warn "ballooning qprime boundaries failed" psi_idx = i exception = err end end end @@ -1029,7 +1031,7 @@ function ballooning_delta_prime_map( delta_prime[k, :] .= vec(res.delta_prime) catch err if verbose - @warn "ballooning delta-prime map failed" psi_idx=i exception=err + @warn "ballooning delta-prime map failed" psi_idx = i exception = err end end end @@ -1076,7 +1078,7 @@ function ballooning_qprime_delta_prime_map( delta_prime[k, :] .= vec(res.delta_prime) catch err if verbose - @warn "ballooning qprime delta-prime map failed" psi_idx=i exception=err + @warn "ballooning qprime delta-prime map failed" psi_idx = i exception = err end end end diff --git a/src/PerturbedEquilibrium/PerturbedEquilibrium.jl b/src/PerturbedEquilibrium/PerturbedEquilibrium.jl index b930fabcf..2beaa5916 100644 --- a/src/PerturbedEquilibrium/PerturbedEquilibrium.jl +++ b/src/PerturbedEquilibrium/PerturbedEquilibrium.jl @@ -58,8 +58,10 @@ surface inductance is free-space, and the response needs Λ from the same no-wal function plasma_response(ffs::ForceFreeStatesResult; compute_singular_coupling::Bool=true, compute_torque_response::Bool=false, verbose::Bool=false)::PlasmaResponse ffs.wall_settings === nothing || - error("plasma_response needs a force-free-states solve without a wall: its surface inductance L is free-space, " * - "so Λ from a wall run would mix two vacuum models. Solve with wall=nothing (no [Wall] section).") + error( + "plasma_response needs a force-free-states solve without a wall: its surface inductance L is free-space, " * + "so Λ from a wall run would mix two vacuum models. Solve with wall=nothing (no [Wall] section)." + ) # Galerkin and matched results publish no plasma edge response wp, so no operator could be built. if ffs.free_boundary === nothing && (ffs.integrator === :galerkin || ffs.closure === :matched) error("plasma_response needs the free-boundary δW, which a $(ffs.integrator) result with $(ffs.closure) closure " * diff --git a/src/PerturbedEquilibrium/ResonantCoupling.jl b/src/PerturbedEquilibrium/ResonantCoupling.jl index 9a786a7e0..4ba63adbe 100644 --- a/src/PerturbedEquilibrium/ResonantCoupling.jl +++ b/src/PerturbedEquilibrium/ResonantCoupling.jl @@ -126,9 +126,13 @@ no basis, which is the bare-matrix construction. function check_mode_basis(dom::DominantCoupling, m_modes::AbstractVector{Int}, n_modes::AbstractVector{Int}, what::AbstractString) isempty(dom.m_modes) && return nothing (dom.m_modes == m_modes && dom.n_modes == n_modes) && return nothing - throw(ArgumentError("$what: the decomposition is on a different (m, n) basis than the spectrum — " * - "m $(extrema(dom.m_modes)) vs $(extrema(m_modes)), n $(extrema(dom.n_modes)) vs $(extrema(n_modes)). " * - "Decompose the same ResonantCoupling the spectrum was built from.")) + throw( + ArgumentError( + "$what: the decomposition is on a different (m, n) basis than the spectrum — " * + "m $(extrema(dom.m_modes)) vs $(extrema(m_modes)), n $(extrema(dom.n_modes)) vs $(extrema(n_modes)). " * + "Decompose the same ResonantCoupling the spectrum was built from." + ) + ) end """ diff --git a/src/PerturbedEquilibrium/Response.jl b/src/PerturbedEquilibrium/Response.jl index 539b9f57c..1d3c3ce17 100644 --- a/src/PerturbedEquilibrium/Response.jl +++ b/src/PerturbedEquilibrium/Response.jl @@ -92,7 +92,7 @@ function apply_response!(state::PerturbedEquilibriumState; verbose::Bool=false) py = zero(ComplexF64) state.toroidal_torque = 0.0 for (in, nn) in enumerate(ffs.nlow:ffs.nhigh) - blk = ((in - 1) * ffs.mpert + 1):(in * ffs.mpert) + blk = ((in-1)*ffs.mpert+1):(in*ffs.mpert) Φ_n = response_flux[blk] py_n = dot(Φ_n, inv(plasma_inductance[blk, blk]) * Φ_n) / 4 py += py_n diff --git a/src/PerturbedEquilibrium/SingularCoupling.jl b/src/PerturbedEquilibrium/SingularCoupling.jl index 084aa0e16..ac1f26afb 100644 --- a/src/PerturbedEquilibrium/SingularCoupling.jl +++ b/src/PerturbedEquilibrium/SingularCoupling.jl @@ -129,7 +129,7 @@ function _solution_at( # Same-side candidate nodes around the bracket, trimmed to the 4 nearest psi. side = sign(psi - psi_surf) - idxs = [j for j in max(1, il-3):min(nstep, ir+3) if sign(odet.psi_store[j] - psi_surf) == side] + idxs = [j for j in max(1, il - 3):min(nstep, ir + 3) if sign(odet.psi_store[j] - psi_surf) == side] while length(idxs) > 4 abs(odet.psi_store[idxs[1]] - psi) > abs(odet.psi_store[idxs[end]] - psi) ? popfirst!(idxs) : pop!(idxs) end @@ -284,7 +284,7 @@ function build_coupling_operators!(resp::PlasmaResponse; verbose::Bool=false) resp.C_penetrated_area_weighted_field = zeros(ComplexF64, n_rational, numpert_total) else resp.C_penetrated_area_weighted_field = zeros(ComplexF64, 0, 0) - @warn "No inner-layer B_pen supplied; penetrated field not computed." maxlog=1 + @warn "No inner-layer B_pen supplied; penetrated field not computed." maxlog = 1 end resp.C_delta_prime = zeros(ComplexF64, n_rational, numpert_total) resp.rational_psi = zeros(Float64, n_rational) diff --git a/src/Tearing/CriticalResonantField/TorqueBalance.jl b/src/Tearing/CriticalResonantField/TorqueBalance.jl index dee4a9968..3933652d8 100644 --- a/src/Tearing/CriticalResonantField/TorqueBalance.jl +++ b/src/Tearing/CriticalResonantField/TorqueBalance.jl @@ -107,7 +107,7 @@ function torque_balance_scan(tb::TorqueBalance; Qmin=nothing, Qmax=nothing, n::I # Follow the first resolved interior maximum without joining samples across excluded intervals. path = [i for i in sort(eachindex(Qs); by=i -> abs(Qs[i] - Qa)) - if min(Qa, Qb) < Qs[i] < max(Qa, Qb) && isfinite(bal[i]) && bal[i] > 0 && abs(Δs[i]) > tb.alpha] + if min(Qa, Qb) < Qs[i] < max(Qa, Qb) && isfinite(bal[i]) && bal[i] > 0 && abs(Δs[i]) > tb.alpha] idx = 0 valley = peak = previous = 0 for i in path diff --git a/src/Tearing/Dispersion/BruteForceScan.jl b/src/Tearing/Dispersion/BruteForceScan.jl index 4b84f9d92..351037f8b 100644 --- a/src/Tearing/Dispersion/BruteForceScan.jl +++ b/src/Tearing/Dispersion/BruteForceScan.jl @@ -5,12 +5,12 @@ Output of a brute-force or AMR Q-plane scan. -| field | meaning | -|------------|---------------------------------------------------| -| `Q` | Complex Q values (`Matrix` for grid, `Vector` for AMR) | -| `Δ` | Residual values, same shape as `Q` | -| `re_axis` | Real-axis grid (only for regular-grid `ScanResult`) | -| `im_axis` | Imaginary-axis grid (only for regular-grid `ScanResult`) | +| field | meaning | +|:--------- |:-------------------------------------------------------- | +| `Q` | Complex Q values (`Matrix` for grid, `Vector` for AMR) | +| `Δ` | Residual values, same shape as `Q` | +| `re_axis` | Real-axis grid (only for regular-grid `ScanResult`) | +| `im_axis` | Imaginary-axis grid (only for regular-grid `ScanResult`) | """ struct ScanResult Q::Matrix{ComplexF64} @@ -43,16 +43,16 @@ from the result. - `threaded` -- distribute Q evaluations across `Threads.@threads` """ function brute_force_scan(f, Q_re_range::NTuple{2,<:Real}, - Q_im_range::NTuple{2,<:Real}; - nre::Integer, nim::Integer, - threaded::Bool=true) + Q_im_range::NTuple{2,<:Real}; + nre::Integer, nim::Integer, + threaded::Bool=true) nre >= 2 || throw(ArgumentError("brute_force_scan: nre must be ≥ 2")) nim >= 2 || throw(ArgumentError("brute_force_scan: nim must be ≥ 2")) re_axis = collect(range(Float64(Q_re_range[1]); stop=Float64(Q_re_range[2]), - length=nre)) + length=nre)) im_axis = collect(range(Float64(Q_im_range[1]); stop=Float64(Q_im_range[2]), - length=nim)) - Q = ComplexF64[(qr + qi*im) for qr in re_axis, qi in im_axis] + length=nim)) + Q = ComplexF64[(qr + qi * im) for qr in re_axis, qi in im_axis] Δ = Matrix{ComplexF64}(undef, nre, nim) if threaded # Pin BLAS to one thread: concurrent multithreaded `det()` reductions are not reproducible diff --git a/src/Tearing/Dispersion/ContourSearchAMR.jl b/src/Tearing/Dispersion/ContourSearchAMR.jl index 40ba8a1fe..bb74e4d75 100644 --- a/src/Tearing/Dispersion/ContourSearchAMR.jl +++ b/src/Tearing/Dispersion/ContourSearchAMR.jl @@ -28,11 +28,11 @@ end Output of `amr_scan`. -| field | meaning | -|:----------- |:-------------------------------------------------------- | -| `cells` | Final list of `AMRCell` after all refinement passes | -| `Q` | Flat `Vector{ComplexF64}` of every unique residual eval | -| `Δ` | Corresponding `Vector{ComplexF64}` of residual values | +| field | meaning | +|:----------- |:------------------------------------------------------------------------------------ | +| `cells` | Final list of `AMRCell` after all refinement passes | +| `Q` | Flat `Vector{ComplexF64}` of every unique residual eval | +| `Δ` | Corresponding `Vector{ComplexF64}` of residual values | | `truncated` | `true` if `max_cells` was hit under `:warn_truncate`; the scan is then not converged | """ struct AMRResult diff --git a/src/Tearing/GGJTearing.jl b/src/Tearing/GGJTearing.jl index c712c841d..c6780aac9 100644 --- a/src/Tearing/GGJTearing.jl +++ b/src/Tearing/GGJTearing.jl @@ -88,7 +88,7 @@ function CommonSolve.solve(prob::TearingProblem, model::GGJModel; config::Tearin if coupled outside = [labels[k] for k in 1:count if !(config.omega_range[1] <= n * Ω_shift[k] <= config.omega_range[2])] isempty(outside) || @warn "GGJ tearing: the E×B frames of $(join(outside, ", ")) (ω = n·Ω_E) lie outside omega_range = " * - "$(config.omega_range); a root near those frequencies would be missed." + "$(config.omega_range); a root near those frequencies would be missed." end # Coupled: each layer sees the lab-frame growth rate in its own E×B frame, s_k = s + i·n·Ω_E,k, so differential diff --git a/src/Tearing/HDF5Output.jl b/src/Tearing/HDF5Output.jl index 7f7f8aa22..dbf1ed5b9 100644 --- a/src/Tearing/HDF5Output.jl +++ b/src/Tearing/HDF5Output.jl @@ -164,7 +164,8 @@ const TEARING_H5_ANNOTATIONS = [ (; long_name="critical normalized resonant field b_r/B_φ for error-field penetration (Cole-Fitzpatrick 2006 Eq. 62; NaN = no maximum or surface skipped)", units="1", dims=("surface",)), "CriticalResonantField/br_crit_tesla" => - (; long_name="critical resonant field br_crit·|B0| with the layer's B0, approximately comparable to SingularCoupling/resonant_area_weighted_field (NaN = no maximum or surface skipped)", + (; + long_name="critical resonant field br_crit·|B0| with the layer's B0, approximately comparable to SingularCoupling/resonant_area_weighted_field (NaN = no maximum or surface skipped)", units="T", dims=("surface",)), "CriticalResonantField/Q0" => (; long_name="normalized natural E×B rotation Q0 = τ_k·n·Ω_E of the m/n mode (NaN where Ω_E is unknown)", units="1", dims=("surface",)) diff --git a/src/Tearing/Result.jl b/src/Tearing/Result.jl index 97f91e7d7..b91f2bb08 100644 --- a/src/Tearing/Result.jl +++ b/src/Tearing/Result.jl @@ -56,6 +56,7 @@ Output of the tearing solve: summary eigenvalues (ω, γ) and the full root-extr ## Fields - `enabled` -- `true` only when the analysis actually ran + - `problem` -- producing TearingProblem, or nothing for a low-level scan - `config` -- resolved scan configuration used by the model - `model` -- the inner-layer model solved; `nothing` when the analysis did not run diff --git a/src/Tearing/SLAYERTearing.jl b/src/Tearing/SLAYERTearing.jl index 8b522013c..7913ac1cb 100644 --- a/src/Tearing/SLAYERTearing.jl +++ b/src/Tearing/SLAYERTearing.jl @@ -175,10 +175,12 @@ function run_slayer_from_inputs(model::InnerLayer.InnerLayerModel, rational_q::Vector{Float64}=Float64[], omega_E::Vector{Float64}=Float64[]) validate(problem, config) - _is_ggj(model) && throw(ArgumentError( - "run_slayer_from_inputs: this runner scans SLAYER's tearing-only residual, which gives no GGJ growth rate. " * - "Use Dispersion.ggj_growth_rates on multi_surface_coupling_full, which matches both parity channels, and " * - "solve_inner for the GGJ layer's Δ.")) + _is_ggj(model) && throw( + ArgumentError( + "run_slayer_from_inputs: this runner scans SLAYER's tearing-only residual, which gives no GGJ growth rate. " * + "Use Dispersion.ggj_growth_rates on multi_surface_coupling_full, which matches both parity channels, and " * + "solve_inner for the GGJ layer's Δ.") + ) isempty(params) && return empty_tearing_result(problem, config, model) n = length(params) @@ -333,8 +335,12 @@ function run_critical_resonant_field(model::InnerLayer.InnerLayerModel, params:: length(omega_E) == nsurf || throw(ArgumentError("run_critical_resonant_field: omega_E has $(length(omega_E)) entries for $nsurf surfaces.")) nsurf > 0 && all(isnan, omega_E) && - throw(ArgumentError("run_critical_resonant_field: the critical resonant field needs the E×B rotation, but the " * - "kinetic file has no omega_E and no [SLAYER] omega_E_kHz entry covers the surfaces.")) + throw( + ArgumentError( + "run_critical_resonant_field: the critical resonant field needs the E×B rotation, but the " * + "kinetic file has no omega_E and no [SLAYER] omega_E_kHz entry covers the surfaces." + ) + ) Q_peak, br_crit = fill(NaN, nsurf), fill(NaN, nsurf) # Cole Sec. IV: ω0 is the mode frequency in the E×B frame; diamagnetic parts enter via Q_e, Q_i. Q0 = Float64[p.tauk * p.n * Ω for (p, Ω) in zip(params, omega_E)] @@ -348,4 +354,3 @@ function run_critical_resonant_field(model::InnerLayer.InnerLayerModel, params:: br_crit_tesla = br_crit .* Float64[abs(p.bt) for p in params] return CriticalResonantFieldResult(true, Int[p.ising for p in params], Q_peak, br_crit, br_crit_tesla, Q0, scan) end - diff --git a/src/Tearing/TearingProblem.jl b/src/Tearing/TearingProblem.jl index 1f5450447..1d1b5a75d 100644 --- a/src/Tearing/TearingProblem.jl +++ b/src/Tearing/TearingProblem.jl @@ -29,7 +29,7 @@ Both models report lab-frame roots from each surface's E×B rotation. ffs::R eta::E = nothing rho::D = nothing - gamma::Float64 = 5/3 + gamma::Float64 = 5 / 3 coupling_mode::Symbol = :uncoupled msing_max::Int = 3 omega_E_kHz::Dict{String,Float64} = Dict{String,Float64}() @@ -82,7 +82,7 @@ end function CommonSolve.solve(prob::TearingProblem, model::SLAYERModel; config::TearingConfig=TearingConfig()) config.gamma_range === nothing && config.omega_range === nothing || throw(ArgumentError("SLAYER uses Q_re_range and Q_im_range.")) - prob.eta === nothing && prob.rho === nothing && prob.gamma == 5/3 || + prob.eta === nothing && prob.rho === nothing && prob.gamma == 5 / 3 || throw(ArgumentError("SLAYER derives its layer inputs from transport profiles; eta, rho, and gamma overrides are GGJ settings.")) ffs = prob.ffs equil = ffs.equil diff --git a/src/Utilities/FourierTransforms.jl b/src/Utilities/FourierTransforms.jl index e7a977cbb..8ca61697d 100644 --- a/src/Utilities/FourierTransforms.jl +++ b/src/Utilities/FourierTransforms.jl @@ -33,7 +33,7 @@ function compute_fourier_coefficients(mtheta::Int, m_modes::AbstractVector{<:Int @assert length(ζ) == mtheta "ζ must have length mtheta" - θ_grid = range(; start=0, length=mtheta, step=2π/mtheta) + θ_grid = range(; start=0, length=mtheta, step=2π / mtheta) arg = m_modes' .* θ_grid .- n .* ζ return transpose(exp.(-im .* arg)) end @@ -67,8 +67,8 @@ function compute_fourier_coefficients( ) @assert nzeta % nfp == 0 "nzeta ($nzeta) must be divisible by nfp ($nfp)" - θ_grid = range(; start=0, length=mtheta, step=2π/mtheta) - ζ_grid = range(; start=0, length=nzeta, step=2π/nzeta) + θ_grid = range(; start=0, length=mtheta, step=2π / mtheta) + ζ_grid = range(; start=0, length=nzeta, step=2π / nzeta) nzeta_out = nzeta ÷ nfp mpert = length(m_modes) diff --git a/src/Utilities/HDF5Annotations.jl b/src/Utilities/HDF5Annotations.jl index 44fa2f40a..08a4bb15c 100644 --- a/src/Utilities/HDF5Annotations.jl +++ b/src/Utilities/HDF5Annotations.jl @@ -7,8 +7,7 @@ Self-describing metadata for `gpec.h5` (the contract in datasets are marked as HDF5 Dimension Scales (netCDF-4 coordinate variables) attached to the arrays that share their axis, so h5py/xarray/HDFView read the file unaided. -Writers stay table-driven: each writer keeps a table of `path => (; long_name, units, -dims)` entries next to it and calls [`annotate!`](@ref) once after its datasets are +Writers stay table-driven: each writer keeps a table of `path => (; long_name, units, dims)` entries next to it and calls [`annotate!`](@ref) once after its datasets are written. Paths absent from the file are skipped silently (many writes are conditional). """ module HDF5Annotations diff --git a/src/Utilities/HDF5Schema.jl b/src/Utilities/HDF5Schema.jl index 2b322b7a7..c5a6de57e 100644 --- a/src/Utilities/HDF5Schema.jl +++ b/src/Utilities/HDF5Schema.jl @@ -152,9 +152,17 @@ const MAIN_H5_ANNOTATIONS = [ "ForceFreeStates/LayerOverlap/width_visco" => (; long_name="visco-resistive comparison scale as a normalized-flux width", dims=("surface_overlap",), attach=(1 => "ForceFreeStates/LayerOverlap/psi",)), "ForceFreeStates/LayerOverlap/width_dr" => - (; long_name="diffusive-resistive layer width (Fitzpatrick 2025 Eq. 100) as a normalized-flux width; the channel the criterion uses", dims=("surface_overlap",), attach=(1 => "ForceFreeStates/LayerOverlap/psi",)), + (; + long_name="diffusive-resistive layer width (Fitzpatrick 2025 Eq. 100) as a normalized-flux width; the channel the criterion uses", + dims=("surface_overlap",), + attach=(1 => "ForceFreeStates/LayerOverlap/psi",) + ), "ForceFreeStates/LayerOverlap/extrapolated" => - (; long_name="1 where the surface was located beyond the equilibrium grid via the separatrix edge q-law", dims=("surface_overlap",), attach=(1 => "ForceFreeStates/LayerOverlap/psi",)), + (; + long_name="1 where the surface was located beyond the equilibrium grid via the separatrix edge q-law", + dims=("surface_overlap",), + attach=(1 => "ForceFreeStates/LayerOverlap/psi",) + ), "ForceFreeStates/LayerOverlap/psilim_overlap" => (; long_name="domain limit implied by the first layer overlap, at the last surface with a well-separated inner region (NaN when no overlap was found in range)"), "ForceFreeStates/LayerOverlap/first_overlap_index" => diff --git a/src/Utilities/PhysicalConstants.jl b/src/Utilities/PhysicalConstants.jl index a9668b611..6511e6df2 100644 --- a/src/Utilities/PhysicalConstants.jl +++ b/src/Utilities/PhysicalConstants.jl @@ -10,11 +10,11 @@ All quantities in SI units. module PhysicalConstants # Match the Fortran GPEC/SLAYER sglobal_mod values exactly so cross-code numerical comparison is meaningful. -const MU_0 = 4.0e-7 * π # vacuum permeability [H/m] -const M_E = 9.1094e-31 # electron mass [kg] -const M_P = 1.6726e-27 # proton mass [kg] +const MU_0 = 4.0e-7 * π # vacuum permeability [H/m] +const M_E = 9.1094e-31 # electron mass [kg] +const M_P = 1.6726e-27 # proton mass [kg] const E_CHG = 1.6021917e-19 # elementary charge [C] -const K_B = 1.3807e-23 # Boltzmann constant [J/K] +const K_B = 1.3807e-23 # Boltzmann constant [J/K] const EPS_0 = 8.8542e-12 # vacuum permittivity [F/m] export MU_0, M_E, M_P, E_CHG, K_B, EPS_0 diff --git a/src/Vacuum/DataTypes.jl b/src/Vacuum/DataTypes.jl index f8d3c9e97..a15f08e33 100644 --- a/src/Vacuum/DataTypes.jl +++ b/src/Vacuum/DataTypes.jl @@ -76,7 +76,7 @@ function VacuumInput( x=r[1:(end-1)], z=z[1:(end-1)], ν=ν[1:(end-1)], - mtheta_in=length(r)-1, + mtheta_in=length(r) - 1, m_modes=collect(Int, m_modes), n_modes=collect(Int, n_modes), mtheta=mtheta, @@ -375,8 +375,8 @@ function PlasmaGeometry(inputs::VacuumInput) @assert length(inputs.x) == length(inputs.z) == length(inputs.ν) "x, z, and ν must have the same length" # Interpolate arrays from input onto mtheta grid - θ_in = range(; start=0, length=inputs.mtheta_in, step=2π/inputs.mtheta_in) - θ_out = range(; start=0, length=inputs.mtheta, step=2π/inputs.mtheta) + θ_in = range(; start=0, length=inputs.mtheta_in, step=2π / inputs.mtheta_in) + θ_out = range(; start=0, length=inputs.mtheta, step=2π / inputs.mtheta) x = cubic_interp(θ_in, inputs.x, θ_out; bc=PeriodicBC(; endpoint=:exclusive)) z = cubic_interp(θ_in, inputs.z, θ_out; bc=PeriodicBC(; endpoint=:exclusive)) @@ -456,8 +456,8 @@ function PlasmaGeometry3D(inputs::VacuumInput) # Interpolate 3D inputs onto vacuum grid @assert !isempty(inputs.y) "y must be provided for 3D (nzeta_in > 1) inputs" @assert length(inputs.x) == length(inputs.y) == length(inputs.z) == inputs.mtheta_in * inputs.nzeta_in "x, y, z must have length mtheta_in * nzeta_in" - θ_in = range(; start=0, length=inputs.mtheta_in, step=2π/inputs.mtheta_in) - ζ_in = range(; start=0, length=inputs.nzeta_in, step=2π/inputs.nzeta_in) + θ_in = range(; start=0, length=inputs.mtheta_in, step=2π / inputs.mtheta_in) + ζ_in = range(; start=0, length=inputs.nzeta_in, step=2π / inputs.nzeta_in) θ_flat = repeat(collect(θ_grid), nzeta) ζ_flat = repeat(collect(ζ_grid); inner=mtheta) grid_points = (θ_flat, ζ_flat) @@ -573,7 +573,7 @@ function WallGeometry(inputs::VacuumInput, plasma_surf::PlasmaGeometry, wall_set zrad = 0.5 * (zmax - zmin) zh = sqrt(abs(zrad^2 - r_minor^2)) - zmuw = log((a/zh) + sqrt((a/zh)^2 + 1)) + zmuw = log((a / zh) + sqrt((a / zh)^2 + 1)) bw_eff = (zh * cosh(zmuw)) / a for i in 1:mtheta @@ -590,7 +590,7 @@ function WallGeometry(inputs::VacuumInput, plasma_surf::PlasmaGeometry, wall_set for i in 1:mtheta the = (i - 1) * (2π / mtheta) x_wall[i] = wcentr + r_minor * (1.0 + a - cw) * cos(the + dw * sin(the)) - z_wall[i] = bw * r_minor * (1.0 + a - cw) * sin(the + tw * sin(2.0*the)) + aw * r_minor * sin(2.0*the) + z_wall[i] = bw * r_minor * (1.0 + a - cw) * sin(the + tw * sin(2.0 * the)) + aw * r_minor * sin(2.0 * the) end elseif wall_settings isa ModDeeWall @@ -601,7 +601,7 @@ function WallGeometry(inputs::VacuumInput, plasma_surf::PlasmaGeometry, wall_set for i in 1:mtheta the = (i - 1) * (2π / mtheta) x_wall[i] = cw + a * cos(the + dw * sin(the)) - z_wall[i] = bw * a * sin(the + tw * sin(2.0*the)) + aw * sin(2.0*the) + z_wall[i] = bw * a * sin(the + tw * sin(2.0 * the)) + aw * sin(2.0 * the) end else diff --git a/src/Vacuum/Kernel2D.jl b/src/Vacuum/Kernel2D.jl index 0fadc644a..9a2d36004 100644 --- a/src/Vacuum/Kernel2D.jl +++ b/src/Vacuum/Kernel2D.jl @@ -112,9 +112,9 @@ grad_greenfunction is not zeroed since it fills a different block of the populate_greenfunction && fill!(greenfunction, 0.0) # S₁ᵢ logarithmic correction factors [Chance Phys. Plasmas 1997 2161 eq. 78] - log_correction_0=16.0*dtheta*(log(2*dtheta)-68.0/15.0)/15.0 - log_correction_1=128.0*dtheta*(log(2*dtheta)-8.0/15.0)/45.0 - log_correction_2=4.0*dtheta*(7.0*log(2*dtheta)-11.0/15.0)/45.0 + log_correction_0 = 16.0 * dtheta * (log(2 * dtheta) - 68.0 / 15.0) / 15.0 + log_correction_1 = 128.0 * dtheta * (log(2 * dtheta) - 8.0 / 15.0) / 45.0 + log_correction_2 = 4.0 * dtheta * (7.0 * log(2 * dtheta) - 11.0 / 15.0) / 45.0 log_correction_array = SVector(log_correction_2, log_correction_1, log_correction_0, log_correction_1, log_correction_2) # Precompute the n-dependent prefactor 2√π·Γ(1/2-n) [Chance Phys. Plasmas 1997 2161 eq. 40] @@ -272,14 +272,14 @@ function elliptic_integral_e(m1) (m1 < 0.0 || m1 > 1.0) && throw(DomainError(m1, "Input `x1` must be in the range (0, 1].")) log_x1 = log(m1) - ae1=0.44325141463 - ae2=0.0626060122 - ae3=0.04757383546 - ae4=0.01736506451 - be1=0.2499836831 - be2=0.09200180037 - be3=0.04069697526 - be4=0.00526449639 + ae1 = 0.44325141463 + ae2 = 0.0626060122 + ae3 = 0.04757383546 + ae4 = 0.01736506451 + be1 = 0.2499836831 + be2 = 0.09200180037 + be3 = 0.04069697526 + be4 = 0.00526449639 p = @evalpoly(m1, 1.0, ae1, ae2, ae3, ae4) q = @evalpoly(m1, 0.0, be1, be2, be3, be4) @@ -300,7 +300,7 @@ end # The paper's eq. 50 has a typo: the exponent is -1/4, not +1/2 function P0_plus_half(s) m1 = (s + sqrt(s^2 - 1))^(-2) - return 2 / π * m1^(-1/4) * elliptic_integral_e(m1) # This is correct + return 2 / π * m1^(-1 / 4) * elliptic_integral_e(m1) # This is correct end @@ -450,8 +450,8 @@ function elliptic_integrals_bulirsch(m1::Float64; error::Float64=1e-8, maxit::In convergence = max(convergence, 1.0e-100) # Calculate final K and E values - K = π/2 * (bval1 + aval1 * emval) / (emval * (emval + pval)) - E = π/2 * (bval2 + aval2 * emval) / (emval * (emval + pval)) + K = π / 2 * (bval1 + aval1 * emval) / (emval * (emval + pval)) + E = π / 2 * (bval2 + aval2 * emval) / (emval * (emval + pval)) return K, E, convergence, kounter end diff --git a/src/Vacuum/Kernel3D.jl b/src/Vacuum/Kernel3D.jl index 2d9bf534d..c668dbf21 100644 --- a/src/Vacuum/Kernel3D.jl +++ b/src/Vacuum/Kernel3D.jl @@ -194,12 +194,12 @@ Fused Laplace kernels: `single = 1/r`, `double = (Δx·n)/r³`. Shares `√(r²) dx = ox - sx dy = oy - sy dz = oz - sz - r2 = dx*dx + dy*dy + dz*dz + r2 = dx * dx + dy * dy + dz * dz r2 < 1e-30 && return (0.0, 0.0) rinv = inv(sqrt(r2)) single = rinv r3inv = rinv * rinv * rinv - double = (dx*nx + dy*ny + dz*nz) * r3inv + double = (dx * nx + dy * ny + dz * nz) * r3inv return (single, double) end diff --git a/src/Vacuum/Utilities.jl b/src/Vacuum/Utilities.jl index 22ce9625a..906b9819c 100644 --- a/src/Vacuum/Utilities.jl +++ b/src/Vacuum/Utilities.jl @@ -74,7 +74,7 @@ function distribute_to_equal_arc_grid(xin::Vector{Float64}, zin::Vector{Float64} end # Interpolate the original (x, z) at equal arc-length targets - arc_length_targets = range(; start=0, length=mtheta, step=arc_length[end]/mtheta) + arc_length_targets = range(; start=0, length=mtheta, step=arc_length[end] / mtheta) # arc_length is an uneven grid so we have to specify the period explicitly periodic_bc = PeriodicBC(; endpoint=:exclusive, period=arc_length[end]) xout = cubic_interp(arc_length[1:(end-1)], xin, arc_length_targets; bc=periodic_bc) @@ -108,8 +108,8 @@ Write the cross product of rows `idx` of the `(N, 3)` matrices `a` and `b` into b2 = b[idx, 2] b3 = b[idx, 3] - c[idx, 1] = a2*b3 - a3*b2 - c[idx, 2] = a3*b1 - a1*b3 - c[idx, 3] = a1*b2 - a2*b1 + c[idx, 1] = a2 * b3 - a3 * b2 + c[idx, 2] = a3 * b1 - a1 * b3 + c[idx, 3] = a1 * b2 - a2 * b1 end end diff --git a/test/runtests.jl b/test/runtests.jl index bc7263af4..95346ac03 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,7 +22,7 @@ using GeneralizedPerturbedEquilibrium function run_test_file(testfile) @info "Running test file" testfile measurement = @timed include(testfile) - @info "Completed test file" testfile elapsed_seconds=measurement.time compile_seconds=measurement.compile_time recompile_seconds=measurement.recompile_time + @info "Completed test file" testfile elapsed_seconds = measurement.time compile_seconds = measurement.compile_time recompile_seconds = measurement.recompile_time return nothing end diff --git a/test/runtests_analysis_plots.jl b/test/runtests_analysis_plots.jl index d17239ec6..4739fe5ba 100644 --- a/test/runtests_analysis_plots.jl +++ b/test/runtests_analysis_plots.jl @@ -28,11 +28,16 @@ using TOML @testset "ideal run with coil forcing and the perturbed-equilibrium response" begin mktempdir() do dir - h5 = _run_fixture(dir, "regression_tj_ideal_example"; ffs=Dict{String,Any}("dW_edge_scan_start" => 0.95), sections=Dict{String,Any}( - "ForcingTerms" => Dict{String,Any}("forcing_data_format" => "coil", "mtheta_coil" => 240, "nzeta_coil" => 32, - "coil_set" => [Dict{String,Any}("name" => "hoop", "source" => "pf_hoop", "radius" => 12.0, "height" => 1.2, - "currents" => [2.0e3], "tiltx" => [3.0])]), - "PerturbedEquilibrium" => Dict{String,Any}("compute_singular_coupling" => true))) + h5 = _run_fixture( + dir, + "regression_tj_ideal_example"; + ffs=Dict{String,Any}("dW_edge_scan_start" => 0.95), + sections=Dict{String,Any}( + "ForcingTerms" => Dict{String,Any}("forcing_data_format" => "coil", "mtheta_coil" => 240, "nzeta_coil" => 32, + "coil_set" => [Dict{String,Any}("name" => "hoop", "source" => "pf_hoop", "radius" => 12.0, "height" => 1.2, + "currents" => [2.0e3], "tiltx" => [3.0])]), + "PerturbedEquilibrium" => Dict{String,Any}("compute_singular_coupling" => true)) + ) for f in (A.Equilibrium.plot_qprofile, A.Equilibrium.plot_pressure_profile, A.Equilibrium.plot_f_profile, A.Equilibrium.plot_flux_surfaces, A.Equilibrium.plot_equilibrium_summary) diff --git a/test/runtests_coils.jl b/test/runtests_coils.jl index 7a22105bd..2a12db7f8 100644 --- a/test/runtests_coils.jl +++ b/test/runtests_coils.jl @@ -739,7 +739,7 @@ end open(flipped, "w") do io for (i, l) in enumerate(lines) if i == 4 # header line 4 starts with the plasma current - vals = [l[j:min(j+15, end)] for j in 1:16:length(l)] + vals = [l[j:min(j + 15, end)] for j in 1:16:length(l)] cur = -parse(Float64, strip(vals[1])) l = @sprintf("%16.9E", cur) * l[17:end] end diff --git a/test/runtests_coordinate_invariant.jl b/test/runtests_coordinate_invariant.jl index 2a98861ee..c4c9991de 100644 --- a/test/runtests_coordinate_invariant.jl +++ b/test/runtests_coordinate_invariant.jl @@ -140,10 +140,10 @@ end @testset "power_norm_matrix! is the ∮J|ξ|² quadratic form" begin FFS = GeneralizedPerturbedEquilibrium.ForceFreeStates mpert, mlow, ntheta, dV_dpsi = 5, -2, 64, 1.7 - θ = range(; start=0, length=ntheta, step=2π/ntheta) + θ = range(; start=0, length=ntheta, step=2π / ntheta) J = 1 .+ 0.3 .* cos.(θ) .+ 0.2 .* sin.(θ) .+ 0.1 .* sin.(2θ) # Fourfit storage: jmat[mpert − d] = J_d = ⟨J e^{−idθ}⟩ - jmat = ComplexF64[sum(J .* cis.(-d .* θ)) / ntheta for d in (mpert-1):-1:(-(mpert-1))] + jmat = ComplexF64[sum(J .* cis.(-d .* θ)) / ntheta for d in (mpert-1):-1:(-(mpert - 1))] m_modes = mlow:(mlow+mpert-1) ξ = ComplexF64[cis(0.7m) * (1 + 0.2m) for m in m_modes] ξθ = [sum(ξ[l] * cis(m * t) for (l, m) in enumerate(m_modes)) for t in θ] diff --git a/test/runtests_core_capped_knots.jl b/test/runtests_core_capped_knots.jl index 84ad3f240..8ff0c584b 100644 --- a/test/runtests_core_capped_knots.jl +++ b/test/runtests_core_capped_knots.jl @@ -15,7 +15,7 @@ using GeneralizedPerturbedEquilibrium # Nothing at or above ψ = 0.1 is dropped. @test count(>=(0.1), kept) == count(>=(0.1), xs) # Below it, kept knots are at least 5% of ψ apart. - core = kept[kept .< 0.1] + core = kept[kept.<0.1] @test all(diff(core) .>= 0.05 .* core[2:end]) # A core rational ends the capped region before its resolution window. diff --git a/test/runtests_critical_resonant_field.jl b/test/runtests_critical_resonant_field.jl index c95a3098e..b1c6ef313 100644 --- a/test/runtests_critical_resonant_field.jl +++ b/test/runtests_critical_resonant_field.jl @@ -191,8 +191,9 @@ InnerLayer.layer_response(::_VRiStub, p, Q::Number) = (; tearing=_vri(-real(Q), @test_throws "needs the E×B rotation" run_slayer_from_inputs(model, params, dp, c, scan; rational_psi=[0.5, 0.7], rational_q=[2.0, 1.5]) # A surface the override leaves without a rotation is skipped; the others are still computed. c_part = TearingProblem(nothing; critical_resonant_field=ctrl, omega_E_kHz=Dict("2/1" => ω_E / (2π * 1e3))) - r_part = (@test_logs (:warn, r"2/2 surface skipped") match_mode = :any run_slayer_from_inputs(model, params, dp, c_part, scan; - rational_psi=[0.5, 0.7], rational_q=[2.0, 1.5])).critical_resonant_field + r_part = + (@test_logs (:warn, r"2/2 surface skipped") match_mode = :any run_slayer_from_inputs(model, params, dp, c_part, scan; + rational_psi=[0.5, 0.7], rational_q=[2.0, 1.5])).critical_resonant_field @test r_part.Q0[1] ≈ r.Q0[1] && isnan(r_part.Q0[2]) @test isequal(r_part.br_crit[1], r.br_crit[1]) && isnan(r_part.br_crit[2]) end diff --git a/test/runtests_dispersion_amr.jl b/test/runtests_dispersion_amr.jl index a29fb8f8c..8b528f7aa 100644 --- a/test/runtests_dispersion_amr.jl +++ b/test/runtests_dispersion_amr.jl @@ -176,7 +176,8 @@ # ========================================================================= # multi_box_amr_scan # ========================================================================= - using GeneralizedPerturbedEquilibrium.Tearing.Dispersion: BoxActivity, NoActivity, + using GeneralizedPerturbedEquilibrium.Tearing.Dispersion: + BoxActivity, NoActivity, ReZeroCrossing, ImZeroCrossing, PoleMagnitude, MultiBoxAMRResult, multi_box_amr_scan, as_amr_result diff --git a/test/runtests_dispersion_ggj.jl b/test/runtests_dispersion_ggj.jl index 77347cf16..e83af9ae7 100644 --- a/test/runtests_dispersion_ggj.jl +++ b/test/runtests_dispersion_ggj.jl @@ -36,7 +36,7 @@ GeneralizedPerturbedEquilibrium.Tearing.Dispersion._residual_domain_radius(f::GG D = GeneralizedPerturbedEquilibrium.Tearing.Dispersion g = GGJDispersion(mc) center = 0.01im - re_paths = [ComplexF64[-1 + center, 1 + center]] + re_paths = [ComplexF64[-1+center, 1+center]] im_paths = [ComplexF64[0.001im, 0.02im]] # A coarse contour estimate must not pull a stable root into a positive-growth search. f = GGJDomainTestResidual(g, Q -> Q + 0.1im, ComplexF64[]) diff --git a/test/runtests_dispersion_polish.jl b/test/runtests_dispersion_polish.jl index cbf8b81d6..c5963fb52 100644 --- a/test/runtests_dispersion_polish.jl +++ b/test/runtests_dispersion_polish.jl @@ -142,7 +142,7 @@ r1 = 0.30 + 0.20im r2 = r1 + 0.002 # second root 0.002 away f(Q) = (ComplexF64(Q) - r1) * (ComplexF64(Q) - r2) - pts = ComplexF64[r1 + 0.0003, r2 - 0.0003] # coarse contour estimates + pts = ComplexF64[r1+0.0003, r2-0.0003] # coarse contour estimates R1 = D._polish_trust_radius(pts, 1, 0.001) R2 = D._polish_trust_radius(pts, 2, 0.001) p1 = D._polish_root(f, pts[1], R1)[1] @@ -160,7 +160,7 @@ im_paths = [ComplexF64[0+0im, 0+0.1im]] # segment length 0.1 @test D._median_segment_length(re_paths, im_paths) ≈ 0.1 # median of [0.1,0.2,0.1] @test D._median_segment_length(Vector{Vector{ComplexF64}}(), - Vector{Vector{ComplexF64}}()) == 0.0 + Vector{Vector{ComplexF64}}()) == 0.0 end # ---------------------------------------------------------------- diff --git a/test/runtests_dispersion_residual.jl b/test/runtests_dispersion_residual.jl index 92586f969..32cb81d0a 100644 --- a/test/runtests_dispersion_residual.jl +++ b/test/runtests_dispersion_residual.jl @@ -20,50 +20,50 @@ InnerLayerResponse(m.a + m.b * ComplexF64(Q), zero(ComplexF64)) function _slayer_ref() - return slayer_parameters( + return slayer_parameters(; n_e=5.0e19, t_e=1000.0, t_i=1000.0, omega_e=-1.0e4, omega_i=5.0e3, qval=2.0, sval_r=1.0, bt=2.0, rs=0.5, R0=1.7, mu_i=2.0, zeff=1.0, - chi_perp_e=1.0, chi_tor=1.0, m=2, n=1; P_perp_model=:chi_perp_e) + chi_perp_e=1.0, chi_tor=1.0, m=2, n=1, P_perp_model=:chi_perp_e) end @testset "Constructor scale defaults" begin # SLAYER: scale = lu^(1/3) so the dimensionless Δ from riccati_f # is mapped to outer ψ-units (Fortran SLAYER growthrates routine) - p_sl = _slayer_ref() + p_sl = _slayer_ref() sc_sl = surface_coupling(SLAYERModel(), p_sl, -1.0 + 0.0im) - @test sc_sl.scale ≈ p_sl.lu^(1/3) + @test sc_sl.scale ≈ p_sl.lu^(1 / 3) @test sc_sl.dc == 0.0 @test sc_sl.dp_diag == ComplexF64(-1.0) # GGJ: scale = 1 because rescale_delta is applied inside solve_inner - p_ggj = glasser_wang_2020_eq55() - sc_ggj = surface_coupling(GGJModel(solver=:shooting), p_ggj, - -1.0 + 0.0im) + p_ggj = glasser_wang_2020_eq55() + sc_ggj = surface_coupling(GGJModel(; solver=:shooting), p_ggj, + -1.0 + 0.0im) @test sc_ggj.scale == 1.0 # Generic fallback honors explicit scale + dc kwargs - sc_lin = surface_coupling(LinearTestModel(0.0im, 1.0+0im), nothing, - 3.0 + 0.0im; dc=0.5, scale=2.0) + sc_lin = surface_coupling(LinearTestModel(0.0im, 1.0 + 0im), nothing, + 3.0 + 0.0im; dc=0.5, scale=2.0) @test sc_lin.scale == 2.0 @test sc_lin.dc == 0.5 end @testset "Residual arithmetic on synthetic linear model" begin # r(Q) = dp_diag - scale·(a + b·Q) - dc - a, b = 1.0 + 2.0im, -0.5 + 1.0im - scale = 3.0 - dc = 0.25 + a, b = 1.0 + 2.0im, -0.5 + 1.0im + scale = 3.0 + dc = 0.25 Q_root = -0.7 + 0.3im dp_diag = (a + b * Q_root) * scale + dc # construct a known root sc = surface_coupling(LinearTestModel(a, b), nothing, dp_diag; - dc=dc, scale=scale) + dc=dc, scale=scale) @test sc(Q_root) ≈ 0 atol = 1e-12 # Off-root residual matches the closed form - for Q in (0.0+0im, 1.5-0.5im, -0.2+1.2im) + for Q in (0.0 + 0im, 1.5 - 0.5im, -0.2 + 1.2im) expected = dp_diag - scale * (a + b * Q) - dc @test sc(Q) ≈ expected end @@ -76,7 +76,7 @@ m = SLAYERModel() Q_pin = 0.3 + 0.4im Δ_pin = layer_response(m, p, Q_pin).tearing - dp_diag = p.lu^(1/3) * Δ_pin + dp_diag = p.lu^(1 / 3) * Δ_pin sc = surface_coupling(m, p, dp_diag) @test abs(sc(Q_pin)) < 1e-13 # self-consistent @@ -90,14 +90,14 @@ # Both inner-layer models flow through the same SurfaceCoupling # API. Numerical agreement is *not* asserted (different physics) — # only that both pipelines construct and evaluate. - p_sl = _slayer_ref() + p_sl = _slayer_ref() sc_sl = surface_coupling(SLAYERModel(), p_sl, -100.0 + 0.0im) @test sc_sl isa SurfaceCoupling{SLAYERModel{:fitzpatrick},SLAYERParameters} @test sc_sl(0.0 + 0.5im) isa ComplexF64 - p_ggj = glasser_wang_2020_eq55() - sc_ggj = surface_coupling(GGJModel(solver=:shooting), p_ggj, - -1.0 + 0.0im) + p_ggj = glasser_wang_2020_eq55() + sc_ggj = surface_coupling(GGJModel(; solver=:shooting), p_ggj, + -1.0 + 0.0im) @test sc_ggj isa SurfaceCoupling{<:GGJModel{:shooting},GGJParameters} @test sc_ggj(1e-3 + 0.0im) isa ComplexF64 end @@ -105,10 +105,10 @@ @testset "Residual is callable on grids (broadcast)" begin # Brute-force / AMR scans (PR 5/6) will broadcast `sc` over a 2D # complex-Q grid; verify that broadcasting works element-wise. - a, b = 0.0+0im, 1.0+0im - sc = surface_coupling(LinearTestModel(a, b), nothing, 2.0+0im; - dc=0.0, scale=1.0) - Q_grid = [(qr + qi*im) for qr in -1.0:0.5:1.0, qi in -1.0:0.5:1.0] + a, b = 0.0 + 0im, 1.0 + 0im + sc = surface_coupling(LinearTestModel(a, b), nothing, 2.0 + 0im; + dc=0.0, scale=1.0) + Q_grid = [(qr + qi * im) for qr in -1.0:0.5:1.0, qi in -1.0:0.5:1.0] Δ_grid = sc.(Q_grid) @test size(Δ_grid) == size(Q_grid) @test all(d -> d isa ComplexF64, Δ_grid) diff --git a/test/runtests_dispersion_scan.jl b/test/runtests_dispersion_scan.jl index 92dc380ec..7635ceb19 100644 --- a/test/runtests_dispersion_scan.jl +++ b/test/runtests_dispersion_scan.jl @@ -7,36 +7,36 @@ @testset "brute_force_scan: regular grid evaluation" begin f(Q) = ComplexF64(Q)^2 - 1 scan = brute_force_scan(f, (-2.0, 2.0), (-1.0, 1.0); - nre=21, nim=11, threaded=false) + nre=21, nim=11, threaded=false) @test scan isa ScanResult @test size(scan.Q) == (21, 11) @test size(scan.Δ) == (21, 11) @test length(scan.re_axis) == 21 @test length(scan.im_axis) == 11 - @test scan.re_axis[1] == -2.0 - @test scan.re_axis[end] == 2.0 - @test scan.im_axis[1] == -1.0 - @test scan.im_axis[end] == 1.0 + @test scan.re_axis[1] == -2.0 + @test scan.re_axis[end] == 2.0 + @test scan.im_axis[1] == -1.0 + @test scan.im_axis[end] == 1.0 # Spot-check a grid value i, j = 11, 6 - @test scan.Q[i, j] ≈ scan.re_axis[i] + scan.im_axis[j]*im + @test scan.Q[i, j] ≈ scan.re_axis[i] + scan.im_axis[j] * im @test scan.Δ[i, j] ≈ scan.Q[i, j]^2 - 1 end @testset "brute_force_scan: threaded vs non-threaded agree" begin f(Q) = sin(ComplexF64(Q)) s_t = brute_force_scan(f, (-1.0, 1.0), (-0.5, 0.5); - nre=15, nim=10, threaded=true) + nre=15, nim=10, threaded=true) s_n = brute_force_scan(f, (-1.0, 1.0), (-0.5, 0.5); - nre=15, nim=10, threaded=false) + nre=15, nim=10, threaded=false) @test s_t.Δ == s_n.Δ end @testset "brute_force_scan: argument validation" begin @test_throws ArgumentError brute_force_scan(identity, (0.0, 1.0), - (0.0, 1.0); nre=1, nim=10) + (0.0, 1.0); nre=1, nim=10) @test_throws ArgumentError brute_force_scan(identity, (0.0, 1.0), - (0.0, 1.0); nre=10, nim=1) + (0.0, 1.0); nre=10, nim=1) end @testset "find_growth_rates: single isolated root" begin @@ -44,7 +44,7 @@ Q_root = 0.42 + 0.27im f(Q) = ComplexF64(Q) - Q_root scan = brute_force_scan(f, (-1.0, 1.5), (-0.5, 1.0); - nre=80, nim=60, threaded=false) + nre=80, nim=60, threaded=false) result = find_growth_rates(scan, 1.0) @test result isa GrowthRateResult @test isempty(result.poles) @@ -60,7 +60,7 @@ Q2 = -0.4 + 0.1im # lower γ f(Q) = (ComplexF64(Q) - Q1) * (ComplexF64(Q) - Q2) scan = brute_force_scan(f, (-1.0, 1.0), (-0.3, 0.8); - nre=100, nim=80, threaded=false) + nre=100, nim=80, threaded=false) result = find_growth_rates(scan, 1.0) @test length(result.valid_roots) == 2 @test abs(result.Q_root - Q1) < 1e-3 # higher-γ root chosen @@ -73,7 +73,7 @@ Q_p = -0.5 + 0.6im # pole at higher γ f(Q) = (ComplexF64(Q) - Q_r) / (ComplexF64(Q) - Q_p) scan = brute_force_scan(f, (-1.5, 1.5), (-0.5, 1.5); - nre=120, nim=100, threaded=false) + nre=120, nim=100, threaded=false) result = find_growth_rates(scan, 1.0; pole_threshold=10.0) # Pole correctly classified — but the root is at lower γ than the # pole, so even with filter_above_poles=true the root must survive. @@ -86,14 +86,14 @@ Q_root = 1.0 + 2.0im f(Q) = ComplexF64(Q) - Q_root scan = brute_force_scan(f, (-2.0, 3.0), (-1.0, 4.0); - nre=80, nim=80, threaded=false) + nre=80, nim=80, threaded=false) tauk = 5.0e-5 result = find_growth_rates(scan, tauk) @test result.omega ≈ real(result.Q_root) / tauk @test result.gamma ≈ imag(result.Q_root) / tauk # Check sensible orders of magnitude (Q_root ≈ 1+2im, tauk ≈ 5e-5) - @test result.omega ≈ 1 / tauk atol = 1 / tauk * 5e-3 - @test result.gamma ≈ 2 / tauk atol = 2 / tauk * 5e-3 + @test result.omega ≈ 1 / tauk atol = 1 / tauk * 5e-3 + @test result.gamma ≈ 2 / tauk atol = 2 / tauk * 5e-3 end @testset "find_growth_rates: empty result when no contour intersections" begin @@ -102,7 +102,7 @@ f(Q) = 1.0 + ComplexF64(Q) # Choose a box where Δ has no zeros — far above the real axis scan = brute_force_scan(f, (1.0, 2.0), (1.0, 2.0); - nre=30, nim=30, threaded=false) + nre=30, nim=30, threaded=false) result = find_growth_rates(scan, 1.0) # Either no valid roots, or a NaN Q_root @test isempty(result.valid_roots) || isnan(real(result.Q_root)) @@ -121,10 +121,10 @@ # Single-surface scan via SurfaceCoupling (Q_root by construction = 0.7-0.3im) Q_pin = 0.7 - 0.3im - sc = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - Q_pin; scale=1.0, tauk=1.0) + sc = surface_coupling(LinModel(0.0im, 1.0 + 0im), nothing, + Q_pin; scale=1.0, tauk=1.0) scan = brute_force_scan(sc, (-0.5, 1.5), (-1.0, 0.5); - nre=80, nim=80, threaded=false) + nre=80, nim=80, threaded=false) res = find_growth_rates(scan, sc.tauk) @test abs(res.Q_root - Q_pin) < 1e-3 @@ -135,14 +135,14 @@ # so to put a root at Q = Q_pin_k we need dp[k,k] = Q_pin_k (the # full complex value, not just its real part). Q_a, Q_b = 0.7 - 0.3im, -0.4 + 0.5im - sc1 = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - ComplexF64(0); scale=1.0, tauk=1.0) - sc2 = surface_coupling(LinModel(0.0im, 1.0+0im), nothing, - ComplexF64(0); scale=1.0, tauk=1.0) + sc1 = surface_coupling(LinModel(0.0im, 1.0 + 0im), nothing, + ComplexF64(0); scale=1.0, tauk=1.0) + sc2 = surface_coupling(LinModel(0.0im, 1.0 + 0im), nothing, + ComplexF64(0); scale=1.0, tauk=1.0) dp = ComplexF64[Q_a 0.0; 0.0 Q_b] # diagonal Δ' mc = multi_surface_coupling([sc1, sc2], dp) scan_c = brute_force_scan(mc, (-1.0, 1.5), (-1.0, 1.0); - nre=120, nim=100, threaded=false) + nre=120, nim=100, threaded=false) res_c = find_growth_rates(scan_c, mc.surfaces[mc.ref_idx].tauk) # With diagonal Δ', det = (Q_a - Q)·(Q_b - Q) → roots at Q_a, Q_b. # The higher-γ root is Q_b (γ = 0.5). diff --git a/test/runtests_equil.jl b/test/runtests_equil.jl index 84dc30c58..7ff86b067 100644 --- a/test/runtests_equil.jl +++ b/test/runtests_equil.jl @@ -238,8 +238,12 @@ using TOML @test_throws r"set kinetic_file in \[Equilibrium\]" GPEC.parse_deck(with(d -> d["ForceFreeStates"]["kinetic"] = "KineticForces"), template) # Values take their field types: an array becomes a range or a tuple, a string a Symbol. @test GPEC.parse_deck(with(d -> d["ForceFreeStates"]["nn"] = [1, 2]), template).force_balance.keywords[:nn] == 1:2 - tearing = GPEC.tearing_from_deck(Dict{String,Any}("Tearing" => Dict{String,Any}("inner_model" => "SLAYER", "coupling_mode" => "coupled", - "search" => Dict{String,Any}("Q_re_range" => [-2, 2]), "CriticalResonantField" => Dict{String,Any}("n" => 500)))) + tearing = GPEC.tearing_from_deck( + Dict{String,Any}( + "Tearing" => Dict{String,Any}("inner_model" => "SLAYER", "coupling_mode" => "coupled", + "search" => Dict{String,Any}("Q_re_range" => [-2, 2]), "CriticalResonantField" => Dict{String,Any}("n" => 500)) + ) + ) @test tearing.problem[:coupling_mode] === :coupled @test tearing.config.Q_re_range === (-2.0, 2.0) @test tearing.problem[:critical_resonant_field].n == 500 diff --git a/test/runtests_fouriertransforms.jl b/test/runtests_fouriertransforms.jl index b1013d9b5..2eb09fd64 100644 --- a/test/runtests_fouriertransforms.jl +++ b/test/runtests_fouriertransforms.jl @@ -16,7 +16,7 @@ const ATOL_TIGHT = 1e-12 # in-place vs allocating / formula-vs-formula checks @testset "single real mode → ±m amplitudes" begin N, mlow, mpert = 64, -10, 21 # modes -10..10 ft = FourierTransform(N, mpert, mlow) - θ = range(; start=0, length=N, step=2π/N) + θ = range(; start=0, length=N, step=2π / N) # cos(m0 θ): real 0.5 at m = ±m0, zero elsewhere; imag ≈ 0 everywhere. m0 = 3 @@ -36,7 +36,7 @@ const ATOL_TIGHT = 1e-12 # in-place vs allocating / formula-vs-formula checks @testset "single complex mode → Kronecker delta" begin N, mlow, mpert = 64, -10, 21 ft = FourierTransform(N, mpert, mlow) - θ = collect(range(; start=0, length=N, step=2π/N)) + θ = collect(range(; start=0, length=N, step=2π / N)) for m0 in (3, -2, 0) modes = ft(exp.(im .* m0 .* θ)) @@ -65,7 +65,7 @@ const ATOL_TIGHT = 1e-12 # in-place vs allocating / formula-vs-formula checks @testset "matrix input transforms columns independently" begin N, mlow, mpert = 48, -8, 17 # modes -8..8 ft = FourierTransform(N, mpert, mlow) - θ = collect(range(; start=0, length=N, step=2π/N)) + θ = collect(range(; start=0, length=N, step=2π / N)) data = hcat(cos.(3 .* θ), sin.(5 .* θ)) modes = ft(data) @@ -88,7 +88,7 @@ end basis = compute_fourier_coefficients(N, m_modes, n, ζ) @test size(basis) == (mpert, N) - θ = collect(range(; start=0, length=N, step=2π/N)) + θ = collect(range(; start=0, length=N, step=2π / N)) for (l, m) in enumerate(m_modes) expected = exp.(-im .* (m .* θ .- n .* ζ)) @test all(isapprox.(basis[l, :], expected; atol)) diff --git a/test/runtests_galerkin_cholesky.jl b/test/runtests_galerkin_cholesky.jl index 3b0130b84..11a38764f 100644 --- a/test/runtests_galerkin_cholesky.jl +++ b/test/runtests_galerkin_cholesky.jl @@ -8,7 +8,7 @@ using LinearAlgebra @test FFS.empty_galerkin_result().solver == "none" n, kl, fixed = 24, 3, [1, 2, 24] H = zeros(ComplexF64, n, n) - for j in 1:n, i in max(1, j-kl):min(n, j+kl) + for j in 1:n, i in max(1, j - kl):min(n, j + kl) H[i, j] = i == j ? 4 + sin(j) : 0.3 * cis(0.3i + 0.7j) end H = (H + H') / 2 # diagonally dominant → positive definite @@ -17,7 +17,7 @@ using LinearAlgebra A[fixed, :] .= 0 A[fixed, fixed] = I(length(fixed)) ab = zeros(ComplexF64, 3kl + 1, n) - for j in 1:n, i in max(1, j-kl):min(n, j+kl) + for j in 1:n, i in max(1, j - kl):min(n, j + kl) ab[2kl+1+i-j, j] = A[i, j] end return A, ab @@ -91,7 +91,7 @@ using LinearAlgebra kl_rect, ku_rect = 2, 1 A = ComplexF64[3 0.1 0; 0.2 3 0.1; 0.1 0.2 3] ab = zeros(ComplexF64, 2kl_rect + ku_rect + 1, 3) - for j in 1:3, i in max(1, j-ku_rect):min(3, j+kl_rect) + for j in 1:3, i in max(1, j - ku_rect):min(3, j + kl_rect) ab[kl_rect+ku_rect+1+i-j, j] = A[i, j] end b = ones(ComplexF64, 3, 1) @@ -120,7 +120,7 @@ end intr = FFS.ForceFreeStatesInternal(; mlow=1, mhigh=2, nlow=1, nhigh=1, numpert_total=2) for x in (xs..., 0.42), q in (1.0, 1.4) L = reshape(lower(x), 2, 2) - Q = Diagonal([1-q, 2-q]) + Q = Diagonal([1 - q, 2 - q]) expected = Q * L * L' * Q F, K, G = FFS.gal_get_fkg(mats, intr, x, q) @test F ≈ expected diff --git a/test/runtests_imas.jl b/test/runtests_imas.jl index de35804fc..e0b5f6131 100644 --- a/test/runtests_imas.jl +++ b/test/runtests_imas.jl @@ -20,52 +20,52 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # COCOS 11: ψ_IMAS = 2π × ψ_internal psi_axis_int = 0.0 - psi_bnd_int = 1.5 # Wb/rad + psi_bnd_int = 1.5 # Wb/rad cf = cocos == 11 ? 2π : 1.0 - eqt.global_quantities.psi_axis = psi_axis_int * cf - eqt.global_quantities.psi_boundary = psi_bnd_int * cf + eqt.global_quantities.psi_axis = psi_axis_int * cf + eqt.global_quantities.psi_boundary = psi_bnd_int * cf nw = 64 psi_1d = collect(LinRange(psi_axis_int, psi_bnd_int, nw)) - eqt.profiles_1d.psi = psi_1d .* cf - eqt.profiles_1d.f = fill(5.0, nw) + eqt.profiles_1d.psi = psi_1d .* cf + eqt.profiles_1d.f = fill(5.0, nw) eqt.profiles_1d.pressure = collect(LinRange(1e4, 0.0, nw)) - eqt.profiles_1d.q = collect(LinRange(1.0, 3.0, nw)) + eqt.profiles_1d.q = collect(LinRange(1.0, 3.0, nw)) # Minimal 2D ψ(R,Z) — rough circular flux surfaces nR, nZ = 32, 40 R_grid = collect(LinRange(1.0, 2.5, nR)) Z_grid = collect(LinRange(-0.8, 0.8, nZ)) - Rmag = 1.75 + Rmag = 1.75 psi_rz = [min((R - Rmag)^2 / 0.6 + Z^2 / 0.7, psi_bnd_int * 1.4) for R in R_grid, Z in Z_grid] resize!(eqt.profiles_2d, 1; wipe=true) - prof2d = eqt.profiles_2d[1] + prof2d = eqt.profiles_2d[1] prof2d.grid_type.index = 1 - prof2d.grid.dim1 = R_grid - prof2d.grid.dim2 = Z_grid - prof2d.psi = psi_rz .* cf + prof2d.grid.dim1 = R_grid + prof2d.grid.dim2 = Z_grid + prof2d.psi = psi_rz .* cf return dd, psi_bnd_int end # Test 1: read_imas — COCOS 11 conversion produces correct psio @testset "read_imas: COCOS 11 conversion" begin - dd, psi_bnd_int = make_mock_dd(cocos=11) + dd, psi_bnd_int = make_mock_dd(; cocos=11) config = EquilibriumConfig(; eq_type="imas", eq_filename="mock", imas_cocos=11) result = Equilibrium.read_imas(config, dd) # psio should equal |psi_boundary - psi_axis| in internal (COCOS 2) units @test isapprox(result.psio, psi_bnd_int; rtol=1e-6) - @test result.rmin ≈ 1.0 atol=1e-9 - @test result.rmax ≈ 2.5 atol=1e-9 + @test result.rmin ≈ 1.0 atol = 1e-9 + @test result.rmax ≈ 2.5 atol = 1e-9 end # Test 2: read_imas — COCOS 2 input requires no conversion @testset "read_imas: COCOS 2 no-op conversion" begin - dd, psi_bnd_int = make_mock_dd(cocos=2) + dd, psi_bnd_int = make_mock_dd(; cocos=2) config = EquilibriumConfig(; eq_type="imas", eq_filename="mock", imas_cocos=2) result = Equilibrium.read_imas(config, dd) @@ -133,16 +133,16 @@ using GeneralizedPerturbedEquilibrium.Equilibrium dd = IMASdd.dd() # Mock result: npert=1 (n=1 only), 3 eigenvalues sorted ascending - mock_et = [0.4+0im, 0.7+0im, 1.1+0im] - mock_n_idx = [0, 0, 0] # all belong to n=1 (j=0) - mock_result = ( - ffs = (integrator=:forward, free_boundary=(et=mock_et, n_tor_idx=mock_n_idx), + mock_et = [0.4 + 0im, 0.7 + 0im, 1.1 + 0im] + mock_n_idx = [0, 0, 0] # all belong to n=1 (j=0) + mock_result = ( + ffs=(integrator=:forward, free_boundary=(et=mock_et, n_tor_idx=mock_n_idx), numpert_total=3, npert=1, nlow=1), ) GeneralizedPerturbedEquilibrium.write_imas(dd, mock_result) - @test dd.mhd_linear.code.name == "GPEC" + @test dd.mhd_linear.code.name == "GPEC" @test dd.mhd_linear.ideal_flag == 1 @test length(dd.mhd_linear.time_slice) == 1 @@ -163,10 +163,10 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # et sorted ascending (least stable globally first). # n=1 (j=0) has eigenvalues: real=0.3 (idx 1) and real=0.6 (idx 3) # n=2 (j=1) has eigenvalues: real=0.5 (idx 2) and real=0.7 (idx 4) - mock_et = [0.3+0im, 0.5+0im, 0.6+0im, 0.7+0im] + mock_et = [0.3 + 0im, 0.5 + 0im, 0.6 + 0im, 0.7 + 0im] mock_n_idx = [0, 1, 0, 1] mock_result = ( - ffs = (integrator=:forward, free_boundary=(et=mock_et, n_tor_idx=mock_n_idx), + ffs=(integrator=:forward, free_boundary=(et=mock_et, n_tor_idx=mock_n_idx), numpert_total=4, npert=2, nlow=1), ) @@ -190,7 +190,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # Single n=1 run dd_single = IMASdd.dd() result_single = ( - ffs = (integrator=:forward, free_boundary=(et=[0.3+0im, 0.6+0im], n_tor_idx=[0, 0]), + ffs=(integrator=:forward, free_boundary=(et=[0.3 + 0im, 0.6 + 0im], n_tor_idx=[0, 0]), numpert_total=2, npert=1, nlow=1), ) GeneralizedPerturbedEquilibrium.write_imas(dd_single, result_single) @@ -198,7 +198,7 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # Single n=2 run dd_single2 = IMASdd.dd() result_single2 = ( - ffs = (integrator=:forward, free_boundary=(et=[0.5+0im, 0.7+0im], n_tor_idx=[0, 0]), + ffs=(integrator=:forward, free_boundary=(et=[0.5 + 0im, 0.7 + 0im], n_tor_idx=[0, 0]), numpert_total=2, npert=1, nlow=2), ) GeneralizedPerturbedEquilibrium.write_imas(dd_single2, result_single2) @@ -206,14 +206,14 @@ using GeneralizedPerturbedEquilibrium.Equilibrium # Combined n=1,2 run (same eigenvalues, now interleaved) dd_multi = IMASdd.dd() result_multi = ( - ffs = (integrator=:forward, free_boundary=(et=[0.3+0im, 0.5+0im, 0.6+0im, 0.7+0im], n_tor_idx=[0, 1, 0, 1]), + ffs=(integrator=:forward, free_boundary=(et=[0.3 + 0im, 0.5 + 0im, 0.6 + 0im, 0.7 + 0im], n_tor_idx=[0, 1, 0, 1]), numpert_total=4, npert=2, nlow=1), ) GeneralizedPerturbedEquilibrium.write_imas(dd_multi, result_multi) - ts_single = dd_single.mhd_linear.time_slice[1] + ts_single = dd_single.mhd_linear.time_slice[1] ts_single2 = dd_single2.mhd_linear.time_slice[1] - ts_multi = dd_multi.mhd_linear.time_slice[1] + ts_multi = dd_multi.mhd_linear.time_slice[1] # n=1 energy from combined run must match the standalone n=1 run @test ts_multi.toroidal_mode[1].energy_perturbed == ts_single.toroidal_mode[1].energy_perturbed diff --git a/test/runtests_kinetic.jl b/test/runtests_kinetic.jl index 5b0371798..1b03704e1 100644 --- a/test/runtests_kinetic.jl +++ b/test/runtests_kinetic.jl @@ -807,7 +807,10 @@ using TOML deck = TOML.parsefile(joinpath(template, "gpec.toml")) sol = GeneralizedPerturbedEquilibrium.analytic_config(deck) # A relative kinetic_file resolves against the deck directory, like eq_filename. - config = GeneralizedPerturbedEquilibrium.equilibrium_config(merge(deck, Dict{String,Any}("Equilibrium" => merge(deck["Equilibrium"], Dict{String,Any}("kinetic_file" => relpath(h5, template))))), template) + config = GeneralizedPerturbedEquilibrium.equilibrium_config( + merge(deck, Dict{String,Any}("Equilibrium" => merge(deck["Equilibrium"], Dict{String,Any}("kinetic_file" => relpath(h5, template))))), + template + ) @test config.kinetic_file == normpath(h5) raw = E.read_kinetic_file(h5) equil = E.PlasmaEquilibrium(config, sol) diff --git a/test/runtests_layer_overlap_fitzpatrick.jl b/test/runtests_layer_overlap_fitzpatrick.jl index 5ed370391..bb1f86a49 100644 --- a/test/runtests_layer_overlap_fitzpatrick.jl +++ b/test/runtests_layer_overlap_fitzpatrick.jl @@ -123,7 +123,7 @@ psi1 = overlap_psi(1) @test psi1 !== nothing - psi1 === nothing || @info "Fitzpatrick 2025 overlap, n = 1" psi=psi1 paper=0.9985 deviation=abs(psi1 - 0.9985) atol=1e-4 + psi1 === nothing || @info "Fitzpatrick 2025 overlap, n = 1" psi = psi1 paper = 0.9985 deviation = abs(psi1 - 0.9985) atol = 1e-4 # Paper: Psi = 0.9985 (n = 1); measured deviation 1.1e-5. The bound covers the pedestal read # off Fig. 8 and the resistivity closure (Spitzer-Harm here against the paper's Eqs. 70-72), # and still leaves ~9x margin. Pure quadrature and root-finding, no BLAS, so platform spread @@ -132,7 +132,7 @@ psi4 = overlap_psi(4) @test psi4 !== nothing - psi4 === nothing || @info "Fitzpatrick 2025 overlap, n = 4" psi=psi4 paper=0.9952 deviation=abs(psi4 - 0.9952) atol=1e-3 + psi4 === nothing || @info "Fitzpatrick 2025 overlap, n = 4" psi = psi4 paper = 0.9952 deviation = abs(psi4 - 0.9952) atol = 1e-3 # Paper: Psi = 0.9952 (n = 4); measured deviation 2.3e-4. Looser than n = 1 because these # surfaces sit further in, where the digitised pedestal shape matters more. @test isapprox(psi4, 0.9952; atol=1e-3) @@ -301,7 +301,8 @@ end trunc_dir = joinpath(dirname(@__DIR__), "examples", "DIIID-like_truncation_example") trunc_inputs = TOML.parsefile(joinpath(trunc_dir, "gpec.toml")) diiid(psihigh) = Equilibrium.PlasmaEquilibrium( - GeneralizedPerturbedEquilibrium.equilibrium_config(Dict{String,Any}("Equilibrium" => merge(trunc_inputs["Equilibrium"], Dict("psihigh" => psihigh))), trunc_dir), nothing) + GeneralizedPerturbedEquilibrium.equilibrium_config(Dict{String,Any}("Equilibrium" => merge(trunc_inputs["Equilibrium"], Dict("psihigh" => psihigh))), trunc_dir), + nothing) long, short = diiid(0.9999), diiid(0.995) # One lower X-point, 1e-4 outside this file's boundary; the law reproduces the traced shear. diff --git a/test/runtests_multiion.jl b/test/runtests_multiion.jl index 2cf775e6e..ed2e78d9e 100644 --- a/test/runtests_multiion.jl +++ b/test/runtests_multiion.jl @@ -27,8 +27,9 @@ using HDF5 @testset "IonSpecies + TOML conversion" begin # TOML.jl parses [[Equilibrium.ion_species]] as a Vector{Any} of Dicts. v = Any[Dict("z" => 1, "m" => 2, "fraction" => 0.5), Dict("z" => 1, "m" => 3, "fraction" => 0.5)] - c = GeneralizedPerturbedEquilibrium.equilibrium_config(Dict{String,Any}("Equilibrium" => - Dict{String,Any}("eq_type" => "efit", "kinetic_file" => "k.h5", "ion_species" => v)), ".") + c = GeneralizedPerturbedEquilibrium.equilibrium_config( + Dict{String,Any}("Equilibrium" => + Dict{String,Any}("eq_type" => "efit", "kinetic_file" => "k.h5", "ion_species" => v)), ".") @test length(c.ion_species) == 2 @test (c.ion_species[1].z, c.ion_species[1].m, c.ion_species[1].fraction) == (1, 2, 0.5) @test GeneralizedPerturbedEquilibrium.Equilibrium.EquilibriumConfig().ion_species === nothing # default single-ion diff --git a/test/runtests_parallel_integration.jl b/test/runtests_parallel_integration.jl index 61bd56a61..7ddba18d9 100644 --- a/test/runtests_parallel_integration.jl +++ b/test/runtests_parallel_integration.jl @@ -67,8 +67,8 @@ end GeneralizedPerturbedEquilibrium.ForceFreeStates.apply_propagator!(odet, prop) - @test odet.u[:, :, 1] ≈ u1_in rtol=1e-12 - @test odet.u[:, :, 2] ≈ u2_in rtol=1e-12 + @test odet.u[:, :, 1] ≈ u1_in rtol = 1e-12 + @test odet.u[:, :, 2] ≈ u2_in rtol = 1e-12 end @testset "apply_propagator! linearity" begin @@ -104,8 +104,8 @@ end u1_expected = U1_upper * u1_in + U1_lower * u2_in u2_expected = U2_upper * u1_in + U2_lower * u2_in - @test odet.u[:, :, 1] ≈ u1_expected rtol=1e-12 - @test odet.u[:, :, 2] ≈ u2_expected rtol=1e-12 + @test odet.u[:, :, 1] ≈ u1_expected rtol = 1e-12 + @test odet.u[:, :, 2] ≈ u2_expected rtol = 1e-12 end @testset "apply_propagator_inverse! is inverse of apply_propagator!" begin @@ -139,8 +139,8 @@ end GeneralizedPerturbedEquilibrium.ForceFreeStates.apply_propagator_inverse!(odet, prop) GeneralizedPerturbedEquilibrium.ForceFreeStates.apply_propagator!(odet, prop) - @test odet.u[:, :, 1] ≈ u1_in rtol=1e-12 - @test odet.u[:, :, 2] ≈ u2_in rtol=1e-12 + @test odet.u[:, :, 1] ≈ u1_in rtol = 1e-12 + @test odet.u[:, :, 2] ≈ u2_in rtol = 1e-12 end @testset "balance_integration_chunks produces target count" begin @@ -176,7 +176,7 @@ end # gap of ≈2·singfac_min/|n·q1| between the pre-crossing and post-crossing intervals. for i in eachindex(balanced)[2:end] if !balanced[i-1].needs_crossing - @test balanced[i].psi_start ≈ balanced[i-1].psi_end rtol=1e-10 + @test balanced[i].psi_start ≈ balanced[i-1].psi_end rtol = 1e-10 else # Inner-layer gap: post-crossing chunk starts AFTER the rational surface @test balanced[i].psi_start > balanced[i-1].psi_end @@ -204,7 +204,7 @@ end # An nchunks below the singular-surface floor is clamped up, with a warning. min_chunks = 2 * intr.msing + 3 ctrl_few = first(_prepared_solovev("Riccati"; nchunks=1)) - balanced_few = @test_logs (:warn,) match_mode=:any GeneralizedPerturbedEquilibrium.ForceFreeStates.balance_integration_chunks(base_chunks, ctrl_few, intr) + balanced_few = @test_logs (:warn,) match_mode = :any GeneralizedPerturbedEquilibrium.ForceFreeStates.balance_integration_chunks(base_chunks, ctrl_few, intr) @test length(balanced_few) == max(min_chunks, length(base_chunks)) end diff --git a/test/runtests_riccati.jl b/test/runtests_riccati.jl index 76eead85b..b3904b970 100644 --- a/test/runtests_riccati.jl +++ b/test/runtests_riccati.jl @@ -28,8 +28,8 @@ end 0.0 1.2+0.1im 0.0im 0.2; 0.1+0.1im 0.0 0.9+0.3im 0.1im; 0.0im 0.2 0.0 1.1+0.2im] - U1 = rng .+ 0.5*I(N) - U2 = 0.5*rng .+ I(N) # near-identity to ensure invertibility + U1 = rng .+ 0.5 * I(N) + U2 = 0.5 * rng .+ I(N) # near-identity to ensure invertibility u = zeros(ComplexF64, N, N, 2) u[:, :, 1] .= U1 @@ -40,7 +40,7 @@ end FFS.renormalize_riccati_inplace!(u, N) @test u[:, :, 2] ≈ I(N) - @test u[:, :, 1] ≈ S_expected rtol=1e-12 + @test u[:, :, 1] ≈ S_expected rtol = 1e-12 end @testset "renormalize_riccati_inplace! idempotent" begin @@ -56,7 +56,7 @@ end FFS.renormalize_riccati_inplace!(u, N) @test u[:, :, 2] ≈ I(N) - @test u[:, :, 1] ≈ S rtol=1e-12 + @test u[:, :, 1] ≈ S rtol = 1e-12 end @testset "renormalize_riccati! (OdeState)" begin @@ -64,8 +64,8 @@ end rng = [1.0+0.5im 0.2im 0.1; 0.0im 1.2+0.1im 0.0; 0.1+0.1im 0.0 0.9+0.3im] - U1 = rng .+ 0.5*I(N) - U2 = 0.2*rng .+ I(N) + U1 = rng .+ 0.5 * I(N) + U2 = 0.2 * rng .+ I(N) odet = FFS.OdeState(N, 10, 5, 1) odet.u[:, :, 1] .= U1 @@ -77,7 +77,7 @@ end FFS.renormalize_riccati!(odet, intr) @test odet.u[:, :, 2] ≈ I(N) - @test odet.u[:, :, 1] ≈ S_expected rtol=1e-12 + @test odet.u[:, :, 1] ≈ S_expected rtol = 1e-12 end # ── Shared Solovev setup ────────────────────────────────────────────────── @@ -134,7 +134,7 @@ end @testset "Riccati end state has U₂ ≈ I" begin # The outer-region re-integration that closes riccati_eulerlagrange_integration # leaves odet.u[:,:,2] as the identity (canonical Riccati convention after final renorm) - @test odet_ric.u[:, :, 2] ≈ I(N) rtol=1e-10 + @test odet_ric.u[:, :, 2] ≈ I(N) rtol = 1e-10 end @testset "riccati_der! formula — Glasser 2018 Eq. 19" begin diff --git a/test/runtests_sfl_sampling.jl b/test/runtests_sfl_sampling.jl index 161a43c12..d6506fd15 100644 --- a/test/runtests_sfl_sampling.jl +++ b/test/runtests_sfl_sampling.jl @@ -18,10 +18,12 @@ using GeneralizedPerturbedEquilibrium @testset "Solovev: rzphi independent of ψ resolution and on the exact surfaces" begin sc = Eq.SolovevConfig(64, 64, 64, 1.6, 0.33, 1.0, 1.9, 1.0, 1.0, 1.0) - sol_eq(mpsi) = Eq.equilibrium_solver(Eq.sol_run( - Eq.EquilibriumConfig(; eq_type="sol", eq_filename="unused", jac_type="pest", grid_type="core_edge_packed", - psilow=1e-4, psihigh=0.99999, mpsi=mpsi, mtheta=128), - sc)) + sol_eq(mpsi) = Eq.equilibrium_solver( + Eq.sol_run( + Eq.EquilibriumConfig(; eq_type="sol", eq_filename="unused", jac_type="pest", grid_type="core_edge_packed", + psilow=1e-4, psihigh=0.99999, mpsi=mpsi, mtheta=128), + sc) + ) coarse, fine = sol_eq(64), sol_eq(128) # ν is identically zero for this equilibrium, so it carries no signal. for field in (:rzphi_offset, :rzphi_jac, :rzphi_rsquared) @@ -44,8 +46,10 @@ using GeneralizedPerturbedEquilibrium @testset "EFIT: efit and efit_arclength tracers agree" begin efit_file = joinpath(@__DIR__, "test_data", "CHEASE_test_data", "EQDSK_COCOS_02") - efit_eq(kind) = Eq.PlasmaEquilibrium(Eq.EquilibriumConfig(; eq_filename=efit_file, eq_type=kind, - jac_type="boozer", grid_type="core_edge_packed", psilow=0.01, psihigh=0.994, mpsi=64, mtheta=128)) + efit_eq(kind) = Eq.PlasmaEquilibrium( + Eq.EquilibriumConfig(; eq_filename=efit_file, eq_type=kind, + jac_type="boozer", grid_type="core_edge_packed", psilow=0.01, psihigh=0.994, mpsi=64, mtheta=128) + ) direct, arclength = efit_eq("efit"), efit_eq("efit_arclength") # Two integrators with different step sequences along the same surfaces. Measured: Jacobian 8.7e-8 # and ν 1.7e-7 when both sample at common abscissae; 2.9e-4 and 1.1e-5 with per-surface resampling. diff --git a/test/runtests_sing.jl b/test/runtests_sing.jl index 18d11fec7..277d57bd8 100644 --- a/test/runtests_sing.jl +++ b/test/runtests_sing.jl @@ -233,7 +233,8 @@ using FastInterpolations: cubic_interp, CubicFit, LinearBinarySearch, Series, Ex @test isapprox(intr.qlim, equil.params.qmax; atol=1e-12) @test isapprox(intr.psilim, equil.params.psihigh_resolved; atol=1e-12) - ctrl = GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; qhigh=max(equil.params.qmin + 0.1, equil.params.qmax - 0.5), truncate_at_rational_offset=false) + ctrl = + GeneralizedPerturbedEquilibrium.ForceFreeStates.ForceFreeStatesControl(; qhigh=max(equil.params.qmin + 0.1, equil.params.qmax - 0.5), truncate_at_rational_offset=false) GeneralizedPerturbedEquilibrium.ForceFreeStates.sing_lim!(intr, ctrl, equil) @test intr.qlim < equil.params.qmax + 1e-12 @test intr.psilim <= equil.params.psihigh_resolved diff --git a/test/runtests_slayer_inputs.jl b/test/runtests_slayer_inputs.jl index 851d5dbda..89b27dfbd 100644 --- a/test/runtests_slayer_inputs.jl +++ b/test/runtests_slayer_inputs.jl @@ -193,7 +193,7 @@ end @testset "build_slayer_inputs: P_perp_model forwards the profile gradients and minor radius" begin - sings = [_mk_sing(psi=0.5, q=2.4, q1=1.2, m=2, n=1)] + sings = [_mk_sing(; psi=0.5, q=2.4, q1=1.2, m=2, n=1)] kw = (; bt=2.0, chi_perp_e=2.0, chi_perp_i=1.0, chi_tor=1.5, dr_val=0.0) ref = build_slayer_inputs(equil, sings, profiles; P_perp_model=:chi_perp_e, kw...)[1] # Flat n_e and linear T_e, T_i: the D_⊥ weights are T_s′/(T_e′ + T_i′) = 7/13 and 6/13 diff --git a/test/runtests_slayer_runner.jl b/test/runtests_slayer_runner.jl index 947a2e7c1..e3f205cbc 100644 --- a/test/runtests_slayer_runner.jl +++ b/test/runtests_slayer_runner.jl @@ -188,7 +188,8 @@ # The LAR deck carries no kinetic profiles, so a missing ρ is named in the error. @test_throws "GGJ tearing: give rho, or load kinetic profiles" solve(TearingProblem(ffs; eta=1e-7), GGJModel(); config=TearingConfig(; gamma_range=(600.0, 2600.0), omega_range=(-1500.0, 1500.0))) - @test_throws "SLAYER input" solve(TearingProblem(ffs; eta=1e-7, rho=1e-7, + @test_throws "SLAYER input" solve( + TearingProblem(ffs; eta=1e-7, rho=1e-7, critical_resonant_field=GeneralizedPerturbedEquilibrium.Tearing.CriticalResonantFieldControl()), GGJModel(); config=TearingConfig(; gamma_range=(600.0, 2600.0), omega_range=(-1500.0, 1500.0))) end diff --git a/test/runtests_solve_api.jl b/test/runtests_solve_api.jl index 134ae9129..78f35b5d6 100644 --- a/test/runtests_solve_api.jl +++ b/test/runtests_solve_api.jl @@ -199,8 +199,11 @@ using HDF5 @test dp.matrix ≈ FFS.pest3_decompose(dp.raw).Δ @test dp.A !== nothing # the parity blocks the galerkin solve persists - reference = GPEC.main([_stage_deck(dir; ffs_overrides=Dict{String,Any}("integrator" => "Galerkin"), - extra_sections=Dict{String,Any}("Galerkin" => Dict{String,Any}("nx" => 32)))]).ffs + reference = + GPEC.main([ + _stage_deck(dir; ffs_overrides=Dict{String,Any}("integrator" => "Galerkin"), + extra_sections=Dict{String,Any}("Galerkin" => Dict{String,Any}("nx" => 32))) + ]).ffs @test reference.galerkin.msing == msing @test dp.matrix ≈ reference.delta_prime.matrix rtol = 1e-12 @test dp.raw ≈ reference.delta_prime.raw rtol = 1e-12 @@ -287,7 +290,7 @@ using HDF5 @test d.terms[2].scale == 1.0 + 0.0im @test (im * a).scale == im @test (a * 3).scale == 3.0 + 0.0im - @test (a - b).terms[2].scale == -0.5 + 0.0im + @test (a-b).terms[2].scale == -0.5 + 0.0im @test (-a).scale == -1.0 + 0.0im end @@ -553,9 +556,10 @@ using HDF5 @testset "deck kinetic source names" begin # A deck selects only the KineticForces model; test matrices and the retired key stop the parse. - parsed(overrides) = mktempdir() do dir - GPEC.parse_deck(TOML.parsefile(joinpath(_stage_deck(dir; ffs_overrides=overrides), "gpec.toml")), dir) - end + parsed(overrides) = + mktempdir() do dir + GPEC.parse_deck(TOML.parsefile(joinpath(_stage_deck(dir; ffs_overrides=overrides), "gpec.toml")), dir) + end @test_throws "script-only" parsed(Dict{String,Any}("kinetic" => "TestKineticMatrices")) @test_throws "not a kinetic source" parsed(Dict{String,Any}("kinetic" => "fixed")) @test_throws "no longer a key" parsed(Dict{String,Any}("kinetic_source" => "fixed")) diff --git a/test/runtests_vacuum.jl b/test/runtests_vacuum.jl index 2184fe2e2..bdea95309 100644 --- a/test/runtests_vacuum.jl +++ b/test/runtests_vacuum.jl @@ -879,11 +879,11 @@ using GeneralizedPerturbedEquilibrium.Vacuum: ConformalWall, EllipticalWall, Dee # so the two agree only if both use the same relation. Negating ν in 2D alone misses by O(0.1). @testset "2D and 3D paths agree for a nonzero ν" begin mtheta = 48 - θ = range(; start=0, length=mtheta, step=2π/mtheta) + θ = range(; start=0, length=mtheta, step=2π / mtheta) R = 1.7 .+ 0.3 .* cos.(θ) Z = 0.3 .* sin.(θ) .+ 0.08 .* sin.(2θ) .+ 0.08 .* cos.(θ) ν = 0.25 .* sin.(θ) .+ 0.1 .* cos.(2θ) .+ 0.05 - make(nzeta, ν) = VacuumInput(x=collect(R), z=collect(Z), ν=collect(ν), + make(nzeta, ν) = VacuumInput(; x=collect(R), z=collect(Z), ν=collect(ν), mtheta_in=mtheta, nzeta_in=1, m_modes=collect(-3:3), n_modes=[1], mtheta=mtheta, nzeta=nzeta) nowall = nothing @@ -896,7 +896,7 @@ using GeneralizedPerturbedEquilibrium.Vacuum: ConformalWall, EllipticalWall, Dee # D = diag(exp(i·m·a)). An operator left in the conjugate frame follows D†·A·D instead and fails this by O(0.1). @testset "wv and I_v follow a θ-origin shift in the same Fourier frame" begin mtheta, k = 64, 4 - θ = range(; start=0, length=mtheta, step=2π/mtheta) + θ = range(; start=0, length=mtheta, step=2π / mtheta) R = 1.7 .+ 0.5 .* cos.(θ .+ 0.3 .* sin.(θ)) Z = 0.8 .* sin.(θ) .+ 0.08 .* cos.(θ) .+ 0.1 .* cos.(2θ) m_modes = collect(-4:6) @@ -914,21 +914,22 @@ using GeneralizedPerturbedEquilibrium.Vacuum: ConformalWall, EllipticalWall, Dee @testset "clockwise contours" begin mtheta = 32 - θ = range(; start=0, length=mtheta, step=2π/mtheta) + θ = range(; start=0, length=mtheta, step=2π / mtheta) R, Z = 1.7 .+ 0.3 .* cos.(θ), 0.4 .* sin.(θ) make(x, z) = VacuumInput(; x, z, ν=zeros(mtheta), mtheta_in=mtheta, nzeta_in=1, m_modes=collect(-2:2), n_modes=[1], mtheta, nzeta=1) @test_throws ArgumentError compute_vacuum_response(make(reverse(R), reverse(Z)), nothing) # A wall file written clockwise is turned round and gives the same operator as its counter-clockwise twin Rw, Zw = 1.7 .+ 0.6 .* cos.(θ), 0.8 .* sin.(θ) - wall_response(x, z) = mktempdir() do dir - path = joinpath(dir, "wall.dat") - open(path, "w") do io - println(io, mtheta, "\n", 1.7, "\nindex R Z") - foreach(i -> println(io, i, " ", x[i], " ", z[i]), 1:mtheta) + wall_response(x, z) = + mktempdir() do dir + path = joinpath(dir, "wall.dat") + open(path, "w") do io + println(io, mtheta, "\n", 1.7, "\nindex R Z") + foreach(i -> println(io, i, " ", x[i], " ", z[i]), 1:mtheta) + end + compute_vacuum_response(make(collect(R), collect(Z)), FileWall(; file=path, equal_arc_wall=false)) end - compute_vacuum_response(make(collect(R), collect(Z)), FileWall(; file=path, equal_arc_wall=false)) - end ccw = wall_response(Rw, Zw) cw = @test_logs (:warn, r"runs clockwise") match_mode = :any wall_response(circshift(reverse(Rw), 1), circshift(reverse(Zw), 1)) @test cw.wv ≈ ccw.wv From 1883beeb073f6390064db53b263137202f5854f4 Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 19:50:44 -0500 Subject: [PATCH 3/5] Repo - MINOR - Skip the formatting sweep in git blame Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..a6cad9688 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# Commits that only reformat; `git config blame.ignoreRevsFile .git-blame-ignore-revs` makes local blame skip them. +# Format the repository with the pinned pre-commit hooks +9e57323f9221755140cb818a03e033dc7a42a4b2 From ee76864c66a29087a624f5e1562e9fcefd911f2a Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 20:01:25 -0500 Subject: [PATCH 4/5] CI - MINOR - Describe the check as enabled with the sweep and also run it on pushes to develop Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- .github/workflows/format.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml index 68b3111e2..4e53a3051 100644 --- a/.github/workflows/format.yaml +++ b/.github/workflows/format.yaml @@ -4,13 +4,15 @@ name: Format and Hygiene # contributors who have not run `pre-commit install` locally are still caught. # # The `pre-commit` job fails whenever the hooks rewrite a tracked file, so it -# reports whether the repository is currently clean under the formatter. It is -# expected to fail until the one-off `pre-commit run --all-files` sweep lands. -# -# Make `pre-commit` a required status check only after that sweep, otherwise it -# blocks every pull request on pre-existing drift. +# reports whether the repository is clean under the formatter. The repository +# was swept with `pre-commit run --all-files` when this check was enabled, so +# `pre-commit` can be a required status check. Pushes to develop are checked too, +# since two pull requests that are each clean can merge into unformatted code. on: workflow_dispatch: + push: + branches: + - develop pull_request: branches: - main From f7fe63ce8f602567460ec9efadc5c73948cb4002 Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 20:02:45 -0500 Subject: [PATCH 5/5] Docs - DOCS - Pin JuliaFormatter 1.0.62 in the setup guide and describe the pre-commit CI check An unpinned Pkg.add installs JuliaFormatter 2.x, which formats differently and would fail the check on every contributor's first PR. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- CLAUDE.md | 2 +- docs/src/set_up.md | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f5c1ad884..cbd8e2cad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -138,7 +138,7 @@ These rules apply to **every** Agent tool invocation, not just performance work. ### Code Formatting -Pre-commit hooks enforce formatting via JuliaFormatter and general file hygiene. The hook runs the developer's globally installed JuliaFormatter (the version is not currently pinned), so previously untouched files may normalize wholesale on first edit; this churn is expected and should not be reverted. **All code you write or modify must already conform to these standards before committing**, so the hooks have nothing to fix. Failing to do this creates noisy diffs in PRs where formatting changes leak into unrelated files. +Pre-commit hooks enforce formatting via JuliaFormatter and general file hygiene, and the same hooks run as the `pre-commit` CI check on every pull request. The hook runs the JuliaFormatter in the default Julia environment; CI pins **1.0.62** (`.pre-commit-config.yaml`, `.github/workflows/format.yaml`), so install exactly that version or the formatting will differ. The repository is clean under the hooks, so a file that changes when you run them changed because of your edit. **All code you write or modify must already conform to these standards before committing**, so the hooks have nothing to fix. Failing to do this creates noisy diffs in PRs where formatting changes leak into unrelated files. The project's `.JuliaFormatter.toml` settings: - **Line width**: 180 characters max (`margin = 180`) diff --git a/docs/src/set_up.md b/docs/src/set_up.md index d671f5d25..c63df74f4 100644 --- a/docs/src/set_up.md +++ b/docs/src/set_up.md @@ -419,7 +419,9 @@ end ### Pre-commit Hooks -The repository uses pre-commit hooks to maintain code quality. They run automatically on `git commit` and: +The repository uses pre-commit hooks to maintain code quality. They run automatically on `git commit`, and +the same hooks run in CI on every pull request (the `pre-commit` check), which fails if they would change a file. +They: - Format Julia code according to `.JuliaFormatter.toml` settings - Remove trailing whitespace and fix line endings - Validate YAML/TOML syntax @@ -433,8 +435,9 @@ The repository uses pre-commit hooks to maintain code quality. They run automati # Install pre-commit (requires Python/pip) pip install pre-commit -# Install JuliaFormatter globally (required for Julia code formatting hook) -julia -e 'using Pkg; Pkg.add("JuliaFormatter")' +# Install JuliaFormatter 1.0.62 in the default environment: the hook runs whatever version is there, +# and CI pins this one, so another version formats differently and fails the check +julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="1.0.62"))' # Install the git hooks in your local repository cd /path/to/GPEC