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

Interface and design #21

Open
simonbyrne opened this issue May 19, 2020 · 2 comments
Open

Interface and design #21

simonbyrne opened this issue May 19, 2020 · 2 comments
Assignees

Comments

@simonbyrne
Copy link
Member

simonbyrne commented May 19, 2020

The current package was a stop-gap until we can figure out something more useable.

In the current package we would have a series of .toml files; the first would specify the parameter sets:

# ParameterSets.toml
[ sets.Default ]

[ sets.Earth ]
inherit = "Default"

the second would specify the parameters:

# parameters/Universal.toml

[gas_constant]
description = "Universal gas constant"
units = "J/mol/K"
value.Default = 8.3144598
# parameters/Planet.toml

[molmass_water]
description = "Molecular weight"
units = "kg/mol"
value.Earth = 18.01528e-3
# parameters/Atmos.toml

[SGS.C_smag]
description = "Smagorinsky constant"
units = ""
value.Earth = 0.21

We will still keep the idea that parameter sets are types, and parameters are functions, but we have the problem that in Julia you can't subtype concrete types. So what I was thinking is that we could build our own inheritance system, so the above would generate:

abstract type AbstractParameterSet end

struct Default{FT} <: AbstractParameterSet end
struct Earth{FT} <: AbstractParameterSet end
parent(::Earth{FT}) where {FT} = Default{FT}()

and that each parameter would promote if no compatible parameter set was found, e.g.

gas_constant(ps::AbstractParameterSet) = gas_constant(parent(ps))
gas_constant(::Default{FT}) = FT(8.3144598)

Some open questions:

How to handle derive quantities?

We could allow symbolic expressions, where any non-numeric symbols would be treated as parameters, i.e.

[molmass_ratio]
derived.Default = "molmass_dryair / molmass_water"

would generate:

molmass_ratio(ps::Default{FT}) = molmass_dryair(ps) / molmass_water(ps)

How to override parameter values

An experiment would provide their own custom Toml file, which would have a simplified version of the above schema:

# Custom.toml
inherit = "Earth"

[values]
Atmos.SGS.C_smag = 0.20

How to specify a parameter ensemble?

There are two ways we could do this: the first is an array of tables:

# Ensemble1.toml
inherit = "Earth"

[[ ensemble ]]
Atmos.SGS.C_smag = 0.2012

[[ ensemble ]]
Atmos.SGS.C_smag = 0.2194

[[ ensemble ]]
Atmos.SGS.C_smag = 0.2102

The second is just specifying arrays for the relevant parameters

# Ensemble1.toml
inherit = "Earth"

[ ensembles ]
Atmos.SGS.C_smag = [0.2012, 0.2194, 0.2102]

This would correspond to a struct with fields for the ensemble parameters, and the parameter would just access the field:

struct Ensemble1{FT}
   C_smag::FT
end
Atmos.SGS.C_smag(ps::Ensemble1{FT}) = ps.C_smag

and we would need to store vector of ensemble members somewhere:

const Ensemble1_vals = [Ensemble1(0.2012), Ensemble1(0.2194), Ensemble1(0.2102)]

How to specify prior distributions?

TBD...

@simonbyrne
Copy link
Member Author

abstract type AbstractParameterSet end

struct Default{FT} <: AbstractParameterSet end
struct Earth{FT} <: AbstractParameterSet end
parent(::Earth{FT}) where {FT} = Default{FT}()

Ah, it occurred to me that one downside of this is that it would break derived quantities, e.g.

molmass_ratio(ps::Default{FT}) = molmass_dryair(ps) / molmass_water(ps)

since calling molmass_ratio(Earth{FT}()) => molmass_ratio(Default{FT}()) => molmass_dryair(Default{FT}()) / molmass_water(Default{FT}()) which would throw an error.

The only other way I can see to do this is to define an abstract type and a struct for every ParameterSet, not dissimilar to what we have now (except that the struct would be part of the repo).

@vchuravy
Copy link

You can also specify the inheritance tree with abstract types and then have a ParameterSet{Earth}, where Earth is a abstract type. Not sure what the best solution here is.

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

No branches or pull requests

4 participants