def save(self, directory, parameters='all'):
        """
        Saves results to disk.

        Depending on which results are selected and if they exist, the
        following directories and files are created:

        * `powerflow_results` directory

          * `voltages_pu.csv`

            See :py:attr:`~pfa_v_mag_pu` for more information.
          * `currents.csv`

            See :func:`~i_res` for more information.
          * `active_powers.csv`

            See :py:attr:`~pfa_p` for more information.
          * `reactive_powers.csv`

            See :py:attr:`~pfa_q` for more information.
          * `apparent_powers.csv`

            See :func:`~s_res` for more information.
          * `grid_losses.csv`

            See :py:attr:`~grid_losses` for more information.
          * `hv_mv_exchanges.csv`

            See :py:attr:`~hv_mv_exchanges` for more information.

        * `pypsa_network` directory

          See :py:func:`pypsa.Network.export_to_csv_folder`

        * `grid_expansion_results` directory

          * `grid_expansion_costs.csv`

            See :py:attr:`~grid_expansion_costs` for more information.
          * `equipment_changes.csv`

            See :py:attr:`~equipment_changes` for more information.
          * `unresolved_issues.csv`

            See :py:attr:`~unresolved_issues` for more information.

        * `curtailment_results` directory

          Files depend on curtailment specifications. There will be one file
          for each curtailment specification, that is for every key in
          :py:attr:`~curtailment` dictionary.

        * `storage_integration_results` directory

          * `storages.csv`

            See :func:`~storages` for more information.

        Parameters
        ----------
        directory : :obj:`str`
            Directory to save the results in.
        parameters : :obj:`str` or :obj:`list` of :obj:`str`
            Specifies which results will be saved. By default all results are
            saved. To only save certain results set `parameters` to one of the
            following options or choose several options by providing a list:

            * 'pypsa_network'
            * 'powerflow_results'
            * 'grid_expansion_results'
            * 'curtailment_results'
            * 'storage_integration_results'

        """
        def _save_power_flow_results(target_dir):
            if self.pfa_v_mag_pu is not None:
                # create directory
                os.makedirs(target_dir, exist_ok=True)

                # voltage
                self.pfa_v_mag_pu.to_csv(
                    os.path.join(target_dir, 'voltages_pu.csv'))

                # current
                self.i_res.to_csv(
                    os.path.join(target_dir, 'currents.csv'))

                # active power
                self.pfa_p.to_csv(
                    os.path.join(target_dir, 'active_powers.csv'))

                # reactive power
                self.pfa_q.to_csv(
                    os.path.join(target_dir, 'reactive_powers.csv'))

                # apparent power
                self.s_res().to_csv(
                    os.path.join(target_dir, 'apparent_powers.csv'))

                # grid losses
                self.grid_losses.to_csv(
                    os.path.join(target_dir, 'grid_losses.csv'))

                # grid exchanges
                self.hv_mv_exchanges.to_csv(os.path.join(
                    target_dir, 'hv_mv_exchanges.csv'))

        def _save_pypsa_network(target_dir):
            if self.network.pypsa:
                # create directory
                os.makedirs(target_dir, exist_ok=True)
                self.network.pypsa.export_to_csv_folder(target_dir)

        def _save_grid_expansion_results(target_dir):
            if self.grid_expansion_costs is not None:
                # create directory
                os.makedirs(target_dir, exist_ok=True)

                # grid expansion costs
                self.grid_expansion_costs.to_csv(os.path.join(
                    target_dir, 'grid_expansion_costs.csv'))

                # unresolved issues
                pd.DataFrame(self.unresolved_issues).to_csv(os.path.join(
                    target_dir, 'unresolved_issues.csv'))

                # equipment changes
                self.equipment_changes.to_csv(os.path.join(
                    target_dir, 'equipment_changes.csv'))

        def _save_curtailment_results(target_dir):
            if self.curtailment is not None:
                # create directory
                os.makedirs(target_dir, exist_ok=True)

                for key, curtailment_df in self.curtailment.items():
                    if type(key) == tuple:
                        type_prefix = '-'.join([key[0], str(key[1])])
                    elif type(key) == str:
                        type_prefix = key
                    else:
                        raise KeyError("Unknown key type {} for key {}".format(
                            type(key), key))

                    filename = os.path.join(
                        target_dir, '{}.csv'.format(type_prefix))

                    curtailment_df.to_csv(filename, index_label=type_prefix)

        def _save_storage_integration_results(target_dir):
            storages = self.storages
            if not storages.empty:
                # create directory
                os.makedirs(target_dir, exist_ok=True)

                # general storage information
                storages.to_csv(os.path.join(target_dir, 'storages.csv'))

                # storages time series
                ts_p, ts_q = self.storages_timeseries()
                ts_p.to_csv(os.path.join(
                    target_dir, 'storages_active_power.csv'))
                ts_q.to_csv(os.path.join(
                    target_dir, 'storages_reactive_power.csv'))

                if not self.storages_costs_reduction is None:
                    self.storages_costs_reduction.to_csv(
                        os.path.join(target_dir,
                                     'storages_costs_reduction.csv'))

        # dictionary with function to call to save each parameter
        func_dict = {
            'powerflow_results': _save_power_flow_results,
            'pypsa_network': _save_pypsa_network,
            'grid_expansion_results': _save_grid_expansion_results,
            'curtailment_results': _save_curtailment_results,
            'storage_integration_results': _save_storage_integration_results
        }

        # if string is given convert to list
        if isinstance(parameters, str):
            if parameters == 'all':
                parameters = ['powerflow_results', 'pypsa_network',
                              'grid_expansion_results', 'curtailment_results',
                              'storage_integration_results']
            else:
                parameters = [parameters]

        # save each parameter
        for parameter in parameters:
            try:
                func_dict[parameter](os.path.join(directory, parameter))
            except KeyError:
                message = "Invalid input {} for `parameters` when saving " \
                          "results. Must be any or a list of the following: " \
                          "'pypsa_network', 'powerflow_results', " \
                          "'grid_expansion_results', 'curtailment_results', " \
                          "'storage_integration_results'.".format(parameter)
                logger.error(message)
                raise KeyError(message)
            except:
                raise
        # save measures
        pd.DataFrame(data={'measure': self.measures}).to_csv(
            os.path.join(directory, 'measures.csv'))
        # save configs
        with open(os.path.join(directory, 'configs.csv'), 'w') as f:
            writer = csv.writer(f)
            rows = [
                ['{}'.format(key)] + [value for item in values.items()
                                      for value in item]
                for key, values in self.network.config._data.items()]
            writer.writerows(rows)