From 6bff691ba2aae8e5817269bdfb926e27f441cf42 Mon Sep 17 00:00:00 2001 From: jellepoland Date: Mon, 23 Feb 2026 15:02:09 +0100 Subject: [PATCH 1/7] allow more aero panel input than available struc geometry --- src/system_structure/system_structure_core.jl | 2 + src/system_structure/utilities.jl | 3 + src/vsm_refine.jl | 90 +++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/src/system_structure/system_structure_core.jl b/src/system_structure/system_structure_core.jl index ab7a38c9..1fa09bbb 100644 --- a/src/system_structure/system_structure_core.jl +++ b/src/system_structure/system_structure_core.jl @@ -834,6 +834,8 @@ function SystemStructure(name, set; @assert wing.idx == i # For REFINE wings, set defaults if not provided if wing.wing_type == REFINE + prime_polars_then_lock_unrefined_to_structure!(wing, points) + # Build point_to_vsm_point mapping if not provided if isnothing(wing.point_to_vsm_point) # Get WING-type points for this wing diff --git a/src/system_structure/utilities.jl b/src/system_structure/utilities.jl index 9a1651a3..f01ca156 100644 --- a/src/system_structure/utilities.jl +++ b/src/system_structure/utilities.jl @@ -389,6 +389,9 @@ function reinit!(sys_struct::SystemStructure, set::Settings; vsm_wing.R_cad_body .= wing.R_b_to_c VortexStepMethod.reinit!( wing.vsm_aero) + + prime_polars_then_lock_unrefined_to_structure!(wing, points) + if !isnothing(wing.point_to_vsm_point) wing_point_idxs = collect( keys(wing.point_to_vsm_point)) diff --git a/src/vsm_refine.jl b/src/vsm_refine.jl index cf590191..ff8caf5b 100644 --- a/src/vsm_refine.jl +++ b/src/vsm_refine.jl @@ -52,6 +52,96 @@ function identify_wing_segments(wing_points::AbstractVector{Point}) return segments end +""" + prime_polars_then_lock_unrefined_to_structure!(wing::VSMWing, points::AbstractVector{Point}) + +Lock REFINE unrefined aerodynamic sections to structural LE/TE sections when +their counts differ, while preserving already initialized refined/panel polars. + +This helper supports workflows that initialize polars from a denser +`aero_geometry.yaml` and then run REFINE coupling from structural sections. + +# Behavior +- If `n_struct_sections == n_aero_sections`: no-op +- If counts differ: + - Requires `wing.vsm_wing.use_prior_polar == true` + - Rebuilds `wing.vsm_wing.unrefined_sections` from structural LE/TE pairs + in body frame + - Calls `refine!(...; sort_sections=false)` and `VortexStepMethod.reinit!` +""" +function prime_polars_then_lock_unrefined_to_structure!( + wing::VSMWing, + points::AbstractVector{Point} +) + wing.wing_type == REFINE || return nothing + + wing_points = [ + p for p in points if + p.type == WING && p.wing_idx == wing.idx + ] + n_points = length(wing_points) + n_points % 2 == 0 || error( + "REFINE wing $(wing.idx) must have an even number of WING points, got $(n_points)" + ) + + n_struct_sections = n_points ÷ 2 + n_aero_sections = length(wing.vsm_wing.unrefined_sections) + + n_struct_sections == n_aero_sections && return nothing + + wing.vsm_wing.use_prior_polar || error( + "REFINE wing $(wing.idx): structural sections ($(n_struct_sections)) " * + "do not match aerodynamic sections ($(n_aero_sections)). " * + "Set use_prior_polar=true to allow one-time polar seeding and lock to structural sections." + ) + + isempty(wing.vsm_wing.refined_sections) && error( + "REFINE wing $(wing.idx): cannot lock unrefined sections because no refined sections exist to reuse polars." + ) + + wing_segments = identify_wing_segments(wing_points) + length(wing_segments) == n_struct_sections || error( + "REFINE wing $(wing.idx): failed to identify structural LE/TE pairs." + ) + + template_sections = wing.vsm_wing.unrefined_sections + n_templates = length(template_sections) + n_templates > 0 || error( + "REFINE wing $(wing.idx): aerodynamic geometry has zero unrefined sections." + ) + R_b_to_c = wing.R_b_to_c + origin_cad = wing.pos_cad + new_sections = Vector{VortexStepMethod.Section}(undef, n_struct_sections) + + for (i, (le_idx, te_idx)) in enumerate(wing_segments) + template_idx = n_struct_sections == 1 ? 1 : + round(Int, 1 + (i - 1) * (n_templates - 1) / (n_struct_sections - 1)) + template = template_sections[template_idx] + + le_body = R_b_to_c' * (points[le_idx].pos_cad - origin_cad) + te_body = R_b_to_c' * (points[te_idx].pos_cad - origin_cad) + + section = VortexStepMethod.Section() + if isnothing(template.aero_data) + VortexStepMethod.reinit!( + section, le_body, te_body, template.aero_model + ) + else + VortexStepMethod.reinit!( + section, le_body, te_body, template.aero_model, template.aero_data + ) + end + new_sections[i] = section + end + + wing.vsm_wing.unrefined_sections = new_sections + wing.vsm_wing.n_unrefined_sections = Int16(n_struct_sections) + + refine!(wing.vsm_wing; recompute_mapping=true, sort_sections=false) + VortexStepMethod.reinit!(wing.vsm_aero) + return nothing +end + """ build_point_to_vsm_point_mapping(wing_points::AbstractVector{Point}, vsm_wing::VortexStepMethod.AbstractWing) From ade8feb61e3baa60b41fa05bd7749df07156e2a8 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 27 Feb 2026 11:05:02 +0100 Subject: [PATCH 2/7] Convert to real test --- test/test_bench.jl | 401 +++++++++++++++------------------------------ 1 file changed, 130 insertions(+), 271 deletions(-) diff --git a/test/test_bench.jl b/test/test_bench.jl index 8fc528b9..cfd82c11 100644 --- a/test/test_bench.jl +++ b/test/test_bench.jl @@ -1,11 +1,13 @@ # SPDX-FileCopyrightText: 2025 Bart van de Lint # SPDX-License-Identifier: MPL-2.0 -# Benchmark ODE RHS for 2plate_kite model. -# Tests: raw RHS, registered functions directly, allocation profile. +# Benchmark tests for ODE RHS of 2plate_kite model. +# Verifies allocation counts for registered functions and +# ensures no allocations originate from package source code. # # Usage: julia --project=test test/test_bench.jl +using Test using SymbolicAWEModels using SymbolicAWEModels: VortexStepMethod, SystemStructure, KVec3 using KiteUtils @@ -14,301 +16,158 @@ using Statistics using Printf using Profile -function setup_sam() +function setup_bench_sam() pkg_root = dirname(@__DIR__) src_data = joinpath(pkg_root, "data", "2plate_kite") - tmpdir = mktempdir() - data_path = joinpath(tmpdir, "2plate_kite") - cp(src_data, data_path; force=true) - - set_data_path(data_path) + dp = joinpath(tmpdir, "2plate_kite") + cp(src_data, dp; force=true) + set_data_path(dp) set = Settings("system.yaml") - vsm_set = VortexStepMethod.VSMSettings( - joinpath(data_path, "vsm_settings.yaml"); + joinpath(dp, "vsm_settings.yaml"); data_prefix=false) - - struc_yaml = joinpath(data_path, - "quat_struc_geometry.yaml") + struc_yaml = joinpath(dp, "quat_struc_geometry.yaml") sys = load_sys_struct_from_yaml(struc_yaml; system_name="bench", set, vsm_set) sys.winches[:main_winch].brake = true - sam = SymbolicAWEModel(set, sys) - init!(sam; remake=false, prn=true) + init!(sam; remake=false, prn=false) return sam end -# --- 1. RHS Benchmark --- -function bench_rhs(sam) - f = sam.integrator.f - u = copy(sam.integrator.u) - p = sam.integrator.p - t = sam.integrator.t - du = similar(u) - f(du, u, p, t) - return @benchmark $f($du, $u, $p, $t) samples=10 +function get_pkg_src_files() + pkg_root = dirname(@__DIR__) + src_files = Set{String}() + for (_, _, files) in walkdir(joinpath(pkg_root, "src")) + for f in files + endswith(f, ".jl") && push!(src_files, f) + end + end + return src_files end -# --- 2. Direct registered function calls --- -function bench_registered_functions(sys::SystemStructure) +@testset verbose = true "Benchmarks" begin + sam = setup_bench_sam() + sys = sam.sys_struct idx = Int64(1) - # Warmup - SymbolicAWEModels.get_pos_w(sys, idx) - SymbolicAWEModels.get_Q_b_to_w(sys, idx) - SymbolicAWEModels.get_l0(sys, idx) - SymbolicAWEModels.get_extra_mass(sys, idx) - - header = @sprintf(" %-20s %6s\n", "Function", "Allocs") - sep = " " * "-"^30 - - # Raw field access - println("\n Raw field access (no @register):") - println(sep) - print(header) - println(sep) - - a = @allocations sys.segments[idx].l0 - @printf(" %-20s %6d\n", "seg.l0", a) - - a = @allocations sys.points[idx].extra_mass - @printf(" %-20s %6d\n", "pt.extra_mass", a) - - a = @allocations sys.points[idx].pos_w - @printf(" %-20s %6d\n", "pt.pos_w", a) - - a = @allocations sys.wings[idx].Q_b_to_w - @printf(" %-20s %6d\n", "wing.Q_b_to_w", a) - - a = @allocations sys.wings[idx].com_w - @printf(" %-20s %6d\n", "wing.com_w", a) - - a = @allocations sys.wings[idx].R_b_to_p - @printf(" %-20s %6d\n", "wing.R_b_to_p", a) - - a = @allocations sys.wings[idx].inertia_principal - @printf(" %-20s %6d\n", "wing.inertia_princ", a) - - # @register_symbolic calls - println("\n @register_symbolic calls:") - println(sep) - print(header) - println(sep) - - a = @allocations SymbolicAWEModels.get_l0(sys, idx) - @printf(" %-20s %6d\n", "get_l0", a) - - a = @allocations SymbolicAWEModels.get_extra_mass(sys, idx) - @printf(" %-20s %6d\n", "get_extra_mass", a) - - a = @allocations SymbolicAWEModels.get_pos_w(sys, idx) - @printf(" %-20s %6d\n", "get_pos_w", a) - - a = @allocations SymbolicAWEModels.get_Q_b_to_w(sys, idx) - @printf(" %-20s %6d\n", "get_Q_b_to_w", a) - - a = @allocations SymbolicAWEModels.get_com_w(sys, idx) - @printf(" %-20s %6d\n", "get_com_w", a) - - a = @allocations SymbolicAWEModels.get_R_b_to_p(sys, idx) - @printf(" %-20s %6d\n", "get_R_b_to_p", a) - - a = @allocations SymbolicAWEModels.get_inertia_principal( - sys, idx) - @printf(" %-20s %6d\n", "get_inertia_princ", a) - - # VSM accessors - println("\n VSM accessors:") - println(sep) - print(header) - println(sep) - - a = @allocations SymbolicAWEModels.get_vsm_y(sys, idx, 1) - @printf(" %-20s %6d\n", "get_vsm_y", a) - a = @allocations SymbolicAWEModels.get_vsm_x(sys, idx, 1) - @printf(" %-20s %6d\n", "get_vsm_x", a) - - a = @allocations SymbolicAWEModels.get_vsm_jac( - sys, idx, 1, 1) - @printf(" %-20s %6d\n", "get_vsm_jac", a) - - a = @allocations SymbolicAWEModels.get_aero_force_override( - sys, idx, 1) - @printf(" %-20s %6d\n", "get_aero_f_override", a) - - a = @allocations SymbolicAWEModels.get_aero_moment_override( - sys, idx, 1) - @printf(" %-20s %6d\n", "get_aero_m_override", a) -end - -# --- 3. Allocation profile --- -function profile_rhs_allocs(sam) - f = sam.integrator.f - u = copy(sam.integrator.u) - p = sam.integrator.p - t = sam.integrator.t - du = similar(u) - f(du, u, p, t) - - Profile.Allocs.clear() - Profile.Allocs.@profile sample_rate=1.0 f(du, u, p, t) - results = Profile.Allocs.fetch() - - type_counts = Dict{Any,Int}() - type_bytes = Dict{Any,Int}() - - # Helper: is this a meaningful Julia source frame? - function is_julia_src(frame) - frame.line <= 0 && return false - file = string(frame.file) - # Skip C runtime, GC, profiler, sysimage - contains(file, "gc-") && return false - contains(file, "Profile") && return false - contains(file, "datatype.c") && return false - endswith(file, ".c") && return false - endswith(file, ".h") && return false - file == ":-1" && return false - return true + @testset "ODE RHS" begin + f = sam.integrator.f + u = copy(sam.integrator.u) + p = sam.integrator.p + t = sam.integrator.t + du = similar(u) + f(du, u, p, t) + + rhs = @benchmark $f($du, $u, $p, $t) samples = 10 + med_ms = median(rhs.times) / 1e6 + @printf(" median: %8.3f ms | allocs: %d (%d B)\n", + med_ms, rhs.allocs, rhs.memory) + @test rhs.allocs <= 200 end - # Aggregate by source location (first Julia src frame) - loc_counts = Dict{String,Int}() - loc_bytes = Dict{String,Int}() - - for a in results.allocs - T = a.type - type_counts[T] = get(type_counts, T, 0) + 1 - type_bytes[T] = get(type_bytes, T, 0) + a.size - - loc = "unknown" - for frame in a.stacktrace - is_julia_src(frame) || continue - file = string(frame.file) - # Skip base Julia math (sys.so compiled) - endswith(file, ".so") && continue - basename(file) in ( - "int.jl", "float.jl", "promotion.jl", - "number.jl", "boot.jl") && continue - loc = "$(basename(file)):$(frame.line)" - break - end - loc_counts[loc] = get(loc_counts, loc, 0) + 1 - loc_bytes[loc] = get(loc_bytes, loc, 0) + a.size + # --- warmup all accessors once --- + SymbolicAWEModels.get_l0(sys, idx) + SymbolicAWEModels.get_extra_mass(sys, idx) + SymbolicAWEModels.get_pos_w(sys, idx) + SymbolicAWEModels.get_Q_b_to_w(sys, idx) + SymbolicAWEModels.get_com_w(sys, idx) + SymbolicAWEModels.get_R_b_to_p(sys, idx) + SymbolicAWEModels.get_inertia_principal(sys, idx) + SymbolicAWEModels.get_vsm_y(sys, idx, 1) + SymbolicAWEModels.get_vsm_x(sys, idx, 1) + SymbolicAWEModels.get_vsm_jac(sys, idx, 1, 1) + SymbolicAWEModels.get_aero_force_override(sys, idx, 1) + SymbolicAWEModels.get_aero_moment_override(sys, idx, 1) + + @testset "@register_symbolic" begin + a = @allocations SymbolicAWEModels.get_l0(sys, idx) + @test a == 0 + a = @allocations SymbolicAWEModels.get_extra_mass( + sys, idx) + @test a == 0 + a = @allocations SymbolicAWEModels.get_pos_w( + sys, idx) + @test a <= 1 + a = @allocations SymbolicAWEModels.get_Q_b_to_w( + sys, idx) + @test a == 0 + a = @allocations SymbolicAWEModels.get_com_w( + sys, idx) + @test a == 0 + a = @allocations SymbolicAWEModels.get_R_b_to_p( + sys, idx) + @test a == 0 + a = @allocations SymbolicAWEModels.get_inertia_principal( + sys, idx) + @test a == 0 end - # Aggregate by call stack (top 5 Julia src frames, - # skipping base math) - stack_counts = Dict{String,Int}() - stack_bytes = Dict{String,Int}() - for a in results.allocs - frames = String[] - for frame in a.stacktrace - is_julia_src(frame) || continue - fname = basename(string(frame.file)) - func = string(frame.func) - # Truncate long generated function names - if length(func) > 40 - func = func[1:37] * "..." - end - push!(frames, "$func ($fname:$(frame.line))") - length(frames) >= 5 && break - end - key = isempty(frames) ? "unknown" : - join(frames, "\n <- ") - stack_counts[key] = get(stack_counts, key, 0) + 1 - stack_bytes[key] = get(stack_bytes, key, 0) + a.size + @testset "VSM accessors" begin + a = @allocations SymbolicAWEModels.get_vsm_y( + sys, idx, 1) + @test a == 0 + a = @allocations SymbolicAWEModels.get_vsm_x( + sys, idx, 1) + @test a == 0 + a = @allocations SymbolicAWEModels.get_vsm_jac( + sys, idx, 1, 1) + @test a <= 2 + a = @allocations SymbolicAWEModels.get_aero_force_override( + sys, idx, 1) + @test a <= 4 + a = @allocations SymbolicAWEModels.get_aero_moment_override( + sys, idx, 1) + @test a == 0 end - return (; type_counts, type_bytes, - loc_counts, loc_bytes, - stack_counts, stack_bytes) -end - -# --- Reporting --- -function print_rhs_bench(rhs) - println("\n", "="^60) - println(" ODE RHS Benchmark") - println("="^60) - @printf(" median: %8.3f ms\n", - median(rhs.times) / 1e6) - @printf(" allocs: %8d (%d bytes)\n", - rhs.allocs, rhs.memory) - println("="^60) -end - -function print_alloc_profile(prof) - (; type_counts, type_bytes, - loc_counts, loc_bytes, - stack_counts, stack_bytes) = prof - sorted = sort(collect(type_counts); by=last, rev=true) - total = sum(values(type_counts)) - - println("\n", "="^60) - println(" Allocation Profile by Type ($total total)") - println("="^60) - @printf(" %-35s %7s %10s\n", "Type", "Count", "Bytes") - println(" ", "-"^56) - for (T, count) in sorted[1:min(15, end)] - name = string(T) - if length(name) > 35 - name = name[1:32] * "..." + @testset "No package allocations in RHS" begin + f = sam.integrator.f + u = copy(sam.integrator.u) + p = sam.integrator.p + t = sam.integrator.t + du = similar(u) + f(du, u, p, t) + + Profile.Allocs.clear() + Profile.Allocs.@profile sample_rate = 1.0 begin + f(du, u, p, t) end - bytes = get(type_bytes, T, 0) - @printf(" %-35s %7d %10d\n", name, count, bytes) - end - println("="^60) - - # --- By source location --- - loc_sorted = sort(collect(loc_counts); - by=last, rev=true) - println("\n", "="^70) - println(" Top Allocating Source Locations") - println("="^70) - @printf(" %-50s %7s %10s\n", - "Location", "Count", "Bytes") - println(" ", "-"^67) - for (loc, count) in loc_sorted[1:min(20, end)] - name = loc - if length(name) > 50 - name = "..." * name[end-46:end] + results = Profile.Allocs.fetch() + src_files = get_pkg_src_files() + + skip_bases = ("int.jl", "float.jl", "promotion.jl", + "number.jl", "boot.jl") + + pkg_locs = String[] + for a in results.allocs + for frame in a.stacktrace + frame.line <= 0 && continue + file = string(frame.file) + any(p -> contains(file, p), + ("gc-", "Profile", "datatype.c")) && + continue + (endswith(file, ".c") || + endswith(file, ".h")) && continue + file == ":-1" && continue + fname = basename(file) + endswith(fname, ".so") && continue + fname in skip_bases && continue + if fname in src_files + loc = "$fname:$(frame.line)" + loc ∉ pkg_locs && push!(pkg_locs, loc) + end + break # only check first meaningful frame + end end - bytes = get(loc_bytes, loc, 0) - @printf(" %-50s %7d %10d\n", name, count, bytes) - end - println("="^70) - # --- By call stack --- - stack_sorted = sort(collect(stack_counts); - by=last, rev=true) - println("\n", "="^70) - println(" Top Allocating Call Stacks (top 3 frames)") - println("="^70) - for (i, (stack, count)) in enumerate( - stack_sorted[1:min(15, end)]) - bytes = get(stack_bytes, stack, 0) - @printf(" #%-2d %5d allocs (%d bytes)\n", - i, count, bytes) - for frame in split(stack, " <- ") - println(" ", frame) + if !isempty(pkg_locs) + println(" Allocating locations in package src:") + for loc in pkg_locs + println(" ", loc) + end end - println() + @test isempty(pkg_locs) end - println("="^70) end - -# --- Run --- -println("\n>> Setting up 2plate_kite model...") -sam = setup_sam() - -println("\n>> Benchmarking ODE RHS...") -rhs = bench_rhs(sam) -print_rhs_bench(rhs) - -println("\n>> Benchmarking registered functions directly...") -bench_registered_functions(sam.sys_struct) - -println("\n>> Profiling RHS allocations...") -prof = profile_rhs_allocs(sam) -print_alloc_profile(prof) From dee01fd7340b53d7f0c83b910ab3f698a1c8e388 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 27 Feb 2026 12:08:42 +0100 Subject: [PATCH 3/7] Improve and unify locking --- Manifest-v1.12.toml | 4 +- data/2plate_kite/aero_geometry.yaml | 6 +- examples/coupled_2plate_kite.jl | 2 +- src/system_structure/system_structure_core.jl | 169 ++++++----- src/system_structure/utilities.jl | 61 ++-- src/system_structure/wing.jl | 7 +- src/vsm_refine.jl | 227 +++++++++++---- src/yaml_loader.jl | 25 +- test/test_prime_polars.jl | 268 ++++++++++++++++++ test/test_quaternion_auto_groups.jl | 125 ++++---- 10 files changed, 662 insertions(+), 232 deletions(-) create mode 100644 test/test_prime_polars.jl diff --git a/Manifest-v1.12.toml b/Manifest-v1.12.toml index 65519780..580a5693 100644 --- a/Manifest-v1.12.toml +++ b/Manifest-v1.12.toml @@ -2,7 +2,7 @@ julia_version = "1.12.5" manifest_format = "2.0" -project_hash = "d296d3061f996a5cbf044df76a287df0b07ac23f" +project_hash = "9c15a3db3961b4c54c236d98049d4aa24d20cca9" [[deps.ADTypes]] git-tree-sha1 = "f7304359109c768cf32dc5fa2d371565bb63b68a" @@ -1925,7 +1925,7 @@ version = "0.2.8" deps = ["AtmosphericModels", "CodecZlib", "ControlSystemsBase", "Dates", "DocStringExtensions", "KiteUtils", "LaTeXStrings", "LinearAlgebra", "Logging", "ModelingToolkit", "NonlinearSolve", "OrdinaryDiffEqBDF", "OrdinaryDiffEqCore", "OrdinaryDiffEqNonlinearSolve", "Parameters", "Pkg", "PrecompileTools", "Printf", "RecipesBase", "SHA", "Serialization", "StaticArrays", "Statistics", "SteadyStateDiffEq", "Suppressor", "SymbolicIndexingInterface", "SymbolicUtils", "Symbolics", "TOML", "Tar", "Timers", "UnPack", "VortexStepMethod", "YAML"] path = "." uuid = "9c9a347c-5289-41db-a9b9-25ccc76c3360" -version = "0.5.0" +version = "0.6.1" [deps.SymbolicAWEModels.extensions] SymbolicAWEModelsMakieExt = ["GeometryBasics", "Makie"] diff --git a/data/2plate_kite/aero_geometry.yaml b/data/2plate_kite/aero_geometry.yaml index 7634fb5a..ced517f8 100644 --- a/data/2plate_kite/aero_geometry.yaml +++ b/data/2plate_kite/aero_geometry.yaml @@ -7,13 +7,13 @@ wing_sections: headers: [airfoil_id, LE_x, LE_y, LE_z, TE_x, TE_y, TE_z] data: # Right section: points 2 (LE) and 3 (TE) - - [1, -0.5, 1.0, 2.0, 0.5, 1.0, 2.2] + - [1, -0.5, 1.0, 2.0, 0.5, 1.0, 2.3] # Center section: points 4 (LE) and 5 (TE) - - [1, -0.5, 0.0, 2.5, 0.5, 0.0, 2.7] + - [1, -0.5, 0.0, 2.5, 0.5, 0.0, 2.8] # Left section: points 6 (LE) and 7 (TE) - - [1, -0.5, -1.0, 2.0, 0.5, -1.0, 2.2] + - [1, -0.5, -1.0, 2.0, 0.5, -1.0, 2.3] wing_airfoils: alpha_range: [-180, 180, 1] # deg diff --git a/examples/coupled_2plate_kite.jl b/examples/coupled_2plate_kite.jl index af6d37ff..1664854d 100644 --- a/examples/coupled_2plate_kite.jl +++ b/examples/coupled_2plate_kite.jl @@ -20,7 +20,7 @@ pkg_root = dirname(@__DIR__) set_data_path(joinpath(pkg_root, "data", MODEL_NAME)) struc_yaml = joinpath(get_data_path(), - "quat_struc_geometry.yaml") + "refine_struc_geometry.yaml") aero_yaml = joinpath(get_data_path(), "aero_geometry.yaml") update_aero_yaml_from_struc_yaml!(struc_yaml, aero_yaml) diff --git a/src/system_structure/system_structure_core.jl b/src/system_structure/system_structure_core.jl index 1fa09bbb..e25983b8 100644 --- a/src/system_structure/system_structure_core.jl +++ b/src/system_structure/system_structure_core.jl @@ -398,6 +398,82 @@ function calc_inertia_y_rotation(I_tensor) return I_diag, Ry end +""" + compute_spatial_group_mapping!(the_wing, groups, points) + +Map groups to unrefined sections using spatial proximity. +Each group is assigned to the closest unrefined section +based on distance between centers. +""" +function compute_spatial_group_mapping!( + the_wing::VSMWing, + groups::AbstractVector{Group}, + points::AbstractVector{Point} +) + the_vsm_wing = the_wing.vsm_wing + n_unrefined = the_vsm_wing.n_unrefined_sections + n_groups = length(the_wing.base.group_idxs) + + # Compute group centers in body frame + group_centers = Vector{MVec3}(undef, n_groups) + for (local_idx, group_idx) in + enumerate(the_wing.base.group_idxs) + group = groups[group_idx] + center = zeros(3) + for pt_idx in group.point_idxs + center += the_wing.base.R_b_to_c' * + (points[pt_idx].pos_cad - + the_wing.base.pos_cad) + end + group_centers[local_idx] = + center / length(group.point_idxs) + end + + # Compute unrefined section centers + unrefined_centers = Vector{MVec3}( + undef, n_unrefined) + for i in 1:n_unrefined + le_point = + the_vsm_wing.unrefined_sections[i].LE_point + te_point = + the_vsm_wing.unrefined_sections[i].TE_point + unrefined_centers[i] = + (le_point + te_point) / 2 + end + + # Map each group to closest unrefined section + for (local_idx, group_idx) in + enumerate(the_wing.base.group_idxs) + group = groups[group_idx] + min_dist = Inf + closest_idx = 1 + for unrefined_idx in 1:n_unrefined + dist = norm( + group_centers[local_idx] - + unrefined_centers[unrefined_idx]) + if dist < min_dist + min_dist = dist + closest_idx = unrefined_idx + end + end + group.unrefined_section_idxs = + Int64[closest_idx] + end + + # Validate: check all sections are covered + assigned = Set{Int64}() + for group_idx in the_wing.base.group_idxs + union!(assigned, + groups[group_idx].unrefined_section_idxs) + end + if length(assigned) != n_unrefined + unassigned = setdiff(1:n_unrefined, assigned) + @warn "Wing $(the_wing.base.idx): " * + "$(length(unassigned)) unrefined sections " * + "not assigned to any group: $unassigned" + end +end + # ==================== CONSTRUCTOR ==================== # """ @@ -459,14 +535,6 @@ function SystemStructure(name, set; tether_names_dict, winch_names_dict, wing_names_dict, transform_names_dict) = assign_indices_and_resolve!(points, groups, segments, pulleys, tethers, winches, wings, transforms) - # For REFINE wings, clear group_idxs - groups are not used with REFINE - # (REFINE applies panel forces directly to structural points) - for wing in wings - if wing.wing_type == REFINE && !isempty(wing.group_idxs) - empty!(wing.group_idxs) - end - end - # If no wings defined, convert WING points to STATIC if isempty(wings) wing_point_idxs = findall(p -> p.type == WING, points) @@ -682,12 +750,14 @@ function SystemStructure(name, set; # Use integer as name for auto-created groups group_name = group_idx - # Only TE point, moment_frac=0.0 (rotate around LE) - new_group = Group(group_name, [te_idx], DYNAMIC, 0.0) + # Both LE and TE points (matches YAML convention) + new_group = Group(group_name, + [le_idx, te_idx], DYNAMIC, 0.0) - # Assign idx and resolve point_refs since these are dynamically created + # Assign idx and resolve point_refs since + # these are dynamically created new_group.idx = group_idx - new_group.point_idxs = [te_idx] + new_group.point_idxs = [le_idx, te_idx] push!(groups, new_group) push!(new_group_idxs, Int64(group_idx)) @@ -709,59 +779,24 @@ function SystemStructure(name, set; end end - """ - compute_spatial_group_mapping!(the_wing, groups, points) - - Map groups to unrefined sections using spatial proximity. - Each group is assigned to the closest unrefined section based on distance between centers. - """ - function compute_spatial_group_mapping!(the_wing::VSMWing, groups::AbstractVector{Group}, points::AbstractVector{Point}) - the_vsm_wing = the_wing.vsm_wing - n_unrefined = the_vsm_wing.n_unrefined_sections - n_groups = length(the_wing.base.group_idxs) - - # Compute group centers in body frame (average of all attach points) - group_centers = Vector{MVec3}(undef, n_groups) - for (local_idx, group_idx) in enumerate(the_wing.base.group_idxs) - group = groups[group_idx] - center = zeros(3) - for pt_idx in group.point_idxs - center += the_wing.base.R_b_to_c' * (points[pt_idx].pos_cad - the_wing.base.pos_cad) - end - group_centers[local_idx] = center / length(group.point_idxs) - end - - # Compute unrefined section centers - unrefined_centers = Vector{MVec3}(undef, n_unrefined) - for i in 1:n_unrefined - le_point = the_vsm_wing.unrefined_sections[i].LE_point - te_point = the_vsm_wing.unrefined_sections[i].TE_point - unrefined_centers[i] = (le_point + te_point) / 2 - end - - # Map each group to closest unrefined section - for (local_idx, group_idx) in enumerate(the_wing.base.group_idxs) - group = groups[group_idx] - min_dist = Inf - closest_idx = 1 - for unrefined_idx in 1:n_unrefined - dist = norm(group_centers[local_idx] - unrefined_centers[unrefined_idx]) - if dist < min_dist - min_dist = dist - closest_idx = unrefined_idx - end - end - group.unrefined_section_idxs = Int64[closest_idx] - end + # Lock unrefined aero sections to structural LE/TE for + # ALL VSMWing types (runs after auto-group creation so + # identify_wing_segments can use groups). + for wing in wings + isa(wing, VSMWing) || continue + wing.aero_mode == AERO_NONE && continue + prime_polars_then_lock_unrefined_to_structure!( + wing, points; groups=groups) + end - # Validate: check all sections are covered - assigned = Set{Int64}() - for group_idx in the_wing.base.group_idxs - union!(assigned, groups[group_idx].unrefined_section_idxs) - end - if length(assigned) != n_unrefined - unassigned = setdiff(1:n_unrefined, assigned) - @warn "Wing $(the_wing.base.idx): $(length(unassigned)) unrefined sections not assigned to any group: $unassigned" + # Clear REFINE wing.group_idxs — groups were used + # for LE/TE identification but REFINE doesn't use + # them for aerodynamics. Groups stay in sys_struct + # (useful for structural info / future linearization). + for wing in wings + if wing.wing_type == REFINE && + !isempty(wing.group_idxs) + empty!(wing.group_idxs) end end @@ -834,8 +869,6 @@ function SystemStructure(name, set; @assert wing.idx == i # For REFINE wings, set defaults if not provided if wing.wing_type == REFINE - prime_polars_then_lock_unrefined_to_structure!(wing, points) - # Build point_to_vsm_point mapping if not provided if isnothing(wing.point_to_vsm_point) # Get WING-type points for this wing @@ -860,7 +893,9 @@ function SystemStructure(name, set; # Identify wing segments (LE/TE pairs) if isnothing(wing.wing_segments) wing.wing_segments = - identify_wing_segments(wing_points) + identify_wing_segments( + wing_points; groups=groups, + wing_group_idxs=wing.group_idxs) end # Set default reference points if not provided diff --git a/src/system_structure/utilities.jl b/src/system_structure/utilities.jl index 25f3b3e2..54019513 100644 --- a/src/system_structure/utilities.jl +++ b/src/system_structure/utilities.jl @@ -369,38 +369,39 @@ function reinit!(sys_struct::SystemStructure, set::Settings; # Transform sections: CAD → body frame # (must match SystemStructure constructor) vsm_wing = wing.vsm_wing - if wing.wing_type == QUATERNION - vsm_wing.T_cad_body .= wing.pos_cad - adjust_vsm_panels_to_origin!( - vsm_wing, wing.pos_cad) - rotate_vsm_sections!( - vsm_wing, wing.R_b_to_c') - vsm_wing.R_cad_body .= wing.R_b_to_c + vsm_wing.T_cad_body .= wing.pos_cad + adjust_vsm_panels_to_origin!( + vsm_wing, wing.pos_cad) + rotate_vsm_sections!( + vsm_wing, wing.R_b_to_c') + vsm_wing.R_cad_body .= wing.R_b_to_c + if wing.wing_type != REFINE apply_aero_z_offset!( vsm_wing, wing.aero_z_offset) - VortexStepMethod.reinit!( - wing.vsm_aero) - elseif wing.wing_type == REFINE - vsm_wing.T_cad_body .= wing.pos_cad - adjust_vsm_panels_to_origin!( - vsm_wing, wing.pos_cad) - rotate_vsm_sections!( - vsm_wing, wing.R_b_to_c') - vsm_wing.R_cad_body .= wing.R_b_to_c - VortexStepMethod.reinit!( - wing.vsm_aero) - - prime_polars_then_lock_unrefined_to_structure!(wing, points) - - if !isnothing(wing.point_to_vsm_point) - wing_point_idxs = collect( - keys(wing.point_to_vsm_point)) - wing_points = [points[idx] - for idx in wing_point_idxs] - wing.point_to_vsm_point = - build_point_to_vsm_point_mapping( - wing_points, vsm_wing) - end + end + VortexStepMethod.reinit!(wing.vsm_aero) + + # Lock aero sections to structure (all types) + prime_polars_then_lock_unrefined_to_structure!( + wing, points; groups=groups) + + # Recompute group→section mapping + if wing.wing_type == QUATERNION && + !isempty(wing.group_idxs) + compute_spatial_group_mapping!( + wing, groups, points) + end + + # REFINE-only: rebuild point mapping + if wing.wing_type == REFINE && + !isnothing(wing.point_to_vsm_point) + wing_point_idxs = collect( + keys(wing.point_to_vsm_point)) + wing_pts = [points[idx] + for idx in wing_point_idxs] + wing.point_to_vsm_point = + build_point_to_vsm_point_mapping( + wing_pts, vsm_wing) end end end diff --git a/src/system_structure/wing.jl b/src/system_structure/wing.jl index 6fdb4908..d47f9aa3 100644 --- a/src/system_structure/wing.jl +++ b/src/system_structure/wing.jl @@ -316,7 +316,8 @@ Creates vsm_wing, vsm_aero, and vsm_solver internally. - `y_damping::SimFloat=150.0`: Lateral damping coefficient. - `wing_type::WingType=QUATERNION`: Aerodynamic model type. - `point_to_vsm_point`: 1:1 structural point to VSM point mapping (REFINE only). -- `wing_segments`: LE/TE pairs (REFINE only). +- `wing_segments`: LE/TE pairs (populated for all VSM wing types by + `prime_polars_then_lock_unrefined_to_structure!`). - `z_ref_points`: Chord direction reference points (REFINE only, names or indices). - `y_ref_points`: Span direction reference points (REFINE only, names or indices). - `origin`: Reference to origin point (REFINE only, name or index). @@ -346,8 +347,6 @@ function VSMWing(name, set::Settings, # Validation if wing_type == REFINE - @assert length(groups) == 0 - "REFINE wings cannot have groups" @assert !isnothing(origin) "REFINE wings require origin to define KCU position" if !isnothing(pos_cad) @@ -359,8 +358,6 @@ function VSMWing(name, set::Settings, else @assert isnothing(point_to_vsm_point) "QUATERNION wings: no point_to_vsm_point" - @assert isnothing(wing_segments) - "QUATERNION wings: no wing_segments" # origin, z_ref_points, y_ref_points are now # accepted for QUATERNION wings (body frame # defined by structural ref points) diff --git a/src/vsm_refine.jl b/src/vsm_refine.jl index e2e1e9fb..acc0d60a 100644 --- a/src/vsm_refine.jl +++ b/src/vsm_refine.jl @@ -2,8 +2,11 @@ # SPDX-License-Identifier: MPL-2.0 """ -Helper functions for REFINE wing type that applies VSM panel forces directly to -structural points. +Helper functions for VSM wing types. + +REFINE-specific functions (panel force distribution, structural geometry +updates) are at the bottom of this file. The shared +`prime_polars_then_lock_unrefined_to_structure!` works for all VSMWing types. """ # Baseline chord-based aero scaling for REFINE wings. @@ -11,37 +14,81 @@ structural points. const AERO_SCALE_CHORD = 0.0 """ - identify_wing_segments(wing_points::AbstractVector{Point}) + identify_wing_segments(wing_points; groups=nothing, wing_group_idxs=nothing) Identify wing segments (LE/TE pairs) from WING-type points. -Assumes points are organized in pairs along the span, with even-numbered points -being leading edge and odd-numbered being trailing edge (or vice versa). +When `groups` and `wing_group_idxs` are provided, uses group `point_idxs` +to determine LE (`point_idxs[1]`) and TE (`point_idxs[end]`) for each +section. Falls back to a consecutive-pair heuristic (sorted by point index) +when groups are unavailable. + +In both paths an x-coordinate check swaps LE/TE if needed (LE has +smaller `pos_cad[1]`). # Arguments -- `wing_points::AbstractVector{Point}`: All WING-type points for a wing (sorted by index) +- `wing_points::AbstractVector{Point}`: WING-type points for a wing. + +# Keyword Arguments +- `groups::Union{Nothing, AbstractVector{Group}}`: All groups in the + system (indexed by `wing_group_idxs`). +- `wing_group_idxs::Union{Nothing, AbstractVector{<:Integer}}`: + Indices into `groups` belonging to this wing. # Returns -- `Vector{Tuple{Int64, Int64}}`: Vector of (le_point_idx, te_point_idx) pairs defining segments +- `Vector{Tuple{Int64, Int64}}`: (le_point_idx, te_point_idx) pairs. """ -function identify_wing_segments(wing_points::AbstractVector{Point}) - # Sort points by index to ensure consistent ordering +function identify_wing_segments( + wing_points::AbstractVector{Point}; + groups::Union{Nothing, AbstractVector{Group}}=nothing, + wing_group_idxs::Union{Nothing, + AbstractVector{<:Integer}}=nothing +) + use_groups = !isnothing(groups) && + !isnothing(wing_group_idxs) && + !isempty(wing_group_idxs) + + if use_groups + segments = Tuple{Int64, Int64}[] + for g_idx in wing_group_idxs + group = groups[g_idx] + length(group.point_idxs) >= 2 || error( + "Group $(group.name): need at least " * + "2 point_idxs (LE/TE), got " * + "$(length(group.point_idxs))") + le_idx = group.point_idxs[1] + te_idx = group.point_idxs[end] + le_point = wing_points[findfirst( + p -> p.idx == le_idx, wing_points)] + te_point = wing_points[findfirst( + p -> p.idx == te_idx, wing_points)] + # Safety: swap if LE actually has larger x + if le_point.pos_cad[1] < te_point.pos_cad[1] + push!(segments, (le_idx, te_idx)) + else + push!(segments, (te_idx, le_idx)) + end + end + return segments + end + + # Fallback: consecutive-pair heuristic sorted_points = sort(wing_points, by=p->p.idx) n_points = length(sorted_points) - @assert n_points % 2 == 0 "Wing must have even number of points (LE/TE pairs)" + @assert n_points % 2 == 0 ( + "Wing must have even number of points " * + "(LE/TE pairs)") n_segments = n_points ÷ 2 segments = Tuple{Int64, Int64}[] - # Group consecutive pairs: (point[1], point[2]), (point[3], point[4]), ... for i in 1:n_segments le_idx = 2*i - 1 te_idx = 2*i le_point = sorted_points[le_idx] te_point = sorted_points[te_idx] - # Determine which is LE and which is TE by x-coordinate (LE has smaller x) if le_point.pos_cad[1] < te_point.pos_cad[1] push!(segments, (le_point.idx, te_point.idx)) else @@ -53,92 +100,160 @@ function identify_wing_segments(wing_points::AbstractVector{Point}) end """ - prime_polars_then_lock_unrefined_to_structure!(wing::VSMWing, points::AbstractVector{Point}) + prime_polars_then_lock_unrefined_to_structure!(wing, points; groups) + +Lock unrefined aerodynamic sections to structural LE/TE positions, +preserving already-initialized refined/panel polars. -Lock REFINE unrefined aerodynamic sections to structural LE/TE sections when -their counts differ, while preserving already initialized refined/panel polars. +Works for **all** VSMWing types (QUATERNION and REFINE). When the +structural and aerodynamic section counts match the rebuild is a 1:1 +copy (`template_idx == i`) that ensures positions exactly match +structural points. When they differ, `use_prior_polar` and non-empty +`refined_sections` are required. -This helper supports workflows that initialize polars from a denser -`aero_geometry.yaml` and then run REFINE coupling from structural sections. +For non-REFINE wings whose section count changed, the linearization +vectors (`vsm_y`, `vsm_x`, `vsm_jac`) are resized to match the new +`n_unrefined_sections`. -# Behavior -- If `n_struct_sections == n_aero_sections`: no-op -- If counts differ: - - Requires `wing.vsm_wing.use_prior_polar == true` - - Rebuilds `wing.vsm_wing.unrefined_sections` from structural LE/TE pairs - in body frame - - Calls `refine!(...; sort_sections=false)` and `VortexStepMethod.reinit!` +# Keyword Arguments +- `groups::AbstractVector{Group}`: Groups in the system (used for + group-based LE/TE identification via [`identify_wing_segments`](@ref)). """ function prime_polars_then_lock_unrefined_to_structure!( wing::VSMWing, - points::AbstractVector{Point} + points::AbstractVector{Point}; + groups::AbstractVector{Group}=Group[] ) - wing.wing_type == REFINE || return nothing - wing_points = [ p for p in points if p.type == WING && p.wing_idx == wing.idx ] - n_points = length(wing_points) - n_points % 2 == 0 || error( - "REFINE wing $(wing.idx) must have an even number of WING points, got $(n_points)" - ) - - n_struct_sections = n_points ÷ 2 - n_aero_sections = length(wing.vsm_wing.unrefined_sections) - - n_struct_sections == n_aero_sections && return nothing - wing.vsm_wing.use_prior_polar || error( - "REFINE wing $(wing.idx): structural sections ($(n_struct_sections)) " * - "do not match aerodynamic sections ($(n_aero_sections)). " * - "Set use_prior_polar=true to allow one-time polar seeding and lock to structural sections." - ) + wing_group_idxs = isempty(groups) ? nothing : + wing.group_idxs + grps = isempty(groups) ? nothing : groups + has_groups = !isnothing(grps) && + !isnothing(wing_group_idxs) && + !isempty(wing_group_idxs) + + if has_groups + n_struct_sections = length(wing_group_idxs) + # REFINE: each group is a 2-point strut (LE/TE) + if wing.wing_type == REFINE + for g_idx in wing_group_idxs + g = grps[g_idx] + length(g.point_idxs) == 2 || error( + "REFINE wing $(wing.idx): group " * + "$(g.name) must have exactly 2 " * + "points (LE/TE pair), got " * + "$(length(g.point_idxs))") + end + end + else + n_points = length(wing_points) + n_points % 2 == 0 || error( + "Wing $(wing.idx): no groups and odd " * + "number of WING points " * + "($(n_points)). Define groups to " * + "specify LE/TE pairs.") + n_struct_sections = n_points ÷ 2 + end - isempty(wing.vsm_wing.refined_sections) && error( - "REFINE wing $(wing.idx): cannot lock unrefined sections because no refined sections exist to reuse polars." - ) + n_aero_sections = + length(wing.vsm_wing.unrefined_sections) + counts_differ = n_struct_sections != n_aero_sections + + if counts_differ + wing.vsm_wing.use_prior_polar || error( + "Wing $(wing.idx): structural sections " * + "($(n_struct_sections)) do not match " * + "aerodynamic sections " * + "($(n_aero_sections)). Set " * + "use_prior_polar=true to allow one-time " * + "polar seeding and lock to structural " * + "sections." + ) + + isempty(wing.vsm_wing.refined_sections) && + error( + "Wing $(wing.idx): cannot lock " * + "unrefined sections because no " * + "refined sections exist to reuse " * + "polars." + ) + end - wing_segments = identify_wing_segments(wing_points) + wing_segments = identify_wing_segments( + wing_points; groups=grps, + wing_group_idxs=wing_group_idxs) + wing.wing_segments = wing_segments length(wing_segments) == n_struct_sections || error( - "REFINE wing $(wing.idx): failed to identify structural LE/TE pairs." + "Wing $(wing.idx): failed to identify " * + "structural LE/TE pairs." ) template_sections = wing.vsm_wing.unrefined_sections n_templates = length(template_sections) n_templates > 0 || error( - "REFINE wing $(wing.idx): aerodynamic geometry has zero unrefined sections." + "Wing $(wing.idx): aerodynamic geometry " * + "has zero unrefined sections." ) R_b_to_c = wing.R_b_to_c origin_cad = wing.pos_cad - new_sections = Vector{VortexStepMethod.Section}(undef, n_struct_sections) + new_sections = Vector{VortexStepMethod.Section}( + undef, n_struct_sections) for (i, (le_idx, te_idx)) in enumerate(wing_segments) - template_idx = n_struct_sections == 1 ? 1 : - round(Int, 1 + (i - 1) * (n_templates - 1) / (n_struct_sections - 1)) + template_idx = if counts_differ + n_struct_sections == 1 ? 1 : + round(Int, + 1 + (i - 1) * (n_templates - 1) / + (n_struct_sections - 1)) + else + i # 1:1 copy when counts match + end template = template_sections[template_idx] - le_body = R_b_to_c' * (points[le_idx].pos_cad - origin_cad) - te_body = R_b_to_c' * (points[te_idx].pos_cad - origin_cad) + le_body = R_b_to_c' * + (points[le_idx].pos_cad - origin_cad) + te_body = R_b_to_c' * + (points[te_idx].pos_cad - origin_cad) section = VortexStepMethod.Section() if isnothing(template.aero_data) VortexStepMethod.reinit!( - section, le_body, te_body, template.aero_model + section, le_body, te_body, + template.aero_model ) else VortexStepMethod.reinit!( - section, le_body, te_body, template.aero_model, template.aero_data + section, le_body, te_body, + template.aero_model, + template.aero_data ) end new_sections[i] = section end wing.vsm_wing.unrefined_sections = new_sections - wing.vsm_wing.n_unrefined_sections = Int16(n_struct_sections) + wing.vsm_wing.n_unrefined_sections = + Int16(n_struct_sections) - refine!(wing.vsm_wing; recompute_mapping=true, sort_sections=false) + refine!(wing.vsm_wing; + recompute_mapping=true, sort_sections=false) VortexStepMethod.reinit!(wing.vsm_aero) + + # Resize linearization vectors for non-REFINE wings + # when section count changed. + if counts_differ && wing.wing_type != REFINE + n_un = Int(n_struct_sections) + ny = 3 + n_un + 3 + nx = 3 + 3 + n_un + wing.vsm_y = zeros(SimFloat, ny) + wing.vsm_x = zeros(SimFloat, nx) + wing.vsm_jac = zeros(SimFloat, nx, ny) + end + return nothing end diff --git a/src/yaml_loader.jl b/src/yaml_loader.jl index f3e49ea8..cd76e0e1 100644 --- a/src/yaml_loader.jl +++ b/src/yaml_loader.jl @@ -1066,6 +1066,7 @@ function update_aero_yaml_from_struc_yaml!(source_struc_yaml::AbstractString, # Parse struc YAML to extract WING point positions and group LE/TE pairs struc_lines = readlines(struc_full_path) wing_pos_dict = Dict{String, Vector{Float64}}() # name => [x, y, z] + wing_names_ordered = String[] # preserve YAML order group_le_te = Vector{Tuple{String, String}}() # (le_name, te_name) current_section = :none @@ -1097,10 +1098,12 @@ function update_aero_yaml_from_struc_yaml!(source_struc_yaml::AbstractString, # Format: - [name, [x, y, z], TYPE, ...] m = match(r"^\s*-\s*\[(\w+)\s*,\s*\[([-+]?\d+\.?\d*(?:[eE][-+]?\d+)?)\s*,\s*([-+]?\d+\.?\d*(?:[eE][-+]?\d+)?)\s*,\s*([-+]?\d+\.?\d*(?:[eE][-+]?\d+)?)\s*\]\s*,\s*(\w+)", line) if m !== nothing && m.captures[5] == "WING" - wing_pos_dict[m.captures[1]] = [ + name = m.captures[1] + wing_pos_dict[name] = [ parse(Float64, m.captures[2]), parse(Float64, m.captures[3]), parse(Float64, m.captures[4])] + push!(wing_names_ordered, name) end elseif current_section == :groups # Format: - [name, [pt1, pt2, ...], ...] @@ -1114,10 +1117,26 @@ function update_aero_yaml_from_struc_yaml!(source_struc_yaml::AbstractString, end end - # Validate + # Fallback: consecutive-pair heuristic when no groups if isempty(group_le_te) - error("No groups with point_idxs found in $struc_full_path") + n_wp = length(wing_names_ordered) + n_wp % 2 == 0 || error( + "No groups in $struc_full_path and odd " * + "number of WING points ($n_wp). " * + "Define groups to specify LE/TE pairs.") + for i in 1:2:n_wp + a = wing_names_ordered[i] + b = wing_names_ordered[i + 1] + # LE has smaller x + if wing_pos_dict[a][1] < + wing_pos_dict[b][1] + push!(group_le_te, (a, b)) + else + push!(group_le_te, (b, a)) + end + end end + for (le, te) in group_le_te haskey(wing_pos_dict, le) || error( "Group LE point '$le' not found in WING points") diff --git a/test/test_prime_polars.jl b/test/test_prime_polars.jl new file mode 100644 index 00000000..11c465a7 --- /dev/null +++ b/test/test_prime_polars.jl @@ -0,0 +1,268 @@ +# Copyright (c) 2025 Bart van de Lint +# SPDX-License-Identifier: MPL-2.0 + +# test_prime_polars.jl +# Tests for prime_polars_then_lock_unrefined_to_structure!: +# verifies geometry, unrefined polar propagation, and +# refined polar interpolation for both REFINE and QUATERNION +# wing types. + +using Test +using SymbolicAWEModels +using SymbolicAWEModels: KVec3, VortexStepMethod, WING, + REFINE, QUATERNION, SimFloat, + prime_polars_then_lock_unrefined_to_structure! +using KiteUtils +using LinearAlgebra + +# ── helpers ────────────────────────────────────────────── +pkg_root = dirname(@__DIR__) +src_data = joinpath(pkg_root, "data", "2plate_kite") +tmpdir = mktempdir() +data_path = joinpath(tmpdir, "2plate_kite") +cp(src_data, data_path; force=true) +set_data_path(data_path) + +struc_yaml = joinpath(data_path, + "quat_struc_geometry.yaml") +refine_yaml = joinpath(data_path, + "refine_struc_geometry.yaml") +aero_yaml = joinpath(data_path, "aero_geometry.yaml") + +SymbolicAWEModels.update_aero_yaml_from_struc_yaml!( + struc_yaml, aero_yaml) + +set = Settings("system.yaml") +set.g_earth = 0.0 +vsm_set_path = joinpath(data_path, "vsm_settings.yaml") +vsm_set = VortexStepMethod.VSMSettings( + vsm_set_path; data_prefix=false) + +# ── mock polar helpers ─────────────────────────────────── +alpha_mock = collect(-5.0:1.0:5.0) # 11 points +n_alpha = length(alpha_mock) + +"""Create recognizable mock polar for section `i`: +cl=i, cd=10i, cm=100i (constant across alpha).""" +function mock_polar(i) + cl = fill(Float64(i), n_alpha) + cd = fill(Float64(10i), n_alpha) + cm = fill(Float64(100i), n_alpha) + return (copy(alpha_mock), cl, cd, cm) +end + +# ───────────────────────────────────────────────────────── +@testset "prime_polars — REFINE" begin + + @testset "geometry: LE/TE match structural points" begin + sys = SymbolicAWEModels.load_sys_struct_from_yaml( + refine_yaml; + system_name="refine_geom", set, vsm_set) + wing = sys.wings[1] + points = sys.points + vsm_w = wing.vsm_wing + + n_struct = count( + p -> p.type == WING && + p.wing_idx == wing.idx, + points) ÷ 2 + + # Add extra section to create mismatch + extra = deepcopy(vsm_w.unrefined_sections[1]) + push!(vsm_w.unrefined_sections, extra) + vsm_w.n_unrefined_sections = + Int16(length(vsm_w.unrefined_sections)) + @test vsm_w.n_unrefined_sections != n_struct + + vsm_w.use_prior_polar = true + wing.wing_segments = nothing + + prime_polars_then_lock_unrefined_to_structure!( + wing, points) + + @test vsm_w.n_unrefined_sections == n_struct + @test !isnothing(wing.wing_segments) + @test length(wing.wing_segments) == n_struct + + R = wing.R_b_to_c + origin = wing.pos_cad + for (i, (le_idx, te_idx)) in + enumerate(wing.wing_segments) + sec = vsm_w.unrefined_sections[i] + le_body = R' * (points[le_idx].pos_cad - + origin) + te_body = R' * (points[te_idx].pos_cad - + origin) + @test isapprox(Vector(sec.LE_point), + le_body; atol=1e-10) + @test isapprox(Vector(sec.TE_point), + te_body; atol=1e-10) + end + end + + # Shared setup for polar tests: 5 aero sections with + # mock polars, 3 structural sections, cleared refined + # aero_data so refine! freshly interpolates. + sys = SymbolicAWEModels.load_sys_struct_from_yaml( + refine_yaml; + system_name="refine_polar", set, vsm_set) + wing = sys.wings[1] + points = sys.points + vsm_w = wing.vsm_wing + + n_struct = count( + p -> p.type == WING && + p.wing_idx == wing.idx, + points) ÷ 2 + + # Add 2 extra sections: 5 aero vs 3 struct + for _ in 1:2 + push!(vsm_w.unrefined_sections, + deepcopy(vsm_w.unrefined_sections[1])) + end + n_templates = length(vsm_w.unrefined_sections) + vsm_w.n_unrefined_sections = Int16(n_templates) + + # Stamp recognizable mock polars on all 5 sections + for i in 1:n_templates + sec = vsm_w.unrefined_sections[i] + sec.aero_model = VortexStepMethod.POLAR_VECTORS + sec.aero_data = mock_polar(i) + end + + # Clear refined section aero_data so refine! freshly + # interpolates (makes _can_reuse_prior_refined_polar_data + # return false). + for sec in vsm_w.refined_sections + sec.aero_data = nothing + sec.aero_model = VortexStepMethod.POLAR_VECTORS + end + + vsm_w.use_prior_polar = true + wing.wing_segments = nothing + + prime_polars_then_lock_unrefined_to_structure!( + wing, points) + + @testset "polars correct on unrefined sections" begin + @test vsm_w.n_unrefined_sections == n_struct + + for i in 1:n_struct + sec = vsm_w.unrefined_sections[i] + @test sec.aero_model == + VortexStepMethod.POLAR_VECTORS + + # Same index mapping as vsm_refine.jl + tidx = n_struct == 1 ? 1 : + round(Int, 1 + (i - 1) * + (n_templates - 1) / + (n_struct - 1)) + expected = mock_polar(tidx) + + @test sec.aero_data[1] ≈ expected[1] + @test sec.aero_data[2] ≈ expected[2] + @test sec.aero_data[3] ≈ expected[3] + @test sec.aero_data[4] ≈ expected[4] + end + end + + @testset "polars correct on refined sections" begin + refined = vsm_w.refined_sections + n_panels = Int(vsm_w.n_panels) + @test length(refined) == n_panels + 1 + + # Unrefined cl values (constant per section) + unrefined_cls = [ + Float64( + vsm_w.unrefined_sections[i].aero_data[2][1] + ) + for i in 1:n_struct + ] + cl_lo = minimum(unrefined_cls) + cl_hi = maximum(unrefined_cls) + + for sec in refined + @test sec.aero_model == + VortexStepMethod.POLAR_VECTORS + @test !isnothing(sec.aero_data) + + # Every refined cl value should be a weighted + # interpolation of neighboring unrefined cls, + # so it must lie within [cl_lo, cl_hi]. + cl_val = sec.aero_data[2][1] + @test cl_lo - 1e-10 ≤ cl_val ≤ cl_hi + 1e-10 + end + end +end + +# ───────────────────────────────────────────────────────── +@testset "prime_polars — QUATERNION" begin + + @testset "geometry: LE/TE match structural points" begin + sys_q = SymbolicAWEModels.load_sys_struct_from_yaml( + struc_yaml; + system_name="quat_geom", set, vsm_set, + wing_type=QUATERNION) + wing = sys_q.wings[1] + points = sys_q.points + vsm_w = wing.vsm_wing + + # wing_segments populated by constructor + @test !isnothing(wing.wing_segments) + + n_struct = length(wing.group_idxs) + @test length(wing.wing_segments) == n_struct + @test vsm_w.n_unrefined_sections == n_struct + + # Verify LE/TE positions match + R = wing.R_b_to_c + origin = wing.pos_cad + for (i, (le_idx, te_idx)) in + enumerate(wing.wing_segments) + sec = vsm_w.unrefined_sections[i] + le_body = R' * (points[le_idx].pos_cad - + origin) + te_body = R' * (points[te_idx].pos_cad - + origin) + @test isapprox(Vector(sec.LE_point), + le_body; atol=1e-10) + @test isapprox(Vector(sec.TE_point), + te_body; atol=1e-10) + end + end + + @testset "vsm resize after count mismatch" begin + sys_q = SymbolicAWEModels.load_sys_struct_from_yaml( + struc_yaml; + system_name="quat_resize", set, vsm_set, + wing_type=QUATERNION) + wing = sys_q.wings[1] + points = sys_q.points + vsm_w = wing.vsm_wing + + n_struct = length(wing.group_idxs) + + # Add extra section to create mismatch + extra = deepcopy(vsm_w.unrefined_sections[1]) + push!(vsm_w.unrefined_sections, extra) + vsm_w.n_unrefined_sections = + Int16(length(vsm_w.unrefined_sections)) + @test vsm_w.n_unrefined_sections != n_struct + + vsm_w.use_prior_polar = true + wing.wing_segments = nothing + + prime_polars_then_lock_unrefined_to_structure!( + wing, points; + groups=collect(sys_q.groups)) + + @test vsm_w.n_unrefined_sections == n_struct + + # Verify linearization vectors resized + ny = 3 + n_struct + 3 + nx = 3 + 3 + n_struct + @test length(wing.vsm_y) == ny + @test length(wing.vsm_x) == nx + @test size(wing.vsm_jac) == (nx, ny) + end +end diff --git a/test/test_quaternion_auto_groups.jl b/test/test_quaternion_auto_groups.jl index 99650ac9..3d8a770e 100644 --- a/test/test_quaternion_auto_groups.jl +++ b/test/test_quaternion_auto_groups.jl @@ -3,6 +3,8 @@ # Test auto-creation of groups for QUATERNION wings using SymbolicAWEModels +using SymbolicAWEModels: VortexStepMethod, WING, + QUATERNION, REFINE using Test using LinearAlgebra @@ -16,85 +18,78 @@ using LinearAlgebra data_path = joinpath(tmpdir, "2plate_kite") cp(src_data_path, data_path; force=true) set_data_path(data_path) - set = Settings("system.yaml") - # Load with REFINE (should have 0 groups) - println("\n=== Testing REFINE wing (no auto-groups) ===") + struc_yaml = joinpath( + data_path, "quat_struc_geometry.yaml") refine_yaml = joinpath( - data_path, "refine_struc_geometry.yaml" - ) + data_path, "refine_struc_geometry.yaml") + aero_yaml = joinpath( + data_path, "aero_geometry.yaml") + + SymbolicAWEModels.update_aero_yaml_from_struc_yaml!( + struc_yaml, aero_yaml) + + set = Settings("system.yaml") vsm_set_path = joinpath( - data_path, "vsm_settings.yaml" - ) - vsm_set = SymbolicAWEModels.VortexStepMethod.VSMSettings( - vsm_set_path; data_prefix=false - ) + data_path, "vsm_settings.yaml") + vsm_set = VortexStepMethod.VSMSettings( + vsm_set_path; data_prefix=false) + + # ── REFINE: should have 0 groups ────────────── sys_refine = load_sys_struct_from_yaml( refine_yaml; - system_name="2plate_refine", set, vsm_set - ) + system_name="2plate_refine", set, vsm_set) @test length(sys_refine.wings) == 1 - @test sys_refine.wings[1].wing_type == SymbolicAWEModels.REFINE + @test sys_refine.wings[1].wing_type == REFINE @test length(sys_refine.groups) == 0 @test length(sys_refine.wings[1].group_idxs) == 0 - println("✓ REFINE wing: $(length(sys_refine.groups)) groups") - - # Now test manually creating a QUATERNION wing with WING points - println("\n=== Testing QUATERNION wing auto-group creation ===") - # Get WING points from REFINE system - wing_points = [p for p in sys_refine.points if p.type == SymbolicAWEModels.WING] - println("Found $(length(wing_points)) WING points") - @test length(wing_points) == 6 # 3 LE/TE pairs - - # Create a QUATERNION wing with these points - vsm_wing = SymbolicAWEModels.Wing( - set, vsm_set; prn=false - ) - vsm_aero = SymbolicAWEModels.BodyAerodynamics([vsm_wing]) - vsm_solver = SymbolicAWEModels.Solver(vsm_aero; - solver_type=SymbolicAWEModels.NONLIN, - atol=2e-8, rtol=2e-8) + # ── QUATERNION with YAML-defined groups ─────── + # quat_struc_geometry.yaml has 3 explicit groups + # and 7 WING points (6 LE/TE + kcu). + sys_quat = load_sys_struct_from_yaml( + struc_yaml; + system_name="2plate_quat", set, vsm_set, + wing_type=QUATERNION) - # Create wing with QUATERNION type and empty group_idxs - quat_wing = SymbolicAWEModels.VSMWing( - SymbolicAWEModels.BaseWing( - :main_wing, Int16[], I(3), - zeros(3), ones(3); - wing_type=SymbolicAWEModels.QUATERNION - ), - vsm_aero, vsm_wing, vsm_solver, - Float64[], Float64[], zeros(0, 0), - nothing, nothing, - nothing, nothing, nothing, nothing, - nothing, nothing, 0.0, 0.0 - ) + wing = sys_quat.wings[1] + @test wing.wing_type == QUATERNION + @test length(sys_quat.groups) == 3 + @test length(wing.group_idxs) == 3 + @test !isnothing(wing.wing_segments) + @test length(wing.wing_segments) == 3 - # Create SystemStructure (should auto-create groups) - # collect() converts NamedCollection to Vector - sys_quat = SymbolicAWEModels.SystemStructure( - "2plate_quat", set; - points=collect(sys_refine.points), - segments=collect(sys_refine.segments), - pulleys=collect(sys_refine.pulleys), - tethers=collect(sys_refine.tethers), - winches=collect(sys_refine.winches), - wings=[quat_wing], - transforms=collect(sys_refine.transforms) - ) + # Geometry was computed from closest VSM panel + for group in sys_quat.groups + @test !iszero(group.chord) + @test !iszero(group.y_airf) + end - # Verify groups were auto-created - @test length(sys_quat.groups) == 3 # One group per LE/TE pair - @test length(sys_quat.wings[1].group_idxs) == 3 - @test sys_quat.wings[1].wing_type == SymbolicAWEModels.QUATERNION + # ── QUATERNION auto-group creation ──────────── + # Load without explicit groups: auto-group should + # kick in for the 6 LE/TE WING points (kcu is + # excluded because it isn't in any group → the + # group-based path is unavailable and the fallback + # consecutive-pair heuristic uses only even-count + # subsets). + # Easiest approach: load REFINE YAML as QUATERNION + # (REFINE YAML has 6 WING points, no groups, no + # kcu WING point). + sys_auto = load_sys_struct_from_yaml( + refine_yaml; + system_name="2plate_auto", set, vsm_set, + wing_type=QUATERNION) - println("✓ QUATERNION wing: $(length(sys_quat.groups)) groups auto-created") + wing_auto = sys_auto.wings[1] + @test wing_auto.wing_type == QUATERNION + @test length(sys_auto.groups) == 3 + @test length(wing_auto.group_idxs) == 3 + @test !isnothing(wing_auto.wing_segments) + @test length(wing_auto.wing_segments) == 3 - # Check that geometry was computed from closest VSM panel - for (i, group) in enumerate(sys_quat.groups) - println(" Group $i: le_pos = $(group.le_pos), chord_norm = $(norm(group.chord)), points = $(group.point_idxs)") - @test !iszero(group.chord) # Chord should be computed from panel - @test !iszero(group.y_airf) # y_airf should be computed from panel + for group in sys_auto.groups + @test !iszero(group.chord) + @test !iszero(group.y_airf) end end From 340800b08101c28d8db6d5017729770b7cdaeed3 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 27 Feb 2026 12:16:21 +0100 Subject: [PATCH 4/7] No manifest in git --- Manifest-v1.12.toml | 2214 ------------------------------------------- 1 file changed, 2214 deletions(-) delete mode 100644 Manifest-v1.12.toml diff --git a/Manifest-v1.12.toml b/Manifest-v1.12.toml deleted file mode 100644 index 580a5693..00000000 --- a/Manifest-v1.12.toml +++ /dev/null @@ -1,2214 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -julia_version = "1.12.5" -manifest_format = "2.0" -project_hash = "9c15a3db3961b4c54c236d98049d4aa24d20cca9" - -[[deps.ADTypes]] -git-tree-sha1 = "f7304359109c768cf32dc5fa2d371565bb63b68a" -uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" -version = "1.21.0" -weakdeps = ["ChainRulesCore", "ConstructionBase", "EnzymeCore"] - - [deps.ADTypes.extensions] - ADTypesChainRulesCoreExt = "ChainRulesCore" - ADTypesConstructionBaseExt = "ConstructionBase" - ADTypesEnzymeCoreExt = "EnzymeCore" - -[[deps.AbstractFFTs]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" -uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" -version = "1.5.0" -weakdeps = ["ChainRulesCore", "Test"] - - [deps.AbstractFFTs.extensions] - AbstractFFTsChainRulesCoreExt = "ChainRulesCore" - AbstractFFTsTestExt = "Test" - -[[deps.AbstractPlutoDingetjes]] -deps = ["Pkg"] -git-tree-sha1 = "6e1d2a35f2f90a4bc7c2ed98079b2ba09c35b83a" -uuid = "6e696c72-6542-2067-7265-42206c756150" -version = "1.3.2" - -[[deps.AbstractTrees]] -git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177" -uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" -version = "0.4.5" - -[[deps.Accessors]] -deps = ["CompositionsBase", "ConstructionBase", "Dates", "InverseFunctions", "MacroTools"] -git-tree-sha1 = "856ecd7cebb68e5fc87abecd2326ad59f0f911f3" -uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" -version = "0.1.43" - - [deps.Accessors.extensions] - AxisKeysExt = "AxisKeys" - IntervalSetsExt = "IntervalSets" - LinearAlgebraExt = "LinearAlgebra" - StaticArraysExt = "StaticArrays" - StructArraysExt = "StructArrays" - TestExt = "Test" - UnitfulExt = "Unitful" - - [deps.Accessors.weakdeps] - AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5" - IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" - LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" - Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" - -[[deps.Adapt]] -deps = ["LinearAlgebra", "Requires"] -git-tree-sha1 = "7e35fca2bdfba44d797c53dfe63a51fabf39bfc0" -uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "4.4.0" -weakdeps = ["SparseArrays", "StaticArrays"] - - [deps.Adapt.extensions] - AdaptSparseArraysExt = "SparseArrays" - AdaptStaticArraysExt = "StaticArrays" - -[[deps.ArgTools]] -uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" -version = "1.1.2" - -[[deps.ArnoldiMethod]] -deps = ["LinearAlgebra", "Random", "StaticArrays"] -git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6" -uuid = "ec485272-7323-5ecc-a04f-4719b315124d" -version = "0.4.0" - -[[deps.ArrayInterface]] -deps = ["Adapt", "LinearAlgebra"] -git-tree-sha1 = "d81ae5489e13bc03567d4fbbb06c546a5e53c857" -uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "7.22.0" - - [deps.ArrayInterface.extensions] - ArrayInterfaceBandedMatricesExt = "BandedMatrices" - ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" - ArrayInterfaceCUDAExt = "CUDA" - ArrayInterfaceCUDSSExt = ["CUDSS", "CUDA"] - ArrayInterfaceChainRulesCoreExt = "ChainRulesCore" - ArrayInterfaceChainRulesExt = "ChainRules" - ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" - ArrayInterfaceMetalExt = "Metal" - ArrayInterfaceReverseDiffExt = "ReverseDiff" - ArrayInterfaceSparseArraysExt = "SparseArrays" - ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" - ArrayInterfaceTrackerExt = "Tracker" - - [deps.ArrayInterface.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" - CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" - CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" - ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" - Metal = "dde4c033-4e86-420c-a63e-0dd931031962" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - -[[deps.ArrayLayouts]] -deps = ["FillArrays", "LinearAlgebra", "StaticArrays"] -git-tree-sha1 = "e0b47732a192dd59b9d079a06d04235e2f833963" -uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "1.12.2" -weakdeps = ["SparseArrays"] - - [deps.ArrayLayouts.extensions] - ArrayLayoutsSparseArraysExt = "SparseArrays" - -[[deps.Arrow]] -deps = ["ArrowTypes", "BitIntegers", "CodecLz4", "CodecZstd", "ConcurrentUtilities", "DataAPI", "Dates", "EnumX", "Mmap", "PooledArrays", "SentinelArrays", "StringViews", "Tables", "TimeZones", "TranscodingStreams", "UUIDs"] -git-tree-sha1 = "4a69a3eadc1f7da78d950d1ef270c3a62c1f7e01" -uuid = "69666777-d1a9-59fb-9406-91d4454c9d45" -version = "2.8.1" - -[[deps.ArrowTypes]] -deps = ["Sockets", "UUIDs"] -git-tree-sha1 = "404265cd8128a2515a81d5eae16de90fdef05101" -uuid = "31f734f8-188a-4ce0-8406-c8a06bd891cd" -version = "2.3.0" - -[[deps.Artifacts]] -uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -version = "1.11.0" - -[[deps.AtmosphericModels]] -deps = ["FFTW", "HypergeometricFunctions", "KiteUtils", "LinearAlgebra", "MeshGrid", "NPZ", "Printf", "Random", "Statistics"] -git-tree-sha1 = "609912d6d1da0033add574d587c50ddf19665696" -uuid = "c59cac55-771d-4f45-b14d-1c681463a295" -version = "0.3.2" - -[[deps.AxisAlgorithms]] -deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"] -git-tree-sha1 = "01b8ccb13d68535d73d2b0c23e39bd23155fb712" -uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950" -version = "1.1.0" - -[[deps.Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" -version = "1.11.0" - -[[deps.Bijections]] -git-tree-sha1 = "a2d308fcd4c2fb90e943cf9cd2fbfa9c32b69733" -uuid = "e2ed5e7c-b2de-5872-ae92-c73ca462fb04" -version = "0.2.2" - -[[deps.BipartiteGraphs]] -deps = ["DataStructures", "DocStringExtensions", "Graphs", "PrecompileTools"] -git-tree-sha1 = "3b050c43d6156f7115f37cf206d3fa34d118c61b" -uuid = "caf10ac8-0290-4205-88aa-f15908547e8d" -version = "0.1.7" -weakdeps = ["SparseArrays"] - - [deps.BipartiteGraphs.extensions] - BipartiteGraphsSparseArraysExt = "SparseArrays" - -[[deps.BitIntegers]] -deps = ["Random"] -git-tree-sha1 = "091d591a060e43df1dd35faab3ca284925c48e46" -uuid = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1" -version = "0.3.7" - -[[deps.BitTwiddlingConvenienceFunctions]] -deps = ["Static"] -git-tree-sha1 = "f21cfd4950cb9f0587d5067e69405ad2acd27b87" -uuid = "62783981-4cbd-42fc-bca8-16325de8dc4b" -version = "0.1.6" - -[[deps.BlockArrays]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra"] -git-tree-sha1 = "0f606a9894e2bcda541ceb82a91a13c5d450ed97" -uuid = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" -version = "1.9.3" - - [deps.BlockArrays.extensions] - BlockArraysAdaptExt = "Adapt" - BlockArraysBandedMatricesExt = "BandedMatrices" - - [deps.BlockArrays.weakdeps] - Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - -[[deps.BracketingNonlinearSolve]] -deps = ["CommonSolve", "ConcreteStructs", "NonlinearSolveBase", "PrecompileTools", "Reexport", "SciMLBase"] -git-tree-sha1 = "fad1448f07155b299bfb925ebf22f5d553bdfb6e" -uuid = "70df07ce-3d50-431d-a3e7-ca6ddb60ac1e" -version = "1.10.0" -weakdeps = ["ChainRulesCore", "ForwardDiff"] - - [deps.BracketingNonlinearSolve.extensions] - BracketingNonlinearSolveChainRulesCoreExt = ["ChainRulesCore", "ForwardDiff"] - BracketingNonlinearSolveForwardDiffExt = "ForwardDiff" - -[[deps.CPUSummary]] -deps = ["CpuId", "IfElse", "PrecompileTools", "Preferences", "Static"] -git-tree-sha1 = "f3a21d7fc84ba618a779d1ed2fcca2e682865bab" -uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" -version = "0.2.7" - -[[deps.CSV]] -deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] -git-tree-sha1 = "8d8e0b0f350b8e1c91420b5e64e5de774c2f0f4d" -uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -version = "0.10.16" - -[[deps.ChainRulesCore]] -deps = ["Compat", "LinearAlgebra"] -git-tree-sha1 = "e4c6a16e77171a5f5e25e9646617ab1c276c5607" -uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "1.26.0" -weakdeps = ["SparseArrays"] - - [deps.ChainRulesCore.extensions] - ChainRulesCoreSparseArraysExt = "SparseArrays" - -[[deps.CloseOpenIntervals]] -deps = ["Static", "StaticArrayInterface"] -git-tree-sha1 = "05ba0d07cd4fd8b7a39541e31a7b0254704ea581" -uuid = "fb6a15b2-703c-40df-9091-08a04967cfa9" -version = "0.1.13" - -[[deps.CodecLz4]] -deps = ["Lz4_jll", "TranscodingStreams"] -git-tree-sha1 = "d58afcd2833601636b48ee8cbeb2edcb086522c2" -uuid = "5ba52731-8f18-5e0d-9241-30f10d1ec561" -version = "0.4.6" - -[[deps.CodecZlib]] -deps = ["TranscodingStreams", "Zlib_jll"] -git-tree-sha1 = "962834c22b66e32aa10f7611c08c8ca4e20749a9" -uuid = "944b1d66-785c-5afd-91f1-9de20f533193" -version = "0.7.8" - -[[deps.CodecZstd]] -deps = ["TranscodingStreams", "Zstd_jll"] -git-tree-sha1 = "da54a6cd93c54950c15adf1d336cfd7d71f51a56" -uuid = "6b39b394-51ab-5f42-8807-6242bab2b4c2" -version = "0.8.7" - -[[deps.ColorTypes]] -deps = ["FixedPointNumbers", "Random"] -git-tree-sha1 = "67e11ee83a43eb71ddc950302c53bf33f0690dfe" -uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" -version = "0.12.1" -weakdeps = ["StyledStrings"] - - [deps.ColorTypes.extensions] - StyledStringsExt = "StyledStrings" - -[[deps.Colors]] -deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] -git-tree-sha1 = "37ea44092930b1811e666c3bc38065d7d87fcc74" -uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" -version = "0.13.1" - -[[deps.Combinatorics]] -git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860" -uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" -version = "1.0.2" - -[[deps.CommonSolve]] -git-tree-sha1 = "78ea4ddbcf9c241827e7035c3a03e2e456711470" -uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" -version = "0.2.6" - -[[deps.CommonSubexpressions]] -deps = ["MacroTools"] -git-tree-sha1 = "cda2cfaebb4be89c9084adaca7dd7333369715c5" -uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" -version = "0.3.1" - -[[deps.CommonWorldInvalidations]] -git-tree-sha1 = "ae52d1c52048455e85a387fbee9be553ec2b68d0" -uuid = "f70d9fcc-98c5-4d4a-abd7-e4cdeebd8ca8" -version = "1.0.0" - -[[deps.Compat]] -deps = ["TOML", "UUIDs"] -git-tree-sha1 = "9d8a54ce4b17aa5bdce0ea5c34bc5e7c340d16ad" -uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.18.1" -weakdeps = ["Dates", "LinearAlgebra"] - - [deps.Compat.extensions] - CompatLinearAlgebraExt = "LinearAlgebra" - -[[deps.CompilerSupportLibraries_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.3.0+1" - -[[deps.CompositeTypes]] -git-tree-sha1 = "bce26c3dab336582805503bed209faab1c279768" -uuid = "b152e2b5-7a66-4b01-a709-34e65c35f657" -version = "0.1.4" - -[[deps.CompositionsBase]] -git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad" -uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b" -version = "0.1.2" -weakdeps = ["InverseFunctions"] - - [deps.CompositionsBase.extensions] - CompositionsBaseInverseFunctionsExt = "InverseFunctions" - -[[deps.ConcreteStructs]] -git-tree-sha1 = "f749037478283d372048690eb3b5f92a79432b34" -uuid = "2569d6c7-a4a2-43d3-a901-331e8e4be471" -version = "0.2.3" - -[[deps.ConcurrentUtilities]] -deps = ["Serialization", "Sockets"] -git-tree-sha1 = "21d088c496ea22914fe80906eb5bce65755e5ec8" -uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" -version = "2.5.1" - -[[deps.ConstructionBase]] -git-tree-sha1 = "b4b092499347b18a015186eae3042f72267106cb" -uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" -version = "1.6.0" -weakdeps = ["IntervalSets", "LinearAlgebra", "StaticArrays"] - - [deps.ConstructionBase.extensions] - ConstructionBaseIntervalSetsExt = "IntervalSets" - ConstructionBaseLinearAlgebraExt = "LinearAlgebra" - ConstructionBaseStaticArraysExt = "StaticArrays" - -[[deps.ControlSystemsBase]] -deps = ["ForwardDiff", "Hungarian", "LinearAlgebra", "MacroTools", "MatrixEquations", "MatrixPencils", "Polynomials", "PrecompileTools", "Printf", "Random", "RecipesBase", "StaticArraysCore", "UUIDs"] -git-tree-sha1 = "cfc01bc7e5a51764fede0c1bb493ebf5697c6f1f" -uuid = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e" -version = "1.20.2" - - [deps.ControlSystemsBase.extensions] - ControlSystemsBaseDSPExt = ["DSP"] - ControlSystemsBaseImplicitDifferentiationExt = ["ImplicitDifferentiation", "ComponentArrays"] - ControlSystemsBaseMakieExt = ["Makie"] - - [deps.ControlSystemsBase.weakdeps] - ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" - DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2" - ImplicitDifferentiation = "57b37032-215b-411a-8a7c-41a003a55207" - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - -[[deps.CpuId]] -deps = ["Markdown"] -git-tree-sha1 = "fcbb72b032692610bfbdb15018ac16a36cf2e406" -uuid = "adafc99b-e345-5852-983c-f28acb93d879" -version = "0.3.1" - -[[deps.Crayons]] -git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" -uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" -version = "4.1.1" - -[[deps.DataAPI]] -git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" -uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.16.0" - -[[deps.DataStructures]] -deps = ["OrderedCollections"] -git-tree-sha1 = "e357641bb3e0638d353c4b29ea0e40ea644066a6" -uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.19.3" - -[[deps.DataValueInterfaces]] -git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" -uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" -version = "1.0.0" - -[[deps.Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" -version = "1.11.0" - -[[deps.DefaultApplication]] -deps = ["InteractiveUtils"] -git-tree-sha1 = "c0dfa5a35710a193d83f03124356eef3386688fc" -uuid = "3f0dd361-4fe0-5fc6-8523-80b14ec94d85" -version = "1.1.0" - -[[deps.DelimitedFiles]] -deps = ["Mmap"] -git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae" -uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" -version = "1.9.1" - -[[deps.DiffEqBase]] -deps = ["ArrayInterface", "BracketingNonlinearSolve", "ConcreteStructs", "DocStringExtensions", "FastBroadcast", "FastClosures", "FastPower", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SciMLStructures", "Setfield", "Static", "StaticArraysCore", "SymbolicIndexingInterface", "TruncatedStacktraces"] -git-tree-sha1 = "450d2277df09cd48c65d7651a7c92759244ab299" -uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.205.1" - - [deps.DiffEqBase.extensions] - DiffEqBaseCUDAExt = "CUDA" - DiffEqBaseChainRulesCoreExt = "ChainRulesCore" - DiffEqBaseEnzymeExt = ["ChainRulesCore", "Enzyme"] - DiffEqBaseFlexUnitsExt = "FlexUnits" - DiffEqBaseForwardDiffExt = ["ForwardDiff"] - DiffEqBaseGTPSAExt = "GTPSA" - DiffEqBaseGeneralizedGeneratedExt = "GeneralizedGenerated" - DiffEqBaseMPIExt = "MPI" - DiffEqBaseMeasurementsExt = "Measurements" - DiffEqBaseMonteCarloMeasurementsExt = "MonteCarloMeasurements" - DiffEqBaseMooncakeExt = "Mooncake" - DiffEqBaseReverseDiffExt = "ReverseDiff" - DiffEqBaseSparseArraysExt = "SparseArrays" - DiffEqBaseTrackerExt = "Tracker" - DiffEqBaseUnitfulExt = "Unitful" - - [deps.DiffEqBase.weakdeps] - CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - FlexUnits = "76e01b6b-c995-4ce6-8559-91e72a3d4e95" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - GTPSA = "b27dd330-f138-47c5-815b-40db9dd9b6e8" - GeneralizedGenerated = "6b9d7cbe-bcb9-11e9-073f-15a7a543e2eb" - MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" - Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" - MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" - -[[deps.DiffEqCallbacks]] -deps = ["ConcreteStructs", "DataStructures", "DiffEqBase", "DifferentiationInterface", "LinearAlgebra", "Markdown", "PrecompileTools", "RecipesBase", "RecursiveArrayTools", "SciMLBase", "StaticArraysCore"] -git-tree-sha1 = "f17b863c2d5d496363fe36c8d8535cc6a33c9952" -uuid = "459566f4-90b8-5000-8ac3-15dfb0a30def" -version = "4.12.0" - - [deps.DiffEqCallbacks.extensions] - DiffEqCallbacksFunctorsExt = "Functors" - - [deps.DiffEqCallbacks.weakdeps] - Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196" - -[[deps.DiffResults]] -deps = ["StaticArraysCore"] -git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" -uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" -version = "1.1.0" - -[[deps.DiffRules]] -deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"] -git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272" -uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" -version = "1.15.1" - -[[deps.DifferentiationInterface]] -deps = ["ADTypes", "LinearAlgebra"] -git-tree-sha1 = "7ae99144ea44715402c6c882bfef2adbeadbc4ce" -uuid = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63" -version = "0.7.16" - - [deps.DifferentiationInterface.extensions] - DifferentiationInterfaceChainRulesCoreExt = "ChainRulesCore" - DifferentiationInterfaceDiffractorExt = "Diffractor" - DifferentiationInterfaceEnzymeExt = ["EnzymeCore", "Enzyme"] - DifferentiationInterfaceFastDifferentiationExt = "FastDifferentiation" - DifferentiationInterfaceFiniteDiffExt = "FiniteDiff" - DifferentiationInterfaceFiniteDifferencesExt = "FiniteDifferences" - DifferentiationInterfaceForwardDiffExt = ["ForwardDiff", "DiffResults"] - DifferentiationInterfaceGPUArraysCoreExt = "GPUArraysCore" - DifferentiationInterfaceGTPSAExt = "GTPSA" - DifferentiationInterfaceMooncakeExt = "Mooncake" - DifferentiationInterfacePolyesterForwardDiffExt = ["PolyesterForwardDiff", "ForwardDiff", "DiffResults"] - DifferentiationInterfaceReverseDiffExt = ["ReverseDiff", "DiffResults"] - DifferentiationInterfaceSparseArraysExt = "SparseArrays" - DifferentiationInterfaceSparseConnectivityTracerExt = "SparseConnectivityTracer" - DifferentiationInterfaceSparseMatrixColoringsExt = "SparseMatrixColorings" - DifferentiationInterfaceStaticArraysExt = "StaticArrays" - DifferentiationInterfaceSymbolicsExt = "Symbolics" - DifferentiationInterfaceTrackerExt = "Tracker" - DifferentiationInterfaceZygoteExt = ["Zygote", "ForwardDiff"] - - [deps.DifferentiationInterface.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - DiffResults = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" - Diffractor = "9f5e2b26-1114-432f-b630-d3fe2085c51c" - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" - FastDifferentiation = "eb9bf01b-bf85-4b60-bf87-ee5de06c00be" - FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41" - FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" - GTPSA = "b27dd330-f138-47c5-815b-40db9dd9b6e8" - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - SparseConnectivityTracer = "9f842d2f-2579-4b1d-911e-f412cf18a3f5" - SparseMatrixColorings = "0a514795-09f3-496d-8182-132a7b665d35" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.Distributed]] -deps = ["Random", "Serialization", "Sockets"] -uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" -version = "1.11.0" - -[[deps.DocStringExtensions]] -git-tree-sha1 = "7442a5dfe1ebb773c29cc2962a8980f47221d76c" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.9.5" - -[[deps.DomainSets]] -deps = ["CompositeTypes", "IntervalSets", "LinearAlgebra", "StaticArrays"] -git-tree-sha1 = "c249d86e97a7e8398ce2068dce4c078a1c3464de" -uuid = "5b8099bc-c8ec-5219-889f-1d9e522a28bf" -version = "0.7.16" - - [deps.DomainSets.extensions] - DomainSetsMakieExt = "Makie" - DomainSetsRandomExt = "Random" - - [deps.DomainSets.weakdeps] - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[deps.Downloads]] -deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] -uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -version = "1.7.0" - -[[deps.DynamicPolynomials]] -deps = ["Future", "LinearAlgebra", "MultivariatePolynomials", "MutableArithmetics", "Reexport", "Test"] -git-tree-sha1 = "3f50fa86c968fc1a9e006c07b6bc40ccbb1b704d" -uuid = "7c1d4256-1411-5781-91ec-d7bc3513ac07" -version = "0.6.4" - -[[deps.EnumX]] -git-tree-sha1 = "7bebc8aad6ee6217c78c5ddcf7ed289d65d0263e" -uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" -version = "1.0.6" - -[[deps.EnzymeCore]] -git-tree-sha1 = "990991b8aa76d17693a98e3a915ac7aa49f08d1a" -uuid = "f151be2c-9106-41f4-ab19-57ee4f262869" -version = "0.8.18" -weakdeps = ["Adapt", "ChainRulesCore"] - - [deps.EnzymeCore.extensions] - AdaptExt = "Adapt" - EnzymeCoreChainRulesCoreExt = "ChainRulesCore" - -[[deps.ExprTools]] -git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" -uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" -version = "0.1.10" - -[[deps.ExproniconLite]] -git-tree-sha1 = "c13f0b150373771b0fdc1713c97860f8df12e6c2" -uuid = "55351af7-c7e9-48d6-89ff-24e801d99491" -version = "0.10.14" - -[[deps.FFTW]] -deps = ["AbstractFFTs", "FFTW_jll", "Libdl", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"] -git-tree-sha1 = "97f08406df914023af55ade2f843c39e99c5d969" -uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" -version = "1.10.0" - -[[deps.FFTW_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "6d6219a004b8cf1e0b4dbe27a2860b8e04eba0be" -uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a" -version = "3.3.11+0" - -[[deps.FastBroadcast]] -deps = ["ArrayInterface", "LinearAlgebra", "Polyester", "Static", "StaticArrayInterface", "StrideArraysCore"] -git-tree-sha1 = "ab1b34570bcdf272899062e1a56285a53ecaae08" -uuid = "7034ab61-46d4-4ed7-9d0f-46aef9175898" -version = "0.3.5" - -[[deps.FastClosures]] -git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" -uuid = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a" -version = "0.3.2" - -[[deps.FastPower]] -git-tree-sha1 = "862831f78c7a48681a074ecc9aac09f2de563f71" -uuid = "a4df4552-cc26-4903-aec0-212e50a0e84b" -version = "1.3.1" - - [deps.FastPower.extensions] - FastPowerEnzymeExt = "Enzyme" - FastPowerForwardDiffExt = "ForwardDiff" - FastPowerMeasurementsExt = "Measurements" - FastPowerMonteCarloMeasurementsExt = "MonteCarloMeasurements" - FastPowerMooncakeExt = "Mooncake" - FastPowerReverseDiffExt = "ReverseDiff" - FastPowerTrackerExt = "Tracker" - - [deps.FastPower.weakdeps] - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" - MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - -[[deps.FileIO]] -deps = ["Pkg", "Requires", "UUIDs"] -git-tree-sha1 = "6522cfb3b8fe97bec632252263057996cbd3de20" -uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -version = "1.18.0" - - [deps.FileIO.extensions] - HTTPExt = "HTTP" - - [deps.FileIO.weakdeps] - HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" - -[[deps.FilePathsBase]] -deps = ["Compat", "Dates"] -git-tree-sha1 = "3bab2c5aa25e7840a4b065805c0cdfc01f3068d2" -uuid = "48062228-2e41-5def-b9a4-89aafe57970f" -version = "0.9.24" -weakdeps = ["Mmap", "Test"] - - [deps.FilePathsBase.extensions] - FilePathsBaseMmapExt = "Mmap" - FilePathsBaseTestExt = "Test" - -[[deps.FileWatching]] -uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" -version = "1.11.0" - -[[deps.FillArrays]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "2f979084d1e13948a3352cf64a25df6bd3b4dca3" -uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "1.16.0" - - [deps.FillArrays.extensions] - FillArraysPDMatsExt = "PDMats" - FillArraysSparseArraysExt = "SparseArrays" - FillArraysStaticArraysExt = "StaticArrays" - FillArraysStatisticsExt = "Statistics" - - [deps.FillArrays.weakdeps] - PDMats = "90014a1f-27ba-587c-ab20-58faa44d9150" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" - -[[deps.FindFirstFunctions]] -deps = ["PrecompileTools"] -git-tree-sha1 = "27b495de668ccea58de6b06d6d13181396598ea0" -uuid = "64ca27bc-2ba2-4a57-88aa-44e436879224" -version = "1.8.0" - -[[deps.FiniteDiff]] -deps = ["ArrayInterface", "LinearAlgebra", "Setfield"] -git-tree-sha1 = "9340ca07ca27093ff68418b7558ca37b05f8aeb1" -uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" -version = "2.29.0" - - [deps.FiniteDiff.extensions] - FiniteDiffBandedMatricesExt = "BandedMatrices" - FiniteDiffBlockBandedMatricesExt = "BlockBandedMatrices" - FiniteDiffSparseArraysExt = "SparseArrays" - FiniteDiffStaticArraysExt = "StaticArrays" - - [deps.FiniteDiff.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - -[[deps.FixedPointNumbers]] -deps = ["Statistics"] -git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" -uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" -version = "0.8.5" - -[[deps.ForwardDiff]] -deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] -git-tree-sha1 = "eef4c86803f47dcb61e9b8790ecaa96956fdd8ae" -uuid = "f6369f11-7733-5829-9624-2563aa707210" -version = "1.3.2" -weakdeps = ["StaticArrays"] - - [deps.ForwardDiff.extensions] - ForwardDiffStaticArraysExt = "StaticArrays" - -[[deps.FunctionWrappers]] -git-tree-sha1 = "d62485945ce5ae9c0c48f124a84998d755bae00e" -uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e" -version = "1.1.3" - -[[deps.FunctionWrappersWrappers]] -deps = ["FunctionWrappers"] -git-tree-sha1 = "b104d487b34566608f8b4e1c39fb0b10aa279ff8" -uuid = "77dc65aa-8811-40c2-897b-53d922fa7daf" -version = "0.1.3" - -[[deps.Future]] -deps = ["Random"] -uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" -version = "1.11.0" - -[[deps.GPUArraysCore]] -deps = ["Adapt"] -git-tree-sha1 = "83cf05ab16a73219e5f6bd1bdfa9848fa24ac627" -uuid = "46192b85-c4d5-4398-a991-12ede77f4527" -version = "0.2.0" - -[[deps.Graphs]] -deps = ["ArnoldiMethod", "DataStructures", "Inflate", "LinearAlgebra", "Random", "SimpleTraits", "SparseArrays", "Statistics"] -git-tree-sha1 = "031d63d09bd3e6e319df66bb466f5c3e8d147bee" -uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" -version = "1.13.4" -weakdeps = ["Distributed", "SharedArrays"] - - [deps.Graphs.extensions] - GraphsSharedArraysExt = "SharedArrays" - -[[deps.Hungarian]] -deps = ["LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "4f84db415ccb0ea750b10738bfecdd55388fd1b6" -uuid = "e91730f6-4275-51fb-a7a0-7064cfbd3b39" -version = "0.7.0" - -[[deps.HypergeometricFunctions]] -deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] -git-tree-sha1 = "68c173f4f449de5b438ee67ed0c9c748dc31a2ec" -uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" -version = "0.3.28" - -[[deps.IfElse]] -git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1" -uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" -version = "0.1.1" - -[[deps.ImplicitDiscreteSolve]] -deps = ["ConcreteStructs", "DiffEqBase", "NonlinearSolveBase", "NonlinearSolveFirstOrder", "OrdinaryDiffEqCore", "Reexport", "SciMLBase", "SymbolicIndexingInterface"] -git-tree-sha1 = "2a8b83132a262302305f359d3b50cba598f9785e" -uuid = "3263718b-31ed-49cf-8a0f-35a466e8af96" -version = "1.7.0" - -[[deps.Inflate]] -git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d" -uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" -version = "0.1.5" - -[[deps.InlineStrings]] -git-tree-sha1 = "8f3d257792a522b4601c24a577954b0a8cd7334d" -uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" -version = "1.4.5" -weakdeps = ["ArrowTypes", "Parsers"] - - [deps.InlineStrings.extensions] - ArrowTypesExt = "ArrowTypes" - ParsersExt = "Parsers" - -[[deps.IntegerMathUtils]] -git-tree-sha1 = "4c1acff2dc6b6967e7e750633c50bc3b8d83e617" -uuid = "18e54dd8-cb9d-406c-a71d-865a43cbb235" -version = "0.1.3" - -[[deps.IntelOpenMP_jll]] -deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"] -git-tree-sha1 = "ec1debd61c300961f98064cfb21287613ad7f303" -uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" -version = "2025.2.0+0" - -[[deps.InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -version = "1.11.0" - -[[deps.Interpolations]] -deps = ["Adapt", "AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"] -git-tree-sha1 = "65d505fa4c0d7072990d659ef3fc086eb6da8208" -uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" -version = "0.16.2" - - [deps.Interpolations.extensions] - InterpolationsForwardDiffExt = "ForwardDiff" - InterpolationsUnitfulExt = "Unitful" - - [deps.Interpolations.weakdeps] - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" - -[[deps.IntervalSets]] -git-tree-sha1 = "d966f85b3b7a8e49d034d27a189e9a4874b4391a" -uuid = "8197267c-284f-5f27-9208-e0e47529a953" -version = "0.7.13" -weakdeps = ["Random", "RecipesBase", "Statistics"] - - [deps.IntervalSets.extensions] - IntervalSetsRandomExt = "Random" - IntervalSetsRecipesBaseExt = "RecipesBase" - IntervalSetsStatisticsExt = "Statistics" - -[[deps.InverseFunctions]] -git-tree-sha1 = "a779299d77cd080bf77b97535acecd73e1c5e5cb" -uuid = "3587e190-3f89-42d0-90ee-14403ec27112" -version = "0.1.17" -weakdeps = ["Dates", "Test"] - - [deps.InverseFunctions.extensions] - InverseFunctionsDatesExt = "Dates" - InverseFunctionsTestExt = "Test" - -[[deps.IrrationalConstants]] -git-tree-sha1 = "b2d91fe939cae05960e760110b328288867b5758" -uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" -version = "0.2.6" - -[[deps.IteratorInterfaceExtensions]] -git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" -uuid = "82899510-4779-5014-852e-03e436cf321d" -version = "1.0.0" - -[[deps.JLLWrappers]] -deps = ["Artifacts", "Preferences"] -git-tree-sha1 = "0533e564aae234aff59ab625543145446d8b6ec2" -uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.7.1" - -[[deps.Jieko]] -deps = ["ExproniconLite"] -git-tree-sha1 = "2f05ed29618da60c06a87e9c033982d4f71d0b6c" -uuid = "ae98c720-c025-4a4a-838c-29b094483192" -version = "0.2.1" - -[[deps.JuliaSyntaxHighlighting]] -deps = ["StyledStrings"] -uuid = "ac6e5ff7-fb65-4e79-a425-ec3bc9c03011" -version = "1.12.0" - -[[deps.JumpProcesses]] -deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "DiffEqCallbacks", "DocStringExtensions", "FunctionWrappers", "Graphs", "LinearAlgebra", "PoissonRandom", "Random", "RecursiveArrayTools", "Reexport", "SciMLBase", "StaticArrays", "SymbolicIndexingInterface"] -git-tree-sha1 = "1032d39ce1ecccd880de042ba92b842e78b6ae39" -uuid = "ccbc3e58-028d-4f4c-8cd5-9ae44345cda5" -version = "9.22.0" - - [deps.JumpProcesses.extensions] - JumpProcessesKernelAbstractionsExt = ["Adapt", "KernelAbstractions"] - - [deps.JumpProcesses.weakdeps] - Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" - FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" - KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" - -[[deps.KiteUtils]] -deps = ["Arrow", "CSV", "DocStringExtensions", "LinearAlgebra", "OrderedCollections", "Parameters", "Parsers", "Pkg", "PrecompileTools", "RecursiveArrayTools", "ReferenceFrameRotations", "Rotations", "StaticArrays", "StructArrays", "StructTypes", "YAML"] -git-tree-sha1 = "949e79e875ffb9c2ab0ba60bda95130a04a3c590" -uuid = "90980105-b163-44e5-ba9f-8b1c83bb0533" -version = "0.11.2" - -[[deps.Krylov]] -deps = ["LinearAlgebra", "Printf", "SparseArrays"] -git-tree-sha1 = "125d65fe5042faf078383312dd060adf11d90802" -uuid = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7" -version = "0.10.5" - -[[deps.LaTeXStrings]] -git-tree-sha1 = "dda21b8cbd6a6c40d9d02a73230f9d70fed6918c" -uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" -version = "1.4.0" - -[[deps.LayoutPointers]] -deps = ["ArrayInterface", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface"] -git-tree-sha1 = "a9eaadb366f5493a5654e843864c13d8b107548c" -uuid = "10f19ff3-798f-405d-979b-55457f8fc047" -version = "0.1.17" - -[[deps.LazyArtifacts]] -deps = ["Artifacts", "Pkg"] -uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" -version = "1.11.0" - -[[deps.LibCURL]] -deps = ["LibCURL_jll", "MozillaCACerts_jll"] -uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.4" - -[[deps.LibCURL_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "OpenSSL_jll", "Zlib_jll", "nghttp2_jll"] -uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "8.15.0+0" - -[[deps.LibGit2]] -deps = ["LibGit2_jll", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" -version = "1.11.0" - -[[deps.LibGit2_jll]] -deps = ["Artifacts", "LibSSH2_jll", "Libdl", "OpenSSL_jll"] -uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.9.0+0" - -[[deps.LibSSH2_jll]] -deps = ["Artifacts", "Libdl", "OpenSSL_jll"] -uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.11.3+1" - -[[deps.Libdl]] -uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" -version = "1.11.0" - -[[deps.Libiconv_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "be484f5c92fad0bd8acfef35fe017900b0b73809" -uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" -version = "1.18.0+0" - -[[deps.LineSearch]] -deps = ["ADTypes", "CommonSolve", "ConcreteStructs", "FastClosures", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "SciMLBase", "SciMLJacobianOperators", "StaticArraysCore"] -git-tree-sha1 = "9f7253c0574b4b585c8909232adb890930da980a" -uuid = "87fe0de2-c867-4266-b59a-2f0a94fc965b" -version = "0.1.6" - - [deps.LineSearch.extensions] - LineSearchLineSearchesExt = "LineSearches" - - [deps.LineSearch.weakdeps] - LineSearches = "d3d80556-e9d4-5f37-9878-2ab0fcc64255" - -[[deps.LinearAlgebra]] -deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] -uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -version = "1.12.0" - -[[deps.LinearMaps]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "7f6be2e4cdaaf558623d93113d6ddade7b916209" -uuid = "7a12625a-238d-50fd-b39a-03d52299707e" -version = "3.11.4" -weakdeps = ["ChainRulesCore", "SparseArrays", "Statistics"] - - [deps.LinearMaps.extensions] - LinearMapsChainRulesCoreExt = "ChainRulesCore" - LinearMapsSparseArraysExt = "SparseArrays" - LinearMapsStatisticsExt = "Statistics" - -[[deps.LinearSolve]] -deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "GPUArraysCore", "InteractiveUtils", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "OpenBLAS_jll", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLLogging", "SciMLOperators", "Setfield", "StaticArraysCore"] -git-tree-sha1 = "f9e19cacc616da676db6fbb74827d3979ad6c0ae" -uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "3.59.1" - - [deps.LinearSolve.extensions] - LinearSolveAMDGPUExt = "AMDGPU" - LinearSolveBLISExt = ["blis_jll", "LAPACK_jll"] - LinearSolveBandedMatricesExt = "BandedMatrices" - LinearSolveBlockDiagonalsExt = "BlockDiagonals" - LinearSolveCUDAExt = "CUDA" - LinearSolveCUDSSExt = "CUDSS" - LinearSolveCUSOLVERRFExt = ["CUSOLVERRF", "SparseArrays"] - LinearSolveCliqueTreesExt = ["CliqueTrees", "SparseArrays"] - LinearSolveEnzymeExt = ["EnzymeCore", "SparseArrays"] - LinearSolveFastAlmostBandedMatricesExt = "FastAlmostBandedMatrices" - LinearSolveFastLapackInterfaceExt = "FastLapackInterface" - LinearSolveForwardDiffExt = "ForwardDiff" - LinearSolveHYPREExt = "HYPRE" - LinearSolveIterativeSolversExt = "IterativeSolvers" - LinearSolveKernelAbstractionsExt = "KernelAbstractions" - LinearSolveKrylovKitExt = "KrylovKit" - LinearSolveMetalExt = "Metal" - LinearSolveMooncakeExt = "Mooncake" - LinearSolvePETScExt = ["PETSc", "SparseArrays"] - LinearSolvePardisoExt = ["Pardiso", "SparseArrays"] - LinearSolveRecursiveFactorizationExt = "RecursiveFactorization" - LinearSolveSparseArraysExt = "SparseArrays" - LinearSolveSparspakExt = ["SparseArrays", "Sparspak"] - - [deps.LinearSolve.weakdeps] - AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - BlockDiagonals = "0a1fb500-61f7-11e9-3c65-f5ef3456f9f0" - CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" - CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" - CUSOLVERRF = "a8cc9031-bad2-4722-94f5-40deabb4245c" - CliqueTrees = "60701a23-6482-424a-84db-faee86b9b1f8" - EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" - FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" - FastLapackInterface = "29a986be-02c6-4525-aec4-84b980013641" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - HYPRE = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" - IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153" - KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" - KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" - LAPACK_jll = "51474c39-65e3-53ba-86ba-03b1b862ec14" - Metal = "dde4c033-4e86-420c-a63e-0dd931031962" - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - PETSc = "ace2c81b-2b5f-4b1e-a30d-d662738edfe0" - Pardiso = "46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" - RecursiveFactorization = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - Sparspak = "e56a9233-b9d6-4f03-8d0f-1825330902ac" - blis_jll = "6136c539-28a5-5bf0-87cc-b183200dce32" - -[[deps.LogExpFunctions]] -deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "13ca9e2586b89836fd20cccf56e57e2b9ae7f38f" -uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.29" - - [deps.LogExpFunctions.extensions] - LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" - LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" - LogExpFunctionsInverseFunctionsExt = "InverseFunctions" - - [deps.LogExpFunctions.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" - InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" - -[[deps.Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" -version = "1.11.0" - -[[deps.LoggingExtras]] -deps = ["Dates", "Logging"] -git-tree-sha1 = "f00544d95982ea270145636c181ceda21c4e2575" -uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" -version = "1.2.0" - -[[deps.Lz4_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "191686b1ac1ea9c89fc52e996ad15d1d241d1e33" -uuid = "5ced341a-0733-55b8-9ab6-a4889d929147" -version = "1.10.1+0" - -[[deps.MKL_jll]] -deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "oneTBB_jll"] -git-tree-sha1 = "282cadc186e7b2ae0eeadbd7a4dffed4196ae2aa" -uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" -version = "2025.2.0+0" - -[[deps.MacroTools]] -git-tree-sha1 = "1e0228a030642014fe5cfe68c2c0a818f9e3f522" -uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.16" - -[[deps.ManualMemory]] -git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd" -uuid = "d125e4d3-2237-4719-b19c-fa641b8a4667" -version = "0.1.8" - -[[deps.Markdown]] -deps = ["Base64", "JuliaSyntaxHighlighting", "StyledStrings"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" -version = "1.11.0" - -[[deps.MatrixEquations]] -deps = ["LinearAlgebra", "LinearMaps"] -git-tree-sha1 = "51f3fade0b4ff2cf90b36b3312425460631abb56" -uuid = "99c1a7ee-ab34-5fd5-8076-27c950a045f4" -version = "2.5.6" - -[[deps.MatrixPencils]] -deps = ["LinearAlgebra", "MatrixEquations", "Polynomials", "Random"] -git-tree-sha1 = "d852fb5efe6eea8f764d44a3e6a559664fa88e20" -uuid = "48965c70-4690-11ea-1f13-43a2532b2fa8" -version = "1.9.1" - -[[deps.MaybeInplace]] -deps = ["ArrayInterface", "LinearAlgebra", "MacroTools"] -git-tree-sha1 = "54e2fdc38130c05b42be423e90da3bade29b74bd" -uuid = "bb5d69b7-63fc-4a16-80bd-7e42200c7bdb" -version = "0.1.4" -weakdeps = ["SparseArrays"] - - [deps.MaybeInplace.extensions] - MaybeInplaceSparseArraysExt = "SparseArrays" - -[[deps.Measures]] -git-tree-sha1 = "b513cedd20d9c914783d8ad83d08120702bf2c77" -uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e" -version = "0.3.3" - -[[deps.MeshGrid]] -git-tree-sha1 = "0a7fe9ae5a02fe24e9f041d0200f6173606ce02a" -uuid = "ebf956a0-ef5e-43be-9fb1-27952996e635" -version = "1.0.4" - -[[deps.Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" -version = "1.11.0" - -[[deps.Mocking]] -deps = ["Compat", "ExprTools"] -git-tree-sha1 = "2c140d60d7cb82badf06d8783800d0bcd1a7daa2" -uuid = "78c3b35d-d492-501b-9361-3d52fe80e533" -version = "0.8.1" - -[[deps.ModelingToolkit]] -deps = ["ADTypes", "BipartiteGraphs", "BlockArrays", "Combinatorics", "CommonSolve", "DataStructures", "DiffEqBase", "DifferentiationInterface", "DocStringExtensions", "FillArrays", "FindFirstFunctions", "ForwardDiff", "Graphs", "InteractiveUtils", "Libdl", "LinearAlgebra", "ModelingToolkitBase", "ModelingToolkitTearing", "Moshi", "OffsetArrays", "OrderedCollections", "PreallocationTools", "PrecompileTools", "REPL", "Reexport", "RuntimeGeneratedFunctions", "SCCNonlinearSolve", "SciMLBase", "SciMLPublic", "Serialization", "Setfield", "SimpleNonlinearSolve", "SparseArrays", "StateSelection", "StaticArrays", "SymbolicCompilerPasses", "SymbolicIndexingInterface", "SymbolicUtils", "Symbolics", "UnPack"] -git-tree-sha1 = "63d2d581402890b9e67244efa221ebe46f43765f" -uuid = "961ee093-0014-501f-94e3-6117800e7a78" -version = "11.11.0" - - [deps.ModelingToolkit.extensions] - MTKFMIExt = "FMIImport" - - [deps.ModelingToolkit.weakdeps] - FMIImport = "9fcbc62e-52a0-44e9-a616-1359a0008194" - -[[deps.ModelingToolkitBase]] -deps = ["ADTypes", "AbstractTrees", "ArrayInterface", "BipartiteGraphs", "BlockArrays", "Combinatorics", "CommonSolve", "Compat", "ConstructionBase", "DataStructures", "DiffEqBase", "DiffEqCallbacks", "DiffRules", "DifferentiationInterface", "DocStringExtensions", "DomainSets", "EnumX", "ExprTools", "FillArrays", "FindFirstFunctions", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "Graphs", "ImplicitDiscreteSolve", "InteractiveUtils", "JumpProcesses", "Libdl", "LinearAlgebra", "Moshi", "NaNMath", "OffsetArrays", "OrderedCollections", "PreallocationTools", "PrecompileTools", "REPL", "Random", "ReadOnlyDicts", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLBase", "SciMLPublic", "SciMLStructures", "Serialization", "Setfield", "SimpleNonlinearSolve", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicIndexingInterface", "SymbolicUtils", "Symbolics", "UnPack"] -git-tree-sha1 = "0b71d8ff34b871ad93d0f96e338761e96e41cd82" -uuid = "7771a370-6774-4173-bd38-47e70ca0b839" -version = "1.14.0" - - [deps.ModelingToolkitBase.extensions] - MTKBifurcationKitExt = "BifurcationKit" - MTKCasADiDynamicOptExt = "CasADi" - MTKChainRulesCoreExt = "ChainRulesCore" - MTKDiffEqNoiseProcessExt = "DiffEqNoiseProcess" - MTKDynamicQuantitiesExt = "DynamicQuantities" - MTKInfiniteOptExt = "InfiniteOpt" - MTKJuliaFormatterExt = "JuliaFormatter" - MTKLabelledArraysExt = "LabelledArrays" - MTKLatexifyExt = "Latexify" - MTKPyomoDynamicOptExt = "Pyomo" - - [deps.ModelingToolkitBase.weakdeps] - BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665" - CasADi = "c49709b8-5c63-11e9-2fb2-69db5844192f" - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - DiffEqNoiseProcess = "77a26b50-5914-5dd7-bc55-306e6241c503" - DynamicQuantities = "06fc5a27-2a28-4c7c-a15d-362465fb6821" - InfiniteOpt = "20393b10-9daf-11e9-18c9-8db751c92c57" - JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" - LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800" - Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" - Pyomo = "0e8e1daf-01b5-4eba-a626-3897743a3816" - -[[deps.ModelingToolkitTearing]] -deps = ["BipartiteGraphs", "CommonSolve", "DocStringExtensions", "Graphs", "LinearAlgebra", "ModelingToolkitBase", "Moshi", "OffsetArrays", "OrderedCollections", "SciMLBase", "Setfield", "SparseArrays", "StateSelection", "SymbolicIndexingInterface", "SymbolicUtils", "Symbolics"] -git-tree-sha1 = "17f5e5ab38eba3fcfbe080e37b871a10987e3101" -uuid = "6bb917b9-1269-42b9-9f7c-b0dca72083ab" -version = "1.3.1" - -[[deps.Moshi]] -deps = ["ExproniconLite", "Jieko"] -git-tree-sha1 = "53f817d3e84537d84545e0ad749e483412dd6b2a" -uuid = "2e0e35c7-a2e4-4343-998d-7ef72827ed2d" -version = "0.3.7" - -[[deps.MozillaCACerts_jll]] -uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2025.11.4" - -[[deps.MuladdMacro]] -git-tree-sha1 = "cac9cc5499c25554cba55cd3c30543cff5ca4fab" -uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" -version = "0.2.4" - -[[deps.MultivariatePolynomials]] -deps = ["DataStructures", "LinearAlgebra", "MutableArithmetics"] -git-tree-sha1 = "d38b8653b1cdfac5a7da3b819c0a8d6024f9a18c" -uuid = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3" -version = "0.5.13" -weakdeps = ["ChainRulesCore"] - - [deps.MultivariatePolynomials.extensions] - MultivariatePolynomialsChainRulesCoreExt = "ChainRulesCore" - -[[deps.MutableArithmetics]] -deps = ["LinearAlgebra", "SparseArrays", "Test"] -git-tree-sha1 = "22df8573f8e7c593ac205455ca088989d0a2c7a0" -uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" -version = "1.6.7" - -[[deps.NPZ]] -deps = ["FileIO", "ZipFile"] -git-tree-sha1 = "60a8e272fe0c5079363b28b0953831e2dd7b7e6f" -uuid = "15e1cf62-19b3-5cfa-8e77-841668bca605" -version = "0.4.3" - -[[deps.NaNMath]] -deps = ["OpenLibm_jll"] -git-tree-sha1 = "9b8215b1ee9e78a293f99797cd31375471b2bcae" -uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" -version = "1.1.3" - -[[deps.NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" -version = "1.3.0" - -[[deps.NonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "BracketingNonlinearSolve", "CommonSolve", "ConcreteStructs", "DifferentiationInterface", "FastClosures", "FiniteDiff", "ForwardDiff", "LineSearch", "LinearAlgebra", "LinearSolve", "NonlinearSolveBase", "NonlinearSolveFirstOrder", "NonlinearSolveQuasiNewton", "NonlinearSolveSpectralMethods", "PrecompileTools", "Preferences", "Reexport", "SciMLBase", "SciMLLogging", "SimpleNonlinearSolve", "StaticArraysCore", "SymbolicIndexingInterface"] -git-tree-sha1 = "da41d5cd90c1118f5a8914392cf561263a1d09cb" -uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "4.15.0" - - [deps.NonlinearSolve.extensions] - NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt" - NonlinearSolveFixedPointAccelerationExt = "FixedPointAcceleration" - NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" - NonlinearSolveMINPACKExt = "MINPACK" - NonlinearSolveNLSolversExt = "NLSolvers" - NonlinearSolveNLsolveExt = ["NLsolve", "LineSearches"] - NonlinearSolvePETScExt = ["PETSc", "MPI", "SparseArrays"] - NonlinearSolveSIAMFANLEquationsExt = "SIAMFANLEquations" - NonlinearSolveSpeedMappingExt = "SpeedMapping" - NonlinearSolveSundialsExt = "Sundials" - - [deps.NonlinearSolve.weakdeps] - FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce" - FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176" - LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" - LineSearches = "d3d80556-e9d4-5f37-9878-2ab0fcc64255" - MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" - MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" - NLSolvers = "337daf1e-9722-11e9-073e-8b9effe078ba" - NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" - PETSc = "ace2c81b-2b5f-4b1e-a30d-d662738edfe0" - SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" - Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4" - -[[deps.NonlinearSolveBase]] -deps = ["ADTypes", "Adapt", "ArrayInterface", "CommonSolve", "Compat", "ConcreteStructs", "DifferentiationInterface", "EnzymeCore", "FastClosures", "LinearAlgebra", "LogExpFunctions", "Markdown", "MaybeInplace", "PreallocationTools", "Preferences", "Printf", "RecursiveArrayTools", "SciMLBase", "SciMLJacobianOperators", "SciMLLogging", "SciMLOperators", "SciMLStructures", "Setfield", "StaticArraysCore", "SymbolicIndexingInterface", "TimerOutputs"] -git-tree-sha1 = "079e3482b0b1c7c1804c48244771980de02e3c64" -uuid = "be0214bd-f91f-a760-ac4e-3421ce2b2da0" -version = "2.13.0" - - [deps.NonlinearSolveBase.extensions] - NonlinearSolveBaseBandedMatricesExt = "BandedMatrices" - NonlinearSolveBaseChainRulesCoreExt = "ChainRulesCore" - NonlinearSolveBaseEnzymeExt = ["ChainRulesCore", "Enzyme"] - NonlinearSolveBaseForwardDiffExt = "ForwardDiff" - NonlinearSolveBaseLineSearchExt = "LineSearch" - NonlinearSolveBaseLinearSolveExt = "LinearSolve" - NonlinearSolveBaseMooncakeExt = "Mooncake" - NonlinearSolveBaseReverseDiffExt = "ReverseDiff" - NonlinearSolveBaseSparseArraysExt = "SparseArrays" - NonlinearSolveBaseSparseMatrixColoringsExt = "SparseMatrixColorings" - NonlinearSolveBaseTrackerExt = "Tracker" - - [deps.NonlinearSolveBase.weakdeps] - BandedMatrices = "aae01518-5342-5314-be14-df237901396f" - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - LineSearch = "87fe0de2-c867-4266-b59a-2f0a94fc965b" - LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - SparseMatrixColorings = "0a514795-09f3-496d-8182-132a7b665d35" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - -[[deps.NonlinearSolveFirstOrder]] -deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConcreteStructs", "FiniteDiff", "ForwardDiff", "LineSearch", "LinearAlgebra", "LinearSolve", "MaybeInplace", "NonlinearSolveBase", "PrecompileTools", "Reexport", "SciMLBase", "SciMLJacobianOperators", "Setfield", "StaticArraysCore"] -git-tree-sha1 = "df31d105d8e7254447256a44606f2a7e98b61aba" -uuid = "5959db7a-ea39-4486-b5fe-2dd0bf03d60d" -version = "1.11.1" - -[[deps.NonlinearSolveQuasiNewton]] -deps = ["ArrayInterface", "CommonSolve", "ConcreteStructs", "LinearAlgebra", "LinearSolve", "MaybeInplace", "NonlinearSolveBase", "PrecompileTools", "Reexport", "SciMLBase", "SciMLOperators", "StaticArraysCore"] -git-tree-sha1 = "ade27e8e9566b6cec63ee62f6a6650a11cf9a2eb" -uuid = "9a2c21bd-3a47-402d-9113-8faf9a0ee114" -version = "1.12.0" -weakdeps = ["ForwardDiff"] - - [deps.NonlinearSolveQuasiNewton.extensions] - NonlinearSolveQuasiNewtonForwardDiffExt = "ForwardDiff" - -[[deps.NonlinearSolveSpectralMethods]] -deps = ["CommonSolve", "ConcreteStructs", "LineSearch", "MaybeInplace", "NonlinearSolveBase", "PrecompileTools", "Reexport", "SciMLBase"] -git-tree-sha1 = "eafd027b5cd768f19bb5de76c0e908a9065ddd36" -uuid = "26075421-4e9a-44e1-8bd1-420ed7ad02b2" -version = "1.6.0" -weakdeps = ["ForwardDiff"] - - [deps.NonlinearSolveSpectralMethods.extensions] - NonlinearSolveSpectralMethodsForwardDiffExt = "ForwardDiff" - -[[deps.OffsetArrays]] -git-tree-sha1 = "117432e406b5c023f665fa73dc26e79ec3630151" -uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.17.0" -weakdeps = ["Adapt"] - - [deps.OffsetArrays.extensions] - OffsetArraysAdaptExt = "Adapt" - -[[deps.OpenBLAS_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] -uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.29+0" - -[[deps.OpenLibm_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.7+0" - -[[deps.OpenSSL_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "3.5.4+0" - -[[deps.OpenSpecFun_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] -git-tree-sha1 = "1346c9208249809840c91b26703912dff463d335" -uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" -version = "0.5.6+0" - -[[deps.OrderedCollections]] -git-tree-sha1 = "05868e21324cede2207c6f0f466b4bfef6d5e7ee" -uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.8.1" - -[[deps.OrdinaryDiffEqBDF]] -deps = ["ADTypes", "ArrayInterface", "DiffEqBase", "FastBroadcast", "LinearAlgebra", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "OrdinaryDiffEqSDIRK", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "StaticArrays", "TruncatedStacktraces"] -git-tree-sha1 = "8ee2d193c90fd4963d7e0c5efd9d7af56832bb73" -uuid = "6ad6398a-0878-4a85-9266-38940aa047c8" -version = "1.17.0" - -[[deps.OrdinaryDiffEqCore]] -deps = ["ADTypes", "Accessors", "Adapt", "ArrayInterface", "ConcreteStructs", "DataStructures", "DiffEqBase", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "FastClosures", "FastPower", "FillArrays", "FunctionWrappersWrappers", "InteractiveUtils", "LinearAlgebra", "Logging", "MacroTools", "MuladdMacro", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLLogging", "SciMLOperators", "SciMLStructures", "Static", "StaticArrayInterface", "StaticArraysCore", "SymbolicIndexingInterface", "TruncatedStacktraces"] -git-tree-sha1 = "61ebd6dbcb288df48ab2dc0020d4a615cf335d5e" -uuid = "bbf590c4-e513-4bbe-9b18-05decba2e5d8" -version = "3.5.2" - - [deps.OrdinaryDiffEqCore.extensions] - OrdinaryDiffEqCoreMooncakeExt = "Mooncake" - OrdinaryDiffEqCoreSparseArraysExt = "SparseArrays" - - [deps.OrdinaryDiffEqCore.weakdeps] - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - -[[deps.OrdinaryDiffEqDifferentiation]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "ConstructionBase", "DiffEqBase", "DifferentiationInterface", "FastBroadcast", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "LinearAlgebra", "LinearSolve", "OrdinaryDiffEqCore", "SciMLBase", "SciMLOperators", "SparseMatrixColorings", "StaticArrayInterface", "StaticArrays"] -git-tree-sha1 = "752ab1cc4a89dc23db63a0e747c8ef47e79473f2" -uuid = "4302a76b-040a-498a-8c04-15b101fed76b" -version = "2.0.0" -weakdeps = ["SparseArrays"] - - [deps.OrdinaryDiffEqDifferentiation.extensions] - OrdinaryDiffEqDifferentiationSparseArraysExt = "SparseArrays" - -[[deps.OrdinaryDiffEqNonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "DiffEqBase", "FastBroadcast", "FastClosures", "ForwardDiff", "LinearAlgebra", "LinearSolve", "MuladdMacro", "NonlinearSolve", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "PreallocationTools", "RecursiveArrayTools", "SciMLBase", "SciMLOperators", "SciMLStructures", "SimpleNonlinearSolve", "SparseArrays", "StaticArrays"] -git-tree-sha1 = "c2a64b20ab8c6c3d0155b146b02dbc79182d5f09" -uuid = "127b3ac7-2247-4354-8eb6-78cf4e7c58e8" -version = "1.20.0" - -[[deps.OrdinaryDiffEqSDIRK]] -deps = ["ADTypes", "DiffEqBase", "FastBroadcast", "LinearAlgebra", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "RecursiveArrayTools", "Reexport", "SciMLBase", "TruncatedStacktraces"] -git-tree-sha1 = "0b766d820e3b948881f1f246899de9ef3d329224" -uuid = "2d112036-d095-4a1e-ab9a-08536f3ecdbf" -version = "1.12.0" - -[[deps.Parameters]] -deps = ["OrderedCollections", "UnPack"] -git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" -uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" -version = "0.12.3" - -[[deps.Parsers]] -deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "7d2f8f21da5db6a806faf7b9b292296da42b2810" -uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.8.3" - -[[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] -uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.12.1" -weakdeps = ["REPL"] - - [deps.Pkg.extensions] - REPLExt = "REPL" - -[[deps.PoissonRandom]] -deps = ["LogExpFunctions", "Random"] -git-tree-sha1 = "67afbcbe9e184d6729a92a022147ed4cf972ca7b" -uuid = "e409e4f3-bfea-5376-8464-e040bb5c01ab" -version = "0.4.7" - -[[deps.Polyester]] -deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"] -git-tree-sha1 = "16bbc30b5ebea91e9ce1671adc03de2832cff552" -uuid = "f517fe37-dbe3-4b94-8317-1923a5111588" -version = "0.7.19" - -[[deps.PolyesterWeave]] -deps = ["BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "Static", "ThreadingUtilities"] -git-tree-sha1 = "645bed98cd47f72f67316fd42fc47dee771aefcd" -uuid = "1d0040c9-8b98-4ee7-8388-3f51789ca0ad" -version = "0.2.2" - -[[deps.Polynomials]] -deps = ["LinearAlgebra", "OrderedCollections", "RecipesBase", "Requires", "Setfield", "SparseArrays"] -git-tree-sha1 = "972089912ba299fba87671b025cd0da74f5f54f7" -uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" -version = "4.1.0" - - [deps.Polynomials.extensions] - PolynomialsChainRulesCoreExt = "ChainRulesCore" - PolynomialsFFTWExt = "FFTW" - PolynomialsMakieExt = "Makie" - PolynomialsMutableArithmeticsExt = "MutableArithmetics" - - [deps.Polynomials.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" - -[[deps.PooledArrays]] -deps = ["DataAPI", "Future"] -git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" -uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" -version = "1.4.3" - -[[deps.PreallocationTools]] -deps = ["Adapt", "ArrayInterface", "PrecompileTools"] -git-tree-sha1 = "dc8d6bde5005a0eac05ae8faf1eceaaca166cfa4" -uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" -version = "1.1.2" - - [deps.PreallocationTools.extensions] - PreallocationToolsForwardDiffExt = "ForwardDiff" - PreallocationToolsReverseDiffExt = "ReverseDiff" - PreallocationToolsSparseConnectivityTracerExt = "SparseConnectivityTracer" - - [deps.PreallocationTools.weakdeps] - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - SparseConnectivityTracer = "9f842d2f-2579-4b1d-911e-f412cf18a3f5" - -[[deps.PrecompileTools]] -deps = ["Preferences"] -git-tree-sha1 = "07a921781cab75691315adc645096ed5e370cb77" -uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.3.3" - -[[deps.Preferences]] -deps = ["TOML"] -git-tree-sha1 = "522f093a29b31a93e34eaea17ba055d850edea28" -uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.5.1" - -[[deps.Primes]] -deps = ["IntegerMathUtils"] -git-tree-sha1 = "25cdd1d20cd005b52fc12cb6be3f75faaf59bb9b" -uuid = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" -version = "0.5.7" - -[[deps.Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" -version = "1.11.0" - -[[deps.Quaternions]] -deps = ["LinearAlgebra", "Random", "RealDot"] -git-tree-sha1 = "4d8c1b7c3329c1885b857abb50d08fa3f4d9e3c8" -uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" -version = "0.7.7" - -[[deps.REPL]] -deps = ["InteractiveUtils", "JuliaSyntaxHighlighting", "Markdown", "Sockets", "StyledStrings", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" -version = "1.11.0" - -[[deps.Random]] -deps = ["SHA"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -version = "1.11.0" - -[[deps.Ratios]] -deps = ["Requires"] -git-tree-sha1 = "1342a47bf3260ee108163042310d26f2be5ec90b" -uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" -version = "0.4.5" -weakdeps = ["FixedPointNumbers"] - - [deps.Ratios.extensions] - RatiosFixedPointNumbersExt = "FixedPointNumbers" - -[[deps.ReadOnlyArrays]] -git-tree-sha1 = "e6f7ddf48cf141cb312b078ca21cb2d29d0dc11d" -uuid = "988b38a3-91fc-5605-94a2-ee2116b3bd83" -version = "0.2.0" - -[[deps.ReadOnlyDicts]] -deps = ["DocStringExtensions"] -git-tree-sha1 = "711acef70140078d808be9cd33040f510af57f5e" -uuid = "795d4caa-f5a7-4580-b5d8-c01d53451803" -version = "1.0.1" - -[[deps.RealDot]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9" -uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" -version = "0.1.0" - -[[deps.RecipesBase]] -deps = ["PrecompileTools"] -git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" -uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" -version = "1.3.4" - -[[deps.RecursiveArrayTools]] -deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "LinearAlgebra", "PrecompileTools", "RecipesBase", "StaticArraysCore", "SymbolicIndexingInterface"] -git-tree-sha1 = "18d2a6fd1ea9a8205cadb3a5704f8e51abdd748b" -uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "3.48.0" - - [deps.RecursiveArrayTools.extensions] - RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" - RecursiveArrayToolsForwardDiffExt = "ForwardDiff" - RecursiveArrayToolsKernelAbstractionsExt = "KernelAbstractions" - RecursiveArrayToolsMeasurementsExt = "Measurements" - RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" - RecursiveArrayToolsReverseDiffExt = ["ReverseDiff", "Zygote"] - RecursiveArrayToolsSparseArraysExt = ["SparseArrays"] - RecursiveArrayToolsStatisticsExt = "Statistics" - RecursiveArrayToolsStructArraysExt = "StructArrays" - RecursiveArrayToolsTablesExt = ["Tables"] - RecursiveArrayToolsTrackerExt = "Tracker" - RecursiveArrayToolsZygoteExt = "Zygote" - - [deps.RecursiveArrayTools.weakdeps] - FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" - Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" - MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" - StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" - Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.Reexport]] -git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" -uuid = "189a3867-3050-52da-a836-e630ba90ab69" -version = "1.2.2" - -[[deps.ReferenceFrameRotations]] -deps = ["Crayons", "LinearAlgebra", "Printf", "Random", "StaticArrays"] -git-tree-sha1 = "bbeaa5c8b63c066a134f2cad8cca1b8527cce9b5" -uuid = "74f56ac7-18b3-5285-802d-d4bd4f104033" -version = "3.1.2" - - [deps.ReferenceFrameRotations.extensions] - ReferenceFrameRotationsZygoteExt = ["ForwardDiff", "Zygote"] - - [deps.ReferenceFrameRotations.weakdeps] - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.Requires]] -deps = ["UUIDs"] -git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64" -uuid = "ae029012-a4dd-5104-9daa-d747884805df" -version = "1.3.1" - -[[deps.Rotations]] -deps = ["LinearAlgebra", "Quaternions", "Random", "StaticArrays"] -git-tree-sha1 = "5680a9276685d392c87407df00d57c9924d9f11e" -uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc" -version = "1.7.1" -weakdeps = ["RecipesBase"] - - [deps.Rotations.extensions] - RotationsRecipesBaseExt = "RecipesBase" - -[[deps.RuntimeGeneratedFunctions]] -deps = ["ExprTools", "SHA", "Serialization"] -git-tree-sha1 = "7257165d5477fd1025f7cb656019dcb6b0512c38" -uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47" -version = "0.5.17" - -[[deps.SCCNonlinearSolve]] -deps = ["CommonSolve", "PrecompileTools", "Reexport", "SciMLBase", "SymbolicIndexingInterface"] -git-tree-sha1 = "b1fed39f2acdd4524c17b50ce6f4406be61b936d" -uuid = "9dfe8606-65a1-4bb3-9748-cb89d1561431" -version = "1.11.0" -weakdeps = ["ChainRulesCore"] - - [deps.SCCNonlinearSolve.extensions] - SCCNonlinearSolveChainRulesCoreExt = "ChainRulesCore" - -[[deps.SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" -version = "0.7.0" - -[[deps.SIMDTypes]] -git-tree-sha1 = "330289636fb8107c5f32088d2741e9fd7a061a5c" -uuid = "94e857df-77ce-4151-89e5-788b33177be4" -version = "0.1.0" - -[[deps.SciMLBase]] -deps = ["ADTypes", "Accessors", "Adapt", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "Moshi", "PreallocationTools", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLLogging", "SciMLOperators", "SciMLPublic", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface"] -git-tree-sha1 = "cfbb2b828940381def7e1ad6e45e402ebe6a2ebb" -uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "2.140.0" - - [deps.SciMLBase.extensions] - SciMLBaseChainRulesCoreExt = "ChainRulesCore" - SciMLBaseDifferentiationInterfaceExt = "DifferentiationInterface" - SciMLBaseDistributionsExt = "Distributions" - SciMLBaseEnzymeExt = "Enzyme" - SciMLBaseForwardDiffExt = "ForwardDiff" - SciMLBaseMLStyleExt = "MLStyle" - SciMLBaseMakieExt = "Makie" - SciMLBaseMeasurementsExt = "Measurements" - SciMLBaseMonteCarloMeasurementsExt = "MonteCarloMeasurements" - SciMLBaseMooncakeExt = "Mooncake" - SciMLBasePartialFunctionsExt = "PartialFunctions" - SciMLBasePyCallExt = "PyCall" - SciMLBasePythonCallExt = "PythonCall" - SciMLBaseRCallExt = "RCall" - SciMLBaseReverseDiffExt = "ReverseDiff" - SciMLBaseTrackerExt = "Tracker" - SciMLBaseZygoteExt = ["Zygote", "ChainRulesCore"] - - [deps.SciMLBase.weakdeps] - ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63" - Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" - Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078" - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" - MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" - Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" - PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b" - PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" - PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" - RCall = "6f49c342-dc21-5d91-9882-a32aef131414" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" - -[[deps.SciMLJacobianOperators]] -deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "ConstructionBase", "DifferentiationInterface", "FastClosures", "LinearAlgebra", "SciMLBase", "SciMLOperators"] -git-tree-sha1 = "e96d5e96debf7f80a50d0b976a13dea556ccfd3a" -uuid = "19f34311-ddf3-4b8b-af20-060888a46c0e" -version = "0.1.12" - -[[deps.SciMLLogging]] -deps = ["Logging", "LoggingExtras", "Preferences"] -git-tree-sha1 = "0161be062570af4042cf6f69e3d5d0b0555b6927" -uuid = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" -version = "1.9.1" - - [deps.SciMLLogging.extensions] - SciMLLoggingTracyExt = "Tracy" - - [deps.SciMLLogging.weakdeps] - Tracy = "e689c965-62c8-4b79-b2c5-8359227902fd" - -[[deps.SciMLOperators]] -deps = ["Accessors", "ArrayInterface", "DocStringExtensions", "LinearAlgebra"] -git-tree-sha1 = "794c760e6aafe9f40dcd7dd30526ea33f0adc8b7" -uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" -version = "1.15.1" -weakdeps = ["SparseArrays", "StaticArraysCore"] - - [deps.SciMLOperators.extensions] - SciMLOperatorsSparseArraysExt = "SparseArrays" - SciMLOperatorsStaticArraysCoreExt = "StaticArraysCore" - -[[deps.SciMLPublic]] -git-tree-sha1 = "0ba076dbdce87ba230fff48ca9bca62e1f345c9b" -uuid = "431bcebd-1456-4ced-9d72-93c2757fff0b" -version = "1.0.1" - -[[deps.SciMLStructures]] -deps = ["ArrayInterface", "PrecompileTools"] -git-tree-sha1 = "607f6867d0b0553e98fc7f725c9f9f13b4d01a32" -uuid = "53ae85a6-f571-4167-b2af-e1d143709226" -version = "1.10.0" - -[[deps.Scratch]] -deps = ["Dates"] -git-tree-sha1 = "9b81b8393e50b7d4e6d0a9f14e192294d3b7c109" -uuid = "6c6a2e73-6563-6170-7368-637461726353" -version = "1.3.0" - -[[deps.SentinelArrays]] -deps = ["Dates", "Random"] -git-tree-sha1 = "ebe7e59b37c400f694f52b58c93d26201387da70" -uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" -version = "1.4.9" - -[[deps.Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" -version = "1.11.0" - -[[deps.Setfield]] -deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"] -git-tree-sha1 = "c5391c6ace3bc430ca630251d02ea9687169ca68" -uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46" -version = "1.1.2" - -[[deps.SharedArrays]] -deps = ["Distributed", "Mmap", "Random", "Serialization"] -uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" -version = "1.11.0" - -[[deps.SimpleNonlinearSolve]] -deps = ["ADTypes", "ArrayInterface", "BracketingNonlinearSolve", "CommonSolve", "ConcreteStructs", "DifferentiationInterface", "FastClosures", "FiniteDiff", "ForwardDiff", "LineSearch", "LinearAlgebra", "MaybeInplace", "NonlinearSolveBase", "PrecompileTools", "Reexport", "SciMLBase", "Setfield", "StaticArraysCore"] -git-tree-sha1 = "744c3f0fb186ad28376199c1e72ca39d0c614b5d" -uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" -version = "2.11.0" - - [deps.SimpleNonlinearSolve.extensions] - SimpleNonlinearSolveChainRulesCoreExt = "ChainRulesCore" - SimpleNonlinearSolveReverseDiffExt = "ReverseDiff" - SimpleNonlinearSolveTrackerExt = "Tracker" - - [deps.SimpleNonlinearSolve.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - -[[deps.SimpleTraits]] -deps = ["InteractiveUtils", "MacroTools"] -git-tree-sha1 = "be8eeac05ec97d379347584fa9fe2f5f76795bcb" -uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" -version = "0.9.5" - -[[deps.Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" -version = "1.11.0" - -[[deps.SparseArrays]] -deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] -uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -version = "1.12.0" - -[[deps.SparseMatrixColorings]] -deps = ["ADTypes", "DocStringExtensions", "LinearAlgebra", "PrecompileTools", "Random", "SparseArrays"] -git-tree-sha1 = "6ed48d9a3b22417c765dc273ae3e1e4de035e7c8" -uuid = "0a514795-09f3-496d-8182-132a7b665d35" -version = "0.4.23" - - [deps.SparseMatrixColorings.extensions] - SparseMatrixColoringsCUDAExt = "CUDA" - SparseMatrixColoringsCliqueTreesExt = "CliqueTrees" - SparseMatrixColoringsColorsExt = "Colors" - SparseMatrixColoringsJuMPExt = ["JuMP", "MathOptInterface"] - - [deps.SparseMatrixColorings.weakdeps] - CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" - CliqueTrees = "60701a23-6482-424a-84db-faee86b9b1f8" - Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" - JuMP = "4076af6c-e467-56ae-b986-b466b2749572" - MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" - -[[deps.SpecialFunctions]] -deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "5acc6a41b3082920f79ca3c759acbcecf18a8d78" -uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.7.1" -weakdeps = ["ChainRulesCore"] - - [deps.SpecialFunctions.extensions] - SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" - -[[deps.StateSelection]] -deps = ["BipartiteGraphs", "DocStringExtensions", "FindFirstFunctions", "Graphs", "LinearAlgebra", "OrderedCollections", "Setfield", "SparseArrays"] -git-tree-sha1 = "2482a0ee31419c63be997d8added773d412c42d2" -uuid = "64909d44-ed92-46a8-bbd9-f047dfbdc84b" -version = "1.3.0" - - [deps.StateSelection.extensions] - StateSelectionDeepDiffsExt = "DeepDiffs" - - [deps.StateSelection.weakdeps] - DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6" - -[[deps.Static]] -deps = ["CommonWorldInvalidations", "IfElse", "PrecompileTools", "SciMLPublic"] -git-tree-sha1 = "49440414711eddc7227724ae6e570c7d5559a086" -uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" -version = "1.3.1" - -[[deps.StaticArrayInterface]] -deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "PrecompileTools", "SciMLPublic", "Static"] -git-tree-sha1 = "aa1ea41b3d45ac449d10477f65e2b40e3197a0d2" -uuid = "0d7ed370-da01-4f52-bd93-41d350b8b718" -version = "1.9.0" -weakdeps = ["OffsetArrays", "StaticArrays"] - - [deps.StaticArrayInterface.extensions] - StaticArrayInterfaceOffsetArraysExt = "OffsetArrays" - StaticArrayInterfaceStaticArraysExt = "StaticArrays" - -[[deps.StaticArrays]] -deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] -git-tree-sha1 = "0f529006004a8be48f1be25f3451186579392d47" -uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.9.17" -weakdeps = ["ChainRulesCore", "Statistics"] - - [deps.StaticArrays.extensions] - StaticArraysChainRulesCoreExt = "ChainRulesCore" - StaticArraysStatisticsExt = "Statistics" - -[[deps.StaticArraysCore]] -git-tree-sha1 = "6ab403037779dae8c514bad259f32a447262455a" -uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" -version = "1.4.4" - -[[deps.Statistics]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -version = "1.11.1" -weakdeps = ["SparseArrays"] - - [deps.Statistics.extensions] - SparseArraysExt = ["SparseArrays"] - -[[deps.SteadyStateDiffEq]] -deps = ["ConcreteStructs", "DiffEqBase", "DiffEqCallbacks", "LinearAlgebra", "NonlinearSolveBase", "Reexport", "SciMLBase"] -git-tree-sha1 = "7b32737ebda77355ee61cfa9e59d376de3604629" -uuid = "9672c7b4-1e72-59bd-8a11-6ac3964bc41f" -version = "2.9.0" - -[[deps.StrideArraysCore]] -deps = ["ArrayInterface", "CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface", "ThreadingUtilities"] -git-tree-sha1 = "83151ba8065a73f53ca2ae98bc7274d817aa30f2" -uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da" -version = "0.5.8" - -[[deps.StringEncodings]] -deps = ["Libiconv_jll"] -git-tree-sha1 = "b765e46ba27ecf6b44faf70df40c57aa3a547dcb" -uuid = "69024149-9ee7-55f6-a4c4-859efe599b68" -version = "0.3.7" - -[[deps.StringViews]] -git-tree-sha1 = "f2dcb92855b31ad92fe8f079d4f75ac57c93e4b8" -uuid = "354b36f9-a18e-4713-926e-db85100087ba" -version = "1.3.7" - -[[deps.StructArrays]] -deps = ["ConstructionBase", "DataAPI", "Tables"] -git-tree-sha1 = "a2c37d815bf00575332b7bd0389f771cb7987214" -uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" -version = "0.7.2" - - [deps.StructArrays.extensions] - StructArraysAdaptExt = "Adapt" - StructArraysGPUArraysCoreExt = ["GPUArraysCore", "KernelAbstractions"] - StructArraysLinearAlgebraExt = "LinearAlgebra" - StructArraysSparseArraysExt = "SparseArrays" - StructArraysStaticArraysExt = "StaticArrays" - - [deps.StructArrays.weakdeps] - Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" - GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" - KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" - LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" - SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" - StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" - -[[deps.StructMapping]] -git-tree-sha1 = "42f7869cc68f9a83e33ce6a3e408c774900a37e3" -uuid = "7c3b921d-20d6-4eba-ad57-605525e86ab2" -version = "0.2.3" - -[[deps.StructTypes]] -deps = ["Dates", "UUIDs"] -git-tree-sha1 = "159331b30e94d7b11379037feeb9b690950cace8" -uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" -version = "1.11.0" - -[[deps.StyledStrings]] -uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" -version = "1.11.0" - -[[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] -uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "7.8.3+2" - -[[deps.Suppressor]] -deps = ["Logging"] -git-tree-sha1 = "6dbb5b635c5437c68c28c2ac9e39b87138f37c0a" -uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb" -version = "0.2.8" - -[[deps.SymbolicAWEModels]] -deps = ["AtmosphericModels", "CodecZlib", "ControlSystemsBase", "Dates", "DocStringExtensions", "KiteUtils", "LaTeXStrings", "LinearAlgebra", "Logging", "ModelingToolkit", "NonlinearSolve", "OrdinaryDiffEqBDF", "OrdinaryDiffEqCore", "OrdinaryDiffEqNonlinearSolve", "Parameters", "Pkg", "PrecompileTools", "Printf", "RecipesBase", "SHA", "Serialization", "StaticArrays", "Statistics", "SteadyStateDiffEq", "Suppressor", "SymbolicIndexingInterface", "SymbolicUtils", "Symbolics", "TOML", "Tar", "Timers", "UnPack", "VortexStepMethod", "YAML"] -path = "." -uuid = "9c9a347c-5289-41db-a9b9-25ccc76c3360" -version = "0.6.1" - - [deps.SymbolicAWEModels.extensions] - SymbolicAWEModelsMakieExt = ["GeometryBasics", "Makie"] - - [deps.SymbolicAWEModels.weakdeps] - GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - -[[deps.SymbolicCompilerPasses]] -deps = ["LinearAlgebra", "PreallocationTools", "StaticArrays", "SymbolicUtils"] -git-tree-sha1 = "b0d41c9e1ab4f81a6e5800bb7d2534330071d520" -uuid = "3384d301-0fbe-4b40-9ae0-b0e68bedb069" -version = "0.1.2" -weakdeps = ["LinearSolve"] - - [deps.SymbolicCompilerPasses.extensions] - SCPLinearSolveExt = ["LinearSolve"] - -[[deps.SymbolicIndexingInterface]] -deps = ["Accessors", "ArrayInterface", "RuntimeGeneratedFunctions", "StaticArraysCore"] -git-tree-sha1 = "94c58884e013efff548002e8dc2fdd1cb74dfce5" -uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" -version = "0.3.46" - - [deps.SymbolicIndexingInterface.extensions] - SymbolicIndexingInterfacePrettyTablesExt = "PrettyTables" - - [deps.SymbolicIndexingInterface.weakdeps] - PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" - -[[deps.SymbolicLimits]] -deps = ["SymbolicUtils", "TermInterface"] -git-tree-sha1 = "5085671d2cba1eb02136a3d6661c583e801984c1" -uuid = "19f23fe9-fdab-4a78-91af-e7b7767979c3" -version = "1.1.0" - -[[deps.SymbolicUtils]] -deps = ["AbstractTrees", "ArrayInterface", "Combinatorics", "ConstructionBase", "DataStructures", "DocStringExtensions", "DynamicPolynomials", "EnumX", "ExproniconLite", "LinearAlgebra", "MacroTools", "Moshi", "MultivariatePolynomials", "MutableArithmetics", "NaNMath", "PrecompileTools", "ReadOnlyArrays", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArraysCore", "SymbolicIndexingInterface", "TaskLocalValues", "TermInterface", "WeakCacheSets"] -git-tree-sha1 = "8eca181fd593cb962bcaaa458177847a65a18542" -uuid = "d1185830-fcd6-423d-90d6-eec64667417b" -version = "4.18.3" - - [deps.SymbolicUtils.extensions] - SymbolicUtilsChainRulesCoreExt = "ChainRulesCore" - SymbolicUtilsDistributionsExt = "Distributions" - SymbolicUtilsLabelledArraysExt = "LabelledArrays" - SymbolicUtilsReverseDiffExt = "ReverseDiff" - - [deps.SymbolicUtils.weakdeps] - ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" - Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" - LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800" - ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" - -[[deps.Symbolics]] -deps = ["ADTypes", "AbstractPlutoDingetjes", "ArrayInterface", "Bijections", "CommonWorldInvalidations", "ConstructionBase", "DataStructures", "DiffRules", "DocStringExtensions", "DomainSets", "DynamicPolynomials", "Libdl", "LinearAlgebra", "LogExpFunctions", "MacroTools", "Markdown", "Moshi", "MultivariatePolynomials", "MutableArithmetics", "NaNMath", "PrecompileTools", "Preferences", "Primes", "RecipesBase", "Reexport", "RuntimeGeneratedFunctions", "SciMLPublic", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArraysCore", "SymbolicIndexingInterface", "SymbolicLimits", "SymbolicUtils", "TermInterface"] -git-tree-sha1 = "c2929e4bbdbc4cf8f920ffc9a4d1266ea126ba9f" -uuid = "0c5d862f-8b57-4792-8d23-62f2024744c7" -version = "7.15.1" - - [deps.Symbolics.extensions] - SymbolicsD3TreesExt = "D3Trees" - SymbolicsDistributionsExt = "Distributions" - SymbolicsForwardDiffExt = "ForwardDiff" - SymbolicsGroebnerExt = "Groebner" - SymbolicsHypergeometricFunctionsExt = "HypergeometricFunctions" - SymbolicsLatexifyExt = ["Latexify", "LaTeXStrings"] - SymbolicsLuxExt = "Lux" - SymbolicsNemoExt = "Nemo" - SymbolicsPreallocationToolsExt = ["PreallocationTools", "ForwardDiff"] - SymbolicsSymPyExt = "SymPy" - SymbolicsSymPyPythonCallExt = "SymPyPythonCall" - - [deps.Symbolics.weakdeps] - D3Trees = "e3df1716-f71e-5df9-9e2d-98e193103c45" - Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" - ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" - Groebner = "0b43b601-686d-58a3-8a1c-6623616c7cd4" - HypergeometricFunctions = "34004b35-14d8-5ef3-9330-4cdb6864b03a" - LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" - Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" - Lux = "b2108857-7c20-44ae-9111-449ecde12c47" - Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a" - PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" - SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" - SymPyPythonCall = "bc8888f7-b21e-4b7c-a06a-5d9c9496438c" - -[[deps.TOML]] -deps = ["Dates"] -uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" -version = "1.0.3" - -[[deps.TZJData]] -deps = ["Artifacts"] -git-tree-sha1 = "72df96b3a595b7aab1e101eb07d2a435963a97e2" -uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" -version = "1.5.0+2025b" - -[[deps.TableTraits]] -deps = ["IteratorInterfaceExtensions"] -git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" -uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" -version = "1.0.1" - -[[deps.Tables]] -deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] -git-tree-sha1 = "f2c1efbc8f3a609aadf318094f8fc5204bdaf344" -uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.12.1" - -[[deps.Tar]] -deps = ["ArgTools", "SHA"] -uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" -version = "1.10.0" - -[[deps.TaskLocalValues]] -git-tree-sha1 = "67e469338d9ce74fc578f7db1736a74d93a49eb8" -uuid = "ed4db957-447d-4319-bfb6-7fa9ae7ecf34" -version = "0.1.3" - -[[deps.TermInterface]] -git-tree-sha1 = "d673e0aca9e46a2f63720201f55cc7b3e7169b16" -uuid = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c" -version = "2.0.0" - -[[deps.Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -version = "1.11.0" - -[[deps.TestEnv]] -deps = ["Pkg"] -git-tree-sha1 = "ee6dbe7137903ffb607b4359e93c42f406b01d03" -uuid = "1e6cf692-eddd-4d53-88a5-2d735e33781b" -version = "1.103.5" - -[[deps.ThreadingUtilities]] -deps = ["ManualMemory"] -git-tree-sha1 = "d969183d3d244b6c33796b5ed01ab97328f2db85" -uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" -version = "0.5.5" - -[[deps.TimeZones]] -deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] -git-tree-sha1 = "d422301b2a1e294e3e4214061e44f338cafe18a2" -uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.22.2" -weakdeps = ["RecipesBase"] - - [deps.TimeZones.extensions] - TimeZonesRecipesBaseExt = "RecipesBase" - -[[deps.TimerOutputs]] -deps = ["ExprTools", "Printf"] -git-tree-sha1 = "3748bd928e68c7c346b52125cf41fff0de6937d0" -uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" -version = "0.5.29" - - [deps.TimerOutputs.extensions] - FlameGraphsExt = "FlameGraphs" - - [deps.TimerOutputs.weakdeps] - FlameGraphs = "08572546-2f56-4bcf-ba4e-bab62c3a3f89" - -[[deps.Timers]] -deps = ["Pkg", "TestEnv"] -git-tree-sha1 = "fe7046d2b5bc1d31cde8fd19fad7c5506e3960b4" -uuid = "21f18d07-b854-4dab-86f0-c15a3821819a" -version = "0.1.5" - -[[deps.TranscodingStreams]] -git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742" -uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.11.3" - -[[deps.TruncatedStacktraces]] -deps = ["InteractiveUtils", "MacroTools", "Preferences"] -git-tree-sha1 = "ea3e54c2bdde39062abf5a9758a23735558705e1" -uuid = "781d530d-4396-4725-bb49-402e4bee1e77" -version = "1.4.0" - -[[deps.UUIDs]] -deps = ["Random", "SHA"] -uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" -version = "1.11.0" - -[[deps.UnPack]] -git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" -uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" -version = "1.0.2" - -[[deps.Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" -version = "1.11.0" - -[[deps.VortexStepMethod]] -deps = ["Colors", "DefaultApplication", "DelimitedFiles", "DifferentiationInterface", "FiniteDiff", "Interpolations", "LaTeXStrings", "LinearAlgebra", "Logging", "Measures", "NonlinearSolve", "Parameters", "Pkg", "PreallocationTools", "PrecompileTools", "RecursiveArrayTools", "SciMLBase", "Serialization", "StaticArrays", "Statistics", "StructMapping", "Timers", "Xfoil", "YAML"] -git-tree-sha1 = "c9a27a89a2bb89007dfa16bfccf6522300f08bf5" -uuid = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" -version = "3.0.0" - - [deps.VortexStepMethod.extensions] - VortexStepMethodControlPlotsExt = "ControlPlots" - VortexStepMethodMakieExt = "Makie" - - [deps.VortexStepMethod.weakdeps] - ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" - Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" - -[[deps.WeakCacheSets]] -git-tree-sha1 = "386050ae4353310d8ff9c228f83b1affca2f7f38" -uuid = "d30d5f5c-d141-4870-aa07-aabb0f5fe7d5" -version = "0.1.0" - -[[deps.WeakRefStrings]] -deps = ["DataAPI", "InlineStrings", "Parsers"] -git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23" -uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" -version = "1.4.2" - -[[deps.WoodburyMatrices]] -deps = ["LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "248a7031b3da79a127f14e5dc5f417e26f9f6db7" -uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6" -version = "1.1.0" - -[[deps.WorkerUtilities]] -git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7" -uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" -version = "1.6.1" - -[[deps.Xfoil]] -deps = ["Printf", "xfoil_light_jll"] -git-tree-sha1 = "d12e518323d02400b27554feb5ac5088e22280cb" -uuid = "19641d66-a62d-11e8-2441-8f57a969a9c4" -version = "1.1.0" - -[[deps.YAML]] -deps = ["Base64", "Dates", "Printf", "StringEncodings"] -git-tree-sha1 = "a1c0c7585346251353cddede21f180b96388c403" -uuid = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" -version = "0.4.16" - -[[deps.ZipFile]] -deps = ["Libdl", "Printf", "Zlib_jll"] -git-tree-sha1 = "f492b7fe1698e623024e873244f10d89c95c340a" -uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" -version = "0.10.1" - -[[deps.Zlib_jll]] -deps = ["Libdl"] -uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.3.1+2" - -[[deps.Zstd_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "446b23e73536f84e8037f5dce465e92275f6a308" -uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" -version = "1.5.7+1" - -[[deps.libblastrampoline_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.15.0+0" - -[[deps.nghttp2_jll]] -deps = ["Artifacts", "Libdl"] -uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.64.0+1" - -[[deps.oneTBB_jll]] -deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"] -git-tree-sha1 = "1350188a69a6e46f799d3945beef36435ed7262f" -uuid = "1317d2d5-d96f-522e-a858-c73665f53c3e" -version = "2022.0.0+1" - -[[deps.p7zip_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] -uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.7.0+0" - -[[deps.xfoil_light_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "1ebea4f4577b2aa95d4151e11ed6210341e76f62" -uuid = "70cc596b-f351-5640-b155-76ddf0ff62ca" -version = "0.2.1+0" From 0337e91a3acbec9d4495a4dafe8a7a3cd58f9555 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 27 Feb 2026 13:13:48 +0100 Subject: [PATCH 5/7] Improve naming --- src/system_structure/system_structure_core.jl | 6 +-- src/system_structure/utilities.jl | 4 +- src/system_structure/wing.jl | 2 +- src/vsm_refine.jl | 44 +++++++++---------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/system_structure/system_structure_core.jl b/src/system_structure/system_structure_core.jl index e25983b8..25285e69 100644 --- a/src/system_structure/system_structure_core.jl +++ b/src/system_structure/system_structure_core.jl @@ -779,13 +779,13 @@ function SystemStructure(name, set; end end - # Lock unrefined aero sections to structural LE/TE for - # ALL VSMWing types (runs after auto-group creation so + # Match aero sections to structural LE/TE for ALL + # VSMWing types (runs after auto-group creation so # identify_wing_segments can use groups). for wing in wings isa(wing, VSMWing) || continue wing.aero_mode == AERO_NONE && continue - prime_polars_then_lock_unrefined_to_structure!( + match_aero_sections_to_structure!( wing, points; groups=groups) end diff --git a/src/system_structure/utilities.jl b/src/system_structure/utilities.jl index 54019513..8592db95 100644 --- a/src/system_structure/utilities.jl +++ b/src/system_structure/utilities.jl @@ -381,8 +381,8 @@ function reinit!(sys_struct::SystemStructure, set::Settings; end VortexStepMethod.reinit!(wing.vsm_aero) - # Lock aero sections to structure (all types) - prime_polars_then_lock_unrefined_to_structure!( + # Match aero sections to structure (all types) + match_aero_sections_to_structure!( wing, points; groups=groups) # Recompute group→section mapping diff --git a/src/system_structure/wing.jl b/src/system_structure/wing.jl index d47f9aa3..49f51a6a 100644 --- a/src/system_structure/wing.jl +++ b/src/system_structure/wing.jl @@ -317,7 +317,7 @@ Creates vsm_wing, vsm_aero, and vsm_solver internally. - `wing_type::WingType=QUATERNION`: Aerodynamic model type. - `point_to_vsm_point`: 1:1 structural point to VSM point mapping (REFINE only). - `wing_segments`: LE/TE pairs (populated for all VSM wing types by - `prime_polars_then_lock_unrefined_to_structure!`). + `match_aero_sections_to_structure!`). - `z_ref_points`: Chord direction reference points (REFINE only, names or indices). - `y_ref_points`: Span direction reference points (REFINE only, names or indices). - `origin`: Reference to origin point (REFINE only, name or index). diff --git a/src/vsm_refine.jl b/src/vsm_refine.jl index acc0d60a..c4f59ff3 100644 --- a/src/vsm_refine.jl +++ b/src/vsm_refine.jl @@ -6,7 +6,7 @@ Helper functions for VSM wing types. REFINE-specific functions (panel force distribution, structural geometry updates) are at the bottom of this file. The shared -`prime_polars_then_lock_unrefined_to_structure!` works for all VSMWing types. +`match_aero_sections_to_structure!` works for all VSMWing types. """ # Baseline chord-based aero scaling for REFINE wings. @@ -100,14 +100,14 @@ function identify_wing_segments( end """ - prime_polars_then_lock_unrefined_to_structure!(wing, points; groups) + match_aero_sections_to_structure!(wing, points; groups) -Lock unrefined aerodynamic sections to structural LE/TE positions, -preserving already-initialized refined/panel polars. +Rebuild unrefined sections to match structural LE/TE positions, +preserving refined panel polars via `use_prior_polar`. Works for **all** VSMWing types (QUATERNION and REFINE). When the structural and aerodynamic section counts match the rebuild is a 1:1 -copy (`template_idx == i`) that ensures positions exactly match +copy (`source_idx == i`) that ensures positions exactly match structural points. When they differ, `use_prior_polar` and non-empty `refined_sections` are required. @@ -119,7 +119,7 @@ vectors (`vsm_y`, `vsm_x`, `vsm_jac`) are resized to match the new - `groups::AbstractVector{Group}`: Groups in the system (used for group-based LE/TE identification via [`identify_wing_segments`](@ref)). """ -function prime_polars_then_lock_unrefined_to_structure!( +function match_aero_sections_to_structure!( wing::VSMWing, points::AbstractVector{Point}; groups::AbstractVector{Group}=Group[] @@ -169,17 +169,17 @@ function prime_polars_then_lock_unrefined_to_structure!( "($(n_struct_sections)) do not match " * "aerodynamic sections " * "($(n_aero_sections)). Set " * - "use_prior_polar=true to allow one-time " * - "polar seeding and lock to structural " * - "sections." + "use_prior_polar=true to rebuild " * + "unrefined sections from structural " * + "geometry." ) isempty(wing.vsm_wing.refined_sections) && error( - "Wing $(wing.idx): cannot lock " * + "Wing $(wing.idx): cannot rebuild " * "unrefined sections because no " * - "refined sections exist to reuse " * - "polars." + "refined sections exist to " * + "preserve polars from." ) end @@ -192,9 +192,9 @@ function prime_polars_then_lock_unrefined_to_structure!( "structural LE/TE pairs." ) - template_sections = wing.vsm_wing.unrefined_sections - n_templates = length(template_sections) - n_templates > 0 || error( + original_sections = wing.vsm_wing.unrefined_sections + n_original = length(original_sections) + n_original > 0 || error( "Wing $(wing.idx): aerodynamic geometry " * "has zero unrefined sections." ) @@ -204,15 +204,15 @@ function prime_polars_then_lock_unrefined_to_structure!( undef, n_struct_sections) for (i, (le_idx, te_idx)) in enumerate(wing_segments) - template_idx = if counts_differ + source_idx = if counts_differ n_struct_sections == 1 ? 1 : round(Int, - 1 + (i - 1) * (n_templates - 1) / + 1 + (i - 1) * (n_original - 1) / (n_struct_sections - 1)) else i # 1:1 copy when counts match end - template = template_sections[template_idx] + source_section = original_sections[source_idx] le_body = R_b_to_c' * (points[le_idx].pos_cad - origin_cad) @@ -220,16 +220,16 @@ function prime_polars_then_lock_unrefined_to_structure!( (points[te_idx].pos_cad - origin_cad) section = VortexStepMethod.Section() - if isnothing(template.aero_data) + if isnothing(source_section.aero_data) VortexStepMethod.reinit!( section, le_body, te_body, - template.aero_model + source_section.aero_model ) else VortexStepMethod.reinit!( section, le_body, te_body, - template.aero_model, - template.aero_data + source_section.aero_model, + source_section.aero_data ) end new_sections[i] = section From 96d2a7bb9d12dd17bebe795bb247ff4c57da4555 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 27 Feb 2026 13:17:16 +0100 Subject: [PATCH 6/7] Update docs for new coupling --- docs/Project.toml | 4 + docs/src/private_functions.md | 2 + docs/src/tutorial_julia.md | 3 + docs/src/vsm_coupling.md | 259 +++++++++++++++++++++++++--------- 4 files changed, 205 insertions(+), 63 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 29d24313..810cce87 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -11,3 +11,7 @@ VortexStepMethod = "ed3cd733-9f0f-46a9-93e0-89b8d4998dd9" [compat] Documenter = "1.11" + +[sources] +SymbolicAWEModels = {path = ".."} + diff --git a/docs/src/private_functions.md b/docs/src/private_functions.md index 82fabb07..d0b65537 100644 --- a/docs/src/private_functions.md +++ b/docs/src/private_functions.md @@ -133,6 +133,8 @@ SymbolicAWEModels.resolve_ref_spec SymbolicAWEModels.validate_sys_struct SymbolicAWEModels.build_name_dict SymbolicAWEModels.identify_wing_segments +SymbolicAWEModels.match_aero_sections_to_structure! +SymbolicAWEModels.compute_spatial_group_mapping! SymbolicAWEModels.init_untransformed_components! SymbolicAWEModels.adjust_vsm_panels_to_origin! SymbolicAWEModels.apply_aero_z_offset! diff --git a/docs/src/tutorial_julia.md b/docs/src/tutorial_julia.md index 7bdf6a01..f60eaca2 100644 --- a/docs/src/tutorial_julia.md +++ b/docs/src/tutorial_julia.md @@ -2,6 +2,9 @@ EditURL = "literate/tutorial_julia.jl" ``` +Copyright (c) 2025 Bart van de Lint, Jelle Poland +SPDX-License-Identifier: MPL-2.0 + ```@meta CurrentModule = SymbolicAWEModels ``` diff --git a/docs/src/vsm_coupling.md b/docs/src/vsm_coupling.md index 70222154..d732bead 100644 --- a/docs/src/vsm_coupling.md +++ b/docs/src/vsm_coupling.md @@ -1,28 +1,48 @@ # VSM coupling -This document explains how SymbolicAWEModels couples with the Vortex Step Method (VSM) for aerodynamic force computation. The coupling differs between the two wing types: [`QUATERNION` and `REFINE`](@ref WingType). +This document explains how SymbolicAWEModels couples with the +Vortex Step Method (VSM) for aerodynamic force computation. The +coupling is configured by two orthogonal choices: +[`WingType`](@ref) (structural representation) and +[`AeroMode`](@ref) (force computation strategy). ## Overview -Both wing types use **unrefined sections** as the fundamental structural element that maps to VSM geometry: +Both wing types use **unrefined sections** as the fundamental +element that maps to VSM geometry: -- **Unrefined section**: A structural element defined by two points (leading edge and trailing edge) along the wing span -- **Refined panel**: VSM can subdivide unrefined sections into multiple panels for higher aerodynamic fidelity -- **`refined_panel_mapping`**: Maps each refined panel back to its parent unrefined section +- **Unrefined section**: A structural element defined by two + points (leading edge and trailing edge) along the wing span +- **Refined panel**: VSM can subdivide unrefined sections into + multiple panels for higher aerodynamic fidelity +- **`refined_panel_mapping`**: Maps each refined panel back to + its parent unrefined section -The VSM solver computes aerodynamic coefficients (cl, cd, cm, alpha) at both refined and unrefined levels. SymbolicAWEModels uses the **unrefined-level coefficients** to map forces back to the structural model. +The VSM solver computes aerodynamic coefficients (cl, cd, cm, +alpha) at both refined and unrefined levels. SymbolicAWEModels +uses the **unrefined-level coefficients** to map forces back to +the structural model. ## Wing types -### REFINE wing type +[`WingType`](@ref) controls the **structural representation** of +the wing — how it deforms and how forces are distributed to +structural degrees of freedom. -The `REFINE` wing type creates the most direct coupling between structure and aerodynamics. +### REFINE + +The `REFINE` wing type creates the most direct coupling between +structure and aerodynamics. #### Structural model -- Wing structure consists of [`WING`](@ref DynamicsType)-type points organized in leading edge (LE) and trailing edge (TE) pairs -- Each consecutive pair (point i, point i+1) forms a structural segment (strut) -- Points can move independently - the wing can deform structurally +- Wing structure consists of [`WING`](@ref DynamicsType)-type + points organized in leading edge (LE) and trailing edge (TE) + pairs +- Each consecutive pair (point i, point i+1) forms a structural + segment (strut) +- Points can move independently — the wing can deform + structurally - Number of structural segments = (number of WING points) / 2 #### VSM mapping @@ -35,20 +55,16 @@ Structural points: [LE₁, TE₁] [LE₂, TE₂] [LE₃, TE₃] Unrefined sections: Sec₁ Sec₂ Sec₃ ``` -Each VSM section is defined by its LE and TE point positions, taken directly from the structural point positions. VSM can subdivide these into refined panels for higher fidelity; `refined_panel_mapping` maps each refined panel back to its parent section. - -#### Force distribution - -Forces are computed and distributed in several steps: - -1. **VSM solve**: Computes aerodynamic coefficients and per-panel forces/moments in body frame -2. **Panel → section mapping**: Each refined panel maps to its parent unrefined section via `refined_panel_mapping` -3. **Moment-preserving LE/TE split** (`compute_aerostruc_loads`): Each panel's force and moment are split into LE and TE contributions that preserve the total moment about a reference point -4. **Accumulation at structural points**: LE/TE forces are accumulated at the corresponding structural points via the `point_to_vsm_point` mapping +Each VSM section is defined by its LE and TE point positions, +taken directly from the structural point positions. VSM can +subdivide these into refined panels for higher fidelity; +`refined_panel_mapping` maps each refined panel back to its +parent section. #### Geometry update -Each timestep, structural point positions update VSM section geometry: +Each timestep, structural point positions update VSM section +geometry: ```julia # For each structural point mapped to a VSM section point: @@ -56,22 +72,43 @@ pos_b = R_b_to_w' * (point.pos_w - wing.origin) section.LE_point = pos_b # or section.TE_point ``` -This bidirectional coupling allows structural deformation to affect aerodynamics. +This bidirectional coupling allows structural deformation to +affect aerodynamics. + +#### Force distribution + +Per-panel forces are distributed to structural points: + +1. **Panel → section mapping**: Each refined panel maps to its + parent unrefined section via `refined_panel_mapping` +2. **Moment-preserving LE/TE split** (`compute_aerostruc_loads`): + Each panel's force and moment are split into LE and TE + contributions that preserve the total moment about a reference + point +3. **Accumulation at structural points**: LE/TE forces are + accumulated at the corresponding structural points via the + `point_to_vsm_point` mapping -### QUATERNION wing type +### QUATERNION -The `QUATERNION` wing type uses a rigid body representation with optional deformable groups. +The `QUATERNION` wing type uses a rigid body representation with +optional deformable groups. #### Structural model - Wing treated as a rigid body with quaternion-based orientation -- No per-point wing structure - aerodynamic forces applied to wing center of mass -- Optional **groups** represent deformable sections with twist degrees of freedom -- Groups control segment twist angles but don't affect primary aerodynamic geometry +- No per-point wing structure — aerodynamic forces applied to + wing center of mass +- Optional **groups** represent deformable sections with twist + degrees of freedom +- Groups control segment twist angles. With + `use_prior_polar=true`, group LE/TE positions also define the + aerodynamic section geometry #### VSM mapping -VSM still uses unrefined sections, but they don't correspond to individual structural points: +VSM still uses unrefined sections, but they don't correspond to +individual structural points: ``` Unrefined sections: [Sec₁, Sec₂, Sec₃, Sec₄, Sec₅] @@ -80,42 +117,129 @@ Groups: [─ Group₁ ─] [─ Group₂ ─] twist DOF θ₁ twist DOF θ₂ ``` -Multiple unrefined sections can be combined into a single group for twist control. The mapping is configured via: +Multiple unrefined sections can be combined into a single group +for twist control. The mapping is configured via: ```julia group.unrefined_section_idxs = [start_idx:end_idx] ``` -#### Force computation - -VSM linearization returns integrated aerodynamic coefficients per wing: - -1. **VSM linearize**: Computes baseline coefficients and Jacobian around the current operating point - - Output state `vsm_x = [C_F(3), C_M(3), section_moments(n_unrefined)]` - - Input state `vsm_y = [va_b(3), twist_angles(n_unrefined), ω_b(3)]` -2. **Symbolic linearization**: The ODE uses `F = q∞ · A · (C₀ + J · Δstate)` where `Δstate = state - state₀` - - `C₀[1:3]` → total force coefficient, `C₀[4:6]` → total moment coefficient - - `C₀[7:end]` → per-section twist moment coefficients, summed per group -3. **Rigid body dynamics**: Integrated force/moment drive quaternion dynamics +#### Force distribution -Groups affect twist deformation applied to VSM sections before the solve. Each group's aerodynamic moment is the sum of its unrefined section moments, driving the twist DOF. +Integrated force and moment coefficients are applied to the rigid +body, driving quaternion dynamics. Each group's aerodynamic moment +is the sum of its unrefined section moments, driving the twist +DOF. + +## Aero modes + +[`AeroMode`](@ref) controls **how aerodynamic forces enter the +ODE system** — orthogonal to the wing type choice. + +### AERO_DIRECT + +The VSM solver runs a full nonlinear solve. The resulting forces +are stored in the wing struct and read by registered symbolic +functions during ODE evaluation: + +1. `VortexStepMethod.linearize()` computes baseline coefficients +2. Physical forces are computed: `F = q∞ · A · C₀` +3. Forces are stored in `wing.aero_force_b` and + `wing.aero_moment_b` (QUATERNION) or per-point via + `distribute_panel_forces_to_points!` (REFINE) +4. Between VSM updates (controlled by `vsm_interval`), forces + are held constant + +For QUATERNION wings, the symbolic equations read the stored +forces via `get_aero_force_override` / `get_aero_moment_override`. +For REFINE wings, per-point forces are read via +`get_point_aero_force`. + +### AERO_LINEARIZED + +A first-order Taylor expansion using the Jacobian from VSM +linearization. This enables the ODE solver to see smooth +force variations between VSM updates: + +1. `VortexStepMethod.linearize()` computes the Jacobian and + baseline coefficients around the current operating point + - Output state + `vsm_x = [C_F(3), C_M(3), section_moments(n_unrefined)]` + - Input state + `vsm_y = [va_b(3), twist_angles(n_unrefined), ω_b(3)]` +2. The symbolic ODE uses + `F = q∞ · A · (C₀ + J · Δstate)` where + `Δstate = state - state₀` + - `C₀[1:3]` → total force coefficient, + `C₀[4:6]` → total moment coefficient + - `C₀[7:end]` → per-section twist moment coefficients, + summed per group +3. Between VSM updates, the Jacobian extrapolates forces as + the state evolves + +### AERO_NONE + +Returns zero forces. Useful for debugging rigid body dynamics +without aerodynamic coupling. + +### Compatibility + +| Wing type | Default aero mode | Supported modes | +|-----------|-------------------|-----------------| +| **QUATERNION** | `AERO_LINEARIZED` | `AERO_LINEARIZED`, `AERO_DIRECT`, `AERO_NONE` | +| **REFINE** | `AERO_DIRECT` | `AERO_DIRECT`, `AERO_NONE` | + +`REFINE` + `AERO_LINEARIZED` is not yet implemented (raises an +error at runtime). + +## Aligning aero sections to structure + +When the number of aerodynamic sections differs from the number +of structural LE/TE pairs, `match_aero_sections_to_structure!` +rebuilds the unrefined sections so their geometry matches the +structure. This applies to both wing types and requires +`use_prior_polar=true` on the VortexStepMethod wing. + +The steps are: + +1. **Find structural LE/TE pairs**: `identify_wing_segments` + extracts pairs from groups (preferred) or uses a + consecutive-pair heuristic +2. **Rebuild unrefined sections**: For each structural pair, a + new `Section` is created with LE/TE positions from the + structural points (in body frame). Its airfoil data + (`aero_model`, `aero_data`) is copied from the nearest + original unrefined section by span index +3. **Re-refine**: `refine!` updates refined panel geometry from + the rebuilt unrefined sections. Because `use_prior_polar=true` + and `n_panels` is unchanged, existing refined panel polars are + preserved — only positions are re-interpolated +4. **Resize linearization state**: For non-REFINE wings, `vsm_y`, + `vsm_x`, and `vsm_jac` are resized to match the new section + count ## Refined panel mapping -Both wing types use `refined_panel_mapping` to handle VSM mesh refinement: +Both wing types use `refined_panel_mapping` to handle VSM mesh +refinement: ### Purpose -VSM can subdivide unrefined sections into multiple refined panels for higher aerodynamic fidelity. The mapping tracks which parent unrefined section each refined panel belongs to. +VSM can subdivide unrefined sections into multiple refined panels +for higher aerodynamic fidelity. The mapping tracks which parent +unrefined section each refined panel belongs to. ### Computation -After VSM refinement, `compute_refined_panel_mapping!` finds the closest unrefined section for each refined panel by comparing center positions: +After VSM refinement, `compute_refined_panel_mapping!` finds the +closest unrefined section for each refined panel by comparing +center positions: ```julia for each refined_panel in wing.refined_sections center = compute_center(refined_panel) - closest_section = argmin(distance(center, unrefined_section_centers)) + closest_section = argmin( + distance(center, unrefined_section_centers)) refined_panel_mapping[refined_panel_idx] = closest_section end ``` @@ -124,27 +248,36 @@ end The mapping enables: -1. **Group twist angles**: Applying the correct twist angle from groups to refined panels via their parent section -2. **Force distribution (REFINE)**: Accumulating refined panel forces at the structural points of their parent section -3. **Linearization (QUATERNION)**: Propagating state perturbations through the correct sections +1. **Group twist angles**: Applying the correct twist angle from + groups to refined panels via their parent section +2. **Force distribution (REFINE)**: Accumulating refined panel + forces at the structural points of their parent section +3. **Linearization (QUATERNION + AERO_LINEARIZED)**: Propagating + state perturbations through the correct sections -## Key differences summary +## Wing type summary | Aspect | REFINE | QUATERNION | |--------|--------|------------| -| **Structural representation** | Individual WING points | Rigid body with quaternion | -| **Unrefined section count** | = number of structural LE/TE pairs | Independent of structure | -| **Force distribution** | Per-point via moment-preserving LE/TE split | Integrated force/moment coefficients | -| **Deformation coupling** | Direct: point motion → VSM geometry | Indirect: group twists → VSM sections | -| **Computational cost** | Higher (full VSM solve per step) | Lower (linearized) | -| **Fidelity** | Higher (aeroelastic coupling) | Lower (rigid body) | +| **Structural repr.** | Individual WING points | Rigid body + quaternion | +| **Section count** | = structural LE/TE pairs | Independent; optionally rebuilt via `use_prior_polar` | +| **Force distribution** | Per-point moment-preserving LE/TE split | Integrated force/moment on body | +| **Deformation** | Direct: point motion → VSM geometry | Indirect: group twists → sections | +| **Default aero mode** | `AERO_DIRECT` | `AERO_LINEARIZED` | ## Implementation files -- `src/vsm_refine.jl`: REFINE wing force distribution and geometry updates -- `src/system_structure/types.jl`: Component type definitions (Point, Segment, etc.) -- `src/system_structure/wing.jl`: Wing and VSMWing type definitions, group-to-section mapping -- `src/generate_system/vsm_eqs.jl`: Symbolic VSM equation generation -- `src/generate_system/wing_eqs.jl`: Wing dynamics equation generation -- `src/linearize.jl`: VSM linearization and Jacobian updates -- VortexStepMethod.jl `src/wing_geometry.jl`: `refined_panel_mapping` computation +- `src/vsm_refine.jl`: Aero-to-structure alignment (all wing + types), REFINE force distribution, and geometry updates +- `src/system_structure/types.jl`: Component type definitions + including `WingType` and `AeroMode` enums +- `src/system_structure/wing.jl`: Wing and VSMWing type + definitions, group-to-section mapping +- `src/generate_system/vsm_eqs.jl`: Symbolic VSM equation + generation (all wing type × aero mode combinations) +- `src/generate_system/wing_eqs.jl`: Wing dynamics equation + generation +- `src/linearize.jl`: VSM update dispatch — linearization + (QUATERNION) and nonlinear solve (REFINE) +- VortexStepMethod.jl `src/wing_geometry.jl`: + `refined_panel_mapping` computation From e8bc63219570b581662992f10ec00b4f97745f4f Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 27 Feb 2026 14:00:48 +0100 Subject: [PATCH 7/7] Improved tests and updated version --- CHANGELOG.md | 36 +++ Project.toml | 2 +- README.md | 1 + ..._polars.jl => test_match_aero_sections.jl} | 252 ++++++++++-------- 4 files changed, 185 insertions(+), 106 deletions(-) rename test/{test_prime_polars.jl => test_match_aero_sections.jl} (50%) diff --git a/CHANGELOG.md b/CHANGELOG.md index bccd9932..ec23fb6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,42 @@ SPDX-FileCopyrightText: 2025 Uwe Fechner, Bart van de Lint SPDX-License-Identifier: MPL-2.0 --> +# v0.7.0 DD-02-2026 + +## Changed +- BREAKING: Julia version requirement raised from 1.10 to 1.11, 1.12. +- `reinit!()` uses a unified code path for all wing types, calling + `match_aero_sections_to_structure!` and + `compute_spatial_group_mapping!` during VSM rebuild. +- `test_bench.jl` refactored from ad-hoc benchmarks into a proper + `@testset` suite with `setup_bench_sam()` helper. +- Added `[workspace]` configuration in `Project.toml` for docs, examples, + scripts, and test sub-projects. +- Manifest files renamed to `.default` suffix and gitignored. + +## Added +- Asymmetric aero/structural section counts: aerodynamic and structural + meshes can now have different numbers of sections. When counts differ, + `match_aero_sections_to_structure!()` rebuilds unrefined + sections from structural LE/TE positions while `use_prior_polar=true` + preserves existing refined panel polars. Opt-in via + `use_prior_polar=true` on the VortexStepMethod wing. +- `identify_wing_segments()` — identifies LE/TE pairs from groups + (preferred) or via a consecutive-pair heuristic. +- `compute_spatial_group_mapping!()` — maps groups to VSM sections by + spatial proximity, supporting n_groups != n_aero_sections. +- REFINE wings can now have groups (used for LE/TE pair identification). +- QUATERNION wings can now have `wing_segments` for structural geometry + locking. +- YAML loader fallback LE/TE detection in + `update_aero_yaml_from_struc_yaml!()` when no groups are defined + (consecutive-pair heuristic with x-coordinate check). +- `test_match_aero_sections.jl` — tests geometry matching and polar + interpolation for both REFINE and QUATERNION wings, including + mismatched section counts. +- Helper scripts: `bin/install` (environment setup, Julia version detection) + and `bin/run_julia` (launcher with system image support). + # v0.6.1 23-02-2026 ## Fixed diff --git a/Project.toml b/Project.toml index 2d2108f0..145a222d 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "SymbolicAWEModels" uuid = "9c9a347c-5289-41db-a9b9-25ccc76c3360" -version = "0.6.1" +version = "0.7.0" authors = ["Bart van de Lint and contributors"] [deps] diff --git a/README.md b/README.md index 2d9a8c0d..0cd9876f 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,7 @@ julia --project=test test/test_point.jl | `test_principal_body_frame` | Principal vs body frame separation | | `test_heading_calculation` | Kite heading from tether geometry | | `test_section_alignment` | VSM section ↔ structural point mapping | +| `test_match_aero_sections` | Asymmetric aero/structural section matching, polar interpolation | | `test_profile_law` | Atmospheric wind profile verification | | `test_bench` | Performance regression tracking | diff --git a/test/test_prime_polars.jl b/test/test_match_aero_sections.jl similarity index 50% rename from test/test_prime_polars.jl rename to test/test_match_aero_sections.jl index 11c465a7..41780ea7 100644 --- a/test/test_prime_polars.jl +++ b/test/test_match_aero_sections.jl @@ -1,17 +1,17 @@ # Copyright (c) 2025 Bart van de Lint # SPDX-License-Identifier: MPL-2.0 -# test_prime_polars.jl -# Tests for prime_polars_then_lock_unrefined_to_structure!: -# verifies geometry, unrefined polar propagation, and -# refined polar interpolation for both REFINE and QUATERNION -# wing types. +# test_match_aero_sections.jl +# Tests for match_aero_sections_to_structure!: +# verifies geometry alignment and that use_prior_polar +# preserves refined panel polars across section count +# changes (no re-interpolation). using Test using SymbolicAWEModels using SymbolicAWEModels: KVec3, VortexStepMethod, WING, REFINE, QUATERNION, SimFloat, - prime_polars_then_lock_unrefined_to_structure! + match_aero_sections_to_structure! using KiteUtils using LinearAlgebra @@ -38,21 +38,8 @@ vsm_set_path = joinpath(data_path, "vsm_settings.yaml") vsm_set = VortexStepMethod.VSMSettings( vsm_set_path; data_prefix=false) -# ── mock polar helpers ─────────────────────────────────── -alpha_mock = collect(-5.0:1.0:5.0) # 11 points -n_alpha = length(alpha_mock) - -"""Create recognizable mock polar for section `i`: -cl=i, cd=10i, cm=100i (constant across alpha).""" -function mock_polar(i) - cl = fill(Float64(i), n_alpha) - cd = fill(Float64(10i), n_alpha) - cm = fill(Float64(100i), n_alpha) - return (copy(alpha_mock), cl, cd, cm) -end - # ───────────────────────────────────────────────────────── -@testset "prime_polars — REFINE" begin +@testset "match_aero_sections — REFINE" begin @testset "geometry: LE/TE match structural points" begin sys = SymbolicAWEModels.load_sys_struct_from_yaml( @@ -77,7 +64,7 @@ end vsm_w.use_prior_polar = true wing.wing_segments = nothing - prime_polars_then_lock_unrefined_to_structure!( + match_aero_sections_to_structure!( wing, points) @test vsm_w.n_unrefined_sections == n_struct @@ -100,103 +87,111 @@ end end end - # Shared setup for polar tests: 5 aero sections with - # mock polars, 3 structural sections, cleared refined - # aero_data so refine! freshly interpolates. - sys = SymbolicAWEModels.load_sys_struct_from_yaml( - refine_yaml; - system_name="refine_polar", set, vsm_set) - wing = sys.wings[1] - points = sys.points - vsm_w = wing.vsm_wing - - n_struct = count( - p -> p.type == WING && - p.wing_idx == wing.idx, - points) ÷ 2 - - # Add 2 extra sections: 5 aero vs 3 struct - for _ in 1:2 - push!(vsm_w.unrefined_sections, - deepcopy(vsm_w.unrefined_sections[1])) - end - n_templates = length(vsm_w.unrefined_sections) - vsm_w.n_unrefined_sections = Int16(n_templates) - - # Stamp recognizable mock polars on all 5 sections - for i in 1:n_templates - sec = vsm_w.unrefined_sections[i] - sec.aero_model = VortexStepMethod.POLAR_VECTORS - sec.aero_data = mock_polar(i) - end + @testset "use_prior_polar preserves refined polars" begin + sys = SymbolicAWEModels.load_sys_struct_from_yaml( + refine_yaml; + system_name="refine_polar", set, vsm_set) + wing = sys.wings[1] + points = sys.points + vsm_w = wing.vsm_wing - # Clear refined section aero_data so refine! freshly - # interpolates (makes _can_reuse_prior_refined_polar_data - # return false). - for sec in vsm_w.refined_sections - sec.aero_data = nothing - sec.aero_model = VortexStepMethod.POLAR_VECTORS - end + # Baseline refined polars from constructor + n_refined = length(vsm_w.refined_sections) + @test n_refined > 0 + @test all( + s -> !isnothing(s.aero_data), + vsm_w.refined_sections) + baseline = [ + deepcopy(sec.aero_data) + for sec in vsm_w.refined_sections + ] - vsm_w.use_prior_polar = true - wing.wing_segments = nothing + n_struct = count( + p -> p.type == WING && + p.wing_idx == wing.idx, + points) ÷ 2 - prime_polars_then_lock_unrefined_to_structure!( - wing, points) + # Set all unrefined polars to a scaled value so + # re-interpolation would produce uniform output + # that differs from baseline + orig_ad = vsm_w.unrefined_sections[1].aero_data + @test !isnothing(orig_ad) + uniform = Tuple(v .* 2.0 for v in orig_ad) + for sec in vsm_w.unrefined_sections + sec.aero_data = deepcopy(uniform) + end - @testset "polars correct on unrefined sections" begin - @test vsm_w.n_unrefined_sections == n_struct + # Verify non-trivial: some baseline refined + # polars differ from the uniform unrefined data + @test any( + any(!isapprox(baseline[i][k], uniform[k]) + for k in eachindex(uniform)) + for i in eachindex(baseline)) + + # Create mismatch: add 2 extra unrefined sections + for _ in 1:2 + push!(vsm_w.unrefined_sections, + deepcopy(vsm_w.unrefined_sections[1])) + end + vsm_w.n_unrefined_sections = + Int16(length(vsm_w.unrefined_sections)) + @test vsm_w.n_unrefined_sections != n_struct - for i in 1:n_struct - sec = vsm_w.unrefined_sections[i] - @test sec.aero_model == - VortexStepMethod.POLAR_VECTORS - - # Same index mapping as vsm_refine.jl - tidx = n_struct == 1 ? 1 : - round(Int, 1 + (i - 1) * - (n_templates - 1) / - (n_struct - 1)) - expected = mock_polar(tidx) - - @test sec.aero_data[1] ≈ expected[1] - @test sec.aero_data[2] ≈ expected[2] - @test sec.aero_data[3] ≈ expected[3] - @test sec.aero_data[4] ≈ expected[4] + vsm_w.use_prior_polar = true + wing.wing_segments = nothing + + match_aero_sections_to_structure!( + wing, points) + + # Refined count unchanged (n_panels unchanged) + @test length(vsm_w.refined_sections) == n_refined + + # Refined polars preserved — NOT re-interpolated + for (i, sec) in + enumerate(vsm_w.refined_sections) + @test !isnothing(sec.aero_data) + for k in eachindex(baseline[i]) + @test sec.aero_data[k] ≈ baseline[i][k] + end end + + # Preserved polars differ from rebuilt unrefined + # (re-interpolation would have made them equal) + unrefined_ad = vsm_w.unrefined_sections[1].aero_data + @test any( + any(!isapprox(sec.aero_data[k], + unrefined_ad[k]) + for k in eachindex(sec.aero_data)) + for sec in vsm_w.refined_sections) + + # Unrefined sections rebuilt to match structure + @test vsm_w.n_unrefined_sections == n_struct end - @testset "polars correct on refined sections" begin - refined = vsm_w.refined_sections - n_panels = Int(vsm_w.n_panels) - @test length(refined) == n_panels + 1 - - # Unrefined cl values (constant per section) - unrefined_cls = [ - Float64( - vsm_w.unrefined_sections[i].aero_data[2][1] - ) - for i in 1:n_struct - ] - cl_lo = minimum(unrefined_cls) - cl_hi = maximum(unrefined_cls) + @testset "errors when use_prior_polar=false" begin + sys = SymbolicAWEModels.load_sys_struct_from_yaml( + refine_yaml; + system_name="refine_err", set, vsm_set) + wing = sys.wings[1] + points = sys.points + vsm_w = wing.vsm_wing - for sec in refined - @test sec.aero_model == - VortexStepMethod.POLAR_VECTORS - @test !isnothing(sec.aero_data) + # Create mismatch + push!(vsm_w.unrefined_sections, + deepcopy(vsm_w.unrefined_sections[1])) + vsm_w.n_unrefined_sections = + Int16(length(vsm_w.unrefined_sections)) - # Every refined cl value should be a weighted - # interpolation of neighboring unrefined cls, - # so it must lie within [cl_lo, cl_hi]. - cl_val = sec.aero_data[2][1] - @test cl_lo - 1e-10 ≤ cl_val ≤ cl_hi + 1e-10 - end + vsm_w.use_prior_polar = false + wing.wing_segments = nothing + + @test_throws ErrorException match_aero_sections_to_structure!( + wing, points) end end # ───────────────────────────────────────────────────────── -@testset "prime_polars — QUATERNION" begin +@testset "match_aero_sections — QUATERNION" begin @testset "geometry: LE/TE match structural points" begin sys_q = SymbolicAWEModels.load_sys_struct_from_yaml( @@ -242,6 +237,34 @@ end n_struct = length(wing.group_idxs) + # Save baseline refined polars + n_refined = length(vsm_w.refined_sections) + @test n_refined > 0 + @test all( + s -> !isnothing(s.aero_data), + vsm_w.refined_sections) + baseline = [ + deepcopy(sec.aero_data) + for sec in vsm_w.refined_sections + ] + + # Set all unrefined polars to a scaled value so + # re-interpolation would produce uniform output + # that differs from baseline + orig_ad = vsm_w.unrefined_sections[1].aero_data + @test !isnothing(orig_ad) + uniform = Tuple(v .* 2.0 for v in orig_ad) + for sec in vsm_w.unrefined_sections + sec.aero_data = deepcopy(uniform) + end + + # Verify non-trivial: some baseline refined + # polars differ from the uniform unrefined data + @test any( + any(!isapprox(baseline[i][k], uniform[k]) + for k in eachindex(uniform)) + for i in eachindex(baseline)) + # Add extra section to create mismatch extra = deepcopy(vsm_w.unrefined_sections[1]) push!(vsm_w.unrefined_sections, extra) @@ -252,7 +275,7 @@ end vsm_w.use_prior_polar = true wing.wing_segments = nothing - prime_polars_then_lock_unrefined_to_structure!( + match_aero_sections_to_structure!( wing, points; groups=collect(sys_q.groups)) @@ -264,5 +287,24 @@ end @test length(wing.vsm_y) == ny @test length(wing.vsm_x) == nx @test size(wing.vsm_jac) == (nx, ny) + + # Refined polars preserved — NOT re-interpolated + @test length(vsm_w.refined_sections) == n_refined + for (i, sec) in + enumerate(vsm_w.refined_sections) + @test !isnothing(sec.aero_data) + for k in eachindex(baseline[i]) + @test sec.aero_data[k] ≈ baseline[i][k] + end + end + + # Preserved polars differ from rebuilt unrefined + # (re-interpolation would have made them equal) + unrefined_ad = vsm_w.unrefined_sections[1].aero_data + @test any( + any(!isapprox(sec.aero_data[k], + unrefined_ad[k]) + for k in eachindex(sec.aero_data)) + for sec in vsm_w.refined_sections) end end