Skip to content

Commit

Permalink
Merge pull request #29 from open-AIMS/fix-outplant-function
Browse files Browse the repository at this point in the history
Fix error when setting outplanting levels due to latest RME expecting density as vector
  • Loading branch information
ConnectedSystems authored Dec 12, 2024
2 parents 3ffddb8 + 4256add commit a6d3cfa
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 63 deletions.
6 changes: 4 additions & 2 deletions docs/src/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,9 @@ 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

# Adding dhw tolerance was removed in v1.0.31
# Add 3 DHW enhancement to outplanted corals
set_option("restoration_dhw_tolerance_outplants", 3)
# set_option("restoration_dhw_tolerance_outplants", 3)

# Create a reef set using the target reefs
@RME reefSetAddFromIdList("iv_example"::Cstring, target_reef_ids::Ptr{Cstring}, length(target_reef_ids)::Cint)::Cint
Expand Down Expand Up @@ -303,7 +304,8 @@ for r in 1:reps

# 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
# Adding dhw tolerance was removed in v1.0.31
# @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
Expand Down
160 changes: 104 additions & 56 deletions src/deployment.jl
Original file line number Diff line number Diff line change
@@ -1,41 +1,59 @@
"""
deployment_area(n_corals::Int64, max_n_corals::Int64, density::Float64, target_areas::Vector{Float64})::Tuple{Float64,Float64}
rme_version_info()::@NamedTuple{major::Int64, minor::Int64, patch::Int64}
Get RME version
"""
function rme_version_info()::@NamedTuple{major::Int64, minor::Int64, patch::Int64}
rme_ver = @RME version()::Cstring
rme_ver = parse.(Int64, split(rme_ver, '.'))
return (major=rme_ver[1], minor=rme_ver[2], patch=rme_ver[3])
end

"""
deployment_area(n_corals::Int64, max_n_corals::Int64, density::Union{Float64, Vector{Float64}}, target_areas::Vector{Float64})::Union{Tuple{Float64,Float64},Tuple{Float64,Vector{Float64}}}
Determine deployment area for the expected number of corals to be deployed.
# Arguments
- `n_corals` : Number of corals,
- `max_n_corals` : Expected maximum deployment effort (total number of corals in intervention set)
- `density` : Stocking density per m²
- `density` : Stocking density per m². In RME versions higher than v1.0.28 density needs to be a vector
with each element representing the density per functional group
- `target_areas` : Available area at target location(s)
# Returns
Tuple
- Percent area of deployment
- modified stocking density [currently no modifications are made]
"""
function deployment_area(n_corals::Int64, max_n_corals::Int64, density::Float64, target_areas::Vector{Float64})::Tuple{Float64,Float64}
function deployment_area(
n_corals::Int64,
max_n_corals::Int64,
density::Union{Float64,Vector{Float64}},
target_areas::Vector{Float64}
)::Union{Tuple{Float64,Float64},Tuple{Float64,Vector{Float64}}}
req_area = area_needed(max_n_corals, density)

# Divide by half (i.e., `* 0.5`) as RME simulates two deployments per year
mod_density = (n_corals * 0.5) / (req_area / m2_TO_km2)
deployment_area_pct = min((req_area / sum(target_areas)) * 100.0, 100.0)
mod_density = area_needed(n_corals, req_area)
summed_req_area = sum(req_area)
deployment_area_pct = min((summed_req_area / sum(target_areas)) * 100.0, 100.0)

# Adjust grid size if needed to simulate deployment area/percent
min_cells::Int64 = 3
if (RME_BASE_GRID_SIZE[] * req_area / sum(target_areas)) < min_cells
if (RME_BASE_GRID_SIZE[] * summed_req_area / sum(target_areas)) < min_cells
# Determine new grid resolution in terms of number of N by N cells
target_grid_size::Float64 = 3.0 * sum(target_areas) / req_area
target_grid_size::Float64 = 3.0 * (sum(target_areas) / summed_req_area)
cell_res::Int64 = ceil(Int64, sqrt(target_grid_size)) # new cell resolution

# RME supported cell sizes (N by N)
# Determine smallest appropriate grid size when larger grid sizes are set.
# Larger grid sizes = greater cell resolution, incurring larger runtime costs.
p::Vector{Int64} = Int64[10, 20, 25, 30, 36, 43, 55, 64, 85, 100]
n_cells::Int64 = try
first(p[p.>=cell_res])
first(p[p .>= cell_res])
catch
p[end-1]
p[end - 1]
end

RME_BASE_GRID_SIZE[] = n_cells * n_cells
Expand All @@ -49,16 +67,19 @@ function deployment_area(n_corals::Int64, max_n_corals::Int64, density::Float64,
end

"""
deployment_area(max_n_corals::Int64, target_areas::Vector{Float64})::Tuple{Float64,Float64}
deployment_area(max_n_corals::Int64, target_areas::Vector{Float64})::Union{Tuple{Float64,Float64}, Tuple{Float64,Vector{Float64}}}
Determine deployment area for given number of corals and target area, calculating the
appropriate deployment density to maintain the specified grid size.
"""
function deployment_area(max_n_corals::Int64, target_areas::Vector{Float64})::Tuple{Float64,Float64}

function deployment_area(
max_n_corals::Int64,
target_areas::Vector{Float64}
)::Union{Tuple{Float64,Float64},Tuple{Float64,Vector{Float64}}}
min_cells::Int64 = 3
density::Float64 = 0.0
density = 0.0
req_area::Float64 = 0.0

for d in reverse(0.05:0.1:13.0)
req_area = area_needed(max_n_corals, d)

Expand All @@ -71,18 +92,29 @@ function deployment_area(max_n_corals::Int64, target_areas::Vector{Float64})::Tu
end

if density == 0.0
throw(DomainError("Could not determine adequate deployment density: $((RME_BASE_GRID_SIZE[] * req_area / sum(target_areas)))"))
throw(
DomainError(
"Could not determine adequate deployment density: $((RME_BASE_GRID_SIZE[] *sum(req_area) / sum(target_areas)))"
)
)
end

@info "Determined min. deployment density to be: $(density) / m²"

deployment_area_pct = min((req_area / sum(target_areas)) * 100.0, 100.0)

# In RME versions higher than 1.0.28 density needs to be a vector with each element representing density per species
rme_version = rme_version_info()
density =
if (rme_version.major == 1)&&(rme_version.minor == 0)&&(rme_version.patch <= 28)
density
else
fill(density, 6)
end
return deployment_area_pct, density
end

"""
set_outplant_deployment!(name::String, reefset::String, n_corals::Int64, year::Int64, area_km2::Vector{Float64}, density::Float64)::Nothing
set_outplant_deployment!(name::String, reefset::String, n_corals::Int64, year::Int64, area_km2::Vector{Float64}, density::Union{Float64, Vector{Float64}})::Nothing
Set outplanting deployments for a single year.
Expand All @@ -100,13 +132,15 @@ function set_outplant_deployment!(
n_corals::Int64,
year::Int64,
area_km2::Vector{Float64},
density::Float64
density::Union{Float64, Vector{Float64}}
)::Nothing
set_outplant_deployment!(name, reefset, n_corals, n_corals, year, year, 1, area_km2, density)
return set_outplant_deployment!(
name, reefset, n_corals, n_corals, year, year, 1, area_km2, density
)
end

"""
set_outplant_deployment!(name::String, reefset::String, n_corals::Int64, max_effort::Int64, first_year::Int64, last_year::Int64, year_step::Int64, area_km2::Vector{Float64}, density::Float64)::Nothing
set_outplant_deployment!(name::String, reefset::String, n_corals::Int64, max_effort::Int64, first_year::Int64, last_year::Int64, year_step::Int64, area_km2::Vector{Float64}, density::Union{Vector{Float64}, Float})::Nothing
Set outplanting deployments across a range of years.
Expand All @@ -130,15 +164,30 @@ function set_outplant_deployment!(
last_year::Int64,
year_step::Int64,
area_km2::Vector{Float64},
density::Float64
density::Union{Vector{Float64},Float64}
)::Nothing
iv_type = "outplant"

area_pct, mod_density = deployment_area(n_corals, max_effort, density, area_km2)

@RME ivAdd(name::Cstring, iv_type::Cstring, reefset::Cstring, first_year::Cint, last_year::Cint, year_step::Cint)::Cint
@RME ivAdd(
name::Cstring,
iv_type::Cstring,
reefset::Cstring,
first_year::Cint,
last_year::Cint,
year_step::Cint
)::Cint
@RME ivSetOutplantAreaPct(name::Cstring, area_pct::Cdouble)::Cint
@RME ivSetOutplantCountPerM2(name::Cstring, mod_density::Cdouble)::Cint

rme_version = rme_version_info()
if !((rme_version.major == 1)&&(rme_version.minor == 0)&&(rme_version.patch <= 28))
@RME ivSetOutplantCountPerM2(
name::Cstring, mod_density::Vector{Cdouble}, length(mod_density)::Cint
)::Cint
else
@RME ivSetOutplantCountPerM2(name::Cstring, mod_density::Cdouble)::Cint
end

return nothing
end
Expand All @@ -163,19 +212,11 @@ function set_outplant_deployment!(
year::Int64,
area_km2::Vector{Float64}
)::Nothing
set_outplant_deployment!(name, reefset, n_corals, year, year, 1, area_km2)
return set_outplant_deployment!(name, reefset, n_corals, year, year, 1, area_km2)
end

"""
set_outplant_deployment!(
name::String,
reefset::String,
max_effort::Int64,
first_year::Int64,
last_year::Int64,
year_step::Int64,
area_km2::Vector{Float64},
)::Nothing
set_outplant_deployment!(name::String, reefset::String, max_effort::Int64, first_year::Int64, last_year::Int64, year_step::Int64, area_km2::Vector{Float64})::Nothing
Set outplanting deployments across a range of years, automatically determining the
coral deployment density to maintain the set grid size.
Expand All @@ -187,28 +228,36 @@ function set_outplant_deployment!(
first_year::Int64,
last_year::Int64,
year_step::Int64,
area_km2::Vector{Float64},
area_km2::Vector{Float64}
)::Nothing
iv_type = "outplant"

area_pct, mod_density = deployment_area(max_effort, area_km2)

@RME ivAdd(name::Cstring, iv_type::Cstring, reefset::Cstring, first_year::Cint, last_year::Cint, year_step::Cint)::Cint
@RME ivAdd(
name::Cstring,
iv_type::Cstring,
reefset::Cstring,
first_year::Cint,
last_year::Cint,
year_step::Cint
)::Cint
@RME ivSetOutplantAreaPct(name::Cstring, area_pct::Cdouble)::Cint
@RME ivSetOutplantCountPerM2(name::Cstring, mod_density::Cdouble)::Cint

rme_version = rme_version_info()
if !((rme_version.major == 1)&&(rme_version.minor == 0)&&(rme_version.patch <= 28))
@RME ivSetOutplantCountPerM2(
name::Cstring, mod_density::Vector{Cdouble}, length(mod_density)::Cint
)::Cint
else
@RME ivSetOutplantCountPerM2(name::Cstring, mod_density::Cdouble)::Cint
end

return nothing
end

"""
set_enrichment_deployment!(
name::String,
reefset::String,
n_larvae::Int64,
year::Int64,
area_km2::Vector{Float64},
density::Float64
)::Nothing
set_enrichment_deployment!(name::String, reefset::String, n_larvae::Int64, year::Int64, area_km2::Vector{Float64}, density::Float64)::Nothing
As `set_seeding_deployment()` but for larvae enrichment (also known as assisted migration).
Set deployment for a single target year.
Expand All @@ -221,21 +270,13 @@ function set_enrichment_deployment!(
area_km2::Vector{Float64},
density::Float64
)::Nothing
set_enrichment_deployment!(name, reefset, n_larvae, n_larvae, year, year, 1, area_km2, density)
return set_enrichment_deployment!(
name, reefset, n_larvae, n_larvae, year, year, 1, area_km2, density
)
end

"""
set_enrichment_deployment!(
name::String,
reefset::String,
n_larvae::Int64,
max_effort::Int64,
first_year::Int64,
last_year::Int64,
year_step::Int64,
area_km2::Vector{Float64},
density::Float64
)::Nothing
set_enrichment_deployment!(name::String, reefset::String, n_larvae::Int64, max_effort::Int64, first_year::Int64, last_year::Int64, year_step::Int64, area_km2::Vector{Float64}, density::Float64)::Nothing
Set deployment for multiple years at a given frequency.
"""
Expand All @@ -254,7 +295,14 @@ function set_enrichment_deployment!(

area_pct, mod_density = deployment_area(n_larvae, max_effort, density, area_km2)

@RME ivAdd(name::Cstring, iv_type::Cstring, reefset::Cstring, first_year::Cint, last_year::Cint, year_step::Cint)::Cint
@RME ivAdd(
name::Cstring,
iv_type::Cstring,
reefset::Cstring,
first_year::Cint,
last_year::Cint,
year_step::Cint
)::Cint
@RME ivSetEnrichAreaPct(name::Cstring, area_pct::Cdouble)::Cint
@RME ivSetEnrichCountPerM2(name::Cstring, mod_density::Cdouble)::Cint

Expand Down
12 changes: 7 additions & 5 deletions src/interface.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""
area_needed(n_corals::Int64, density::Float64)::Float64
area_needed(n_corals::Int64, density::Union{Float64,Vector{Float64}})::Union{Vector{Float64},Float64}
Determine area (in km²) needed to deploy the given number of corals at the specified density.
Determine area (in km²) needed to deploy the given the number of corals at the specified density.
"""
function area_needed(n_corals::Int64, density::Float64)::Float64
function area_needed(
n_corals::Int64, density::Union{Float64,Vector{Float64}}
)::Union{Vector{Float64},Float64}
# ReefMod deploys twice a year so halve the number of corals to deploy
return ((n_corals * 0.5) / density) * m2_TO_km2 # Convert m² to km²
return ((n_corals * 0.5) ./ density) .* m2_TO_km2 # Convert m² to km²
end

"""
Expand All @@ -15,7 +17,7 @@ Get list of reef ids in the order expected by ReefMod Engine.
"""
function reef_ids()::Vector{String}
n_reefs = 3806
reef_id_list = fill("", n_reefs);
reef_id_list = fill("", n_reefs)

for i in 1:n_reefs
reef_id_list[i] = @RME reefId(i::Cint)::Cstring
Expand Down

0 comments on commit a6d3cfa

Please sign in to comment.