Rooftop constraint

This notebook incorporates a roof area constraint: The total area of all the converters occupying roof area must be less than the total area available on the roof.

[ ]:
from pyehub.energy_hub.ehub_model import EHubModel
from pyehub.energy_hub.utils import constraint
from pyehub.outputter import pretty_print

from pylp import RealVariable
  • Specify the available roof area.
  • Inherit the EHubModel class to build a custom model.
  • Specify the Roof-Area constraint in this new model:
    • precede the roof-area constraint function by @constraint() decorator. [This is how the model recognizes a constraint]
    • make roof_area_per_unit_capacity, which is a dictionary containing the area occupied by roof-cnverters per unit capacity of the tech.
    • calculate total_roof_area occupied by all roof-converters by summing up products of roof_area_per_unit_capacity and capacities ranging for all roof-converters.
    • Impose the Roof-Area constraint.
[ ]:
MAX_ROOF_AREA = 80  # available roof area


class RoofModel(EHubModel):
    """
    This is a subclass of EHubModel with roof constraints.
    """

    @constraint()
    def roof_tech_area_below_max(self):
        """ Ensure the roof techs are taking up less area than there is roof.
        """
        # The following dictionary contains the 'area [m2] per unit capacity [kWp]'
        roof_area_per_unit_capacity = {"PV": 40, "ST": 5}

        # multiply roof-area-per-unit-capacity by the capacity for all listed technologies and sum
        total_roof_area = sum(
            (self.capacities[tech_name]) * (roof_area_per_unit_capacity[tech_name])
            for tech_name in roof_area_per_unit_capacity
        )

        # return the constraint that this variable <= available area
        return total_roof_area <= MAX_ROOF_AREA

Now we load and run a model.

[ ]:
excel_file = "test_file_all_constraints_work.xlsx"  # name of the excel file. [This must be in the current directory]
my_model = RoofModel(
    excel=excel_file
)  # instantiate our model. Nothing is solved at this point.
results = my_model.solve()  # solve the model and get back our results
pretty_print(results)  # print the results to the console

Tracking the roof area

To keep track of the roof area used we build a tracking constraint that will track the area. Then add an additional constraint to contrain the tracking constraint.

By adding a variable to track the roof area it will be stored in the output file.

[ ]:
MAX_ROOF_AREA = 80  # available roof area


class RoofModel(EHubModel):
    """
    This is a subclass of EHubModel with roof constraints.
    """

    def __init__(
        self, *, excel=None, request=None, max_carbon=0, MAX_ROOF_AREA=MAX_ROOF_AREA
    ):
        super().__init__(excel=excel, request=request)
        self.MAX_ROOF_AREA = MAX_ROOF_AREA
        # The following dictionary contains the 'area [m2] per unit capacity [kWp]'
        self.area_per_capacity = {"PV": 40, "ST": 5}

    def _add_variables(self):
        super()._add_variables()
        self.total_roof_area = RealVariable()

    # This will track the amount of are used
    @constraint()
    def roof_tech_area_definition(self):
        """
        Ensure the roof techs are taking up less area than there is roof.
        """

        # multiply area-per-unit-capacity and capacity for all roof-techs and sum all of them
        total_roof_area = sum(
            (self.capacities[tech_name]) * (self.area_per_capacity[tech_name])
            for tech_name in self.area_per_capacity
        )

        return self.total_roof_area == total_roof_area

    # This will constrain the area used.
    @constraint()
    def roof_tech_area_below_max(self):
        """ Ensure the roof techs are taking up less area than there is roof.
        """

        # return the constraint that this variable <= available area
        return self.total_roof_area <= self.MAX_ROOF_AREA
[ ]:
excel_file = "test_file_all_constraints_work.xlsx"  # name of the excel file. [This must be in the current directory]
my_model = RoofModel(
    excel=excel_file
)  # instantiate our model. Nothing is solved at this point.
results = my_model.solve()  # solve the model and get back our results
pretty_print(results)  # print the results to the console
[ ]: