From 5a83e589c05e97f81a12a1b710ed592049ab1244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Str=C3=B6mer?= Date: Fri, 18 Oct 2024 14:05:06 +0200 Subject: [PATCH] feat: allow storing multiple finalizer function for a single Virtual, which are executed in reverse (inner-most template first) order --- src/IESopt.jl | 11 ++++++----- src/core/virtual.jl | 1 + src/templates/parse.jl | 38 ++++++++++++++++++++------------------ 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/IESopt.jl b/src/IESopt.jl index 4533a37..95ebca1 100644 --- a/src/IESopt.jl +++ b/src/IESopt.jl @@ -154,11 +154,12 @@ function _build_model!(model::JuMP.Model; callbacks::Union{Nothing, Dict}) end end - # TODO: rework storage of Virtuals/templates/... since we can actually access them as first-class CoreComponents - # without having to store them separately - # Call finalization functions of all Core Templates. - for (name, entry) in _iesopt(model).results._templates - entry.finalize(entry.virtual) + @info "Finalizing Virtuals" + for component in corder + component isa Virtual || continue + for i in reverse(eachindex(component._finalizers)) + component._finalizers[i](component) + end end # Construct relevant ETDF constraints. diff --git a/src/core/virtual.jl b/src/core/virtual.jl index 04f6365..4ecb419 100644 --- a/src/core/virtual.jl +++ b/src/core/virtual.jl @@ -17,6 +17,7 @@ might expect (and want) to be able to interact with "my_storage_foo". Since the # [Internal] ======================================================================================================= _parameters = Dict{String, Any}() + _finalizers::Vector{Base.Callable} = Base.Callable[] # [External] ======================================================================================================= # - diff --git a/src/templates/parse.jl b/src/templates/parse.jl index 11af97f..ce98080 100644 --- a/src/templates/parse.jl +++ b/src/templates/parse.jl @@ -56,26 +56,29 @@ function _parse_noncore_component!( parameters[k] = v end - # Write the final version of parameters into the Virtual. - virtual = _iesopt(model).model.components[cname] - merge!(virtual._parameters, parameters) + if haskey(template.yaml, "functions") + @warn "It is highly recommended NOT to use `functions` in single component templates that just \"rename\" another template" template = template.name maxlog = 1 - # Validate and then prepare. - template.functions[:validate](virtual) || @critical "Template validation failed" component = cname - template.functions[:prepare](virtual) + # Write the final version of parameters into the Virtual. + virtual = _iesopt(model).model.components[cname] + merge!(virtual._parameters, parameters) - # Add an entry for finalization. - _iesopt(model).results._templates[cname] = - (finalize=template.functions[:finalize], virtual=virtual) # parameters=parameters, items=Vector{Any}()) + # Validate and then prepare. + template.functions[:validate](virtual) || @critical "Template validation failed" component = cname + template.functions[:prepare](virtual) - # Convert data types that do not "render" well to strings using JSON. - # Example: - # `Dict{String, Any}("electricity" => 1)` will just be rendered as `"Dict{String, Any}("electricity" => 1)"`, - # which then messes with replacement in the YAML parsing. + # Add an entry for finalization. + push!(virtual._finalizers, template.functions[:finalize]) - # This would result in modifying the original `parameters` dictionary, which is not desired. - # Therefore, we keep a copy (not a deep copy!) and modify that, only duplicating potential json-ed items. - parameters = copy(virtual._parameters) + # Convert data types that do not "render" well to strings using JSON. + # Example: + # `Dict{String, Any}("electricity" => 1)` will just be rendered as `"Dict{String, Any}("electricity" => 1)"`, + # which then messes with replacement in the YAML parsing. + + # This would result in modifying the original `parameters` dictionary, which is not desired. + # Therefore, we keep a copy (not a deep copy!) and modify that, only duplicating potential json-ed items. + parameters = copy(virtual._parameters) + end # Convert data types that do not "render" well to strings using JSON. # Example: @@ -202,8 +205,7 @@ function _parse_container!( template.functions[:prepare](virtual) # Add an entry for finalization. - _iesopt(model).results._templates[name] = - (finalize=template.functions[:finalize], virtual=virtual) # parameters=parameters, items=Vector{Any}()) + push!(virtual._finalizers, template.functions[:finalize]) # Convert data types that do not "render" well to strings using JSON. # Example: