docs: def pf_post_lopf(network, args, extra_functionality, add_foreign_lopf):
  
      """ Function that prepares and runs non-linar load flow using PyPSA pf. 
      
      If network has been extendable, a second lopf with reactances adapted to
      new s_nom is needed. 
      
      If crossborder lines are DC-links, pf is only applied on german network. 
      Crossborder flows are still considerd due to the active behavior of links.
      To return a network containing the whole grid, the optimised solution of the
      foreign components can be added afterwards. 
  
      Parameters
      ----------
      network : :class:`pypsa.Network
          Overall container of PyPSA
      args: dict
          Contains calculation settings of appl.py   
      extra_fuctionality: function or NoneType
          Adds constraint to optimization (e.g. when applied snapshot clustering)
      add_foreign_lopf: boolean
          Choose if foreign results of lopf should be added to the network when
          foreign lines are DC
  
      Returns
      -------
      pf_solve: pandas.Dataframe
          Contains information about convergency and calculation time of pf
          
      """
      network_pf = network
  
      # Update x of extended lines and transformers
      if network_pf.lines.s_nom_extendable.any() or \
              network_pf.transformers.s_nom_extendable.any():
  
          storages_extendable = network_pf.storage_units.p_nom_extendable.copy()
          lines_extendable = network_pf.lines.s_nom_extendable.copy()
          links_extendable = network_pf.links.p_nom_extendable.copy()
          trafos_extendable = network_pf.transformers.s_nom_extendable.copy()
          
          storages_p_nom =  network_pf.storage_units.p_nom.copy()
          lines_s_nom=  network_pf.lines.s_nom.copy()
          links_p_nom =  network_pf.links.p_nom.copy()
          trafos_s_nom =  network_pf.transformers.s_nom.copy()
          
          network_pf.lines.x[network.lines.s_nom_extendable] = \
              network_pf.lines.x * network.lines.s_nom /\
              network_pf.lines.s_nom_opt
  
          network_pf.lines.r[network.lines.s_nom_extendable] = \
              network_pf.lines.r * network.lines.s_nom /\
              network_pf.lines.s_nom_opt
  
          network_pf.lines.b[network.lines.s_nom_extendable] = \
              network_pf.lines.b * network.lines.s_nom_opt /\
              network_pf.lines.s_nom
  
          network_pf.lines.g[network.lines.s_nom_extendable] = \
              network_pf.lines.g * network.lines.s_nom_opt /\
              network_pf.lines.s_nom
  
          network_pf.transformers.x[network.transformers.s_nom_extendable] = \
              network_pf.transformers.x * network.transformers.s_nom / \
              network_pf.transformers.s_nom_opt
  
          network_pf.lines.s_nom_extendable = False
          network_pf.transformers.s_nom_extendable = False
          network_pf.storage_units.p_nom_extendable = False
          network_pf.links.p_nom_extendable = False
          network_pf.lines.s_nom = network.lines.s_nom_opt
          network_pf.transformers.s_nom = network.transformers.s_nom_opt
          network_pf.storage_units.p_nom = network_pf.storage_units.p_nom_opt
          network_pf.links.p_nom = network_pf.links.p_nom_opt
  
          network_pf.lopf(network.snapshots,
              solver_name=args['solver'],
              solver_options=args['solver_options'],
              extra_functionality=extra_functionality)
          
          network_pf.storage_units.p_nom_extendable = storages_extendable
          network_pf.lines.s_nom_extendable = lines_extendable 
          network_pf.links.p_nom_extendable = links_extendable
          network_pf.transformers.s_nom_extendable = trafos_extendable
          
          network_pf.storage_units.p_nom = storages_p_nom
          network_pf.lines.s_nom = lines_s_nom
          network_pf.links.p_nom = links_p_nom
          network_pf.transformers.s_nom = trafos_s_nom
  
      # For the PF, set the P to the optimised P
      network_pf.generators_t.p_set = network_pf.generators_t.p_set.reindex(
          columns=network_pf.generators.index)
      network_pf.generators_t.p_set = network_pf.generators_t.p
  
      network_pf.storage_units_t.p_set = network_pf.storage_units_t.p_set\
          .reindex(columns=network_pf.storage_units.index)
      network_pf.storage_units_t.p_set = network_pf.storage_units_t.p
  
      network_pf.links_t.p_set = network_pf.links_t.p_set.reindex(
          columns=network_pf.links.index)
      network_pf.links_t.p_set = network_pf.links_t.p0
  
      # if foreign lines are DC, execute pf only on sub_network in Germany
      if (args['foreign_lines']['carrier'] == 'DC') or ((args['scn_extension']!=
         None) and ('BE_NO_NEP 2035' in args['scn_extension'])):
          n_bus = pd.Series(index=network.sub_networks.index)
  
          for i in range(0, len(network.sub_networks.index)-1):
              n_bus[i] = len(network.buses.index[
                      network.buses.sub_network.astype(int) == i])
  
          sub_network_DE = n_bus.index[n_bus == n_bus.max()]
  
          foreign_bus = network.buses[network.buses.sub_network !=
                                      sub_network_DE.values[0]]
  
          foreign_comp = {'Bus': network.buses[
                                      network.buses.sub_network !=
                                      sub_network_DE.values[0]],
                          'Generator': network.generators[
                                  network.generators.bus.isin(
                                          foreign_bus.index)],
                          'Load': network.loads[
                                  network.loads.bus.isin(foreign_bus.index)],
                          'Transformer': network.transformers[
                                  network.transformers.bus0.isin(
                                          foreign_bus.index)],
                          'StorageUnit': network.storage_units[
                                  network.storage_units.bus.isin(
                                          foreign_bus.index)]}
  
          foreign_series = {'Bus': network.buses_t.copy(),
                            'Generator': network.generators_t.copy(),
                            'Load': network.loads_t.copy(),
                            'Transformer':  network.transformers_t.copy(),
                            'StorageUnit': network.storage_units_t.copy()}
  
          for comp in sorted(foreign_series):
              attr = sorted(foreign_series[comp])
              for a in attr:
                  if not foreign_series[comp][a].empty:
                      if a != 'p_max_pu':
                          foreign_series[comp][a] = foreign_series[comp][a][
                                 foreign_comp[comp].index]
  
                      else:
                          foreign_series[comp][a] = foreign_series[comp][a][
                                 foreign_comp[comp][foreign_comp[
                                         comp]['carrier'].isin(
                                                  ['solar', 'wind_onshore',
                                                   'wind_offshore',
                                                   'run_of_river'])].index]
  
          network.buses = network.buses.drop(foreign_bus.index)
          network.generators = network.generators[
                  network.generators.bus.isin(network.buses.index)]
          network.loads = network.loads[
                  network.loads.bus.isin(network.buses.index)]
          network.transformers = network.transformers[
                   network.transformers.bus0.isin(network.buses.index)]
          network.storage_units = network.storage_units[
                  network.storage_units.bus.isin(network.buses.index)]
          
      # Set slack bus
      network = set_slack(network)
  
      # execute non-linear pf
      pf_solution = network_pf.pf(network.snapshots, use_seed=True)
  
      # if selected, copy lopf results of neighboring countries to network
      if ((args['foreign_lines']['carrier'] == 'DC') or ((args['scn_extension']!=
         None) and ('BE_NO_NEP 2035' in args['scn_extension']))) and add_foreign_lopf:
          for comp in sorted(foreign_series):
              network.import_components_from_dataframe(foreign_comp[comp], comp)
  
              for attr in sorted(foreign_series[comp]):
                  network.import_series_from_dataframe(foreign_series
                                                       [comp][attr], comp, attr)
  
      pf_solve = pd.DataFrame(index=pf_solution['converged'].index)
      pf_solve['converged'] = pf_solution['converged'].values
      pf_solve['error'] = pf_solution['error'].values
      pf_solve['n_iter'] = pf_solution['n_iter'].values
  
      if not pf_solve[~pf_solve.converged].count().max() == 0:
          logger.warning("PF of %d snapshots not converged.",
                         pf_solve[~pf_solve.converged].count().max())
  
      return pf_solve