traitecoevo / plant

Trait-Driven Models of Ecology and Evolution :evergreen_tree:
https://traitecoevo.github.io/plant
53 stars 20 forks source link

Refactor Control and Parameters objects #306

Closed aornugent closed 2 years ago

aornugent commented 2 years ago

Background

When exposing Environment state variables in #305 we found it difficult to add new environment settings and accessing them in the correct place.

Worse -we only wanted to use some settings with some strategies. For example, the FF16_Strategy operates in a light only environment, but the new Water_Strategy includes water infiltration.

Both strategies leverage the FF16_Environment (to reuse the adaptive Canopy interpolator for calculating shading) but the FF16_Strategy does not initialise any soil layers, whereas the Water_Strategy segfaults if not initialised with a soil layer.

Proposed solution

We decided to resolve this by separating the Parameters object, which was kind of a dumping ground passing things into the SCM and Patch APIs:

Previously:

params <- scm_base_parameters("FF16")
params$disturbance_mean_interval <- 30.0
patch <- expand_parameters(trait_matrix(c(0.0825, 1.202), "lma"), params, mutant = FALSE)
result <- run_scm_collect(patch)

where the Parameters object holds a Control object, some information about the DisturbanceRegime, a Strategy and Environment type and one or more Strategies object(s)

class(params$control)    # "Control"
class(params)            # "Parameters<FF16,FF16_Env>" "Parameters"               
length(patch$strategies) # 2

Now: By passing in fully configured SpeciesParameters, Environment, DisturbanceRegime and Control objects, we can provide maximum flexibility, with sensible defaults for each strategy handled by the R interface:

result <- run_scm_collect(traits = expand_traits("FF16", trait_matrix), 
                          environment = set_environment("FF16", soil_n_depths = 12) , 
                          disturbance = NoDisturbance(), 
                          control = scm_default_control())

Notes

aornugent commented 2 years ago

On names: I think Traits is safest to avoid name clashes with the Species class. Traits matches well with the <T> type used throughout the C++ templates.

So:

Species<T, E> = Traits<T> + Environment<E>

where the Traits object(s) that are passed into the solver represent one or more instances of Strategy <T>?

dfalster commented 2 years ago

Hi @aornugent

Just checking where this is up to? I am considering the logic with hyper-parameterisation, and want to align with new API.

I see parts have been merged but perhaps not all?

aornugent commented 2 years ago

Hi @dfalster - I think the only thing left was a re-naming of Parameters. I'll file a separate issue for this and close the PR. The core API features have been merged:

result <- run_scm_collect(parameters, environment, control)