From 6a172bd85af54e8cc811e150432db33761d3a439 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 8 Aug 2026 13:38:09 -0400 Subject: [PATCH] Strengthen public API documentation QA Co-Authored-By: Chris Rackauckas --- Project.toml | 4 +- docs/make.jl | 4 +- docs/src/array_types.md | 8 + docs/src/index.md | 4 + docs/src/plotting.md | 4 + docs/src/ragged_arrays.md | 3 + .../test/qa/Project.toml | 7 +- .../test/qa/qa.jl | 3 +- .../test/runtests.jl | 16 +- .../src/RecursiveArrayToolsRaggedArrays.jl | 78 +++++----- .../test/qa/Project.toml | 7 +- .../test/qa/qa.jl | 18 +-- .../test/runtests.jl | 16 +- .../test/qa/Project.toml | 7 +- .../test/qa/qa.jl | 3 +- .../test/runtests.jl | 16 +- src/RecursiveArrayTools.jl | 26 +++- src/array_partition.jl | 53 +++---- src/named_array_partition.jl | 16 +- src/precompilation.jl | 2 +- src/utils.jl | 140 ++++++++++++------ src/vector_of_array.jl | 131 ++++++++-------- test/Core/public_api_test.jl | 53 +++++++ test/QA/Project.toml | 2 +- test/QA/qa.jl | 5 - test/runtests.jl | 1 + 26 files changed, 363 insertions(+), 264 deletions(-) create mode 100644 test/Core/public_api_test.jl diff --git a/Project.toml b/Project.toml index 190c9c31..ebbf9687 100644 --- a/Project.toml +++ b/Project.toml @@ -6,7 +6,6 @@ version = "4.3.6" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" @@ -53,7 +52,6 @@ RecursiveArrayToolsZygoteExt = "Zygote" Adapt = "4" ArrayInterface = "7.17.0" CUDA = "5, 6.0" -DocStringExtensions = "0.9.3" FastBroadcast = "1.3" ForwardDiff = "0.10.38, 1" GPUArraysCore = "0.2" @@ -71,7 +69,7 @@ RecursiveArrayToolsShorthandConstructors = "1" ReverseDiff = "1.15" SafeTestsets = "0.1" SciMLPublic = "1" -SciMLTesting = "2.1" +SciMLTesting = "2.4" SparseArrays = "1.10" StaticArrays = "1.6" StaticArraysCore = "1.4.2" diff --git a/docs/make.jl b/docs/make.jl index 87628932..068a14e3 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -9,8 +9,8 @@ makedocs( sitename = "RecursiveArrayTools.jl", authors = "Chris Rackauckas", modules = [RecursiveArrayTools, RecursiveArrayToolsRaggedArrays], - clean = true, doctest = false, linkcheck = true, - warnonly = [:missing_docs], + clean = true, doctest = true, linkcheck = true, + checkdocs = :exports, format = Documenter.HTML( assets = ["assets/favicon.ico"], canonical = "https://docs.sciml.ai/RecursiveArrayTools/stable/" diff --git a/docs/src/array_types.md b/docs/src/array_types.md index 19f712a3..7926dc88 100644 --- a/docs/src/array_types.md +++ b/docs/src/array_types.md @@ -21,5 +21,13 @@ NamedArrayPartition ```@docs VA AP +``` + +## Developer Interfaces + +`AllObserved` is intended for packages extending symbolic indexing of differential-equation +arrays. Application code should use the ordinary symbolic indexing interface. + +```@docs AllObserved ``` diff --git a/docs/src/index.md b/docs/src/index.md index 777b696e..b8484be8 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,9 @@ # RecursiveArrayTools.jl: Arrays of Arrays and Even Deeper +```@docs +RecursiveArrayTools +``` + RecursiveArrayTools.jl is a set of tools for dealing with recursive arrays, like arrays of arrays. It contains type wrappers for making recursive arrays act more like normal arrays (for example, automating the recursion of broadcast, maps, diff --git a/docs/src/plotting.md b/docs/src/plotting.md index fb23b5ff..c3072743 100644 --- a/docs/src/plotting.md +++ b/docs/src/plotting.md @@ -155,6 +155,10 @@ when plotting solution objects. ## Plot Helper API +!!! warning "Developer API" + These helpers support plot recipe implementations in packages such as SciMLBase. Application + code should use the plotting interfaces described above instead of depending on these helpers. + ```@docs DEFAULT_PLOT_FUNC plottable_indices diff --git a/docs/src/ragged_arrays.md b/docs/src/ragged_arrays.md index d2a3c89f..0c6bcaa4 100644 --- a/docs/src/ragged_arrays.md +++ b/docs/src/ragged_arrays.md @@ -181,6 +181,9 @@ structure and access elements without implicit zeros. ## API Reference +The abstract types below are developer interfaces for packages implementing ragged containers. +Application code should construct `RaggedVectorOfArray` or `RaggedDiffEqArray`. + ```@docs RecursiveArrayTools.AbstractRaggedVectorOfArray RecursiveArrayTools.AbstractRaggedDiffEqArray diff --git a/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/Project.toml b/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/Project.toml index 9f55eb95..52cd3ef5 100644 --- a/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/Project.toml +++ b/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/Project.toml @@ -1,17 +1,16 @@ [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" RecursiveArrayToolsArrayPartitionAnyAll = "172d604e-c495-4f00-97bf-d70957099afa" SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -[sources] -RecursiveArrayToolsArrayPartitionAnyAll = {path = "../.."} - [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +RecursiveArrayTools = "4" RecursiveArrayToolsArrayPartitionAnyAll = "1" -SciMLTesting = "1.6, 2.1" +SciMLTesting = "2.4" Test = "1" julia = "1.10" diff --git a/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/qa.jl b/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/qa.jl index 330f6943..0e439704 100644 --- a/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/qa.jl +++ b/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/qa/qa.jl @@ -4,9 +4,8 @@ const RATAPAA = RecursiveArrayToolsArrayPartitionAnyAll run_qa( RATAPAA; - explicit_imports = true, # `any`/`all` are extended on the RecursiveArrayTools-owned `ArrayPartition` # type, so they are intentional (owned) methods, not piracy. aqua_kwargs = (; piracies = (; treat_as_own = [RATAPAA.ArrayPartition])), - jet_kwargs = (; target_defined_modules = true), + jet_kwargs = (; target_modules = (RATAPAA,)), ) diff --git a/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/runtests.jl b/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/runtests.jl index db8ee476..4f2aa9b6 100644 --- a/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/runtests.jl +++ b/lib/RecursiveArrayToolsArrayPartitionAnyAll/test/runtests.jl @@ -5,16 +5,12 @@ const TEST_GROUP = get(ENV, "RECURSIVEARRAYTOOLS_TEST_GROUP", "Core") function activate_qa_env() Pkg.activate(joinpath(@__DIR__, "qa")) - # On Julia < 1.11, the [sources] section in the qa Project.toml is not - # honored, so Pkg.develop the local paths explicitly. - if VERSION < v"1.11.0-DEV.0" - Pkg.develop( - [ - PackageSpec(path = dirname(@__DIR__)), - PackageSpec(path = normpath(joinpath(dirname(@__DIR__), "..", ".."))), - ] - ) - end + Pkg.develop( + [ + PackageSpec(path = dirname(@__DIR__)), + PackageSpec(path = normpath(joinpath(dirname(@__DIR__), "..", ".."))), + ] + ) return Pkg.instantiate() end diff --git a/lib/RecursiveArrayToolsRaggedArrays/src/RecursiveArrayToolsRaggedArrays.jl b/lib/RecursiveArrayToolsRaggedArrays/src/RecursiveArrayToolsRaggedArrays.jl index aaca7ef4..4b48e38b 100644 --- a/lib/RecursiveArrayToolsRaggedArrays/src/RecursiveArrayToolsRaggedArrays.jl +++ b/lib/RecursiveArrayToolsRaggedArrays/src/RecursiveArrayToolsRaggedArrays.jl @@ -4,12 +4,14 @@ import RecursiveArrayTools: RecursiveArrayTools, AbstractRaggedVectorOfArray, AbstractRaggedDiffEqArray, VectorOfArray, DiffEqArray, AbstractVectorOfArray, AbstractDiffEqArray, recursivefill!, recursivecopy! -using SymbolicIndexingInterface +import Adapt +import ArrayInterface +import StaticArraysCore +import SymbolicIndexingInterface using SymbolicIndexingInterface: ParameterTimeseriesCollection, ParameterIndexingProxy, - ScalarSymbolic, ArraySymbolic, NotSymbolic, Timeseries, SymbolCache -using Adapt -using ArrayInterface -using StaticArraysCore + ScalarSymbolic, ArraySymbolic, NotSymbolic, Timeseries, SymbolCache, + all_variable_symbols, getu, is_parameter, is_timeseries_parameter, observed, + parameter_values, symbolic_container, symbolic_type, variable_symbols using LinearAlgebra: Adjoint export RaggedVectorOfArray, RaggedDiffEqArray @@ -17,39 +19,22 @@ export RaggedVectorOfArray, RaggedDiffEqArray # Based on code from M. Bauman Stackexchange answer + Gitter discussion """ -```julia -RaggedVectorOfArray(u::AbstractVector) -``` - -A `RaggedVectorOfArray` is an array which has the underlying data structure `Vector{AbstractArray{T}}` -(but, hopefully, concretely typed!). This wrapper over such data structures allows one to lazily -act like it's a higher-dimensional vector, and easily convert it to different forms. The indexing -structure is: - -```julia -A.u[i] # Returns the ith array in the vector of arrays -A[j, i] # Returns the jth component in the ith array -A[j1, ..., jN, i] # Returns the (j1,...,jN) component of the ith array -``` + RaggedVectorOfArray(u::AbstractVector) -which presents itself as a column-major matrix with the columns being the arrays from the vector. -The `AbstractArray` interface is implemented, giving access to `copy`, `push`, `append!`, etc. functions, -which act appropriately. Points to note are: +Wrap a collection of arrays while preserving each array's shape. Unlike `VectorOfArray`, +this type does not present zero-padded ragged data as a rectangular `AbstractArray`. - - The length is the number of vectors, or `length(A.u)` where `u` is the vector of arrays. - - Iteration follows the linear index and goes over the vectors +# Fields -Additionally, the `convert(Array,VA::AbstractRaggedVectorOfArray)` function is provided, which transforms -the `RaggedVectorOfArray` into a matrix/tensor. Also, `vecarr_to_vectors(VA::AbstractRaggedVectorOfArray)` -returns a vector of the series for each component, that is, `A[i,:]` for each `i`. +- `u`: the collection of stored arrays. -There is also support for `RaggedVectorOfArray` constructed from multi-dimensional arrays +# Examples ```julia -RaggedVectorOfArray(u::AbstractArray{AT}) where {T, N, AT <: AbstractArray{T, N}} +A = RaggedVectorOfArray([[1, 2], [3, 4, 5]]) +A[:, 1] == [1, 2] +A[end, 2] == 5 ``` - -where `IndexStyle(typeof(u)) isa IndexLinear`. """ mutable struct RaggedVectorOfArray{T, N, A} <: AbstractRaggedVectorOfArray{T, N, A} u::A # A <: AbstractArray{<: AbstractArray{T, N - 1}} @@ -57,23 +42,28 @@ end # RaggedVectorOfArray with an added series for time """ -```julia -RaggedDiffEqArray(u::AbstractVector, t::AbstractVector) -``` + RaggedDiffEqArray(u::AbstractVector, t::AbstractVector; kwargs...) + +Wrap ragged saved states `u` and matching time points `t` with differential-equation and +symbolic-indexing metadata. + +# Fields -This is a `RaggedVectorOfArray`, which stores `A.t` that matches `A.u`. This will plot -`(A.t[i],A[i,:])`. The function `tuples(diffeq_arr)` returns tuples of `(t,u)`. +- `u`: the saved ragged state arrays. +- `t`: the time corresponding to each entry of `u`. +- `p`: parameter values associated with the solution. +- `sys`: symbolic indexing metadata. +- `discretes`: discrete parameter timeseries, or `nothing`. +- `interp`: interpolation object for dense output, or `nothing`. +- `dense`: whether dense interpolation is available. -To construct a RaggedDiffEqArray +# Examples ```julia -t = 0.0:0.1:10.0 -f(t) = t - 1 -f2(t) = t^2 -vals = [[f(tval) f2(tval)] for tval in t] -A = RaggedDiffEqArray(vals, t) -A[1, :] # all time periods for f(t) -A.t +t = [0.0, 1.0] +u = [[1.0, 2.0], [3.0, 4.0, 5.0]] +A = RaggedDiffEqArray(u, t) +A[:, 2] == [3.0, 4.0, 5.0] ``` """ mutable struct RaggedDiffEqArray{ diff --git a/lib/RecursiveArrayToolsRaggedArrays/test/qa/Project.toml b/lib/RecursiveArrayToolsRaggedArrays/test/qa/Project.toml index 7a1d2cea..e03ace5e 100644 --- a/lib/RecursiveArrayToolsRaggedArrays/test/qa/Project.toml +++ b/lib/RecursiveArrayToolsRaggedArrays/test/qa/Project.toml @@ -1,17 +1,16 @@ [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" RecursiveArrayToolsRaggedArrays = "c384ba91-639a-44ca-823a-e1d3691ab84a" SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -[sources] -RecursiveArrayToolsRaggedArrays = {path = "../.."} - [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +RecursiveArrayTools = "4" RecursiveArrayToolsRaggedArrays = "1" -SciMLTesting = "1.6, 2.1" +SciMLTesting = "2.4" Test = "1" julia = "1.10" diff --git a/lib/RecursiveArrayToolsRaggedArrays/test/qa/qa.jl b/lib/RecursiveArrayToolsRaggedArrays/test/qa/qa.jl index 96e7f46e..f43eec28 100644 --- a/lib/RecursiveArrayToolsRaggedArrays/test/qa/qa.jl +++ b/lib/RecursiveArrayToolsRaggedArrays/test/qa/qa.jl @@ -2,7 +2,6 @@ using SciMLTesting, RecursiveArrayToolsRaggedArrays, JET, Test run_qa( RecursiveArrayToolsRaggedArrays; - explicit_imports = true, # The arithmetic/array methods (`*`, `+`, `Array`, `copyto!`, ...) are defined on # the RecursiveArrayTools-owned `AbstractRaggedVectorOfArray` / # `AbstractRaggedDiffEqArray` abstract types, so they are intentional (owned) @@ -15,23 +14,17 @@ run_qa( ], ), ), - jet_kwargs = (; target_defined_modules = true), + jet_kwargs = (; target_modules = (RecursiveArrayToolsRaggedArrays,)), # Pre-existing JET typo-mode finding (reproduces byte-identically on master): # the `copyto!`/`fill!`/broadcast immutable-element branches call # `StaticArraysCore.similar_type(dest.u[i])`, but `dest.u[i]` infers as `::Any` # because the abstract `AbstractRaggedVectorOfArray` `.u` field is untyped, so # `similar_type(::Any)` has no matching method. Tracked (with the real fix — # tightening the `.u` type / guarding the immutable branch) in - # https://github.com/SciML/RecursiveArrayTools.jl/issues/620. `jet_broken` - # auto-flags an Unexpected Pass once that fix lands, prompting removal. - jet_broken = true, + # https://github.com/SciML/RecursiveArrayTools.jl/issues/620. JET 0.9 on Julia + # 1.10 does not report this finding, so keep that stricter lane unbroken. + jet_broken = VERSION >= v"1.11", ei_kwargs = (; - # `AbstractRaggedVectorOfArray`/`AbstractRaggedDiffEqArray` are - # RecursiveArrayTools-owned abstract types this subpackage subtypes; they are - # not (yet) declared public in RecursiveArrayTools. - all_explicit_imports_are_public = (; - ignore = (:AbstractRaggedVectorOfArray, :AbstractRaggedDiffEqArray), - ), # Non-public names legitimately qualified/imported from upstream packages # (Base, Base.Broadcast, StaticArraysCore, ArrayInterface, Adapt, # SymbolicIndexingInterface). Not this subpackage's to make public. @@ -47,7 +40,4 @@ run_qa( ), ), ), - # Whole-module `using` exposes many names implicitly; explicit-import refactor - # tracked in https://github.com/SciML/RecursiveArrayTools.jl/issues/619 - ei_broken = (:no_implicit_imports,), ) diff --git a/lib/RecursiveArrayToolsRaggedArrays/test/runtests.jl b/lib/RecursiveArrayToolsRaggedArrays/test/runtests.jl index ea4e55cf..2c56aa4e 100644 --- a/lib/RecursiveArrayToolsRaggedArrays/test/runtests.jl +++ b/lib/RecursiveArrayToolsRaggedArrays/test/runtests.jl @@ -9,16 +9,12 @@ const TEST_GROUP = get(ENV, "RECURSIVEARRAYTOOLS_TEST_GROUP", "Core") function activate_qa_env() Pkg.activate(joinpath(@__DIR__, "qa")) - # On Julia < 1.11, the [sources] section in the qa Project.toml is not - # honored, so Pkg.develop the local paths explicitly. - if VERSION < v"1.11.0-DEV.0" - Pkg.develop( - [ - PackageSpec(path = dirname(@__DIR__)), - PackageSpec(path = normpath(joinpath(dirname(@__DIR__), "..", ".."))), - ] - ) - end + Pkg.develop( + [ + PackageSpec(path = dirname(@__DIR__)), + PackageSpec(path = normpath(joinpath(dirname(@__DIR__), "..", ".."))), + ] + ) return Pkg.instantiate() end diff --git a/lib/RecursiveArrayToolsShorthandConstructors/test/qa/Project.toml b/lib/RecursiveArrayToolsShorthandConstructors/test/qa/Project.toml index df06bf36..f0f201e2 100644 --- a/lib/RecursiveArrayToolsShorthandConstructors/test/qa/Project.toml +++ b/lib/RecursiveArrayToolsShorthandConstructors/test/qa/Project.toml @@ -1,17 +1,16 @@ [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" RecursiveArrayToolsShorthandConstructors = "39fb7555-b4ad-4efd-8abe-30331df017d3" SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -[sources] -RecursiveArrayToolsShorthandConstructors = {path = "../.."} - [compat] Aqua = "0.8" JET = "0.9, 0.10, 0.11" +RecursiveArrayTools = "4" RecursiveArrayToolsShorthandConstructors = "1" -SciMLTesting = "1.6, 2.1" +SciMLTesting = "2.4" Test = "1" julia = "1.10" diff --git a/lib/RecursiveArrayToolsShorthandConstructors/test/qa/qa.jl b/lib/RecursiveArrayToolsShorthandConstructors/test/qa/qa.jl index d9e5e6ed..86e1e643 100644 --- a/lib/RecursiveArrayToolsShorthandConstructors/test/qa/qa.jl +++ b/lib/RecursiveArrayToolsShorthandConstructors/test/qa/qa.jl @@ -4,10 +4,9 @@ const RATSC = RecursiveArrayToolsShorthandConstructors run_qa( RATSC; - explicit_imports = true, # `getindex(::Type{VA}, ...)` / `getindex(::Type{AP}, ...)` extend Base on # RecursiveArrayTools-owned types, so they are intentional (owned) methods, # not piracy. aqua_kwargs = (; piracies = (; treat_as_own = [RATSC.VA, RATSC.AP])), - jet_kwargs = (; target_defined_modules = true), + jet_kwargs = (; target_modules = (RATSC,)), ) diff --git a/lib/RecursiveArrayToolsShorthandConstructors/test/runtests.jl b/lib/RecursiveArrayToolsShorthandConstructors/test/runtests.jl index 612959b1..c708d4df 100644 --- a/lib/RecursiveArrayToolsShorthandConstructors/test/runtests.jl +++ b/lib/RecursiveArrayToolsShorthandConstructors/test/runtests.jl @@ -5,16 +5,12 @@ const TEST_GROUP = get(ENV, "RECURSIVEARRAYTOOLS_TEST_GROUP", "Core") function activate_qa_env() Pkg.activate(joinpath(@__DIR__, "qa")) - # On Julia < 1.11, the [sources] section in the qa Project.toml is not - # honored, so Pkg.develop the local paths explicitly. - if VERSION < v"1.11.0-DEV.0" - Pkg.develop( - [ - PackageSpec(path = dirname(@__DIR__)), - PackageSpec(path = normpath(joinpath(dirname(@__DIR__), "..", ".."))), - ] - ) - end + Pkg.develop( + [ + PackageSpec(path = dirname(@__DIR__)), + PackageSpec(path = normpath(joinpath(dirname(@__DIR__), "..", ".."))), + ] + ) return Pkg.instantiate() end diff --git a/src/RecursiveArrayTools.jl b/src/RecursiveArrayTools.jl index a3436cac..e78f6451 100644 --- a/src/RecursiveArrayTools.jl +++ b/src/RecursiveArrayTools.jl @@ -1,14 +1,26 @@ __precompile__() """ -$(DocStringExtensions.README) + RecursiveArrayTools + +Array types and utilities for working with recursively nested arrays. The package +provides array-compatible wrappers such as [`VectorOfArray`](@ref), [`DiffEqArray`](@ref), +[`ArrayPartition`](@ref), and [`NamedArrayPartition`](@ref). """ module RecursiveArrayTools - using DocStringExtensions - using RecipesBase, StaticArraysCore, - ArrayInterface, LinearAlgebra - using SymbolicIndexingInterface + using ArrayInterface: ArrayInterface + using LinearAlgebra: LinearAlgebra, Adjoint, Factorization, I, LDLt, LU, + LowerTriangular, SymTridiagonal, Transpose, Tridiagonal, UnitLowerTriangular, + UnitUpperTriangular, UpperTriangular, ldiv!, mul! + using RecipesBase: RecipesBase, @recipe using SciMLPublic: @public + using StaticArraysCore: StaticArraysCore + using SymbolicIndexingInterface: SymbolicIndexingInterface, ArraySymbolic, + NotSymbolic, ParameterIndexingProxy, ParameterTimeseriesCollection, + ScalarSymbolic, SymbolCache, Timeseries, all_variable_symbols, getu, + independent_variable_symbols, is_parameter, is_timeseries_parameter, + observed, parameter_values, symbolic_container, symbolic_type, + variable_symbols import Adapt @@ -114,8 +126,8 @@ module RecursiveArrayTools the pairing `DiffEqArray([[1,2],[3,4]],[1.0,2.0])` which means that at time 1.0 the values were `[1,2]` and at time 2.0 the values were `[3,4]`. - An AbstractDiffEqArray has all of the same behaviors as an AbstractVectorOfArray with the - additional properties: + An AbstractDiffEqArray has all of the same behaviors as an AbstractVectorOfArray with + the additional properties: ## Fields diff --git a/src/array_partition.jl b/src/array_partition.jl index c0bf2cae..62ef7d77 100644 --- a/src/array_partition.jl +++ b/src/array_partition.jl @@ -1,27 +1,22 @@ """ -```julia -ArrayPartition(x::AbstractArray...) -``` + ArrayPartition(parts...) + +Wrap arrays with potentially different types as one linear `AbstractVector`. Indexing +traverses the partitions in order, while broadcasting operates partition-by-partition +without losing the individual array types. -An `ArrayPartition` `A` is an array, which is made up of different arrays `A.x`. -These index like a single array, but each subarray may have a different type. -However, broadcast is overloaded to loop in an efficient manner, meaning that -`A .+= 2.+B` is type-stable in its computations, even if `A.x[i]` and `A.x[j]` -do not match types. A full array interface is included for completeness, which -allows this array type to be used in place of a standard array where -such a type stable broadcast may be needed. One example is in heterogeneous -differential equations for [DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/stable/). +# Fields -An `ArrayPartition` acts like a single array. `A[i]` indexes through the first -array, then the second, etc., all linearly. But `A.x` is where the arrays are stored. -Thus, for: +- `x`: the tuple of stored arrays. + +# Examples ```julia -using RecursiveArrayTools -A = ArrayPartition(y, z) +A = ArrayPartition([1, 2], [3.0, 4.0]) +A[3] == 3.0 +A.x[1] == [1, 2] +collect(A) == [1.0, 2.0, 3.0, 4.0] ``` - -we would have `A.x[1]==y` and `A.x[2]==z`. Broadcasting like `f.(A)` is efficient. """ struct ArrayPartition{T, S <: Tuple} <: AbstractVector{T} x::S @@ -735,26 +730,18 @@ function Adapt.adapt_structure(to, ap::ArrayPartition) end """ -```julia -AP[ matrices, ] -``` + AP -Create an `ArrayPartition` using vector syntax. Equivalent to `ArrayPartition(matrices)`, but looks nicer with nesting. +Shorthand constructor marker for `ArrayPartition`. Load +`RecursiveArrayToolsShorthandConstructors` to enable `AP[parts...]` syntax. -# Examples: +# Examples -Simple examples: ```julia -ArrayPartition([1,2,3], [1 2;3 4]) == AP[[1,2,3], [1 2;3 4]] # true -AP[1u"m/s^2", 1u"m/s", 1u"m"] +using RecursiveArrayToolsShorthandConstructors +A = AP[[1, 2], [3.0, 4.0]] +A == ArrayPartition([1, 2], [3.0, 4.0]) ``` - -With an ODEProblem: -```julia -func(u, p, t) = AP[5u.x[1], u.x[2]./2] -ODEProblem(func, AP[ [1.,2.,3.], [1. 2.;3. 4.] ], (0, 1)) |> solve -``` - """ struct AP end diff --git a/src/named_array_partition.jl b/src/named_array_partition.jl index d88f1c13..40bee471 100644 --- a/src/named_array_partition.jl +++ b/src/named_array_partition.jl @@ -5,6 +5,14 @@ Similar to an `ArrayPartition` but the individual arrays can be accessed via the constructor-specified names. However, unlike `ArrayPartition`, each individual array must have the same element type. + +# Examples + +```julia +A = NamedArrayPartition(position = [1.0, 2.0], velocity = [3.0, 4.0]) +A.position == [1.0, 2.0] +collect(A) == [1.0, 2.0, 3.0, 4.0] +``` """ struct NamedArrayPartition{T, A <: ArrayPartition{T}, NT <: NamedTuple} <: AbstractVector{T} array_partition::A @@ -154,14 +162,14 @@ function Base.BroadcastStyle( end # hook into ArrayPartition broadcasting routines -@inline RecursiveArrayTools.npartitions(x::NamedArrayPartition) = npartitions(ArrayPartition(x)) -@inline RecursiveArrayTools.unpack( +@inline npartitions(x::NamedArrayPartition) = npartitions(ArrayPartition(x)) +@inline unpack( bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{NamedArrayPartition}}, i ) = Broadcast.Broadcasted( - bc.f, RecursiveArrayTools.unpack_args(i, bc.args) + bc.f, unpack_args(i, bc.args) ) -@inline RecursiveArrayTools.unpack(x::NamedArrayPartition, i) = unpack(ArrayPartition(x), i) +@inline unpack(x::NamedArrayPartition, i) = unpack(ArrayPartition(x), i) function Base.copy(A::NamedArrayPartition{T, S, NT}) where {T, S, NT} return NamedArrayPartition{T, S, NT}(copy(ArrayPartition(A)), getfield(A, :names_to_indices)) diff --git a/src/precompilation.jl b/src/precompilation.jl index f1ae301e..74e0eb3f 100644 --- a/src/precompilation.jl +++ b/src/precompilation.jl @@ -1,4 +1,4 @@ -using PrecompileTools +using PrecompileTools: @compile_workload, @setup_workload @setup_workload begin @compile_workload begin diff --git a/src/utils.jl b/src/utils.jl index dc91ebaf..0209140a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -2,12 +2,19 @@ unrolled_foreach!(f, t::Tuple) = (f(t[1]); unrolled_foreach!(f, Base.tail(t))) unrolled_foreach!(f, ::Tuple{}) = nothing """ + recursivecopy(a) + +Copy `a` recursively. This acts like `deepcopy` for nested arrays and like `copy` for +arrays of scalar values. + +# Examples + ```julia -recursivecopy(a::Union{AbstractArray{T, N}, AbstractVectorOfArray{T, N}}) +original = [[1, 2], [3, 4]] +copied = recursivecopy(original) +copied[1][1] = 10 +original[1][1] == 1 ``` - -A recursive `copy` function. Acts like a `deepcopy` on arrays of arrays, but -like `copy` on arrays of scalars. """ function recursivecopy(a) return deepcopy(a) @@ -54,14 +61,20 @@ function recursivecopy(a::AbstractVectorOfArray) end """ + recursivecopy!(dest, src) + +Copy `src` recursively into `dest`. This acts like `deepcopy!` for nested arrays and +like `copy!` for arrays of scalar values. `dest` and `src` must have matching +dimensionality; use [`recursivecopyto!`](@ref) for linear copying between different +shapes. + +# Examples + ```julia -recursivecopy!(b::AbstractArray{T, N}, a::AbstractArray{T, N}) +dest = [zeros(2), zeros(2)] +src = [[1.0, 2.0], [3.0, 4.0]] +recursivecopy!(dest, src) ``` - -A recursive `copy!` function. Acts like a `deepcopy!` on arrays of arrays, but -like `copy!` on arrays of scalars. Requires `b` and `a` to have matching `ndims`; -use [`recursivecopyto!`](@ref) for the `copyto!`-style linear-index variant that -allows mismatched shapes. """ function recursivecopy! end @@ -122,18 +135,20 @@ function recursivecopy!(b::AbstractVectorOfArray, a::AbstractVectorOfArray) end """ -```julia -recursivecopyto!(b::AbstractArray, a::AbstractArray) -``` + recursivecopyto!(dest, src) -> dest -A recursive `copyto!` function. Acts like a `deepcopy!` on arrays of arrays, but -like `copyto!` on arrays of scalars. +Copy `src` recursively into `dest` in linear, column-major order. This acts like +`deepcopy!` for nested arrays and like `copyto!` for arrays of scalar values. -Unlike [`recursivecopy!`](@ref), this does not require `b` and `a` to have matching -`ndims` or axes; only that `length(b) >= length(a)`. Elements are copied in linear -(column-major) order, matching the semantics of `Base.copyto!`. Use this when -flattening/reshaping between destination and source is intended, e.g. copying a -`Vector` into a `Matrix` of the same total length. +Unlike [`recursivecopy!`](@ref), this does not require matching dimensions or axes. +Use it when copying between different shapes is intentional. + +# Examples + +```julia +dest = zeros(2, 2) +recursivecopyto!(dest, [1.0, 2.0, 3.0, 4.0]) +``` """ function recursivecopyto! end @@ -184,11 +199,16 @@ function recursivecopyto!(b::AbstractVectorOfArray, a::AbstractVectorOfArray) end """ + recursivefill!(dest, value) + +Fill every scalar element of the nested container `dest` with `value`. + +# Examples + ```julia -recursivefill!(b::AbstractArray{T, N}, a) +dest = [zeros(2), zeros(3)] +recursivefill!(dest, 1.0) ``` - -A recursive `fill!` function. """ function recursivefill! end @@ -286,6 +306,12 @@ end Convert a vector of equal-length vectors into a dense matrix whose rows are the input vectors. + +# Examples + +```julia +vecvec_to_mat([[1, 2], [3, 4]]) == [1 2; 3 4] +``` """ function vecvec_to_mat(vecvec) mat = Matrix{eltype(eltype(vecvec))}(undef, length(vecvec), length(vecvec[1])) @@ -296,11 +322,15 @@ function vecvec_to_mat(vecvec) end """ + vecvecapply(f, v) + +Flatten the nested array `v` and call `f` on the resulting vector. + +# Examples + ```julia -vecvecapply(f::Base.Callable, v) +vecvecapply(sum, [[1, 2], [3, 4]]) == 10 ``` - -Calls `f` on each element of a vecvec `v`. """ function vecvecapply(f, v::AbstractArray{<:AbstractArray}) sol = Vector{eltype(eltype(v))}() @@ -323,12 +353,18 @@ function vecvecapply(f, v::T) where {T <: Number} end """ + copyat_or_push!(a, i, x[, perform_copy = true]) -> nothing + +Recursively copy `x` into `a[i]` when that element exists, or append a recursive copy +of `x` otherwise. Set `perform_copy = false` to assign or append `x` directly. + +# Examples + ```julia -copyat_or_push!{T}(a::AbstractVector{T}, i::Int, x) +values = [[1, 2]] +copyat_or_push!(values, 2, [3, 4]) +values == [[1, 2], [3, 4]] ``` - -If `i= i @@ -361,11 +397,15 @@ function copyat_or_push!( end """ + recursive_one(a) + +Return `one` for the scalar value at the bottom of the nested container `a`. + +# Examples + ```julia -recursive_one(a) +recursive_one([[2.0]]) == 1.0 ``` - -Calls `one` on the bottom container to get the "true element one type". """ recursive_one(a) = recursive_one(a[1]) recursive_one(a::T) where {T <: Number} = one(a) @@ -375,16 +415,25 @@ recursive_one(a::T) where {T <: Number} = one(a) Return the scalar element type at the bottom of nested array-like element types. + +# Examples + +```julia +recursive_bottom_eltype(Vector{Vector{Float32}}) === Float32 +``` """ recursive_bottom_eltype(a) = a == eltype(a) ? a : recursive_bottom_eltype(eltype(a)) """ + recursive_unitless_bottom_eltype(a) + +Return the unitless scalar type at the bottom of the nested container type `a`. + +# Examples + ```julia -recursive_unitless_bottom_eltype(a) +recursive_unitless_bottom_eltype(Vector{Vector{Float64}}) === Float64 ``` - -Grabs the unitless element type at the bottom of the chain. For example, if -ones has a `Array{Array{Float64,N},N}`, this will return `Float64`. """ recursive_unitless_bottom_eltype(a) = recursive_unitless_bottom_eltype(typeof(a)) recursive_unitless_bottom_eltype(a::Type{Any}) = Any @@ -400,12 +449,9 @@ end recursive_unitless_bottom_eltype(::Type{<:Enum{T}}) where {T} = T """ -```julia -recursive_unitless_eltype(a) -``` + recursive_unitless_eltype(a) -Grabs the unitless element type. For example, if -ones has a `Array{Array{Float64,N},N}`, this will return `Array{Float64,N}`. +Return the element type of `a` after recursively removing units from its scalar type. """ recursive_unitless_eltype(a) = recursive_unitless_eltype(eltype(a)) recursive_unitless_eltype(a::Type{Any}) = Any @@ -425,6 +471,12 @@ recursive_unitless_eltype(::Type{<:Enum{T}}) where {T} = T Compute a mean value through recursive array containers without requiring `Statistics.mean`. + +# Examples + +```julia +recursive_mean([[1.0, 3.0], [3.0, 5.0]]) == [2.0, 4.0] +``` """ function recursive_mean(vecvec::Vector{T}) where {T <: AbstractArray} out = zero(vecvec[1]) @@ -458,7 +510,9 @@ end Iterate through any number of iterators in sequence. ```jldoctest -julia> for i in chain(1:3, ['a', 'b', 'c']) +julia> using RecursiveArrayTools + +julia> for i in RecursiveArrayTools.chain(1:3, ['a', 'b', 'c']) @show i end i = 1 diff --git a/src/vector_of_array.jl b/src/vector_of_array.jl index 39c9f752..088f893a 100644 --- a/src/vector_of_array.jl +++ b/src/vector_of_array.jl @@ -1,40 +1,25 @@ # Based on code from M. Bauman Stackexchange answer + Gitter discussion """ -```julia -VectorOfArray(u::AbstractVector) -``` - -A `VectorOfArray` is an array which has the underlying data structure `Vector{AbstractArray{T}}` -(but, hopefully, concretely typed!). This wrapper over such data structures allows one to lazily -act like it's a higher-dimensional vector, and easily convert it to different forms. The indexing -structure is: - -```julia -A.u[i] # Returns the ith array in the vector of arrays -A[j, i] # Returns the jth component in the ith array -A[j1, ..., jN, i] # Returns the (j1,...,jN) component of the ith array -``` + VectorOfArray(u::AbstractVector) -which presents itself as a column-major matrix with the columns being the arrays from the vector. -The `AbstractArray` interface is implemented, giving access to `copy`, `push`, `append!`, etc. functions, -which act appropriately. Points to note are: +Wrap a collection of equally shaped or ragged arrays as one column-major `AbstractArray` +without materializing a dense concatenation. The last index selects an inner array: +`A[j, i]` accesses component `j` of `A.u[i]`, while `A.u[i]` returns the stored +array itself. - - The length is the number of vectors, or `length(A.u)` where `u` is the vector of arrays. - - Iteration follows the linear index and goes over the vectors +# Fields -Additionally, the `convert(Array,VA::AbstractVectorOfArray)` function is provided, which transforms -the `VectorOfArray` into a matrix/tensor. Also, `vecarr_to_vectors(VA::AbstractVectorOfArray)` -returns a vector of the series for each component, that is, `A[i,:]` for each `i`. -A plot recipe is provided, which plots the `A[i,:]` series. +- `u`: the collection of stored arrays. -There is also support for `VectorOfArray` constructed from multi-dimensional arrays +# Examples ```julia -VectorOfArray(u::AbstractArray{AT}) where {T, N, AT <: AbstractArray{T, N}} +A = VectorOfArray([[1, 2], [3, 4]]) +size(A) == (2, 2) +A[2, 1] == 2 +Array(A) == [1 3; 2 4] ``` - -where `IndexStyle(typeof(u)) isa IndexLinear`. """ mutable struct VectorOfArray{T, N, A} <: AbstractVectorOfArray{T, N, A} u::A # A <: AbstractArray{<: AbstractArray{T, N - 1}} @@ -42,23 +27,29 @@ end # VectorOfArray with an added series for time """ -```julia -DiffEqArray(u::AbstractVector, t::AbstractVector) -``` + DiffEqArray(u::AbstractVector, t::AbstractVector; kwargs...) + +Wrap saved state arrays `u` and matching time points `t` as an `AbstractDiffEqArray`. +The result supports the `VectorOfArray` interface and stores metadata used for symbolic +indexing, interpolation, and plotting. -This is a `VectorOfArray`, which stores `A.t` that matches `A.u`. This will plot -`(A.t[i],A[i,:])`. The function `tuples(diffeq_arr)` returns tuples of `(t,u)`. +# Fields -To construct a DiffEqArray +- `u`: the saved state arrays. +- `t`: the time corresponding to each entry of `u`. +- `p`: parameter values associated with the solution. +- `sys`: symbolic indexing metadata. +- `discretes`: discrete parameter timeseries, or `nothing`. +- `interp`: interpolation object for dense output, or `nothing`. +- `dense`: whether dense interpolation is available. + +# Examples ```julia -t = 0.0:0.1:10.0 -f(t) = t - 1 -f2(t) = t^2 -vals = [[f(tval) f2(tval)] for tval in t] -A = DiffEqArray(vals, t) -A[1, :] # all time periods for f(t) -A.t +t = [0.0, 0.5, 1.0] +u = [[sin(ti), cos(ti)] for ti in t] +A = DiffEqArray(u, t) +A[1, :] == sin.(t) ``` """ mutable struct DiffEqArray{ @@ -78,8 +69,9 @@ end """ AllObserved() -Sentinel used by symbolic indexing paths to request all observed variables from -an `AbstractDiffEqArray`. +Sentinel used by symbolic indexing implementations to request all observed variables from +an `AbstractDiffEqArray`. This is a developer interface for packages extending symbolic +indexing. """ struct AllObserved end @@ -947,6 +939,13 @@ end tuples(A::DiffEqArray) Return the saved time/state pairs of `A` as `(t, u)` tuples. + +# Examples + +```julia +A = DiffEqArray([[1.0], [2.0]], [0.0, 1.0]) +tuples(A) == [(0.0, [1.0]), (1.0, [2.0])] +``` """ tuples(VA::DiffEqArray) = tuple.(VA.t, VA.u) @@ -1148,6 +1147,13 @@ end vecarr_to_vectors(A::AbstractVectorOfArray) Collect the component time series of `A` as one vector per component. + +# Examples + +```julia +A = VectorOfArray([[1, 2], [3, 4]]) +vecarr_to_vectors(A) == [[1, 3], [2, 4]] +``` """ vecarr_to_vectors(VA::AbstractVectorOfArray) = [VA[i, :] for i in eachindex(VA.u[1])] # linear algebra @@ -1191,7 +1197,7 @@ end DEFAULT_PLOT_FUNC(x, y, z) Default transformation used by plotting helpers when no custom plotting -function is supplied. +function is supplied. This is a developer interface for plot recipe implementations. """ DEFAULT_PLOT_FUNC(x, y) = (x, y) DEFAULT_PLOT_FUNC(x, y, z) = (x, y, z) @@ -1200,6 +1206,8 @@ DEFAULT_PLOT_FUNC(x, y, z) = (x, y, z) plottable_indices(x) Return the default component indices to plot for `x`. + +This is a developer interface for plot recipe implementations. """ plottable_indices(x::AbstractArray) = 1:length(x) plottable_indices(x::Number) = 1 @@ -1209,6 +1217,8 @@ plottable_indices(x::Number) = 1 Return the index iterator used when expanding array-valued data into plot series. + +This is a developer interface for plot recipe implementations. """ plot_indices(A::AbstractArray) = eachindex(A) @@ -1216,6 +1226,8 @@ plot_indices(A::AbstractArray) = eachindex(A) getindepsym_defaultt(A) Return the independent variable symbol for `A`, defaulting to `:t`. + +This is a developer interface for plot recipe implementations. """ function getindepsym_defaultt(A) syms = independent_variable_symbols(A) @@ -1228,6 +1240,8 @@ end Normalize user-provided variable specifications into a standard internal format: a list of tuples `(func, xvar, yvar[, zvar])`. Index `0` represents the independent variable (time). + +This is a developer interface for plot recipe implementations. """ function interpret_vars(vars, A) if vars === nothing @@ -1305,6 +1319,8 @@ end add_labels!(labels, x, dims, A, strs) Append the plot label for the variable tuple `x` to `labels`. + +This is a developer interface for plot recipe implementations. """ function add_labels!(labels, x, dims, A, strs) if ((x[2] isa Integer && x[2] == 0) || isequal(x[2], getindepsym_defaultt(A))) && @@ -1322,6 +1338,8 @@ end diffeq_to_arrays(A, denseplot, plotdensity, tspan, vars, tscale, plotat) Convert an `AbstractDiffEqArray` into plot-ready arrays. Returns `(plot_vecs, labels)`. + +This is a developer interface for plot recipe implementations. """ function diffeq_to_arrays( A, denseplot, plotdensity, tspan, vars, tscale, plotat @@ -1364,6 +1382,8 @@ end Build plot vectors and labels for interpreted plotting variables over the sample points `plott`. + +This is a developer interface for plot recipe implementations. """ function solplot_vecs_and_labels(dims, vars, plott, A) plot_vecs = [] @@ -1643,28 +1663,17 @@ unpack_args_voa(i, args::Tuple{Any}) = (unpack_voa(args[1], i),) unpack_args_voa(::Any, args::Tuple{}) = () """ -```julia -VA[ matrices, ] -``` + VA -Create an `VectorOfArray` using vector syntax. Equivalent to `VectorOfArray([matrices])`, but looks nicer with nesting. +Shorthand constructor marker for `VectorOfArray`. Load +`RecursiveArrayToolsShorthandConstructors` to enable `VA[arrays...]` syntax. -# Simple example: -```julia -VectorOfArray([[1,2,3], [1 2;3 4]]) == VA[[1,2,3], [1 2;3 4]] # true -``` +# Examples -# All the layers: ```julia -nested = VA[ - fill(1, 2, 3), - VA[ - VA[8, [1, 2, 3], [1 2;3 4], VA[1, 2, 3]], - fill(2, 3, 4), - VA[3ones(3), zeros(3)], - ], -] +using RecursiveArrayToolsShorthandConstructors +A = VA[[1, 2], [3, 4]] +A == VectorOfArray([[1, 2], [3, 4]]) ``` - """ struct VA end diff --git a/test/Core/public_api_test.jl b/test/Core/public_api_test.jl new file mode 100644 index 00000000..b41f610d --- /dev/null +++ b/test/Core/public_api_test.jl @@ -0,0 +1,53 @@ +using RecursiveArrayTools +using RecursiveArrayToolsShorthandConstructors +using Test + +@testset "Documented constructors and utilities" begin + vector_of_array = VectorOfArray([[1, 2], [3, 4]]) + @test size(vector_of_array) == (2, 2) + @test Array(vector_of_array) == [1 3; 2 4] + @test vecarr_to_vectors(vector_of_array) == [[1, 3], [2, 4]] + + diffeq_array = DiffEqArray([[1.0], [2.0]], [0.0, 1.0]) + @test tuples(diffeq_array) == [(0.0, [1.0]), (1.0, [2.0])] + + partition = ArrayPartition([1, 2], [3.0, 4.0]) + @test collect(partition) == [1.0, 2.0, 3.0, 4.0] + @test AP[[1, 2], [3.0, 4.0]] == partition + @test VA[[1, 2], [3, 4]] == vector_of_array + + named_partition = NamedArrayPartition( + position = [1.0, 2.0], velocity = [3.0, 4.0] + ) + @test named_partition.position == [1.0, 2.0] + @test vecvec_to_mat([[1, 2], [3, 4]]) == [1 2; 3 4] + + values = [[1, 2]] + copyat_or_push!(values, 2, [3, 4]) + @test values == [[1, 2], [3, 4]] + @test recursive_one([[2.0]]) == 1.0 +end + +@testset "Plot recipe developer interface" begin + A = DiffEqArray([[1.0, 2.0], [3.0, 4.0]], [0.0, 1.0]) + + @test DEFAULT_PLOT_FUNC(1, 2) == (1, 2) + @test DEFAULT_PLOT_FUNC(1, 2, 3) == (1, 2, 3) + @test plottable_indices([1, 2]) == 1:2 + @test plottable_indices(1) == 1 + @test plot_indices([1, 2]) == eachindex([1, 2]) + @test getindepsym_defaultt(A) == :t + + vars = interpret_vars(nothing, A) + @test vars == [(DEFAULT_PLOT_FUNC, 0, 1), (DEFAULT_PLOT_FUNC, 0, 2)] + + labels = String[] + @test add_labels!(labels, vars[1], 2, A, ["t", "u[1]"]) === labels + @test labels == ["u[1]"] + + plot_vecs, plot_labels = diffeq_to_arrays( + A, false, 100, nothing, vars, :identity, nothing + ) + @test plot_vecs == [[0.0 0.0; 1.0 1.0], [1.0 2.0; 3.0 4.0]] + @test plot_labels == ["u[1]", "u[2]"] +end diff --git a/test/QA/Project.toml b/test/QA/Project.toml index 2d93261c..f68a98ac 100644 --- a/test/QA/Project.toml +++ b/test/QA/Project.toml @@ -9,6 +9,6 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Aqua = "0.8" Pkg = "1" RecursiveArrayTools = "4" -SciMLTesting = "2.1" +SciMLTesting = "2.4" Test = "1" julia = "1.10" diff --git a/test/QA/qa.jl b/test/QA/qa.jl index 7cdf4e24..cacca4a1 100644 --- a/test/QA/qa.jl +++ b/test/QA/qa.jl @@ -9,8 +9,6 @@ end run_qa( RecursiveArrayTools; - explicit_imports = true, - api_docs_kwargs = (; rendered = true), # Method-table ambiguities tracked in # https://github.com/SciML/RecursiveArrayTools.jl/issues/326 aqua_broken = (:ambiguities,), @@ -31,7 +29,4 @@ run_qa( ), ), ), - # Whole-module `using` exposes many names implicitly; explicit-import refactor - # tracked in https://github.com/SciML/RecursiveArrayTools.jl/issues/619 - ei_broken = (:no_implicit_imports,), ) diff --git a/test/runtests.jl b/test/runtests.jl index a0fe285f..1c949610 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -19,6 +19,7 @@ run_tests(; @time @safetestset "Partitions and StaticArrays Tests" include("Core/partitions_and_static_arrays.jl") @time @safetestset "VecOfArr Indexing Tests" include("Core/basic_indexing.jl") @time @safetestset "VecOfArr Interface Tests" include("Core/interface_tests.jl") + @time @safetestset "Public API Tests" include("Core/public_api_test.jl") @time @safetestset "Table traits" include("Core/tabletraits.jl") @time @safetestset "StaticArrays Tests" include("Core/copy_static_array_test.jl") @time @safetestset "Linear Algebra Tests" include("Core/linalg.jl")