# Path: calliope/backend/pyomo/util.py
# @memoize
# def get_param(backend_model, var, dims):
#     """
#     Get an input parameter held in a Pyomo object, or held in the defaults
#     dictionary if that Pyomo object doesn't exist.
# 
#     Parameters
#     ----------
#     backend_model : Pyomo model instance
#     var : str
#     dims : single value or tuple
# 
#     """
#     try:
#         return getattr(backend_model, var)[dims]
#     except AttributeError:  # i.e. parameter doesn't exist at all
#         logger.debug(
#             "get_param: var {} and dims {} leading to default lookup".format(var, dims)
#         )
#         return backend_model.__calliope_defaults[var]
#     except KeyError:  # try removing timestep
#         try:
#             if len(dims) > 2:
#                 return getattr(backend_model, var)[dims[:-1]]
#             else:
#                 return getattr(backend_model, var)[dims[0]]
#         except KeyError:  # Static default value
#             logger.debug(
#                 "get_param: var {} and dims {} leading to default lookup".format(
#                     var, dims
#                 )
#             )
#             return backend_model.__calliope_defaults[var]
# 
# @memoize
# def get_timestep_weight(backend_model):
#     """
#     Get the total number of years this model considers, by summing all
#     timestep resolution with timestep weight (a weight/resolution of 1 = 1 hour)
#     and divide it by number of hours in the year. Weight/resolution will almost
#     always be 1 per step, unless time clustering/masking/resampling has taken place.
#     """
#     time_res = [po.value(i) for i in backend_model.timestep_resolution.values()]
#     weights = [po.value(i) for i in backend_model.timestep_weights.values()]
#     return sum(np.multiply(time_res, weights)) / 8760
# 
# def loc_tech_is_in(backend_model, loc_tech, model_set):
#     """
#     Check if set exists and if loc_tech is in the set
# 
#     Parameters
#     ----------
#     loc_tech : string
#     model_set : string
#     """
# 
#     if hasattr(backend_model, model_set) and loc_tech in getattr(
#         backend_model, model_set
#     ):
#         return True
#     else:
#         return False


import pyomo.core as po
from calliope.backend.pyomo.util import get_param, get_timestep_weight, loc_tech_is_in

            cost_{cap}(cost, loc::tech) =
            depreciation\\_rate * ts\\_weight *
            (cost_{energy\\_cap}(cost, loc::tech) \\times \\boldsymbol{energy_{cap}}(loc::tech)
            + cost_{storage\\_cap}(cost, loc::tech) \\times \\boldsymbol{storage_{cap}}(loc::tech)
            + cost_{resource\\_cap}(cost, loc::tech) \\times \\boldsymbol{resource_{cap}}(loc::tech)
            + cost_{resource\\_area}(cost, loc::tech)) \\times \\boldsymbol{resource_{area}}(loc::tech)

            depreciation\\_rate =
            \\begin{cases}
                = 1 / plant\\_life,&
                    \\text{if } interest\\_rate = 0\\\\
                = \\frac{interest\\_rate \\times (1 + interest\\_rate)^{plant\\_life}}{(1 + interest\\_rate)^{plant\\_life} - 1},&
                    \\text{if } interest\\_rate \\gt 0\\\\
            \\end{cases}

            ts\\_weight = \\sum_{timestep \\in timesteps} (time\\_res(timestep) \\times weight(timestep)) \\times \\frac{1}{8760}

    """

    def _get_investment_cost(capacity_decision_variable):
        """
        Conditionally add investment costs, if the relevant set of technologies
        exists. Both inputs are strings.
        """
        if loc_tech_is_in(
            backend_model, (node, tech), capacity_decision_variable + "_index"
        ):
            _cost = getattr(backend_model, capacity_decision_variable)[
                node, tech

# Path: calliope/backend/pyomo/util.py
# @memoize
# def get_param(backend_model, var, dims):
#     """
#     Get an input parameter held in a Pyomo object, or held in the defaults
#     dictionary if that Pyomo object doesn't exist.
# 
#     Parameters
#     ----------
#     backend_model : Pyomo model instance
#     var : str
#     dims : single value or tuple
# 
#     """
#     try:
#         return getattr(backend_model, var)[dims]
#     except AttributeError:  # i.e. parameter doesn't exist at all
#         logger.debug(
#             "get_param: var {} and dims {} leading to default lookup".format(var, dims)
#         )
#         return backend_model.__calliope_defaults[var]
#     except KeyError:  # try removing timestep
#         try:
#             if len(dims) > 2:
#                 return getattr(backend_model, var)[dims[:-1]]
#             else:
#                 return getattr(backend_model, var)[dims[0]]
#         except KeyError:  # Static default value
#             logger.debug(
#                 "get_param: var {} and dims {} leading to default lookup".format(
#                     var, dims
#                 )
#             )
#             return backend_model.__calliope_defaults[var]
# 
# @memoize
# def get_timestep_weight(backend_model):
#     """
#     Get the total number of years this model considers, by summing all
#     timestep resolution with timestep weight (a weight/resolution of 1 = 1 hour)
#     and divide it by number of hours in the year. Weight/resolution will almost
#     always be 1 per step, unless time clustering/masking/resampling has taken place.
#     """
#     time_res = [po.value(i) for i in backend_model.timestep_resolution.values()]
#     weights = [po.value(i) for i in backend_model.timestep_weights.values()]
#     return sum(np.multiply(time_res, weights)) / 8760
# 
# def loc_tech_is_in(backend_model, loc_tech, model_set):
#     """
#     Check if set exists and if loc_tech is in the set
# 
#     Parameters
#     ----------
#     loc_tech : string
#     model_set : string
#     """
# 
#     if hasattr(backend_model, model_set) and loc_tech in getattr(
#         backend_model, model_set
#     ):
#         return True
#     else:
#         return False


# Path: calliope/backend/pyomo/constraints/costs.py
import pyomo.core as po
from calliope.backend.pyomo.util import get_param, get_timestep_weight, loc_tech_is_in


            cost_{cap}(cost, loc::tech) =
            depreciation\\_rate * ts\\_weight *
            (cost_{energy\\_cap}(cost, loc::tech) \\times \\boldsymbol{energy_{cap}}(loc::tech)
            + cost_{storage\\_cap}(cost, loc::tech) \\times \\boldsymbol{storage_{cap}}(loc::tech)
            + cost_{resource\\_cap}(cost, loc::tech) \\times \\boldsymbol{resource_{cap}}(loc::tech)
            + cost_{resource\\_area}(cost, loc::tech)) \\times \\boldsymbol{resource_{area}}(loc::tech)

            depreciation\\_rate =
            \\begin{cases}
                = 1 / plant\\_life,&
                    \\text{if } interest\\_rate = 0\\\\
                = \\frac{interest\\_rate \\times (1 + interest\\_rate)^{plant\\_life}}{(1 + interest\\_rate)^{plant\\_life} - 1},&
                    \\text{if } interest\\_rate \\gt 0\\\\
            \\end{cases}

            ts\\_weight = \\sum_{timestep \\in timesteps} (time\\_res(timestep) \\times weight(timestep)) \\times \\frac{1}{8760}

    """

    def _get_investment_cost(capacity_decision_variable):
        """
        Conditionally add investment costs, if the relevant set of technologies
        exists. Both inputs are strings.
        """
        if loc_tech_is_in(
            backend_model, (node, tech), capacity_decision_variable + "_index"
        ):
            _cost = getattr(backend_model, capacity_decision_variable)[
                node, tech

            ] * get_param(