Skip to content
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
243 changes: 216 additions & 27 deletions docs/src/getting_started.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,111 @@
# Usage example
# Getting Started

## Preface

ReefMod is a coral ecology model developed at the University of Queensland with more than
20 years of development history. The original ReefMod model was written in MATLAB.
ReefMod has been ported to C++ to address issues and concerns around computational
efficiency. This port is referred to as the ReefMod Engine (RME).

This package, ReefModEngine.jl, provides a Julia interface to the RME, leveraging Julia's
first-class language interoperability support.

To avoid confusion, the following naming conventions are used when referring to each.

- The original MATLAB implementation is _always_ referred to as ReefMod.
- The C++ port, ReefMod Engine (RME), is referred to either as RME or its full name.
- This package, ReefModEngine.jl, is _always_ referred to by its full name.

## Initialization

Before anything can be done, the RME library has to first be initialized.

```julia
# Initialize RME (may take a minute or two)
init_rme("path to RME directory")
# [ Info: Loaded RME 1.0.28
```

## Setting RME options

RME is able to run multiple simulations at the same time via multi-threading.
The recommended value according to the RME documentation is a number equal to or less than
the number of available CPU cores.

```julia
# Set to use two threads
set_option("thread_count", 2)
```

::: tip

Do remember, however, that each process requires memory as well, so the total number of
threads should not exceed `ceil([available memory] / [memory required per thread])`.

The required memory depends on a number of factors including the represented grid size.
As a general indication, RME's memory use is ~4-5GB for a single run with a 10x10 grid.

:::

ReefModEngine.jl provides a few convenience functions to interact with RME.
All other RME functions are available for direct use via the `@RME` macro.
Care needs to be taken to call RME functions. Specifically:

- The exact types as expected by the RME function needs to be used.
- No protection is provided if mismatched types are used (e.g., passing in a Float instead of an Integer)

A full list of ReefModEngine.jl functions is provided in [API](@ref API).

## Short list of RME interface functions

```julia
# Set RME options by its config name
# See RME documentation for list of available options
set_option("thread_count", 2)
set_option("restoration_dhw_tolerance_outplants", 3)
set_option("use_fixed_seed", 1) # turn on use of a fixed seed value
set_option("fixed_seed", 123) # set the fixed seed value

# Get list of reef ids as specified by ReefMod Engine
reef_id_list = reef_ids()

# Retrieve list of reef areas in km² (in same order as reef ids)
reef_area_km² = reef_areas()

# Retrieve list of reef areas in km² for specified reefs by their ids
first_10_reef_area_km² = reef_areas(reef_id_list[1:10])

# Find the index position of a reef by its GBRMPA ID
match_id("10-330")
# 1

# Calculate the minimum area required (in km²) to deploy a number of corals
# at a given density
area_needed(100_000, 6.8)

# Create a convenient result store to help extract data from RME
result_store = ResultStore(start_year, end_year, reps)

# Collect results for runs 1, 3 and 5 only
collect_rep_results!(result_store, start_year, end_year, [1,3,5])

# Collect and store all results, where `reps` is the total number of expected runs.
collect_all_results!(result_store, start_year, end_year, reps)

# Initialize RME runs
run_init()

# Reset RME, clearing all stored data and deployment configuration.
reset_rme()
```

If more runs are desired after running RME, it is required to first clear RME's state.

```julia
reset_rme()
```

## Example usage

