Process Constraints

Process Capacity Rule: The constraint process capacity rule defines the variable total process capacity \(\kappa_{yvp}\). The variable total process capacity is defined by the constraint as the sum of the parameter process capacity installed \(K_{vp}\) and the variable new process capacity \(\hat{\kappa}_{yvp}\). The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint process capacity rule is defined and calculated by the following code fragment:

m.def_process_capacity = pyomo.Constraint(
    m.pro_tuples,
    rule=def_process_capacity_rule,
    doc='total process capacity = inst-cap + new capacity')
def def_process_capacity_rule(m, stf, sit, pro):
    if m.mode['int']:
        if (sit, pro, stf) in m.inst_pro_tuples:
            if (sit, pro, min(m.stf)) in m.pro_const_cap_dict:
                cap_pro = m.process_dict['inst-cap'][(stf, sit, pro)]
            else:
                cap_pro = \
                    (sum(m.cap_pro_new[stf_built, sit, pro]
                         for stf_built in m.stf
                         if (sit, pro, stf_built, stf)
                         in m.operational_pro_tuples) +
                     m.process_dict['inst-cap'][(min(m.stf), sit, pro)])
        else:
            cap_pro = sum(
                m.cap_pro_new[stf_built, sit, pro]
                for stf_built in m.stf
                if (sit, pro, stf_built, stf) in m.operational_pro_tuples)
    else:
        if (sit, pro, stf) in m.pro_const_cap_dict:
            cap_pro = m.process_dict['inst-cap'][(stf, sit, pro)]
        else:
            cap_pro = (m.cap_pro_new[stf, sit, pro] +
                       m.process_dict['inst-cap'][(stf, sit, pro)])
    return cap_pro

Process Input Rule: The constraint process input rule defines the variable process input commodity flow \(\epsilon_{yvcpt}^\text{in}\). The variable process input commodity flow is defined by the constraint as the product of the variable process throughput \(\tau_{yvpt}\) and the parameter process input ratio \(r_{ypc}^\text{in}\).The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint process input rule is defined and calculated by the following code fragment:

m.def_process_input = pyomo.Constraint(
    m.tm, m.pro_input_tuples - m.pro_partial_input_tuples,
    rule=def_process_input_rule,
    doc='process input = process throughput * input ratio')
def def_process_input_rule(m, tm, stf, sit, pro, com):
    return (m.e_pro_in[tm, stf, sit, pro, com] ==
            m.tau_pro[tm, stf, sit, pro] * m.r_in_dict[(stf, pro, com)])

Process Output Rule: The constraint process output rule defines the variable process output commodity flow \(\epsilon_{yvcpt}^\text{out}\). The variable process output commodity flow is defined by the constraint as the product of the variable process throughput \(\tau_{yvpt}\) and the parameter process output ratio \(r_{ypc}^\text{out}\). The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint process output rule is defined and calculated by the following code fragment:

m.def_process_output = pyomo.Constraint(
    m.tm, (m.pro_output_tuples - m.pro_partial_output_tuples -
           m.pro_timevar_output_tuples),
    rule=def_process_output_rule,
    doc='process output = process throughput * output ratio')
def def_process_output_rule(m, tm, stf, sit, pro, com):
    return (m.e_pro_out[tm, stf, sit, pro, com] ==
            m.tau_pro[tm, stf, sit, pro] * m.r_out_dict[(stf, pro, com)])

Intermittent Supply Rule: The constraint intermittent supply rule defines the variable process input commodity flow \(\epsilon_{yvcpt}^\text{in}\) for processes \(p\) that use a supply intermittent commodity \(c \in C_\text{sup}\) as input. Therefore this constraint only applies if a commodity is an intermittent supply commodity \(c \in C_\text{sup}\). The variable process input commodity flow is defined by the constraint as the product of the variable total process capacity \(\kappa_{yvp}\) and the parameter intermittent supply capacity factor \(s_{yvct}\), scaled by the size of the timesteps \(\Delta t\). The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint intermittent supply rule is defined and calculated by the following code fragment:

m.def_intermittent_supply = pyomo.Constraint(
    m.tm, m.pro_input_tuples,
    rule=def_intermittent_supply_rule,
    doc='process output = process capacity * supim timeseries')
def def_intermittent_supply_rule(m, tm, stf, sit, pro, coin):
    if coin in m.com_supim:
        return (m.e_pro_in[tm, stf, sit, pro, coin] ==
                m.cap_pro[stf, sit, pro] * m.supim_dict[(sit, coin)]
                [(stf, tm)] * m.dt)
    else:
        return pyomo.Constraint.Skip

Process Throughput by Capacity Rule: The constraint process throughput by capacity rule limits the variable process throughput \(\tau_{yvpt}\). This constraint prevents processes from exceeding their capacity. The constraint states that the variable process throughput must be less than or equal to the variable total process capacity \(\kappa_{yvp}\), scaled by the size of the timesteps \(\Delta t\). The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint process throughput by capacity rule is defined and calculated by the following code fragment:

