Demand And Flexibility

Demand-side builders cover fixed consumption, annually constrained flexible consumption, and virtual demand response. All components are created and connected immediately. Electric vehicles are covered separately in Electric Vehicles.

See Component Builders for shared naming, workbook, cost, capacity, and port conventions, and Tags And Post-Processing for tagging and reporting. Each section's diagram follows the conventions in Reading The Port Diagrams.

Electricity Demand

makedemand creates a fixed Nosy demand with the name "$name $(n.name)". Its input profile is

\[d_t = c p_t + D / 8760,\]

where c is profile_multiplier, p_t is the workbook series selected by zone, and D is annual_flat_demand. profile_shift_hours circularly shifts the workbook series before the flat term is added. Setting profile_multiplier=0 suppresses the workbook lookup, which is useful for self-contained examples and purely flat demand.

When grid_losses is non-zero, the builder adds a linked grid losses input proportional to demand. The value must lie in [0, 1).

Ports of an electricity demand component

Tags: :tech => tech, :zone => n.name, and the function tags electricity and demand.

The workbook series is read from sheet demand, column <zone>. With the standard hourly MW/MWh convention, annual_flat_demand is in MWh/year.

See the One Country example for a complete model using this builder.

Posy2.makedemand — Function
makedemand(name::String, zone::String, n::Node, s::Snapshot;
    tech::String=name, profile=nothing, profile_multiplier=1.0, profile_shift_hours::Int=0,
    annual_flat_demand::Real=0., grid_losses=0.,
)

Build, connect and return a component based on the Demand template.

Arguments:

  • name: component name prefix.
  • tech: technology label used for reporting and component queries; defaults to name.
  • zone: time series name in the time series workbook (demand sheet).
  • n: demand node to connect the component to.
  • s: snapshot to register the component in.
  • profile: Hourly demand in MW, or a scalar expanded across the simulation mesh. If nothing, read zone from the demand sheet.
  • profile_multiplier: Dimensionless multiplier applied to the profile demand. 0 disables it and skips the zone, profile, and profile_shift_hours inputs.
  • profile_shift_hours: Circular profile shift in hours (e.g. align the first day to Monday).
  • annual_flat_demand: Flat demand in MWh/year, distributed over 8760 hours (annual_flat_demand >= 0).
  • grid_losses: Proportional grid-loss fraction on demand input (0 <= grid_losses < 1).
source

Hydrogen Demand

makeflathydrogendemand creates a fixed input of annual_demand / 8760 at a hydrogen node. makeflexhydrogendemand instead creates a flexible input whose sum over the model year must equal annual_demand. Both builders therefore take an annual hydrogen-energy quantity, but only the flat builder fixes its hourly shape.

The generated name is "$name $(n.name)". They do not read a workbook and do not add a cost or capacity behaviour.

Ports of a flat hydrogen demand component

Ports of a flexible hydrogen demand component

Tags for both builders: :tech => tech, :zone => n.name, and the function tags hydrogen and demand.

Posy2.makeflathydrogendemand — Function
makeflathydrogendemand(name::String, n::Node, annual_demand::Real, s::Snapshot;
    tech::String=name)

Build, connect and return a flat hydrogen demand component.

Arguments:

  • name: component name prefix.
  • tech: technology label used for reporting and component queries; defaults to name.
  • n: hydrogen demand node to connect the component to.
  • annual_demand: Total hydrogen demand in MWh/year. Must satisfy annual_demand >= 0.
  • s: snapshot to register the component in.
source
Posy2.makeflexhydrogendemand — Function
makeflexhydrogendemand(name::String, n::Node, annual_demand::Real, s::Snapshot;
    tech::String=name)

Build, connect and return a flexible hydrogen demand component.

Arguments:

  • name: component name prefix.
  • tech: technology label used for reporting and component queries; defaults to name.
  • n: hydrogen demand node to connect the component to.
  • annual_demand: Total hydrogen demand in MWh/year, enforced through YearlySum("input", annual_demand, :equal). Must satisfy annual_demand >= 0.
  • s: snapshot to register the component in.
source

Demand Response

makedemandresponse represents demand response as negative consumption at the electricity node. Its positive output is an unconnected accounting flow used for capacity, activation cost, and reporting. A linked negative consumption input equal to -(1 - elec.losses) * output is connected instead, so the existing consumption components remain unchanged while demand response enters the nodal balance from the demand side. With zero node losses this is exactly -output. A numeric cap adds fixed response capacity, a JuMP variable or affine expression reuses an external response-capacity decision, nothing creates a new response-capacity decision, and Inf leaves response output unlimited. Because these last two cases are easy to confuse, cap=nothing emits a warning suggesting cap=Inf when unlimited capacity was intended.

Ports of a demand response component

cost is the activation cost per unit of the positive output flow and is applied directly. type selects the variable-cost category used by reports and defaults to :volDR.

The generated component is named "$name $(elec.name)".

Tags: :tech => tech, :zone => elec.name, and the function tags virtual and demandresponse.

See the Demand Response example for a complete model using this builder.

Posy2.makedemandresponse — Function
makedemandresponse(name::String, elec::Node, cap, cost::Real, s::Snapshot;
    tech::String=name, type::Symbol=:volDR)

Build, connect and return a demand response component represented as negative consumption.

The positive output is an unconnected accounting flow used for capacity, cost, and reporting. The connected negative consumption input is -(1 - elec.losses) * output; when node losses are zero, it is exactly -output. Consequently, activation enters the nodal balance on the demand side without modifying existing demand components.

Arguments:

  • name: component name prefix.
  • tech: technology label used for reporting and component queries; defaults to name.
  • elec: electricity node to connect the component to.
  • cap: Response capacity in MW. A number fixes capacity, a JuMP VariableRef or AffExpr reuses that expression, nothing creates a capacity decision, and Inf leaves output unlimited. nothing emits a warning to distinguish it from unlimited capacity.
  • cost: Activation cost in currency/MWh.
  • s: snapshot to register the component in.
  • type: variable cost label used for reporting (default :volDR).
source