From acba31042459ddf8c7ee866f07d2ea4e5df0ca03 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 07:46:25 -0400 Subject: [PATCH 1/4] QA: run_qa v1.6 form + ExplicitImports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a SciMLTesting `run_qa`-based QA group (test/qa/qa.jl) with ExplicitImports enabled, replacing the bare hand-rolled QA env that previously only ran the bespoke `@test_opt` type-stability suite (kept as test/jet_tests.jl). The QA group now runs, on the `lts` and `1` matrix versions: * Aqua.test_all (all sub-checks), * JET.test_package (report-clean: 0 reports, run as a hard check), and * ExplicitImports' six standard + public-API checks. ExplicitImports findings: * no_stale_explicit_imports: FIXED — dropped the unused `arithmetic_closure` import (no method/use site, not extended downstream). * no_implicit_imports: BROKEN via `ei_broken = (:no_implicit_imports,)` — ~75 names implicitly imported through heavy `using` of KernelAbstractions / SciMLBase / DiffEqBase / StaticArrays / ...; making them explicit is a large refactor. Tracked in #466 (auto-flags Unexpected Pass once fixed). * owners + are-public checks: per-check ignore-lists for upstream packages' non-owner / non-public names (SciMLBase, DiffEqBase, ForwardDiff, LinearSolve, SimpleDiffEq, StaticArrays internals, ...), documented by source in qa.jl. Aqua deps_compat finding FIXED in Project.toml: added the missing [compat] entries for the stdlib deps Distributed/LinearAlgebra/Random and the [extras]-only Test/pocl_jll (check_extras), so no Aqua sub-check is disabled. Also make the GROUP=="QA" branch of runtests.jl terminal (`exit()`): it previously fell through into the GPU-backend testsets, which error on the CPU-only QA lane. test/qa/Project.toml: add SciMLTesting (compat "1.6") and Aqua (the ambiguities sub-check needs Aqua a direct dep); ExplicitImports stays transitive via SciMLTesting. Verified locally vs released SciMLTesting 1.6.0 (Pkg resolves it): Quality Assurance | 17 Pass, 1 Broken, 0 Fail/Error (lts = 1.10.11 and 1 = 1.12.6) JET static analysis | 75 Pass Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- Project.toml | 5 ++++ src/DiffEqGPU.jl | 2 +- test/qa/Project.toml | 10 +++++++ test/qa/qa.jl | 71 ++++++++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 4 +++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 test/qa/qa.jl diff --git a/Project.toml b/Project.toml index fec56db8..98e3da68 100644 --- a/Project.toml +++ b/Project.toml @@ -48,16 +48,19 @@ Adapt = "4" CUDA = "5, 6" ChainRulesCore = "1" DiffEqBase = "7" +Distributed = "1" DocStringExtensions = "0.9" ForwardDiff = "1" GPUArraysCore = "0.2" JLArrays = "0.3" KernelAbstractions = "0.9.38" +LinearAlgebra = "1" LinearSolve = "3" Metal = "1" MuladdMacro = "0.2.4" OpenCL = "0.10" Parameters = "0.12, 0.13" +Random = "1" RecursiveArrayTools = "4" SciMLBase = "3.1" Setfield = "1" @@ -65,9 +68,11 @@ SimpleDiffEq = "1.11" SimpleNonlinearSolve = "2" StaticArrays = "1.9.14" TOML = "1" +Test = "1" ZygoteRules = "0.2.7" julia = "1.10" oneAPI = "2" +pocl_jll = "7" [extras] AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" diff --git a/src/DiffEqGPU.jl b/src/DiffEqGPU.jl index 00ee068b..ee9ecd63 100644 --- a/src/DiffEqGPU.jl +++ b/src/DiffEqGPU.jl @@ -24,7 +24,7 @@ using Setfield using ForwardDiff import StaticArrays: StaticVecOrMat, @_inline_meta # import LinearAlgebra: \ -import StaticArrays: LU, StaticLUMatrix, arithmetic_closure +import StaticArrays: LU, StaticLUMatrix import SciMLBase: ImmutableODEProblem abstract type EnsembleArrayAlgorithm <: SciMLBase.EnsembleAlgorithm end diff --git a/test/qa/Project.toml b/test/qa/Project.toml index 2939dc85..dd6c0823 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -1,7 +1,17 @@ [deps] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DiffEqGPU = "071ae1c0-96b5-11e9-1965-c90190d839ea" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" +SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[compat] +Aqua = "0.8" +ForwardDiff = "1" +JET = "0.9, 0.10" +SciMLBase = "3.1" +SciMLTesting = "1.6" +StaticArrays = "1.9.14" diff --git a/test/qa/qa.jl b/test/qa/qa.jl new file mode 100644 index 00000000..366203b7 --- /dev/null +++ b/test/qa/qa.jl @@ -0,0 +1,71 @@ +using SciMLTesting, DiffEqGPU, Test +using JET + +run_qa( + DiffEqGPU; + explicit_imports = true, + ei_kwargs = (; + # StaticVecOrMat is re-exported by StaticArrays but owned by StaticArraysCore, + # which is not a direct dependency. + all_explicit_imports_via_owners = (; ignore = (:StaticVecOrMat,)), + # SciMLBase abstract types/traits re-exported through DiffEqBase, accessed as + # DiffEqBase.; DiffEqBase is the natural import point here. + all_qualified_accesses_via_owners = (; + ignore = ( + :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractSDEAlgorithm, + :has_jac, :has_tgrad, + ), + ), + # Non-public names from upstream packages (SciMLBase, DiffEqBase, ForwardDiff, + # LinearSolve, SimpleDiffEq, LinearAlgebra, Adapt, Random, Base/Core); these + # become public as those base libraries declare `public`. + all_qualified_accesses_are_public = (; + ignore = ( + # SciMLBase + :AbstractContinuousCallback, :AbstractDEAlgorithm, + :AbstractDiscreteCallback, :AbstractEnsembleProblem, + :AbstractJumpProblem, :AbstractODEProblem, :DEFAULT_REDUCTION, + :Default, :EnsembleAlgorithm, :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, + :LeftRootFind, :NoRootFind, :RootfindOpt, :Success, :T, :Terminated, + :__solve, :_unwrap_val, :build_linear_solution, :build_solution, + :default_rng_func, :generate_sim_seeds, :has_initialization_data, + :is_diagonal_noise, :solve_batch, :specialization, + :successful_retcode, :tighten_container_eltype, + # SciMLBase + DiffEqBase + :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractSDEAlgorithm, + :has_jac, :has_tgrad, + # DiffEqBase + :ODE_DEFAULT_NORM, :RecursiveArrayTools, :find_callback_time, + :find_first_continuous_callback, :get_condition, + # ForwardDiff + :Chunk, :Dual, :Partials, :construct_seeds, :derivative, :jacobian, + :npartials, :partials, :value, + # LinearSolve + :LinearCache, :SciMLLinearSolveAlgorithm, :init_cacheval, + :needs_concrete_A, + # SimpleDiffEq + :_build_atsit5_caches, :_build_tsit5_caches, :bθs, + # LinearAlgebra + :HermOrSym, + # Adapt + :adapt_structure, + # Random + :seed!, + # Base / Core + :Compiler, :Fix2, :return_type, + ), + ), + # Non-public names imported from upstream packages (StaticArrays internals, + # SciMLBase.ImmutableODEProblem). + all_explicit_imports_are_public = (; + ignore = ( + :var"@_inline_meta", :ImmutableODEProblem, :LU, :StaticLUMatrix, + :StaticVecOrMat, + ), + ), + ), + # ~75 names implicitly imported via heavy `using` of KernelAbstractions/SciMLBase/ + # DiffEqBase/StaticArrays/... ; making them explicit is a large refactor. + # https://github.com/SciML/DiffEqGPU.jl/issues/466 + ei_broken = (:no_implicit_imports,), +) diff --git a/test/runtests.jl b/test/runtests.jl index 0ef9fe74..2987b8a6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -24,9 +24,13 @@ if GROUP == "QA" Pkg.activate(joinpath(@__DIR__, "qa")) Pkg.develop(Pkg.PackageSpec(path = dirname(@__DIR__))) Pkg.instantiate() + @time @safetestset "Quality Assurance" begin + include("qa/qa.jl") + end @time @safetestset "JET static analysis" begin include("jet_tests.jl") end + exit() end @time @safetestset "GPU Kernelized Stiff ODE Mass Matrix" begin From 23aa27c2527835e4a163685ae845351397f20c05 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 26 Jun 2026 15:19:50 -0400 Subject: [PATCH 2/4] QA: sweep redundant public-API EI ignores after base-lib make-public releases SciMLTesting 1.7.0 now runs check_all_qualified_accesses_are_public and check_all_explicit_imports_are_public only on Julia >= 1.11 (skipped on lts), and several base libs declared more names public (SciMLBase 3.24.0 etc.). Removed 11 now-redundant entries from all_qualified_accesses_are_public: AbstractDEAlgorithm, AbstractODEProblem, build_solution, successful_retcode (now public in SciMLBase 3.24.0); Default, Success, T, Terminated (no longer accessed); Fix2 (public in Base); adapt_structure (Adapt), seed! (Random) (no longer flagged against registered releases). Bumped qa env compat: SciMLTesting "1.6"->"1.7", SciMLBase "3.1"->"3.24". Verified against registered releases (no dev): Julia 1.12 QA group 17 pass / 1 broken / 0 fail (public-API checks pass with the surviving minimal ignore-list); Julia 1.10 QA group 15 pass / 1 broken / 0 fail (public-API checks skipped on lts). The surviving ignores name genuine internals of SciMLBase/DiffEqBase/ForwardDiff/LinearSolve/SimpleDiffEq/LinearAlgebra/Core that are still non-public in the registered releases. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/qa/Project.toml | 4 ++-- test/qa/qa.jl | 28 +++++++++++----------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/test/qa/Project.toml b/test/qa/Project.toml index dd6c0823..ef000843 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -12,6 +12,6 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Aqua = "0.8" ForwardDiff = "1" JET = "0.9, 0.10" -SciMLBase = "3.1" -SciMLTesting = "1.6" +SciMLBase = "3.24" +SciMLTesting = "1.7" StaticArrays = "1.9.14" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 366203b7..93ab1e7c 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -17,20 +17,18 @@ run_qa( ), ), # Non-public names from upstream packages (SciMLBase, DiffEqBase, ForwardDiff, - # LinearSolve, SimpleDiffEq, LinearAlgebra, Adapt, Random, Base/Core); these - # become public as those base libraries declare `public`. + # LinearSolve, SimpleDiffEq, LinearAlgebra, Core); these become public as those + # base libraries declare `public`. all_qualified_accesses_are_public = (; ignore = ( # SciMLBase - :AbstractContinuousCallback, :AbstractDEAlgorithm, - :AbstractDiscreteCallback, :AbstractEnsembleProblem, - :AbstractJumpProblem, :AbstractODEProblem, :DEFAULT_REDUCTION, - :Default, :EnsembleAlgorithm, :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, - :LeftRootFind, :NoRootFind, :RootfindOpt, :Success, :T, :Terminated, - :__solve, :_unwrap_val, :build_linear_solution, :build_solution, - :default_rng_func, :generate_sim_seeds, :has_initialization_data, - :is_diagonal_noise, :solve_batch, :specialization, - :successful_retcode, :tighten_container_eltype, + :AbstractContinuousCallback, :AbstractDiscreteCallback, + :AbstractEnsembleProblem, :AbstractJumpProblem, :DEFAULT_REDUCTION, + :EnsembleAlgorithm, :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, + :LeftRootFind, :NoRootFind, :RootfindOpt, :__solve, :_unwrap_val, + :build_linear_solution, :default_rng_func, :generate_sim_seeds, + :has_initialization_data, :is_diagonal_noise, :solve_batch, + :specialization, :tighten_container_eltype, # SciMLBase + DiffEqBase :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractSDEAlgorithm, :has_jac, :has_tgrad, @@ -47,12 +45,8 @@ run_qa( :_build_atsit5_caches, :_build_tsit5_caches, :bθs, # LinearAlgebra :HermOrSym, - # Adapt - :adapt_structure, - # Random - :seed!, - # Base / Core - :Compiler, :Fix2, :return_type, + # Core + :Compiler, :return_type, ), ), # Non-public names imported from upstream packages (StaticArrays internals, From cfd56c55a2f9e9abc7010db082f772d11e336b9c Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 27 Jun 2026 00:11:13 -0400 Subject: [PATCH 3/4] QA: migrate SciMLBase-owned accesses to SciMLBase, strip now-public EI ignores After the base-library make-public releases (SciMLBase 3.27.0, DiffEqBase 7.6.0, SciMLTesting 1.7.0), finish the public-API ExplicitImports cleanup: - Caller-migrate `DiffEqBase.X` -> `SciMLBase.X` for the SciMLBase-owned names (AbstractODEAlgorithm, AbstractSDEAlgorithm, AbstractODEIntegrator, has_jac, has_tgrad) now that SciMLBase is the owner. `using SciMLBase` is already in the module and SciMLBase is already a [deps] entry. This makes `all_qualified_accesses_via_owners` pass for those names via the owner. - Bump the QA env SciMLBase compat floor to 3.27 so the released make-public versions are admitted. - Empty and re-derive the two public-API ignore tuples (`all_qualified_accesses_are_public`, `all_explicit_imports_are_public`) against the registered releases on Julia 1.12 (where these checks run). Names that became public are dropped (AbstractEnsembleProblem, AbstractJumpProblem, is_diagonal_noise, AbstractODEAlgorithm, AbstractSDEAlgorithm, has_jac, ImmutableODEProblem, ODE_DEFAULT_NORM, find_callback_time, find_first_continuous_callback, get_condition); names still non-public are kept (SciMLBase internals incl. AbstractODEIntegrator/ has_tgrad, ForwardDiff, LinearSolve, SimpleDiffEq, LinearAlgebra, Core internals, the DiffEqBase RecursiveArrayTools re-export, StaticArrays internals). Verified the QA group against the registered releases (no dev of base libs): Julia 1.12 (public-API checks active): 17 Pass, 1 Broken (the known `no_implicit_imports` ei_broken), 0 errored, 0 failed. Julia 1.10 (public-API checks skipped per SciMLTesting 1.7): 15 Pass, 1 Broken, 0 errored, 0 failed. `no_implicit_imports` (ei_broken, #466) and the `*_via_owners` ignores are left untouched. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- src/DiffEqGPU.jl | 4 +-- .../integrators/integrator_utils.jl | 28 ++++++++-------- .../integrators/nonstiff/interpolants.jl | 2 +- .../integrators/nonstiff/types.jl | 12 +++---- .../integrators/stiff/types.jl | 20 +++++------ src/ensemblegpukernel/nlsolve/type.jl | 4 +-- test/qa/Project.toml | 2 +- test/qa/qa.jl | 33 ++++++++----------- 8 files changed, 49 insertions(+), 56 deletions(-) diff --git a/src/DiffEqGPU.jl b/src/DiffEqGPU.jl index ee9ecd63..fa749653 100644 --- a/src/DiffEqGPU.jl +++ b/src/DiffEqGPU.jl @@ -31,8 +31,8 @@ abstract type EnsembleArrayAlgorithm <: SciMLBase.EnsembleAlgorithm end abstract type EnsembleKernelAlgorithm <: SciMLBase.EnsembleAlgorithm end ##Solvers for EnsembleGPUKernel -abstract type GPUODEAlgorithm <: DiffEqBase.AbstractODEAlgorithm end -abstract type GPUSDEAlgorithm <: DiffEqBase.AbstractSDEAlgorithm end +abstract type GPUODEAlgorithm <: SciMLBase.AbstractODEAlgorithm end +abstract type GPUSDEAlgorithm <: SciMLBase.AbstractSDEAlgorithm end abstract type GPUODEImplicitAlgorithm{AD} <: GPUODEAlgorithm end include("ensemblegpuarray/callbacks.jl") diff --git a/src/ensemblegpukernel/integrators/integrator_utils.jl b/src/ensemblegpukernel/integrators/integrator_utils.jl index f8302b44..1216bca5 100644 --- a/src/ensemblegpukernel/integrators/integrator_utils.jl +++ b/src/ensemblegpukernel/integrators/integrator_utils.jl @@ -11,7 +11,7 @@ function build_adaptive_controller_cache(alg::A, ::Type{T}) where {A, T} end @inline function savevalues!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, @@ -50,7 +50,7 @@ end end @inline function DiffEqBase.terminate!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, @@ -67,7 +67,7 @@ end end @inline function apply_discrete_callback!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, @@ -91,7 +91,7 @@ end end @inline function apply_discrete_callback!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, @@ -111,7 +111,7 @@ end end @inline function apply_discrete_callback!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, @@ -137,7 +137,7 @@ end end @inline function apply_discrete_callback!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, @@ -156,7 +156,7 @@ end end @inline function interpolate( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, @@ -176,7 +176,7 @@ end end @inline function _change_t_via_interpolation!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, @@ -205,7 +205,7 @@ end end end @inline function DiffEqBase.change_t_via_interpolation!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, @@ -227,7 +227,7 @@ end end @inline function apply_callback!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, }, @@ -272,7 +272,7 @@ end end @inline function handle_callbacks!( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, }, @@ -384,7 +384,7 @@ end end @inline function DiffEqBase.find_callback_time( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, @@ -442,7 +442,7 @@ end end @inline function SciMLBase.get_tmp_cache( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, @@ -458,7 +458,7 @@ end end @inline function DiffEqBase.get_condition( - integrator::DiffEqBase.AbstractODEIntegrator{ + integrator::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, diff --git a/src/ensemblegpukernel/integrators/nonstiff/interpolants.jl b/src/ensemblegpukernel/integrators/nonstiff/interpolants.jl index a2ce9d40..a72811cb 100644 --- a/src/ensemblegpukernel/integrators/nonstiff/interpolants.jl +++ b/src/ensemblegpukernel/integrators/nonstiff/interpolants.jl @@ -1,7 +1,7 @@ # Default: Hermite Interpolation @inline @muladd function _ode_interpolant( Θ, dt, y₀, - integ::DiffEqBase.AbstractODEIntegrator{ + integ::SciMLBase.AbstractODEIntegrator{ AlgType, IIP, S, T, } diff --git a/src/ensemblegpukernel/integrators/nonstiff/types.jl b/src/ensemblegpukernel/integrators/nonstiff/types.jl index 7a1c4737..7df0fce3 100644 --- a/src/ensemblegpukernel/integrators/nonstiff/types.jl +++ b/src/ensemblegpukernel/integrators/nonstiff/types.jl @@ -1,7 +1,7 @@ ## Fixed TimeStep Integrator mutable struct GPUTsit5Integrator{IIP, S, T, ST, P, F, TS, CB, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -52,7 +52,7 @@ DiffEqBase.isinplace(::GPUT5I{IIP}) where {IIP} = IIP ## Adaptive TimeStep Integrator mutable struct GPUATsit5Integrator{IIP, S, T, ST, P, F, N, TOL, Q, TS, CB, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -108,7 +108,7 @@ end ## Vern7 mutable struct GPUV7Integrator{IIP, S, T, ST, P, F, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -152,7 +152,7 @@ const GPUV7I = GPUV7Integrator end mutable struct GPUAV7Integrator{IIP, S, T, ST, P, F, N, TOL, Q, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -205,7 +205,7 @@ end ## Vern9 mutable struct GPUV9Integrator{IIP, S, T, ST, P, F, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -249,7 +249,7 @@ const GPUV9I = GPUV9Integrator end mutable struct GPUAV9Integrator{IIP, S, T, ST, P, F, N, TOL, Q, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state diff --git a/src/ensemblegpukernel/integrators/stiff/types.jl b/src/ensemblegpukernel/integrators/stiff/types.jl index 96bf1772..b63e601f 100644 --- a/src/ensemblegpukernel/integrators/stiff/types.jl +++ b/src/ensemblegpukernel/integrators/stiff/types.jl @@ -1,5 +1,5 @@ mutable struct GPURosenbrock23Integrator{IIP, S, T, ST, P, F, TS, CB, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -77,7 +77,7 @@ mutable struct GPUARosenbrock23Integrator{ CB, AlgType, } <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -181,7 +181,7 @@ end ########################## # Fixed Step mutable struct GPURodas4Integrator{IIP, S, T, ST, P, F, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -268,7 +268,7 @@ mutable struct GPUARodas4Integrator{ TabType, AlgType, } <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -370,7 +370,7 @@ end ########################## # Fixed Step mutable struct GPURodas5PIntegrator{IIP, S, T, ST, P, F, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -449,7 +449,7 @@ mutable struct GPUARodas5PIntegrator{ IIP, S, T, ST, P, F, N, TOL, Q, TS, CB, TabType, AlgType, } <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -553,7 +553,7 @@ end ########################## # Fixed Step mutable struct GPUKvaerno3Integrator{IIP, S, T, ST, P, F, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -632,7 +632,7 @@ mutable struct GPUAKvaerno3Integrator{ IIP, S, T, ST, P, F, N, TOL, Q, TS, CB, TabType, AlgType, } <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -735,7 +735,7 @@ end ########################## # Fixed Step mutable struct GPUKvaerno5Integrator{IIP, S, T, ST, P, F, TS, CB, TabType, AlgType} <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state @@ -814,7 +814,7 @@ mutable struct GPUAKvaerno5Integrator{ IIP, S, T, ST, P, F, N, TOL, Q, TS, CB, TabType, AlgType, } <: - DiffEqBase.AbstractODEIntegrator{AlgType, IIP, S, T} + SciMLBase.AbstractODEIntegrator{AlgType, IIP, S, T} alg::AlgType f::F # eom uprev::S # previous state diff --git a/src/ensemblegpukernel/nlsolve/type.jl b/src/ensemblegpukernel/nlsolve/type.jl index cf861755..33aca977 100644 --- a/src/ensemblegpukernel/nlsolve/type.jl +++ b/src/ensemblegpukernel/nlsolve/type.jl @@ -53,7 +53,7 @@ end @inline function build_J_W(alg, f, γ, dt) J(u, p, t) = - if DiffEqBase.has_jac(f) + if SciMLBase.has_jac(f) f.jac(u, p, t) elseif alg_autodiff(alg) ForwardDiff.jacobian(u -> f(u, p, t), u) @@ -66,7 +66,7 @@ end @inline function build_tgrad(alg, f) function tgrad(u, p, t) - return if DiffEqBase.has_tgrad(f) + return if SciMLBase.has_tgrad(f) f.tgrad(u, p, t) elseif alg_autodiff(alg) ForwardDiff.derivative(t -> f(u, p, t), t) diff --git a/test/qa/Project.toml b/test/qa/Project.toml index ef000843..cf69ad9b 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -12,6 +12,6 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Aqua = "0.8" ForwardDiff = "1" JET = "0.9, 0.10" -SciMLBase = "3.24" +SciMLBase = "3.27" SciMLTesting = "1.7" StaticArrays = "1.9.14" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 93ab1e7c..8edc0597 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -16,25 +16,20 @@ run_qa( :has_jac, :has_tgrad, ), ), - # Non-public names from upstream packages (SciMLBase, DiffEqBase, ForwardDiff, - # LinearSolve, SimpleDiffEq, LinearAlgebra, Core); these become public as those - # base libraries declare `public`. + # Non-public names from upstream packages; these become public as those base + # libraries declare `public` (verified flagged against the registered releases + # on Julia 1.12, where these checks run). all_qualified_accesses_are_public = (; ignore = ( - # SciMLBase + # SciMLBase (owned here, but not yet declared public) :AbstractContinuousCallback, :AbstractDiscreteCallback, - :AbstractEnsembleProblem, :AbstractJumpProblem, :DEFAULT_REDUCTION, - :EnsembleAlgorithm, :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, - :LeftRootFind, :NoRootFind, :RootfindOpt, :__solve, :_unwrap_val, - :build_linear_solution, :default_rng_func, :generate_sim_seeds, - :has_initialization_data, :is_diagonal_noise, :solve_batch, - :specialization, :tighten_container_eltype, - # SciMLBase + DiffEqBase - :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractSDEAlgorithm, - :has_jac, :has_tgrad, - # DiffEqBase - :ODE_DEFAULT_NORM, :RecursiveArrayTools, :find_callback_time, - :find_first_continuous_callback, :get_condition, + :AbstractODEIntegrator, :DEFAULT_REDUCTION, :EnsembleAlgorithm, + :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, :LeftRootFind, :NoRootFind, + :RootfindOpt, :__solve, :_unwrap_val, :build_linear_solution, + :default_rng_func, :generate_sim_seeds, :has_initialization_data, + :has_tgrad, :solve_batch, :specialization, :tighten_container_eltype, + # DiffEqBase (the RecursiveArrayTools re-export module) + :RecursiveArrayTools, # ForwardDiff :Chunk, :Dual, :Partials, :construct_seeds, :derivative, :jacobian, :npartials, :partials, :value, @@ -49,12 +44,10 @@ run_qa( :Compiler, :return_type, ), ), - # Non-public names imported from upstream packages (StaticArrays internals, - # SciMLBase.ImmutableODEProblem). + # Non-public names imported from upstream packages (StaticArrays internals). all_explicit_imports_are_public = (; ignore = ( - :var"@_inline_meta", :ImmutableODEProblem, :LU, :StaticLUMatrix, - :StaticVecOrMat, + :var"@_inline_meta", :LU, :StaticLUMatrix, :StaticVecOrMat, ), ), ), From 047589cf215e85d1d7708c9962330ca3539f68bc Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Mon, 29 Jun 2026 07:06:00 -0400 Subject: [PATCH 4/4] QA: minimize ExplicitImports exceptions (real fixes, not ignores) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate the `:no_implicit_imports` ei_broken blanket (which hid 72 names) by making every implicit import explicit, and trim the qualified-access / explicit-import ignore lists to the genuinely-irreducible residuals. Root fixes (drop ignore, no behavior change): - Make all 72 implicit `using X` names explicit `using X: a, b, ...`; add CommonSolve, StaticArraysCore, UnPack as direct deps (true owners of `solve`, the Static* aliases, and `@unpack`). Drops `:no_implicit_imports`. - Migrate `DiffEqBase.RecursiveArrayTools.recursive_bottom_eltype` to the public `RecursiveArrayTools.recursive_bottom_eltype` (RAT is a direct dep). - Define a local `_unwrap_val` (the SciMLBase internal is `_`-prefixed and won't be publicized) and drop the SciMLBase qualification + ignore. - Drop the now-empty `all_qualified_accesses_via_owners` list and the now-public SciMLBase names (EnsembleAlgorithm/has_tgrad/AbstractODEIntegrator/ has_initialization_data) from `all_qualified_accesses_are_public` (public in SciMLBase 3.30); bump qa-env SciMLBase compat to 3.30. Remaining exceptions are genuine non-public upstream APIs (ForwardDiff differentiation, LinearSolve cache/algorithm extension, SimpleDiffEq tableau internals, SciMLBase callback/rootfind/ensemble internals, LinearAlgebra HermOrSym, Core.Compiler.return_type with no cross-version public equivalent on the 1.10 LTS floor, and StaticArrays/StaticArraysCore/Base internals backing the vendored GPU LU/linsolve kernels) — each documented inline. Net qa.jl exception entries 51 -> 42. Verified GROUP=QA on Julia 1.12.6 (18/18 pass, all 6 EI checks green) and package load on Julia 1.10.11 LTS. Co-Authored-By: Chris Rackauckas --- Project.toml | 6 ++ src/DiffEqGPU.jl | 50 ++++++++++++----- src/ensemblegpukernel/alg_utils.jl | 2 +- src/ensemblegpukernel/gpukernel_algorithms.jl | 2 +- test/qa/Project.toml | 2 +- test/qa/qa.jl | 55 ++++++++----------- 6 files changed, 68 insertions(+), 49 deletions(-) diff --git a/Project.toml b/Project.toml index 98e3da68..8f2f62d7 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "3.15.1" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" @@ -23,7 +24,9 @@ Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46" SimpleDiffEq = "05bca326-078c-5bf0-a5bf-ce7c7982d7fd" SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" ZygoteRules = "700de1a5-db45-46bc-99cf-38207098b444" [weakdeps] @@ -47,6 +50,7 @@ AMDGPU = "2" Adapt = "4" CUDA = "5, 6" ChainRulesCore = "1" +CommonSolve = "0.2" DiffEqBase = "7" Distributed = "1" DocStringExtensions = "0.9" @@ -67,8 +71,10 @@ Setfield = "1" SimpleDiffEq = "1.11" SimpleNonlinearSolve = "2" StaticArrays = "1.9.14" +StaticArraysCore = "1.4" TOML = "1" Test = "1" +UnPack = "1" ZygoteRules = "0.2.7" julia = "1.10" oneAPI = "2" diff --git a/src/DiffEqGPU.jl b/src/DiffEqGPU.jl index fa749653..05194c71 100644 --- a/src/DiffEqGPU.jl +++ b/src/DiffEqGPU.jl @@ -3,28 +3,45 @@ $(DocStringExtensions.README) """ module DiffEqGPU -using DocStringExtensions -using KernelAbstractions +using DocStringExtensions: DocStringExtensions +using KernelAbstractions: KernelAbstractions, @Const, @index, @kernel, CPU import KernelAbstractions: get_backend, allocate -using SciMLBase, DiffEqBase, LinearAlgebra, Distributed -using ForwardDiff +using SciMLBase: SciMLBase, CallbackSet, CheckInit, ContinuousCallback, + DiscreteCallback, EnsembleDistributed, EnsembleProblem, + EnsembleSerial, EnsembleSolution, EnsembleThreads, ODEFunction, + ODEProblem, ReturnCode, SDEFunction, SDEProblem, + VectorContinuousCallback, remake, terminate! +using DiffEqBase: DiffEqBase, BrownFullBasicInit +using LinearAlgebra: LinearAlgebra, I, LowerTriangular, NoPivot, RowMaximum, + SingularException, UpperTriangular, det +using Distributed: Distributed, nprocs, pmap +using ForwardDiff: ForwardDiff import ChainRulesCore import ChainRulesCore: NoTangent -using RecursiveArrayTools +using RecursiveArrayTools: RecursiveArrayTools, VectorOfArray import ZygoteRules import Base.Threads -using LinearSolve -using SimpleNonlinearSolve +using Base: setindex +using CommonSolve: solve +using LinearSolve: LinearSolve +using SimpleNonlinearSolve: SimpleNonlinearSolve import SimpleNonlinearSolve: SimpleTrustRegion #For gpu_tsit5 -using Adapt, SimpleDiffEq, StaticArrays -using Parameters, MuladdMacro -using Random -using Setfield -using ForwardDiff -import StaticArrays: StaticVecOrMat, @_inline_meta -# import LinearAlgebra: \ -import StaticArrays: LU, StaticLUMatrix +using Adapt: Adapt, adapt +using SimpleDiffEq: SimpleDiffEq, GPUSimpleATsit5, GPUSimpleAVern7, GPUSimpleAVern9, + GPUSimpleTsit5, GPUSimpleVern7, GPUSimpleVern9, SimpleEM +using StaticArrays: StaticArrays +using StaticArraysCore: MArray, MMatrix, SArray, SMatrix, SVector, Size, + StaticMatrix, StaticVector, similar_type +using Parameters: Parameters +using MuladdMacro: MuladdMacro, @muladd +using Random: Random +using Setfield: Setfield, @set, @set! +using UnPack: @unpack +# StaticArraysCore-owned type alias (re-exported by StaticArrays); used in dispatch. +import StaticArrays: StaticVecOrMat +# Non-public StaticArrays internals used by the vendored GPU LU/linsolve kernels. +import StaticArrays: @_inline_meta, LU, StaticLUMatrix import SciMLBase: ImmutableODEProblem abstract type EnsembleArrayAlgorithm <: SciMLBase.EnsembleAlgorithm end @@ -35,6 +52,9 @@ abstract type GPUODEAlgorithm <: SciMLBase.AbstractODEAlgorithm end abstract type GPUSDEAlgorithm <: SciMLBase.AbstractSDEAlgorithm end abstract type GPUODEImplicitAlgorithm{AD} <: GPUODEAlgorithm end +_unwrap_val(B) = B +_unwrap_val(::Val{B}) where {B} = B + include("ensemblegpuarray/callbacks.jl") include("ensemblegpuarray/kernels.jl") include("ensemblegpuarray/problem_generation.jl") diff --git a/src/ensemblegpukernel/alg_utils.jl b/src/ensemblegpukernel/alg_utils.jl index b9701aaa..6ceb1c41 100644 --- a/src/ensemblegpukernel/alg_utils.jl +++ b/src/ensemblegpukernel/alg_utils.jl @@ -15,7 +15,7 @@ alg_order(alg::GPUEM) = 1 alg_order(alg::GPUSIEA) = 2 function finite_diff_jac(f, jac_prototype, x) - dx = sqrt(eps(DiffEqBase.RecursiveArrayTools.recursive_bottom_eltype(x))) + dx = sqrt(eps(RecursiveArrayTools.recursive_bottom_eltype(x))) jac = MMatrix{size(x, 1), size(x, 1), eltype(x)}(1I) for i in eachindex(x) x_dx = convert(MArray, x) diff --git a/src/ensemblegpukernel/gpukernel_algorithms.jl b/src/ensemblegpukernel/gpukernel_algorithms.jl index ce6e4d3f..5d5dbfda 100644 --- a/src/ensemblegpukernel/gpukernel_algorithms.jl +++ b/src/ensemblegpukernel/gpukernel_algorithms.jl @@ -66,7 +66,7 @@ struct GPUKvaerno5{AD} <: GPUODEImplicitAlgorithm{AD} end for Alg in [:GPURosenbrock23, :GPURodas4, :GPURodas5P, :GPUKvaerno3, :GPUKvaerno5] @eval begin function $Alg(; autodiff = Val{true}()) - return $Alg{SciMLBase._unwrap_val(autodiff)}() + return $Alg{_unwrap_val(autodiff)}() end end end diff --git a/test/qa/Project.toml b/test/qa/Project.toml index cf69ad9b..9282b032 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -12,6 +12,6 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Aqua = "0.8" ForwardDiff = "1" JET = "0.9, 0.10" -SciMLBase = "3.27" +SciMLBase = "3.30" SciMLTesting = "1.7" StaticArrays = "1.9.14" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 8edc0597..f64083c1 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -5,54 +5,47 @@ run_qa( DiffEqGPU; explicit_imports = true, ei_kwargs = (; - # StaticVecOrMat is re-exported by StaticArrays but owned by StaticArraysCore, - # which is not a direct dependency. + # StaticVecOrMat is re-exported by StaticArrays but owned by StaticArraysCore. + # It is a non-public type alias used only in method-signature dispatch for the + # vendored GPU linear-solve kernels; importing it from its true owner would + # still leave it non-public, so the via-owners exception is the natural place. all_explicit_imports_via_owners = (; ignore = (:StaticVecOrMat,)), - # SciMLBase abstract types/traits re-exported through DiffEqBase, accessed as - # DiffEqBase.; DiffEqBase is the natural import point here. - all_qualified_accesses_via_owners = (; - ignore = ( - :AbstractODEAlgorithm, :AbstractODEIntegrator, :AbstractSDEAlgorithm, - :has_jac, :has_tgrad, - ), - ), - # Non-public names from upstream packages; these become public as those base - # libraries declare `public` (verified flagged against the registered releases - # on Julia 1.12, where these checks run). + # Non-public names accessed qualified from upstream packages. These are genuine + # internal/extension APIs; they will drop out of this list as those packages + # declare `public` (verified flagged against the registered releases on Julia + # 1.12, where these checks run). all_qualified_accesses_are_public = (; ignore = ( - # SciMLBase (owned here, but not yet declared public) + # SciMLBase callback/rootfind/ensemble internals (not yet `public`) :AbstractContinuousCallback, :AbstractDiscreteCallback, - :AbstractODEIntegrator, :DEFAULT_REDUCTION, :EnsembleAlgorithm, - :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, :LeftRootFind, :NoRootFind, - :RootfindOpt, :__solve, :_unwrap_val, :build_linear_solution, - :default_rng_func, :generate_sim_seeds, :has_initialization_data, - :has_tgrad, :solve_batch, :specialization, :tighten_container_eltype, - # DiffEqBase (the RecursiveArrayTools re-export module) - :RecursiveArrayTools, - # ForwardDiff + :DEFAULT_REDUCTION, :FINALIZE_DEFAULT, :INITIALIZE_DEFAULT, + :LeftRootFind, :NoRootFind, :RootfindOpt, :build_linear_solution, + :default_rng_func, :generate_sim_seeds, :solve_batch, + :specialization, :tighten_container_eltype, + # ForwardDiff differentiation API (documented but not `public`) :Chunk, :Dual, :Partials, :construct_seeds, :derivative, :jacobian, :npartials, :partials, :value, - # LinearSolve + # LinearSolve cache/algorithm extension interface (not `public`) :LinearCache, :SciMLLinearSolveAlgorithm, :init_cacheval, :needs_concrete_A, - # SimpleDiffEq + # SimpleDiffEq Tsit5 tableau-cache internals (not `public`) :_build_atsit5_caches, :_build_tsit5_caches, :bθs, - # LinearAlgebra + # LinearAlgebra Hermitian/Symmetric union (stdlib, not `public`) :HermOrSym, - # Core + # Core compiler inference used to size a Channel/Vector eltype; no + # public cross-version replacement (Base.infer_return_type is 1.11+, + # and the LTS floor is Julia 1.10). :Compiler, :return_type, ), ), - # Non-public names imported from upstream packages (StaticArrays internals). + # Non-public names imported explicitly from upstream packages. The + # StaticArrays/StaticArraysCore internals back the vendored GPU LU/linsolve + # kernels; `setindex` is the immutable Base helper used by the GPU LU pivot. all_explicit_imports_are_public = (; ignore = ( :var"@_inline_meta", :LU, :StaticLUMatrix, :StaticVecOrMat, + :StaticMatrix, :StaticVector, :similar_type, :setindex, ), ), ), - # ~75 names implicitly imported via heavy `using` of KernelAbstractions/SciMLBase/ - # DiffEqBase/StaticArrays/... ; making them explicit is a large refactor. - # https://github.com/SciML/DiffEqGPU.jl/issues/466 - ei_broken = (:no_implicit_imports,), )