Skip to content

Commit

Permalink
Add more julia docstrings and convenience functions (#607)
Browse files Browse the repository at this point in the history
I started this off simply wanting to switch to Documenter.jl version 1.0
that recently got released. But what wasn't clear from #470 is that the
[DocumenterMarkdown](https://github.com/JuliaDocs/DocumenterMarkdown.jl)
backend we use is not actively maintained, meaning we are stuck for now
on the old Documenter 0.27.

In any case this addresses a few Documenter 0.27 warnings about missing
docstrings. And when I started adding docstrings I figured the key
functions really need some docstrings. I also added some more convenient
methods, e.g. extending `solve!` from SciML on our Model, and adding
`model = Ribasim.Model(config)` instead of only the more verbose BMI
interface method `model = BMI.initialize(Ribasim.Model, config)`.
  • Loading branch information
visr authored Sep 25, 2023
1 parent 104eea0 commit 0b83781
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 18 deletions.
14 changes: 14 additions & 0 deletions core/src/Ribasim.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
"""
module Ribasim
Ribasim is a water resources model.
The computational core is implemented in Julia in the Ribasim package.
It is currently mainly designed to be used as an application.
To run a simulation from Julia, use [`Ribasim.run`](@ref).
For more granular access, see:
- [`Config`](@ref)
- [`Model`](@ref)
- [`solve!`](@ref)
- [`BMI.finalize`](@ref)
"""
module Ribasim

import IterTools
Expand Down
26 changes: 24 additions & 2 deletions core/src/bmi.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
"""
BMI.initialize(T::Type{Model}, config_path::AbstractString)::Model
Initialize a [`Model`](@ref) from the path to the TOML configuration file.
"""
function BMI.initialize(T::Type{Model}, config_path::AbstractString)::Model
config = Config(config_path)
BMI.initialize(T, config)
end

"""
BMI.initialize(T::Type{Model}, config::Config)::Model
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)
Expand Down Expand Up @@ -134,6 +144,11 @@ function BMI.initialize(T::Type{Model}, config::Config)::Model
return Model(integrator, config, saved_flow)
end

"""
BMI.finalize(model::Model)::Model
Write all output to the configured output files.
"""
function BMI.finalize(model::Model)::Model
compress = get_compressor(model.config.output)
write_basin_output(model, compress)
Expand Down Expand Up @@ -528,6 +543,13 @@ BMI.get_end_time(model::Model) = seconds_since(model.config.endtime, model.confi
BMI.get_time_units(model::Model) = "s"
BMI.get_time_step(model::Model) = get_proposed_dt(model.integrator)

"""
run(config_file::AbstractString)::Model
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).
"""
run(config_file::AbstractString)::Model = run(Config(config_file))

function is_current_module(log)
Expand All @@ -549,8 +571,8 @@ function run(config::Config)::Model
end

with_logger(logger) do
model = BMI.initialize(Model, config)
solve!(model.integrator)
model = Model(config)
solve!(model)
BMI.finalize(model)
return model
end
Expand Down
27 changes: 25 additions & 2 deletions core/src/config.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
"""
module config
Ribasim.config is a submodule of [`Ribasim`](@ref) to handle the configuration of a Ribasim model.
It is implemented using the [Configurations](https://configurations.rogerluo.dev/stable/) package.
A full configuration is represented by [`Config`](@ref), which is the main API.
Ribasim.config is a submodule mainly to avoid name clashes between the configuration sections and the rest of Ribasim.
"""
module config

using Configurations: Configurations, Maybe, @option, from_toml, @type_alias
using DataStructures: DefaultDict
using Dates
using Legolas: Legolas, record_type
using Logging: LogLevel, Debug, Info, Warn, Error
using ..Ribasim: Ribasim, isnode, nodetype
using OrdinaryDiffEq
Expand Down Expand Up @@ -169,7 +176,23 @@ function Base.show(io::IO, c::TableOption)
end
end

"Map from config string to supported algorithm type"
"""
const algorithms::Dict{String, Type}
Map from config string to a supported algorithm type from [OrdinaryDiffEq](https://docs.sciml.ai/DiffEqDocs/stable/solvers/ode_solve/).
Supported algorithms:
- `QNDF`
- `Rosenbrock23`
- `TRBDF2`
- `Rodas5`
- `KenCarp4`
- `Tsit5`
- `RK4`
- `ImplicitEuler`
- `Euler`
"""
const algorithms = Dict{String, Type}(
"QNDF" => QNDF,
"Rosenbrock23" => Rosenbrock23,
Expand Down
34 changes: 25 additions & 9 deletions core/src/lib.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"""
Model(
sys::MTK.AbstractODESystem,
config::Config,
saved_flow::SavedValues(Float64, Vector{Float64}),
integrator::SciMLBase.AbstractODEIntegrator
)
Struct that combines data from the System and Integrator that we will need during and after
model construction.
Model(config_path::AbstractString)
Model(config::Config)
Initialize a Model.
The Model struct is an initialized model, combined with the [`Config`](@ref) used to create it and saved outputs.
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.
"""
struct Model{T}
integrator::T
Expand All @@ -22,6 +21,14 @@ struct Model{T}
end
end

function Model(config_path::AbstractString)::Model
return BMI.initialize(Model, config_path::AbstractString)
end

function Model(config::Config)::Model
return BMI.initialize(Model, config::Config)
end

timesteps(model::Model) = model.integrator.sol.t

function Base.show(io::IO, model::Model)
Expand All @@ -34,3 +41,12 @@ end
function SciMLBase.successful_retcode(model::Model)::Bool
return SciMLBase.successful_retcode(model.integrator.sol)
end

"""
solve!(model::Model)::ODESolution
Solve a Model until the configured `endtime`.
"""
function SciMLBase.solve!(model::Model)::ODESolution
return solve!(model.integrator)
end
3 changes: 1 addition & 2 deletions core/test/bmi.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Test
using Configurations: from_toml
using Ribasim
import BasicModelInterface as BMI

Expand Down Expand Up @@ -31,7 +30,7 @@ end
)
@test config.solver.algorithm == "ImplicitEuler"
@test !config.solver.adaptive
model = BMI.initialize(Ribasim.Model, config)
model = Ribasim.Model(config)

@test BMI.get_time_step(model) == dt
BMI.update(model)
Expand Down
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using DocumenterMarkdown
DocMeta.setdocmeta!(Ribasim, :DocTestSetup, :(using Ribasim); recursive = true)

makedocs(;
modules = [Ribasim],
modules = [Ribasim, Ribasim.config],
format = Markdown(),
repo = "https://github.com/Deltares/Ribasim.jl/blob/{commit}{path}#L{line}",
sitename = "Ribasim.jl",
Expand Down
25 changes: 23 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
```@contents
```

## Functions
## Modules

```@autodocs
Modules = [Ribasim, Ribasim.config]
Order = [:function]
Order = [:module]
```

## Types
Expand All @@ -18,6 +18,27 @@ Modules = [Ribasim, Ribasim.config]
Order = [:type]
```

## Functions

```@autodocs
Modules = [Ribasim, Ribasim.config]
Order = [:function]
```

## Constants

```@autodocs
Modules = [Ribasim, Ribasim.config]
Order = [:constant]
```

## Macros

```@autodocs
Modules = [Ribasim, Ribasim.config]
Order = [:macro]
```

## Index

```@index
Expand Down

0 comments on commit 0b83781

Please sign in to comment.