diff --git a/component_library/component_models/BaseStorage.py b/component_library/component_models/BaseStorage.py
index 81e292171c8b40d3f1879c1f52440be5f462d78b..9b8388e3b3434feae032b97faa84fca600c24b41 100644
--- a/component_library/component_models/BaseStorage.py
+++ b/component_library/component_models/BaseStorage.py
@@ -229,6 +229,7 @@ class BaseStorage(BaseComponent):
         self._constraint_maxcap(model, var_dict, T)
         self._constraint_conser(model, flows, var_dict, T)
         self._constraint_vdi2067(model, var_dict, T)
+        self._constraint_bidirectional_flows(model, var_dict, T, self.max_size)
         #self._constraint_reopt(model, flows, var_dict, T)
 
     def add_variables(self, input_profiles, plant_parameters, var_dict, flows,
diff --git a/input_files/models/district_models/example_CA/config.csv b/input_files/models/district_models/example_CA/config.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8d15c623466861f434533b792b808cc2d943dd11
--- /dev/null
+++ b/input_files/models/district_models/example_CA/config.csv
@@ -0,0 +1,2 @@
+injection_price,injection_price_variable,injection/pvpeak,gas_price,gas_price_variable,elec_price,elec_price_variable,heat_price,heat_price_variable,cooling_price,cooling_price_variable,injection_price_gas,injection_price_gas_variable,injection_price_heat,injection_price_heat_variable,injection_price_cooling,injection_price_cooling_variable,elec_emission,gas_emission,yearly_interest,planning_horizon
+0.0793,0,0.7,0.0606,0,0.3046,0,0,0,0,0,0,0,0,0,0,0,0.401,0.21,0.03,20
diff --git a/input_files/models/district_models/example_CA/data_path.csv b/input_files/models/district_models/example_CA/data_path.csv
new file mode 100644
index 0000000000000000000000000000000000000000..aa0479f160f0098ef724bba48c299f1cb0ca738d
--- /dev/null
+++ b/input_files/models/district_models/example_CA/data_path.csv
@@ -0,0 +1,5 @@
+type,path,unit
+demand_electric,generate,h
+demand_heat,generate,h
+irradiance,input_files/data/irradiance/Lindenberg2006BSRN_Irradiance_60sec.csv,min
+temperature,input_files/data/temperature/temperature.csv,h
diff --git a/input_files/models/district_models/example_CA/elec_matrix.csv b/input_files/models/district_models/example_CA/elec_matrix.csv
new file mode 100644
index 0000000000000000000000000000000000000000..2ac712600082b9ce6e4524a08bf81d224af2feab
--- /dev/null
+++ b/input_files/models/district_models/example_CA/elec_matrix.csv
@@ -0,0 +1,5 @@
+comp_name,comp_type,model,min_size,max_size,current_size,inv_pv_bat,battery,grd,elec_cns
+inv_pv_bat,Inverter,STP-7000TL-20,0,20,0,0,1,1,1
+battery,LiionBattery,BAT1,0,6,6,1,0,0,0
+grd,StandardACGrid,GRD1,1000,1000,1000,1,0,0,1
+elec_cns,StandardElectricalConsumption,CNS1,1000,1000,0,0,0,0,0
diff --git a/input_files/models/district_models/example_community/config.csv b/input_files/models/district_models/example_community/config.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6d77d4fff831a65e6ae805c2c5f457dca1457eb2
--- /dev/null
+++ b/input_files/models/district_models/example_community/config.csv
@@ -0,0 +1,2 @@
+injection_price,injection_price_variable,injection/pvpeak,gas_price,gas_price_variable,elec_price,elec_price_variable,network_usage_capacity_fee_low,network_usage_energy_fee_low,network_usage_capacity_fee_high,network_usage_energy_fee_high,heat_price,levies_int,levies_ext,concession,electricity_tax_int,electricity_tax_ext,VAT,heat_price_variable,cooling_price,cooling_price_variable,injection_price_gas,injection_price_gas_variable,injection_price_heat,injection_price_heat_variable,injection_price_cooling,injection_price_cooling_variable,elec_emission,gas_emission,yearly_interest,planning_horizon
+0.0793,0,0.7,0.0606,0,0.3046,0,14.79,0.0506,50.54,0.0363,0,0.0276,0.0496,0.0199,0,0.0205,0.190,0,0,0,0,0,0,0,0,0,0.401,0.21,0.03,20
diff --git a/input_files/models/district_models/example_community/data_path.csv b/input_files/models/district_models/example_community/data_path.csv
new file mode 100644
index 0000000000000000000000000000000000000000..e0a77e063aad3d88e2eef7d788cd38527bc3d28a
--- /dev/null
+++ b/input_files/models/district_models/example_community/data_path.csv
@@ -0,0 +1,2 @@
+type,path,unit
+elec_price,input_files/data/prices/day-ahead/hourly_price.csv,h
diff --git a/input_files/models/district_models/example_community/elec_matrix.csv b/input_files/models/district_models/example_community/elec_matrix.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f072d2fea74caf87564656c41c00a5bc1b9b9a79
--- /dev/null
+++ b/input_files/models/district_models/example_community/elec_matrix.csv
@@ -0,0 +1,6 @@
+comp_name,comp_type,model,min_size,max_size,current_size,pv_roof,inv_pv_bat,battery,grd,elec_cns
+pv_roof,StandardPVGenerator,PV2,6,6,6,0,1,0,0,0
+inv_pv_bat,Inverter,STP-7000TL-20,0,20,0,0,0,1,1,1
+battery,LiionBattery,BAT1,6,6,6,0,1,0,0,0
+grd,StandardACGrid,GRD1,1000,1000,1000,0,1,0,0,1
+elec_cns,StandardElectricalConsumption,CNS1,1000,1000,0,0,0,0,0,0
diff --git a/runme_community_new.py b/runme_community_new.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb2fea46b0fe5045dc45597360131f0dde300df5
--- /dev/null
+++ b/runme_community_new.py
@@ -0,0 +1,315 @@
+# runme.py is the central script to execute the optimization of the community.
+
+# Importing the necessary files
+
+import numpy as np
+import Model_Library.District.scripts as scripts
+from datetime import timedelta
+import math
+import time
+import pandas as pd
+import Model_Library.Prosumer.scripts as scripts
+import Model_Library.Prosumer.main as main
+import Model_Library.Prosumer.scripts.extract_inputs as extract_inputs
+from functools import partial
+from multiprocessing import Pool
+from tqdm import tqdm
+import os
+import argparse
+
+from Model_Library.Prosumer.scripts.results_evaluation.results_evaluation import Plot_savings
+
+import Model_Library.Prosumer.main_ca as main_ca
+import Model_Library.District.main_district as main_district
+
+
+def process_each_prosumer(prosumer_name, prosumer_dict, data_source, commentary, no_process_bar_rh):
+    try:
+        # PLEASE CHANGE HERE
+        # Set the simulation time frame and optional rolling horizon configurations:
+        # 't_start': start date of simulations, Unit: JJJJ-MM-DD hh:mm:ss
+        # 't_end': end date of simulations, Unit: JJJJ-MM-DD hh:mm:ss
+        # 't_step': granularity of optimization model, Unit: hours
+        # Rolling horizon (RH) can be set by:
+        # 't_rh_horizon': width of rolling horizon intervals, Unit: hours, MINIMUM VALUE: 2 !!!
+        # 't_rh_shift': rolling horizon shift between intervals, Unit: hours
+        # 't_current_value_length': number of values at beginning of rolling horizon interval that are replaced by real values, Unit: hours
+        # 't_history': number of days before actual simulation interval for the demand generator to be able to make required predictions
+        if prosumer_dict[prosumer_name]['rolling_horizon']:
+            t_start = pd.Timestamp("2019-09-01 00:00:00")
+            t_end = pd.Timestamp("2019-09-01 5:00:00")
+            t_step = 1
+            t_rh_horizon = 3
+            t_rh_shift = 1
+            t_current_value_length = 2
+            t_history = 14  # days
+
+            # PLEASE CHANGE HERE
+            # Prediction settings
+            predictions = {'demand_electric': 'SameHourYesterday',
+                           'demand_heat': 'SameHourYesterday',
+                           'day_ahead_price': 'SameHourYesterday',
+                           'intraday_price': 'SameHourYesterday',
+                           'solar_radiation': 'Perfect',
+                           # currently the method generate_g_t_series takes the same t_start as the prediction -> no historical
+                           # data for the prediction available: easy fix would be to set a minus time delta in the t_start
+                           # argument of generate_g_t_series
+                           'temperature': 'SameHourYesterday'}
+        else:
+            t_start = pd.Timestamp("2019-07-01 00:00:00")
+            t_end = pd.Timestamp("2019-7-10 23:00:00") + pd.Timedelta(hours=1)
+            t_step = 1
+            t_rh_horizon = (t_end - t_start) / pd.Timedelta(hours=1)
+            t_rh_shift = t_rh_horizon - 1
+            t_current_value_length = t_rh_horizon
+            t_history = 0  # days
+
+            # PLEASE CHANGE HERE
+            # Prediction settings
+            predictions = {'demand_electric': 'Perfect',
+                           'demand_heat': 'Perfect',
+                           'day_ahead_price': 'Perfect',
+                           'intraday_price': 'Perfect',
+                           'solar_radiation': 'Perfect',
+                           # currently the method generate_g_t_series takes the same t_start as the prediction -> no historical
+                           # data for the prediction available: easy fix would be to set a minus time delta in the t_start
+                           # argument of generate_g_t_series
+                           'temperature': 'Perfect'}
+
+        # Fixed variables - DO NOT CHANGE
+        storage_states = {}
+        interim_results = {}
+        final_iteration = False
+
+        # Set aggregation options
+        parser = argparse.ArgumentParser(description='Start optimization from DB or local data')
+        parser.add_argument('-a', '--aggregate', action="store_true", dest="aggregate",
+                            help="activating aggregation of input time series", default=False)
+        options = parser.parse_args()
+
+        # Calculate number of rolling horizon intervals and loop through them
+        for t in tqdm(pd.date_range(t_start, t_end - pd.Timedelta(hours=t_rh_shift + 1), freq=str(t_rh_shift) + 'H'), disable=no_process_bar_rh):
+            # ToDo: replace first value with perfect value (can be done in runme)
+            # set end date for current loop
+            t_end_loop = t + pd.Timedelta(hours=t_rh_horizon)
+
+            # exceptions that occur at global end of simulation horizon
+            if t_end_loop > t_end:
+                t_end_loop = t_end
+            if t_current_value_length > (t_end_loop - t) / pd.Timedelta(hours=1):
+                t_current_value_length = (t_end_loop - t) / pd.Timedelta(hours=1)
+
+            # Set flag for final iteration
+            if t == t_end - pd.Timedelta(hours=t_rh_shift + 1):
+                final_iteration = True
+
+            # Start main programme
+            prosumer = main.Main(data_source, {prosumer_name: prosumer_dict[prosumer_name]}, t, t_end_loop, t_step,
+                                 predictions, t_current_value_length, t_end,
+                                 t_history, commentary, storage_states, t_rh_shift, aggregation=options.aggregate)
+
+            # Run optimization
+            prosumer.run_optimization(prosumer.prosumer_name_list)
+
+            # Show results - Results are only plotted after last iteration of rolling horizon
+            prosumer.show_results(prosumer.prosumer_name_list, interim_results, final_iteration)
+
+            # Get storage states from this iteration
+            storage_states = prosumer.charge_status
+
+            # Get interim results of current rolling horizon interval
+            interim_results = prosumer.interim_results
+
+            return prosumer.prosumer[prosumer_name]
+    except ValueError:
+        print(prosumer_name+" could not be optimized!")
+
+# # MAIN PROGRAM -------------------------------------------------------------------------------------------------------
+if __name__ == "__main__":
+    # Initialization scenario path and global variables for the prosumer optimization
+    # Start timer
+    start = time.time()
+
+    # PLEASE CHANGE HERE
+    # Path to local data - this is only used when selecting local mode
+    # 'topology_path': path to matrices that define the prosumer topology
+    # 'config_path': path to global configurations like prices, injection prices, emission costs, etc.
+    #topology_path = 'input_files/models/Study_Base'
+    #config_path = topology_path + '/config.csv'
+    #data_path = topology_path + '/data_path.csv'
+    #prosumer_name = 'office'
+    #prosumer_dict = {prosumer_name: {'topology_path': topology_path, 'config_path': config_path, 'data_path': data_path}}
+    topology_path = ['input_files/models/prosumer_models/SCN0_CAT1']
+    prosumer_name = ['SCN0_CAT1', 'SCN0_CAT1']
+    rolling_horizon = [False]
+    elec_demand = [1500, 10000]
+    therm_demand = [5000, 20000]
+    hot_water_demand = 1500#[1500, 1500]
+    step_elec_demand = 500
+    step_therm_demand = 500
+    #step_hot_water_demand = 0
+    prosumer_dict = {}
+    """    for i in range(len(prosumer_name)):
+        for j in range(elec_demand[0], elec_demand[1], step_elec_demand):
+            for k in range(therm_demand[0], therm_demand[1], step_therm_demand):
+                #for l in range(hot_water_demand[0], hot_water_demand[1], step_hot_water_demand):
+                prosumer_dict[prosumer_name[i]+'_'+str(j)+'_'+str(k)] = {'elec_demand': j,
+                                                                                    'therm_demand': k,
+                                                                                    'hot_water_demand': hot_water_demand,
+                                                                                    'topology_path': topology_path[i],
+                                                                                    'config_path': topology_path[i] + '/config.csv',
+                                                                                    'data_path': topology_path[i] + '/data_path.csv',
+                                                                                    'rolling_horizon': rolling_horizon[i]}"""
+
+    prosumer_dict={'SCN2_CAT1_PV11_3000_6000': {'elec_demand': 3000, 'therm_demand': 6000, 'hot_water_demand': 1500,
+                                                'topology_path': 'input_files/models/prosumer_models/SCN2_CAT1_PV11',
+                                                'config_path': 'input_files/models/prosumer_models/SCN2_CAT1_PV11/config.csv',
+                                                'data_path': 'input_files/models/prosumer_models/SCN2_CAT1_PV11/data_path.csv',
+                                                'rolling_horizon': False},
+                   'SCN2_CAT1_PV12_BA_6000_6000': {'elec_demand': 6000, 'therm_demand': 6000, 'hot_water_demand': 1500,
+                                                   'topology_path': 'input_files/models/prosumer_models/SCN2_CAT1_PV12_BA',
+                                                   'config_path': 'input_files/models/prosumer_models/SCN2_CAT1_PV12_BA/config.csv',
+                                                   'data_path': 'input_files/models/prosumer_models/SCN2_CAT1_PV12_BA/data_path.csv',
+                                                   'rolling_horizon': False},
+                   'SCN0_CAT1_6000_6000': {'elec_demand': 6000, 'therm_demand': 6000, 'hot_water_demand': 1500,
+                                           'topology_path': 'input_files/models/prosumer_models/SCN0_CAT1',
+                                           'config_path': 'input_files/models/prosumer_models/SCN0_CAT1/config.csv',
+                                           'data_path': 'input_files/models/prosumer_models/SCN0_CAT1/data_path.csv',
+                                           'rolling_horizon': False},
+                   'SCN0_CAT1_3000_6000': {'elec_demand': 3000, 'therm_demand': 6000, 'hot_water_demand': 1500,
+                                           'topology_path': 'input_files/models/prosumer_models/SCN0_CAT1',
+                                           'config_path': 'input_files/models/prosumer_models/SCN0_CAT1/config.csv',
+                                           'data_path': 'input_files/models/prosumer_models/SCN0_CAT1/data_path.csv',
+                                           'rolling_horizon': False}}
+    # PLEASE CHANGE HERE
+    # Select data source
+    # Options: '1': import from database, '2': import from local folder
+    data_source = 2
+    reference_results = {}
+    commentary = False
+    no_process_bar_rh = True
+    parallel_processing = False
+
+    # Timer output
+    tic = time.time()
+    # Start program
+    # Run multiple independent prosumers in parallel on multiple cores
+    final_prosumer_dict = dict.fromkeys(prosumer_dict.keys())
+    if parallel_processing:
+        count_processes = len(prosumer_dict.keys())
+        pool = Pool(os.cpu_count())
+        parallel_func = partial(process_each_prosumer, prosumer_dict=prosumer_dict, data_source=data_source, commentary=commentary, no_process_bar_rh=no_process_bar_rh)
+        mapped_values = list(tqdm(pool.map(parallel_func, list(prosumer_dict.keys())), total=count_processes))
+    # Normal processing, one core only
+    else:
+        for prosumer_name in list(prosumer_dict.keys()):
+            final_prosumer_dict[prosumer_name] = process_each_prosumer(prosumer_name= prosumer_name, prosumer_dict=prosumer_dict, data_source=data_source, commentary=commentary, no_process_bar_rh=no_process_bar_rh)
+
+    # Timer output
+    toc = time.time()
+
+    if reference_results:
+        for topology in prosumer_name:
+            Plot_savings(reference_results, topology)
+
+    # Timer output
+    end = time.time()
+    # Additional console output
+    if commentary:
+        print("============ Execution Times =============")
+        print("Pre-processing [s]: \t" + str(tic - start))
+        #print("(Interaction with database [s]:\t" + str(prosumer.connect_with_db) + ")")
+        print("Optimization [s]: \t" + str(toc - tic))
+        print("Post-processing [s]: \t" + str(end - toc))
+        print("----------------------------------------")
+        print("Total [s]: \t" + str((end - toc) + (toc - tic) + (tic - start)))
+        print("==========================================")
+
+'-----------------COMMUNITY-PART----------------------------------'
+start_total = time.time()
+
+data_source = 2  # [1]: datasource from data bank; [2]: datasource from local
+commentary = False
+
+t_start = pd.Timestamp("2019-07-01 00:00:00")
+t_end = pd.Timestamp("2019-07-10 23:00:00") + pd.Timedelta(hours=1)
+t_step = 1
+t_rh_horizon = (t_end - t_start) / pd.Timedelta(hours=1)
+
+t_horizon = (pd.Timestamp(t_end) - pd.Timestamp(t_start)) / np.timedelta64(t_step, 'h')
+
+"------------------------Communnity Asset---------------------------"
+"-------------------------------------------------------------------"
+
+topology_path = 'input_files/models/district_models/example_CA'
+config_path = topology_path + '/config.csv'
+data_path = topology_path + '/data_path.csv'
+ca_dict = {'ca_bat': {'elec_demand': 0,
+                      'therm_demand': 0,
+                      'hot_water_demand': 0,
+                      'topology_path': topology_path,
+                      'config_path': config_path,
+                      'data_path': data_path}}
+#ca_dict = {}
+# PLEASE CHANGE HERE
+# Prediction settings
+predictions = {'demand_electric': 'SameHourYesterday',
+               'demand_heat': 'SameHourYesterday',
+               'day_ahead_price': 'SameHourYesterday',
+               'intraday_price': 'SameHourYesterday',
+               'solar_radiation': 'Perfect',
+               # currently the method generate_g_t_series takes the same t_start as the prediction -> no historical
+               # data for the prediction available: easy fix would be to set a minus time delta in the t_start
+               # argument of generate_g_t_series
+               'temperature': 'SameHourYesterday'}
+
+# Fixed variables - DO NOT CHANGE
+storage_states = {}
+interim_results = {}
+final_iteration = False
+
+ca_strategy = 'sizing_max_operational_profit'
+
+# create time steps list
+time_steps = []
+for t in pd.date_range(pd.Timestamp(t_start),
+                       pd.Timestamp(t_start) + timedelta(hours=t_horizon) - timedelta(hours=t_step),
+                       freq=str(t_step)+'H'):
+    time_steps.append(t)
+
+t_start = pd.Timestamp(t_start)
+t_end = pd.Timestamp(t_start) + timedelta(hours=t_horizon) - timedelta(hours=t_step)
+t_rh_shift = 0
+t_current_value_length = (t_end-t_start)/np.timedelta64(t_step, 'h')
+t_history = t_horizon/24
+
+# initialize community component in the same way prosumers are.
+# The difference is that they are not directly optimized
+comm_assets = main.Main_CA(data_source, ca_dict, t_start, t_end, t_step, predictions, t_current_value_length, t_end,
+                            t_history, commentary, storage_states, t_rh_shift, aggregation=False)
+
+
+"""---------------------------COMMUNITY-LEVEL----------------------"""
+"""----------------------------------------------------------------"""
+
+topology_path = 'input_files/models/district_models/example_community'
+config_path = topology_path + '/config.csv'
+data_path_comm = topology_path + '/data_path.csv'
+comm_dict = {'community': {'topology_path': topology_path, 'config_path': config_path, 'data_path': data_path_comm}}
+comm_strategy = ['max_operational_profit']
+
+community_main = main_district.MainDistrict(final_prosumer_dict,
+                                            comm_assets,
+                                            time_steps,
+                                            t_step,
+                                            comm_dict,
+                                            ca_strategy,
+                                            comm_strategy,
+                                            t_horizon)
+
+# ------------POST-PROCESS-----------------
+
+
+
+
+