Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/src/nodes/multiplebuildingtypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This approach allows modeling building demands with flexible penalty mechanisms

The subtype [`MultipleBuildingTypes`](@ref) is used to enable a specialized constructor that samples the [`Tecnalia_Building-Stock-Energy-Model`](https://github.com/iDesignRES/Tecnalia_Building-Stock-Energy-Model) module.

The subtype [`Building`](@ref) can be used to model a simple building demand where the heat demand is calculated from the temperature at a single location and a user-defined temperature-to-demand function.
The subtype [`Building`](@ref) can be used to model a simple building demand where the heat demand is calculated from the temperature at a single location and a user-defined temperature-to-demand function.
See the [constructor](@ref lib-pub-sampling_constructors) for more details.

!!! note "Sampling Tecnalia_Building-Stock-Energy-Model module"
Expand Down Expand Up @@ -42,8 +42,8 @@ Standard fields of [AbstractBuildings](@ref EMLI.AbstractBuildings) nodes are gi
All values have to be non-negative.
- **`data::Vector{<:ExtensionData}`**:\
An entry for providing additional data to the model.
In the current version, it is not applicable.
We intend to change this in future releases to enable investments.
The subtype [`MultipleBuildingTypes`](@ref) adds automatically [`EmissionsEnergy`](@extref EnergyModelsBase.EmissionsEnergy) to account for the emissions given by energy consumption through an inner constructor, if not specified explicitly.
The subtype [`Building`](@ref) does not automatically add [`EmissionsEnergy`](@extref EnergyModelsBase.EmissionsEnergy) as it is not a requirement that the emissions are associated directly to this node.

!!! note "Constructor for `AbstractBuildings` nodes"
The field `data` is not required as we include a constructor when the value is excluded.
Expand Down
49 changes: 32 additions & 17 deletions src/datastructures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ abstract type AbstractParameters end

"""
PVParameters
PVParameters(lat::Real, lon::Real; loss::Real = 14.0,
pvtechchoice::String = "crystSi", mountingplace::String = "free",
optimalangles::Bool = true, usehorizon::Bool = true,
PVParameters(lat::Real, lon::Real; loss::Real = 14.0,
pvtechchoice::String = "crystSi", mountingplace::String = "free",
optimalangles::Bool = true, usehorizon::Bool = true,
)

A structure to hold parameters for photovoltaic (PV) power generation.
Expand Down Expand Up @@ -206,7 +206,7 @@ end
PV <: AbstractNonDisRES

A photovoltaic source. It extends the existing `AbstractNonDisRES` node through extracting
data from the PVGIS tool from the EU Science Hub (available at https://re.jrc.ec.europa.eu/pvg_tools)
data from the PVGIS tool from the EU Science Hub (available at https://re.jrc.ec.europa.eu/pvg_tools)
through a constructor.

# Fields
Expand Down Expand Up @@ -584,15 +584,15 @@ end
)

Constructs a [`Building`](@ref) instance where the heat demand profile is generated from temperature data
downloaded using hindcast data (see [`heat_demand_profile`](@ref) for details).
downloaded using hindcast data (see [`heat_demand_profile`](@ref) for details).
The temperature-to-demand mapping is provided by `temp_to_demand`.

# Arguments
- **`id`** is the name/identifier of the node.
- **`cap::Dict{<:Resource,<:TimeProfile}`** is the demand (no need to provide heat demand, it will be generated).
- **`penalty_surplus::Dict{<:Resource,<:TimeProfile}`** are the penalties for surplus.
- **`penalty_deficit::Dict{<:Resource,<:TimeProfile}`** are the penalties for deficit.
- **`input::Dict{<:Resource,<:Real}`** are the input [`Resource`](@extref EnergyModelsBase.Resource)s
- **`input::Dict{<:Resource,<:Real}`** are the input [`Resource`](@extref EnergyModelsBase.Resource)s
with conversion value `Real`.
- **`time_start::DateTime`** is the start time for the demand profile.
- **`time_end::DateTime`** is the end time for the demand profile.
Expand Down Expand Up @@ -664,8 +664,9 @@ and deficit.
- **`penalty_deficit::Dict{<:Resource,<:TimeProfile}`** are the penalties for deficit.
- **`input::Dict{<:Resource,<:Real}`** are the input
[`Resource`](@extref EnergyModelsBase.Resource)s with conversion value `Real`.
- **`data::Vector{<:ExtensionData}`** is the additional data (*e.g.*, for investments). The field `data`
is conditional through usage of a constructor.
- **`data::Vector{<:ExtensionData}`** is the additional data. The field `data` is
conditional through usage of a constructor. An inner constructor adds
[`EmissionsEnergy`](@extref EnergyModelsBase.EmissionsEnergy) as data if it is not specified.

!!! danger
Investments are not available for this node.
Expand All @@ -677,6 +678,21 @@ struct MultipleBuildingTypes <: AbstractBuildings
penalty_deficit::Dict{<:Resource,<:TimeProfile}
input::Dict{<:Resource,<:Real}
data::Vector{<:ExtensionData}
function MultipleBuildingTypes(
id::Any,
cap::Dict{<:Resource,<:TimeProfile},
penalty_surplus::Dict{<:Resource,<:TimeProfile},
penalty_deficit::Dict{<:Resource,<:TimeProfile},
input::Dict{<:Resource,<:Real},
data::Vector{<:ExtensionData},
)
# Add emission data if it is not included by the user
if !any(isa.(data, EmissionsData))
data = convert(Vector{ExtensionData}, data)
push!(data, EmissionsEnergy())
end
new(id, cap, penalty_surplus, penalty_deficit, input, data)
end
end
function MultipleBuildingTypes(
id::Any,
Expand All @@ -691,7 +707,7 @@ function MultipleBuildingTypes(
penalty_surplus,
penalty_deficit,
input,
ExtensionData[],
ExtensionData[EmissionsEnergy()],
)
end

Expand Down Expand Up @@ -804,8 +820,8 @@ function MultipleBuildingTypes(
overwrite_saved_data::Bool = false,
)
oper_length = length(T.operational[1]) # Assume the length to be the same in all Strategic periods
resources = values(resources_map)
cap_vec = Dict{Resource,Vector}(resource => zeros(oper_length) for resource ∈ resources)
𝒫 = values(resources_map)
cap_vec = Dict{Resource,Vector}(resource => zeros(oper_length) for resource ∈ 𝒫)

data_path = joinpath(data_location, "all_buildings.yml")
if isfile(data_path) && !overwrite_saved_data
Expand Down Expand Up @@ -850,13 +866,12 @@ function MultipleBuildingTypes(
end
end

# Convert to OperationalProfile
cap = Dict{Resource,TimeProfile}(
resource => OperationalProfile(cap_vec[resource]) for
resource ∈ resources
)
# Convert the demand profile to OperationalProfile
cap = Dict{Resource,TimeProfile}(p => OperationalProfile(cap_vec[p]) for p ∈ 𝒫)

# Create the input map for the node
input = Dict{Resource,Float64}(p => 1.0 for p ∈ 𝒫)

input = Dict{Resource,Real}(resource => 1.0 for resource ∈ resources)
return MultipleBuildingTypes(id, cap, penalty_surplus, penalty_deficit, input, data)
end

Expand Down
6 changes: 3 additions & 3 deletions test/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ end
function simple_graph_buildings(; cap_p = nothing,
penalty_surplus = Dict(HeatHT=>FixedProfile(0.5), Power=>FixedProfile(0.5)),
penalty_deficit = Dict(HeatHT=>FixedProfile(0.5), Power=>FixedProfile(0.5)),
input = Dict(HeatHT=>1.0, Power=>1.0))
input = Dict(HeatHT=>1.0, Power=>1.0),
)

# Creation of the initial problem with the NonDisRES node
time_start_str = "2019-01-01"
time_end_str = "2019-01-07"
Expand All @@ -120,7 +122,6 @@ function simple_graph_buildings(; cap_p = nothing,
operational_periods = SimpleTimes(op_number, op_duration)

sp_duration = [1, 2, 10]
sp_number = length(sp_duration)
T = TwoLevel(sp_duration, operational_periods; op_per_strat = 8760.0)

# Load paths to default Buildings process
Expand Down Expand Up @@ -193,7 +194,6 @@ function simple_graph_buildings(; cap_p = nothing,
T, # Time structure
penalty_surplus, # surplus penalty for the node in €/MWh;
penalty_deficit, # deficit penalty for the node in €/MWh;
data = [EmissionsEnergy()],
data_location = joinpath(pkgdir(EMLI), "test", "data", "buildings"),
overwrite_saved_data = false,
)
Expand Down
Loading