Skip to content

Commit

Permalink
Merge pull request #35 from PALEOtoolkit/setup_fixes
Browse files Browse the repository at this point in the history
Fix setup of constant (non-state) Variables
  • Loading branch information
sjdaines authored Jun 26, 2022
2 parents 4167fbd + 5883223 commit 7c03f36
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PALEOboxes"
uuid = "804b410e-d900-4b2a-9ecd-f5a06d4c1fd4"
authors = ["Stuart Daines <[email protected]>"]
version = "0.19.1"
version = "0.19.2"

[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
Expand Down
2 changes: 1 addition & 1 deletion src/VariableReaction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ function create_accessors(va::VarList_components, modeldata::AbstractModelData)
if va.allow_unlinked
append!(accessors_generic, fill(nothing, num_components(v)))
else
error("create_accessors(::VarList_components, ) - unlinked variable $(v.reaction.name).$(v.localname) $v")
error("create_accessors(::VarList_components, ) - unlinked variable $(fullname(v)) $v")
end
else
append!(accessors_generic, a)
Expand Down
7 changes: 6 additions & 1 deletion src/reactioncatalog/Reservoirs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,12 @@ function PB.register_methods!(rj::ReactionReservoirScalar)

if rj.pars.const.v
R = PB.VarPropScalar( "R", "mol", "scalar constant reservoir", attributes=(:field_data =>rj.pars.field_data.v,))
PB.add_method_setup_initialvalue_vars_default!(rj, [R], filterfn = v->true, setup_callback=setup_callback) # force setup even though R is not a state Variable
PB.add_method_setup_initialvalue_vars_default!(
rj, [R],
filterfn = v->true, # force setup even though R is not a state Variable
force_initial_norm_value=true, # setup :norm_value, :initial_value to get norm_value callback, even though R is not a state Variable
setup_callback=setup_callback
)
# no _sms variable
else
R = PB.VarStateExplicitScalar("R", "mol", "scalar reservoir", attributes=(:field_data =>rj.pars.field_data.v,))
Expand Down
47 changes: 35 additions & 12 deletions src/reactionmethods/SetupInitializeUtilityMethods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@
add_method_setup_initialvalue_vars_default!(react::AbstractReaction, variables [; kwargs...])
Create and add a default method to initialize Variables matching `filterfn` (defaults to state Variables)
from Attributes `:initial_value`, `:norm_value` at beginning of integration.
at beginning of integration.
# Setup callbacks used
- State Variables and similar (`:vfunction != VF_Undefined`) are initialized in a setup callback with
`attribute_name in (:initial_value, :norm_value)`, with values from those Variable attributes.
- If `force_state_norm_value=false`, other Variables (with `:vfunction == VF_Undefined`) are initialized in a setup callback with
`attribute_name=:setup`, with values from the `:initial_value` Variable attribute. NB: `filterfn` must be set to include these Variables.
- If `force_initial_norm_value=true`, all Variables (including those with `:vfunction == VF_Undefined`) are initialised as state Variables
# Keywords
- `filterfn`: set to f(var)::Bool to override the default selection on :vfunction for state variables.
- `filterfn`: set to f(var)::Bool to override the default selection for state variables only
(Variables with `:vfunction in (VF_StateExplicit, VF_State, VF_Total, VF_Constraint)`)
- `force_initial_norm_value=false`: `true` to always use `:initial_value`, `:norm_value`, even for variables with `:vfunction=VF_Undefined`
- `transfer_attribute_vars=[]`: Set to a list of the same length as `variables` to initialise `variables`
from attributes of `transfer_attribute_vars`.
- `setup_callback=(method, attribute_name, var, vardata) -> nothing`: Set to a function that is called
Expand All @@ -33,6 +42,7 @@ Example: To interpret `:initial_value` as a concentration-like quantity:
function add_method_setup_initialvalue_vars_default!(
react::AbstractReaction, variables;
filterfn=var -> get_attribute(var, :vfunction) in (VF_StateExplicit, VF_State, VF_Total, VF_Constraint),
force_initial_norm_value=false,
transfer_attribute_vars = [],
convertvars = [],
convertfn = (convertvars_tuple, i) -> 1.0,
Expand All @@ -58,7 +68,7 @@ function add_method_setup_initialvalue_vars_default!(
react,
setup_initialvalue_vars_default,
(VarList_fields(setup_vars), VarList_tuple(setup_transfer_vars), VarList_tuple(convertvars)),
p = (convertfn, convertinfo, setup_callback),
p = (force_initial_norm_value, convertfn, convertinfo, setup_callback),
)

return nothing
Expand All @@ -75,11 +85,8 @@ function setup_initialvalue_vars_default(
cellrange::AbstractCellRange,
attribute_name
)
attribute_name in (:norm_value, :initial_value) || return

(convertfn, convertinfo, setup_callback) = m.p

@info "$(fullname(m)):"
(force_initial_norm_value, convertfn, convertinfo, setup_callback) = m.p

# VariableReactions corresponding to (vardata, transfervardata, convertvarsdata)
vars, transfer_attribute_vars, convertvars = get_variables_tuple(m)

Expand All @@ -90,16 +97,32 @@ function setup_initialvalue_vars_default(
attrbvars = [v.linkvar for v in transfer_attribute_vars]
end

for (rv, v, attrbv, vfield) in IteratorUtils.zipstrict(vars, domvars, attrbvars, varfields)

first_var = true
for (rv, v, attrbv, vfield) in IteratorUtils.zipstrict(vars, domvars, attrbvars, varfields)
vfunction = get_attribute(v, :vfunction, VF_Undefined)
if vfunction == VF_Undefined && !force_initial_norm_value
# non-state Variables are initialized in :setup, from :initial_value attribute
attribute_name == :setup || continue
attribute_to_read = :initial_value
else
# state Variables etc are initialized in :initial_value, :norm_value, from that attribute
attribute_name in (:initial_value, :norm_value) || continue
attribute_to_read = attribute_name
end

if first_var
@info "$(fullname(m)):"
first_var = false
end

if v === attrbv
trsfrinfo = ""
else
trsfrinfo = " [from $(fullname(attrbv))]"
end

init_field!(
vfield, attribute_name, attrbv, convertfn, convertvarsdata, cellrange, (fullname(v), convertinfo, trsfrinfo)
vfield, attribute_to_read, attrbv, convertfn, convertvarsdata, cellrange, (fullname(v), convertinfo, trsfrinfo)
)

setup_callback(m, attribute_name, rv, vfield.values)
Expand Down

2 comments on commit 7c03f36

@sjdaines
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/63151

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.19.2 -m "<description of version>" 7c03f36ecc00043a4f89de00b0d5d9d7082069ef
git push origin v0.19.2

Please sign in to comment.