Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor constructor #143

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open

Refactor constructor #143

wants to merge 31 commits into from

Conversation

radka-j
Copy link
Contributor

@radka-j radka-j commented Jan 30, 2025

Closes #141

Overview for reviewers

In the end this is not really a refactor. In addition to the construct method, which we already had, this PR adds an instantiate method.

As before, the user starts by constructing the type, which fixes:

  • the number of phyto/zooplankton in the model
  • tracer functions to be used (and the associated parameters)

If a user wants to change any of these quantities they have to create a new type. The reason we can't have the N of plankton change dynamically is because there have to be as many tracer functions as there are plankton and their input arguments also depends on how many plankton there are in the model.

Once a type is created, the user can instantiate an object with the default values just by calling the type, as we've done before:

N2P2ZD = Agate.Constructors.NPZD_size_structured.construct()
model = N2P2ZD()

Note that the constructor takes in size dependent parameters and computers emergent parameters from those. The emergent parameters are then used as fields in the N2P2ZD struct.

The above wasn't satisfactory on its own because the user might want to instantiate the model using different size-dependant parameter values. They can now do this using the new function:

model = Agate.Constructors.NPZD_size_structured.instantiate(N2P2ZD; <phyto/zoo args here...>)

Same as the constructor, this takes in the size dependent parameters, does the required computation and instantiates the struct with the computed emergent parameters.

The annoying thing is that if the user wants to use different tracer functions (and arguments) than the default, they have to pass the updated arguments to both functions but I don't see an obvious way around this:

N2P2ZD_geider = Agate.Constructors.NPZD_size_structured.construct(;
    phyto_args=Agate.Constructors.NPZD_size_structured.DEFAULT_PHYTO_GEIDER_ARGS,
    nutrient_dynamics=nutrients_geider_light,
    phyto_dynamics=phytoplankton_growth_single_nutrient_geider_light,
)

model_geider = Agate.Constructors.NPZD_size_structured.instantiate(
    N2P2ZD_geider;
    phyto_args=Agate.Constructors.NPZD_size_structured.DEFAULT_PHYTO_GEIDER_ARGS,
)

I'd appreciate any feedback on this - the general structure as well the naming conventions. It's worth saying that there is some further refactoring to do in how we handle things like sinking tracers but I'll tackle that in a separate PR.

@radka-j radka-j mentioned this pull request Jan 31, 2025
1 task
@radka-j radka-j marked this pull request as ready for review February 11, 2025 17:11
@radka-j radka-j requested review from nanophyto and ljwolf February 11, 2025 17:16
@nanophyto
Copy link
Contributor

The annoying thing is that if the user wants to use different tracer functions (and arguments) than the default, they have to pass the updated arguments to both functions but I don't see an obvious way around this:

N2P2ZD_geider = Agate.Constructors.NPZD_size_structured.construct(;
    phyto_args=Agate.Constructors.NPZD_size_structured.DEFAULT_PHYTO_GEIDER_ARGS,
    nutrient_dynamics=nutrients_geider_light,
    phyto_dynamics=phytoplankton_growth_single_nutrient_geider_light,
)

model_geider = Agate.Constructors.NPZD_size_structured.instantiate(
    N2P2ZD_geider;
    phyto_args=Agate.Constructors.NPZD_size_structured.DEFAULT_PHYTO_GEIDER_ARGS,
)

Yes, this is not ideal but since this still works:

N2P2ZD_geider = Agate.Constructors.NPZD_size_structured.construct(;
     phyto_args=Agate.Constructors.NPZD_size_structured.DEFAULT_PHYTO_GEIDER_ARGS,
     nutrient_dynamics=nutrients_geider_light,
     phyto_dynamics=phytoplankton_growth_single_nutrient_geider_light,
)
N2P2ZD_geider() 

I don't think it is too much of an issue.

@nanophyto
Copy link
Contributor

I'd appreciate any feedback on this - the general structure as well the naming conventions. It's worth saying that there is some further refactoring to do in how we handle things like sinking tracers but I'll tackle that in a separate PR.

I worry that instantiate is too technical - but it is hard to come up with a better alternative, so maybe I'm overthinking it. Thinking out loud: update, revise, clone, spawn. The main context in which it would be used would be updating it in a for loop or something like latin hypercube sampling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor high level constructor interface
2 participants