Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fc5d14f
first draft
SouthEndMusic Nov 3, 2025
c6334ae
Make nicer API
SouthEndMusic Nov 4, 2025
44890bb
Merge branch 'master' into internal_SI_units
SouthEndMusic Nov 4, 2025
90157e9
Add missing units, convert units in standard_name.jl
SouthEndMusic Nov 4, 2025
b082b0a
Convert to SI unit in `set_states!`
SouthEndMusic Nov 4, 2025
c36879a
Towards taking units into account in `ncread`
SouthEndMusic Nov 5, 2025
84ae4e7
Generalize the Unit system and add to docstring how to add new unit
SouthEndMusic Nov 6, 2025
ffc771a
All test models are initializable again
SouthEndMusic Nov 7, 2025
c65fe13
Store unit in InputEntry
SouthEndMusic Nov 7, 2025
4923e5e
Pass all IO tests
SouthEndMusic Nov 11, 2025
2b29e9b
Some fixes and many computation unit annotations
SouthEndMusic Nov 18, 2025
d5265e9
Merge branch 'master' into internal_SI_units
SouthEndMusic Nov 18, 2025
7720cc9
Pretty printing of info data in tables
SouthEndMusic Nov 18, 2025
4e73d82
Improved info message format
SouthEndMusic Nov 20, 2025
14bbe5f
More units!
SouthEndMusic Nov 24, 2025
c68a5c9
Merge branch 'master' into internal_SI_units
SouthEndMusic Nov 24, 2025
ef7f28a
nits
SouthEndMusic Nov 24, 2025
88b4aa6
Remove debug toml
SouthEndMusic Nov 24, 2025
daf39d1
Re-ignore debug TOML
SouthEndMusic Nov 24, 2025
47c196a
Improve unit performance
SouthEndMusic Nov 25, 2025
a2f36bd
Fixes
SouthEndMusic Nov 25, 2025
6724bb1
More code cleanup
SouthEndMusic Nov 26, 2025
d03c626
Merge branch 'master' into internal_SI_units
SouthEndMusic Nov 26, 2025
4d66f93
Fixes
SouthEndMusic Nov 26, 2025
b9a1b2d
Pass all vertical process unit tests
SouthEndMusic Nov 27, 2025
8407112
Pass all reservoir tests
SouthEndMusic Dec 1, 2025
e4da6be
Many unit updates + sediment code cleanup
SouthEndMusic Dec 4, 2025
e0f1110
Merge branch 'master' into internal_SI_units
SouthEndMusic Dec 4, 2025
5b07f9a
more fixes
SouthEndMusic Dec 4, 2025
679db4f
Fixes
SouthEndMusic Dec 4, 2025
c10b34e
More fixes
SouthEndMusic Dec 9, 2025
4448812
Merge branch 'master' into internal_SI_units
SouthEndMusic Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
/dev/
/Wflow/test/data/
/tmp/
/Wflow/test/sbm_piave_config-debug.toml

# Build files
/build/create_binaries/wflow_bundle/
Expand Down
84 changes: 77 additions & 7 deletions Wflow/Manifest.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# This file is machine-generated - editing it directly is not advised

julia_version = "1.11.7"
julia_version = "1.11.6"
manifest_format = "2.0"
project_hash = "148175f27ef6c8998b573b6ac910e2135dc65a34"
project_hash = "5d1fe94697c628916f3f529fcebaeeebdadb2781"

[[deps.AbstractTrees]]
git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177"
Expand Down Expand Up @@ -193,12 +193,27 @@ git-tree-sha1 = "fcbb72b032692610bfbdb15018ac16a36cf2e406"
uuid = "adafc99b-e345-5852-983c-f28acb93d879"
version = "0.3.1"

[[deps.Crayons]]
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"

[[deps.DataAPI]]
git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.16.0"

[[deps.DataStructures]]
deps = ["OrderedCollections"]
git-tree-sha1 = "e357641bb3e0638d353c4b29ea0e40ea644066a6"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.19.3"

[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down Expand Up @@ -247,9 +262,9 @@ version = "1.15.0"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[deps.Glob]]
git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496"
git-tree-sha1 = "83cb0092e2792b9e3a865b6655e88f5b862607e2"
uuid = "c27321d9-0574-5035-807b-f59d2c89b15c"
version = "1.3.1"
version = "1.4.0"

[[deps.Graphs]]
deps = ["ArnoldiMethod", "DataStructures", "Inflate", "LinearAlgebra", "Random", "SimpleTraits", "SparseArrays", "Statistics"]
Expand Down Expand Up @@ -304,6 +319,11 @@ version = "0.1.17"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[deps.JLLWrappers]]
deps = ["Artifacts", "Preferences"]
git-tree-sha1 = "0533e564aae234aff59ab625543145446d8b6ec2"
Expand All @@ -319,6 +339,11 @@ weakdeps = ["Serialization"]
[deps.LRUCache.extensions]
SerializationExt = ["Serialization"]

[[deps.LaTeXStrings]]
git-tree-sha1 = "dda21b8cbd6a6c40d9d02a73230f9d70fed6918c"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.4.0"

[[deps.LayoutPointers]]
deps = ["ArrayInterface", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface"]
git-tree-sha1 = "a9eaadb366f5493a5654e843864c13d8b107548c"
Expand Down Expand Up @@ -507,13 +532,11 @@ version = "0.12.3"
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.11.0"
weakdeps = ["REPL"]

[deps.Pkg.extensions]
REPLExt = "REPL"

[deps.Pkg.weakdeps]
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Polyester]]
deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"]
git-tree-sha1 = "6f7cd22a802094d239824c57d94c8e2d0f7cfc7d"
Expand All @@ -538,6 +561,12 @@ git-tree-sha1 = "0f27480397253da18fe2c12a4ba4eb9eb208bf3d"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.5.0"

[[deps.PrettyTables]]
deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "REPL", "Reexport", "StringManipulation", "Tables"]
git-tree-sha1 = "c5a07210bd060d6a8491b0ccdee2fa0235fc00bf"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "3.1.2"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Expand All @@ -554,11 +583,21 @@ git-tree-sha1 = "a6b4c12d38387a4382fa53b8a6591f9c219add16"
uuid = "f8a19df8-e894-5f55-a973-672c1158cbca"
version = "0.2.1"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
version = "1.11.0"