m.res_process_throughput_by_capacity = pyomo.Constraint(
    m.tm, m.pro_tuples,
    rule=res_process_throughput_by_capacity_rule,
    doc='process throughput <= total process capacity')
def res_process_throughput_by_capacity_rule(m, tm, stf, sit, pro):
    return (m.tau_pro[tm, stf, sit, pro] <= m.dt * m.cap_pro[stf, sit, pro])

Process Throughput Gradient Rule: The constraint process throughput gradient rule limits the process power gradient \(\left| \tau_{yvpt} - \tau_{yvp(t-1)} \right|\). This constraint prevents processes from exceeding their maximal possible change in activity from one time step to the next. The constraint states that absolute power gradient must be less than or equal to the maximal power gradient \(\overline{PG}_{yvp}\) parameter (scaled to capacity and by timestep duration). The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint process throughput gradient rule is split into 2 parts and defined and calculated by the following code fragments:

m.res_process_maxgrad_lower = pyomo.Constraint(
    m.tm, m.pro_maxgrad_tuples,
    rule=res_process_maxgrad_lower_rule,
    doc='throughput may not decrease faster than maximal gradient')
m.res_process_maxgrad_upper = pyomo.Constraint(
    m.tm, m.pro_maxgrad_tuples,
    rule=res_process_maxgrad_upper_rule,
    doc='throughput may not increase faster than maximal gradient')
def res_process_maxgrad_lower_rule(m, t, stf, sit, pro):
    return (m.tau_pro[t - 1, stf, sit, pro] -
            m.cap_pro[stf, sit, pro] *
            m.process_dict['max-grad'][(stf, sit, pro)] * m.dt <=
            m.tau_pro[t, stf, sit, pro])
def res_process_maxgrad_upper_rule(m, t, stf, sit, pro):
    return (m.tau_pro[t - 1, stf, sit, pro] +
            m.cap_pro[stf, sit, pro] *
            m.process_dict['max-grad'][(stf, sit, pro)] * m.dt >=
            m.tau_pro[t, stf, sit, pro])

Process Capacity Limit Rule: The constraint process capacity limit rule limits the variable total process capacity \(\kappa_{yvp}\). This constraint restricts a process \(p\) in a site \(v\) and support timeframe \(y\) from having more total capacity than an upper bound and having less than a lower bound. The constraint states that the variable total process capacity \(\kappa_{yvp}\) must be greater than or equal to the parameter process capacity lower bound \(\underline{K}_{yvp}\) and less than or equal to the parameter process capacity upper bound \(\overline{K}_{yvp}\). The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py the constraint process capacity limit rule is defined and calculated by the following code fragment:

m.res_process_capacity = pyomo.Constraint(
    m.pro_tuples,
    rule=res_process_capacity_rule,
    doc='process.cap-lo <= total process capacity <= process.cap-up')
def res_process_capacity_rule(m, stf, sit, pro):
    return (m.process_dict['cap-lo'][stf, sit, pro],
            m.cap_pro[stf, sit, pro],
            m.process_dict['cap-up'][stf, sit, pro])

Sell Buy Symmetry Rule: The constraint sell buy symmetry rule defines the total process capacity \(\kappa_{yvp}\) of a process \(p\) in a site \(v\) and support timeframe \(y\) that uses either sell or buy commodities ( \(c \in C_\text{sell} \vee C_\text{buy}\)), therefore this constraint only applies to processes that use sell or buy commodities. The constraint states that the total process capacities \(\kappa_{yvp}\) of processes that use complementary buy and sell commodities must be equal. Buy and sell commodities are complementary, when a commodity \(c\) is an output of a process where the buy commodity is an input, and at the same time the commodity \(c\) is an input commodity of a process where the sell commodity is an output. The mathematical explanation of this rule is given in Trading with an External Market.

In script BuySellPrice.py the constraint sell buy symmetry rule is defined and calculated by the following code fragment:

m.res_sell_buy_symmetry = pyomo.Constraint(
    m.pro_input_tuples,
    rule=res_sell_buy_symmetry_rule,
    doc='total power connection capacity must be symmetric in both '
        'directions')
def res_sell_buy_symmetry_rule(m, stf, sit_in, pro_in, coin):
    # constraint only for sell and buy processes
    # and the processes must be in the same site
    if coin in m.com_buy:
        sell_pro = search_sell_buy_tuple(m, stf, sit_in, pro_in, coin)
        if sell_pro is None:
            return pyomo.Constraint.Skip
        else:
            return (m.cap_pro[stf, sit_in, pro_in] ==
                    m.cap_pro[stf, sit_in, sell_pro])
    else:
        return pyomo.Constraint.Skip

