Ejemplo n.º 1
0
def optimal_adapt_level(gross_damages, m, r):
    if value(m.adapt_g1[r]) * value(m.adapt_g2[r]) == 0:
        return 0

    eps = 0.0005
    return (soft_min(gross_damages, 0.01) / (m.adapt_g1[r] * m.adapt_g2[r]) + eps) ** (
        1 / (m.adapt_g2[r] - 1)
    )
Ejemplo n.º 2
0
def var_to_row(rows, m, var, is_regional):
    # If var is a list, second element is the name
    if isinstance(var, list):
        name = var[1]
        var = var[0]
    else:
        name = var.name

    # Check if var is a function or a pyomo variable
    if is_regional:
        fct = lambda t, r: (var(m.year(t), r)
                            if callable(var) else value(var[t, r]))
        for r in m.regions:
            rows.append([name, r] + [fct(t, r) for t in m.t])
    else:
        fct = lambda t: (var(m.year(t)) if callable(var) else value(var[t]))
        rows.append([name, "Global"] + [fct(t) for t in m.t])
Ejemplo n.º 3
0
    def solve(
        self,
        verbose=True,
        halt_on_ampl_error="no",
        use_neos=False,
        neos_email=None,
        ipopt_output_file=None,
    ) -> None:
        """Sends the concrete model to a solver.

        Args:
            verbose (bool, optional): Prints intermediate IPOPT results. Defaults to True.
            halt_on_ampl_error (str, optional): Lets IPOPT stop when invalid values are encountered. Defaults to "no".
            use_neos (bool, optional): Uses the external NEOS server for solving. Defaults to False.
            neos_email (str or None, optional): E-mail address for NEOS server. Defaults to None.
            ipopt_output_file (str or None, optional): Filename for IPOPT intermediate output. Defaults to None.

        Raises:
            SolverException: raised if solver did not exit with status OK
        """

        if use_neos:
            # Send concrete model to external solver on NEOS server
            # Requires authenticated email address
            os.environ["NEOS_EMAIL"] = neos_email
            solver_manager = SolverManagerFactory("neos")
            solver = "ipopt"  # or "conopt'
            results = solver_manager.solve(self.concrete_model, opt=solver)
        else:
            # Solve locally using ipopt
            opt: OptSolver = SolverFactory("ipopt")
            opt.options["halt_on_ampl_error"] = halt_on_ampl_error
            if ipopt_output_file is not None:
                opt.options["output_file"] = ipopt_output_file
            results = opt.solve(self.concrete_model,
                                tee=verbose,
                                symbolic_solver_labels=True)
            if ipopt_output_file is not None:
                visualise_ipopt_output(ipopt_output_file)

        self.postprocessing()

        logger.info("Status: {}".format(results.solver.status))

        if results.solver.status != SolverStatus.ok:
            logger.error("Status: {}, termination condition: {}".format(
                results.solver.status, results.solver.termination_condition))
            if results.solver.status != SolverStatus.warning:
                raise SolverException("Solver did not exit with status OK")

        logger.info("Final NPV: {}".format(
            value(self.concrete_model.NPV[self.concrete_model.tf])))
Ejemplo n.º 4
0
def functional_form(x, m, r, is_slr=False):
    if is_slr:
        form = m.damage_slr_form[r]
        b1, b2, b3 = m.damage_slr_b1[r], m.damage_slr_b2[r], m.damage_slr_b3[r]
        a = m.damage_slr_a[r]
    else:
        form = m.damage_noslr_form[r]
        b1, b2, b3 = m.damage_noslr_b1[r], m.damage_noslr_b2[
            r], m.damage_noslr_b3[r]
        a = m.damage_noslr_a[r]

    # Linear functional form
    if "Linear" in value(form):
        return a * b1 * x / 100.0

    # Quadratic functional form
    if "Quadratic" in value(form):
        return a * (b1 * x + b2 * x**2) / 100.0

    # Logistic functional form
    if "Logistic" in value(form):
        return a * logistic(x, b1, b2, b3) / 100.0

    raise NotImplementedError
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
def get_constraints(m: AbstractModel) -> Sequence[GeneralConstraint]:
    """Economics and Cobb-Douglas equations and constraints

    Necessary variables:
        m.L (equal to m.population)
        m.dk

    Returns:
        list of constraints (any of:
           - GlobalConstraint
           - GlobalInitConstraint
           - RegionalConstraint
           - RegionalInitConstraint
        )
    """
    constraints = []

    m.init_capitalstock_factor = Param(m.regions)
    m.capital_stock = Var(
        m.t,
        m.regions,
        initialize=lambda m, t, r: m.init_capitalstock_factor[r] * m.GDP(
            m.year(t), r),
    )

    # Parameters
    m.alpha = Param()
    m.dk = Param()
    m.sr = Param()

    m.GDP_gross = Var(m.t,
                      m.regions,
                      initialize=lambda m, t, r: m.GDP(m.year(0), r))
    m.GDP_net = Var(m.t, m.regions)
    m.investments = Var(m.t, m.regions)
    m.consumption = Var(m.t, m.regions)

    m.ignore_damages = Param()

    # Cobb-Douglas, GDP, investments, capital and consumption
    constraints.extend([
        RegionalConstraint(
            lambda m, t, r: m.GDP_gross[t, r] == economics.calc_GDP(
                m.TFP(m.year(t), r),
                m.L(m.year(t), r),
                soft_min(m.capital_stock[t, r], scale=10),
                m.alpha,
            ),
            "GDP_gross",
        ),
        RegionalConstraint(
            lambda m, t, r: m.GDP_net[t, r] == m.GDP_gross[t, r] *
            (1 - (m.damage_costs[t, r] if not value(m.ignore_damages) else 0)
             ) - m.abatement_costs[t, r],
            "GDP_net",
        ),
        RegionalConstraint(
            lambda m, t, r: m.investments[t, r] == m.sr * m.GDP_net[t, r],
            "investments",
        ),
        RegionalConstraint(
            lambda m, t, r: m.consumption[t, r] ==
            (1 - m.sr) * m.GDP_net[t, r],
            "consumption",
        ),
        RegionalConstraint(
            lambda m, t, r: (m.capital_stock[t, r] == m.capital_stock[
                t - 1, r] + m.dt * economics.calc_dKdt(m.capital_stock[
                    t, r], m.dk, m.investments[t, r], m.dt))
            if t > 0 else Constraint.Skip,
            "capital_stock",
        ),
        RegionalInitConstraint(lambda m, r: m.capital_stock[
            0, r] == m.init_capitalstock_factor[r] * m.GDP(m.year(0), r)),
    ])

    return constraints