From 9ef9f10b6eb9562764efd8274a0f836b12ae1216 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Wed, 16 Sep 2026 21:19:14 +0200 Subject: [PATCH 1/3] Build a Solver from VSMSettings or from panel and section counts Solver(settings; kwargs...) takes the panel count from the wings' n_panels and the unrefined-section count from the rows of each geometry_file, with solver_settings as defaults that kwargs override. Solver(n_panels, n_unrefined_sections, T) is the core the body_aero constructors now call. solve_base! throws a DimensionMismatch when the body_aero does not match the solver's panel and section counts. Refs #153 Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 11 ++++ docs/src/private_functions.md | 3 + docs/src/settings.md | 2 +- src/solver.jl | 106 +++++++++++++++++++++++++--------- src/yaml_geometry.jl | 12 ++++ test/solver/test_solver.jl | 23 ++++++++ 6 files changed, 129 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 783899e8..3f83439e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +### Added + +- `Solver(settings)` and `Solver(n_panels, n_unrefined_sections)` build a solver without + a `BodyAerodynamics`; keyword arguments override the settings. + +### Fixed + +- `solve!` and `solve` throw a `DimensionMismatch` naming both sizes for a `body_aero` whose + panel or unrefined-section count differs from the solver's, where they failed on a + broadcast partway through or silently left section results at zero. + ### Changed - Requires Julia 1.12 or 1.13; 1.10 and 1.11 keep resolving v5.1.1. diff --git a/docs/src/private_functions.md b/docs/src/private_functions.md index d7807c42..0ff2234e 100644 --- a/docs/src/private_functions.md +++ b/docs/src/private_functions.md @@ -12,6 +12,9 @@ settings_range ### Solver, forces and circulation ```@docs +n_unrefined_sections +solver_kwargs +check_dimensions calculate_AIC_matrices! gamma_loop! build_spanwise_laplacian! diff --git a/docs/src/settings.md b/docs/src/settings.md index 3b2fba46..5de45969 100644 --- a/docs/src/settings.md +++ b/docs/src/settings.md @@ -11,7 +11,7 @@ settings = VSMSettings("my/vsm_settings.yaml"; data_prefix=false) # as written wing = Wing(settings) body_aero = BodyAerodynamics([wing]) -solver = Solver(body_aero, settings) +solver = Solver(settings) set_va!(body_aero, settings) ``` diff --git a/src/solver.jl b/src/solver.jl index 9a706020..3a385dc6 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -190,36 +190,72 @@ sol::VSMSolution = VSMSolution(): The result of calling [`solve!`](@ref) sol::VSMSolution{P, U, T} = VSMSolution{P, U, T}() end -function Solver(body_aero::BodyAerodynamics{P, W, T}; reference_point=[0.0, 0.0, 0.0], kwargs...) where {P, W, T} - U = sum([wing.n_unrefined_sections for wing in body_aero.wings]) +""" + Solver(n_panels, n_unrefined_sections, T=Float64; reference_point=[0.0, 0.0, 0.0], + kwargs...) + Solver(body_aero::BodyAerodynamics; kwargs...) + Solver(settings::VSMSettings; kwargs...) + Solver(body_aero, settings::VSMSettings) + +Build a [`Solver`](@ref) for `n_panels` panels and `n_unrefined_sections` unrefined +sections of element type `T`, with `kwargs` setting its fields. `body_aero` supplies the +counts and `T`; `settings` supplies the counts from the `n_panels` and `geometry_file` of +its wings, and from its `solver_settings` the fields `kwargs` leaves unset. +[`solve!`](@ref) throws a `DimensionMismatch` for a body of other counts. +""" +function Solver(n_panels::Integer, n_unrefined_sections::Integer, ::Type{T}=Float64; + reference_point=[0.0, 0.0, 0.0], kwargs...) where {T} reference_point_checked = check_reference_point(reference_point, T) - return Solver{P, U, T}(; reference_point=reference_point_checked, kwargs...) + return Solver{Int(n_panels), Int(n_unrefined_sections), T}(; + reference_point=reference_point_checked, kwargs...) +end + +Solver(body_aero::BodyAerodynamics{P, W, T}; kwargs...) where {P, W, T} = + Solver(P, n_unrefined_sections(body_aero), T; kwargs...) + +function Solver(settings::VSMSettings; kwargs...) + n_panels = sum(wing.n_panels for wing in settings.wings) + n_sections = sum(n_unrefined_sections, settings.wings) + return Solver(n_panels, n_sections; solver_kwargs(settings.solver_settings)..., + kwargs...) end -function Solver(body_aero, settings::VSMSettings) - ss = settings.solver_settings - solver_type = ss.solver_type == "NONLIN" ? NONLIN : LOOP - reference_point = hasproperty(ss, :reference_point) ? ss.reference_point : [0.0, 0.0, 0.0] - Solver(body_aero; - solver_type, - aerodynamic_model_type=ss.aerodynamic_model_type, - density=ss.density, - max_iterations=ss.max_iterations, - rtol=ss.rtol, - tol_reference_error=ss.tol_reference_error, - relaxation_factor=ss.relaxation_factor, - is_with_artificial_damping=ss.artificial_damping, - artificial_damping=(k2=ss.k2, k4=ss.k4), - is_with_artificial_viscosity=ss.is_with_artificial_viscosity, - artificial_viscosity_factor=ss.artificial_viscosity_factor, - type_initial_gamma_distribution=ss.type_initial_gamma_distribution, - use_gamma_prev=ss.use_gamma_prev, - core_radius_fraction=ss.core_radius_fraction, - mu=ss.mu, - is_only_f_and_gamma_output=ss.calc_only_f_and_gamma, - correct_aoa=ss.correct_aoa, - flow_curvature=ss.flow_curvature, - reference_point=reference_point, +Solver(body_aero, settings::VSMSettings) = + Solver(body_aero; solver_kwargs(settings.solver_settings)...) + +""" + n_unrefined_sections(body_aero::BodyAerodynamics) -> Int + +Number of unrefined sections summed over the wings of `body_aero`. +""" +n_unrefined_sections(body_aero::BodyAerodynamics) = + sum(wing -> wing.n_unrefined_sections, body_aero.wings) + +""" + solver_kwargs(solver_settings::SolverSettings) -> NamedTuple + +The [`Solver`](@ref) fields that `solver_settings` sets, as keyword arguments. +""" +function solver_kwargs(solver_settings::SolverSettings) + return ( + solver_type=solver_settings.solver_type == "NONLIN" ? NONLIN : LOOP, + aerodynamic_model_type=solver_settings.aerodynamic_model_type, + density=solver_settings.density, + max_iterations=solver_settings.max_iterations, + rtol=solver_settings.rtol, + tol_reference_error=solver_settings.tol_reference_error, + relaxation_factor=solver_settings.relaxation_factor, + is_with_artificial_damping=solver_settings.artificial_damping, + artificial_damping=(k2=solver_settings.k2, k4=solver_settings.k4), + is_with_artificial_viscosity=solver_settings.is_with_artificial_viscosity, + artificial_viscosity_factor=solver_settings.artificial_viscosity_factor, + type_initial_gamma_distribution=solver_settings.type_initial_gamma_distribution, + use_gamma_prev=solver_settings.use_gamma_prev, + core_radius_fraction=solver_settings.core_radius_fraction, + mu=solver_settings.mu, + is_only_f_and_gamma_output=solver_settings.calc_only_f_and_gamma, + correct_aoa=solver_settings.correct_aoa, + flow_curvature=solver_settings.flow_curvature, ) end @@ -610,6 +646,21 @@ end end end +""" + check_dimensions(solver::Solver, body_aero::BodyAerodynamics) + +Throw a `DimensionMismatch` unless `solver` was built for as many panels and unrefined +sections as `body_aero` has. +""" +function check_dimensions(::Solver{P, U}, body_aero::BodyAerodynamics) where {P, U} + n_panels = length(body_aero.panels) + n_sections = n_unrefined_sections(body_aero) + n_panels == P && n_sections == U || throw(DimensionMismatch( + "Solver built for $P panels and $U unrefined sections is given a body_aero " * + "with $n_panels panels and $n_sections unrefined sections")) + return nothing +end + """ solve_base!(solver::Solver, body_aero::BodyAerodynamics, gamma_distribution=nothing; log=false) @@ -625,6 +676,7 @@ function solve_base!(solver::Solver{P, U, T}, body_aero::BodyAerodynamics, gamma log=false) where {P, U, T} # check arguments + check_dimensions(solver, body_aero) isnothing(body_aero.panels[1].va) && throw(ArgumentError("Inflow conditions are not set, use set_va!(body_aero, va)")) # Initialize variables diff --git a/src/yaml_geometry.jl b/src/yaml_geometry.jl index 11da48ac..456c3656 100644 --- a/src/yaml_geometry.jl +++ b/src/yaml_geometry.jl @@ -427,6 +427,18 @@ function Wing(settings::VSMSettings; sort_sections::Bool=true) end end +""" + n_unrefined_sections(wing_settings::WingSettings) -> Int + +Number of unrefined sections the [`Wing`](@ref) built from `wing_settings` carries: the +rows of its `geometry_file`'s `wing_sections`. +""" +function n_unrefined_sections(wing_settings::WingSettings) + isempty(wing_settings.geometry_file) && throw(ArgumentError( + "wing \"$(wing_settings.name)\" has no geometry_file to count its sections from")) + return length(YAML.load_file(wing_settings.geometry_file)["wing_sections"]["data"]) +end + """ ObjWing(obj_path[, dat_path]; n_panels, Re, alpha_range, delta_range, n_sections, spanwise_direction, aero_solver, remake, output_dir, diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index b940c69e..cb8b7640 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -30,6 +30,29 @@ end sol = solve!(solver, body_aero) @test sol isa VSMSolution + @testset "Solver from VSMSettings alone matches the one on body_aero" begin + solver_from_settings = Solver(settings) + @test solver_from_settings isa typeof(solver) + @test solve!(solver_from_settings, body_aero).force ≈ sol.force + @test Solver(settings; density=1.0).density == 1.0 + end + + @testset "Solver from panel and section counts" begin + n_sections = wing.n_unrefined_sections + solver_from_counts = Solver(wing.n_panels, n_sections) + @test solver_from_counts isa typeof(solver) + @test solve!(solver_from_counts, body_aero).force ≈ sol.force + end + + @testset "solve refuses a body_aero sized for another solver" begin + n_sections = wing.n_unrefined_sections + for other in (Solver(wing.n_panels + 1, n_sections), + Solver(wing.n_panels, n_sections + 1)) + @test_throws DimensionMismatch solve!(other, body_aero) + @test_throws "Solver built for" solve!(other, body_aero) + @test_throws DimensionMismatch solve(other, body_aero) + end + end finally # Cleanup rm(settings_file; force=true) From d165c7f62a07c3a3777998b41dc725c854a74560 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Thu, 17 Sep 2026 00:20:50 +0200 Subject: [PATCH 2/3] Deprecate the Solver constructors that take a body_aero Solver(body_aero; kwargs...) and Solver(body_aero, settings) keep working but warn on use, pointing to Solver(settings) and Solver(n_panels, n_unrefined_sections). make_dual_shadow, the examples, the docs example and the tests build their solvers with those instead. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 10 ++-- docs/src/examples.md | 4 +- examples/V3_kite.jl | 4 +- examples/V3_neuralfoil.jl | 8 ++- examples/bench.jl | 6 +- examples/billowing.jl | 8 +-- examples/linearize_check.jl | 2 +- examples/obj_to_yaml_kite.jl | 3 +- examples/pyramid_model.jl | 2 +- examples/ram_air_kite.jl | 6 +- examples/rectangular_wing.jl | 4 +- examples/stall_model.jl | 4 +- mwes/mwe_warntype.jl | 2 +- src/solver.jl | 33 +++++++---- test/bench.jl | 6 +- test/bench_solve.jl | 2 +- .../test_body_aerodynamics.jl | 8 ++- test/body_aerodynamics/test_results.jl | 2 +- test/plotting/test_plotting.jl | 7 ++- test/solver/test_backend_comparison.jl | 7 ++- test/solver/test_flow_curvature.jl | 6 +- test/solver/test_forwarddiff.jl | 6 +- test/solver/test_moment_units.jl | 9 ++- test/solver/test_solver.jl | 57 +++++++++++-------- test/solver/test_unrefined_dist.jl | 6 +- test/verification/test_verification.jl | 4 +- 26 files changed, 128 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc61a68..40213d4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - `solve!` and `solve` throw a `DimensionMismatch` naming both sizes for a `body_aero` whose panel or unrefined-section count differs from the solver's, where they failed on a broadcast partway through or silently left section results at zero. +- The `VSMSolution` docstring gives `lift_dist`, `drag_dist` and `panel_moment_dist` in + the per-unit-span units they hold, [N/m] and [Nm/m], instead of [N] and [Nm]. ### Changed @@ -19,11 +21,9 @@ - The Makie `plot!` methods for a `Panel` or a `BodyAerodynamics` return a `Vector{Makie.AbstractPlot}` instead of a `Vector{Any}`; for a `BodyAerodynamics` drawn as flat panels it is one flat list rather than a list per panel. - -### Fixed - -- The `VSMSolution` docstring gives `lift_dist`, `drag_dist` and `panel_moment_dist` in - the per-unit-span units they hold, [N/m] and [Nm/m], instead of [N] and [Nm]. +- `Solver(body_aero; kwargs...)` and `Solver(body_aero, settings)` are deprecated and warn + on use; build the solver with `Solver(settings)` or + `Solver(n_panels, n_unrefined_sections)` instead. ## VortexStepMethod v5.1.1 2026-09-12 diff --git a/docs/src/examples.md b/docs/src/examples.md index 2c37cfbe..ed03f4df 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -84,8 +84,8 @@ julia> set_va!(body_aero, vel_app, [0, 0, 0.1]) #### Step 5: Initialize solvers for both LLT and VSM methods ```julia -julia> llt_solver = Solver(body_aero; aerodynamic_model_type=LLT) -julia> vsm_solver = Solver(body_aero; aerodynamic_model_type=VSM) +julia> llt_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=LLT) +julia> vsm_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=VSM) ``` #### Step 6: Solve using both methods diff --git a/examples/V3_kite.jl b/examples/V3_kite.jl index 4a7b831c..9b747b30 100644 --- a/examples/V3_kite.jl +++ b/examples/V3_kite.jl @@ -42,7 +42,7 @@ wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) VortexStepMethod.reinit!(body_aero) -solver = Solver(body_aero, settings) +solver = Solver(settings) solver.reference_point .= REFERENCE_POINT if DEFORM @@ -75,7 +75,7 @@ if NEURALFOIL refine!(wing_nf) body_nf = BodyAerodynamics([wing_nf]) VortexStepMethod.reinit!(body_nf) - solver_nf = Solver(body_nf, settings_nf) + solver_nf = Solver(settings_nf) solver_nf.reference_point .= REFERENCE_POINT # Reading the generated directory instead of the OBJ shows the airfoils the polar diff --git a/examples/V3_neuralfoil.jl b/examples/V3_neuralfoil.jl index 88064a5b..9d91b3fc 100644 --- a/examples/V3_neuralfoil.jl +++ b/examples/V3_neuralfoil.jl @@ -81,14 +81,18 @@ wing_cfd = Wing(settings_cfd) refine!(wing_cfd) body_cfd = BodyAerodynamics([wing_cfd]) VortexStepMethod.reinit!(body_cfd) -solver_cfd = Solver(body_cfd, settings_cfd) +solver_cfd = Solver(settings_cfd) println("Creating wing with NeuralFoil polars...") wing_nf = Wing(nf_yaml; n_panels=50, spanwise_distribution=LINEAR) refine!(wing_nf) body_nf = BodyAerodynamics([wing_nf]) VortexStepMethod.reinit!(body_nf) -solver_nf = Solver(body_nf, settings_cfd) +settings_nf = VSMSettings("TUDELFT_V3_KITE/vsm_settings.yaml") +settings_nf.wings[1].geometry_file = nf_yaml +settings_nf.solver_settings.relaxation_factor = RELAXATION +settings_nf.solver_settings.artificial_damping = ARTIFICIAL_DAMPING +solver_nf = Solver(settings_nf) # Compare CFD-polar and NeuralFoil-polar wings against published references # (Poland 2025 RANS CFD and wind tunnel). `plot_polars` sweeps each solver over the diff --git a/examples/bench.jl b/examples/bench.jl index ca9414ec..c757f149 100644 --- a/examples/bench.jl +++ b/examples/bench.jl @@ -41,8 +41,8 @@ vel_app = [cos(alpha), 0.0, sin(alpha)] .* v_a set_va!(body_aero, vel_app) # Step 4: Initialize solvers for both LLT and VSM methods -llt_solver = Solver(body_aero; aerodynamic_model_type=LLT) -vsm_solver = Solver(body_aero; aerodynamic_model_type=VSM) +llt_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=LLT) +vsm_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=VSM) # Step 5: Solve using both methods results_vsm = solve(vsm_solver, body_aero, nothing) @@ -66,7 +66,7 @@ body_aero = BodyAerodynamics([wing]) # Create solvers vsm_solver = Solver( - body_aero; + wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=false, solver_type=LOOP, diff --git a/examples/billowing.jl b/examples/billowing.jl index 219b7e54..87a25d13 100644 --- a/examples/billowing.jl +++ b/examples/billowing.jl @@ -84,8 +84,8 @@ body_aero_bill = BodyAerodynamics([wing_bill]) VortexStepMethod.reinit!(body_aero_bill) # --- Build solvers --- -function make_solver(body_aero) - Solver(body_aero; +function make_solver(wing) + Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=(solver_cfg["solver_type"] == "NONLIN" ? NONLIN : LOOP), aerodynamic_model_type=getproperty( @@ -114,8 +114,8 @@ function make_solver(body_aero) ) end -solver_flat = make_solver(body_aero_flat) -solver_bill = make_solver(body_aero_bill) +solver_flat = make_solver(wing_flat) +solver_bill = make_solver(wing_bill) # --- Set flight conditions --- wind_speed = condition_cfg["wind_speed"] diff --git a/examples/linearize_check.jl b/examples/linearize_check.jl index 63614520..2fa404d9 100644 --- a/examples/linearize_check.jl +++ b/examples/linearize_check.jl @@ -23,7 +23,7 @@ yaml = obj_to_yaml( wing = Wing(yaml; n_panels=16) body_aero = BodyAerodynamics([wing]) -solver = Solver(body_aero; +solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=false, rtol=1e-7, diff --git a/examples/obj_to_yaml_kite.jl b/examples/obj_to_yaml_kite.jl index c76531b8..c2c7340d 100644 --- a/examples/obj_to_yaml_kite.jl +++ b/examples/obj_to_yaml_kite.jl @@ -72,7 +72,8 @@ refine!(wing) body_aero = BodyAerodynamics([wing]) VortexStepMethod.reinit!(body_aero) -solver = Solver(body_aero; aerodynamic_model_type=VSM, rtol=1e-5, solver_type=LOOP) +solver = Solver(wing.n_panels, wing.n_unrefined_sections; + aerodynamic_model_type=VSM, rtol=1e-5, solver_type=LOOP) set_va!(body_aero, [cos(deg2rad(8)) * v_a, 0.0, sin(deg2rad(8)) * v_a]) results = VortexStepMethod.solve(solver, body_aero; log=true) diff --git a/examples/pyramid_model.jl b/examples/pyramid_model.jl index 445638c0..58760996 100644 --- a/examples/pyramid_model.jl +++ b/examples/pyramid_model.jl @@ -14,7 +14,7 @@ vsm_settings = VSMSettings("pyramid_model/vsm_settings.yaml") wing = Wing(vsm_settings) refine!(wing) body_aero = BodyAerodynamics([wing]) -solver = Solver(body_aero, vsm_settings) +solver = Solver(vsm_settings) # Set flight conditions from settings set_va!(body_aero, vsm_settings) diff --git a/examples/ram_air_kite.jl b/examples/ram_air_kite.jl index 2eabe7fe..b1168738 100644 --- a/examples/ram_air_kite.jl +++ b/examples/ram_air_kite.jl @@ -80,13 +80,15 @@ fig_audit = plot_slices_3d(joinpath("data", "ram_air_kite", "polars_xfoil"); delta=1.0, obj_path=obj_path) GLMakie.save("ram_air_slices_audit.png", fig_audit) body_xfoil = BodyAerodynamics([wing_xfoil]) -solver_xfoil = Solver(body_xfoil; aerodynamic_model_type=VSM, rtol=1e-5, solver_type=LOOP, +solver_xfoil = Solver(wing_xfoil.n_panels, wing_xfoil.n_unrefined_sections; + aerodynamic_model_type=VSM, rtol=1e-5, solver_type=LOOP, relaxation_factor=RELAXATION, is_with_artificial_damping=ARTIFICIAL_DAMPING) println("Creating NeuralFoil wing...") wing_nf = matrix_wing(NF_SOLVER, "polars_neuralfoil") body_nf = BodyAerodynamics([wing_nf]) -solver_nf = Solver(body_nf; aerodynamic_model_type=VSM, rtol=1e-5, solver_type=LOOP, +solver_nf = Solver(wing_nf.n_panels, wing_nf.n_unrefined_sections; + aerodynamic_model_type=VSM, rtol=1e-5, solver_type=LOOP, relaxation_factor=RELAXATION, is_with_artificial_damping=ARTIFICIAL_DAMPING) # Compare using plot_polars diff --git a/examples/rectangular_wing.jl b/examples/rectangular_wing.jl index 069db9b1..97f7d113 100644 --- a/examples/rectangular_wing.jl +++ b/examples/rectangular_wing.jl @@ -45,8 +45,8 @@ vel_app = [cos(alpha), 0.0, sin(alpha)] .* v_a set_va!(body_aero, vel_app, [0, 0, 0.1]) # Step 4: Initialize solvers for both LLT and VSM methods -llt_solver = Solver(body_aero; aerodynamic_model_type=LLT) -vsm_solver = Solver(body_aero; aerodynamic_model_type=VSM) +llt_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=LLT) +vsm_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=VSM) # Step 5: Solve using both methods results_llt = solve(llt_solver, body_aero) diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 1b675c3c..661cb670 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -46,11 +46,11 @@ refine!(CAD_wing) body_aero = BodyAerodynamics([CAD_wing]) # Create solvers -vsm_solver = Solver(body_aero; +vsm_solver = Solver(CAD_wing.n_panels, CAD_wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=false ) -VSM_with_stall_correction = Solver(body_aero; +VSM_with_stall_correction = Solver(CAD_wing.n_panels, CAD_wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=true ) diff --git a/mwes/mwe_warntype.jl b/mwes/mwe_warntype.jl index a7b6401c..3a55a7cd 100644 --- a/mwes/mwe_warntype.jl +++ b/mwes/mwe_warntype.jl @@ -27,7 +27,7 @@ refine!(wing) body_aero = BodyAerodynamics([wing]) vel_app = [cos(alpha), 0.0, sin(alpha)] .* 20.0 set_va!(body_aero, vel_app) -solver = Solver(body_aero) +solver = Solver(wing.n_panels, wing.n_unrefined_sections) va_norm_array = ones(n_panels) va_unit_array = ones(n_panels, 3) diff --git a/src/solver.jl b/src/solver.jl index 7598a9b5..704b7d52 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -193,15 +193,15 @@ end """ Solver(n_panels, n_unrefined_sections, T=Float64; reference_point=[0.0, 0.0, 0.0], kwargs...) - Solver(body_aero::BodyAerodynamics; kwargs...) Solver(settings::VSMSettings; kwargs...) - Solver(body_aero, settings::VSMSettings) Build a [`Solver`](@ref) for `n_panels` panels and `n_unrefined_sections` unrefined -sections of element type `T`, with `kwargs` setting its fields. `body_aero` supplies the -counts and `T`; `settings` supplies the counts from the `n_panels` and `geometry_file` of -its wings, and from its `solver_settings` the fields `kwargs` leaves unset. -[`solve!`](@ref) throws a `DimensionMismatch` for a body of other counts. +sections of element type `T`, with `kwargs` setting its fields. `settings` supplies the +counts from the `n_panels` and `geometry_file` of its wings, and from its +`solver_settings` the fields `kwargs` leaves unset. [`solve!`](@ref) throws a +`DimensionMismatch` for a body of other counts. + +`Solver(body_aero; kwargs...)` and `Solver(body_aero, settings)` are deprecated. """ function Solver(n_panels::Integer, n_unrefined_sections::Integer, ::Type{T}=Float64; reference_point=[0.0, 0.0, 0.0], kwargs...) where {T} @@ -210,9 +210,6 @@ function Solver(n_panels::Integer, n_unrefined_sections::Integer, ::Type{T}=Floa reference_point=reference_point_checked, kwargs...) end -Solver(body_aero::BodyAerodynamics{P, W, T}; kwargs...) where {P, W, T} = - Solver(P, n_unrefined_sections(body_aero), T; kwargs...) - function Solver(settings::VSMSettings; kwargs...) n_panels = sum(wing.n_panels for wing in settings.wings) n_sections = sum(n_unrefined_sections, settings.wings) @@ -220,8 +217,20 @@ function Solver(settings::VSMSettings; kwargs...) kwargs...) end -Solver(body_aero, settings::VSMSettings) = - Solver(body_aero; solver_kwargs(settings.solver_settings)...) +function Solver(body_aero::BodyAerodynamics{P, W, T}; kwargs...) where {P, W, T} + Base.depwarn("`Solver(body_aero; kwargs...)` is deprecated, use " * + "`Solver(n_panels, n_unrefined_sections; kwargs...)` or " * + "`Solver(settings; kwargs...)`.", :Solver; force=true) + return Solver(P, n_unrefined_sections(body_aero), T; kwargs...) +end + +function Solver(body_aero::BodyAerodynamics{P, W, T}, settings::VSMSettings + ) where {P, W, T} + Base.depwarn("`Solver(body_aero, settings)` is deprecated, use `Solver(settings)`.", + :Solver; force=true) + return Solver(P, n_unrefined_sections(body_aero), T; + solver_kwargs(settings.solver_settings)...) +end """ n_unrefined_sections(body_aero::BodyAerodynamics) -> Int @@ -1272,7 +1281,7 @@ function make_dual_shadow(solver::Solver{P, U, Float64}, va = MVector{3, TD}(body_aero._va), omega = MVector{3, TD}(body_aero.omega), ) - solver_d = Solver(body_aero_d; + solver_d = Solver(P, U, TD; solver_type = solver.solver_type, aerodynamic_model_type = solver.aerodynamic_model_type, density = TD(solver.density), diff --git a/test/bench.jl b/test/bench.jl index fb0a2c6b..2e06cb53 100644 --- a/test/bench.jl +++ b/test/bench.jl @@ -72,8 +72,8 @@ using LinearAlgebra set_va!(body_aero, vel_app) # Initialize solvers for both LLT and VSM methods - solver = Solver(body_aero) - nonlin_solver = Solver(body_aero; solver_type=NONLIN) + solver = Solver(wing.n_panels, wing.n_unrefined_sections) + nonlin_solver = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=NONLIN) # Pre-allocate arrays gamma = rand(n_panels) @@ -142,7 +142,7 @@ using LinearAlgebra refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero; + solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=model ) solver.sol._va_dist .= va_array diff --git a/test/bench_solve.jl b/test/bench_solve.jl index f9dcc4be..7533906c 100644 --- a/test/bench_solve.jl +++ b/test/bench_solve.jl @@ -38,7 +38,7 @@ vel_app = [cos(alpha), 0.0, sin(alpha)] .* v_a set_va!(body_aero, vel_app) # Step 4: Initialize solvers for both LLT and VSM methods -vsm_solver = Solver(body_aero; aerodynamic_model_type=VSM) +vsm_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=VSM) # Step 5: Solve using both methods result = @benchmark solve_base!($vsm_solver, $body_aero, nothing) # 34 allocations diff --git a/test/body_aerodynamics/test_body_aerodynamics.jl b/test/body_aerodynamics/test_body_aerodynamics.jl index 94a73bfb..037081ca 100644 --- a/test/body_aerodynamics/test_body_aerodynamics.jl +++ b/test/body_aerodynamics/test_body_aerodynamics.jl @@ -325,7 +325,7 @@ end set_va!(body_aero, v_a) # Run analysis - loop_solver = Solver(body_aero; + loop_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=model, core_radius_fraction=core_radius_fraction, solver_type=LOOP, @@ -333,7 +333,7 @@ end atol=1e-8, rtol=1e-8 ) - nonlin_solver = Solver(body_aero; + nonlin_solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=model, core_radius_fraction=core_radius_fraction, solver_type=NONLIN, @@ -509,7 +509,9 @@ The `BodyAerodynamics` built from `wings` in a 10 m/s inflow and its `solve!` so """ function solve_wings(wings) body_aero = BodyAerodynamics(wings; va=[10.0, 0.0, 1.0]) - return body_aero, solve!(Solver(body_aero), body_aero) + solver = Solver(sum(wing -> wing.n_panels, wings), + sum(wing -> wing.n_unrefined_sections, wings)) + return body_aero, solve!(solver, body_aero) end @testset "solve! on a two-wing body" begin diff --git a/test/body_aerodynamics/test_results.jl b/test/body_aerodynamics/test_results.jl index 83aa8fc2..e4dec374 100644 --- a/test/body_aerodynamics/test_results.jl +++ b/test/body_aerodynamics/test_results.jl @@ -32,7 +32,7 @@ end VortexStepMethod.unrefined_deform!(ram_wing, theta, delta; smooth=false) body_aero = BodyAerodynamics([ram_wing]; va, omega) - solver = Solver(body_aero; + solver = Solver(ram_wing.n_panels, ram_wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=false, atol=1e-5, diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 5a0476b7..170048d0 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -77,8 +77,11 @@ end end # Initialize the solvers - vsm_solver = Solver(body_aero; aerodynamic_model_type=VSM) - llt_solver = Solver(body_aero; aerodynamic_model_type=LLT) + wing = only(body_aero.wings) + vsm_solver = Solver(wing.n_panels, wing.n_unrefined_sections; + aerodynamic_model_type=VSM) + llt_solver = Solver(wing.n_panels, wing.n_unrefined_sections; + aerodynamic_model_type=LLT) # Solve the VSM and LLT results_vsm = solve(vsm_solver, body_aero) diff --git a/test/solver/test_backend_comparison.jl b/test/solver/test_backend_comparison.jl index 3cc47b63..849114ee 100644 --- a/test/solver/test_backend_comparison.jl +++ b/test/solver/test_backend_comparison.jl @@ -39,10 +39,13 @@ using Test return wing end function lift(matrices) - body = BodyAerodynamics([flat_wing(matrices)]) + wing = flat_wing(matrices) + body = BodyAerodynamics([wing]) aoa = deg2rad(4.0) set_va!(body, [cos(aoa), 0.0, sin(aoa)] * 15.0) - return collect(solve!(Solver(body; aerodynamic_model_type=VSM), body).force_coeffs) + solver = Solver(wing.n_panels, wing.n_unrefined_sections; + aerodynamic_model_type=VSM) + return collect(solve!(solver, body).force_coeffs) end fc_nf, fc_xf = lift(nf), lift(xf) @test fc_nf[3] > 0 && fc_xf[3] > 0 # positive lift at positive alpha diff --git a/test/solver/test_flow_curvature.jl b/test/solver/test_flow_curvature.jl index 645a7d12..3ad771fd 100644 --- a/test/solver/test_flow_curvature.jl +++ b/test/solver/test_flow_curvature.jl @@ -102,8 +102,8 @@ end @test sign(dot(dv, panel.z_airf)) == sign(q_local) end - solver_off = Solver(body_aero; flow_curvature=false) - solver_on = Solver(body_aero; flow_curvature=true) + solver_off = Solver(wing.n_panels, wing.n_unrefined_sections; flow_curvature=false) + solver_on = Solver(wing.n_panels, wing.n_unrefined_sections; flow_curvature=true) function moment_at(solver, omega) set_va!(body_aero, [V, 0.0, 0.0], omega) @@ -128,7 +128,7 @@ end end @testset "defaults to off" begin - @test Solver(body_aero).flow_curvature == false + @test Solver(wing.n_panels, wing.n_unrefined_sections).flow_curvature == false @test VortexStepMethod.SolverSettings().flow_curvature == false end diff --git a/test/solver/test_forwarddiff.jl b/test/solver/test_forwarddiff.jl index c052aae4..00f210ea 100644 --- a/test/solver/test_forwarddiff.jl +++ b/test/solver/test_forwarddiff.jl @@ -22,7 +22,7 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, y0 = [va; omega] @testset "AutoForwardDiff matches AutoFiniteDiff (LOOP, INVISCID)" begin - solver = Solver(body_aero; + solver = Solver(wing.n_panels, wing.n_unrefined_sections; use_gamma_prev=false, type_initial_gamma_distribution=ELLIPTIC) @@ -44,7 +44,7 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, end @testset "NONLIN+ForwardDiff is rejected" begin - solver_nl = Solver(body_aero; solver_type=NONLIN) + solver_nl = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=NONLIN) @test_throws ErrorException VortexStepMethod.linearize( solver_nl, body_aero, y0; theta_idxs=nothing, va_idxs=1:3, omega_idxs=4:6, @@ -57,7 +57,7 @@ relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, delta_range=deg2rad.(-3:3:3), ) ram_body = BodyAerodynamics([ram_wing]) - ram_solver = Solver(ram_body; + ram_solver = Solver(ram_wing.n_panels, ram_wing.n_unrefined_sections; aerodynamic_model_type=VSM, is_with_artificial_damping=false, rtol=1e-11, diff --git a/test/solver/test_moment_units.jl b/test/solver/test_moment_units.jl index baa67e7f..62bf2f9b 100644 --- a/test/solver/test_moment_units.jl +++ b/test/solver/test_moment_units.jl @@ -31,7 +31,10 @@ end @testset "solve!" begin small, large = map((1.0, k)) do scale body_aero = scaled_wing_aero(scale) - solve!(Solver(body_aero; reference_point=reference_point(scale)), body_aero) + wing = only(body_aero.wings) + solver = Solver(wing.n_panels, wing.n_unrefined_sections; + reference_point=reference_point(scale)) + solve!(solver, body_aero) end @test small.solver_status == large.solver_status == FEASIBLE @test all(!iszero, small.panel_moment_dist) @@ -48,7 +51,9 @@ end @testset "solve" begin small, large = map((1.0, k)) do scale body_aero = scaled_wing_aero(scale) - solve(Solver(body_aero), body_aero; reference_point=reference_point(scale)) + wing = only(body_aero.wings) + solver = Solver(wing.n_panels, wing.n_unrefined_sections) + solve(solver, body_aero; reference_point=reference_point(scale)) end for key in ("Mx", "My", "Mz", "M_distribution") @test large[key] ≈ k^3 .* small[key] rtol = 1e-6 diff --git a/test/solver/test_solver.jl b/test/solver/test_solver.jl index cb8b7640..4b5f85d2 100644 --- a/test/solver/test_solver.jl +++ b/test/solver/test_solver.jl @@ -18,11 +18,12 @@ end wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) + solver = Solver(settings) # Verify solver properties match settings @test solver.aerodynamic_model_type == VSM @test solver.density == 1.225 + @test Solver(settings; density=1.0).density == 1.0 # Test that the solver can solve va = [10.0, 0.0, 0.0] @@ -30,11 +31,19 @@ end sol = solve!(solver, body_aero) @test sol isa VSMSolution - @testset "Solver from VSMSettings alone matches the one on body_aero" begin - solver_from_settings = Solver(settings) - @test solver_from_settings isa typeof(solver) - @test solve!(solver_from_settings, body_aero).force ≈ sol.force - @test Solver(settings; density=1.0).density == 1.0 + @testset "body_aero constructors warn and match Solver(settings)" begin + with_settings = r"`Solver\(body_aero, settings\)` is deprecated" + solver_from_body = @test_logs((:warn, with_settings), + Solver(body_aero, settings)) + @test solver_from_body isa typeof(solver) + @test solver_from_body.density == solver.density + @test solve!(solver_from_body, body_aero).force ≈ sol.force + + with_kwargs = r"`Solver\(body_aero; kwargs...\)` is deprecated" + solver_from_body = @test_logs((:warn, with_kwargs), + Solver(body_aero; density=1.0)) + @test solver_from_body isa typeof(solver) + @test solver_from_body.density == 1.0 end @testset "Solver from panel and section counts" begin @@ -72,7 +81,7 @@ end body_aero = BodyAerodynamics([wing]) solver = Solver( - body_aero; + wing.n_panels, wing.n_unrefined_sections; solver_type=NONLIN, aerodynamic_model_type=VSM, type_initial_gamma_distribution=ELLIPTIC, @@ -105,10 +114,10 @@ end refine!(wing) body_aero = BodyAerodynamics([wing]) va = [10.0, 0.0, 5.0] # 26.6 deg angle of attack, past stall - nonlin = Solver(body_aero; solver_type=NONLIN, aerodynamic_model_type=VSM, - type_initial_gamma_distribution=ELLIPTIC) - loop = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM, - type_initial_gamma_distribution=ELLIPTIC) + nonlin = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=NONLIN, + aerodynamic_model_type=VSM, type_initial_gamma_distribution=ELLIPTIC) + loop = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=LOOP, + aerodynamic_model_type=VSM, type_initial_gamma_distribution=ELLIPTIC) set_va!(body_aero, va) sol_nonlin = solve!(nonlin, body_aero) @@ -132,8 +141,9 @@ One unrelaxed fixed-point step `F(gamma)` of the LOOP iteration, so that """ function unrelaxed_step(body_aero, gamma) # An infinite rtol accepts the single step, so solve_base! skips its retry. - probe = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM, - relaxation_factor=1.0, max_iterations=1, rtol=Inf) + wing = only(body_aero.wings) + probe = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=LOOP, + aerodynamic_model_type=VSM, relaxation_factor=1.0, max_iterations=1, rtol=Inf) VortexStepMethod.solve_base!(probe, body_aero, gamma) return copy(probe.lr.gamma_new) end @@ -148,8 +158,8 @@ end wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM, - type_initial_gamma_distribution=ELLIPTIC) + solver = Solver(wing.n_panels, wing.n_unrefined_sections; solver_type=LOOP, + aerodynamic_model_type=VSM, type_initial_gamma_distribution=ELLIPTIC) for va in ([10.0, 0.0, 0.0], [10.0, 0.0, 5.0]) # 0 deg, and 26.6 deg past stall set_va!(body_aero, va) @@ -176,7 +186,7 @@ calc_forces_allocs(solver, body_aero) = wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) + solver = Solver(settings) set_va!(body_aero, [10.0, 0.0, 0.0]) solve!(solver, body_aero) @@ -273,10 +283,10 @@ end @testset "solve! artificial viscosity: attached no-op, post-stall finite" begin body_aero = BodyAerodynamics([poststall_wing]) - solver_off = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM, - is_with_artificial_viscosity=false) - solver_on = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM, - is_with_artificial_viscosity=true) + solver_off = Solver(poststall_wing.n_panels, poststall_wing.n_unrefined_sections; + solver_type=LOOP, aerodynamic_model_type=VSM, is_with_artificial_viscosity=false) + solver_on = Solver(poststall_wing.n_panels, poststall_wing.n_unrefined_sections; + solver_type=LOOP, aerodynamic_model_type=VSM, is_with_artificial_viscosity=true) # Attached flow: viscosity never fires, so results are bit-identical. set_va!(body_aero, [10.0, 0.0, 0.0]) @@ -293,8 +303,8 @@ end @testset "solve! reports a solve that missed the tolerances" begin body_aero = BodyAerodynamics([poststall_wing]) - solver = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM, - max_iterations=1) + solver = Solver(poststall_wing.n_panels, poststall_wing.n_unrefined_sections; + solver_type=LOOP, aerodynamic_model_type=VSM, max_iterations=1) set_va!(body_aero, [10.0, 0.0, 0.0]) sol = solve!(solver, body_aero) @@ -305,7 +315,8 @@ end @test_throws "did not converge in 1 iterations" solve!(solver, body_aero; throw_on_fail=true) - converged = Solver(body_aero; solver_type=LOOP, aerodynamic_model_type=VSM) + converged = Solver(poststall_wing.n_panels, poststall_wing.n_unrefined_sections; + solver_type=LOOP, aerodynamic_model_type=VSM) @test solve!(converged, body_aero; throw_on_fail=true) isa VSMSolution end diff --git a/test/solver/test_unrefined_dist.jl b/test/solver/test_unrefined_dist.jl index 67f0bee3..dbfc3cad 100644 --- a/test/solver/test_unrefined_dist.jl +++ b/test/solver/test_unrefined_dist.jl @@ -21,7 +21,7 @@ using Test wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) + solver = Solver(settings) # Set conditions and solve va = [10.0, 0.0, 0.0] @@ -96,7 +96,7 @@ using Test wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) + solver = Solver(settings) va = [10.0, 0.0, 0.0] set_va!(body_aero, va) @@ -169,7 +169,7 @@ using Test wing = Wing(settings) refine!(wing) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero, settings) + solver = Solver(settings) va = [10.0, 0.0, 0.0] set_va!(body_aero, va) diff --git a/test/verification/test_verification.jl b/test/verification/test_verification.jl index c32d0e31..d90bdce8 100644 --- a/test/verification/test_verification.jl +++ b/test/verification/test_verification.jl @@ -56,8 +56,8 @@ settings of the Python verification cases. """ function lift_drag_polar(wing, model, alphas; wind_speed, relaxation_factor) body_aero = BodyAerodynamics([wing]) - solver = Solver(body_aero; aerodynamic_model_type=model, relaxation_factor, - core_radius_fraction=1e-20) + solver = Solver(wing.n_panels, wing.n_unrefined_sections; aerodynamic_model_type=model, + relaxation_factor, core_radius_fraction=1e-20) CL = zeros(length(alphas)) CD = zeros(length(alphas)) for (i, alpha) in enumerate(alphas) From da666bf29a2197fe807fd04472bbd9871b5b12e8 Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:33:52 +0200 Subject: [PATCH 3/3] Build the billowing example's solvers with Solver(settings) The coarse V3 settings file named the 37-section aero_geometry.yaml while it describes, and the example flies, the 10-section coarse discretisation. It now names that file, so the example loads it as VSMSettings and builds both solvers from it instead of mapping solver_settings by hand. Co-Authored-By: Claude Opus 5 --- data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml | 2 +- examples/billowing.jl | 55 ++++--------------- 2 files changed, 11 insertions(+), 46 deletions(-) diff --git a/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml b/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml index e29eb6d5..1e6f80bb 100644 --- a/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml +++ b/data/TUDELFT_V3_KITE/vsm_settings_coarse.yaml @@ -44,7 +44,7 @@ condition: # Define wing geometry files and discretization parameters wings: - name: V3_Kite # Wing identifier for output labeling - geometry_file: data/TUDELFT_V3_KITE/aero_geometry.yaml + geometry_file: data/TUDELFT_V3_KITE/aero_geometry_coarse_discretisation.yaml n_panels: 54 # Total number of panels along wingspan spanwise_panel_distribution: SPLIT_PROVIDED # Panel spacing algorithm spanwise_direction: [0.0, 1.0, 0.0] # Unit vector defining wingspan direction diff --git a/examples/billowing.jl b/examples/billowing.jl index d0368abf..e99d0d52 100644 --- a/examples/billowing.jl +++ b/examples/billowing.jl @@ -30,15 +30,12 @@ literature_paths = [ "windtunnel_alpha_sweep_beta_00_0_Poland_2025_Rey_5e5.csv"), ] -# Load solver settings (coarse: 54 panels, matches 10-section geometry) -settings_data = VortexStepMethod.YAML.load_file( - joinpath(v3_dir, "vsm_settings_coarse.yaml")) -condition_cfg = settings_data["condition"] -solver_cfg = settings_data["solver_settings"] -wing_cfg = settings_data["wings"][1] -n_panels = wing_cfg["n_panels"] +# Coarse settings: 54 panels on the 10-section geometry +settings = VSMSettings(joinpath(v3_dir, "vsm_settings_coarse.yaml"); data_prefix=false) +settings.wings[1].geometry_file = joinpath(project_dir, settings.wings[1].geometry_file) +n_panels = settings.wings[1].n_panels -BILLOWING_PCT = get(wing_cfg, "billowing_percentage", 0.0) +BILLOWING_PCT = settings.wings[1].billowing_percentage labels = [ "VSM flat", @@ -49,9 +46,7 @@ labels = [ "WindTunnel Re=5e5", ] -# Load coarse geometry (10 structural rib sections) -geom_data = VortexStepMethod.YAML.load_file( - joinpath(v3_dir, "aero_geometry_coarse_discretisation.yaml")) +geom_data = VortexStepMethod.YAML.load_file(settings.wings[1].geometry_file) section_headers = geom_data["wing_sections"]["headers"] section_rows = geom_data["wing_sections"]["data"] @@ -84,43 +79,13 @@ body_aero_bill = BodyAerodynamics([wing_bill]) VortexStepMethod.reinit!(body_aero_bill) # --- Build solvers --- -function make_solver(wing) - Solver(wing.n_panels, wing.n_unrefined_sections; - solver_type=(solver_cfg["solver_type"] == "NONLIN" ? - NONLIN : LOOP), - aerodynamic_model_type=getproperty( - VortexStepMethod, - Symbol(solver_cfg["aerodynamic_model_type"])), - density=solver_cfg["density"], - max_iterations=solver_cfg["max_iterations"], - rtol=solver_cfg["rtol"], - tol_reference_error=solver_cfg["tol_reference_error"], - relaxation_factor=solver_cfg["relaxation_factor"], - is_with_artificial_damping=solver_cfg["artificial_damping"], - artificial_damping=( - k2=solver_cfg["k2"], k4=solver_cfg["k4"]), - type_initial_gamma_distribution=getproperty( - VortexStepMethod, - Symbol(solver_cfg["type_initial_gamma_distribution"])), - use_gamma_prev=get(solver_cfg, "use_gamma_prev", - get(solver_cfg, "use_gamme_prev", true)), - core_radius_fraction=solver_cfg["core_radius_fraction"], - mu=solver_cfg["mu"], - is_only_f_and_gamma_output=get( - solver_cfg, "calc_only_f_and_gamma", false), - correct_aoa=get(solver_cfg, "correct_aoa", false), - reference_point=get(solver_cfg, "reference_point", - [0.422646, 0.0, 9.3667]), - ) -end - -solver_flat = make_solver(wing_flat) -solver_bill = make_solver(wing_bill) +solver_flat = Solver(settings; reference_point=[0.422646, 0.0, 9.3667]) +solver_bill = Solver(settings; reference_point=[0.422646, 0.0, 9.3667]) # --- Set flight conditions --- -wind_speed = condition_cfg["wind_speed"] +wind_speed = settings.condition.wind_speed angle_of_attack_deg = 10.0 -sideslip_deg = condition_cfg["beta"] +sideslip_deg = settings.condition.beta α0 = deg2rad(angle_of_attack_deg) β0 = deg2rad(sideslip_deg)