Repository: Deltares/Wflow.jl (language: python)

Issue:
`BMI.update_until` can throw an `InexactError`
### Wflow version checks

- [X] I have checked that this issue has not already been reported.

- [X] I have checked that this bug exists on the latest version of Wflow.


### Reproducible Example

While running `BMI.update_until` the following error can occur: `InexactError: Int64`

### Current behaviour

 `InexactError`.

### Desired behaviour

No `InexactError`.

### Additional Context

_No response_


Discussion / hints:

Fix patch:
diff --git a/docs/src/changelog.md b/docs/src/changelog.md
index ec2e38872..3b96a025e 100644
--- a/docs/src/changelog.md
+++ b/docs/src/changelog.md
@@ -25,8 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - For the computation of Gash interception model parameter `e_r` multiply the precipitation
   input with the canopy fraction (this was only done for the potential evapotranspiration
   input).
-
-
+ - Function `BMI.update_until` could throw an `InexactError: Int64` caused by a not whole
+  number, representing how many times (`steps`) an update of a wflow model is required. This
+  is fixed by using `divrem` for the computation of the number of `steps` in this function.
+  An error is thrown when the absolute remainder of `divrem` is larger than `eps()`, or when
+  the number of `steps` is negative.
+  
 ### Changed
 - Stop exposing scalar variables through BMI. The `BMI.get_value_ptr` function was not
   working correctly for scalar model variables (a `view` was applied). Only a few scalar
diff --git a/src/bmi.jl b/src/bmi.jl
index 9aeab436e..def51be69 100644
--- a/src/bmi.jl
+++ b/src/bmi.jl
@@ -65,9 +65,19 @@ end
 
 function BMI.update_until(model::Model, time::Float64)
     @unpack clock, network, config = model
-    curtime = BMI.get_current_time(model)
-    n = Int(max(0, (time - curtime) / model.clock.Δt.value))
-    for _ = 1:n
+    t = BMI.get_current_time(model)
+    _div, _rem = divrem(time - t, model.clock.Δt.value)
+    steps = Int(_div)
+    if steps < 0
+        error("The current model timestamp $t is larger than provided `time` $time")
+    elseif abs(_rem) > eps()
+        error_message = string(
+            "Provided `time` $time minus the current model timestamp $t",
+            " is not an integer multiple of model time step $(model.clock.Δt.value)",
+        )
+        error(error_message)
+    end
+    for _ = 1:steps
         model = run_timestep(model)
     end
     return model


Test patch:
diff --git a/test/bmi.jl b/test/bmi.jl
index 75470c4d5..dfd1a5577 100644
--- a/test/bmi.jl
+++ b/test/bmi.jl
@@ -117,8 +117,12 @@ tomlpath = joinpath(@__DIR__, "sbm_config.toml")
 
         @testset "update until and finalize" begin
             time = BMI.get_current_time(model) + 2 * BMI.get_time_step(model)
-            @test_logs (:info, "update model until 9.470304e8")
             model = BMI.update_until(model, time)
+            @test model.clock.iteration == 3
+            time_off = BMI.get_current_time(model) + 1 * BMI.get_time_step(model) + 1e-06
+            @test_throws ErrorException model = BMI.update_until(model, time_off)
+            @test_throws ErrorException model =
+                BMI.update_until(model, time - BMI.get_time_step(model))
             BMI.finalize(model)
         end