Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manually test Wflow.jl model #14

Merged
merged 2 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions RemoteBMI.jl/example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
data
sbm_config.toml
110 changes: 107 additions & 3 deletions RemoteBMI.jl/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ Interact with it using the Python client.
```python
from remotebmi.client.client import RemoteBmiClient
from remotebmi.reserve import reserve_values
import os

client = RemoteBmiClient('http://localhost:50555')
# TODO use placeholder for path
# client.initialize('<absolute path>/heat.toml')
client.initialize('/home/stefanv/git/eWaterCycle/remotebmi/python/heat.toml')
client.initialize(os.getcwd() + '/heat.toml')
client.get_component_name()
'The 2D Heat Equation'
client.update()
Expand All @@ -50,3 +49,108 @@ r = client.get_value('plate_surface__temperature', dest)
r
client.finalize()
```

# Run Wflow.jl

```shell
julia --project=.
]
add Wflow
# Install RemoteBMI
dev ..
<backspace>

# Download a parameter set
# From https://deltares.github.io/Wflow.jl/stable/user_guide/sample_data/#wflow_sbm_data
# with *nc moved to data/input
toml_url = "https://raw.githubusercontent.com/Deltares/Wflow.jl/master/test/sbm_config.toml"
staticmaps = "https://github.com/visr/wflow-artifacts/releases/download/v0.2.9/staticmaps-moselle.nc"
forcing = "https://github.com/visr/wflow-artifacts/releases/download/v0.2.6/forcing-moselle.nc"
instates = "https://github.com/visr/wflow-artifacts/releases/download/v0.2.6/instates-moselle.nc"
# create a "data" directory in the current directory
datadir = joinpath(@__DIR__, "data")
mkpath(datadir)
inputDir = joinpath(datadir, "input")
mkpath(inputDir)
toml_path = joinpath(@__DIR__, "sbm_config.toml")
# download resources to current and data dirs
download(staticmaps, joinpath(inputDir, "staticmaps-moselle.nc"))
download(forcing, joinpath(datadir, "forcing-moselle.nc"))
download(instates, joinpath(inputDir, "instates-moselle.nc"))
download(toml_url, toml_path)

# Run server
using Wflow
import RemoteBMI
port = parse(Int, get(ENV, "BMI_PORT", "50051"))
RemoteBMI.run(Wflow.Model, "0.0.0.0", port)
```

Interact with it using the Python client.

```python
from remotebmi.client.client import RemoteBmiClient
from remotebmi.reserve import reserve_values, reserve_grid_nodes, reserve_grid_edge_nodes, reserve_grid_nodes_per_face, reserve_grid_face_
import numpy as np
import os

client = RemoteBmiClient('http://localhost:50051')
# Change to location of sbm_config.toml
os.chdir('../RemoteBMI.jl/example')
%time client.initialize(os.getcwd() + '/sbm_config.toml')
CPU times: user 3.08 ms, sys: 8 μs, total: 3.09 ms
Wall time: 18.7 s
%time client.update()
CPU times: user 1.45 ms, sys: 78 μs, total: 1.53 ms
Wall time: 7.78 s
%time client.update()
CPU times: user 596 μs, sys: 980 μs, total: 1.58 ms
Wall time: 227 ms
client.get_component_name()
'sbm'
client.get_current_time()
172800.0
client.get_time_units()
's'
client.get_output_var_names()
['vertical.nlayers',
'vertical.n_unsatlayers',
...
'lateral.river.q',
...
'lateral.river.reservoir.evaporation',
'lateral.river.reservoir.actevap']
client.get_var_location('lateral.river.q')
'node'
client.get_var_type('lateral.river.q')
numpy.float64
client.get_var_grid('lateral.river.q')
3
client.get_grid_type(3)
'unstructured'
client.get_grid_rank(3)
2
client.get_grid_size(3)
5809
client.get_grid_shape(3, np.empty(2))
# Method does not exist, which is ok for this grid type
x = client.get_grid_x(3, reserve_grid_nodes(client, 3))
len(x)
5809
y = client.get_grid_y(3, reserve_grid_nodes(client, 3))
len(y)
5809
value = client.get_value('lateral.river.q', reserve_values(client, 'lateral.river.q'))
len(value)
5809
client.get_grid_node_count(3)
5809
client.get_grid_edge_count(3)
5808
client.get_grid_face_count(3)
# Method does not exist, which is ok for this var location
edge_nodes = client.get_grid_edge_nodes(3, reserve_grid_edge_nodes(client, 3))
len(edge_nodes)
11616
client.finalize()
```
6 changes: 3 additions & 3 deletions RemoteBMI.jl/src/RemoteBMI.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,17 @@ function reserve_grid_coords(m, grid::Int64, dim_index::Int8)::Vector{Float64}
end

function get_grid_x(req::HTTP.Request, grid::Int64;)::Vector{Float64}
x = reserve_grid_coords(m, grid, 1)
x = reserve_grid_coords(m, grid, Int8(1))
return BMI.get_grid_x(m, grid, x)
end

function get_grid_y(req::HTTP.Request, grid::Int64;)::Vector{Float64}
y = reserve_grid_coords(m, grid, 2)
y = reserve_grid_coords(m, grid, Int8(2))
return BMI.get_grid_y(m, grid, y)
end

function get_grid_z(req::HTTP.Request, grid::Int64;)::Vector{Float64}
z = reserve_grid_coords(m, grid, 3)
z = reserve_grid_coords(m, grid, Int8(3))
return BMI.get_grid_z(m, grid, z)
end

Expand Down
12 changes: 10 additions & 2 deletions python/remotebmi/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@


class RemoteBmiClient(Bmi):
def __init__(self, base_url, max_keepalive_connections=0):
def __init__(self, base_url, timeout=60 * 60 * 24, max_keepalive_connections=0):
"""RemoteBmiClient constructor

Args:
base_url: Where the remote BMI server is running.
timeout: How long a response can take.
Defaults to 1 day. Set to None to disable timeout.
max_keepalive_connections: How many connections to keep alive.
"""
# In some Python environments the reusing connection causes `illegal status line: bytesarray(b'14')` error
# So we need to disable keepalive connections to be more reliable, but less efficient
limits = Limits(max_keepalive_connections=max_keepalive_connections)
self.client = Client(base_url=base_url, limits=limits)
self.client = Client(base_url=base_url, timeout=timeout, limits=limits)

def __del__(self):
self.client.close()
Expand Down
2 changes: 1 addition & 1 deletion python/remotebmi/reserve.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def reserve_grid_padding(model: Bmi, grid_id: int) -> np.ndarray:
return np.empty(model.get_grid_rank(grid_id), dtype=np.float64)


def reserve_grid_nodes(model: Bmi, grid_id: int, dim_index: int) -> np.ndarray:
def reserve_grid_nodes(model: Bmi, grid_id: int, dim_index: int = 0) -> np.ndarray:
"""Reserve dest for :func:`bmipy.Bmi.get_grid_x`, :func:`bmipy.Bmi.get_grid_y` and :func:`bmipy.Bmi.get_grid_z`

The dim_index goes x,y,z and model.get_grid_shape goes z,y,x or y,x so index is inverted
Expand Down
Loading