Constraint Macros
MacroEnergy.@add_balance — Macro
@add_balance(component, balance_id, equation)A macro to add a balance definition to a Node, Transformation, or Storage.
@add_balance is the primary balance-definition interface for asset modelers. It supports equality and inequality balances with flow(...) terms and scalar or time-varying coefficients.
@add_balance lets a modeler write a named flow relationship in ordinary algebraic form and attach it to a vertex. Macro stores that relationship as normalized balance data, which BalanceConstraint later enforces at each time step.
Arguments
component: The component object to add balance data tobalance_id: Symbol key for the balance equation (e.g.,:energy,:mass)equation: Balance equation with operators:==,=,<=,<,>=,>
Supported terms
flow(edge)
Coefficients
Coefficients may be:
- a scalar number
- a length-1 vector
- a vector with one coefficient per time step of the host vertex
Coefficients should be written before flow(edge), for example heat_rate * flow(edge).
@add_balance expects linear terms. Expressions such as c / flow(edge) are nonlinear because they divide by a decision variable. Write every flow term as a coefficient multiplied by a flow, such as (1 / efficiency) * flow(edge).
Examples
@add_balance(transform, :energy, flow(elec_edge) == 0.5 * flow(h2_edge))
@add_balance(transform, :energy_lb, flow(elec_edge) >= eff * flow(h2_edge))Method
@add_balance parses the equation, moves all terms onto the left-hand side, records the constraint sense (:eq, :le, or :ge), and converts each flow(...) term into a BalanceTerm. For flow terms, the stored coefficient is pre-adjusted using the edge incidence at the host vertex so that the compiled balance reproduces the algebraic equation the user wrote.
MacroEnergy.@add_stoichiometric_balance — Macro
@add_stoichiometric_balance(component, balance_id, equation, base_term)Expand a stoichiometric-style balance written with the --> operator into multiple pairwise balances anchored on base_term.
This macro is a convenience wrapper for recipe-style or chemical-style relationships. For general balances, @add_balance is the preferred interface.
@add_stoichiometric_balance lets a modeler describe a recipe using incoming_terms --> outgoing_terms, then expands that shorthand into one or more ordinary balances that Macro can store and enforce.
Example
@add_stoichiometric_balance(
electrolyzer,
:energy,
flow(elec_edge) --> efficiency * flow(h2_edge),
flow(h2_edge),
)Method
The macro parses the left and right sides of --> into weighted flow(...) terms, validates that left-hand terms are incoming and right-hand terms are outgoing relative to the host component, identifies the coefficient on base_term, and generates one pairwise @add_balance call for each remaining term using the proportional rule base_coeff * flow(term) - term_coeff * flow(base_term) == 0. This keeps the recipe syntax compact while delegating final balance construction to @add_balance.
MacroEnergy.@add_to_balance — Macro
@add_to_balance(component, balance_id, expression)Add one or more terms to an existing named balance without writing an explicit constraint sense. This stores the provided expression as a raw additive contribution to balance_id.
Modelers should usually write positive coefficients for both incoming and outgoing flow(...) terms. MacroEnergy applies edge-direction handling later when compiling the balance, so outgoing flows contribute with a negative sign in the common case.
Example
@add_to_balance(transform, :energy, flow(fuel_edge))
@add_to_balance(transform, :energy, 0.5 * flow(elec_edge))MacroEnergy.@add_to_storage_balance — Macro
@add_to_storage_balance(storage, expression)
@add_to_storage_balance(storage, :storage, expression)Add terms to the reserved :storage balance on a storage component. This macro is a convenience wrapper around @add_to_balance that defaults the balance ID to :storage.
Modelers should usually write positive coefficients for both inflow and outflow terms. MacroEnergy applies edge-direction handling later when compiling the final storage balance, so outgoing storage flows reduce storage in the common case.
Example
@add_to_storage_balance(storage, charge_efficiency * flow(charge_edge))
@add_to_storage_balance(storage, 1 / discharge_efficiency * flow(discharge_edge))MacroEnergy.@inspect_stoichiometric_balance — Macro
@inspect_stoichiometric_balance(component, balance_id, equation, base_term)
@inspect_stoichiometric_balance(component, balance_id, equation, base_term, verify_edge_directions = true)Return the pairwise algebraic balance equations that @add_stoichiometric_balance would generate.
This is a debugging helper for understanding the recipe expansion without reading the lower-level BalanceTerm machinery. The macro returns a vector of Pair{Symbol, Expr} values mapping each generated balance ID to the plain algebraic equation that would be passed to @add_balance.
By default the macro skips orientation validation so the algebraic expansion can be inspected without requiring live component and edge objects. Pass verify_edge_directions = true to reuse the same orientation validation as @add_stoichiometric_balance.