diff --git a/.github/workflows/TestLTS.yml b/.github/workflows/TestLTS.yml new file mode 100644 index 0000000..33dc030 --- /dev/null +++ b/.github/workflows/TestLTS.yml @@ -0,0 +1,57 @@ +name: Test v1.6 (LTS) + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + paths: + - 'src/**' + - 'test/**' + - '.github/workflows/Test.yml' + - 'Project.toml' + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + julia-version: ['1.6'] + julia-arch: [x64] + os: [ubuntu-latest, windows-latest] + experimental: [false] + + steps: + # Checks-out your repository + - name: Check out repository + uses: actions/checkout@v3 + + # Set up Julia + - name: "Set up Julia" + uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.julia-version }} + arch: ${{ matrix.julia-arch }} + + # Set up cache + - name: "Set up cache" + uses: actions/cache@v3 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + + # Build package + - name: "Build package" + uses: julia-actions/julia-buildpkg@v1 + + # Run the tests + - name: "Run tests" + uses: julia-actions/julia-runtest@v1 diff --git a/.github/workflows/Test.yml b/.github/workflows/TestLatest.yml similarity index 87% rename from .github/workflows/Test.yml rename to .github/workflows/TestLatest.yml index 91a9d9b..06da0c5 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/TestLatest.yml @@ -1,4 +1,4 @@ -name: Run Tests +name: Test v1 (latest) on: workflow_dispatch: @@ -9,7 +9,7 @@ on: paths: - 'src/**' - 'test/**' - - '.github/**' + - '.github/workflows/Test.yml' - 'Project.toml' jobs: @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - julia-version: ['1.6', '1'] + julia-version: ['1'] julia-arch: [x64] os: [ubuntu-latest, windows-latest] experimental: [false] @@ -35,7 +35,7 @@ jobs: version: ${{ matrix.julia-version }} arch: ${{ matrix.julia-arch }} - # Set up cache + # Set up cache - name: "Set up cache" uses: actions/cache@v3 env: @@ -47,7 +47,7 @@ jobs: ${{ runner.os }}-test-${{ env.cache-name }}- ${{ runner.os }}-test- ${{ runner.os }}- - + # Build package - name: "Build package" uses: julia-actions/julia-buildpkg@v1 @@ -62,6 +62,8 @@ jobs: # Run codecov - name: "Run CodeCov" - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: file: lcov.info diff --git a/Project.toml b/Project.toml index 6bb08fb..db86218 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FMIImport" uuid = "9fcbc62e-52a0-44e9-a616-1359a0008194" authors = ["TT ", "LM ", "JK "] -version = "1.0.4" +version = "1.0.5" [deps] Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" diff --git a/README.md b/README.md index 41b51d8..87f0ba5 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ [![Dev Docs](https://img.shields.io/badge/docs-dev-blue.svg)](https://thummeto.github.io/FMI.jl/dev/) -[![Run Tests](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/Test.yml/badge.svg)](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/Test.yml) +[![Test (latest)](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/TestLatest.yml/badge.svg)](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/TestLatest.yml) +[![Test (LTS)](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/TestLTS.yml/badge.svg)](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/TestLTS.yml) [![Run PkgEval](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/Eval.yml/badge.svg)](https://github.com/ThummeTo/FMIImport.jl/actions/workflows/Eval.yml) [![Coverage](https://codecov.io/gh/ThummeTo/FMIImport.jl/branch/main/graph/badge.svg)](https://app.codecov.io/gh/ThummeTo/FMIImport.jl) [![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac) diff --git a/src/FMI2/md.jl b/src/FMI2/md.jl index 5eb44bd..7afb2a8 100644 --- a/src/FMI2/md.jl +++ b/src/FMI2/md.jl @@ -437,6 +437,7 @@ end # ToDo: Comment function parseDerivatives(md::fmi2ModelDescription, nodes::EzXML.Node) @assert (nodes.name == "Derivatives") "Wrong element name." + md.modelStructure.derivatives = [] for node in eachelement(nodes) if node.name == "Unknown" @@ -463,6 +464,8 @@ function parseDerivatives(md::fmi2ModelDescription, nodes::EzXML.Node) @warn "Unknown entry in `ModelStructure.Derivatives` named `$(node.name)`." end end + + nothing end # ToDo: Comment diff --git a/src/FMIImport.jl b/src/FMIImport.jl index 5e21755..f318ad2 100644 --- a/src/FMIImport.jl +++ b/src/FMIImport.jl @@ -19,7 +19,6 @@ import FMIBase.ChainRulesCore: ignore_derivatives using RelocatableFolders import FMIBase: EzXML -include("convert.jl") include("zip.jl") include("binary.jl") include("md_parse.jl") diff --git a/src/binary.jl b/src/binary.jl index 76f53b4..8f60623 100644 --- a/src/binary.jl +++ b/src/binary.jl @@ -59,6 +59,7 @@ function loadFMU( unpackPath::Union{String,Nothing} = nothing, cleanup::Bool = true, type::Union{Symbol,Nothing} = nothing, + kwargs... ) unzippedAbsPath, zipAbsPath = @@ -72,11 +73,11 @@ function loadFMU( version = root["fmiVersion"] if version == "1.0" - @assert false "FMI version 1.0 deteted, this is (currently) not supported by FMI.jl." + @assert false "FMI version 1.0 detected, this is (currently) not supported by FMI.jl." elseif version == "2.0" - return createFMU2(unzippedAbsPath, zipAbsPath; type = type) + return createFMU2(unzippedAbsPath, zipAbsPath; type = type, kwargs...) elseif version == "3.0" - return createFMU3(unzippedAbsPath, zipAbsPath; type = type) + return createFMU3(unzippedAbsPath, zipAbsPath; type = type, kwargs...) else @assert false, "Unknwon FMI version `$(version)`." end @@ -113,7 +114,7 @@ function unloadFMU(fmu::FMU2, cleanUp::Bool = true; secure_pointers::Bool = true end # the components are removed from the component list via call to fmi2FreeInstance! - @assert length(fmu.components) == 0 "fmi2Unload(...): Failure during deleting components, $(length(fmu.components)) remaining in stack." + @assert length(fmu.components) == 0 "unloadFMU(fmu::FMU2, ...): Failure during deleting components, $(length(fmu.components)) remaining in stack." if secure_pointers unloadPointers(fmu) @@ -139,7 +140,7 @@ function unloadFMU(fmu::FMU3, cleanUp::Bool = true) dlclose(fmu.libHandle) # the instances are removed from the instances list via call to fmi3FreeInstance! - @assert length(fmu.instances) == 0 "fmi3Unload(...): Failure during deleting instances, $(length(fmu.instances)) remaining in stack." + @assert length(fmu.instances) == 0 "unloadFMU(fmu::FMU3, ...): Failure during deleting instances, $(length(fmu.instances)) remaining in stack." if cleanUp try diff --git a/src/convert.jl b/src/convert.jl deleted file mode 100644 index c8a9c23..0000000 --- a/src/convert.jl +++ /dev/null @@ -1,207 +0,0 @@ -# -# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher -# Licensed under the MIT license. See LICENSE file in the project root for details. -# - -""" - getState(solution::FMUSolution, i::fmi2ValueReferenceFormat; isIndex::Bool=false) - -Returns the solution state for a given value reference `i` (for `isIndex=false`) or the i-th state (for `isIndex=true`). -""" -function getState( - solution::FMUSolution, - vrs::fmi2ValueReferenceFormat; - isIndex::Bool = false, -) - - indices = [] - - if isIndex - if length(vrs) == 1 - indices = [vrs] - else - indices = vrs - end - else - ignore_derivatives() do - vrs = prepareValueReference(solution.component.fmu, vrs) - - if !isnothing(solution.states) - for vr in vrs - found = false - for i = - 1:length( - solution.component.fmu.modelDescription.stateValueReferences, - ) - if solution.component.fmu.modelDescription.stateValueReferences[i] == - vr - push!(indices, i) - found = true - break - end - end - @assert found "Couldn't find the index for value reference `$(vr)`! This is probaly because this value reference does not belong to a system state." - end - end - - end # ignore_derivatives - end - - # found something - if length(indices) == length(vrs) - - if length(vrs) == 1 # single value - return collect(u[indices[1]] for u in solution.states.u) - - else # multi value - return collect( - collect(u[indices[i]] for u in solution.states.u) for i = 1:length(indices) - ) - - end - end - - return nothing -end -export getState - -""" - getStateDerivative(solution::FMUSolution, i::fmi2ValueReferenceFormat; isIndex::Bool=false) - -Returns the solution state derivative for a given value reference `i` (for `isIndex=false`) or the i-th state (for `isIndex=true`). -""" -function getStateDerivative( - solution::FMUSolution, - vrs::fmi2ValueReferenceFormat; - isIndex::Bool = false, - order::Integer = 1, -) - indices = [] - - if isIndex - if length(vrs) == 1 - indices = [vrs] - else - indices = vrs - end - else - ignore_derivatives() do - vrs = prepareValueReference(solution.component.fmu, vrs) - - if !isnothing(solution.states) - for vr in vrs - found = false - for i = - 1:length( - solution.component.fmu.modelDescription.stateValueReferences, - ) - if solution.component.fmu.modelDescription.stateValueReferences[i] == - vr - push!(indices, i) - found = true - break - end - end - @assert found "Couldn't find the index for value reference `$(vr)`! This is probaly because this value reference does not belong to a system state." - end - end - - end # ignore_derivatives - end - - # found something - if length(indices) == length(vrs) - - if length(vrs) == 1 # single value - return collect( - solution.states(t, Val{order})[indices[1]] for t in solution.states.t - ) - - else # multi value - return collect( - collect( - solution.states(t, Val{order})[indices[i]] for t in solution.states.t - ) for i = 1:length(indices) - ) - end - end - - return nothing -end -export getStateDerivative - -""" - getValue(solution::FMU2Solution, i::fmi2ValueReferenceFormat; isIndex::Bool=false) - -Returns the values for a given value reference `i` (for `isIndex=false`) or the i-th value (for `isIndex=true`). -Recording of values must be enabled. -""" -function FMIBase.getValue( - solution::FMUSolution, - vrs::fmi2ValueReferenceFormat; - isIndex::Bool = false, -) - - indices = [] - - if isIndex - if length(vrs) == 1 - indices = [vrs] - else - indices = vrs - end - else - ignore_derivatives() do - vrs = prepareValueReference(solution.component.fmu, vrs) - - if !isnothing(solution.values) - for vr in vrs - found = false - for i = 1:length(solution.valueReferences) - if solution.valueReferences[i] == vr - push!(indices, i) - found = true - break - end - end - @assert found "Couldn't find the index for value reference `$(vr)`! This is probaly because this value reference does not exist for this system." - end - end - - end # ignore_derivatives - end - - # found something - if length(indices) == length(vrs) - - if length(vrs) == 1 # single value - return collect(u[indices[1]] for u in solution.values.saveval) - - else # multi value - return collect( - collect(u[indices[i]] for u in solution.values.saveval) for - i = 1:length(indices) - ) - - end - end - - return nothing -end -export getValue - -""" - getTime(solution::FMU2Solution) - -Returns the points in time of the solution `solution`. -""" -function getTime(solution::FMUSolution) - if !isnothing(solution.states) - return solution.states.t - elseif !isnothing(solution.values) - return solution.values.t - else - return nothing - end -end -export getTime diff --git a/src/info.jl b/src/info.jl index b472e2c..c553040 100644 --- a/src/info.jl +++ b/src/info.jl @@ -11,13 +11,11 @@ function printValueReferences(fmu, vrs; max = 10) println("\t\t$(vr) $(valueReferenceToString(fmu, vr))") end else - half = floor(Integer, max) - 1 + half = floor(Integer, max/2) - 1 for vr in vrs[1:half] println("\t\t$(vr) $(valueReferenceToString(fmu, vr))") end - println(".") - println(".") - println(".") + println("\t\t...") for vr in vrs[len-half:end] println("\t\t$(vr) $(valueReferenceToString(fmu, vr))") end @@ -63,7 +61,7 @@ function info(fmu::FMU2) println("\tStates:\t\t\t\t$(length(fmu.modelDescription.stateValueReferences))") printValueReferences(fmu, fmu.modelDescription.stateValueReferences) - println("\tParameters:\t\t\t\t$(length(fmu.modelDescription.parameterValueReferences))") + println("\tParameters:\t\t\t$(length(fmu.modelDescription.parameterValueReferences))") printValueReferences(fmu, fmu.modelDescription.parameterValueReferences) println("\tSupports Co-Simulation:\t\t$(isCoSimulation(fmu))") @@ -137,7 +135,7 @@ function info(fmu::FMU3) println("\tStates:\t\t\t\t$(length(fmu.modelDescription.stateValueReferences))") printValueReferences(fmu, fmu.modelDescription.stateValueReferences) - println("\tParameters:\t\t\t\t$(length(fmu.modelDescription.parameterValueReferences))") + println("\tParameters:\t\t\t$(length(fmu.modelDescription.parameterValueReferences))") printValueReferences(fmu, fmu.modelDescription.parameterValueReferences) println("\tSupports Co-Simulation:\t\t$(isCoSimulation(fmu))") diff --git a/src/jacobian.jl b/src/jacobian.jl index a2b0a44..60788dc 100644 --- a/src/jacobian.jl +++ b/src/jacobian.jl @@ -69,7 +69,7 @@ Computes the directional derivatives of an FMU. An FMU has different Modes and i 𝐯_unknown = 𝐡(𝐯_known, 𝐯_rest) - `v_unknown`: vector of unknown Real variables computed in the actual Mode: - - Initialization Mode: unkowns kisted under `` that have type Real. + - Initialization Mode: unknowns listed under `` that have type Real. - Continuous-Time Mode (ModelExchange): The continuous-time outputs and state derivatives. (= the variables listed under `` with type Real and variability = `continuous` and the variables listed as state derivatives under `)`. - Event Mode (ModelExchange): The same variables as in the Continuous-Time Mode and additionally variables under `` with type Real and variability = `discrete`. - Step Mode (CoSimulation): The variables listed under `` with type Real and variability = `continuous` or `discrete`. If `` is present, also the variables listed here as state derivatives. @@ -305,7 +305,7 @@ function getJacobian!( ) @assert size(jac) == (length(rdx), length(rx)) [ - "fmi2GetJacobian!: Dimension missmatch between `jac` $(size(jac)), `rdx` $(length(rdx)) and `rx` $(length(rx)).", + "fmi2GetJacobian!: Dimension mismatch between `jac` $(size(jac)), `rdx` $(length(rdx)) and `rx` $(length(rx)).", ] if length(rdx) == 0 || length(rx) == 0