# 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]
# 
# def get_previous_timestep(timesteps, timestep):
#     """Get the timestamp for the timestep previous to the input timestep"""
#     return timesteps[timesteps.ord(timestep) - 1]


import pyomo.core as po
from calliope.backend.pyomo.util import (
    get_param,
    get_previous_timestep,
)
            backend_model.resource_con[node, tech, timestep] * resource_eff
            == carrier_prod
        )

    # B) Case where storage is allowed
    else:
        resource = backend_model.resource_con[node, tech, timestep] * resource_eff
        # Pyomo returns the order 1-indexed, but we want 0-indexing
        current_timestep = backend_model.timesteps.ord(timestep) - 1
        if current_timestep == 0 and not run_config["cyclic_storage"]:
            storage_previous_step = (
                get_param(backend_model, "storage_initial", (node, tech))
                * backend_model.storage_cap[node, tech]
            )
        elif (
            hasattr(backend_model, "storage_inter_cluster")
            and backend_model.lookup_cluster_first_timestep[timestep]
        ):
            storage_previous_step = 0
        else:
            if (
                hasattr(backend_model, "clusters")
                and backend_model.lookup_cluster_first_timestep[timestep]
            ):
                previous_step = backend_model.lookup_cluster_last_timestep[
                    timestep
                ].value
            elif current_timestep == 0 and run_config["cyclic_storage"]:
                previous_step = backend_model.timesteps[-1]
            else:

# 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]
# 
# def get_previous_timestep(timesteps, timestep):
#     """Get the timestamp for the timestep previous to the input timestep"""
#     return timesteps[timesteps.ord(timestep) - 1]


# Path: calliope/backend/pyomo/constraints/energy_balance.py
import pyomo.core as po
from calliope.backend.pyomo.util import (
    get_param,
    get_previous_timestep,
)

            backend_model.resource_con[node, tech, timestep] * resource_eff
            == carrier_prod
        )

    # B) Case where storage is allowed
    else:
        resource = backend_model.resource_con[node, tech, timestep] * resource_eff
        # Pyomo returns the order 1-indexed, but we want 0-indexing
        current_timestep = backend_model.timesteps.ord(timestep) - 1
        if current_timestep == 0 and not run_config["cyclic_storage"]:
            storage_previous_step = (
                get_param(backend_model, "storage_initial", (node, tech))
                * backend_model.storage_cap[node, tech]
            )
        elif (
            hasattr(backend_model, "storage_inter_cluster")
            and backend_model.lookup_cluster_first_timestep[timestep]
        ):
            storage_previous_step = 0
        else:
            if (
                hasattr(backend_model, "clusters")
                and backend_model.lookup_cluster_first_timestep[timestep]
            ):
                previous_step = backend_model.lookup_cluster_last_timestep[
                    timestep
                ].value
            elif current_timestep == 0 and run_config["cyclic_storage"]:
                previous_step = backend_model.timesteps[-1]
            else:

                previous_step = get_previous_timestep(backend_model.timesteps, timestep)