def _extra_global_constraint(variable_name, interp_data: InterpolatingData, eps): return [ GlobalConstraint( lambda m, t: getattr(m, variable_name)[t] - interp_data.get( "Global", m.year(t)) <= eps # if t > 0 # and m.year(t) <= interp_data.maxyear # else Constraint.Skip ), GlobalConstraint( lambda m, t: getattr(m, variable_name)[t] - interp_data.get( "Global", m.year(t)) >= -eps # if t > 0 # and m.year(t) <= interp_data.maxyear # else Constraint.Skip ), ]
def get_constraints( m: AbstractModel) -> Tuple[Objective, Sequence[GeneralConstraint]]: """Equations and constraints for the objective of the optimisation (utility specification) Necessary variables: - Returns: - Objective - list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ constraints = [] m.NPV = Var(m.t) m.PRTP = Param() constraints.extend([ GlobalConstraint( lambda m, t: m.NPV[t] == m.NPV[t - 1] + m.dt * exp(-m.PRTP * ( m.year(t) - m.beginyear)) * sum( m.L(m.year(t), r) * m.utility[t, r] for r in m.regions) if t > 0 else Constraint.Skip, name="NPV", ), GlobalInitConstraint(lambda m: m.NPV[0] == 0), ]) ## If carbon budget is a soft constraint (not in use now): # m.obj = Objective(rule=lambda m: m.NPV[m.tf] * ( # soft_switch(m.budget-( # m.cumulative_emissions[m.year2100] # + sum(soft_min(m.global_emissions[t]) for t in m.t if m.year(t) >= 2100) # ), scale=1) # ), sense=maximize) objective = Objective(rule=lambda m: m.NPV[m.tf], sense=maximize) return objective, constraints
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]: """Utility and welfare equations Necessary variables: m.utility m.welfare Returns: list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ constraints = [] # Parameters m.elasmu = Param() m.inequal_aversion = Param() m.utility = Var(m.t, m.regions, initialize=10) m.yearly_welfare = Var(m.t) constraints.extend([ RegionalConstraint( lambda m, t, r: m.utility[t, r] == m.consumption[t, r] / m.L( m.year(t), r), "utility", ), GlobalConstraint( lambda m, t: m.yearly_welfare[t] == sum( m.L(m.year(t), r) for r in m.regions) * calc_utility( sum(m.consumption[t, r] for r in m.regions), sum(m.L(m.year(t), r) for r in m.regions), m.elasmu, ), "yearly_welfare", ), ]) return constraints
def get_constraints( m: AbstractModel) -> Tuple[Objective, Sequence[GeneralConstraint]]: """Equations and constraints for the objective of the optimisation (global costs specification) Necessary variables: Returns: - Objective - list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ constraints = [] m.NPV = Var(m.t) m.PRTP = Param() constraints.extend([ GlobalConstraint( lambda m, t: m.NPV[t] == m.NPV[t - 1] + m.dt * exp(-m.PRTP * ( m.year(t) - m.beginyear)) * (sum(m.abatement_costs[t, r] for r in m.regions) + sum( m.damage_costs[t, r] * m.GDP_gross[t, r] for r in m.regions)) if t > 0 else Constraint.Skip, name="NPV", ), GlobalInitConstraint(lambda m: m.NPV[0] == 0), ]) objective = Objective(rule=lambda m: m.NPV[m.tf], sense=minimize) return objective, constraints
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]: """Emissions and temperature equations and constraints Necessary variables: m.relative_abatement m.cumulative_emissions m.T0 m.temperature Returns: list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ constraints = [] m.regional_emissions = Var(m.t, m.regions) m.baseline = Var(m.t, m.regions) m.baseline_carbon_intensity = Param() m.relative_abatement = Var(m.t, m.regions, initialize=0, bounds=(0, 2)) m.cumulative_emissions = Var(m.t) m.global_emissions = Var(m.t) constraints.extend([ # Baseline emissions based on emissions or carbon intensity RegionalConstraint( lambda m, t, r: (m.baseline[t, r] == m.carbon_intensity( m.year(t), r) * m.GDP_net[t, r]) if value(m.baseline_carbon_intensity) else (m.baseline[t, r] == m.baseline_emissions(m.year(t), r)), name="baseline_emissions", ), # Regional emissions from baseline and relative abatement RegionalConstraint( lambda m, t, r: m.regional_emissions[t, r] == (1 - m.relative_abatement[t, r]) * m.baseline_emissions( m.year(t), r), "regional_abatement", ), RegionalInitConstraint(lambda m, r: m.regional_emissions[0, r] == m. baseline_emissions(m.year(0), r)), # Global emissions (sum from regional emissions) GlobalConstraint( lambda m, t: m.global_emissions[t] == sum( m.regional_emissions[t, r] for r in m.regions), "global_emissions", ), GlobalInitConstraint( lambda m: m.global_emissions[0] == sum( m.baseline_emissions(m.year(0), r) for r in m.regions), "global_emissions_init", ), # Cumulative global emissions GlobalConstraint( lambda m, t: m.cumulative_emissions[t] == m.cumulative_emissions[ t - 1] + m.dt * m.global_emissions[t] if t > 0 else Constraint.Skip, "cumulative_emissions", ), GlobalInitConstraint(lambda m: m.cumulative_emissions[0] == 0), ]) m.T0 = Param() m.temperature = Var(m.t, initialize=lambda m, t: m.T0) m.TCRE = Param() m.temperature_target = Param() constraints.extend([ GlobalConstraint( lambda m, t: m.temperature[t] == m.T0 + m.TCRE * m. cumulative_emissions[t], "temperature", ), GlobalInitConstraint(lambda m: m.temperature[0] == m.T0), GlobalConstraint( lambda m, t: m.temperature[t] <= m.temperature_target if (m.year(t) >= 2100 and value(m.temperature_target) is not False) else Constraint.Skip, name="temperature_target", ), ]) m.perc_reversible_damages = Param() # m.overshoot = Var(m.t, initialize=0) # m.overshootdot = DerivativeVar(m.overshoot, wrt=m.t) # m.netnegative_emissions = Var(m.t) # global_constraints.extend( # [ # lambda m, t: m.netnegative_emissions[t] # == m.global_emissions[t] * (1 - tanh(m.global_emissions[t] * 10)) / 2 # if value(m.perc_reversible_damages) < 1 # else Constraint.Skip, # lambda m, t: m.overshootdot[t] # == (m.netnegative_emissions[t] if t <= value(m.year2100) and t > 0 else 0) # if value(m.perc_reversible_damages) < 1 # else Constraint.Skip, # ] # ) # global_constraints_init.extend([lambda m: m.overshoot[0] == 0]) # Emission constraints m.budget = Param() m.inertia_global = Param() m.inertia_regional = Param() m.global_min_level = Param() m.regional_min_level = Param() m.no_pos_emissions_after_budget_year = Param() constraints.extend([ # Carbon budget constraints: GlobalConstraint( lambda m, t: m.cumulative_emissions[t] - (m.budget + (m.overshoot[t] * (1 - m.perc_reversible_damages) if value(m.perc_reversible_damages) < 1 else 0)) <= 0 if (m.year(t) >= 2100 and value(m.budget) is not False ) else Constraint.Skip, name="carbon_budget", ), GlobalConstraint( lambda m, t: m.global_emissions[t] <= 0 if (m.year(t) >= 2100 and value(m.no_pos_emissions_after_budget_year) is True and value(m.budget) is not False) else Constraint.Skip, name="net_zero_after_2100", ), GlobalConstraint(lambda m, t: m.cumulative_emissions[t] >= 0), # Global and regional inertia constraints: GlobalConstraint( lambda m, t: m.global_emissions[t] - m.global_emissions[t - 1] >= m .dt * m.inertia_global * sum( m.baseline_emissions(m.year(0), r) for r in m.regions) if value(m.inertia_global ) is not False and t > 0 else Constraint.Skip, name="global_inertia", ), RegionalConstraint( lambda m, t, r: m.regional_emissions[t, r] - m.regional_emissions[ t - 1, r] >= m.dt * m.inertia_regional * m.baseline_emissions( m.year(0), r) if value(m.inertia_regional) is not False and t > 0 else Constraint.Skip, name="regional_inertia", ), GlobalConstraint( lambda m, t: m.global_emissions[t] >= m.global_min_level if value(m.global_min_level) is not False else Constraint.Skip, "global_min_level", ), RegionalConstraint( lambda m, t, r: m.regional_emissions[t, r] >= m.regional_min_level if value(m.regional_min_level) is not False else Constraint.Skip, "regional_min_level", ), ]) m.emission_relative_cumulative = Var(m.t, initialize=1) constraints.extend([ GlobalConstraint( lambda m, t: (m.emission_relative_cumulative[t] == m.cumulative_emissions[t] / m .baseline_cumulative_global(m, m.year(0), m.year(t))) if t > 0 else Constraint.Skip, name="relative_cumulative_emissions", ), GlobalInitConstraint(lambda m: m.emission_relative_cumulative[0] == 1), ]) return constraints
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]: """Damage and adaptation costs equations and constraints (RICE specification) Necessary variables: m.damage_costs (sum of residual damages and adaptation costs, as % of GDP) Returns: list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ constraints = [] m.damage_costs = Var(m.t, m.regions) m.smoothed_factor = Var(m.t, bounds=(0, 1)) m.gross_damages = Var(m.t, m.regions) m.resid_damages = Var(m.t, m.regions) m.adapt_costs = Var(m.t, m.regions) m.adapt_level = Var(m.t, m.regions, bounds=(0, 1)) m.damage_a1 = Param(m.regions) m.damage_a2 = Param(m.regions) m.damage_a3 = Param(m.regions) m.damage_scale_factor = Param() m.adapt_g1 = Param(m.regions) m.adapt_g2 = Param(m.regions) m.adapt_curr_level = Param() m.fixed_adaptation = Param() constraints.extend( [ # Smoothing factor for partially reversible damages GlobalConstraint( lambda m, t: m.smoothed_factor[t] == smoothed_factor(t, m.temperature, m.dt, m.perc_reversible_damages), name="smoothed_factor", ), # Gross damages RegionalConstraint( lambda m, t, r: m.gross_damages[t, r] == calc_gross_damages(m, t, r, m.perc_reversible_damages), name="gross_damages", ), RegionalConstraint(lambda m, t, r: m.gross_damages[t, r] >= 0), RegionalInitConstraint(lambda m, r: m.gross_damages[0, r] == 0), ] ) # Adaptation constraints.extend( [ RegionalConstraint( lambda m, t, r: m.adapt_level[t, r] == ( m.adapt_curr_level if value(m.fixed_adaptation) else optimal_adapt_level(m.gross_damages[t, r], m, r) ), name="adapt_level", ), RegionalConstraint( lambda m, t, r: m.resid_damages[t, r] == m.gross_damages[t, r] * (1 - m.adapt_level[t, r]), "resid_damages", ), RegionalConstraint( lambda m, t, r: m.adapt_costs[t, r] == adaptation_costs(m.adapt_level[t, r], m, r), "adapt_costs", ), RegionalConstraint( lambda m, t, r: m.damage_costs[t, r] == m.resid_damages[t, r] + m.adapt_costs[t, r], "damage_costs", ), ] ) return constraints
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]: """Abatement cost equations and constraints Necessary variables: m.abatement_costs Returns: list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ constraints = [] ### Technological learning # Learning by doing m.LBD_rate = Param() m.log_LBD_rate = Param(initialize=log(m.LBD_rate) / log(2)) m.LBD_scaling = Param() m.LBD_factor = Var(m.t) # , bounds=(0,1), initialize=1) constraints.append( GlobalConstraint( lambda m, t: m.LBD_factor[t] == soft_min( ( m.baseline_cumulative_global(m, m.year(0), m.year(t)) - m.cumulative_emissions[t] ) / m.LBD_scaling + 1.0 ) ** m.log_LBD_rate, name="LBD", ) ) # Learning over time and total learning factor m.LOT_rate = Param() m.LOT_factor = Var(m.t) m.learning_factor = Var(m.t) constraints.extend( [ GlobalConstraint( lambda m, t: m.LOT_factor[t] == 1 / (1 + m.LOT_rate) ** t, "LOT" ), GlobalConstraint( lambda m, t: m.learning_factor[t] == (m.LBD_factor[t] * m.LOT_factor[t]), "learning", ), ] ) # Abatement costs and MAC m.abatement_costs = Var(m.t, m.regions, within=NonNegativeReals, initialize=0) m.area_under_MAC = Var(m.t, m.regions, within=NonNegativeReals, initialize=0) m.rel_abatement_costs = Var(m.t, m.regions, bounds=(0, 0.3)) m.MAC_gamma = Param() m.MAC_beta = Param() m.MAC_scaling_factor = Param(m.regions) # Regional scaling of the MAC m.carbonprice = Var(m.t, m.regions, bounds=lambda m: (0, 1.5 * m.MAC_gamma)) constraints.extend( [ RegionalConstraint( lambda m, t, r: ( m.area_under_MAC[t, r] if value(m.allow_trade) else m.abatement_costs[t, r] ) == AC( m.relative_abatement[t, r], m.learning_factor[t], m.MAC_gamma, m.MAC_beta, m.MAC_scaling_factor[r], ) * m.baseline[t, r], "abatement_costs", ), RegionalConstraint( lambda m, t, r: m.rel_abatement_costs[t, r] == m.abatement_costs[t, r] / m.GDP_gross[t, r], "rel_abatement_costs", ), RegionalConstraint( lambda m, t, r: m.carbonprice[t, r] == MAC( m.relative_abatement[t, r], m.learning_factor[t], m.MAC_gamma, m.MAC_beta, m.MAC_scaling_factor[r], ), "carbonprice", ), RegionalInitConstraint( lambda m, r: m.carbonprice[0, r] == 0, "init_carbon_price" ), ] ) # How are mitigation costs distributed over regions? m.allow_trade = Param() constraints.extend( [ GlobalConstraint( lambda m, t: sum(m.abatement_costs[t, r] for r in m.regions) == sum(m.area_under_MAC[t, r] for r in m.regions) if m.allow_trade else Constraint.Skip ), RegionalConstraint( lambda m, t, r: m.abatement_costs[t, r] <= 1.5 * m.area_under_MAC[t, r] if m.allow_trade else Constraint.Skip ), # RegionalConstraint( # lambda m, t, r: m.abatement_costs[t, r] >= 0.5 * m.area_under_MAC[t, r] # if m.allow_trade # else Constraint.Skip # ), ] ) # Keep track of relative global costs m.global_rel_abatement_costs = Var(m.t) constraints.extend( [ GlobalConstraint( lambda m, t: m.global_rel_abatement_costs[t] == sum(m.abatement_costs[t, r] for r in m.regions) / sum(m.GDP_gross[t, r] for r in m.regions), "global_rel_abatement_costs", ) ] ) return constraints
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]: """Emissions and temperature equations and constraints Necessary variables: m.total_SLR Returns: list of constraints (any of: - GlobalConstraint - GlobalInitConstraint - RegionalConstraint - RegionalInitConstraint ) """ # Parameters and variables necessary for sea level rise m.slr_thermal = Var(m.t) m.slr_thermal_equil = Param() m.slr_thermal_init = Param() m.slr_thermal_adjust_rate = Param() m.slr_cumgsic = Var(m.t) m.slr_gsic_melt_rate = Param() m.slr_gsic_total_ice = Param() m.slr_gsic_equil_temp = Param() m.slr_cumgis = Var(m.t) m.slr_gis_melt_rate_above_thresh = Param() m.slr_gis_init_melt_rate = Param() m.slr_gis_init_ice_vol = Param() m.total_SLR = Var(m.t) # Constraints relating to SLR constraints = [ # Thermal expansion GlobalConstraint( lambda m, t: m.slr_thermal[t] == slr_thermal_expansion( m.slr_thermal[t - 1], m.temperature[t - 1], m) if t > 0 else Constraint.Skip, name="SLR_thermal", ), GlobalInitConstraint(lambda m: m.slr_thermal[ 0] == m.slr_thermal_init + m.slr_thermal_adjust_rate * ( m.T0 * m.slr_thermal_equil - m.slr_thermal_init)), # GSIC GlobalConstraint( lambda m, t: m.slr_cumgsic[t] == slr_gsic(m.slr_cumgsic[ t - 1], m.temperature[t - 1], m) if t > 0 else Constraint.Skip, name="SLR_GSIC", ), GlobalInitConstraint(lambda m: m.slr_cumgsic[0] == 0.015), # GIS GlobalConstraint( lambda m, t: m.slr_cumgis[t] == slr_gis(m.slr_cumgis[ t - 1], m.temperature[t - 1], m) if t > 0 else Constraint.Skip, name="SLR_GIS", ), GlobalInitConstraint(lambda m: m.slr_cumgis[0] == 0.006), # Total SLR is sum of each contributing factors GlobalConstraint( lambda m, t: m.total_SLR[t] == m.slr_thermal[t] + m.slr_cumgsic[t] + m.slr_cumgis[t], name="total_SLR", ), ] return constraints