CoCalc Public Filesexample_BS.ipynb
Authors: Delinchant Delinchant, Camille Pajot
Views : 85

Example for PV self-consumption

• Import the function needed for this example
In [1]:
from example_utils import *


STEP 1: Create an empty optimization model

In [2]:
model = OptimisationModel(name='example')


STEP 2: Set the time periods

5 minutes time step: dt=1/12 hours

Daily study: periods = 24 hours (24*12 time steps)

In [3]:
time = TimeUnit(periods=24*12, dt=1/12)

You are studying the period from 2018-01-01 00:00:00 to 2018-01-01 23:55:00

STEP 3: Create the household consumption units

• Import the domestic hot water load profile
In [4]:
dhw_load = import_domestic_hot_water_load_profile()

• Import the lothes washing machine and dryer load profiles*
In [5]:
cl_wash_load, cl_dry_load = import_clothes_washer_and_dryer_load_profiles()

• Create the consumption models
• A FixedConsumptionUnit is used for known load profiles
• ShiftableConsumptionUnit are used for load profiles that can be shifted during time.
In [6]:
dhw = FixedConsumptionUnit(time, 'dhw', energy_type='Heat', p=dhw_load)

clothes_washer = ShiftableConsumptionUnit(time, name='clothes_washer',
energy_type='Electrical')

clothes_dryer = ShiftableConsumptionUnit(time, name='clothes_dryer',
energy_type='Electrical')

Creating the dhw. Creating the clothes_washer. Creating the clothes_dryer.

STEP 4: Create the PV panels and the grid imports and exports

• Import the electrical production from PV panels
In [7]:
PV_prod_profile = import_PV_profile_5_min()

• Create the PV production model
In [8]:
PV_prod = FixedProductionUnit(time, name='PV_prod', p=PV_prod_profile)

Creating the PV_prod.
• Create the electrical grid imports as a production
• A VariableProductionUnit is used for unknown production profiles
• Minimal/maximal power of operation can be set with pmin/pmax
• Maximal ramping values (up/down) can be fixed with max_ramp_up/max_ramp_down
• Here, these parameters are free to model an infinite power grid
In [9]:
elec_grid_imports = VariableProductionUnit(time, 'elec_grid_imports',
energy_type='Electrical')

Creating the elec_grid_imports.
• Create the electrical grid exports as a consumption

• A VariableConsumptionUnit is used for unknown consumption profiles
• Here, parameters are free to model an infinite power grid
In [10]:
elec_grid_exports = VariableConsumptionUnit(time, 'elec_grid_exports',
energy_type='Electrical')

Creating the elec_grid_exports.

STEP 5: Avoid importing and exporting at the same time

• Create the ExtDynConstraint which inherits from:
• DynamicConstraint for a time-dependant constraint
• ExternalConstraint for a constraint not expressing a physical law or a variable calculation
• Set the time-dependant expression
• u indicates if the EnergyUnit is operating, so that: unit_1_u(t) + unit_2_u(t) <= 1.5 avoid a simultaneous operation
• t_range expresses the set of index for whom the constraint should be considered
In [11]:
imp_exp = ExtDynConstraint(name='imp_exp',
exp_t='elec_grid_imports_u[t] + '
'elec_grid_exports_u[t] <= 1.5',
t_range='for t in time.I',
parent=elec_grid_imports)

• Add the constraint to the elec_grid_imports model
In [12]:
setattr(elec_grid_imports, 'imp_exp', imp_exp)


STEP 6: Create the water heater and the water tank

• Create the water heater as an ElectricalToHeatConversionUnit with:
• A ratio of conversion from electricty to heat of 90%
• A maximal power for the electricity consumption of 6kW (6000W)
In [13]:
water_heater = ElectricalToHeatConversionUnit(time, 'water_heater',
elec_to_heat_ratio=0.9,
pmax_in_elec=6000)

Creating the water_heater_heat_prod. Creating the water_heater_elec_cons. Creating the water_heater.
• Define the tank capacity of 6kWh (6000Wh)
In [14]:
tank_capacity = 6000

• Define a minimal state of charge for the storage of 20%
In [15]:
SoC_min = 0.2

• Define losses with a self-discharge parameter of 5% per hour
In [16]:
self_disch = 0.05 * time.DT

• Define if the state of charge of the storage has to be regained at the end of the time period (yes)
In [17]:
is_cycling = True

• Create the storage model with StorageUnit
In [18]:
water_tank = StorageUnit(time, 'water_tank', capacity=tank_capacity,
energy_type='Heat', ef_is_e0=is_cycling,
self_disch=self_disch, soc_min=SoC_min)

Creating the water_tank.

STEP 7: Avoid that the dryer starts before the end of the washing machine cycle

• Create the ExtDynConstraint
• Set the time-dependant expression
• The expression avoid that the clothes_dryer starts before that the clothes washer switched off
• start_up indicates if the EnergyUnit is starting
• switch_off indicates if the EnergyUnit
In [19]:
wait_to_dry = ExtDynConstraint(name='wait_to_dry',
exp_t='clothes_dryer_start_up[t] <= '
'lpSum(clothes_washer_switch_off[k] '
'for k in range(0, t))',
t_range='for t in time.I',
parent=clothes_dryer)

• Add the constraint to the dryer model
In [20]:
setattr(clothes_dryer, 'wait_to_dry', wait_to_dry)


STEP 8: Define the objective

• Maximizing the self-consumption means minimizing the imports from the elctrical grid
In [21]:
elec_grid_imports.minimize_production()


STEP 9: Create the energy nodes

• Creating the heat node
In [22]:
heat_node = EnergyNode(time, 'heat__node', energy_type='Heat')

Creating the heat__node.
• Connect the thermal units to the heat node
In [23]:
heat_node.connect_units(dhw, water_tank, water_heater.heat_production_unit)


• Create the electrical node
In [24]:
elec_node = EnergyNode(time, 'elec_node', energy_type='Electrical')


Creating the elec_node.
• Connect the electrical units to the electrical node
In [25]:
elec_node.connect_units(clothes_washer, clothes_dryer, elec_grid_imports,
elec_grid_exports, PV_prod,
water_heater.elec_consumption_unit)


STEP 10: Add the energy nodes to the optimization model

In [26]:
model.add_nodes(elec_node, heat_node)


STEP 11: Launch the optimization

• Write and store the model in the .lp format (can be skipped off-line)
In [27]:
model.writeLP('example.lp')

In [28]:
model.solve_and_update()

- - - - - RUN OPTIMIZATION - - - - - - - - - - UPDATE RESULTS - - - - - Updating unit : elec_node Updating unit : clothes_washer Quantity : p Quantity : e_tot Quantity : u Quantity : start_up Quantity : switch_off Quantity : power_values Updating unit : clothes_dryer Quantity : p Quantity : e_tot Quantity : u Quantity : start_up Quantity : switch_off Quantity : power_values Updating unit : elec_grid_imports Quantity : p Quantity : e_tot Quantity : u Updating unit : elec_grid_exports Quantity : p Quantity : e_tot Quantity : u Updating unit : PV_prod Quantity : p Quantity : e_tot Quantity : u Updating unit : water_heater_elec_cons Quantity : p Quantity : e_tot Quantity : u Updating unit : water_heater Updating unit : water_heater_heat_prod Quantity : p Quantity : e_tot Quantity : u Updating unit : heat__node Updating unit : dhw Quantity : p Quantity : e_tot Quantity : u Updating unit : water_tank Quantity : p Quantity : e_tot Quantity : u Quantity : capacity Quantity : e Quantity : pc Quantity : pd Quantity : uc

STEP 12: Plot the results

In [29]:
plot_node_energetic_flows(heat_node, p_unit='W')
plot_node_energetic_flows(elec_node, p_unit='W')
plt.show()

Preparing to plot the energetic flows through the node heat__node. Add power from dhw. Add power from water_tank. Add power from water_heater_heat_prod. Preparing to plot the energetic flows through the node elec_node. Add power from clothes_washer. Add power from clothes_dryer. Add power from elec_grid_imports. Add power from elec_grid_exports. Add power from PV_prod. Add power from water_heater_elec_cons.
In [ ]: