From 9198fb1be7c01aabae68bbf9a3b535bea5c6d13c Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Tue, 1 Jul 2025 15:20:04 +0200 Subject: [PATCH 1/4] Add Adapt as dependency --- Wflow/Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Wflow/Project.toml b/Wflow/Project.toml index f5d27b3f2..5ff9d1181 100644 --- a/Wflow/Project.toml +++ b/Wflow/Project.toml @@ -5,6 +5,7 @@ version = "1.0.0-rc2-dev" [deps] Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" +Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" BasicModelInterface = "59605e27-edc0-445a-b93d-c09a3a50b330" CFTime = "179af706-886a-5703-950a-314cd64e0468" CompositionsBase = "a33af91c-f02d-484b-be07-31d278c5ca2b" @@ -24,6 +25,7 @@ TerminalLoggers = "5d786b92-1e48-4d6f-9151-6b4477ca9bed" [compat] Accessors = "0.1" +Adapt = "4.3.0" Aqua = "0.8" BasicModelInterface = "0.1" CFTime = "0.1, 0.2" From 9a2bbd1deb8593c6a9ff86cd0c7ad6e1f5e55c00 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Wed, 2 Jul 2025 11:22:22 +0200 Subject: [PATCH 2/4] Make LocalInertialRiverFlow and related structs parametric, allow adapting to GPU --- Wflow/src/Wflow.jl | 1 + Wflow/src/demand/water_demand.jl | 12 +- Wflow/src/io.jl | 10 +- Wflow/src/routing/reservoir.jl | 82 +++++++----- Wflow/src/routing/surface_kinwave.jl | 14 ++- Wflow/src/routing/surface_local_inertial.jl | 131 +++++++++++--------- Wflow/src/routing/timestepping.jl | 9 +- Wflow/test/reservoir.jl | 4 +- 8 files changed, 159 insertions(+), 104 deletions(-) diff --git a/Wflow/src/Wflow.jl b/Wflow/src/Wflow.jl index 9628d7006..f495f415c 100644 --- a/Wflow/src/Wflow.jl +++ b/Wflow/src/Wflow.jl @@ -3,6 +3,7 @@ module Wflow import BasicModelInterface as BMI using Accessors: @optic, @reset, PropertyLens +import Adapt: adapt, @adapt_structure, adapt_structure using Base.Threads: nthreads using CFTime: CFTime, monthday, dayofyear using CompositionsBase: decompose diff --git a/Wflow/src/demand/water_demand.jl b/Wflow/src/demand/water_demand.jl index ff1d75564..fbb9de7ed 100644 --- a/Wflow/src/demand/water_demand.jl +++ b/Wflow/src/demand/water_demand.jl @@ -438,12 +438,13 @@ function Demand( end "Struct to store river allocation model variables" -@with_kw struct AllocationRiverVariables - act_surfacewater_abst::Vector{Float64} # actual surface water abstraction [mm Δt⁻¹] - act_surfacewater_abst_vol::Vector{Float64} # actual surface water abstraction [m³ Δt⁻¹] - available_surfacewater::Vector{Float64} # available surface water [m³] - nonirri_returnflow::Vector{Float64} # return flow from non irrigation [mm Δt⁻¹] +@with_kw struct AllocationRiverVariables{T <: AbstractArray{<:AbstractFloat}} + act_surfacewater_abst::T # actual surface water abstraction [mm Δt⁻¹] + act_surfacewater_abst_vol::T # actual surface water abstraction [m³ Δt⁻¹] + available_surfacewater::T # available surface water [m³] + nonirri_returnflow::T # return flow from non irrigation [mm Δt⁻¹] end +@adapt_structure AllocationRiverVariables "Initialize river allocation model variables" function AllocationRiverVariables(n::Int) @@ -459,6 +460,7 @@ end @with_kw struct AllocationRiver <: AbstractAllocationModel variables::AllocationRiverVariables end +@adapt_structure AllocationRiver get_nonirrigation_returnflow(model::AllocationRiver) = model.variables.nonirri_returnflow get_nonirrigation_returnflow(model::NoAllocationRiver) = 0.0 diff --git a/Wflow/src/io.jl b/Wflow/src/io.jl index 6a4ed33ac..5d48025cf 100644 --- a/Wflow/src/io.jl +++ b/Wflow/src/io.jl @@ -1426,8 +1426,14 @@ function read_hq_csv(path) end # these represent the type of the rating curve and specific storage data -const SH = NamedTuple{(:H, :S), Tuple{Vector{Float64}, Vector{Float64}}} -const HQ = NamedTuple{(:H, :Q), Tuple{Vector{Float64}, Matrix{Float64}}} +const SH = NamedTuple{ + (:H, :S), + Tuple{<:AbstractArray{<:AbstractFloat}, <:AbstractArray{<:AbstractFloat}}, +} +const HQ = NamedTuple{ + (:H, :Q), + Tuple{<:AbstractArray{<:AbstractFloat}, <:AbstractArray{<:AbstractFloat, 2}}, +} is_increasing(v) = last(v) > first(v) diff --git a/Wflow/src/routing/reservoir.jl b/Wflow/src/routing/reservoir.jl index 642d1c94d..6e4a005a4 100644 --- a/Wflow/src/routing/reservoir.jl +++ b/Wflow/src/routing/reservoir.jl @@ -1,38 +1,61 @@ "Struct for storing reservoir model parameters" -@with_kw struct ReservoirParameters +@with_kw struct ReservoirParameters{ + T <: AbstractArray{<:AbstractFloat}, + I <: AbstractArray{Int}, +} # type of reservoir storage curve, 1: S = AH, 2: S = f(H) from reservoir data and # interpolation - storfunc::Vector{Int} + storfunc::I # type of reservoir rating curve, 1: Q = f(H) from reservoir data and interpolation, 2: # General Q = b(H - H₀)ᵉ, 3: Case of Puls Approach Q = b(H - H₀)², 4: Simple reservoir - outflowfunc::Vector{Int} + outflowfunc::I # reservoir area [m²] - area::Vector{Float64} + area::T # index of lower reservoir (linked reservoirs) [-] - lower_reservoir_ind::Vector{Int} = fill(0, length(area)) + lower_reservoir_ind::I = fill(0, length(area)) # reservoir maximum storage for rating curve types 1 and 4 [m³] - maxstorage::Vector{Float64} = fill(MISSING_VALUE, length(area)) + maxstorage::T = fill(MISSING_VALUE, length(area)) # water level threshold H₀ [m] below that level outflow is zero - threshold::Vector{Float64} = fill(MISSING_VALUE, length(area)) + threshold::T = fill(MISSING_VALUE, length(area)) # rating curve coefficient [m3/2 s-1] (if e=3/2) - b::Vector{Float64} = fill(MISSING_VALUE, length(area)) + b::T = fill(MISSING_VALUE, length(area)) # rating curve exponent [-] - e::Vector{Float64} = fill(MISSING_VALUE, length(area)) + e::T = fill(MISSING_VALUE, length(area)) # data for storage curve sh::Vector{Union{SH, Missing}} = Vector{Union{SH, Missing}}(missing, length(area)) # data for rating curve hq::Vector{Union{HQ, Missing}} = Vector{Union{HQ, Missing}}(missing, length(area)) # column index of rating curve data hq - col_index_hq::Vector{Int} = [1] + col_index_hq::I = [1] # maximum amount that can be released if below spillway for rating curve type 4 [m³ s⁻¹] - maxrelease::Vector{Float64} = fill(MISSING_VALUE, length(area)) + maxrelease::T = fill(MISSING_VALUE, length(area)) # minimum (environmental) flow requirement downstream of the reservoir for rating curve # type 4 [m³ s⁻¹] - demand::Vector{Float64} = fill(MISSING_VALUE, length(area)) + demand::T = fill(MISSING_VALUE, length(area)) # target minimum full fraction (of max storage) for rating curve type 4 [-] - targetminfrac::Vector{Float64} = fill(MISSING_VALUE, length(area)) + targetminfrac::T = fill(MISSING_VALUE, length(area)) # target fraction full (of max storage) for rating curve type 4 [-] - targetfullfrac::Vector{Float64} = fill(MISSING_VALUE, length(area)) + targetfullfrac::T = fill(MISSING_VALUE, length(area)) +end + +function adapt_structure(to, from::ReservoirParameters) + return ReservoirParameters( + adapt(to, from.storfunc), + adapt(to, from.outflowfunc), + adapt(to, from.area), + adapt(to, from.lower_reservoir_ind), + adapt(to, from.maxstorage), + adapt(to, from.threshold), + adapt(to, from.b), + adapt(to, from.e), + [adapt(to, sh) for sh in from.sh], # TODO: might not be compatible with GPU computations + [adapt(to, hq) for hq in from.hq], + adapt(to, from.col_index_hq), + adapt(to, from.maxrelease), + adapt(to, from.demand), + adapt(to, from.targetminfrac), + adapt(to, from.targetfullfrac), + ) end "Initialize reservoir model parameters" @@ -181,26 +204,27 @@ function ReservoirParameters(dataset::NCDataset, config::Config, network::Networ end "Struct for storing reservoir model variables" -@with_kw struct ReservoirVariables +@with_kw struct ReservoirVariables{T <: AbstractArray{<:AbstractFloat}} # waterlevel H [m] of reservoir - waterlevel::Vector{Float64} + waterlevel::T # average waterlevel H [m] of reservoir for model timestep Δt - waterlevel_av::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + waterlevel_av::T = fill(MISSING_VALUE, length(waterlevel)) # reservoir storage [m³] - storage::Vector{Float64} + storage::T # average reservoir storage [m³] for model timestep Δt - storage_av::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + storage_av::T = fill(MISSING_VALUE, length(waterlevel)) # outflow from reservoir [m³ s⁻¹] - outflow::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + outflow::T = fill(MISSING_VALUE, length(waterlevel)) # average outflow from reservoir [m³ s⁻¹] for model timestep Δt - outflow_av::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + outflow_av::T = fill(MISSING_VALUE, length(waterlevel)) # average actual evaporation for reservoir area [mm Δt⁻¹] - actevap::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + actevap::T = fill(MISSING_VALUE, length(waterlevel)) # fraction full (of max storage) for rating curve type 4 [-] - percfull::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + percfull::T = fill(MISSING_VALUE, length(waterlevel)) # minimum (environmental) flow released from reservoir for rating curve type 4 [m³ s⁻¹] - demandrelease::Vector{Float64} = fill(MISSING_VALUE, length(waterlevel)) + demandrelease::T = fill(MISSING_VALUE, length(waterlevel)) end +@adapt_structure ReservoirVariables "Initialize reservoir model variables" function ReservoirVariables(parameters::ReservoirParameters, waterlevel::Vector{Float64}) @@ -213,11 +237,12 @@ function ReservoirVariables(parameters::ReservoirParameters, waterlevel::Vector{ end "Struct for storing reservoir model boundary conditions" -@with_kw struct ReservoirBC - inflow::Vector{Float64} # inflow into reservoir [m³ s⁻¹] for model timestep Δt - precipitation::Vector{Float64} # average precipitation for reservoir area [mm Δt⁻¹] - evaporation::Vector{Float64} # average potential evaporation for reservoir area [mm Δt⁻¹] +@with_kw struct ReservoirBC{T <: AbstractArray{<:AbstractFloat}} + inflow::T # inflow into reservoir [m³ s⁻¹] for model timestep Δt + precipitation::T # average precipitation for reservoir area [mm Δt⁻¹] + evaporation::T # average potential evaporation for reservoir area [mm Δt⁻¹] end +@adapt_structure ReservoirBC "Initialize reservoir model boundary conditions" function ReservoirBC(n::Int) @@ -235,6 +260,7 @@ end parameters::ReservoirParameters variables::ReservoirVariables end +@adapt_structure Reservoir "Initialize reservoir model `SimpleReservoir`" function Reservoir(dataset::NCDataset, config::Config, network::NetworkReservoir) diff --git a/Wflow/src/routing/surface_kinwave.jl b/Wflow/src/routing/surface_kinwave.jl index 387578d29..a39f17171 100644 --- a/Wflow/src/routing/surface_kinwave.jl +++ b/Wflow/src/routing/surface_kinwave.jl @@ -105,15 +105,17 @@ function RiverFlowParameters(dataset::NCDataset, config::Config, domain::DomainR end "Struct for storing river flow model boundary conditions" -@with_kw struct RiverFlowBC{R} - inwater::Vector{Float64} # Lateral inflow [m³ s⁻¹] - inflow::Vector{Float64} # External inflow (abstraction/supply/demand) [m³ s⁻¹] - actual_external_abstraction_av::Vector{Float64} # Actual abstraction from external negative inflow [m³ s⁻¹] - inflow_reservoir::Vector{Float64} # inflow reservoir from land part [m³ s⁻¹] - abstraction::Vector{Float64} # Abstraction (computed as part of water demand and allocation) [m³ s⁻¹] +@with_kw struct RiverFlowBC{T <: AbstractArray{<:AbstractFloat}, R} + inwater::T # Lateral inflow [m³ s⁻¹] + inflow::T # External inflow (abstraction/supply/demand) [m³ s⁻¹] + actual_external_abstraction_av::T # Actual abstraction from external negative inflow [m³ s⁻¹] + inflow_reservoir::T # inflow reservoir from land part [m³ s⁻¹] + abstraction::T # Abstraction (computed as part of water demand and allocation) [m³ s⁻¹] reservoir::R # Reservoir model struct of arrays end +@adapt_structure RiverFlowBC + "Initialize river flow model boundary conditions" function RiverFlowBC(n::Int, reservoir::Union{Reservoir, Nothing}) bc = RiverFlowBC(; diff --git a/Wflow/src/routing/surface_local_inertial.jl b/Wflow/src/routing/surface_local_inertial.jl index 4df7279f8..6789f8381 100644 --- a/Wflow/src/routing/surface_local_inertial.jl +++ b/Wflow/src/routing/surface_local_inertial.jl @@ -1,21 +1,26 @@ "Struct for storing local inertial river flow model parameters" -@with_kw struct LocalInertialRiverFlowParameters - n::Int # number of cells [-] - ne::Int # number of edges [-] - active_n::Vector{Int} # active nodes [-] - active_e::Vector{Int} # active edges [-] - g::Float64 # acceleration due to gravity [m s⁻²] - froude_limit::Bool # if true a check is performed if froude number > 1.0 (algorithm is modified) [-] - h_thresh::Float64 # depth threshold for calculating flow [m] - zb::Vector{Float64} # river bed elevation [m] - zb_max::Vector{Float64} # maximum channel bed elevation [m] - bankfull_storage::Vector{Float64} # bankfull storage [m³] - bankfull_depth::Vector{Float64} # bankfull depth [m] - mannings_n_sq::Vector{Float64} # Manning's roughness squared at edge [(s m-1/3)2] - mannings_n::Vector{Float64} # Manning's roughness [s m-1/3] at node - flow_length_at_edge::Vector{Float64} # flow (river) length at edge [m] - flow_width_at_edge::Vector{Float64} # flow (river) width at edge [m] +@with_kw struct LocalInertialRiverFlowParameters{ + T <: AbstractArray{<:AbstractFloat}, + I <: AbstractArray{Int}, + S <: AbstractFloat, +} + n::Int # number of cells [-] + ne::Int # number of edges [-] + active_n::I # active nodes [-] + active_e::I # active edges [-] + g::S # acceleration due to gravity [m s⁻²] + froude_limit::Bool # if true a check is performed if froude number > 1.0 (algorithm is modified) [-] + h_thresh::S # depth threshold for calculating flow [m] + zb::T # river bed elevation [m] + zb_max::T # maximum channel bed elevation [m] + bankfull_storage::T # bankfull storage [m³] + bankfull_depth::T # bankfull depth [m] + mannings_n_sq::T # Manning's roughness squared at edge [(s m-1/3)2] + mannings_n::T # Manning's roughness [s m-1/3] at node + flow_length_at_edge::T # flow (river) length at edge [m] + flow_width_at_edge::T # flow (river) width at edge [m] end +@adapt_structure LocalInertialRiverFlowParameters "Initialize local inertial river flow model parameters" function LocalInertialRiverFlowParameters( @@ -101,23 +106,24 @@ function LocalInertialRiverFlowParameters( end "Struct for storing local inertial river flow model variables" -@with_kw struct LocalInertialRiverFlowVariables - q::Vector{Float64} # river discharge at edge (subgrid channel) [m³ s⁻¹] - q0::Vector{Float64} # river discharge at edge (subgrid channel) at previous time step [m³ s⁻¹] - q_av::Vector{Float64} # average river channel (+ floodplain) discharge at edge [m³ s⁻¹] (model timestep Δt) - q_channel_av::Vector{Float64} # average river channel discharge at edge [m³ s⁻¹] (for model timestep Δt) - h::Vector{Float64} # water depth [m] - zs_max::Vector{Float64} # maximum water elevation at edge [m] - zs_src::Vector{Float64} # water elevation of source node of edge [m] - zs_dst::Vector{Float64} # water elevation of downstream node of edge [m] - hf::Vector{Float64} # water depth at edge [m] - h_av::Vector{Float64} # average water depth for model timestep Δt [m] - a::Vector{Float64} # flow area at edge [m²] - r::Vector{Float64} # wetted perimeter at edge [m] - storage::Vector{Float64} # river storage [m³] - storage_av::Vector{Float64} # average river storage for model timestep Δt [m³] - error::Vector{Float64} # error storage [m³] +@with_kw struct LocalInertialRiverFlowVariables{T <: AbstractArray{<:AbstractFloat}} + q::T # river discharge at edge (subgrid channel) [m³ s⁻¹] + q0::T # river discharge at edge (subgrid channel) at previous time step [m³ s⁻¹] + q_av::T # average river channel (+ floodplain) discharge at edge [m³ s⁻¹] (model timestep Δt) + q_channel_av::T # average river channel discharge at edge [m³ s⁻¹] (for model timestep Δt) + h::T # water depth [m] + zs_max::T # maximum water elevation at edge [m] + zs_src::T # water elevation of source node of edge [m] + zs_dst::T # water elevation of downstream node of edge [m] + hf::T # water depth at edge [m] + h_av::T # average water depth for model timestep Δt [m] + a::T # flow area at edge [m²] + r::T # wetted perimeter at edge [m] + storage::T # river storage [m³] + storage_av::T # average river storage for model timestep Δt [m³] + error::T # error storage [m³] end +@adapt_structure LocalInertialRiverFlowVariables "Initialize shallow water river flow model variables" function LocalInertialRiverFlowVariables( @@ -168,6 +174,7 @@ end floodplain::F # Floodplain (1D) schematization allocation::A # Water allocation end +@adapt_structure LocalInertialRiverFlow "Initialize shallow water river flow model `LocalIntertialRiverFlow`" function LocalInertialRiverFlow( @@ -1028,13 +1035,17 @@ Floodplain `storage` is a function of `depth` (flood depth intervals). Based on cumulative floodplain `storage` a floodplain profile as a function of `flood_depth` is derived with floodplain area `a` (cumulative) and wetted perimeter radius `p` (cumulative). """ -@with_kw struct FloodPlainProfile{N} - depth::Vector{Float64} # Flood depth [m] - storage::Array{Float64, 2} # Flood storage (cumulative) [m³] - width::Array{Float64, 2} # Flood width [m] - a::Array{Float64, 2} # Flow area (cumulative) [m²] - p::Array{Float64, 2} # Wetted perimeter (cumulative) [m] +@with_kw struct FloodPlainProfile{ + T <: AbstractArray{<:AbstractFloat}, + D <: AbstractArray{<:AbstractFloat, 2}, +} + depth::T # Flood depth [m] + storage::D # Flood storage (cumulative) [m³] + width::D # Flood width [m] + a::D # Flow area (cumulative) [m²] + p::D # Wetted perimeter (cumulative) [m] end +@adapt_structure FloodPlainProfile "Initialize floodplain profile `FloodPlainProfile`" function FloodPlainProfile( @@ -1122,17 +1133,18 @@ function FloodPlainProfile( p = hcat(p, p[:, index_pit]) # initialize floodplain profile parameters - profile = FloodPlainProfile{n_depths}(; storage, width, depth = flood_depths, a, p) + profile = FloodPlainProfile(; storage, width, depth = flood_depths, a, p) return profile end "Struct to store floodplain flow model parameters" -@with_kw struct FloodPlainParameters{P} - profile::P # floodplain profile - mannings_n::Vector{Float64} # manning's roughness [s m-1/3] - mannings_n_sq::Vector{Float64} # manning's roughness squared at edge [(s m-1/3)2] - zb_max::Vector{Float64} # maximum bankfull elevation at edge [m] +@with_kw struct FloodPlainParameters{T <: AbstractArray{<:AbstractFloat}, P} + profile::P # floodplain profile + mannings_n::T # manning's roughness [s m-1/3] + mannings_n_sq::T # manning's roughness squared at edge [(s m-1/3)2] + zb_max::T # maximum bankfull elevation at edge [m] end +@adapt_structure FloodPlainParameters "Initialize floodplain flow model parameters" function FloodPlainParameters( @@ -1170,20 +1182,24 @@ function FloodPlainParameters( end "Struct to store floodplain flow model variables" -@with_kw struct FloodPlainVariables - storage::Vector{Float64} # storage [m³] - storage_av::Vector{Float64} # average storage for model timestep Δt [m³] - h::Vector{Float64} # water depth [m] - h_av::Vector{Float64} # average water depth [m] for model timestep Δt - error::Vector{Float64} # error storage [m³] - a::Vector{Float64} # flow area at egde [m²] - r::Vector{Float64} # hydraulic radius at edge [m] - hf::Vector{Float64} # water depth at edge [m] - q0::Vector{Float64} # discharge at edge at previous time step - q::Vector{Float64} # discharge at edge [m³ s⁻¹] - q_av::Vector{Float64} # average river discharge at edge [m³ s⁻¹] for model timestep Δt - hf_index::Vector{Int} # edge index with `hf` [-] above depth threshold +@with_kw struct FloodPlainVariables{ + T <: AbstractArray{<:AbstractFloat}, + I <: AbstractArray{Int}, +} + storage::T # storage [m³] + storage_av::T # average storage for model timestep Δt [m³] + h::T # water depth [m] + h_av::T # average water depth [m] for model timestep Δt + error::T # error storage [m³] + a::T # flow area at egde [m²] + r::T # hydraulic radius at edge [m] + hf::T # water depth at edge [m] + q0::T # discharge at edge at previous time step + q::T # discharge at edge [m³ s⁻¹] + q_av::T # average river discharge at edge [m³ s⁻¹] for model timestep Δt + hf_index::I # edge index with `hf` [-] above depth threshold end +@adapt_structure FloodPlainVariables "Initialize floodplain flow model variables" function FloodPlainVariables(n::Int, n_edges::Int, index_pit::Vector{Int}) @@ -1209,6 +1225,7 @@ end parameters::FloodPlainParameters{P} variables::FloodPlainVariables end +@adapt_structure FloodPlain "Determine the initial floodplain storage" function initialize_storage!(river, domain::Domain, nriv::Int) diff --git a/Wflow/src/routing/timestepping.jl b/Wflow/src/routing/timestepping.jl index 3fa7c039c..c1d7511de 100644 --- a/Wflow/src/routing/timestepping.jl +++ b/Wflow/src/routing/timestepping.jl @@ -1,11 +1,12 @@ "Timestepping for solving kinematic wave and local inertial river and overland flow routing." -@with_kw struct TimeStepping - stable_timesteps::Vector{Float64} = Float64[] - dt_fixed::Float64 = 0.0 +@with_kw struct TimeStepping{T <: AbstractArray{<:AbstractFloat}, S <: AbstractFloat} + stable_timesteps::T = Float64[] + dt_fixed::S = 0.0 adaptive::Bool = true - cfl::Float64 = 0.70 + cfl::S = 0.70 end +@adapt_structure TimeStepping "Check timestep size" function check_timestepsize(timestepsize, currenttime, endtime) diff --git a/Wflow/test/reservoir.jl b/Wflow/test/reservoir.jl index 01ce57557..dac97ad21 100644 --- a/Wflow/test/reservoir.jl +++ b/Wflow/test/reservoir.jl @@ -159,7 +159,7 @@ end Wflow.read_hq_csv(joinpath(datadir, "input", "reservoir_hq_2.csv")), ]) res_params = Wflow.ReservoirParameters(; - area = [200_000_000], + area = [2.0e8], storfunc = [2], outflowfunc = [1], sh, @@ -167,7 +167,7 @@ end col_index_hq = [15], ) @reset res_params.maxstorage[1] = Wflow.maximum_storage(res_params, 1) - res_vars = Wflow.ReservoirVariables(; waterlevel = [397.75], storage = [410_760_000]) + res_vars = Wflow.ReservoirVariables(; waterlevel = [397.75], storage = [410_760_000.0]) res = Wflow.Reservoir(; boundary_conditions = res_bc, parameters = res_params, From 388079417df973aa4e75f463a44e20f8b8106a5b Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Thu, 10 Jul 2025 11:53:04 +0200 Subject: [PATCH 3/4] Add KernelAbstractions to dependencies --- Wflow/Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Wflow/Project.toml b/Wflow/Project.toml index 5ff9d1181..8c70ff615 100644 --- a/Wflow/Project.toml +++ b/Wflow/Project.toml @@ -13,6 +13,7 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" Glob = "c27321d9-0574-5035-807b-f59d2c89b15c" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" +KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36" NCDatasets = "85f8d34a-cbdd-5861-8df4-14fed0d494ab" Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a" @@ -35,6 +36,7 @@ DelimitedFiles = "1" Downloads = "1" Glob = "1.3" Graphs = "1.4" +KernelAbstractions = "0.9.36" LoggingExtras = "0.4.6,0.5,1" NCDatasets = "0.13.2, 0.14" Parameters = "0.12" From 02c748139e8c5287ebf04709d5a76f66e5329d02 Mon Sep 17 00:00:00 2001 From: Bart Schilperoort Date: Thu, 10 Jul 2025 11:53:20 +0200 Subject: [PATCH 4/4] Add Defaults object to store fp precision, backend --- Wflow/src/Wflow.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Wflow/src/Wflow.jl b/Wflow/src/Wflow.jl index f495f415c..e084b1001 100644 --- a/Wflow/src/Wflow.jl +++ b/Wflow/src/Wflow.jl @@ -1,6 +1,7 @@ module Wflow import BasicModelInterface as BMI +import KernelAbstractions as KA using Accessors: @optic, @reset, PropertyLens import Adapt: adapt, @adapt_structure, adapt_structure @@ -60,6 +61,14 @@ const VERSION = VersionNumber(TOML.parsefile(joinpath(@__DIR__, "..", "Project.toml"))["version"]) const ROUTING_OPTIONS = (("kinematic-wave", "local-inertial")) +mutable struct Defaults + FloatType::DataType + Backend::KA.Backend +end + +Defaults(; FloatType=Float64, Backend=KA.CPU()) = Defaults(FloatType, Backend) +const defaults = Defaults() + mutable struct Clock{T} time::T iteration::Int