Skip to content
Snippets Groups Projects

Stats

Merged
pmagrequested to merge
stats into master
6 files
+ 1969
849
Compare changes
  • Side-by-side
  • Inline

Files

# imports
import pyomo.environ as pyo
# *****************************************************************************
# *****************************************************************************
def add_converters(
model: pyo.AbstractModel,
enable_default_values: bool = True,
enable_validation: bool = True,
enable_initialisation: bool = True,
):
# *************************************************************************
# *************************************************************************
# systems
# set of all systems
model.set_I = pyo.Set()
# set of optional systems
model.set_I_new = pyo.Set(within=model.set_I)
# *************************************************************************
# inputs
# set of inputs (indexed by system)
model.set_M = pyo.Set(model.set_I)
# set of inputs modelled using non-negative real variables
model.set_M_nnr = pyo.Set(model.set_I, within=model.set_M)
# set of inputs modelled using binary variables
model.set_M_bin = pyo.Set(model.set_I, within=model.set_M)
# set of amplitude-constrained inputs
model.set_M_dim = pyo.Set(model.set_I_new, within=model.set_M)
# set of amplitude-constrained inputs
model.set_M_fix = pyo.Set(model.set_I, within=model.set_M)
# set of externality-inducing inputs
model.set_M_ext = pyo.Set(model.set_I, within=model.set_M)
# *************************************************************************
# outputs
# set of outputs (indexed by system)
model.set_R = pyo.Set(model.set_I)
# set of outputs with fixed bounds
model.set_R_fix = pyo.Set(model.set_I, within=model.set_R)
# set of positive amplitude-constrained outputs
model.set_R_dim_pos = pyo.Set(model.set_I, within=model.set_R)
# set of negative amplitude-constrained outputs
model.set_R_dim_neg = pyo.Set(model.set_I, within=model.set_R)
# set of amplitude-limited outputs with matching pos. and neg. amplitudes
model.set_R_dim_eq = pyo.Set(model.set_I, within=model.set_R)
# set of outputs (indexed by system) inducing externalities
model.set_R_ext = pyo.Set(model.set_I)
# *************************************************************************
# states
# set of states
model.set_N = pyo.Set(model.set_I)
# set of states with fixed bounds
model.set_N_fix = pyo.Set(model.set_I, within=model.set_N)
# set of positive amplitude-constrained states
model.set_N_dim_pos = pyo.Set(model.set_I, within=model.set_N)
# set of negative amplitude-constrained states
model.set_N_dim_neg = pyo.Set(model.set_I, within=model.set_N)
# set of amplitude-limited states with matching pos. and neg. amplitudes
model.set_N_dim_eq = pyo.Set(model.set_I, within=model.set_N)
# set of states (indexed by system) inducing externalities
model.set_N_ext = pyo.Set(model.set_I, within=model.set_N)
# set of positive state variation-penalised states
model.set_N_pos_var = pyo.Set(model.set_I, within=model.set_N)
# set of negative state variation-penalised states
model.set_N_neg_var = pyo.Set(model.set_I, within=model.set_N)
# set of upper reference violation-penalised states
model.set_N_ref_u = pyo.Set(model.set_I, within=model.set_N)
# set of lower reference violation-penalised states
model.set_N_ref_d = pyo.Set(model.set_I, within=model.set_N)
# *************************************************************************
# *************************************************************************
# sparse index sets
# *************************************************************************
# *************************************************************************
# inputs
# set of IM tuples
def init_set_IM(m):
return ((i, m_i) for i in m.set_I for m_i in m.set_M[i])
model.set_IM = pyo.Set(dimen=2, initialize=init_set_IM)
# set of IM tuples for systems with binary signals
def init_set_IM_bin(m):
return ((i, m_i) for (i, m_i) in m.set_IM if m_i in m.set_M_bin[i])
model.set_IM_bin = pyo.Set(dimen=2, initialize=init_set_IM_bin, within=model.set_IM)
# set of IM tuples for tech. with dimensionable reference mode levels
def init_set_IM_dim(m):
return ((i, m_i) for (i, m_i) in m.set_IM if m_i in m.set_M_dim[i])
model.set_IM_dim = pyo.Set(dimen=2, initialize=init_set_IM_dim, within=model.set_IM)
# set of IM tuples for fixed amplitude inputs
def init_set_IM_fix(m):
return ((i, m_i) for (i, m_i) in m.set_IM if m_i in m.set_M_fix[i])
model.set_IM_fix = pyo.Set(dimen=2, initialize=init_set_IM_fix, within=model.set_IM)
# set of IM tuples for technologies whose modes can induce externalities
def init_set_IM_ext(m):
return ((i, m_i) for (i, m_i) in m.set_IM if m_i in m.set_M_ext[i])
model.set_IM_ext = pyo.Set(dimen=2, initialize=init_set_IM_ext, within=model.set_IM)
# *************************************************************************
# states
# set of IN tuples
def init_set_IN(m):
return (
(i, n_i) for i in m.set_I for n_i in m.set_N[i] # IN tuple
) # for each state
model.set_IN = pyo.Set(dimen=2, initialize=init_set_IN)
# set of IN tuples for states with fixed bounds
def init_set_IN_fix(m):
return ((i, n_i) for i in m.set_I for n_i in m.set_N_fix[i])
model.set_IN_fix = pyo.Set(dimen=2, initialize=init_set_IN_fix)
# set of IN tuples for converters with amplitude-constrained states
def init_set_IN_dim_eq(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_dim_eq[i])
model.set_IN_dim_eq = pyo.Set(
dimen=2, initialize=init_set_IN_dim_eq, within=model.set_IN
)
# set of IN tuples for converters with pos. amplitude-constrained states
def init_set_IN_dim_pos(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_dim_pos[i])
model.set_IN_dim_pos = pyo.Set(
dimen=2, initialize=init_set_IN_dim_pos, within=model.set_IN
)
# set of IN tuples for converters with neg. amplitude-constrained states
def init_set_IN_dim_neg(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_dim_neg[i])
model.set_IN_dim_neg = pyo.Set(
dimen=2, initialize=init_set_IN_dim_neg, within=model.set_IN
)
# set of IN tuples for converters with externality-inducing states
def init_set_IN_ext(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_ext[i])
model.set_IN_ext = pyo.Set(dimen=2, initialize=init_set_IN_ext, within=model.set_IN)
# set of IN tuples for positive variation-penalised states
def init_set_IN_pos_var(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_pos_var[i])
model.set_IN_pos_var = pyo.Set(
dimen=2, initialize=init_set_IN_pos_var, within=model.set_IN
)
# set of IN tuples for negative variation-penalised states
def init_set_IN_neg_var(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_neg_var[i])
model.set_IN_neg_var = pyo.Set(
dimen=2, initialize=init_set_IN_neg_var, within=model.set_IN
)
# set of IN tuples for upper reference violation penalised states
def init_set_IN_ref_u(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_ref_u[i])
model.set_IN_ref_u = pyo.Set(
dimen=2, initialize=init_set_IN_ref_u, within=model.set_IN
)
# set of IN tuples for lower reference violation penalised states
def init_set_IN_ref_d(m):
return ((i, n_i) for (i, n_i) in m.set_IN if n_i in m.set_N_ref_d[i])
model.set_IN_ref_d = pyo.Set(
dimen=2, initialize=init_set_IN_ref_d, within=model.set_IN
)
# *************************************************************************
# outputs
# set of IR tuples
def init_set_IR(m):
return ((i, r_i) for i in m.set_I for r_i in m.set_R[i])
model.set_IR = pyo.Set(dimen=2, initialize=init_set_IR)
# set of IR tuples for outputs with fixed bounds
def init_set_IR_fix(m):
return ((i, r_i) for i in m.set_I for r_i in m.set_R_fix[i])
model.set_IR_fix = pyo.Set(dimen=2, initialize=init_set_IR_fix)
# set of IR tuples for converters with matching pos. and neg. out. amp. limits
def init_set_IR_dim_eq(m):
return ((i, r_i) for (i, r_i) in m.set_IR if r_i in m.set_R_dim_eq[i])
model.set_IR_dim_eq = pyo.Set(dimen=2, initialize=init_set_IR_dim_eq)
# set of IR tuples for converters with amplitude-penalised outputs
def init_set_IR_dim_neg(m):
return ((i, r_i) for (i, r_i) in m.set_IR if r_i in m.set_R_dim_neg[i])
model.set_IR_dim_neg = pyo.Set(dimen=2, initialize=init_set_IR_dim_neg)
# set of IR tuples for converters with amplitude-penalised outputs
def init_set_IR_dim(m):
return ((i, r_i) for (i, r_i) in m.set_IR if r_i in m.set_R_dim[i])
model.set_IR_dim = pyo.Set(dimen=2, initialize=init_set_IR_dim)
# set of IR tuples for converters with pos. amplitude-constrained outputs
def init_set_IR_dim_pos(m):
return ((i, r_i) for (i, r_i) in m.set_IR if r_i in m.set_R_dim_pos[i])
model.set_IR_dim_pos = pyo.Set(dimen=2, initialize=init_set_IR_dim_pos)
# set of IR tuples for converters with externality-inducing outputs
def init_set_IR_ext(m):
return ((i, r_i) for (i, r_i) in m.set_IR if r_i in m.set_R_ext[i])
model.set_IR_ext = pyo.Set(dimen=2, initialize=init_set_IR_ext)
# *************************************************************************
# combined inputs/states/outputs
# TODO: narrow down these sets if possible
# set of INN tuples
def init_set_INN(m):
return ((i, n1, n2) for (i, n1) in m.set_IN for n2 in m.set_N[i])
model.set_INN = pyo.Set(dimen=3, initialize=init_set_INN)
# set of INM tuples
def init_set_INM(m):
return ((i, n_i, m_i) for (i, n_i) in m.set_IN for m_i in m.set_M[i])
model.set_INM = pyo.Set(dimen=3, initialize=init_set_INM)
# set of IRM tuples
def init_set_IRM(m):
return (
(i, r_i, m_i) for (i, r_i) in m.set_IR for m_i in m.set_M[i]
) # can be further constrained
model.set_IRM = pyo.Set(dimen=3, initialize=init_set_IRM)
# set of IRN tuples
def init_set_IRN(m):
return (
(i, r_i, n_i) for (i, r_i) in m.set_IR for n_i in m.set_N[i]
) # can be further constrained
model.set_IRN = pyo.Set(dimen=3, initialize=init_set_IRN)
# *************************************************************************
# *************************************************************************
# parameters
# converters
# externality cost per input unit
model.param_c_ext_u_imqk = pyo.Param(
model.set_IM_ext, model.set_QK, within=pyo.NonNegativeReals, default=0
)
# externality cost per output unit
model.param_c_ext_y_irqk = pyo.Param(
model.set_IR_ext, model.set_QK, within=pyo.NonNegativeReals, default=0
)
# externality cost per state unit
model.param_c_ext_x_inqk = pyo.Param(
model.set_IN_ext, model.set_QK, within=pyo.NonNegativeReals, default=0
)
# unit cost of positive state variations
model.param_c_pos_var_in = pyo.Param(
model.set_IN_pos_var, within=pyo.NonNegativeReals, default=0
)
# unit cost of negative state variations
model.param_c_neg_var_in = pyo.Param(
model.set_IN_neg_var, within=pyo.NonNegativeReals, default=0
)
# unit cost of upper state reference violations
model.param_c_ref_u_inqk = pyo.Param(
model.set_IN_ref_u, model.set_QK, within=pyo.NonNegativeReals, default=0
)
# unit cost of lower state reference violations
model.param_c_ref_d_inqk = pyo.Param(
model.set_IN_ref_d, model.set_QK, within=pyo.NonNegativeReals, default=0
)
# minimum converter cost
model.param_c_cvt_min_i = pyo.Param(
model.set_I_new, within=pyo.NonNegativeReals, default=0
)
# unit (positive) input amplitude cost
model.param_c_cvt_u_im = pyo.Param(
model.set_IM_dim, within=pyo.NonNegativeReals, default=0
)
# unit output amplitude cost
model.param_c_cvt_y_ir = pyo.Param(
model.set_IR_dim, within=pyo.NonNegativeReals, default=0
)
# unit positive state amplitude cost
model.param_c_cvt_x_pos_in = pyo.Param(
model.set_IN_dim_pos, within=pyo.NonNegativeReals, default=0
)
# unit negative state amplitude cost
model.param_c_cvt_x_neg_in = pyo.Param(
model.set_IN_dim_neg, within=pyo.NonNegativeReals, default=0
)
# unit positive output amplitude cost
model.param_c_cvt_y_pos_ir = pyo.Param(
model.set_IR_dim_pos, within=pyo.NonNegativeReals, default=0
)
# unit negative output amplitude cost
model.param_c_cvt_y_neg_ir = pyo.Param(
model.set_IR_dim_neg, within=pyo.NonNegativeReals, default=0
)
# *************************************************************************
# effect of system inputs on specific network and node pairs
model.param_a_nw_glimqk = pyo.Param(
model.set_GL_not_exp_imp,
model.set_IM,
model.set_QK,
default=0, # default: no effect
within=pyo.Reals,
)
# effect of system outputs on specific network and node pairs
model.param_a_nw_glirqk = pyo.Param(
model.set_GL_not_exp_imp,
model.set_IR,
model.set_QK,
default=0, # default: no effect
within=pyo.Reals,
)
# *************************************************************************
# inputs
# upper bounds for (non-binary, non-dimensionable) inputs
model.param_u_ub_imqk = pyo.Param(
model.set_IM_fix, model.set_QK, within=pyo.PositiveReals
)
# maximum input limits
model.param_u_amp_max_im = pyo.Param(
model.set_IM_dim, within=pyo.PositiveReals, default=1
)
# time interval-dependent adjustment coefficients for input limits
model.param_f_amp_u_imqk = pyo.Param(
model.set_IM_dim, model.set_QK, within=pyo.PositiveReals, default=1
)
# *************************************************************************
# states
# initial conditions
model.param_x_inq0 = pyo.Param(model.set_IN, model.set_Q, within=pyo.Reals)
# fixed upper bounds for state variables
model.param_x_ub_irqk = pyo.Param(model.set_IN_fix, model.set_QK, within=pyo.Reals)
# fixed lower bounds for state variables
model.param_x_lb_irqk = pyo.Param(model.set_IN_fix, model.set_QK, within=pyo.Reals)
# maximum positive amplitude for states
model.param_x_amp_pos_max_in = pyo.Param(
model.set_IN_dim_pos, within=pyo.PositiveReals
)
# maximum negative amplitude for states
model.param_x_amp_neg_max_in = pyo.Param(
model.set_IN_dim_neg, within=pyo.PositiveReals
)
# adjustment of positive state amplitude limits
model.param_f_amp_pos_x_inqk = pyo.Param(
model.set_IN_dim_pos, model.set_QK, within=pyo.PositiveReals, default=1
)
# adjustment of negative state amplitude limits
model.param_f_amp_neg_x_inqk = pyo.Param(
model.set_IN_dim_neg, model.set_QK, within=pyo.PositiveReals, default=1
)
# state equations: coefficients from C matrix
model.param_a_eq_x_innqk = pyo.Param(
model.set_INN, model.set_QK, default=0, within=pyo.Reals # default: no effect
)
# state equations: coefficients from D matrix
model.param_b_eq_x_inmqk = pyo.Param(
model.set_INM, model.set_QK, default=0, within=pyo.Reals # default: no effect
)
# state equations: constant term
model.param_e_eq_x_inqk = pyo.Param(
model.set_IN, model.set_QK, default=0, within=pyo.Reals # default: no effect
)
# *************************************************************************
# outputs
# fixed upper bounds for output variables
model.param_y_ub_irqk = pyo.Param(model.set_IR_fix, model.set_QK, within=pyo.Reals)
# fixed lower bounds for output variables
model.param_y_lb_irqk = pyo.Param(model.set_IR_fix, model.set_QK, within=pyo.Reals)
# adjustment of positive output amplitude limits
model.param_f_amp_y_pos_irqk = pyo.Param(
model.set_IR_dim_pos, model.set_QK, within=pyo.PositiveReals, default=1
)
# adjustment of negative output amplitude limits
model.param_f_amp_y_neg_irqk = pyo.Param(
model.set_IR_dim_neg, model.set_QK, within=pyo.PositiveReals, default=1
)
# maximum positive amplitude limit for outputs
model.param_y_amp_pos_max_ir = pyo.Param(
model.set_IR_dim_pos, within=pyo.PositiveReals
)
# maximum negative amplitude limit for outputs
model.param_y_amp_neg_max_ir = pyo.Param(
model.set_IR_dim_neg, within=pyo.PositiveReals
)
# output equation coefficients from C matrix
model.param_c_eq_y_irnqk = pyo.Param(
model.set_IRN, model.set_QK, default=0, within=pyo.Reals # default: no effect
)
# output equation coefficients from D matrix
model.param_d_eq_y_irmqk = pyo.Param(
model.set_IRM, model.set_QK, default=0, within=pyo.Reals # default: no effect
)
# output equation constant
model.param_e_eq_y_irqk = pyo.Param(
model.set_IR, model.set_QK, default=0, within=pyo.Reals # default: no effect
)
# *************************************************************************
# *************************************************************************
# *************************************************************************
# *************************************************************************
# variables
# *************************************************************************
# *************************************************************************
# capex for installing individual converters
model.var_capex_cvt_i = pyo.Var(model.set_I_new, within=pyo.NonNegativeReals)
# *************************************************************************
# converters
# decision to install converter i
model.var_cvt_inv_i = pyo.Var(model.set_I_new, within=pyo.Binary)
# inputs
# input variables
def bounds_var_u_imqk(m, i, m_i, q, k):
if (i, m_i) in m.param_u_ub_imqk:
# predefined limit
return (0, m.param_u_ub_imqk[(i, m_i, q, k)])
else:
# dynamic limit (set elsewhere)
return (0, None)
def domain_var_u_imqk(m, i, m_i, q, k):
try:
if m_i in m.set_M_bin[i]:
return pyo.Binary # binary: {0,1}
else:
return pyo.NonNegativeReals # nonnegative real: [0,inf]
except KeyError:
return pyo.NonNegativeReals # nonnegative real: [0,inf]
model.var_u_imqk = pyo.Var(
model.set_IM,
model.set_QK,
domain=domain_var_u_imqk,
# within=pyo.NonNegativeReals,
bounds=bounds_var_u_imqk,
)
# input amplitude variables (only one per sign is needed, as vars. are nnr)
model.var_u_amp_im = pyo.Var(model.set_IM_dim, within=pyo.NonNegativeReals)
# *************************************************************************
# outputs
# output variables
def bounds_var_y_irqk(m, i, r, q, k):
if r in m.set_R_fix:
# predefined limit
return (m.param_u_lb_irqk[(i, r, q, k)], m.param_u_ub_irqk[(i, r, q, k)])
else:
# do not enforce any limits
return (None, None)
# def domain_var_y_irqk(m, i, r, k):
# try:
# if m_i in m.set_M_bin[i]:
# return pyo.Binary # binary: {0,1}
# else:
# return pyo.NonNegativeReals # nonnegative real: [0,inf]
# except KeyError:
# return pyo.NonNegativeReals # nonnegative real: [0,inf]
model.var_y_irqk = pyo.Var(
model.set_IR, model.set_QK, bounds=bounds_var_y_irqk, within=pyo.Reals
)
# positive output amplitudes
model.var_y_amp_pos_ir = pyo.Var(model.set_IR_dim_pos, within=pyo.Reals)
# output amplitudes
model.var_y_amp_neg_ir = pyo.Var(model.set_IR_dim_neg, within=pyo.Reals)
# *************************************************************************
# states
# state variables
model.var_x_inqk = pyo.Var(model.set_IN, model.set_QK, within=pyo.Reals)
# positive amplitude variables
model.var_x_amp_pos_in = pyo.Var(model.set_IN_dim_pos, within=pyo.NonNegativeReals)
# negative amplitude variables
model.var_x_amp_neg_in = pyo.Var(model.set_IN_dim_neg, within=pyo.NonNegativeReals)
# positive state variation
model.var_delta_x_pos_var_in = pyo.Var(
model.set_IN_pos_var, within=pyo.NonNegativeReals
)
# negative state variation
model.var_delta_x_neg_var_in = pyo.Var(
model.set_IN_neg_var, within=pyo.NonNegativeReals
)
# positive reference state violation
model.var_delta_x_ref_u_inqk = pyo.Var(
model.set_IN_ref_u, model.set_QK, within=pyo.NonNegativeReals
)
# negative reference state violation
model.var_delta_x_ref_d_inqk = pyo.Var(
model.set_IN_ref_d, model.set_QK, within=pyo.NonNegativeReals
)
# *************************************************************************
# *************************************************************************
# objective function
# capex for converters
def rule_capex_converter(m, i):
return (
m.var_cvt_inv_i[i] * m.param_c_cvt_min_i[i]
+ sum(
m.var_u_amp_im[(i, m_i)] * m.param_c_cvt_u_im[(i, m_i)]
for m_i in m.set_M_dim_i[i]
)
+ sum(
m.var_x_amp_pos_in[(i, n)] * m.param_c_cvt_x_pos_in[(i, n)]
for n in m.set_N_dim_pos[i]
)
+ sum(
m.var_x_amp_neg_in[(i, n)] * m.param_c_cvt_x_neg_in[(i, n)]
for n in m.set_N_dim_neg[i]
)
+ sum(
m.var_y_amp_pos_ir[(i, r)] * m.param_c_cvt_y_pos_ir[(i, r)]
for r in m.set_N_dim_pos[i]
)
+ sum(
m.var_y_amp_neg_ir[(i, r)] * m.param_c_cvt_y_neg_ir[(i, r)]
for r in m.set_N_dim_neg[i]
)
<= m.var_capex_cvt_i[i]
)
model.constr_capex_system = pyo.Constraint(
model.set_I_new, rule=rule_capex_converter
)
# *************************************************************************
# *************************************************************************
# converters
# *************************************************************************
# *************************************************************************
# input signal limits for dimensionable inputs
def rule_constr_u_limit_dim(m, i, m_i, q, k):
return (
m.var_u_imqk[(i, m_i, q, k)]
<= m.var_u_amp_im[(i, m_i)] * m.param_f_amp_u_imqk[(i, m_i, q, k)]
)
model.constr_u_limit_dim = pyo.Constraint(
model.set_IM_dim, model.set_QK, rule=rule_constr_u_limit_dim
)
# nominal input amplitude limit for dimensionable inputs
def rule_constr_u_amp_ub(m, i, m_i):
return (
m.var_u_amp_im[(i, m_i)]
<= m.var_cvt_inv_i[i] * m.param_u_amp_max_im[(i, m_i)]
)
model.constr_u_amp_ub = pyo.Constraint(model.set_IM_dim, rule=rule_constr_u_amp_ub)
# fixed upper limits
def rule_constr_u_fix_limits(m, i, m_i, q, k):
# if we need to know the lim input signal (e.g., for the obj. func.)
if i in m.set_I_new:
# new converter
return (
m.var_u_imqk[(i, m_i, q, k)]
<= m.param_u_ub_imqk[(i, m_i, q, k)] * m.var_cvt_inv_i[i]
)
return m.var_u_imqk[(i, m_i, q, k)] <= m.var_cvt_inv_i[i]
else:
# pre-existing
return m.var_u_imqk[(i, m_i, q, k)] <= m.param_u_ub_imqk[(i, m_i, q, k)]
model.constr_u_fix_limits = pyo.Constraint(
model.set_IM_fix, model.set_QK, rule=rule_constr_u_fix_limits
)
# input limits for binary inputs
def rule_constr_u_bin_limits(m, i, m_i, q, k):
if i in m.set_I_new:
# binary variables
return m.var_u_imqk[(i, m_i, q, k)] <= m.var_cvt_inv_i[i]
else:
return pyo.Constraint.Skip
model.constr_u_bin_limits = pyo.Constraint(
model.set_IM_bin, model.set_QK, rule=rule_constr_u_bin_limits
)
# *************************************************************************
# outputs
# output equations
def rule_constr_output_equations(m, i, r, q, k):
return (
m.var_y_irqk[(i, r, k)]
== sum(
m.param_c_eq_y_irnqk[(i, r, n_i, q, k)] * m.var_x_inqk[(i, n_i, q, k)]
for n_i in m.set_N[i]
)
+ sum(
m.param_d_eq_y_irmqk[(i, r, m_i, q, k)] * m.var_u_imqk[(i, m_i, q, k)]
for m_i in m.set_M[i]
)
+ m.param_e_eq_y_irqk[(i, r, q, k)]
)
model.constr_output_equations = pyo.Constraint(
model.set_IR, model.set_QK, rule=rule_constr_output_equations
)
# positive amplitude limit for output variables
def rule_constr_y_vars_have_pos_amp_limits(m, i, r, q, k):
return m.var_y_irqk[(i, r, q, k)] <= (
m.var_y_amp_pos_ir[(i, r)] * m.param_f_amp_y_pos_irqk[(i, r, q, k)]
)
model.constr_y_vars_have_pos_amp_limits = pyo.Constraint(
model.set_IR_dim_pos, model.set_QK, rule=rule_constr_y_vars_have_pos_amp_limits
)
# negative amplitude limit for output variables
def rule_constr_y_vars_have_neg_amp_limits(m, i, r, q, k):
return m.var_y_irqk[(i, r, q, k)] >= (
-m.var_y_amp_neg_ir[(i, r)] * m.param_f_amp_y_neg_irqk[(i, r, q, k)]
)
model.constr_y_vars_have_neg_amp_limits = pyo.Constraint(
model.set_IR_dim_neg, model.set_QK, rule=rule_constr_y_vars_have_neg_amp_limits
)
# positive amplitude limit must be zero unless the system is installed
def rule_constr_y_amp_pos_zero_if_cvt_not_selected(m, i, r):
return m.var_y_amp_pos_ir[(i, r)] <= (
m.var_cvt_inv_i[i] * m.param_y_amp_pos_ir[(i, r)]
)
model.constr_y_amp_pos_zero_if_cvt_not_newected = pyo.Constraint(
model.set_IR_dim_pos, rule=rule_constr_y_amp_pos_zero_if_cvt_not_selected
)
# negative amplitude limit must be zero unless the system is installed
def rule_constr_y_amp_neg_zero_if_cvt_not_selected(m, i, r):
return m.var_y_amp_neg_ir[(i, r)] <= (
m.var_cvt_inv_i[i] * m.param_y_amp_neg_ir[(i, r)]
)
model.constr_y_amp_neg_zero_if_cvt_not_selected = pyo.Constraint(
model.set_IR_dim_neg, rule=rule_constr_y_amp_neg_zero_if_cvt_not_selected
)
# the positive and negative amplitudes must match
def rule_constr_y_amp_pos_neg_match(m, i, r):
return m.var_y_amp_pos_ir[(i, r)] == m.var_y_amp_neg_ir[(i, r)]
model.constr_y_amp_pos_neg_match = pyo.Constraint(
model.set_IR_dim_eq, rule=rule_constr_y_amp_pos_neg_match
)
# *************************************************************************
# states
def rule_constr_state_equations(m, i, n, q, k):
return (
m.var_x_inqk[(i, n, q, k)]
== sum(
m.param_a_eq_x_innqk[(i, n, n_star, q, k)]
* (
m.var_x_inqk[(i, n_star, q, k - 1)]
if k != 0
else m.param_x_inq0[(i, n, q)]
)
for n_star in m.set_N[i]
)
+ sum(
m.param_b_eq_x_inmqk[(i, n, m_i, q, k)] * m.var_u_imqk[(i, m_i, q, k)]
for m_i in m.set_M[i]
)
+ m.param_e_eq_x_inqk[(i, n, q, k)]
)
model.constr_state_equations = pyo.Constraint(
model.set_IN, model.set_QK, rule=rule_constr_state_equations
)
# positive amplitude limit for state variables
def rule_constr_x_vars_have_pos_amp_limits(m, i, n, q, k):
return m.var_x_inqk[(i, n, q, k)] <= (
m.var_x_amp_pos_in[(i, n)] * m.param_f_amp_x_pos_inqk[(i, n, q, k)]
)
model.constr_x_vars_have_pos_amp_limits = pyo.Constraint(
model.set_IN_dim_pos, model.set_QK, rule=rule_constr_x_vars_have_pos_amp_limits
)
# negative amplitude limit for state variables
def rule_constr_x_vars_have_neg_amp_limits(m, i, n, q, k):
return m.var_x_inqk[(i, n, q, k)] >= (
-m.var_y_amp_neg_in[(i, n)] * m.param_f_amp_x_neg_inqk[(i, n, q, k)]
)
model.constr_x_vars_have_neg_amp_limits = pyo.Constraint(
model.set_IN_dim_neg, model.set_QK, rule=rule_constr_x_vars_have_neg_amp_limits
)
# positive amplitude limit must be zero unless the system is installed
def rule_constr_x_amp_pos_zero_if_cvt_not_selected(m, i, n):
return m.var_x_amp_pos_in[(i, n)] <= (
m.var_cvt_inv_i[i] * m.param_x_amp_pos_in[(i, n)]
)
model.constr_x_amp_pos_zero_if_cvt_not_selected = pyo.Constraint(
model.set_IN_dim_pos, rule=rule_constr_x_amp_pos_zero_if_cvt_not_selected
)
# negative amplitude limit must be zero unless the system is installed
def rule_constr_x_amp_neg_zero_if_cvt_not_selected(m, i, n):
return m.var_x_amp_neg_in[(i, n)] <= (
m.var_cvt_inv_i[i] * m.param_x_amp_neg_in[(i, n)]
)
model.constr_x_amp_neg_zero_if_cvt_not_selected = pyo.Constraint(
model.set_IN_dim_neg, rule=rule_constr_x_amp_neg_zero_if_cvt_not_selected
)
# the positive and negative amplitudes must match
def rule_constr_x_amp_pos_neg_match(m, i, n):
return m.var_x_amp_pos_in[(i, n)] == m.var_x_amp_neg_in[(i, n)]
model.constr_x_amp_pos_neg_match = pyo.Constraint(
model.set_IN_dim_eq, rule=rule_constr_x_amp_pos_neg_match
)
# *************************************************************************
# *************************************************************************
return model
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
# *****************************************************************************
Loading