```julia
using ReefModEngine
Expand All @@ -8,41 +115,48 @@ using CSV, DataFrames, MAT
init_rme("path to RME directory")
# [ Info: Loaded RME 1.0.28

# Set to use two threads
set_option("thread_count", 2)
set_option("thread_count", 2) # Set to use two threads
set_option("use_fixed_seed", 1) # Turn on use of a fixed seed value
set_option("fixed_seed", 123.0) # Set the fixed seed value

# Load target intervention locations determined somehow (e.g., by ADRIA)
# The first column is simply the row number.
# The second column is a list of target reef ids matching the format as found in
# the id list file (the file is found under `data_files/id` of the RME data set)
deploy_loc_details = CSV.read("target_locations.csv", DataFrame, header=["index_id", "reef_id"])

name = "Example"
start_year = 2022
end_year = 2099
RCP_scen = "SSP 2.45"
gcm = "CNRM_ESM2_1"
reps = 2
n_reefs = 3806

# Get list of reef ids as specified by ReefMod Engine
reef_id_list = reef_ids()
deploy_loc_details = CSV.read(
"target_locations.csv",
DataFrame,
header=["index_id", "reef_id"],
types=Dict(1=>Int64, 2=>String) # Force values to be interpreted as expected types
)

# Reef indices and IDs
target_reef_idx = deploy_loc_details.index_id
target_reef_ids = deploy_loc_details.reef_id
n_target_reefs = length(target_reef_idx)

# Get list of reef ids as specified by ReefMod Engine
reef_id_list = reef_ids()

name = "Example" # Name to associate with this set of runs
start_year = 2022
end_year = 2099
RCP_scen = "SSP 2.45" # RCP/SSP scenario to use
gcm = "CNRM_ESM2_1" # The base Global Climate Model (GCM)
reps = 2 # Number of repeats: number of random environmental sequences to run
n_reefs = length(reef_id_list)

# Get reef areas from RME
reef_areas = zeros(n_reefs)
@RME reefAreasKm2(reef_areas::Ptr{Cdouble}, n_reefs::Cint)::Cint
reef_area_km² = reef_areas()

# Get list of areas for the target reefs
target_reef_areas_km² = reef_areas[target_reef_idx]
d_density_m² = 6.8 # coral seeding density (per m²)
target_reef_areas_km² = reef_areas(target_reef_ids)

# Define coral outplanting density (per m²)
d_density_m² = 6.8

# Initialize result store
result_store = ResultStore(start_year, end_year, n_reefs, reps)
result_store = ResultStore(start_year, end_year, reps)
# Outputs:
# ReefModEngine Result Store
#
Expand All @@ -60,8 +174,7 @@ result_store = ResultStore(start_year, end_year, n_reefs, reps)
# species : (78, 3806, 6, 2)

@info "Starting runs"
@RME ivRemoveAll()::Cvoid
@RME reefSetRemoveAll()::Cint
reset_rme() # Reset RME to clear any previous runs

# Note: if the Julia runtime crashes, check that the specified data file location is correct
@RME runCreate(name::Cstring, start_year::Cint, end_year::Cint, RCP_scen::Cstring, gcm::Cstring, reps::Cint)::Cint
Expand All @@ -70,15 +183,24 @@ result_store = ResultStore(start_year, end_year, n_reefs, reps)
set_option("restoration_dhw_tolerance_outplants", 3)

# Create a reef set using the target reefs
@RME reefSetAddFromIdList("iv_moore"::Cstring, target_reef_ids::Ptr{Cstring}, length(target_reef_ids)::Cint)::Cint
@RME reefSetAddFromIdList("iv_example"::Cstring, target_reef_ids::Ptr{Cstring}, length(target_reef_ids)::Cint)::Cint

# Deployments occur between 2025 2030
# Year 1: 100,000 outplants; Year 2: 500,000; Year 3: 1,1M; Year 4: 1,1M; Year 5: 1,1M and Year 6: 1,1M.
set_outplant_deployment!("outplant_iv_2026", "iv_moore", 100_000, 2026, target_reef_areas_km², d_density_m²)
set_outplant_deployment!("outplant_iv_2027", "iv_moore", 500_000, 2027, target_reef_areas_km², d_density_m²)
set_outplant_deployment!("outplant_iv_2028_2031", "iv_moore", Int64(1.1 * 1e6), Int64(1.1 * 1e6)*3, 2028, 2031, 1, target_reef_areas_km², d_density_m²)
# set_outplant_deployment!("outplant_iv_2026", "iv_example", 100_000, 2026, target_reef_areas_km², d_density_m²)
# set_outplant_deployment!("outplant_iv_2027", "iv_example", 500_000, 2027, target_reef_areas_km², d_density_m²)

# Can also specify deployments to occur over a range of years
# set_outplant_deployment!("outplant_iv_2028_2031", "iv_example", Int64(1.1e6), Int64(1.1e6), 2028, 2031, 1, target_reef_areas_km², d_density_m²)

# If no deployment density is specified, ReefModEngine.jl will attempt to calculate the
# most appropriate density to maintain the specified grid size (defaulting to 10x10).
set_outplant_deployment!("outplant_iv_2026", "iv_example", 100_000, 2026, target_reef_areas_km²)
set_outplant_deployment!("outplant_iv_2027", "iv_example", 500_000, 2027, target_reef_areas_km²)
set_outplant_deployment!("outplant_iv_2028_2031", "iv_example", Int64(1.1e6), 2028, 2031, 1, target_reef_areas_km²)

@RME runInit()::Cint
# Initialize RME runs as defined above
run_init()

# Run all years and all reps
@time @RME runProcess()::Cint
Expand All @@ -87,6 +209,7 @@ set_outplant_deployment!("outplant_iv_2028_2031", "iv_moore", Int64(1.1 * 1e6),
collect_all_results!(result_store, start_year, end_year, reps)

# Save results to matfile with entries (matching ReefMod Engine standard names)
# Defaults to "RME_outcomes_[today's date].mat"
# coral_cover_ref
# coral_cover_iv
# dhw_ref
Expand All @@ -104,4 +227,70 @@ collect_all_results!(result_store, start_year, end_year, reps)
# species_ref
# species_iv
save_to_mat(result_store)

# A custom path can also be specified
# save_to_mat(result_store, "../output/my_results.mat")
```