[[deps.Random]]
deps = ["SHA"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
version = "1.11.0"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "62389eeff14780bfe55195b7204c0d8738436d64"
Expand Down Expand Up @@ -589,6 +628,10 @@ git-tree-sha1 = "be8eeac05ec97d379347584fa9fe2f5f76795bcb"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.5"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
version = "1.11.0"

[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Expand Down Expand Up @@ -646,6 +689,21 @@ git-tree-sha1 = "83151ba8065a73f53ca2ae98bc7274d817aa30f2"
uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da"
version = "0.5.8"

[[deps.StringManipulation]]
deps = ["PrecompileTools"]
git-tree-sha1 = "a3c1536470bf8c5e02096ad4853606d7c8f62721"
uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
version = "0.4.2"

[[deps.StyledStrings]]
uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b"
version = "1.11.0"

[[deps.Subscripts]]
git-tree-sha1 = "03b2afbef5bf39f45308c979488d0baaacea9cd9"
uuid = "2b7f82d5-8785-4f63-971e-f18ddbeb808e"
version = "0.1.3"

[[deps.SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
Expand All @@ -656,6 +714,18 @@ deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"

[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"]
git-tree-sha1 = "f2c1efbc8f3a609aadf318094f8fc5204bdaf344"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.12.1"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
Expand Down
10 changes: 7 additions & 3 deletions Wflow/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ CFTime = "179af706-886a-5703-950a-314cd64e0468"
CompositionsBase = "a33af91c-f02d-484b-be07-31d278c5ca2b"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
EnumX = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
Glob = "c27321d9-0574-5035-807b-f59d2c89b15c"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
NCDatasets = "85f8d34a-cbdd-5861-8df4-14fed0d494ab"
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
ProgressLogging = "33c8b6b6-d38a-422a-b730-caa89a2f386c"
PropertyDicts = "f8a19df8-e894-5f55-a973-672c1158cbca"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Subscripts = "2b7f82d5-8785-4f63-971e-f18ddbeb808e"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
TerminalLoggers = "5d786b92-1e48-4d6f-9151-6b4477ca9bed"

Expand All @@ -34,26 +36,28 @@ CompositionsBase = "0.1.2"
Dates = "1"
DelimitedFiles = "1"
Downloads = "1"
FillArrays = "1.14.0"
EnumX = "1.0.5"
FillArrays = "1.14.0"
Glob = "1.3"
Graphs = "1.4"
LoggingExtras = "0.4.6,0.5,1"
NCDatasets = "0.13.2, 0.14"
Parameters = "0.12"
Polyester = "0.7.10"
Polynomials = "3,4"
PrettyTables = "3.0.11"
ProgressLogging = "0.1"
PropertyDicts = "0.2.1"
QuadGK = "2"
Random = "1"
SpecialFunctions = "2.5.1"
StaticArrays = "0.12,1.0"
Statistics = "1"
Subscripts = "0.1.3"
TOML = "1"
TerminalLoggers = "0.1.5"
TestItemRunner = "1.1"
Test = "1"
TestItemRunner = "1.1"
julia = "1.10"

[extras]
Expand Down
53 changes: 51 additions & 2 deletions Wflow/src/Wflow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,16 @@ using StaticArrays: SVector, pushfirst, setindex
using Statistics: mean, median, quantile!, quantile
using TerminalLoggers
using TOML: TOML
using PrettyTables: pretty_table
import Subscripts

const CFDataset = Union{NCDataset, NCDatasets.MFDataset}
const CFVariable_MF = Union{NCDatasets.CFVariable, NCDatasets.MFCFVariable}
const VERSION =
VersionNumber(TOML.parsefile(joinpath(@__DIR__, "..", "Project.toml"))["version"])

g_gravity = 9.81 # m s⁻²

mutable struct Clock{T}
time::T
iteration::Int
Expand Down Expand Up @@ -126,6 +130,28 @@ struct SbmModel <: AbstractModelType end # "sbm" type / sbm_model.jl
struct SbmGwfModel <: AbstractModelType end # "sbm_gwf" type / sbm_gwf_model.jl
struct SedimentModel <: AbstractModelType end # "sediment" type / sediment_model.jl

"""
The AverageVector is a struct for computing averages of a some quantity with unit [u]
over a timestep dt [s].
"""
@with_kw struct AverageVector
n::Int
# Cumulative value [u]
cumulative::Vector{Float64} = zeros(n)
# Average value [u s⁻¹]
average::Vector{Float64} = zeros(n)
end

add_to_cumulative!(v::AverageVector, i::Int, val::Number) = (v.cumulative[i] += val)
average!(v::AverageVector, dt::Number) = (@. v.average = v.cumulative / dt)
zero!(v::AverageVector) = (v.cumulative .= 0)
Base.eltype(::AverageVector) = Float64
Base.iterate(v::AverageVector) = iterate(v.average)
Base.iterate(v::AverageVector, state) = iterate(v.average, state)
Base.length(v::AverageVector) = length(v.average)
Base.collect(v::AverageVector) = v.average

include("units.jl")
include("config_structure.jl")
include("config_utils.jl")
include("config_init.jl")
Expand Down Expand Up @@ -222,7 +248,24 @@ include("sediment_flux.jl")
include("sediment_model.jl")
include("routing/initialize_routing.jl")
include("sbm_gwf_model.jl")
include("standard_name.jl")

include("standard_name/standard_name_domain.jl")
include("standard_name/standard_name_routing.jl")
include("standard_name/standard_name_sbm.jl")
include("standard_name/standard_name_sediment.jl")

# wrapper methods for standard name mapping
standard_name_map(model) = standard_name_map(typeof(model))
standard_name_map(::Type{<:LandHydrologySBM}) = sbm_standard_name_map
standard_name_map(::Type{<:SoilLoss}) = sediment_standard_name_map
standard_name_map(::Type{<:Domain}) = domain_standard_name_map
standard_name_map(::Type{<:Routing}) = routing_standard_name_map
get_lens(name::AbstractString, model) = get_lens(name, typeof(model))
get_lens(name::AbstractString, L::Type) = standard_name_map(L)[name].lens
get_unit(name::AbstractString, model) = get_unit(name, typeof(model))
get_unit(name::AbstractString, L::Type) = standard_name_map(L)[name].unit
get_unit(::AbstractString, ::Type{<:Writer}) = Unit()

include("utils.jl")
include("bmi.jl")
include("subdomains.jl")
Expand Down Expand Up @@ -307,7 +350,13 @@ function run!(model::Model; close_files = true)
endtime = cftime(config.time.endtime, config.time.calendar)
times = range(starttime + dt, endtime; step = dt)

@info "Run information" model_type = String(Symbol(model_type)) starttime dt endtime nthreads()
@info "Run information." * to_table(;
model_type = String(Symbol(model_type)),
starttime,
dt,
endtime,
nthreads = nthreads(),
)
runstart_time = now()
@progress for (i, time) in enumerate(times)
@debug "Starting timestep." time i now()
Expand Down
16 changes: 11 additions & 5 deletions Wflow/src/bmi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ end

function BMI.get_var_units(model::Model, name::String)
(; land) = model
nt = standard_name_map(land)[name]
return nt.unit
(; unit) = standard_name_map(land)[name]
return to_string(to_SI(unit); BMI_standard = true)
end

function BMI.get_var_itemsize(model::Model, name::String)
Expand All @@ -176,7 +176,8 @@ function BMI.get_current_time(model::Model)
(; config, clock) = model
(; starttime, calendar) = config.time
starttime = cftime(starttime, calendar)
return 0.001 * Dates.value(clock.time - starttime)
# ms => s
return Dates.value(clock.time - starttime) / 1e3
end

function BMI.get_start_time(::Model)
Expand All @@ -187,7 +188,8 @@ function BMI.get_end_time(model::Model)
(; starttime, endtime, calendar) = model.config.time
starttime_ = cftime(starttime, calendar)
endtime_ = cftime(endtime, calendar)
return 0.001 * Dates.value(endtime_ - starttime_)
# ms => s
return to_SI(Float64(Dates.value(endtime_ - starttime_)), Unit(; ms = 1))
end

function BMI.get_time_units(model::Model)
Expand Down Expand Up @@ -217,7 +219,11 @@ function BMI.get_value_ptr(model::Model, name::String)
return @view value[ind, 1:n]
else
lens = standard_name_map(land)[name].lens
return @view(lens(model)[1:n])
vec = lens(model)
if vec isa AverageVector
vec = vec.average
end
return @view(vec[1:n])
end
end

Expand Down
3 changes: 3 additions & 0 deletions Wflow/src/config_init.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ function init_config_section(::Type{InputEntry}, dict::AbstractDict{String})

# Invoke default method
return init_config_section_default(InputEntry, dict)
elseif value isa String
# Option 3
return InputEntry(; external_name = value)
elseif !isnothing(value)
# Option 2
return InputEntry(; value)
Expand Down
2 changes: 2 additions & 0 deletions Wflow/src/config_structure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ end
Base.haskey(input_entries::InputEntries, key) = haskey(input_entries.dict, key)
Base.getindex(input_entries::InputEntries, key) = input_entries.dict[key]
Base.setindex!(input_entries::InputEntries, value, key) = (input_entries.dict[key] = value)
Base.setindex!(input_entries::InputEntries, value::AbstractDict, key) =
(input_entries.dict[key] = init_config_section(InputEntry, value))
Base.keys(input_entries::InputEntries) = keys(input_entries.dict)
Base.iterate(input_entries::InputEntries) = iterate(input_entries.dict)
Base.iterate(input_entries::InputEntries, state) = iterate(input_entries.dict, state)
Expand Down
Loading
Loading