Process Time Variable Output Rule: This constraint multiplies the process efficiency with the parameter time series \(f_{yvpt}^\text{out}\). The process output for all commodities is thus manipulated depending on time. This constraint is not valid for environmental commodities since these are typically linked to an input commodity flow rather than an output commodity flow. The mathematical explanation of this rule is given in Time Variable Efficiency.

In script TimeVarEff.py the constraint process time variable output rule is defined and calculated by the following code fragment:

m.def_process_timevar_output = pyomo.Constraint(
    m.tm, m.pro_timevar_output_tuples,
    rule=def_pro_timevar_output_rule,
    doc='e_pro_out = tau_pro * r_out * eff_factor')
def def_pro_timevar_output_rule(m, tm, stf, sit, pro, com):
    return(m.e_pro_out[tm, stf, sit, pro, com] ==
           m.tau_pro[tm, stf, sit, pro] * m.r_out_dict[(stf, pro, com)] *
           m.eff_factor_dict[(sit, pro)][stf, tm])

Process Constraints for Partial Operation

The process constraints for partial operation described in the following are only activated if in the input file there is a value set in the column ratio-min for an input commodity in the process-commodity sheet for the process in question. Values for output commodities in the ratio_min column do not have any effect.

The partial load feature can only be used for processes that are never meant to be shut down and are always operating only between a given part load state and full load. It is important to understand that this partial load formulation can only work if its accompanied by a non-zero value for the minimum partial load fraction \(\underline{P}_{yvp}\).

Throughput by Min Fraction Rule: This constraint limits the minimal operational state of a process downward, making sure that the minimal part load fraction is honored. The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py this constraint is defined and calculated by the following code fragment:

m.res_throughput_by_capacity_min = pyomo.Constraint(
    m.tm, m.pro_partial_tuples,
    rule=res_throughput_by_capacity_min_rule,
    doc='cap_pro * min-fraction <= tau_pro')
def res_throughput_by_capacity_min_rule(m, tm, stf, sit, pro):
    return (m.tau_pro[tm, stf, sit, pro] >=
            m.cap_pro[stf, sit, pro] *
            m.process_dict['min-fraction'][(stf, sit, pro)] * m.dt)

Partial Process Input Rule: The link between operational state \(\tau_{yvpt}\) and commodity in/outputs is changed from a simple linear behavior to a more complex one. Instead of constant in- and output ratios these are now interpolated linearly between the value for full operation \(r^{\text{in/out}}_{yvp}\) at full load and the minimum in/output ratios \(\underline{r}^{\text{in/out}}_{yvp}\) at the minimum operation point. The mathematical explanation of this rule is given in Minimal Optimization Model.

In script model.py this expression is written in the following way for the input ratio (and analogous for the output ratios):

m.def_partial_process_input = pyomo.Constraint(
    m.tm, m.pro_partial_input_tuples,
    rule=def_partial_process_input_rule,
    doc='e_pro_in = cap_pro * min_fraction * (r - R) / (1 - min_fraction)'
                 '+ tau_pro * (R - min_fraction * r) / (1 - min_fraction)')
def def_partial_process_input_rule(m, tm, stf, sit, pro, coin):
    # input ratio at maximum operation point
    R = m.r_in_dict[(stf, pro, coin)]
    # input ratio at lowest operation point
    r = m.r_in_min_fraction_dict[stf, pro, coin]
    min_fraction = m.process_dict['min-fraction'][(stf, sit, pro)]

    online_factor = min_fraction * (r - R) / (1 - min_fraction)
    throughput_factor = (R - min_fraction * r) / (1 - min_fraction)

    return (m.e_pro_in[tm, stf, sit, pro, coin] ==
            m.dt * m.cap_pro[stf, sit, pro] * online_factor +
            m.tau_pro[tm, stf, sit, pro] * throughput_factor)

In case of a process where also a time variable output efficiency is given the code for the output changes to.

m.def_process_partial_timevar_output = pyomo.Constraint(
    m.tm, m.pro_partial_output_tuples & m.pro_timevar_output_tuples,
    rule=def_pro_partial_timevar_output_rule,
    doc='e_pro_out = tau_pro * r_out * eff_factor')
def def_pro_partial_timevar_output_rule(m, tm, stf, sit, pro, coo):
    # input ratio at maximum operation point
    R = m.r_out_dict[stf, pro, coo]
    # input ratio at lowest operation point
    r = m.r_out_min_fraction_dict[stf, pro, coo]
    min_fraction = m.process_dict['min-fraction'][(stf, sit, pro)]

    online_factor = min_fraction * (r - R) / (1 - min_fraction)
    throughput_factor = (R - min_fraction * r) / (1 - min_fraction)
    return (m.e_pro_out[tm, stf, sit, pro, coo] ==
            (m.dt * m.cap_pro[stf, sit, pro] * online_factor +
             m.tau_pro[tm, stf, sit, pro] * throughput_factor) *
            m.eff_factor_dict[(sit, pro)][(stf, tm)])