The RME stores all data in memory, so for larger number of replicates it may be better
to run each replicate individually and store results as they complete.

::: warning

ReefModEngine.jl's result store is currently memory-based as well, so the only advantage
to this approach currently is avoiding storing results when they are no longer necessary.
Efforts will be made to move to a disk-backed store.

:::

Similarly, if cell-level data is desired, RME requires that the simulations be run on a
year-by-year basis, with results extracted every time step.

::: info

TODO: Example of running RME on a year-by-year basis.

:::


```julia
name = "Example" # Name to associate with this set of runs
start_year = 2022
end_year = 2099
RCP_scen = "SSP 2.45" # RCP/SSP scenario to use
gcm = "CNRM_ESM2_1" # The base Global Climate Model (GCM)
reps = 4 # Number of repeats: number of random environmental sequences to run
n_reefs = length(reef_id_list)

# Initialize result store
result_store = ResultStore(start_year, end_year, reps)

set_option("use_fixed_seed", 1) # Turn on use of a fixed seed value
set_option("fixed_seed", 123.0) # Set the fixed seed value

@info "Starting runs"
for r in 1:reps
reset_rme() # Reset RME to clear any previous runs

# Note: if the Julia runtime crashes, check that the specified data file location is correct
@RME runCreate(name::Cstring, start_year::Cint, end_year::Cint, RCP_scen::Cstring, gcm::Cstring, 1::Cint)::Cint
@RME setOption("restoration_dhw_tolerance_outplants"::Cstring, 3::Cint)::Cint

# Create a reef set using the target reefs
@RME reefSetAddFromIdList("iv_example"::Cstring, target_reef_ids::Ptr{Cstring}, length(target_reef_ids)::Cint)::Cint

# Deployments occur between 2025 2030
# Year 1: 100,000 outplants; Year 2: 500,000; Year 3: 1,1M; Year 4: 1,1M; Year 5: 1,1M and Year 6: 1,1M.
set_seeding_deployment("outplant_iv_2026", "iv_example", 100_000, 2026, 2026, 1, target_reef_areas_km², d_density_m²)
set_seeding_deployment("outplant_iv_2027", "iv_example", 500_000, 2027, 2027, 1, target_reef_areas_km², d_density_m²)
set_seeding_deployment("outplant_iv_2028_2031", "iv_example", Int64(1.1 * 1e6), 2028, 2031, 1, target_reef_areas_km², d_density_m²)

@RME runInit()::Cint

# Run all years
@time @RME runProcess()::Cint

# Collect results for this specific replicate
collect_rep_results!(result_store, start_year, end_year, [r])
end
```
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

A Julia interface to the ReefMod Engine (RME) C++ API.

Targets RME v1.0, and provides some convenience functions for outplanting interventions.
Targets RME v1.0, and provides some convenience functions to interact with the RME.
All other functions are accessible via the `@RME` macro.

The RME library, accompanying dataset, and RME documentation has to be requested from RME developers.
6 changes: 3 additions & 3 deletions src/ReefModEngine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ end

# Set up and initialization
export
init_rme, reset_rme, @RME, set_option
init_rme, reset_rme, @RME, set_option, run_init

# Convenience/utility methods
export
reef_ids, deployment_area, set_outplant_deployment!,
match_id, match_ids
match_id, match_ids, reef_areas

# IO
export
ResultStore, collect_all_results!, save_to_mat
ResultStore, collect_all_results!, collect_rep_results!, save_to_mat

end
Loading