Example scenarios

Example scenarios of the co-simulation of the heat pump, hot water tank and controller models are available in the examples folder.

There are cyclic dependencies between the models for each time step, for ex., the hot water tank needing the information from the controller regarding the demands and the water flows, and the controller needing information from the hot water tank regarding the temperature of the water to calculate the flows. mosaik offers two different ways to resolve such cyclic dependencies. The first is the time-shifted resolution, where the information from one model is passed to the other model in the next time step. The second is the same-time-loop resolution, where the information exchange between the models is done in the same time step before progressing the simulation to the next time step. The mosaik documentation describes these two ways of dealing with cyclic dependencies in detail (cyclic-data-flows).

The user can choose between the two types of execution, by specifying the parameter ‘same_time_loop’, while initializing the simulators for each of the models. The default execution mode is the time-shifted resolution. For the same-time-loop resolution, the parameter ‘same_time_loop’ has to be set to ‘True’. Depending on the type of execution, the way the connections between the different models are setup varies, and can be seen in the example scenarios below.

Note

All the simulators must be set to the same type of execution

Time-shifted resolution

The first example scenario uses the time-based resolution of the cyclic dependencies offered by mosaik. The different heat pumps, and calculation modes available in the heat pump model are simulated along with the hot water tank, with the controller model matching both the space heating and domestic hot water demand with the heat available in the hot water tank and controlling the operation of the heat pump.

The simulation is configured as shown below. The inputs/outputs to/from the models are handled by ‘mosaik-csv’.

 5sim_config = {
 6    'CSV': {
 7        'python': 'mosaik_csv:CSV',
 8    },
 9    'CSV_writer': {
10        'python': 'mosaik_csv_writer:CSVWriter'
11    },
12    'HeatPumpSim': {
13        'python': 'mosaik_components.heatpump.Heat_Pump_mosaik:HeatPumpSimulator',
14    },
15    'HotWaterTankSim': {
16        'python': 'mosaik_components.heatpump.hotwatertank.hotwatertank_mosaik:HotWaterTankSimulator',
17    },
18    'ControllerSim': {
19        'python': 'mosaik_components.heatpump.controller.controller_mosaik:ControllerSimulator',
20    },
21}
22
23# The start date, duration, and step size for the simulation
24END = 10 * 60
25START = '01.01.2020 00:00'
26STEP_SIZE = 60 * 1

The parameters and/or initial values for the different models are specified.

28#Parameters for mosaik-heatpump
29params_hp = {'hp_model': 'Air_30kW_1stage',
30             'heat_source': 'Air',
31             'cons_T': 35,
32             'Q_Demand': 19780,
33             'cond_in_T': 30,
34             'heat_source_T': 7,
35             }
36#Parameters for hot water tank model
37params_hwt = {
38    'height': 3600,
39    'volume': 4000,
40    'T_env': 20.0,
41    'htc_walls': 0.28,
42    'htc_layers': 0.897,
43    'n_layers': 6,
44    'n_sensors': 6,
45    'connections': {
46        'sh_in': {'pos': 10},
47        'sh_out': {'pos': 2150},
48        'dhw_in': {'pos': 10},
49        'dhw_out': {'pos': 3400},
50        'hp_in': {'pos': 10},
51        'hp_out': {'pos': 500},
52        },
53    }
54init_vals_hwt = {
55            'layers': {'T': [40.0, 40.0, 40.0, 40.0, 40.0, 40.0]}
56        }
57#Parameters for controller model
58params_ctrl = {
59    'T_hp_sp_h': 50,
60    'T_hp_sp_l': 40,
61    'T_hr_sp_dhw': 40,
62    'T_hr_sp_sh': 35,
63    'dhw_in_T': 10,
64    'sh_dT': 7,
65    'operation_mode': 'heating',
66    'control_strategy': '1'
67}

The different types of heat pumps and calculation modes that are simulated are specified.

28# The different types of heat pumps and calculation modes that are simulated
29model_list = ['Air_30kW_1stage', 'Air_30kW_1stage', 'LW 300(L)', None]
30calc_mode_list = ['detailed', 'fast', 'hplib', 'fixed']
31filename_list = ['detailed', 'fast', 'hplib', 'fixed']

The mosaik ‘world’, and the simulators of the different models are initialized. The inputs required for the different models – domestic hot water demand (DHW Demand); space heating demand (SH Demand); the heat source temperature, which is the ambient air in this case (T_amb); and the temperature of the cold water replacing the domestic hot water supplied from the tank (dhw_in_T) – are available in the ‘scenario_data.csv’ file. The inputs and the outputs are handled by ‘mosaik-csv’ and the output data is saved in csv files.

78    # Initialize the world and the simulators.
79
80    world = mosaik.World(sim_config)
81
82    heatpumpsim = world.start('HeatPumpSim', step_size=STEP_SIZE)
83
84    hwtsim = world.start('HotWaterTankSim', step_size=STEP_SIZE, config=params_hwt)
85
86    ctrlsim = world.start('ControllerSim', step_size=STEP_SIZE)
87
88    heat_load_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'scenario_data.csv')
89    heat_load_sim = world.start('CSV', sim_start=START, datafile=heat_load_file)
90
91    CSV_File = 'Scenario_' + filename_list[i] + '_time_shifted.csv'
92    csv_sim_writer = world.start('CSV_writer', start_date='01.01.2020 00:00', date_format='%d.%m.%Y %H:%M',
93                                 output_file=CSV_File)

The specific parameters for the different heat pump models and calculation modes are added to the parameters.

 95    params_hp['calc_mode'] = calc_mode_list[i]
 96    params_hp['hp_model'] = model_list[i]
 97
 98    if 'hplib' in params_hp['calc_mode']:
 99        params_hp['equivalent_hp_model'] = 'Air_30kW_1stage'
100    elif 'fixed' in params_hp['calc_mode']:
101        params_hp['COP'] = 3.5
102        params_hp['heating capacity'] = 15000
103        params_hp['cond_m'] = 0.5

The different models are instantiated.

105    # Instantiate the models
106    heatpumps = heatpumpsim.HeatPump.create(1, params=params_hp)
107
108    hwts = hwtsim.HotWaterTank.create(1, params=params_hwt, init_vals=init_vals_hwt)
109
110    ctrls = ctrlsim.Controller.create(1, params=params_ctrl)
111
112    heat_load = heat_load_sim.HEATLOAD.create(1)
113
114    csv_writer = csv_sim_writer.CSVWriter(buff_size=60 * 60)

The cyclic data flows between the different models are then set up in the time-shifted manner and the simulation is executed.

116    # connections between the different models
117    world.connect(heat_load[0], ctrls[0], 'T_amb', ('T_amb', 'heat_source_T'), ('SH Demand [kW]', 'sh_demand'),
118                  ('DHW Demand [L]', 'dhw_demand'), 'dhw_in_T')
119
120    world.connect(hwts[0], ctrls[0], ('T_mean', 'T_mean_hwt'), ('mass', 'hwt_mass'),
121                  ('sensor_00.T', 'bottom_layer_T'), ('sensor_04.T', 'top_layer_T'),
122                  ('dhw_out.T', 'dhw_out_T'), ('sh_out.T', 'sh_out_T'), ('hp_out.T', 'hp_out_T'))
123
124    world.connect(ctrls[0], hwts[0], ('sh_in_F', 'sh_in.F'), ('sh_in_T', 'sh_in.T'), ('sh_out_F', 'sh_out.F'),
125                  ('dhw_in_F', 'dhw_in.F'), ('dhw_in_T', 'dhw_in.T'), ('dhw_out_F', 'dhw_out.F'), ('T_amb', 'T_env'),
126                  time_shifted=True,
127                  initial_data={'sh_in_F': 0, 'sh_in_T': 0, 'sh_out_F': 0,
128                                'dhw_in_F': 0, 'dhw_in_T': 0, 'dhw_out_F': 0,
129                                'T_amb': 0,
130                                },
131                  )
132
133    world.connect(heatpumps[0], ctrls[0], ('Q_Supplied', 'hp_supply'), ('on_fraction', 'hp_on_fraction'),
134                  ('cond_m', 'hp_cond_m'))
135
136    world.connect(ctrls[0], heatpumps[0], ('hp_demand', 'Q_Demand'),
137                  'T_amb', 'heat_source_T', time_shifted=True,
138                  initial_data={'hp_demand': 0, 'T_amb': 5, 'heat_source_T': 5})
139
140    world.connect(hwts[0], heatpumps[0], ('hp_out.T', 'cond_in_T'))
141
142    world.connect(heatpumps[0], hwts[0], ('cons_T', 'hp_in.T'), ('cond_m', 'hp_in.F'), ('cond_m_neg', 'hp_out.F'),
143                  time_shifted=True, initial_data={'cons_T': 0, 'cond_m': 0, 'cond_m_neg': 0})
144
145    world.connect(heat_load[0], csv_writer, 'T_amb', 'SH Demand [kW]', 'DHW Demand [L]')
146    world.connect(heatpumps[0], csv_writer, 'Q_Demand', 'Q_Supplied', 'T_amb', 'heat_source_T', 'cons_T', 'P_Required',
147                  'COP', 'cond_m', 'cond_in_T', 'on_fraction')
148
149    world.connect(ctrls[0], csv_writer, 'heat_demand', 'heat_supply', 'hp_demand', 'sh_supply', 'sh_demand', 'hp_supply',
150                  'sh_in_F', 'sh_in_T', 'sh_out_F', 'sh_out_T', 'dhw_in_F', 'dhw_in_T', 'dhw_out_F', 'dhw_out_T',
151                  'hp_in_F', 'hp_in_T', 'hp_out_F', 'hp_out_T', 'P_hr_sh', 'P_hr_dhw', 'dhw_demand', 'dhw_supply')
152    world.connect(hwts[0], csv_writer, 'sensor_00.T', 'sensor_01.T', 'sensor_02.T', 'sensor_03.T', 'sensor_04.T',
153                  'sensor_05.T', 'sh_out.T', 'sh_out.F', 'dhw_out.T', 'dhw_out.F', 'hp_in.T', 'hp_in.F', 'hp_out.T', 'hp_out.F',
154                  'T_mean', 'sh_in.T', 'sh_in.F', 'dhw_in.T', 'dhw_in.F')
155
156    #Run
157    world.run(until=END)

Same-time-loop resolution

The second example scenario uses the event-based resolution of the same-time-loop cycles offered by mosaik. Only the things that need to be changed when compared to the time-based resolution are shown below.

While initializing the model simulators, the ‘same_time_loop’ parameter has to be set to ‘True’ for all the models.

82    heatpumpsim = world.start('HeatPumpSim', step_size=STEP_SIZE, same_time_loop=True)
83
84    hwtsim = world.start('HotWaterTankSim', step_size=STEP_SIZE, config=params_hwt, same_time_loop=True)
85
86    ctrlsim = world.start('ControllerSim', step_size=STEP_SIZE, same_time_loop=True)

The cyclic data flows between the different models are then set up in the same-time-loop manner.

116    # connections between the different models
117    world.connect(heat_load[0], ctrls[0], 'T_amb', ('T_amb', 'heat_source_T'), ('SH Demand [kW]', 'sh_demand'),
118                  ('DHW Demand [L]', 'dhw_demand'), 'dhw_in_T')
119
120    world.connect(hwts[0], ctrls[0], ('T_mean', 'T_mean_hwt'), ('mass', 'hwt_mass'),
121                  ('sensor_00.T', 'bottom_layer_T'), ('sensor_04.T', 'top_layer_T'),
122                  ('dhw_out.T', 'dhw_out_T'), ('sh_out.T', 'sh_out_T'),
123                  ('hp_out.T', 'hp_out_T'))
124
125    world.connect(ctrls[0], hwts[0], ('sh_in_F', 'sh_in.F'), ('sh_in_T', 'sh_in.T'), ('sh_out_F', 'sh_out.F'),
126                  ('dhw_in_F', 'dhw_in.F'), ('dhw_in_T', 'dhw_in.T'), ('dhw_out_F', 'dhw_out.F'), ('T_amb_hwt', 'T_env'),
127                  ('hp_in_T', 'hp_in.T'), ('hp_in_F', 'hp_in.F'), ('hp_out_F', 'hp_out.F'), weak=True)
128
129    world.connect(heatpumps[0], ctrls[0], ('Q_Supplied', 'hp_supply'), ('on_fraction', 'hp_on_fraction'),
130                  ('cond_m', 'hp_in_F'), ('cond_m_neg', 'hp_out_F'), ('cons_T', 'hp_in_T'), weak=True)
131
132    world.connect(ctrls[0], heatpumps[0], ('hp_demand', 'Q_Demand'), ('hp_out_T', 'cond_in_T'),
133                  'T_amb', 'heat_source_T')
134
135
136    world.connect(heat_load[0], csv_writer, 'T_amb', 'SH Demand [kW]', 'DHW Demand [L]')
137    world.connect(heatpumps[0], csv_writer, 'Q_Demand', 'Q_Supplied', 'T_amb', 'heat_source_T', 'cons_T', 'P_Required',
138                  'COP', 'cond_m', 'cond_in_T', 'on_fraction')
139
140    world.connect(ctrls[0], csv_writer, 'heat_demand', 'heat_supply', 'hp_demand', 'sh_supply', 'sh_demand', 'hp_supply',
141                  'sh_in_F', 'sh_in_T', 'sh_out_F', 'sh_out_T','dhw_in_F', 'dhw_in_T', 'dhw_out_F', 'dhw_out_T',
142                  'hp_in_F', 'hp_in_T', 'hp_out_F', 'hp_out_T',  'P_hr_sh', 'P_hr_dhw', 'dhw_demand', 'dhw_supply')
143    world.connect(hwts[0], csv_writer, 'sensor_00.T', 'sensor_01.T', 'sensor_02.T','sensor_03.T', 'sensor_04.T', 'sensor_05.T',
144                  'sh_out.T', 'sh_out.F', 'dhw_out.T', 'dhw_out.F', 'hp_in.T', 'hp_in.F', 'hp_out.T', 'hp_out.F',
145                  'T_mean', 'sh_in.T', 'sh_in.F', 'dhw_in.T', 'dhw_in.F')

For the same-time-loop execution, it is important to set the initial event that kick-starts the simulation, which is the simulation of the hot water tank for this scenario. The simulation is then executed.

147    # To start hwts as first simulator
148    world.set_initial_event(hwts[0].sid)
149
150    #Run
151    world.run(until=END)