From 93255e19abcf9dae58578360394ab3073bbc9c86 Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 17:38:39 -0500 Subject: [PATCH 1/5] ForceFreeStates - BUGFIX! - Force the reduction at kinetic singular crossings in the previous pivot order Match Fortran GPEC 1.6.0: a call at a singular surface always reduces, even right after another reduction, and then keeps that reduction's pivot order. Before, a kinetic crossing reached just after a reduction only reset the reference norms and skipped the forced reduction. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- src/ForceFreeStates/EulerLagrange.jl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ForceFreeStates/EulerLagrange.jl b/src/ForceFreeStates/EulerLagrange.jl index 6e3b8be637..6f68c69114 100644 --- a/src/ForceFreeStates/EulerLagrange.jl +++ b/src/ForceFreeStates/EulerLagrange.jl @@ -777,15 +777,15 @@ end compute_solution_norms!(u::Array{ComplexF64,3}, odet::OdeState, ctrl::ForceFreeStatesControl, intr::ForceFreeStatesInternal, sing_flag::Bool; resonant_rows=Int[]) Compute the column norms of u₁ and apply `apply_gaussian_reduction!` to `u` in place when their -growth since the last reduction exceeds `ctrl.algorithm.renorm_threshold`, or when `sing_flag` is set. -The first call after a reduction only records reference norms. Errors if any norm is zero. -Port of Fortran `ode_unorm`. +growth since the last reduction exceeds `ctrl.algorithm.renorm_threshold`, or always when `sing_flag` is set. +The first call after a reduction records reference norms; if `sing_flag` forces a reduction there, it keeps +the previous reduction's pivot order. Errors if any norm is zero. Port of Fortran `ode_unorm`. ### Arguments - `u` - Solution array, updated in place (the integrator state, to avoid copies) - `sing_flag` - Whether this call is at a singular surface - - `resonant_rows` - Resonant rows at an ideal crossing; when given, the reduction always runs and pivots on them + - `resonant_rows` - Resonant rows at an ideal crossing, pivoted on first """ function compute_solution_norms!(u::Array{ComplexF64,3}, odet::OdeState, ctrl::ForceFreeStatesControl, intr::ForceFreeStatesInternal, sing_flag::Bool; resonant_rows=Int[]) @@ -796,21 +796,21 @@ function compute_solution_norms!(u::Array{ComplexF64,3}, odet::OdeState, ctrl::F error("One of the first solution vector norms unorm(1,$jmax) = 0") end - # The first call after a reduction records the reference norms; an ideal crossing reduces regardless - at_ideal_crossing = !isempty(resonant_rows) - if odet.new && !at_ideal_crossing + # A singular surface always reduces; otherwise reduce when the growth since the last reduction is too uneven + fix_required = sing_flag + if odet.new odet.new = false odet.unorm0 .= odet.unorm - return - end - - # Growth since the last reduction (raw norms if a crossing comes right after one) - if !odet.new + # A forced reduction right after another keeps that reduction's pivot order + if sing_flag && odet.ifix > 0 + odet.unorm[odet.index[:, odet.ifix]] .= (intr.numpert_total-1):-1:0 + end + else odet.unorm ./= odet.unorm0 + fix_required |= maximum(odet.unorm) / minimum(odet.unorm) > ctrl.algorithm.renorm_threshold end - uratio = maximum(odet.unorm) / minimum(odet.unorm) - if uratio > ctrl.algorithm.renorm_threshold || sing_flag + if fix_required if odet.ifix < ctrl.algorithm.numunorms_init odet.ifix += 1 else From b89935112f901719360267982722ba5dfe00d7d8 Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 17:55:28 -0500 Subject: [PATCH 2/5] ForceFreeStates - TEST - Check that a singular call right after a reduction reduces in that reduction's pivot order Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- test/runtests_eulerlagrange.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/runtests_eulerlagrange.jl b/test/runtests_eulerlagrange.jl index d818fc9b36..fc13898f7f 100644 --- a/test/runtests_eulerlagrange.jl +++ b/test/runtests_eulerlagrange.jl @@ -369,6 +369,19 @@ end odet.u[:, 2, 1] .= [1, 0] GeneralizedPerturbedEquilibrium.ForceFreeStates.compute_solution_norms!(odet.u, odet, ctrl, intr, true) @test odet.new == true # fixup triggered + + # Case 6: a singular call right after a reduction still reduces, keeping that reduction's pivot order + # rather than the raw-norm order [1, 2, 3] + FFS = GeneralizedPerturbedEquilibrium.ForceFreeStates + odet = FFS.OdeState(3, 10, 10, 1) + odet.u[:, :, 1] .= [6.0 0.4 0.2; 0.5 0.3 2.0; 0.1 5.0 1.5] + odet.u[:, :, 2] .= 1.0 + odet.ifix = 1 + odet.index[:, 1] .= [3, 1, 2] + odet.new = true + FFS.compute_solution_norms!(odet.u, odet, ctrl, FFS.ForceFreeStatesInternal(; numpert_total=3), true) + @test odet.ifix == 2 && odet.new && odet.sing_flag[2] + @test odet.index[:, 2] == [3, 1, 2] end @testset "ideal-crossing reduction isolates the resonant harmonic" begin From 4be6417614057aed2ccb9557ec95a36230c5244a Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 17:55:29 -0500 Subject: [PATCH 3/5] ForceFreeStates - BUGFIX - Stop with a clear error when no rational surface is left to truncate at With truncate_at_rational_offset on and no rational surface of n far enough below qlim, the stepped-back qlim fell below q_min and the psilim root find failed without saying why. Fortran GPEC stops at the same point. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- src/ForceFreeStates/Surfaces/Finding.jl | 4 ++++ test/runtests_layer_overlap_fitzpatrick.jl | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/ForceFreeStates/Surfaces/Finding.jl b/src/ForceFreeStates/Surfaces/Finding.jl index 61e8ec11b9..1d1eca52a6 100644 --- a/src/ForceFreeStates/Surfaces/Finding.jl +++ b/src/ForceFreeStates/Surfaces/Finding.jl @@ -148,6 +148,10 @@ function sing_lim!(intr::ForceFreeStatesInternal, ctrl::ForceFreeStatesControl, while intr.qlim > qlim_bound intr.qlim -= 1.0 / intr.nlow end + intr.qlim >= equil.params.qmin || + error("sing_lim!: no rational surface of n = $(intr.nlow) lies far enough below qlim = $(@sprintf("%.3f", qlim_bound)) " * + "(q_min = $(@sprintf("%.3f", equil.params.qmin))) to truncate at rational_offset_fraction past it. " * + "Raise qhigh or set truncate_at_rational_offset = false.") end # qlim below qmax: Newton-solve q(psilim) = qlim diff --git a/test/runtests_layer_overlap_fitzpatrick.jl b/test/runtests_layer_overlap_fitzpatrick.jl index 5ed3703911..3e63f204fe 100644 --- a/test/runtests_layer_overlap_fitzpatrick.jl +++ b/test/runtests_layer_overlap_fitzpatrick.jl @@ -196,6 +196,12 @@ end @test i.qlim <= qh end + # No rational surface far enough below the bound leaves nothing to truncate at: a clear error, not a failed root find. + qmin = equil.params.qmin + c_none = ForceFreeStatesControl(; truncate_at_rational_offset=true, rational_offset_fraction=0.2, + qhigh=min(floor(qmin) + 1 - 0.05, qmin + 0.05)) + @test_throws r"no rational surface" sing_lim!(_fresh(), c_none, equil) + # A cap placed exactly on a rational must exclude it on either side of the float knife-edge. q_of = equil.profiles.q_spline lo, hi = equil.profiles.xs[1], equil.params.psihigh_resolved From 29bdbaae3fd1abf66e736c572f2eebe8c5e42e3b Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 19:23:17 -0500 Subject: [PATCH 4/5] ForceFreeStates - BUGFIX - Check qlim against q_min on every truncation path, not only the rational offset Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF --- src/ForceFreeStates/EulerLagrange.jl | 6 +++--- src/ForceFreeStates/Surfaces/Finding.jl | 10 ++++++---- test/runtests_eulerlagrange.jl | 4 +++- test/runtests_layer_overlap_fitzpatrick.jl | 9 ++++++--- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/ForceFreeStates/EulerLagrange.jl b/src/ForceFreeStates/EulerLagrange.jl index 6f68c69114..171752942f 100644 --- a/src/ForceFreeStates/EulerLagrange.jl +++ b/src/ForceFreeStates/EulerLagrange.jl @@ -777,7 +777,7 @@ end compute_solution_norms!(u::Array{ComplexF64,3}, odet::OdeState, ctrl::ForceFreeStatesControl, intr::ForceFreeStatesInternal, sing_flag::Bool; resonant_rows=Int[]) Compute the column norms of u₁ and apply `apply_gaussian_reduction!` to `u` in place when their -growth since the last reduction exceeds `ctrl.algorithm.renorm_threshold`, or always when `sing_flag` is set. +growth since the last reduction exceeds `ctrl.algorithm.renorm_threshold`, and always when `sing_flag` is set. The first call after a reduction records reference norms; if `sing_flag` forces a reduction there, it keeps the previous reduction's pivot order. Errors if any norm is zero. Port of Fortran `ode_unorm`. @@ -801,9 +801,9 @@ function compute_solution_norms!(u::Array{ComplexF64,3}, odet::OdeState, ctrl::F if odet.new odet.new = false odet.unorm0 .= odet.unorm - # A forced reduction right after another keeps that reduction's pivot order + # A forced reduction right after another keeps that reduction's pivot order (none to keep before the first) if sing_flag && odet.ifix > 0 - odet.unorm[odet.index[:, odet.ifix]] .= (intr.numpert_total-1):-1:0 + @views odet.unorm[odet.index[:, odet.ifix]] .= (intr.numpert_total-1):-1:0 end else odet.unorm ./= odet.unorm0 diff --git a/src/ForceFreeStates/Surfaces/Finding.jl b/src/ForceFreeStates/Surfaces/Finding.jl index 1d1eca52a6..30e4549176 100644 --- a/src/ForceFreeStates/Surfaces/Finding.jl +++ b/src/ForceFreeStates/Surfaces/Finding.jl @@ -148,12 +148,14 @@ function sing_lim!(intr::ForceFreeStatesInternal, ctrl::ForceFreeStatesControl, while intr.qlim > qlim_bound intr.qlim -= 1.0 / intr.nlow end - intr.qlim >= equil.params.qmin || - error("sing_lim!: no rational surface of n = $(intr.nlow) lies far enough below qlim = $(@sprintf("%.3f", qlim_bound)) " * - "(q_min = $(@sprintf("%.3f", equil.params.qmin))) to truncate at rational_offset_fraction past it. " * - "Raise qhigh or set truncate_at_rational_offset = false.") end + # A target below q_min has no psilim: say why instead of failing in the root find, as Fortran's "Can't find psilim" + intr.qlim >= equil.params.qmin || + error("sing_lim!: the integration limit qlim = $(@sprintf("%.3f", intr.qlim)) lies below q_min = $(@sprintf("%.3f", equil.params.qmin)), " * + "so no flux surface reaches it. With truncate_at_rational_offset no rational surface of n = $(intr.nlow) is left to truncate at; " * + "widen the domain (qhigh, the layer-overlap cap) or set truncate_at_rational_offset = false.") + # qlim below qmax: Newton-solve q(psilim) = qlim if intr.qlim < equil.params.qmax # Seed from the edge inward at the outermost node with q ≤ qlim, so a reversed-shear profile, which crosses diff --git a/test/runtests_eulerlagrange.jl b/test/runtests_eulerlagrange.jl index fc13898f7f..2fe69f4417 100644 --- a/test/runtests_eulerlagrange.jl +++ b/test/runtests_eulerlagrange.jl @@ -380,7 +380,9 @@ end odet.index[:, 1] .= [3, 1, 2] odet.new = true FFS.compute_solution_norms!(odet.u, odet, ctrl, FFS.ForceFreeStatesInternal(; numpert_total=3), true) - @test odet.ifix == 2 && odet.new && odet.sing_flag[2] + @test odet.ifix == 2 + @test odet.new + @test odet.sing_flag[2] @test odet.index[:, 2] == [3, 1, 2] end diff --git a/test/runtests_layer_overlap_fitzpatrick.jl b/test/runtests_layer_overlap_fitzpatrick.jl index 3e63f204fe..61734f048d 100644 --- a/test/runtests_layer_overlap_fitzpatrick.jl +++ b/test/runtests_layer_overlap_fitzpatrick.jl @@ -197,10 +197,13 @@ end end # No rational surface far enough below the bound leaves nothing to truncate at: a clear error, not a failed root find. + # The offset puts the last rational's truncation point above qhigh and the one before it below q_min. qmin = equil.params.qmin - c_none = ForceFreeStatesControl(; truncate_at_rational_offset=true, rational_offset_fraction=0.2, - qhigh=min(floor(qmin) + 1 - 0.05, qmin + 0.05)) - @test_throws r"no rational surface" sing_lim!(_fresh(), c_none, equil) + c_none = ForceFreeStatesControl(; truncate_at_rational_offset=true, rational_offset_fraction=mod(qmin, 1) + 0.04, + qhigh=qmin + 0.02) + @test_throws r"lies below q_min" sing_lim!(_fresh(), c_none, equil) + # Without truncation, a qhigh below q_min fails the same way. + @test_throws r"lies below q_min" sing_lim!(_fresh(), ForceFreeStatesControl(; truncate_at_rational_offset=false, qhigh=qmin - 0.1), equil) # A cap placed exactly on a rational must exclude it on either side of the float knife-edge. q_of = equil.profiles.q_spline From b181766f96076d4d0546a6320f810d7194bba4a3 Mon Sep 17 00:00:00 2001 From: logan-nc Date: Sun, 1 Nov 2026 19:51:59 -0500 Subject: [PATCH 5/5] Repo - MINOR - Format the branch with the pinned pre-commit hooks 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 | 16 +- 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, 2064 insertions(+), 1886 deletions(-) diff --git a/Project.toml b/Project.toml index f3a49b5c95..f61b337b47 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 138fc91fb1..87464dc8b5 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 ceea29e317..6b5456de71 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 5b14c41b52..3b2ae96fe4 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 d9e77e1e55..46d970b372 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 6827d1d950..184fbe3548 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 9d0fa56291..0485951bef 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 a757a85467..2dc54c30d6 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 5f83146009..bd6faab8dd 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 42c2e45fd3..93cff33b32 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 9a8c9dc78a..2df1356d3a 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 c7288949ce..f93476c680 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 8dbbb521b5..19f906c551 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 a3dc74bd29..1a3db2eb16 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 eea4c4bbe1..9671b0bfa9 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 12eb1c2fd6..f0faf52fd5 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 1f920ba4bb..f02e249ff4 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 9f08e1469a..62178b316a 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 3a1e46134f..10edafd6e3 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 3c0890734f..19539f7d39 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 a3ee164a78..f31cc55dbf 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 01afbd40a2..d1110f8eff 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 6dbfede40c..f00a406cdd 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 03f2696605..83d5cde7bf 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 58aacdaf98..a4dc52174f 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 af593faa09..361cd183ad 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 4f246126ac..e8cec7ddb5 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 e62c1977a2..171a4ad1c3 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 40ff91d9ab..772635b8c4 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 171752942f..d407000592 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 ca367e91f5..5d4f6d2df5 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 4945399267..f80f52eb46 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 a0ac6743ba..fcac7b1151 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 3c0ce25d49..81bd3d831c 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 6f7345c799..0d3f3af248 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 30e4549176..0ea2b436cb 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 @@ -152,9 +154,11 @@ function sing_lim!(intr::ForceFreeStatesInternal, ctrl::ForceFreeStatesControl, # A target below q_min has no psilim: say why instead of failing in the root find, as Fortran's "Can't find psilim" intr.qlim >= equil.params.qmin || - error("sing_lim!: the integration limit qlim = $(@sprintf("%.3f", intr.qlim)) lies below q_min = $(@sprintf("%.3f", equil.params.qmin)), " * - "so no flux surface reaches it. With truncate_at_rational_offset no rational surface of n = $(intr.nlow) is left to truncate at; " * - "widen the domain (qhigh, the layer-overlap cap) or set truncate_at_rational_offset = false.") + error( + "sing_lim!: the integration limit qlim = $(@sprintf("%.3f", intr.qlim)) lies below q_min = $(@sprintf("%.3f", equil.params.qmin)), " * + "so no flux surface reaches it. With truncate_at_rational_offset no rational surface of n = $(intr.nlow) is left to truncate at; " * + "widen the domain (qhigh, the layer-overlap cap) or set truncate_at_rational_offset = false." + ) # qlim below qmax: Newton-solve q(psilim) = qlim if intr.qlim < equil.params.qmax diff --git a/src/ForcingTerms/ForcingTerms.jl b/src/ForcingTerms/ForcingTerms.jl index eae14b0388..98738ad6ae 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 ea2549ad3c..639e8ca414 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 b744bedd8d..476b554510 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 f211a2d1e5..9defc821f6 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 45404b00f0..b70ef435f6 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 e94da889f5..5259e11ccb 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 7d3a798d3e..1bb9ca7855 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 59d20c96db..ba2a4e14f8 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 7cd422f40c..1fa75c2401 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 0abe74451c..32136da918 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 2cfef836b9..3a77f7fd87 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 a48b88b192..639d4fd8f2 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 154975ca88..26b2c4c4e4 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 10b55dcb39..4810d1d8a9 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 597b9fc9bb..ff3b38aaf1 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 2d760e4060..0f17f7925d 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 6b989a7058..2c8470f009 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 b930fabcfd..2beaa59163 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 9a786a7e03..4ba63adbeb 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 539b9f57c9..1d3c3ce17a 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 084aa0e168..ac1f26afba 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 dee4a99682..3933652d84 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 4b84f9d92c..351037f8bc 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 40ba8a1fe3..bb74e4d751 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 c712c841d7..c6780aac95 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 7f7f8aa22e..dbf1ed5b9f 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 97f91e7d71..b91f2bb08f 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 8b522013c3..7913ac1cb7 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 1f54504473..1d1b5a75d0 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 e7a977cbbc..8ca61697d7 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 44fa2f40a0..08a4bb15c4 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 2b322b7a7b..c5a6de57e4 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 a9668b6116..6511e6df2e 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 f8d3c9e97e..a15f08e330 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 0fadc644a0..9a2d36004f 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 2d9bf534d1..c668dbf21b 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 22ce9625a7..906b9819cf 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 bc7263af4d..95346ac03b 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 d17239ec65..4739fe5ba5 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 7a22105bdd..2a12db7f8b 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 2a98861ee2..c4c9991def 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 84ad3f2405..8ff0c584b5 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 c95a3098ea..b1c6ef313f 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 a29fb8f8cf..8b528f7aad 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 77347cf167..e83af9ae70 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 cbf8b81d60..c5963fb522 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 92586f9692..32cb81d0a8 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 92dc380ec9..7635ceb190 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 84dc30c587..7ff86b067a 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 b1013d9b5c..2eb09fd641 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 3b0130b84c..11a38764f9 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 de35804fcf..e0b5f61314 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 5b03717985..1b03704e1f 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 61734f048d..eb8822a42d 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) @@ -310,7 +310,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 2cf775e6ec..ed2e78d9ee 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 61bd56a61d..7ddba18d9f 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 76eead85b4..b3904b9702 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 161a43c12a..d6506fd152 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 18d11fec70..277d57bd88 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 851d5dbda2..89b27dfbdc 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 947a2e7c16..e3f205cbc7 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 134ae91295..78f35b5d6a 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 2184fe2e2e..bdea95309c 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