From 4d6b6064ce347afdd16473975b1cd97e5a26b129 Mon Sep 17 00:00:00 2001 From: hofer_jn Date: Fri, 20 Oct 2023 13:09:23 +0200 Subject: [PATCH 1/5] TeamCity change in 'Ribasim / Ribasim' project: general settings of 'Build ribasim_cli - Windows' build configuration were updated --- .teamcity/Ribasim_Ribasim/buildTypes/BuildRibasimCliWindows.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/.teamcity/Ribasim_Ribasim/buildTypes/BuildRibasimCliWindows.xml b/.teamcity/Ribasim_Ribasim/buildTypes/BuildRibasimCliWindows.xml index 81ea8a81e..12533534d 100644 --- a/.teamcity/Ribasim_Ribasim/buildTypes/BuildRibasimCliWindows.xml +++ b/.teamcity/Ribasim_Ribasim/buildTypes/BuildRibasimCliWindows.xml @@ -6,7 +6,6 @@ From 94a677b188b503fe4fa435eeea652aff677e98c0 Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Fri, 20 Oct 2023 14:43:04 +0200 Subject: [PATCH 2/5] Strip cldr artifact before build (#687) Unfortunately #685 didn't work, since the same problematic artifact is included in older releases. This works around the same issue by stripping the cldr artifact of all unnecessary files. --- build/create_binaries/Manifest.toml | 68 ++++++++++++++++++++++++++++- build/create_binaries/Project.toml | 3 ++ build/create_binaries/create_app.jl | 4 +- build/create_binaries/create_lib.jl | 4 +- build/create_binaries/strip_cldr.jl | 24 ++++++++++ build/libribasim/Manifest.toml | 2 +- build/ribasim_cli/Manifest.toml | 2 +- core/Manifest.toml | 19 +++++--- core/Project.toml | 2 +- 9 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 build/create_binaries/strip_cldr.jl diff --git a/build/create_binaries/Manifest.toml b/build/create_binaries/Manifest.toml index 60801b50c..737ac860a 100644 --- a/build/create_binaries/Manifest.toml +++ b/build/create_binaries/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.9.3" manifest_format = "2.0" -project_hash = "c56985ee841fb30b2cb92ecec4da345315a95306" +project_hash = "71b2262fd2a2bd6f9c0ade48d4062e051c3f39eb" [[deps.ArgTools]] uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" @@ -14,6 +14,19 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [[deps.Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +[[deps.Compat]] +deps = ["UUIDs"] +git-tree-sha1 = "8a62af3e248a8c4bad6b32cbbe663ae02275e32c" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.10.0" + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + + [deps.Compat.weakdeps] + Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + [[deps.Dates]] deps = ["Printf"] uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" @@ -23,6 +36,11 @@ deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" version = "1.6.0" +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" @@ -31,6 +49,12 @@ git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496" uuid = "c27321d9-0574-5035-807b-f59d2c89b15c" version = "1.3.1" +[[deps.InlineStrings]] +deps = ["Parsers"] +git-tree-sha1 = "9cc2baf75c6d09f9da536ddf58eb2f29dedaf461" +uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" +version = "1.4.0" + [[deps.InteractiveUtils]] deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" @@ -73,6 +97,12 @@ deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" version = "2.28.2+0" +[[deps.Mocking]] +deps = ["Compat", "ExprTools"] +git-tree-sha1 = "4cc0c5a83933648b615c36c2b956d94fda70641e" +uuid = "78c3b35d-d492-501b-9361-3d52fe80e533" +version = "0.7.7" + [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" version = "2022.10.11" @@ -87,11 +117,29 @@ git-tree-sha1 = "d24f0920777c64c0265e9725eb4a3ec450bc36dd" uuid = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" version = "2.1.10" +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "716e24b21538abc91f6205fd1d8363f39b442851" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.7.2" + [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" version = "1.9.2" +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.0" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.1" + [[deps.Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" @@ -131,11 +179,29 @@ deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" version = "1.0.3" +[[deps.TZJData]] +deps = ["Artifacts"] +git-tree-sha1 = "d39314cdbaf5b90a047db33858626f8d1cc973e1" +uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" +version = "1.0.0+2023c" + [[deps.Tar]] deps = ["ArgTools", "SHA"] uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" version = "1.10.0" +[[deps.TimeZones]] +deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] +git-tree-sha1 = "89e64d61ef3cd9e80f7fc12b7d13db2d75a23c03" +uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" +version = "1.13.0" + + [deps.TimeZones.extensions] + TimeZonesRecipesBaseExt = "RecipesBase" + + [deps.TimeZones.weakdeps] + RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" + [[deps.UUIDs]] deps = ["Random", "SHA"] uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" diff --git a/build/create_binaries/Project.toml b/build/create_binaries/Project.toml index b6f893ed5..275616313 100644 --- a/build/create_binaries/Project.toml +++ b/build/create_binaries/Project.toml @@ -1,8 +1,11 @@ [deps] +Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433" PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53" [compat] PackageCompiler = "2" +TimeZones = "=1.13.0" julia = "1.9" diff --git a/build/create_binaries/create_app.jl b/build/create_binaries/create_app.jl index 58815815b..72e6a7262 100644 --- a/build/create_binaries/create_app.jl +++ b/build/create_binaries/create_app.jl @@ -2,6 +2,8 @@ using PackageCompiler using TOML using LibGit2 +include("strip_cldr.jl") + # change directory to this script's location cd(@__DIR__) @@ -16,7 +18,7 @@ create_app( # map from binary name to julia function name executables = ["ribasim" => "julia_main"], precompile_execution_file = "precompile.jl", - filter_stdlibs = false, + include_lazy_artifacts = true, force = true, ) diff --git a/build/create_binaries/create_lib.jl b/build/create_binaries/create_lib.jl index df8c5408b..0b8364099 100644 --- a/build/create_binaries/create_lib.jl +++ b/build/create_binaries/create_lib.jl @@ -2,6 +2,8 @@ using PackageCompiler using TOML using LibGit2 +include("strip_cldr.jl") + cd(@__DIR__) project_dir = "../libribasim" @@ -14,7 +16,7 @@ create_library( output_dir; lib_name = "libribasim", precompile_execution_file = "precompile.jl", - include_lazy_artifacts = false, + include_lazy_artifacts = true, force = true, ) diff --git a/build/create_binaries/strip_cldr.jl b/build/create_binaries/strip_cldr.jl new file mode 100644 index 000000000..fbded628c --- /dev/null +++ b/build/create_binaries/strip_cldr.jl @@ -0,0 +1,24 @@ +# The cldr artifact has such long paths that it errors on Windows unless long paths are enabled. +# Also the artifact has many files and is over 300 MB, while we only need a single small file. +# This modifies the artifact to remove everything except the file we need. +# Since the artifact is only used on Windows, only strip do it there. +# This needs exactly TimeZones 1.13.0, which is fixed in the Project.toml. +# https://github.com/JuliaTime/TimeZones.jl/issues/373 + +using Artifacts + +if Sys.iswindows() + # Get the artifact directory and the file path we need to keep + hash = Base.SHA1("40b35727ea0aff9a9f28b7454004b68849caf67b") + @assert artifact_exists(hash) + artifact_dir = artifact_path(hash) + keep_file = + normpath(artifact_dir, "cldr-release-43-1/common/supplemental/windowsZones.xml") + @assert isfile(keep_file) + + # Read the file into memory, empty the artifact dir, and write the file back + keep_file_content = read(keep_file) + rm(artifact_dir; recursive = true) + mkpath(dirname(keep_file)) + write(keep_file, keep_file_content) +end diff --git a/build/libribasim/Manifest.toml b/build/libribasim/Manifest.toml index 95db712d6..5db3c6ffd 100644 --- a/build/libribasim/Manifest.toml +++ b/build/libribasim/Manifest.toml @@ -979,7 +979,7 @@ uuid = "ae029012-a4dd-5104-9daa-d747884805df" version = "1.3.0" [[deps.Ribasim]] -deps = ["Arrow", "BasicModelInterface", "CodecLz4", "CodecZstd", "ComponentArrays", "Configurations", "DBInterface", "DataInterpolations", "DataStructures", "Dates", "Dictionaries", "DiffEqCallbacks", "FiniteDiff", "ForwardDiff", "Graphs", "HiGHS", "IterTools", "JuMP", "Legolas", "Logging", "LoggingExtras", "OrdinaryDiffEq", "PreallocationTools", "SQLite", "SciMLBase", "SparseArrays", "StructArrays", "Tables", "TerminalLoggers", "TimeZones", "TimerOutputs", "TranscodingStreams"] +deps = ["Arrow", "BasicModelInterface", "CodecLz4", "CodecZstd", "ComponentArrays", "Configurations", "DBInterface", "DataInterpolations", "DataStructures", "Dates", "Dictionaries", "DiffEqCallbacks", "FiniteDiff", "ForwardDiff", "Graphs", "HiGHS", "IterTools", "JuMP", "Legolas", "Logging", "LoggingExtras", "OrdinaryDiffEq", "PreallocationTools", "SQLite", "SciMLBase", "SparseArrays", "StructArrays", "Tables", "TerminalLoggers", "TimerOutputs", "TranscodingStreams"] path = "../../core" uuid = "aac5e3d9-0b8f-4d4f-8241-b1a7a9632635" version = "0.3.0" diff --git a/build/ribasim_cli/Manifest.toml b/build/ribasim_cli/Manifest.toml index 873b83b61..5885340d8 100644 --- a/build/ribasim_cli/Manifest.toml +++ b/build/ribasim_cli/Manifest.toml @@ -979,7 +979,7 @@ uuid = "ae029012-a4dd-5104-9daa-d747884805df" version = "1.3.0" [[deps.Ribasim]] -deps = ["Arrow", "BasicModelInterface", "CodecLz4", "CodecZstd", "ComponentArrays", "Configurations", "DBInterface", "DataInterpolations", "DataStructures", "Dates", "Dictionaries", "DiffEqCallbacks", "FiniteDiff", "ForwardDiff", "Graphs", "HiGHS", "IterTools", "JuMP", "Legolas", "Logging", "LoggingExtras", "OrdinaryDiffEq", "PreallocationTools", "SQLite", "SciMLBase", "SparseArrays", "StructArrays", "Tables", "TerminalLoggers", "TimeZones", "TimerOutputs", "TranscodingStreams"] +deps = ["Arrow", "BasicModelInterface", "CodecLz4", "CodecZstd", "ComponentArrays", "Configurations", "DBInterface", "DataInterpolations", "DataStructures", "Dates", "Dictionaries", "DiffEqCallbacks", "FiniteDiff", "ForwardDiff", "Graphs", "HiGHS", "IterTools", "JuMP", "Legolas", "Logging", "LoggingExtras", "OrdinaryDiffEq", "PreallocationTools", "SQLite", "SciMLBase", "SparseArrays", "StructArrays", "Tables", "TerminalLoggers", "TimerOutputs", "TranscodingStreams"] path = "../../core" uuid = "aac5e3d9-0b8f-4d4f-8241-b1a7a9632635" version = "0.3.0" diff --git a/core/Manifest.toml b/core/Manifest.toml index 158e0f0f1..073418681 100644 --- a/core/Manifest.toml +++ b/core/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.9.3" manifest_format = "2.0" -project_hash = "6a00ca0892e2ca78622bd97e6159a398bf80fa0b" +project_hash = "c63b237aec6a6bf6314284b2b07a94b93a9f0a36" [[deps.ADTypes]] git-tree-sha1 = "5d2e21d7b0d8c22f67483ef95ebdc39c0e6b6003" @@ -1217,6 +1217,12 @@ deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" version = "1.0.3" +[[deps.TZJData]] +deps = ["Artifacts"] +git-tree-sha1 = "d39314cdbaf5b90a047db33858626f8d1cc973e1" +uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" +version = "1.0.0+2023c" + [[deps.TableTraits]] deps = ["IteratorInterfaceExtensions"] git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" @@ -1251,11 +1257,14 @@ uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" version = "0.5.2" [[deps.TimeZones]] -deps = ["Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "RecipesBase", "Scratch", "Unicode"] -git-tree-sha1 = "cdaa0c2a4449724aded839550eca7d7240bb6938" -pinned = true +deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] +git-tree-sha1 = "89e64d61ef3cd9e80f7fc12b7d13db2d75a23c03" uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.10.0" +version = "1.13.0" +weakdeps = ["RecipesBase"] + + [deps.TimeZones.extensions] + TimeZonesRecipesBaseExt = "RecipesBase" [[deps.TimerOutputs]] deps = ["ExprTools", "Printf"] diff --git a/core/Project.toml b/core/Project.toml index fc77966e2..62c01fb3b 100644 --- a/core/Project.toml +++ b/core/Project.toml @@ -65,7 +65,7 @@ SciMLBase = "1.60, 2" StructArrays = "0.6.13" Tables = "1" TerminalLoggers = "0.1.7" -TimeZones = "=1.10.0" +TimeZones = "=1.13.0" TimerOutputs = "0.5" TranscodingStreams = "0.9, 0.10" julia = "1.9" From 047fce07e04402dd409ed2282b2400cc6d95a7b9 Mon Sep 17 00:00:00 2001 From: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com> Date: Fri, 20 Oct 2023 17:07:08 +0200 Subject: [PATCH 3/5] Skip version tests of ribasim_api (#689) It (finally) stopped working on TeamCity --- python/ribasim_api/tests/test_bmi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ribasim_api/tests/test_bmi.py b/python/ribasim_api/tests/test_bmi.py index 9129eb5f1..c4665a63c 100644 --- a/python/ribasim_api/tests/test_bmi.py +++ b/python/ribasim_api/tests/test_bmi.py @@ -115,6 +115,7 @@ def test_get_component_name(libribasim): assert libribasim.get_component_name() == "Ribasim" +@pytest.mark.skip("https://github.com/Deltares/Ribasim/issues/364") def test_get_version(libribasim): toml_path = Path(__file__).parents[3] / "core" / "Project.toml" with open(toml_path, mode="rb") as fp: From c710ed2021841310b88a96425e11d4d8f924f11a Mon Sep 17 00:00:00 2001 From: Martijn Visser Date: Sat, 21 Oct 2023 15:50:24 +0200 Subject: [PATCH 4/5] rename model files (#690) Fixes a large part of #638. Not entirely, I listed two follow-ups that are probably best done after #630 in that issue. This also removes the model name from the model, as before the only thing it did was name the TOML and GeoPackage. That meant I had to adapt `ribasim_testmodels` a bit to expose a `constructors` dict which maps the test model names to the constructor functions. https://github.com/Deltares/Ribasim/compare/names?expand=1#diff-b223bf31f9400e170f97d95fa1d8b22393e5d37cfd810a4a5aa7bf480915ac52 This doesn't just change the file names but also updates the documentation to stop talking about GeoPackage so much and consistently refer to the database. Also QGIS panel names are updated, function, class and variable names. TOML section names are updated, so this is breaking. Specifically, the `geopackage` key is now called `database`, and the `[output]` section is now called `[results]`. The default output folder is now also called results. --- build/create_binaries/precompile.jl | 2 +- build/libribasim/README.md | 2 +- build/ribasim_cli/README.md | 4 +- build/ribasim_cli/src/ribasim_cli.jl | 2 +- build/ribasim_cli/tests/test_models.py | 12 +++--- core/src/bmi.jl | 30 +++++++-------- core/src/config.jl | 18 ++++----- core/src/io.jl | 12 +++--- core/src/lib.jl | 2 +- core/src/solve.jl | 2 +- core/src/utils.jl | 8 ++-- core/src/validation.jl | 2 +- core/test/allocation.jl | 6 +-- core/test/bmi.jl | 2 +- core/test/cli.jl | 2 +- core/test/config.jl | 18 ++++----- core/test/control.jl | 20 ++++------ core/test/docs.toml | 16 ++++---- core/test/equations.jl | 23 ++++------- core/test/io.jl | 16 ++++---- core/test/libribasim.jl | 2 +- core/test/run_models.jl | 30 ++++++--------- core/test/testrun.toml | 4 +- core/test/time.jl | 12 +++--- core/test/utils.jl | 13 +++---- core/test/validation.jl | 28 +++++++------- docs/_quarto.yml | 2 +- docs/contribute/core.qmd | 2 +- docs/core/usage.qmd | 32 ++++++++-------- docs/python/examples.ipynb | 38 +++++++++---------- docs/qgis/index.qmd | 20 +++++----- docs/schema/Config.schema.json | 20 +++++----- ...Output.schema.json => Results.schema.json} | 12 +++--- python/ribasim/ribasim/config.py | 22 +++++------ python/ribasim/ribasim/geometry/edge.py | 4 +- python/ribasim/ribasim/geometry/node.py | 4 +- python/ribasim/ribasim/input_base.py | 26 ++++++------- python/ribasim/ribasim/model.py | 30 ++++++--------- python/ribasim/tests/test_io.py | 8 +--- python/ribasim/tests/test_model.py | 2 +- python/ribasim_api/tests/test_bmi.py | 22 +++++------ .../ribasim_testmodels/__init__.py | 12 ++++++ .../ribasim_testmodels/allocation.py | 3 -- .../ribasim_testmodels/backwater.py | 1 - .../ribasim_testmodels/basic.py | 4 -- .../ribasim_testmodels/bucket.py | 1 - .../ribasim_testmodels/discrete_control.py | 5 --- .../ribasim_testmodels/dutch_waterways.py | 1 - .../ribasim_testmodels/equations.py | 5 --- .../ribasim_testmodels/invalid.py | 4 -- .../ribasim_testmodels/pid_control.py | 2 - .../ribasim_testmodels/time.py | 1 - .../ribasim_testmodels/trivial.py | 1 - qgis/core/geopackage.py | 4 +- .../{output_widget.py => results_widget.py} | 24 ++++++------ qgis/widgets/ribasim_widget.py | 8 ++-- utils/generate-testmodels.py | 12 ++---- utils/runstats.jl | 2 +- 58 files changed, 280 insertions(+), 342 deletions(-) rename docs/schema/{Output.schema.json => Results.schema.json} (77%) rename qgis/widgets/{output_widget.py => results_widget.py} (54%) diff --git a/build/create_binaries/precompile.jl b/build/create_binaries/precompile.jl index 30ca8f817..73cd6c6f2 100644 --- a/build/create_binaries/precompile.jl +++ b/build/create_binaries/precompile.jl @@ -3,5 +3,5 @@ using Ribasim, Dates, TOML -toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/basic.toml") +toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/ribasim.toml") Ribasim.run(toml_path) diff --git a/build/libribasim/README.md b/build/libribasim/README.md index 17cb4a070..5906696a7 100644 --- a/build/libribasim/README.md +++ b/build/libribasim/README.md @@ -22,7 +22,7 @@ In [3]: argument = create_string_buffer(0) ...: c_dll.init_julia(c_int(0), byref(argument)) Out[3]: 1 -In [4]: config_path = "run.toml" +In [4]: config_path = "ribasim.toml" In [5]: c_dll.initialize(c_char_p(config_path.encode())) Out[5]: 0 diff --git a/build/ribasim_cli/README.md b/build/ribasim_cli/README.md index aac8814d3..b51c5e27f 100644 --- a/build/ribasim_cli/README.md +++ b/build/ribasim_cli/README.md @@ -13,11 +13,11 @@ If you have installed Julia and Ribasim, a simulation can also be started from t line as follows: ``` -julia --eval 'using Ribasim; Ribasim.run("path/to/config.toml")' +julia --eval 'using Ribasim; Ribasim.run("path/to/model/ribasim.toml")' ``` With a Ribasim CLI build this becomes: ``` -ribasim path/to/config.toml +ribasim path/to/model/ribasim.toml ``` diff --git a/build/ribasim_cli/src/ribasim_cli.jl b/build/ribasim_cli/src/ribasim_cli.jl index 9d0ed7824..d04336281 100644 --- a/build/ribasim_cli/src/ribasim_cli.jl +++ b/build/ribasim_cli/src/ribasim_cli.jl @@ -7,7 +7,7 @@ using Ribasim function help(x)::Cint println(x) - println("Usage: ribasim path/to/config.toml") + println("Usage: ribasim path/to/model/ribasim.toml") return 1 end diff --git a/build/ribasim_cli/tests/test_models.py b/build/ribasim_cli/tests/test_models.py index b84600e33..8f1f02639 100644 --- a/build/ribasim_cli/tests/test_models.py +++ b/build/ribasim_cli/tests/test_models.py @@ -7,13 +7,13 @@ @pytest.mark.parametrize( - "model_constructor", - map(ribasim_testmodels.__dict__.get, ribasim_testmodels.__all__), + "model_name,model_constructor", + ribasim_testmodels.constructors.items(), ) -def test_ribasim_cli(model_constructor, tmp_path): +def test_ribasim_cli(model_name, model_constructor, tmp_path): model = model_constructor() assert isinstance(model, ribasim.Model) - model.write(tmp_path) + model.write(tmp_path / model_name) executable = ( Path(__file__).parents[2] @@ -22,10 +22,10 @@ def test_ribasim_cli(model_constructor, tmp_path): / "bin" / "ribasim.exe" ) - config_file = str(tmp_path / f"{model.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") result = subprocess.run([executable, config_file]) - if model.modelname.startswith("invalid"): + if model_name.startswith("invalid_"): assert result.returncode != 0 else: assert result.returncode == 0 diff --git a/core/src/bmi.jl b/core/src/bmi.jl index c815d0b05..815f65955 100644 --- a/core/src/bmi.jl +++ b/core/src/bmi.jl @@ -15,9 +15,9 @@ Initialize a [`Model`](@ref) from a [`Config`](@ref). """ function BMI.initialize(T::Type{Model}, config::Config)::Model alg = algorithm(config.solver) - gpkg_path = input_path(config, config.geopackage) - if !isfile(gpkg_path) - throw(SystemError("GeoPackage file not found: $gpkg_path")) + db_path = input_path(config, config.database) + if !isfile(db_path) + throw(SystemError("Database file not found: $db_path")) end # Setup timing logging @@ -25,9 +25,9 @@ function BMI.initialize(T::Type{Model}, config::Config)::Model TimerOutputs.enable_debug_timings(Ribasim) # causes recompilation (!) end - # All data from the GeoPackage that we need during runtime is copied into memory, + # All data from the database that we need during runtime is copied into memory, # so we can directly close it again. - db = SQLite.DB(gpkg_path) + db = SQLite.DB(db_path) local parameters, state, n, tstops try parameters = Parameters(db, config) @@ -83,7 +83,7 @@ function BMI.initialize(T::Type{Model}, config::Config)::Model state = load_structvector(db, config, BasinStateV1) n = length(get_ids(db, "Basin")) finally - # always close the GeoPackage, also in case of an error + # always close the database, also in case of an error close(db) end @debug "Read database into memory." @@ -156,29 +156,29 @@ end """ BMI.finalize(model::Model)::Model -Write all output to the configured output files. +Write all results to the configured files. """ function BMI.finalize(model::Model)::Model (; config) = model - (; output) = model.config - compress = get_compressor(output) + (; results) = model.config + compress = get_compressor(results) # basin table = basin_table(model) - path = output_path(config, output.basin) + path = results_path(config, results.basin) write_arrow(path, table, compress) # flow table = flow_table(model) - path = output_path(config, output.flow) + path = results_path(config, results.flow) write_arrow(path, table, compress) # discrete control table = discrete_control_table(model) - path = output_path(config, output.control) + path = results_path(config, results.control) write_arrow(path, table, compress) - @debug "Wrote output." + @debug "Wrote results." return model end @@ -203,7 +203,7 @@ function set_initial_discrete_controlled_parameters!( end """ -Create the different callbacks that are used to store output +Create the different callbacks that are used to store results and feed the simulation with new data. The different callbacks are combined to a CallbackSet that goes to the integrator. Returns the CallbackSet and the SavedValues for flow. @@ -566,7 +566,7 @@ BMI.get_time_step(model::Model) = get_proposed_dt(model.integrator) run(config::Config)::Model Run a [`Model`](@ref), given a path to a TOML configuration file, or a Config object. -Running a model includes initialization, solving to the end with `[`solve!`](@ref)` and writing output with [`BMI.finalize`](@ref). +Running a model includes initialization, solving to the end with `[`solve!`](@ref)` and writing results with [`BMI.finalize`](@ref). """ run(config_file::AbstractString)::Model = run(Config(config_file)) diff --git a/core/src/config.jl b/core/src/config.jl index 376e3ffa5..04da2a593 100644 --- a/core/src/config.jl +++ b/core/src/config.jl @@ -15,7 +15,7 @@ using Logging: LogLevel, Debug, Info, Warn, Error using ..Ribasim: Ribasim, isnode, nodetype using OrdinaryDiffEq -export Config, Solver, Output, Logging +export Config, Solver, Results, Logging export algorithm, snake_case, zstd, lz4 const schemas = @@ -108,10 +108,10 @@ function Base.convert(::Type{Compression}, str::AbstractString) end # Separate struct, as basin clashes with nodetype -@option struct Output <: TableOption - basin::String = "output/basin.arrow" - flow::String = "output/flow.arrow" - control::String = "output/control.arrow" +@option struct Results <: TableOption + basin::String = "results/basin.arrow" + flow::String = "results/flow.arrow" + control::String = "results/control.arrow" outstate::Union{String, Nothing} = nothing compression::Compression = "zstd" compression_level::Int = 6 @@ -132,13 +132,13 @@ end # optional, when Config is created from a TOML file, this is its directory relative_dir::String = "." # ignored(!) input_dir::String = "." - output_dir::String = "." + results_dir::String = "." # input, required - geopackage::String + database::String - # output, required - output::Output = Output() + # results, required + results::Results = Results() solver::Solver = Solver() diff --git a/core/src/io.jl b/core/src/io.jl index ea4be2277..7802c79a7 100644 --- a/core/src/io.jl +++ b/core/src/io.jl @@ -47,7 +47,7 @@ datetime_since(t::Real, t0::DateTime)::DateTime = t0 + Millisecond(round(1000 * """ load_data(db::DB, config::Config, nodetype::Symbol, kind::Symbol)::Union{Table, Query, Nothing} -Load data from Arrow files if available, otherwise the GeoPackage. +Load data from Arrow files if available, otherwise the database. Returns either an `Arrow.Table`, `SQLite.Query` or `nothing` if the data is not present. """ function load_data( @@ -78,7 +78,7 @@ end """ load_structvector(db::DB, config::Config, ::Type{T})::StructVector{T} -Load data from Arrow files if available, otherwise the GeoPackage. +Load data from Arrow files if available, otherwise the database. Always returns a StructVector of the given struct type T, which is empty if the table is not found. This function validates the schema, and enforces the required sort order. """ @@ -95,7 +95,7 @@ function load_structvector( nt = Tables.columntable(table) if table isa Query && haskey(nt, :time) - # time has type timestamp and is stored as a String in the GeoPackage + # time has type timestamp and is stored as a String in the database # currently SQLite.jl does not automatically convert it to DateTime nt = merge( nt, @@ -127,9 +127,9 @@ function input_path(config::Config, path::String) return normpath(config.relative_dir, config.input_dir, path) end -"Construct a path relative to both the TOML directory and the optional `output_dir`" -function output_path(config::Config, path::String) - return normpath(config.relative_dir, config.output_dir, path) +"Construct a path relative to both the TOML directory and the optional `results_dir`" +function results_path(config::Config, path::String) + return normpath(config.relative_dir, config.results_dir, path) end """ diff --git a/core/src/lib.jl b/core/src/lib.jl index ab33f6f44..f07979eb1 100644 --- a/core/src/lib.jl +++ b/core/src/lib.jl @@ -4,7 +4,7 @@ Initialize a Model. -The Model struct is an initialized model, combined with the [`Config`](@ref) used to create it and saved outputs. +The Model struct is an initialized model, combined with the [`Config`](@ref) used to create it and saved results. The Basic Model Interface ([BMI](https://github.com/Deltares/BasicModelInterface.jl)) is implemented on the Model. A Model can be created from the path to a TOML configuration file, or a Config object. """ diff --git a/core/src/solve.jl b/core/src/solve.jl index 00522ea54..1e4d15ae9 100644 --- a/core/src/solve.jl +++ b/core/src/solve.jl @@ -392,7 +392,7 @@ greater_than: The threshold value in the condition condition_value: The current value of each condition control_state: Dictionary: node ID => (control state, control state start) logic_mapping: Dictionary: (control node ID, truth state) => control state -record: Namedtuple with discrete control information for output +record: Namedtuple with discrete control information for results """ struct DiscreteControl <: AbstractParameterNode node_id::Vector{Int} diff --git a/core/src/utils.jl b/core/src/utils.jl index 282007a1a..ad8f200a7 100644 --- a/core/src/utils.jl +++ b/core/src/utils.jl @@ -466,10 +466,10 @@ function basin_bottoms( return bottom_a, bottom_b end -"Get the compressor based on the Output" -function get_compressor(output::Output)::TranscodingStreams.Codec - compressor = output.compression - level = output.compression_level +"Get the compressor based on the Results section" +function get_compressor(results::Results)::TranscodingStreams.Codec + compressor = results.compression + level = results.compression_level c = if compressor == lz4 LZ4FrameCompressor(; compressionlevel = level) elseif compressor == zstd diff --git a/core/src/validation.jl b/core/src/validation.jl index 1cc358867..ed02dbb05 100644 --- a/core/src/validation.jl +++ b/core/src/validation.jl @@ -372,7 +372,7 @@ end """ Depending on if a table can be sorted, either sort it or assert that it is sorted. -Tables loaded from GeoPackage into memory can be sorted. +Tables loaded from the database into memory can be sorted. Tables loaded from Arrow files are memory mapped and can therefore not be sorted. """ function sorted_table!( diff --git a/core/test/allocation.jl b/core/test/allocation.jl index c92dd5dfa..1e892ab8e 100644 --- a/core/test/allocation.jl +++ b/core/test/allocation.jl @@ -3,11 +3,11 @@ using SQLite using JuMP: value @testset "Allocation solve" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/subnetwork/subnetwork.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/subnetwork/ribasim.toml") @test ispath(toml_path) cfg = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(cfg, cfg.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(cfg, cfg.database) + db = SQLite.DB(db_path) p = Ribasim.Parameters(db, cfg) close(db) diff --git a/core/test/bmi.jl b/core/test/bmi.jl index f56f384b4..53329af34 100644 --- a/core/test/bmi.jl +++ b/core/test/bmi.jl @@ -2,7 +2,7 @@ using Test using Ribasim import BasicModelInterface as BMI -toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/basic.toml") +toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/ribasim.toml") @testset "adaptive timestepping" begin model = BMI.initialize(Ribasim.Model, toml_path) diff --git a/core/test/cli.jl b/core/test/cli.jl index 1e56d976c..64bd53af5 100644 --- a/core/test/cli.jl +++ b/core/test/cli.jl @@ -15,7 +15,7 @@ end @testset "toml_path" begin model_path = normpath(@__DIR__, "../../generated_testmodels/basic/") - toml_path = normpath(model_path, "basic.toml") + toml_path = normpath(model_path, "ribasim.toml") @test ispath(toml_path) empty!(ARGS) push!(ARGS, toml_path) diff --git a/core/test/config.jl b/core/test/config.jl index 5e61ef2c8..7c935d1d1 100644 --- a/core/test/config.jl +++ b/core/test/config.jl @@ -11,7 +11,7 @@ using CodecZstd: ZstdCompressor @test_throws UndefKeywordError Ribasim.Config( startime = now(), endtime = now(), - geopackage = "", + database = "", foo = "bar", ) @@ -21,22 +21,22 @@ using CodecZstd: ZstdCompressor @test config.update_timestep == 86400.0 @test config.endtime > config.starttime @test config.solver == Ribasim.Solver(; saveat = 86400.0) - @test config.output.compression == Ribasim.zstd - @test config.output.compression_level == 6 + @test config.results.compression == Ribasim.zstd + @test config.results.compression_level == 6 end - @testset "output" begin - o = Ribasim.Output() - @test o isa Ribasim.Output + @testset "results" begin + o = Ribasim.Results() + @test o isa Ribasim.Results @test o.compression === Ribasim.zstd @test o.compression_level === 6 - @test_throws ArgumentError Ribasim.Output(compression = "lz5") + @test_throws ArgumentError Ribasim.Results(compression = "lz5") @test Ribasim.get_compressor( - Ribasim.Output(; compression = "lz4", compression_level = 2), + Ribasim.Results(; compression = "lz4", compression_level = 2), ) isa LZ4FrameCompressor @test Ribasim.get_compressor( - Ribasim.Output(; compression = "zstd", compression_level = 3), + Ribasim.Results(; compression = "zstd", compression_level = 3), ) isa ZstdCompressor end diff --git a/core/test/control.jl b/core/test/control.jl index c3d25bd27..9faac44dd 100644 --- a/core/test/control.jl +++ b/core/test/control.jl @@ -2,10 +2,8 @@ import Ribasim using Dates: Date @testset "Pump discrete control" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/pump_discrete_control/pump_discrete_control.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/pump_discrete_control/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) p = model.integrator.p @@ -39,8 +37,7 @@ using Dates: Date end @testset "Flow condition control" begin - toml_path = - normpath(@__DIR__, "../../generated_testmodels/flow_condition/flow_condition.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/flow_condition/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) p = model.integrator.p @@ -63,7 +60,7 @@ end @testset "Transient level boundary condition control" begin toml_path = normpath( @__DIR__, - "../../generated_testmodels/level_boundary_condition/level_boundary_condition.toml", + "../../generated_testmodels/level_boundary_condition/ribasim.toml", ) @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -85,8 +82,7 @@ end end @testset "PID control" begin - toml_path = - normpath(@__DIR__, "../../generated_testmodels/pid_control/pid_control.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/pid_control/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) p = model.integrator.p @@ -127,7 +123,7 @@ end @testset "TabulatedRatingCurve control" begin toml_path = normpath( @__DIR__, - "../../generated_testmodels/tabulated_rating_curve_control/tabulated_rating_curve_control.toml", + "../../generated_testmodels/tabulated_rating_curve_control/ribasim.toml", ) @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -146,7 +142,7 @@ end @testset "Setpoint with bounds control" begin toml_path = normpath( @__DIR__, - "../../generated_testmodels/level_setpoint_with_minmax/level_setpoint_with_minmax.toml", + "../../generated_testmodels/level_setpoint_with_minmax/ribasim.toml", ) @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -176,7 +172,7 @@ end @testset "Set PID target with DiscreteControl" begin toml_path = normpath( @__DIR__, - "../../generated_testmodels/discrete_control_of_pid_control/discrete_control_of_pid_control.toml", + "../../generated_testmodels/discrete_control_of_pid_control/ribasim.toml", ) @test ispath(toml_path) model = Ribasim.run(toml_path) diff --git a/core/test/docs.toml b/core/test/docs.toml index b3335c1fa..fb6c8f0ec 100644 --- a/core/test/docs.toml +++ b/core/test/docs.toml @@ -7,19 +7,19 @@ endtime = 2021-01-01 # required update_timestep = 86400.0 # optional, default 1 day # input files -geopackage = "model.gpkg" # required +database = "database.gpkg" # required -[output] -# These output files are always written -flow = "output/flow.arrow" # optional, default "output/flow.arrow" -basin = "output/basin.arrow" # optional, default "output/basin.arrow" -control = "output/control.arrow" # optional, default "output/control.arrow" +[results] +# These results files are always written +flow = "results/flow.arrow" # optional, default "results/flow.arrow" +basin = "results/basin.arrow" # optional, default "results/basin.arrow" +control = "results/control.arrow" # optional, default "results/control.arrow" compression = "zstd" # optional, default "zstd", also supports "lz4" compression_level = 6 # optional, default 6 -# Specific tables can also go into Arrow files rather than the GeoPackage. +# Specific tables can also go into Arrow files rather than the database. # For large tables this can benefit from better compressed file sizes. -# This is optional, tables are retrieved from the GeoPackage if not specified in the TOML. +# This is optional, tables are retrieved from the database if not specified in the TOML. [basin] time = "basin/time.arrow" diff --git a/core/test/equations.jl b/core/test/equations.jl index b7c38043d..7a6d25b43 100644 --- a/core/test/equations.jl +++ b/core/test/equations.jl @@ -62,10 +62,8 @@ TimerOutputs.disable_debug_timings(Ribasim) # causes recompilation (!) # Solution: storage(t) = limit_storage + (storage0 - limit_storage)*exp(-t/(basin_area*resistance)) # Here limit_storage is the storage at which the level of the basin is equal to the level of the level boundary @testset "LinearResistance" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/linear_resistance/linear_resistance.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/linear_resistance/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test successful_retcode(model) @@ -89,8 +87,7 @@ end # Solution: w = 1/(α(t-t0)/basin_area + 1/w(t0)), # storage = storage_min + 1/(α(t-t0)/basin_area^2 + 1/(storage(t0)-storage_min)) @testset "TabulatedRatingCurve" begin - toml_path = - normpath(@__DIR__, "../../generated_testmodels/rating_curve/rating_curve.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/rating_curve/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test successful_retcode(model) @@ -122,10 +119,8 @@ end # Note: The Wolfram Alpha solution contains a factor of the hypergeometric function 2F1, but these values are # so close to 1 that they are omitted. @testset "ManningResistance" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/manning_resistance/manning_resistance.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/manning_resistance/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test successful_retcode(model) @@ -159,10 +154,8 @@ end # differentiating the equation for the storage of the controlled basin # once to time to get rid of the integral term. @testset "PID control" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/pid_control_equation/pid_control_equation.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/pid_control_equation/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test successful_retcode(model) @@ -205,7 +198,7 @@ end # storage2 = storage2(t0) + (t-t0)*q_pump # Note: uses Euler algorithm @testset "MiscellaneousNodes" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/misc_nodes/misc_nodes.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/misc_nodes/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test successful_retcode(model) diff --git a/core/test/io.jl b/core/test/io.jl index a6f96d84b..f058f9067 100644 --- a/core/test/io.jl +++ b/core/test/io.jl @@ -17,7 +17,7 @@ recordproperty("name", "Input/Output") # TODO To check in TeamCity starttime = now(), endtime = now(), relative_dir = "model", - geopackage = "path/to/file", + database = "path/to/file", ) @test Ribasim.input_path(config, "path/to/file") == normpath("model", "path", "to", "file") @@ -28,14 +28,14 @@ recordproperty("name", "Input/Output") # TODO To check in TeamCity endtime = now(), relative_dir = "model", input_dir = "input", - geopackage = "path/to/file", + database = "path/to/file", ) @test Ribasim.input_path(config, "path/to/file") == normpath("model", "input", "path", "to", "file") # absolute path config = - Ribasim.Config(; starttime = now(), endtime = now(), geopackage = "/path/to/file") + Ribasim.Config(; starttime = now(), endtime = now(), database = "/path/to/file") @test Ribasim.input_path(config, "/path/to/file") == abspath("/path/to/file") end @@ -69,13 +69,11 @@ function to_arrow_table( end @testset "table sort" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/basic_transient/basic_transient.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/basic_transient/ribasim.toml") config = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(config, config.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(config, config.database) + db = SQLite.DB(db_path) # load a sorted table table = Ribasim.load_structvector(db, config, Ribasim.BasinTimeV1) diff --git a/core/test/libribasim.jl b/core/test/libribasim.jl index 15edf4a53..9dec51a90 100644 --- a/core/test/libribasim.jl +++ b/core/test/libribasim.jl @@ -4,7 +4,7 @@ import BasicModelInterface as BMI include("../../build/libribasim/src/libribasim.jl") -toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/basic.toml") +toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/ribasim.toml") @testset "libribasim" begin # data from which we create pointers for libribasim diff --git a/core/test/run_models.jl b/core/test/run_models.jl index 116031f4c..69bb3d4ef 100644 --- a/core/test/run_models.jl +++ b/core/test/run_models.jl @@ -9,7 +9,7 @@ using PreallocationTools: get_tmp using DataFrames: DataFrame @testset "trivial model" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/trivial/trivial.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/trivial/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test model isa Ribasim.Model @@ -17,7 +17,7 @@ using DataFrames: DataFrame end @testset "bucket model" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/bucket/bucket.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/bucket/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test model isa Ribasim.Model @@ -25,7 +25,7 @@ end end @testset "basic model" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/basic.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/ribasim.toml") @test ispath(toml_path) logger = TestLogger() @@ -58,10 +58,8 @@ end end @testset "basic transient model" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/basic_transient/basic_transient.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/basic_transient/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test model isa Ribasim.Model @@ -72,10 +70,8 @@ end end @testset "sparse and AD/FDM jac solver options" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/basic_transient/basic_transient.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/basic_transient/ribasim.toml") config = Ribasim.Config(toml_path; solver_sparse = true, solver_autodiff = true) sparse_ad = Ribasim.run(config) @@ -97,10 +93,8 @@ end end @testset "TabulatedRatingCurve model" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/tabulated_rating_curve/tabulated_rating_curve.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/tabulated_rating_curve/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test model isa Ribasim.Model @@ -158,7 +152,7 @@ end end @testset "Outlet constraints" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/outlet/outlet.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/outlet/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -187,7 +181,7 @@ end end @testset "User" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/user/user.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/user/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -254,7 +248,7 @@ end return h end - toml_path = normpath(@__DIR__, "../../generated_testmodels/backwater/backwater.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/backwater/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @test successful_retcode(model) diff --git a/core/test/testrun.toml b/core/test/testrun.toml index 1d58de637..608baf802 100644 --- a/core/test/testrun.toml +++ b/core/test/testrun.toml @@ -6,9 +6,9 @@ update_timestep = 86400.0 # optional, default is the path of the TOML input_dir = "../generated_testmodels/lhm" -output_dir = "../generated_testmodels/lhm" +results_dir = "../generated_testmodels/lhm" -geopackage = "model.gpkg" +database = "database.gpkg" [basin] time = "basin/time.arrow" diff --git a/core/test/time.jl b/core/test/time.jl index da8a996ea..adeebb54c 100644 --- a/core/test/time.jl +++ b/core/test/time.jl @@ -4,10 +4,8 @@ using Dates using DataFrames: DataFrame @testset "Time dependent flow boundary" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/flow_boundary_time/flow_boundary_time.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/flow_boundary_time/ribasim.toml") @test ispath(toml_path) model = Ribasim.run(toml_path) @@ -32,12 +30,12 @@ using DataFrames: DataFrame end @testset "User demand interpolation" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/subnetwork/subnetwork.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/subnetwork/ribasim.toml") @test ispath(toml_path) cfg = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(cfg, cfg.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(cfg, cfg.database) + db = SQLite.DB(db_path) p = Ribasim.Parameters(db, cfg) (; user) = p diff --git a/core/test/utils.jl b/core/test/utils.jl index 80f7a7284..1237d4f92 100644 --- a/core/test/utils.jl +++ b/core/test/utils.jl @@ -160,11 +160,11 @@ end end @testset "Jacobian sparsity" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/basic.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/basic/ribasim.toml") cfg = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(cfg, cfg.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(cfg, cfg.database) + db = SQLite.DB(db_path) p = Ribasim.Parameters(db, cfg) jac_prototype = Ribasim.get_jac_prototype(p) @@ -175,12 +175,11 @@ end @test jac_prototype.rowval == [1, 2, 1, 2, 2, 3, 2, 3, 4] @test jac_prototype.nzval == ones(9) - toml_path = - normpath(@__DIR__, "../../generated_testmodels/pid_control/pid_control.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/pid_control/ribasim.toml") cfg = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(cfg, cfg.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(cfg, cfg.database) + db = SQLite.DB(db_path) p = Ribasim.Parameters(db, cfg) jac_prototype = Ribasim.get_jac_prototype(p) diff --git a/core/test/validation.jl b/core/test/validation.jl index 1f8fcb42e..06ee51832 100644 --- a/core/test/validation.jl +++ b/core/test/validation.jl @@ -26,12 +26,12 @@ using Logging end @testset "Q(h) validation" begin - toml_path = normpath(@__DIR__, "../../generated_testmodels/invalid_qh/invalid_qh.toml") + toml_path = normpath(@__DIR__, "../../generated_testmodels/invalid_qh/ribasim.toml") @test ispath(toml_path) config = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(config, config.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(config, config.database) + db = SQLite.DB(db_path) logger = TestLogger() with_logger(logger) do @@ -153,13 +153,13 @@ if !Sys.islinux() @testset "FractionalFlow validation" begin toml_path = normpath( @__DIR__, - "../../generated_testmodels/invalid_fractional_flow/invalid_fractional_flow.toml", + "../../generated_testmodels/invalid_fractional_flow/ribasim.toml", ) @test ispath(toml_path) config = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(config, config.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(config, config.database) + db = SQLite.DB(db_path) p = Ribasim.Parameters(db, config) (; connectivity, fractional_flow) = p @@ -188,13 +188,13 @@ end @testset "DiscreteControl logic validation" begin toml_path = normpath( @__DIR__, - "../../generated_testmodels/invalid_discrete_control/invalid_discrete_control.toml", + "../../generated_testmodels/invalid_discrete_control/ribasim.toml", ) @test ispath(toml_path) cfg = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(cfg, cfg.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(cfg, cfg.database) + db = SQLite.DB(db_path) p = Ribasim.Parameters(db, cfg) logger = TestLogger() @@ -263,15 +263,13 @@ end end @testset "Edge type validation" begin - toml_path = normpath( - @__DIR__, - "../../generated_testmodels/invalid_edge_types/invalid_edge_types.toml", - ) + toml_path = + normpath(@__DIR__, "../../generated_testmodels/invalid_edge_types/ribasim.toml") @test ispath(toml_path) cfg = Ribasim.Config(toml_path) - gpkg_path = Ribasim.input_path(cfg, cfg.geopackage) - db = SQLite.DB(gpkg_path) + db_path = Ribasim.input_path(cfg, cfg.database) + db = SQLite.DB(db_path) logger = TestLogger() with_logger(logger) do @test !Ribasim.valid_edge_types(db) diff --git a/docs/_quarto.yml b/docs/_quarto.yml index 5025f5a15..ac4e5ef36 100644 --- a/docs/_quarto.yml +++ b/docs/_quarto.yml @@ -71,7 +71,7 @@ quartodoc: contents: - Model - title: Network - desc: The Node and Edge GeoPackage layers define the network layout. + desc: The Node and Edge database layers define the network layout. contents: - Node - Edge diff --git a/docs/contribute/core.qmd b/docs/contribute/core.qmd index bd8d4ae38..ce2815dc4 100644 --- a/docs/contribute/core.qmd +++ b/docs/contribute/core.qmd @@ -138,7 +138,7 @@ pkg> instantiate Press backspace to go back to the Julia REPL. There you can run a model with: ```julia -julia> Ribasim.run("path/to/model.toml") +julia> Ribasim.run("path/to/model/ribasim.toml") ``` :::{.callout-tip} diff --git a/docs/core/usage.qmd b/docs/core/usage.qmd index e91b7e9fe..65c3b3659 100644 --- a/docs/core/usage.qmd +++ b/docs/core/usage.qmd @@ -16,7 +16,7 @@ arguments in the command line. This will give the following message: ``` -Usage: ribasim 'path/to/config.toml' +Usage: ribasim 'path/to/model/ribasim.toml' ``` # Configuration file @@ -30,7 +30,7 @@ format. It contains settings, as well as paths to other input and output files. ## Solver settings {#sec-solver-settings} The solver section in the configuration file is entirely optional, since we aim to use defaults that will generally work well. -Common reasons to modify the solver settings are to adjust the calculation or output stepsizes: `adaptive`, `dt`, and `saveat`. +Common reasons to modify the solver settings are to adjust the calculation or result stepsizes: `adaptive`, `dt`, and `saveat`. If your model does not converge, or your performance is lower than expected, it can help to adjust other solver settings as well. The default solver `algorithm = "QNDF"`, which is a multistep method similar to Matlab's `ode15s` [@shampine1997matlab]. @@ -47,9 +47,9 @@ By default these depend on the problem and algorithm. If a smaller `dt` than `dtmin` is needed to meet the set error tolerances, the simulation stops, unless `force_dtmin` is set to `true`. `force_dtmin` is off by default to ensure an accurate solution. -By default the calculation and output stepsize are the same, with `saveat = []`, which will save every timestep. +By default the calculation and result stepsize are the same, with `saveat = []`, which will save every timestep. `saveat` can be a number, which is the saving interval in seconds, or it can be a list of numbers, which are the times in seconds since start that are saved. -For instance, `saveat = 86400.0` will save output after every day that passed. +For instance, `saveat = 86400.0` will save results after every day that passed. The Jacobian matrix provides information about the local sensitivity of the model with respect to changes in the states. For implicit solvers it must be calculated often, which can be expensive to do. @@ -66,12 +66,12 @@ The total maximum number of iterations `maxiters = 1e9`, can normally stay as-is The absolute and relative tolerance for adaptive timestepping can be set with `abstol` and `reltol`. For more information on these and other solver options, see the [DifferentialEquations.jl docs](https://docs.sciml.ai/DiffEqDocs/latest/basics/common_solver_opts/#solver_options). -# GeoPackage and Arrow tables +# GeoPackage database and Arrow tables The input and output tables described below all share that they are tabular files. The Node -and Edge tables always have to be in the [GeoPackage](https://www.geopackage.org/) file, and -output is always written to [Apache Arrow](https://arrow.apache.org/) files, sometimes also -known as Feather files. All other tables can either be in the GeoPackage or in separate +and Edge tables always have to be in the [GeoPackage](https://www.geopackage.org/) database file, and +results are always written to [Apache Arrow](https://arrow.apache.org/) files, sometimes also +known as Feather files. All other tables can either be in the database or in separate Arrow files that are listed in the TOML as described above. For visualization, the Node and Edge tables typically have associated geometries. GeoPackage @@ -82,8 +82,8 @@ can be updated in place when working on a model. Arrow was chosen since it is standardized, fast, simple and flexible. It can be read and written by many different software packages. In Ribasim we use -[Arrow.jl](https://arrow.apache.org/julia/dev/). Output is written to Arrow, since for long -runs output can producs tables with many rows. Arrow is well suited for large tabular +[Arrow.jl](https://arrow.apache.org/julia/dev/). Results are written to Arrow, since for long +runs Ribasim can produce tables with many rows. Arrow is well suited for large tabular datasets, and file size is kept small by using compression. The Arrow input files can be compressed with LZ4 or Zstd compression. Furthermore, in some of the columns, a small amount of different values are repeated many times. To reduce file sizes it may be a good idea to @@ -127,7 +127,7 @@ geometry | geoarrow | (optional) The available node types as of this writing are listed as the top level bullets below. The sub-bullets indicate which tables are associated to the node type. The table name is the -name it must have in the GeoPackage if it is stored there. +name it must have in the database if it is stored there. - Basin: stores water - `Basin / static`: default forcing values, used if no dynamic data given in the forcing table @@ -266,9 +266,9 @@ Internally this get converted to two functions, $A(S)$ and $h(S)$, by integratin The minimum area cannot be zero to avoid numerical issues. The maximum area is used to convert the precipitation flux into an inflow. -## Basin output +## Basin results -The basin table contains outputs of the storage and level of each basin at every solver +The basin table contains results of the storage and level of each basin at every solver timestep. The initial condition is also written to the file. column | type | unit @@ -280,9 +280,9 @@ level | Float64 | $m$ The table is sorted by time, and per time it is sorted by `node_id`. -## Flow output +## Flow results -The flow table contains outputs of the flow on every edge in the model, for each solver +The flow table contains results of the flow on every edge in the model, for each solver timestep. column | type | unit @@ -547,7 +547,7 @@ node_id | Int | - | sorted truth_state | String | - | Consists of the characters "T" (true), "F" (false), "U" (upcrossing), "D" (downcrossing) and "*" (any) control_state | String | - | -## DiscreteControl output +## DiscreteControl results The control table contains a record of each change of control state: when it happened, which control node was involved, to which control state it changed and based on which truth state. diff --git a/docs/python/examples.ipynb b/docs/python/examples.ipynb index eda723d95..8e9a1f861 100644 --- a/docs/python/examples.ipynb +++ b/docs/python/examples.ipynb @@ -390,7 +390,6 @@ "outputs": [], "source": [ "model = ribasim.Model(\n", - " modelname=\"basic\",\n", " node=node,\n", " edge=edge,\n", " basin=basin,\n", @@ -471,7 +470,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = ribasim.Model.from_toml(datadir / \"basic/basic.toml\")" + "model = ribasim.Model.from_toml(datadir / \"basic/ribasim.toml\")" ] }, { @@ -560,7 +559,6 @@ "metadata": {}, "outputs": [], "source": [ - "model.modelname = \"basic_transient\"\n", "model.write(datadir / \"basic_transient\")" ] }, @@ -578,7 +576,7 @@ " \"julia\",\n", " \"--project=../../core\",\n", " \"--eval\",\n", - " f'using Ribasim; Ribasim.run(\"{datadir.as_posix()}/basic_transient/basic_transient.toml\")',\n", + " f'using Ribasim; Ribasim.run(\"{datadir.as_posix()}/basic_transient/ribasim.toml\")',\n", " ],\n", " check=True,\n", ")" @@ -589,8 +587,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now run the model with `ribasim basic-transient/basic.toml`.\n", - "After running the model, read back the output:" + "Now run the model with `ribasim basic-transient/ribasim.toml`.\n", + "After running the model, read back the results:" ] }, { @@ -599,7 +597,7 @@ "metadata": {}, "outputs": [], "source": [ - "df_basin = pd.read_feather(datadir / \"basic_transient/output/basin.arrow\")\n", + "df_basin = pd.read_feather(datadir / \"basic_transient/results/basin.arrow\")\n", "df_basin_wide = df_basin.pivot_table(\n", " index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n", ")\n", @@ -612,7 +610,7 @@ "metadata": {}, "outputs": [], "source": [ - "df_flow = pd.read_feather(datadir / \"basic_transient/output/flow.arrow\")\n", + "df_flow = pd.read_feather(datadir / \"basic_transient/results/flow.arrow\")\n", "df_flow[\"edge\"] = list(zip(df_flow.from_node_id, df_flow.to_node_id))\n", "df_flow[\"flow_m3d\"] = df_flow.flow * 86400\n", "ax = df_flow.pivot_table(index=\"time\", columns=\"edge\", values=\"flow_m3d\").plot()\n", @@ -906,7 +904,6 @@ "outputs": [], "source": [ "model = ribasim.Model(\n", - " modelname=\"level_setpoint_with_minmax\",\n", " node=node,\n", " edge=edge,\n", " basin=basin,\n", @@ -969,7 +966,7 @@ " \"julia\",\n", " \"--project=../../core\",\n", " \"--eval\",\n", - " f'using Ribasim; Ribasim.run(\"{datadir.as_posix()}/level_setpoint_with_minmax/level_setpoint_with_minmax.toml\")',\n", + " f'using Ribasim; Ribasim.run(\"{datadir.as_posix()}/level_setpoint_with_minmax/ribasim.toml\")',\n", " ],\n", " check=True,\n", ")" @@ -979,8 +976,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now run the model with `level_setpoint_with_minmax/level_setpoint_with_minmax.toml`.\n", - "After running the model, read back the output:" + "Now run the model with `level_setpoint_with_minmax/ribasim.toml`.\n", + "After running the model, read back the results:" ] }, { @@ -991,7 +988,7 @@ "source": [ "from matplotlib.dates import date2num\n", "\n", - "df_basin = pd.read_feather(datadir / \"level_setpoint_with_minmax/output/basin.arrow\")\n", + "df_basin = pd.read_feather(datadir / \"level_setpoint_with_minmax/results/basin.arrow\")\n", "df_basin_wide = df_basin.pivot_table(\n", " index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n", ")\n", @@ -1010,7 +1007,7 @@ ")\n", "\n", "df_control = pd.read_feather(\n", - " datadir / \"level_setpoint_with_minmax/output/control.arrow\"\n", + " datadir / \"level_setpoint_with_minmax/results/control.arrow\"\n", ")\n", "\n", "y_min, y_max = ax.get_ybound()\n", @@ -1050,7 +1047,7 @@ "outputs": [], "source": [ "model.print_discrete_control_record(\n", - " datadir / \"level_setpoint_with_minmax/output/control.arrow\"\n", + " datadir / \"level_setpoint_with_minmax/results/control.arrow\"\n", ")" ] }, @@ -1329,7 +1326,6 @@ "outputs": [], "source": [ "model = ribasim.Model(\n", - " modelname=\"pid_control\",\n", " node=node,\n", " edge=edge,\n", " basin=basin,\n", @@ -1390,7 +1386,7 @@ " \"julia\",\n", " \"--project=../../core\",\n", " \"--eval\",\n", - " f'using Ribasim; Ribasim.run(\"{datadir.as_posix()}/pid_control/pid_control.toml\")',\n", + " f'using Ribasim; Ribasim.run(\"{datadir.as_posix()}/pid_control/ribasim.toml\")',\n", " ],\n", " check=True,\n", ")" @@ -1400,8 +1396,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now run the model with `ribasim pid_control/pid_control.toml`.\n", - "After running the model, read back the output:" + "Now run the model with `ribasim pid_control/ribasim.toml`.\n", + "After running the model, read back the results:" ] }, { @@ -1412,7 +1408,7 @@ "source": [ "from matplotlib.dates import date2num\n", "\n", - "df_basin = pd.read_feather(datadir / \"pid_control/output/basin.arrow\")\n", + "df_basin = pd.read_feather(datadir / \"pid_control/results/basin.arrow\")\n", "df_basin_wide = df_basin.pivot_table(\n", " index=\"time\", columns=\"node_id\", values=[\"storage\", \"level\"]\n", ")\n", @@ -1449,7 +1445,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/docs/qgis/index.qmd b/docs/qgis/index.qmd index d6ef00765..ee1d4a7f7 100644 --- a/docs/qgis/index.qmd +++ b/docs/qgis/index.qmd @@ -39,7 +39,7 @@ Documentation on the Time Series widget can be found in the [iMOD documentation] ### Prepare your model -Open example model `basic.gpkg` or create a new model. +Open example model `database.gpkg` or create a new model. ![](https://user-images.githubusercontent.com/4471859/224939126-b38f0eed-2e89-4120-b541-5b8c31798c09.png){fig-align="left"} @@ -47,7 +47,7 @@ Check if your coordinate reference system (CRS) is set correctly. ![](https://user-images.githubusercontent.com/4471859/224939143-19e9931e-da4b-4717-ba28-67a0f141dd40.png){fig-align="left"} -If you are working with an unknown CRS, right click the model GeoPackage group in Layers, +If you are working with an unknown CRS, right click the model database group in Layers, and click "Set Group CRS...". ![](https://user-images.githubusercontent.com/4471859/224939165-45807f16-2d3a-41b3-92a2-7fe0e86ae72b.png){fig-align="left"} @@ -119,34 +119,34 @@ Now leave the edit mode and save the results to the layer. ## Run a model -- Open a text editor and create an empty file next to your GeoPackage, with the `.toml` +- Open a text editor and create an empty file next to your database, with the `.toml` extension. - Add the following content to the TOML file: -```{.TOML filename="basic.toml"} +```{.TOML filename="ribasim.toml"} starttime = 2020-01-01 00:00:00 endtime = 2021-01-01 00:00:00 -geopackage = "basic.gpkg" +database = "database.gpkg" ``` - Unzip the Ribasim command line interface, `ribasim_cli.zip` - Open your terminal and go to the directory where your TOML is stored. Now run - `path/to/ribasim_cli/ribasim basic.toml`. Adjust the path to the `ribasim_cli` folder to + `path/to/ribasim_cli/ribasim ribasim.toml`. Adjust the path to the `ribasim_cli` folder to where you placed it. This runs the model. -- In your model directory there is now an `output/` folder with `basin.arrow` and +- In your model directory there is now a `results/` folder with `basin.arrow` and `flow.arrow` output files. ## Inspect results {#sec-results} -### Associate output to iMOD time series window +### Associate results to iMOD time series window In QGIS select the model group. ![](https://user-images.githubusercontent.com/4471859/224939378-a026aec7-419d-4e6e-8b20-df80aa415659.png){fig-align="left"} -In the Ribasim plugin widget, select the Output tab and click "Associate Output". +In the Ribasim plugin widget, select the Results tab and click "Associate Results". ![](https://user-images.githubusercontent.com/4471859/224939389-17add58d-6701-49c5-a23a-ce367572d9cd.png){fig-align="left"} -Select `output/basin.arrow`. +Select `results/basin.arrow`. ![](https://user-images.githubusercontent.com/4471859/224939408-5c291840-90a4-4efa-a2f0-4fb5986b8779.png){fig-align="left"} diff --git a/docs/schema/Config.schema.json b/docs/schema/Config.schema.json index 0663dad60..58dea9967 100644 --- a/docs/schema/Config.schema.json +++ b/docs/schema/Config.schema.json @@ -28,21 +28,21 @@ "type": "string", "default": "." }, - "output_dir": { + "results_dir": { "format": "default", "type": "string", "default": "." }, - "geopackage": { + "database": { "format": "default", "type": "string" }, - "output": { - "$ref": "https://deltares.github.io/Ribasim/schema/Output.schema.json", + "results": { + "$ref": "https://deltares.github.io/Ribasim/schema/Results.schema.json", "default": { - "basin": "output/basin.arrow", - "flow": "output/flow.arrow", - "control": "output/control.arrow", + "basin": "results/basin.arrow", + "flow": "results/flow.arrow", + "control": "results/control.arrow", "outstate": null, "compression": "zstd", "compression_level": 6 @@ -169,9 +169,9 @@ "update_timestep", "relative_dir", "input_dir", - "output_dir", - "geopackage", - "output", + "results_dir", + "database", + "results", "solver", "logging", "terminal", diff --git a/docs/schema/Output.schema.json b/docs/schema/Results.schema.json similarity index 77% rename from docs/schema/Output.schema.json rename to docs/schema/Results.schema.json index 2b566470d..eb5305fc3 100644 --- a/docs/schema/Output.schema.json +++ b/docs/schema/Results.schema.json @@ -1,24 +1,24 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://deltares.github.io/Ribasim/schema/Output.schema.json", - "title": "Output", - "description": "A Output object based on Ribasim.config.Output", + "$id": "https://deltares.github.io/Ribasim/schema/Results.schema.json", + "title": "Results", + "description": "A Results object based on Ribasim.config.Results", "type": "object", "properties": { "basin": { "format": "default", "type": "string", - "default": "output/basin.arrow" + "default": "results/basin.arrow" }, "flow": { "format": "default", "type": "string", - "default": "output/flow.arrow" + "default": "results/flow.arrow" }, "control": { "format": "default", "type": "string", - "default": "output/control.arrow" + "default": "results/control.arrow" }, "outstate": { "format": "default", diff --git a/python/ribasim/ribasim/config.py b/python/ribasim/ribasim/config.py index cc12c951d..9aa4edfc4 100644 --- a/python/ribasim/ribasim/config.py +++ b/python/ribasim/ribasim/config.py @@ -9,10 +9,10 @@ from pydantic import BaseModel, Field -class Output(BaseModel): - basin: str = "output/basin.arrow" - flow: str = "output/flow.arrow" - control: str = "output/control.arrow" +class Results(BaseModel): + basin: str = "results/basin.arrow" + flow: str = "results/flow.arrow" + control: str = "results/control.arrow" outstate: Optional[str] = None compression: str = "zstd" compression_level: int = 6 @@ -105,14 +105,14 @@ class Config(BaseModel): update_timestep: float = 86400 relative_dir: str = "." input_dir: str = "." - output_dir: str = "." - geopackage: str - output: Output = Field( - default_factory=lambda: Output.parse_obj( + results_dir: str = "." + database: str + results: Results = Field( + default_factory=lambda: Results.parse_obj( { - "basin": "output/basin.arrow", - "flow": "output/flow.arrow", - "control": "output/control.arrow", + "basin": "results/basin.arrow", + "flow": "results/flow.arrow", + "control": "results/control.arrow", "outstate": None, "compression": "zstd", "compression_level": 6, diff --git a/python/ribasim/ribasim/geometry/edge.py b/python/ribasim/ribasim/geometry/edge.py index d5075d331..0d3c47bc7 100644 --- a/python/ribasim/ribasim/geometry/edge.py +++ b/python/ribasim/ribasim/geometry/edge.py @@ -48,7 +48,7 @@ def _layername(cls, field) -> str: def write_layer(self, path: FilePath) -> None: """ - Write the contents of the input to a GeoPackage. + Write the contents of the input to a database. Parameters ---------- @@ -68,7 +68,7 @@ def write_layer(self, path: FilePath) -> None: return @classmethod - def _kwargs_from_geopackage( + def _kwargs_from_database( cls, path: FilePath ) -> Dict[str, Union[DataFrame[Any], GeoDataFrame, None]]: kwargs = {} diff --git a/python/ribasim/ribasim/geometry/node.py b/python/ribasim/ribasim/geometry/node.py index 37145be82..2995abe66 100644 --- a/python/ribasim/ribasim/geometry/node.py +++ b/python/ribasim/ribasim/geometry/node.py @@ -80,7 +80,7 @@ def get_node_ids_and_types(*nodes): def write_layer(self, path: FilePath) -> None: """ - Write the contents of the input to a GeoPackage. + Write the contents of the input to a database. Parameters ---------- @@ -98,7 +98,7 @@ def write_layer(self, path: FilePath) -> None: return @classmethod - def _kwargs_from_geopackage( + def _kwargs_from_database( cls, path: FilePath ) -> Dict[str, Union[GeoDataFrame, DataFrame[Any], None]]: kwargs = {} diff --git a/python/ribasim/ribasim/input_base.py b/python/ribasim/ribasim/input_base.py index 17a5f808c..cba18a57a 100644 --- a/python/ribasim/ribasim/input_base.py +++ b/python/ribasim/ribasim/input_base.py @@ -90,12 +90,12 @@ def _layername(cls, field) -> str: def write_table(self, connection: Connection) -> None: """ - Write the contents of the input to a GeoPackage. + Write the contents of the input to a database. Parameters ---------- connection : Connection - SQLite connection to the GeoPackage. + SQLite connection to the database. """ self.sort() sql = "INSERT INTO gpkg_contents (table_name, data_type, identifier) VALUES (?, ?, ?)" @@ -112,9 +112,7 @@ def write_table(self, connection: Connection) -> None: return @classmethod - def _kwargs_from_geopackage( - cls, path: FilePath - ) -> Dict[str, Union[DataFrame, None]]: + def _kwargs_from_database(cls, path: FilePath) -> Dict[str, Union[DataFrame, None]]: kwargs = {} with connect(path) as connection: for key in cls.fields(): @@ -135,22 +133,22 @@ def _kwargs_from_toml(cls, config: Dict[str, Any]) -> Dict[str, pd.DataFrame]: return {key: pd.read_feather(path) for key, path in config.items()} @classmethod - def from_geopackage(cls, path: FilePath): + def from_database(cls, path: FilePath): """ - Initialize input from a GeoPackage. + Initialize input from a database. - The GeoPackage tables are searched for the relevant table names. + The database tables are searched for the relevant table names. Parameters ---------- path : Path - Path to the GeoPackage. + Path to the database. Returns ------- ribasim_input """ - kwargs = cls._kwargs_from_geopackage(path) + kwargs = cls._kwargs_from_database(path) return cls(**kwargs) @classmethod @@ -158,9 +156,9 @@ def from_config(cls, config: Dict[str, Any]): """ Initialize input from a TOML configuration file. - The GeoPackage tables are searched for the relevant table names. Arrow + The database tables are searched for the relevant table names. Arrow tables will also be read if specified. If a table is present in both - the GeoPackage and as an Arrow table, the data of the Arrow table is + the database and as an Arrow table, the data of the Arrow table is used. Parameters @@ -171,8 +169,8 @@ def from_config(cls, config: Dict[str, Any]): ------- ribasim_input """ - geopackage = config["geopackage"] - kwargs = cls._kwargs_from_geopackage(geopackage) + database = config["database"] + kwargs = cls._kwargs_from_database(database) input_content = config.get(cls.get_input_type(), None) if input_content: kwargs.update(**cls._kwargs_from_toml(config)) diff --git a/python/ribasim/ribasim/model.py b/python/ribasim/ribasim/model.py index 2faf0d502..b829d3fc1 100644 --- a/python/ribasim/ribasim/model.py +++ b/python/ribasim/ribasim/model.py @@ -46,8 +46,6 @@ class Model(BaseModel): Parameters ---------- - modelname : str - Model name, used in TOML and GeoPackage file name. node : Node The ID, type and geometry of each node. edge : Edge @@ -88,7 +86,6 @@ class Model(BaseModel): Logging settings. """ - modelname: str node: Node edge: Edge basin: Basin @@ -138,7 +135,7 @@ def _write_toml(self, directory: FilePath): content = { "starttime": self.starttime, "endtime": self.endtime, - "geopackage": f"{self.modelname}.gpkg", + "database": "database.gpkg", } if self.solver is not None: section = {k: v for k, v in self.solver.dict().items() if v is not None} @@ -151,27 +148,26 @@ def _write_toml(self, directory: FilePath): section = {k: v for k, v in self.logging.dict().items() if v is not None} content["logging"] = section - with open(directory / f"{self.modelname}.toml", "wb") as f: + with open(directory / "ribasim.toml", "wb") as f: tomli_w.dump(content, f) return def _write_tables(self, directory: FilePath) -> None: - """Write the input to GeoPackage tables.""" - # We write all tables to a temporary GeoPackage with a dot prefix, + """Write the input to database tables.""" + # We write all tables to a temporary database with a dot prefix, # and at the end move this over the target file. # This does not throw a PermissionError if the file is open in QGIS. directory = Path(directory) - gpkg_path = directory / f"{self.modelname}.gpkg" - tempname = "." + self.modelname - temp_path = gpkg_path.with_stem(tempname) + db_path = directory / "database.gpkg" + temp_path = db_path.with_stem(".database.gpkg") # avoid adding tables to existing model temp_path.unlink(missing_ok=True) - # write to GeoPackage using geopandas + # write to database using geopandas self.node.write_layer(temp_path) self.edge.write_layer(temp_path) - # write to GeoPackage using sqlite3 + # write to database using sqlite3 with closing(connect(temp_path)) as connection: for name in self.fields(): input_entry = getattr(self, name) @@ -182,7 +178,7 @@ def _write_tables(self, directory: FilePath) -> None: input_entry.write_table(connection) connection.commit() - shutil.move(temp_path, gpkg_path) + shutil.move(temp_path, db_path) return @staticmethod @@ -298,11 +294,9 @@ def validate_model(self): def write(self, directory: FilePath) -> None: """ - Write the contents of the model to a GeoPackage and a TOML configuration file. + Write the contents of the model to a database and a TOML configuration file. If ``directory`` does not exist, it is created before writing. - The GeoPackage and TOML file will be called ``{modelname}.gpkg`` and - ``{modelname}.toml`` respectively. Parameters ---------- @@ -335,8 +329,8 @@ def from_toml(path: FilePath) -> "Model": with open(path, "rb") as f: config = tomli.load(f) - kwargs: dict[str, Any] = {"modelname": path.stem} - config["geopackage"] = path.parent / config["geopackage"] + kwargs: dict[str, Any] = {} + config["database"] = path.parent / config["database"] for module in [geometry, node_types]: for _, node_type_cls in inspect.getmembers(module, inspect.isclass): diff --git a/python/ribasim/tests/test_io.py b/python/ribasim/tests/test_io.py index e9690ee1f..e821cb4e5 100644 --- a/python/ribasim/tests/test_io.py +++ b/python/ribasim/tests/test_io.py @@ -25,9 +25,8 @@ def assert_equal(a, b): def test_basic(basic, tmp_path): model_orig = basic model_orig.write(tmp_path / "basic") - model_loaded = ribasim.Model.from_toml(tmp_path / "basic/basic.toml") + model_loaded = ribasim.Model.from_toml(tmp_path / "basic/ribasim.toml") - assert model_orig.modelname == model_loaded.modelname index_a = model_orig.node.static.index.to_numpy(int) index_b = model_loaded.node.static.index.to_numpy(int) assert_array_equal(index_a, index_b) @@ -39,11 +38,8 @@ def test_basic(basic, tmp_path): def test_basic_transient(basic_transient, tmp_path): model_orig = basic_transient model_orig.write(tmp_path / "basic_transient") - model_loaded = ribasim.Model.from_toml( - tmp_path / "basic_transient/basic_transient.toml" - ) + model_loaded = ribasim.Model.from_toml(tmp_path / "basic_transient/ribasim.toml") - assert model_orig.modelname == model_loaded.modelname assert_equal(model_orig.node.static, model_loaded.node.static) assert_equal(model_orig.edge.static, model_loaded.edge.static) diff --git a/python/ribasim/tests/test_model.py b/python/ribasim/tests/test_model.py index 454bbe3df..b3a1895ef 100644 --- a/python/ribasim/tests/test_model.py +++ b/python/ribasim/tests/test_model.py @@ -109,4 +109,4 @@ def test_node_ids_unsequential(basic): def test_tabulated_rating_curve_model(tabulated_rating_curve, tmp_path): model_orig = tabulated_rating_curve model_orig.write(tmp_path / "tabulated_rating_curve") - Model.from_toml(tmp_path / "tabulated_rating_curve/tabulated_rating_curve.toml") + Model.from_toml(tmp_path / "tabulated_rating_curve/ribasim.toml") diff --git a/python/ribasim_api/tests/test_bmi.py b/python/ribasim_api/tests/test_bmi.py index c4665a63c..d1c81d449 100644 --- a/python/ribasim_api/tests/test_bmi.py +++ b/python/ribasim_api/tests/test_bmi.py @@ -10,13 +10,13 @@ def test_initialize(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) def test_get_start_time(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) time = libribasim.get_start_time() assert time == pytest.approx(0.0) @@ -24,14 +24,14 @@ def test_get_start_time(libribasim, basic, tmp_path): def test_get_current_time(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) assert libribasim.get_current_time() == pytest.approx(libribasim.get_start_time()) def test_get_end_time(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) actual_end_time = libribasim.get_end_time() excepted_end_time = (basic.endtime - basic.starttime).total_seconds() @@ -40,7 +40,7 @@ def test_get_end_time(libribasim, basic, tmp_path): def test_update(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) libribasim.update() time = libribasim.get_current_time() @@ -49,7 +49,7 @@ def test_update(libribasim, basic, tmp_path): def test_update_until(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) expected_time = 60.0 libribasim.update_until(expected_time) @@ -59,7 +59,7 @@ def test_update_until(libribasim, basic, tmp_path): def test_get_var_type(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) var_type = libribasim.get_var_type("volume") assert var_type == "double" @@ -67,7 +67,7 @@ def test_get_var_type(libribasim, basic, tmp_path): def test_get_var_rank(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) actual_rank = libribasim.get_var_rank("volume") expected_rank = 1 @@ -76,7 +76,7 @@ def test_get_var_rank(libribasim, basic, tmp_path): def test_get_var_shape(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) actual_shape = libribasim.get_var_shape("volume") expected_shape = np.array([4]) @@ -85,7 +85,7 @@ def test_get_var_shape(libribasim, basic, tmp_path): def test_get_value_ptr(libribasim, basic, tmp_path): basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) actual_volume = libribasim.get_value_ptr("volume") expected_volume = np.array([1.0, 1.0, 1.0, 1.0]) @@ -98,7 +98,7 @@ def test_err_unknown_var(libribasim, basic, tmp_path): print the kernel error, and not crash the library """ basic.write(tmp_path) - config_file = str(tmp_path / f"{basic.modelname}.toml") + config_file = str(tmp_path / "ribasim.toml") libribasim.initialize(config_file) variable_name = "var-that-does-not-exist" diff --git a/python/ribasim_testmodels/ribasim_testmodels/__init__.py b/python/ribasim_testmodels/ribasim_testmodels/__init__.py index 028a1d947..8e7e8d71a 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/__init__.py +++ b/python/ribasim_testmodels/ribasim_testmodels/__init__.py @@ -1,5 +1,10 @@ __version__ = "0.2.0" +from typing import Callable, Dict + +import ribasim + +import ribasim_testmodels from ribasim_testmodels.allocation import ( looped_subnetwork_model, subnetwork_model, @@ -71,3 +76,10 @@ "subnetwork_model", "looped_subnetwork_model", ] + +# provide a mapping from model name to its constructor, so we can iterate over all models +constructors: Dict[str, Callable[[], ribasim.Model]] = {} +for model_name_model in __all__: + model_name = model_name_model.removesuffix("_model") + model_constructor = getattr(ribasim_testmodels, model_name_model) + constructors[model_name] = model_constructor diff --git a/python/ribasim_testmodels/ribasim_testmodels/allocation.py b/python/ribasim_testmodels/ribasim_testmodels/allocation.py index 2c9b6786e..faa3ef8d9 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/allocation.py +++ b/python/ribasim_testmodels/ribasim_testmodels/allocation.py @@ -110,7 +110,6 @@ def user_model(): solver = ribasim.Solver(algorithm="Tsit5") model = ribasim.Model( - modelname="user", node=node, edge=edge, basin=basin, @@ -272,7 +271,6 @@ def subnetwork_model(): ) model = ribasim.Model( - modelname="subnetwork", node=node, edge=edge, basin=basin, @@ -520,7 +518,6 @@ def looped_subnetwork_model(): ) model = ribasim.Model( - modelname="looped_subnetwork", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/backwater.py b/python/ribasim_testmodels/ribasim_testmodels/backwater.py index c87e0b7c5..2a5ae844a 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/backwater.py +++ b/python/ribasim_testmodels/ribasim_testmodels/backwater.py @@ -93,7 +93,6 @@ def backwater_model(): ) model = ribasim.Model( - modelname="backwater", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/basic.py b/python/ribasim_testmodels/ribasim_testmodels/basic.py index 1ff43127f..710f4bf5b 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/basic.py +++ b/python/ribasim_testmodels/ribasim_testmodels/basic.py @@ -194,7 +194,6 @@ def basic_model() -> ribasim.Model: # Setup a model: model = ribasim.Model( - modelname="basic", node=node, edge=edge, basin=basin, @@ -263,7 +262,6 @@ def basic_transient_model() -> ribasim.Model: model.basin.state = state model.logging = None - model.modelname = "basic_transient" return model @@ -373,7 +371,6 @@ def tabulated_rating_curve_model() -> ribasim.Model: # Setup a model: model = ribasim.Model( - modelname="tabulated_rating_curve", node=node, edge=edge, basin=basin, @@ -477,7 +474,6 @@ def outlet_model(): ) model = ribasim.Model( - modelname="outlet", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/bucket.py b/python/ribasim_testmodels/ribasim_testmodels/bucket.py index 9d79633eb..f46b9931c 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/bucket.py +++ b/python/ribasim_testmodels/ribasim_testmodels/bucket.py @@ -70,7 +70,6 @@ def bucket_model() -> ribasim.Model: basin = ribasim.Basin(profile=profile, static=static, state=state) model = ribasim.Model( - modelname="bucket", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py b/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py index 926f055d3..9465135d8 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py +++ b/python/ribasim_testmodels/ribasim_testmodels/discrete_control.py @@ -127,7 +127,6 @@ def pump_discrete_control_model() -> ribasim.Model: # Setup a model: model = ribasim.Model( - modelname="pump_discrete_control", node=node, edge=edge, basin=basin, @@ -267,7 +266,6 @@ def flow_condition_model(): # Setup a model: model = ribasim.Model( - modelname="flow_condition", node=node, edge=edge, basin=basin, @@ -415,7 +413,6 @@ def level_boundary_condition_model(): ) model = ribasim.Model( - modelname="level_boundary_condition", node=node, edge=edge, basin=basin, @@ -549,7 +546,6 @@ def tabulated_rating_curve_control_model() -> ribasim.Model: # Setup a model: model = ribasim.Model( - modelname="tabulated_rating_curve_control", node=node, edge=edge, basin=basin, @@ -690,7 +686,6 @@ def level_setpoint_with_minmax_model(): discrete_control = ribasim.DiscreteControl(condition=condition, logic=logic) model = ribasim.Model( - modelname="level_setpoint_with_minmax", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py b/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py index 73551d2d1..a39b76b7b 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py +++ b/python/ribasim_testmodels/ribasim_testmodels/dutch_waterways.py @@ -276,7 +276,6 @@ def dutch_waterways_model(): ) model = ribasim.Model( - modelname="dutch_waterways", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/equations.py b/python/ribasim_testmodels/ribasim_testmodels/equations.py index 67b1c5c0f..9c4be85d2 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/equations.py +++ b/python/ribasim_testmodels/ribasim_testmodels/equations.py @@ -91,7 +91,6 @@ def linear_resistance_model(): # Setup a model: model = ribasim.Model( - modelname="linear_resistance", node=node, edge=edge, basin=basin, @@ -200,7 +199,6 @@ def rating_curve_model(): # Setup a model: model = ribasim.Model( - modelname="rating_curve", node=node, edge=edge, basin=basin, @@ -298,7 +296,6 @@ def manning_resistance_model(): # Setup a model: model = ribasim.Model( - modelname="manning_resistance", node=node, edge=edge, basin=basin, @@ -439,7 +436,6 @@ def misc_nodes_model(): # Setup a model: model = ribasim.Model( - modelname="misc_nodes", node=node, edge=edge, basin=basin, @@ -559,7 +555,6 @@ def pid_control_equation_model(): ) model = ribasim.Model( - modelname="pid_control_equation", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/invalid.py b/python/ribasim_testmodels/ribasim_testmodels/invalid.py index 459edcaaa..c94860665 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/invalid.py +++ b/python/ribasim_testmodels/ribasim_testmodels/invalid.py @@ -85,7 +85,6 @@ def invalid_qh_model(): ) model = ribasim.Model( - modelname="invalid_qh", edge=edge, node=node, basin=basin, @@ -187,7 +186,6 @@ def invalid_fractional_flow_model(): ) model = ribasim.Model( - modelname="invalid_fractional_flow", node=node, edge=edge, basin=basin, @@ -316,7 +314,6 @@ def invalid_discrete_control_model(): discrete_control = ribasim.DiscreteControl(condition=condition, logic=logic) model = ribasim.Model( - modelname="invalid_discrete_control", node=node, edge=edge, basin=basin, @@ -405,7 +402,6 @@ def invalid_edge_types_model(): # Setup a model: model = ribasim.Model( - modelname="invalid_edge_types", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/pid_control.py b/python/ribasim_testmodels/ribasim_testmodels/pid_control.py index b8fc718d9..367cfb3a2 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/pid_control.py +++ b/python/ribasim_testmodels/ribasim_testmodels/pid_control.py @@ -144,7 +144,6 @@ def pid_control_model(): # Setup a model: model = ribasim.Model( - modelname="pid_control", node=node, edge=edge, basin=basin, @@ -319,7 +318,6 @@ def discrete_control_of_pid_control_model(): # Setup a model: model = ribasim.Model( - modelname="discrete_control_of_pid_control", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/time.py b/python/ribasim_testmodels/ribasim_testmodels/time.py index f4b3469eb..a483df3f0 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/time.py +++ b/python/ribasim_testmodels/ribasim_testmodels/time.py @@ -92,7 +92,6 @@ def flow_boundary_time_model(): ) model = ribasim.Model( - modelname="flow_boundary_time", node=node, edge=edge, basin=basin, diff --git a/python/ribasim_testmodels/ribasim_testmodels/trivial.py b/python/ribasim_testmodels/ribasim_testmodels/trivial.py index bd9c554a4..dcb00ee08 100644 --- a/python/ribasim_testmodels/ribasim_testmodels/trivial.py +++ b/python/ribasim_testmodels/ribasim_testmodels/trivial.py @@ -97,7 +97,6 @@ def trivial_model() -> ribasim.Model: ) model = ribasim.Model( - modelname="trivial", node=node, edge=edge, basin=basin, diff --git a/qgis/core/geopackage.py b/qgis/core/geopackage.py index fc68c1ccd..1af432c7b 100644 --- a/qgis/core/geopackage.py +++ b/qgis/core/geopackage.py @@ -50,7 +50,7 @@ def write_layer( path: str, layer: QgsVectorLayer, layername: str, newfile: bool = False ) -> QgsVectorLayer: """ - Write a QgsVectorLayer to a GeoPackage file. + Write a QgsVectorLayer to a GeoPackage database. Parameters ---------- @@ -61,7 +61,7 @@ def write_layer( layername: str Layer name to write in the GeoPackage newfile: bool, optional - Whether to write a new GPGK file. Defaults to false. + Whether to write a new GeoPackage file. Defaults to false. Returns ------- diff --git a/qgis/widgets/output_widget.py b/qgis/widgets/results_widget.py similarity index 54% rename from qgis/widgets/output_widget.py rename to qgis/widgets/results_widget.py index c85b8df6c..e096391b1 100644 --- a/qgis/widgets/output_widget.py +++ b/qgis/widgets/results_widget.py @@ -1,21 +1,21 @@ from PyQt5.QtWidgets import QFileDialog, QPushButton, QVBoxLayout, QWidget -class OutputWidget(QWidget): +class ResultsWidget(QWidget): def __init__(self, parent): super().__init__(parent) self.parent = parent - self.node_output_button = QPushButton("Associate Node Output") - self.edge_output_button = QPushButton("Associate Edge Output") - self.node_output_button.clicked.connect(self.set_node_output) - self.edge_output_button.clicked.connect(self.set_edge_output) + self.node_results_button = QPushButton("Associate Node Results") + self.edge_results_button = QPushButton("Associate Edge Results") + self.node_results_button.clicked.connect(self.set_node_results) + self.edge_results_button.clicked.connect(self.set_edge_results) layout = QVBoxLayout() - layout.addWidget(self.node_output_button) - layout.addWidget(self.edge_output_button) + layout.addWidget(self.node_results_button) + layout.addWidget(self.edge_results_button) layout.addStretch() self.setLayout(layout) - def _set_output(self, layer, column: str): + def _set_results(self, layer, column: str): path, _ = QFileDialog.getOpenFileName(self, "Select file", "", "*.arrow") if path == "": return @@ -25,12 +25,12 @@ def _set_output(self, layer, column: str): layer.setCustomProperty("arrow_fid_column", column) return - def set_node_output(self): + def set_node_results(self): node_layer = self.parent.dataset_widget.node_layer - self._set_output(node_layer, "node_id") + self._set_results(node_layer, "node_id") return - def set_edge_output(self): + def set_edge_results(self): edge_layer = self.parent.dataset_widget.edge_layer - self._set_output(edge_layer, "edge_id") + self._set_results(edge_layer, "edge_id") return diff --git a/qgis/widgets/ribasim_widget.py b/qgis/widgets/ribasim_widget.py index be9eee484..6d3303952 100644 --- a/qgis/widgets/ribasim_widget.py +++ b/qgis/widgets/ribasim_widget.py @@ -11,7 +11,7 @@ from PyQt5.QtWidgets import QTabWidget, QVBoxLayout, QWidget from ribasim_qgis.widgets.dataset_widget import DatasetWidget from ribasim_qgis.widgets.nodes_widget import NodesWidget -from ribasim_qgis.widgets.output_widget import OutputWidget +from ribasim_qgis.widgets.results_widget import ResultsWidget from qgis.core import QgsEditFormConfig, QgsMapLayer, QgsProject @@ -27,15 +27,15 @@ def __init__(self, parent, iface): self.dataset_widget = DatasetWidget(self) self.nodes_widget = NodesWidget(self) - self.output_widget = OutputWidget(self) + self.results_widget = ResultsWidget(self) # Layout self.layout = QVBoxLayout() self.tabwidget = QTabWidget() self.layout.addWidget(self.tabwidget) - self.tabwidget.addTab(self.dataset_widget, "GeoPackage") + self.tabwidget.addTab(self.dataset_widget, "Database") self.tabwidget.addTab(self.nodes_widget, "Nodes") - self.tabwidget.addTab(self.output_widget, "Output") + self.tabwidget.addTab(self.results_widget, "Results") self.setLayout(self.layout) # QGIS Layers Panel groups diff --git a/utils/generate-testmodels.py b/utils/generate-testmodels.py index eee50541f..4f88eb92b 100644 --- a/utils/generate-testmodels.py +++ b/utils/generate-testmodels.py @@ -18,12 +18,6 @@ Don't put important stuff in here, it will be emptied for every run.""" ) - models = [ - model_generator() - for model_generator in map( - ribasim_testmodels.__dict__.get, ribasim_testmodels.__all__ - ) - ] - - for model in models: - model.write(datadir / model.modelname) + for model_name, model_constructor in ribasim_testmodels.constructors.items(): + model = model_constructor() + model.write(datadir / model_name) diff --git a/utils/runstats.jl b/utils/runstats.jl index 64a9026d9..9138b585b 100644 --- a/utils/runstats.jl +++ b/utils/runstats.jl @@ -107,7 +107,7 @@ function get_testmodels()::Vector{String} toml_paths = String[] for dir in dirs if !startswith(dir, "invalid_") - toml_path = normpath("generated_testmodels", dir, "$dir.toml") + toml_path = normpath("generated_testmodels", dir, "ribasim.toml") @assert isfile(toml_path) push!(toml_paths, toml_path) end From 097053cd6e6b2490fe7700e8be3848cf29431822 Mon Sep 17 00:00:00 2001 From: hofer_jn Date: Mon, 23 Oct 2023 08:58:54 +0200 Subject: [PATCH 5/5] TeamCity change in 'Ribasim / Ribasim' project: general settings of 'Test ribasim_cli - Windows' build configuration were updated --- .../buildTypes/Ribasim_Ribasim_TestRibasimCliWindows.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.teamcity/Ribasim_Ribasim/buildTypes/Ribasim_Ribasim_TestRibasimCliWindows.xml b/.teamcity/Ribasim_Ribasim/buildTypes/Ribasim_Ribasim_TestRibasimCliWindows.xml index 9a5317067..f00c7a59a 100644 --- a/.teamcity/Ribasim_Ribasim/buildTypes/Ribasim_Ribasim_TestRibasimCliWindows.xml +++ b/.teamcity/Ribasim_Ribasim/buildTypes/Ribasim_Ribasim_TestRibasimCliWindows.xml @@ -4,7 +4,7 @@ -