### Full Multi-Energy Network Setup and Simulation Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/multienergienetze.ipynb A comprehensive example demonstrating the setup of a multi-energy network, including loading example power and gas networks, configuring fluids, creating conversion elements, defining controllers, and running the simulation. ```python import pandapipes as ppipes import pandapower as ppower from pandapipes import networks as g_nw from pandapower import networks as e_nw from pandapipes.multinet.create_multinet import create_empty_multinet, add_net_to_multinet from pandapipes.multinet.control.controller.multinet_control import P2GControlMultiEnergy, G2PControlMultiEnergy from pandapipes.multinet.control.run_control_multinet import run_control # get networks: net_power = e_nw.example_simple() net_gas = g_nw.gas_meshed_square() # some adjustments: net_gas.junction.pn_bar = net_gas.ext_grid.p_bar = 30 net_gas.pipe.diameter_m = 0.4 net_gas.controller.rename(columns={'controller': 'object'}, inplace=True) # due to new version # set fluid: fluid = {'name':'hydrogen', 'cal_value':38.4} ppipes.create_fluid_from_lib(net_gas, fluid['name'], overwrite=True) # create multinet and add networks: multinet = create_empty_multinet('tutorial_multinet') add_net_to_multinet(multinet, net_power, 'power') add_net_to_multinet(multinet, net_gas, 'gas') # create elements corresponding to conversion units: p2g_id_el = ppower.create_load(net_power, bus=3, p_mw=2, name="power to gas consumption") p2g_id_gas = ppipes.create_source(net_gas, junction=1, mdot_kg_per_s=0, name="power to gas feed in") g2p_id_gas = ppipes.create_sink(net_gas, junction=1, mdot_kg_per_s=0.1, name="gas to power consumption") g2p_id_el = ppower.create_sgen(net_power, bus=5, p_mw=0, name="fuel cell feed in") # create coupling controllers: p2g_ctrl = P2GControlMultiEnergy(multinet, p2g_id_el, p2g_id_gas, efficiency=0.7, name_power_net="power", name_gas_net="gas") g2p_ctrl = G2PControlMultiEnergy(multinet, g2p_id_el, g2p_id_gas, efficiency=0.65, name_power_net="power", name_gas_net="gas") # run simulation: run_control(multinet) ``` -------------------------------- ### Setup and Simulate Coupled Power-Gas Networks Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/coupled_nets_h2_p2g2p.ipynb This comprehensive example sets up two distinct networks (power and gas), defines conversion units (P2G and G2P), creates coupling controllers, and runs the simulation for the multinet. ```python import pandapipes as ppipes import pandapower as ppower from pandapipes import networks as g_nw from pandapower import networks as e_nw from pandapipes.multinet.create_multinet import create_empty_multinet, add_net_to_multinet from pandapipes.multinet.control.controller.multinet_control import P2GControlMultiEnergy, G2PControlMultiEnergy from pandapipes.multinet.control.run_control_multinet import run_control # get networks: net_power = e_nw.example_simple() net_gas = g_nw.gas_meshed_square() # some adjustments: net_gas.junction.pn_bar = net_gas.ext_grid.p_bar = 30 net_gas.pipe.diameter_m = 0.4 net_gas.controller.rename(columns={'controller': 'object'}, inplace=True) # due to new version # set fluid: ppipes.create_fluid_from_lib(net_gas, 'hydrogen', overwrite=True) # create multinet and add networks: multinet = create_empty_multinet('tutorial_multinet') add_net_to_multinet(multinet, net_power, 'power') add_net_to_multinet(multinet, net_gas, 'gas') # create elements corresponding to conversion units: p2g_id_el = ppower.create_load(net_power, bus=3, p_mw=2, name="power to gas consumption") p2g_id_gas = ppipes.create_source(net_gas, junction=1, mdot_kg_per_s=0, name="power to gas feed in") g2p_id_gas = ppipes.create_sink(net_gas, junction=1, mdot_kg_per_s=0.1, name="gas to power consumption") g2p_id_el = ppower.create_sgen(net_power, bus=5, p_mw=0, name="fuel cell feed in") # create coupling controllers: p2g_ctrl = P2GControlMultiEnergy(multinet, p2g_id_el, p2g_id_gas, efficiency=0.7, name_power_net="power", name_gas_net="gas") g2p_ctrl = G2PControlMultiEnergy(multinet, g2p_id_el, g2p_id_gas, efficiency=0.65, name_power_net="power", name_gas_net="gas") # run simulation: run_control(multinet) ``` -------------------------------- ### Import Example Networks and Set Gas Properties Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/coupled_nets_h2_p2g2p.ipynb Imports example power and gas networks and sets specific properties like pressure and pipe diameter. It also sets the fluid for the gas network to hydrogen. ```python from pandapower import networks as e_nw net_power = e_nw.example_simple() import pandapipes as ppipes from pandapipes import networks as g_nw net_gas = g_nw.gas_meshed_square() # some adjustments: net_gas.junction.pn_bar = net_gas.ext_grid.p_bar = 30 net_gas.pipe.diameter_m = 0.4 # set fluid: ppipes.create_fluid_from_lib(net_gas, 'hydrogen', overwrite=True) ``` -------------------------------- ### Initialize Network and Import Libraries Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/multiple_pumps_flow_in_a_circular_district_heating_grid.ipynb Initializes an empty pandapipes network for water and imports necessary libraries. This is the starting point for network modeling. ```python import pandapipes as pp import numpy as np # create empty net net = pp.create_empty_network(fluid ="water") ``` -------------------------------- ### Selective and Aggregated Logging Examples Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/output_writer_tutorial.ipynb Provides examples of selective and aggregated logging. The first logs a single element, while the second aggregates results using a provided function. These techniques help manage output file size and focus on specific data points. ```python ow.log_variable("res_junction", "p_bar", index=[0]) # single element ``` ```python ow.log_variable("res_pipe", "v_mean_m_per_s", eval_function=pd.max) # aggregate ``` -------------------------------- ### Create and Simulate a Simple Network Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/simple_plot.ipynb This code creates a basic pandapipes network with various elements and then runs a pipe flow calculation. It requires the pandapipes library to be installed. ```python import pandapipes as pp # create an empty network net = pp.create_empty_network(fluid="lgas") # create network elements, such as junctions, external grid, pipes, valves, sinks and sources junction1 = pp.create_junction(net, pn_bar=1.05, tfluid_k=293.15, name="Connection to External Grid", geodata=(0, 0)) junction2 = pp.create_junction(net, pn_bar=1.05, tfluid_k=293.15, name="Junction 2", geodata=(2, 0)) junction3 = pp.create_junction(net, pn_bar=1.05, tfluid_k=293.15, name="Junction 3", geodata=(7, 4)) junction4 = pp.create_junction(net, pn_bar=1.05, tfluid_k=293.15, name="Junction 4", geodata=(7, -4)) junction5 = pp.create_junction(net, pn_bar=1.05, tfluid_k=293.15, name="Junction 5", geodata=(5, 3)) junction6 = pp.create_junction(net, pn_bar=1.05, tfluid_k=293.15, name="Junction 6", geodata=(5, -3)) ext_grid = pp.create_ext_grid(net, junction=junction1, p_bar=1.1, t_k=293.15, name="Grid Connection") pipe1 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=10, inner_diameter_mm=300, name="Pipe 1", geodata=[(0, 0), (2, 0)]) pipe2 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=2, inner_diameter_mm=300, name="Pipe 2", geodata=[(2, 0), (2, 4), (7, 4)]) pipe3 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction4, length_km=2.5, inner_diameter_mm=300, name="Pipe 3", geodata=[(2, 0), (2, -4), (7, -4)]) pipe4 = pp.create_pipe_from_parameters(net, from_junction=junction3, to_junction=junction5, length_km=1, inner_diameter_mm=300, name="Pipe 4", geodata=[(7, 4), (7, 3), (5, 3)]) pipe5 = pp.create_pipe_from_parameters(net, from_junction=junction4, to_junction=junction6, length_km=1, inner_diameter_mm=300, name="Pipe 5", geodata=[(7, -4), (7, -3), (5, -3)]) valve = pp.create_valve(net, junction=junction5, element=junction6, et='ju', inner_diameter_mm=50, opened=True) sink = pp.create_sink(net, junction=junction4, mdot_kg_per_s=0.545, name="Sink 1") source = pp.create_source(net, junction=junction3, mdot_kg_per_s=0.234) pp.pipeflow(net) ``` -------------------------------- ### Create Pump from Standard Type Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/standard_libraries.ipynb Installs a pump in the network using a standard type, where the pressure difference is determined by the underlying pump curve. ```python P1 = pp.create_pump(net, from_junction=junction1, to_junction=junction2, std_type="P1") ``` -------------------------------- ### Get Data from Standard Library Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/standard_libraries.ipynb Use 'get_data' to display all entries in a library file. Specify the path to the library CSV and the component type. ```python import os from pandapipes.std_types.std_type_class import get_data from pandapipes import pp_dir path = os.path.join(pp_dir, 'std_types/library/Pipe.csv') print(get_data(path, 'pipe')) ``` -------------------------------- ### Print Controllers in Multi-Energy Networks Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/multienergienetze.ipynb Prints the controllers associated with the multi-network, the power network, and the gas network. This helps in verifying the setup of coupling controllers. ```python print(multinet.controller) print(net_power.controller) print(net_gas.controller) ``` -------------------------------- ### Get log file path Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Retrieves the configured log file path after logging has been set up. ```python Result: 'C:\\Users\\carl\\.oemof\\log_files\\dhnx.log' ``` -------------------------------- ### Import necessary libraries for DHNx and Pandapipes Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Imports essential libraries for network design, optimization, and simulation, including logging, CoolProp, matplotlib, networkx, numpy, osmnx, pandas, pandapipes, shapely, and DHNx modules. Ensure these libraries are installed. ```python import logging import math from CoolProp.CoolProp import PropsSI import matplotlib.pyplot as plt import networkx as nx import numpy as np from oemof.tools import logger import osmnx as ox import pandas as pd import pandapipes as pp from shapely import geometry from dhnx.network import ThermalNetwork from dhnx.input_output import load_invest_options from dhnx.gistools.connect_points import process_geometry from dhnx.optimization.precalc_hydraulic import v_max_bisection, calc_mass_flow, calc_power, calc_pipe_loss ``` -------------------------------- ### Set Up Time Series Simulation Parameters Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/time_series_in_a_circular_district_heating_grid.ipynb Define time steps and create profiles for supply temperature and heat demand. The supply temperature is converted to Kelvin. Heat demand percentages are used to calculate time-dependent qext. ```python start = 0 end = 10 # 8760 hours in a year # time steps with start and end time_steps = np.arange(start, end, 1) # time steps in hours supply_temperature_profile_k = np.array([90, 85, 80, 75, 75, 75, 75, 80, 85, 95]) + 273.15 # Define percentage profiles for each consumer (shape: [n_timesteps, n_consumers]) heat_demand_percentages = np.array([ [1.0, 0.8, 1.2], # t=0 [0.9, 0.7, 1.1], # t=1 [0.8, 0.6, 1.0], # t=2 [0.7, 0.5, 0.9], # t=3 [0.6, 0.4, 0.8], # t=4 [0.7, 0.5, 0.9], # t=5 [0.8, 0.6, 1.0], # t=6 [0.9, 0.7, 1.1], # t=7 [1.0, 0.8, 1.2], # t=8 [1.0, 0.8, 1.2], # t=9 ]) # Calculate time-dependent qext for each consumer qext_profile = qext_w * heat_demand_percentages # shape: (n_timesteps, n_consumers) print(f"Time dependant heat demand profile for the three consumers: \n {qext_profile}") ``` -------------------------------- ### Initialize Network and Storage Controller Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/building_a_storage_controller.ipynb Loads a meshed square gas network, initializes a mass storage unit, and creates a StorageController to manage it using time-series data. ```python from pandapipes.networks import gas_meshed_square import pandapipes as pp import pandas as pd from pandapipes.timeseries import ts # loading the network net = gas_meshed_square() pp.pipeflow(net) # creating a simple time series framedata = pd.DataFrame([0.1, .05, -0.1, .005, -0.2, 0], columns=['mdot_storage']) datasource = ts.DFData(framedata) # creating storage unit in the grid, which will be controlled by our controller store_mass = pp.create_mass_storage(net, junction=3, mdot_kg_per_s=0, init_m_stored_kg=2, min_m_stored_kg=0, max_m_stored_kg=500, type="classical mass storage") # creating an Object of our new build storage controller, controlling the storage unit ctrl = StorageController(net=net, sid=store_mass, data_source=datasource, mdot_profile='mdot_storage') ``` -------------------------------- ### Get Junction Index Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/creating_a_simple_network.ipynb Retrieves the index of a created junction. The returned index can be used to reference the junction in other network elements. ```python junction1 ``` -------------------------------- ### Configure Optimisation Solver Settings Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Sets up the configuration dictionary for the optimisation solver. Options include specifying the solver, printing solver output, and adjusting solver-specific command-line options like allowable gap or maximum runtime. ```python settings = dict(solver='cbc', solve_kw={ 'tee': True, # print solver output }, solver_cmdline_options={ # 'allowableGap': 1e-5, # (absolute gap) default: 1e-10 # 'ratioGap': 0.2, # (0.2 = 20% gap) default: 0 # 'seconds': 60 * 1, # (maximum runtime) default: 1e+100 }, # bidirectional_pipes=True, ) ``` -------------------------------- ### Optimization Initialization Output Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Logs indicating the initialization and creation of the energy system model, including appending nodes and building the operational model. ```log 15:10:36-INFO-Initialize the energy system 15:10:36-INFO-Create oemof objects 15:10:36-INFO-Producers, Consumers Nodes appended. 15:10:36-INFO-DHS Nodes appended. 15:10:36-INFO-Energysystem has been created 15:10:36-INFO-Build the operational model ``` -------------------------------- ### Load Network Data Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/simple_time_series_example.ipynb Loads a predefined pandapipes network. This function is used to get the base network structure for the time series simulation. ```python from pandapipes import networks net = networks.simple_gas_networks.gas_meshed_delta() ``` -------------------------------- ### Create and Initialize P2G and G2P Controllers Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/multienergienetze.ipynb Instantiate P2GControlMultiEnergy and G2PControlMultiEnergy controllers, linking them to the previously created network elements. These controllers act as the coupling points between the networks. ```python from pandapipes.multinet.control.controller.multinet_control import P2GControlMultiEnergy, \ G2PControlMultiEnergy p2g_ctrl = P2GControlMultiEnergy(multinet, p2g_id_el, p2g_id_gas, efficiency=0.7, name_power_net="power", name_gas_net="gas") g2p_ctrl = G2PControlMultiEnergy(multinet, g2p_id_el, g2p_id_gas, efficiency=0.65, name_power_net="power", name_gas_net="gas") ``` -------------------------------- ### Initialize Network and Set Fluid Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/circular_flow_in_a_district_heating_grid.ipynb Imports the pandapipes package and creates an empty network container, specifying 'water' as the working fluid. ```python import pandapipes as pp # create empty net net = pp.create_empty_network(fluid ="water") ``` -------------------------------- ### Create a basic P2G coupling controller Source: https://github.com/e2niee/pandapipes/blob/develop/doc/source/multi_energy_nets/coupling_controllers.md Instantiates a P2GControlMultiEnergy controller to link a power network load to a gas network source. Ensure both networks and their respective elements are pre-defined. ```python >>> p2g_id_el = pandapower.create_load(net_power, bus=3, p_mw=2) >>> p2g_id_gas = ppipes.create_source(net_gas, junction=1, mdot_kg_per_s=0) >>> p2g_ctrl = P2GControlMultiEnergy(multinet, p2g_id_el, p2g_id_gas, efficiency=0.7) ``` -------------------------------- ### Checkout Develop Branch Source: https://github.com/e2niee/pandapipes/blob/develop/CONTRIBUTING.rst Switch to the develop branch on your local machine. ```bash git checkout develop ``` -------------------------------- ### Run pandapipes Tests Locally Source: https://github.com/e2niee/pandapipes/blob/develop/CONTRIBUTING.rst Execute the pandapipes test suite locally to ensure your changes do not introduce regressions. This requires the pandapipes library to be installed. ```python from pandapipes.test.run_tests import run_tests run_tests() ``` -------------------------------- ### Initialize Multinetwork and Add Power and Gas Nets Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/coupled_nets_h2_p2g2p.ipynb Sets up the initial pandapower and pandapipes networks and combines them into a multinetwork structure. This is a prerequisite for defining coupled controllers and running simulations. ```python import pandapower as ppower import pandapipes as ppipes from pandapipes.multinet import create_empty_multinet, add_net_to_multinet # prepare just like before net_power = ppower.example_simple() net_gas = ppipes.gas_meshed_square() net_gas.junction.pn_bar = net_gas.ext_grid.p_bar = 30 net_gas.pipe.diameter_m = 0.4 net_gas.controller.rename(columns={'controller': 'object'}, inplace=True) # due to new version ppipes.create_fluid_from_lib(net_gas, 'hydrogen', overwrite=True) multinet = create_empty_multinet('tutorial_multinet') add_net_to_multinet(multinet, net_power, 'power_net') add_net_to_multinet(multinet, net_gas, 'gas_net') ``` -------------------------------- ### Get Internal Pipe Results Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/temperature_calculation.ipynb Access the detailed internal results for specific pipes, including initial pressure, velocity, and temperature. Specify the pipe index to retrieve its results. ```python pipe_1_results = Pipe.get_internal_results(net, [0]) ``` -------------------------------- ### Create and Configure Fluid Container Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/standard_libraries.ipynb Use this to create a fluid container and add properties such as density, viscosity, and heat capacity. Ensure the necessary property constants are defined beforehand. ```python water_const = fl.Fluid("water_const","liquid") water_const.add_property(property_name="density",prop=density_const) water_const.add_property(property_name="viscosity",prop=viscosity_const) water_const.add_property(property_name="heat_capacity",prop= heat_capacity_const) ``` -------------------------------- ### Get Fluid Property at Specific Temperature Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/standard_libraries.ipynb Retrieves a specific fluid property, such as density, at a given temperature using the 'get_property' method of the fluid object within the network container. ```python net.fluid.get_property("density", 295) ``` -------------------------------- ### Create Pipes from Parameters Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/creating_a_simple_network.ipynb Adds multiple pipe elements to the network, connecting specified junctions. Each pipe is defined by its start and end junctions, length, inner diameter, and an optional name. ```python pipe1 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=10, inner_diameter_mm=300, name="Pipe 1") pipe2 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=2, inner_diameter_mm=300, name="Pipe 2") pipe3 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction4, length_km=2.5, inner_diameter_mm=300, name="Pipe 3") pipe4 = pp.create_pipe_from_parameters(net, from_junction=junction3, to_junction=junction5, length_km=1, inner_diameter_mm=300, name="Pipe 4") pipe5 = pp.create_pipe_from_parameters(net, from_junction=junction4, to_junction=junction6, length_km=1, inner_diameter_mm=300, name="Pipe 5") ``` -------------------------------- ### Display Source Table Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/creating_a_simple_network.ipynb Shows the source table after creation. ```python net.source ``` -------------------------------- ### Define Function to Get DN and Costs Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Combines the functionality of `get_dn_apply` and `get_real_costs` into a single function `get_dn_and_costs`. This function first determines the DN number for each pipe and then calculates the associated real costs. ```python def get_dn_and_costs(df, table): df = get_dn_apply(df, table) df = get_real_costs(df, table) return df ``` -------------------------------- ### Configure logging for DHNx Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Sets up logging for DHNx to record information to both the console and a log file. The log file path is returned. ```python logger.define_logging( screen_level=logging.INFO, logfile="dhnx.log" ) ``` -------------------------------- ### Define Network Constants and Parameters Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/time_series_in_a_circular_district_heating_grid.ipynb Sets up constants for heat demand, temperatures, pipe types, and pump characteristics. Temperatures are converted to Kelvin. ```python # define constants qext_w = np.array([100000, 80000, 120000]) return_temperature_k = np.array([60,55,65]) + 273.15 supply_temperature_k = 85 + 273.15 pipetype = "ISOPLUS_DRE100_STD" k = 0.1 flow_pressure_pump = 4 lift_pressure_pump = 1.5 mass_pump_mass_flow = 0.5 ``` -------------------------------- ### Extract Time Series Simulation Results Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/time_series_in_a_circular_district_heating_grid.ipynb Access the simulation results stored in the OutputWriter object to analyze time-dependent values. This example shows how to extract supply temperature and mass flow at the main pump. ```python # Extract time series results from OutputWriter results = ow.output # Supply temperature at "Pump Supply" pump_supply_idx = net.junction[net.junction['name'] == "Pump Supply"].index[0] supply_temp = results['res_junction.t_k'][pump_supply_idx] # Mass flow at main pump (first and only pump) mass_flow_pump = results['res_circ_pump_pressure.mdot_from_kg_per_s'][pump_supply_idx] print("Supply temperature at 'Pump Supply' over time:") print(supply_temp) print("\nMass flow at main pump over time:") print(mass_flow_pump) ``` -------------------------------- ### Prepare for Time Series Visualization Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/time_series_in_a_circular_district_heating_grid.ipynb Load the simulation results from the OutputWriter and extract the time steps to be used as the x-axis for plotting. This prepares the data for visualizing temperatures, pressures, and heat extraction over time. ```python import matplotlib.pyplot as plt import numpy as np # Load results from OutputWriter results = ow.output # The time axis corresponds to the DataFrame index (time steps) time_steps = results['res_junction.t_k'].index ``` -------------------------------- ### Get Pump Data from Standard Library Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/standard_libraries.ipynb Retrieves data for a specific pump type from its library file using the 'get_data' function. This helps in understanding pump characteristics like pressure raise and flow rate. ```python path = os.path.join(pp_dir, 'std_types/library/Pump/P1.csv') print(get_data(path, 'pump')) ``` -------------------------------- ### Retrieve and Plot Internal Pipe Results Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/circular_flow_in_a_district_heating_grid.ipynb Gets and visualizes the detailed results (pressure, velocity, temperature) at the internal nodes of a specific pipe. This allows for a granular analysis of how these parameters change along the pipe length. ```python from pandapipes.component_models import Pipe pipe_results = Pipe.get_internal_results(net, [0]) ``` ```python Pipe.plot_pipe(net, 0, pipe_results) ``` -------------------------------- ### Access Networks from Multinet Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/coupled_nets_h2_p2g2p.ipynb Demonstrates how to access individual networks (power and gas) from the created multinetwork using their assigned names. This confirms that the networks are correctly stored. ```python print(multinet.nets['power']) print(multinet.nets['gas']) ``` ```python print(net_power) print(net_gas) ``` ```python print(net_power is multinet.nets['power']) print(net_gas is multinet.nets['gas']) ``` -------------------------------- ### Define Function to Get DN Loss Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Defines a function `get_dn_loss` that calculates the energy loss for each pipe based on its length and the power loss associated with its DN number. It joins the power loss data from the pipe table to the pipe DataFrame. ```python def get_dn_loss(df, table): table.rename(columns={"DN number": "DN"}, inplace=True) df = df.join(table[['DN', 'P_loss [kW]']].set_index('DN'), on='DN') df['DN_loss [kW]'] = df['P_loss [kW]'] * df['length'] return df ``` -------------------------------- ### Define Function to Get DN Number Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Defines a function `get_dn` that determines the appropriate DN (Diameter Nominal) number for a given pipe capacity based on a provided table of pipe data. It handles cases where the capacity exceeds the maximum available pipe size. ```python def get_dn(capa, table): if capa > 0.01: if capa > table["P_max [kW]"].max(): index = table.sort_values(by=["P_max [kW]"], ascending=False).index[0] dn = table.loc[index, "Bezeichnung [DN]"] print('Maximum heat demand exceeds capacity of biggest pipe! The ' 'biggest pipe type is selected.') else: index = table[table["P_max [kW]"] >= capa].sort_values( by=["P_max [kW]"]).index[0] dn = table.loc[index, "DN number"] else: dn = 0 return dn ``` -------------------------------- ### Create Input DataFrame for Optimization Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Creates a pandas DataFrame with techno-economic parameters for district heating pipelines, suitable for DHNx optimization. ```python df_pipes = pd.DataFrame( { "label_3": "your-pipe-type-label", "active": 1, "nonconvex": 1, "l_factor": constants_loss[0], "l_factor_fix": constants_loss[1], "cap_max": df_pipe_data['P_max [kW]'].max(), "cap_min": df_pipe_data['P_max [kW]'].min(), "capex_pipes": constants_costs[0], "fix_costs": constants_costs[1], }, index=[0], ) ``` -------------------------------- ### Create an empty network Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/height_difference_example.ipynb Initialize an empty network container, specifying the fluid type for the simulation. ```python net = pp.create_empty_network(fluid="water") # create an empty network ``` -------------------------------- ### Run Time Series Simulation with OutputWriter Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/building_a_storage_controller.ipynb Sets up an OutputWriter to log specific variables during the time-series simulation and then executes the simulation. ```python from pandapipes.timeseries import run_timeseries # defining an OutputWriter to track certain variables log_variables = [("mass_storage", "mdot_kg_per_s"), ("res_mass_storage", "mdot_kg_per_s"), ("mass_storage", "m_stored_kg")] ow = ts.OutputWriter(net, log_variables=log_variables) # starting time series simulation run_timeseries(net, time_steps=range(0, 6)) ``` -------------------------------- ### Build a minimal pandapipes network Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/output_writer_tutorial.ipynb Creates a simple two-junction water network with an external grid, a pipe, and a sink. Includes a static run to verify model consistency and prints results. ```python # Create empty network with water as the working fluid net = pp.create_empty_network(fluid="water") # Junctions j0 = pp.create_junction(net, pn_bar=3.0, tfluid_k=293.15, height_m=0.0, name="Junction 0") j1 = pp.create_junction(net, pn_bar=3.0, tfluid_k=293.15, height_m=0.0, name="Junction 1") # External grid (supply) at j0 eg = pp.create_ext_grid(net, junction=j0, p_bar=3.0, t_k=293.15, name="Ext Grid") # Pipe from j0 -> j1 pipe = pp.create_pipe_from_parameters( net, from_junction=j0, to_junction=j1, length_km=0.3, diameter_m=0.15, k_mm=0.2, sections=1, name="Pipe 0" ) # A sink at j1 (initial value; this will be overwritten by the time series controller) sink = pp.create_sink(net, junction=j1, mdot_kg_per_s=0.30, name="Sink 0") # Quick static run to verify model consistency pp.pipeflow(net) # Show static results print("res_junction columns:", list(net.res_junction.columns)) print(net.res_junction.head()) print("\nres_pipe columns:", list(net.res_pipe.columns)) print(net.res_pipe.head()) ``` -------------------------------- ### Create and Add Networks to MultiNet Source: https://github.com/e2niee/pandapipes/blob/develop/doc/source/multi_energy_nets/multinet.md Demonstrates how to create an empty MultiNet and add existing pandapipes or pandapower networks to it. Networks are stored with unique keys. ```python >>> mn = create_empty_multinet() >>> add_net_to_multinet(mn, net, "first_net_in_multinet") >>> add_nets_to_multinet(mn, ("power_net1", net1), ("power_net2", net2), ("gas_net", net3)) ``` -------------------------------- ### Create and Populate Multinetwork Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/coupled_nets_h2_p2g2p.ipynb Initializes an empty multinetwork and adds the power and gas networks to it with specified names. This structure is essential for coupled simulations. ```python from pandapipes.multinet.create_multinet import create_empty_multinet, add_net_to_multinet multinet = create_empty_multinet('tutorial_multinet') add_net_to_multinet(multinet, net_power, 'power') add_net_to_multinet(multinet, net_gas, 'gas') ``` -------------------------------- ### Create an Empty Network and Add Junctions/Components Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/standard_libraries.ipynb Initializes an empty pandapipes network with a specified fluid and creates essential network elements like junctions, an external grid, and a sink. ```python import pandapipes as pp net = pp.create_empty_network(fluid="water") junction1 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, name="Connection to External Grid") junction2 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, name="Junction") junction3 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, name="Junction to sink") medium_pressure_grid = pp.create_ext_grid(net, junction=junction1, p_bar=1, t_k=293.15, name="Grid Connection") sink = pp.create_sink(net, junction=junction3, mdot_kg_per_s=23.05, name="Sink") ``` -------------------------------- ### Storage Controller Helper Methods Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/building_a_storage_controller.ipynb Provides utility functions to retrieve the current stored mass, free capacity, and filling levels as percentages. ```python # Some convenience methods to calculate indicators for the state of charge: def get_stored_mass(self): # return the absolute stored mass return self.m_stored_kg def get_free_stored_mass(self): # return the stored mass excl. minimum filling level return self.m_stored_kg - self.min_m_kg def get_filling_level_percent(self): # return the ratio of absolute stored mass and total maximum storable mass in Percent return 100 * self.get_stored_mass() / self.max_m_kg def get_free_filling_level_percent(self): # return the ratio of available stored mass (i.e. excl. min_m_stored_kg) and difference between max and min in Percent return 100 * self.get_free_stored_mass() / (self.max_m_kg - self.min_m_kg) ``` -------------------------------- ### Create Elements for P2G and G2P Controllers Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/multienergienetze.ipynb Create the necessary elements in both the power and gas networks that will be connected to the controllers. These elements represent consumption or feed-in points. ```python import pandapower as ppower import pandapipes as ppipes p2g_id_el = ppower.create_load(net_power, bus=3, p_mw=2, name="power to gas consumption") p2g_id_gas = ppipes.create_source(net_gas, junction=1, mdot_kg_per_s=0, name="power to gas feed in") g2p_id_gas = ppipes.create_sink(net_gas, junction=1, mdot_kg_per_s=0.1, name="gas to power consumption") g2p_id_el = ppower.create_sgen(net_power, bus=5, p_mw=0, name="fuel cell feed in") ``` -------------------------------- ### Create Network, Fluid, and Junctions Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/temperature_calculation.ipynb Initializes an empty pandapipes network, defines 'water' as the fluid, and creates four junctions with specified pressure and temperature. ```python # create empty network net = pandapipes.create_empty_network("net") # create fluid pandapipes.create_fluid_from_lib(net, "water", overwrite=True) # create junctions junction1 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=290, name="Junction 1") junction2 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=290, name="Junction 2") junction3 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=290, name="Junction 3") junction4 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=290, name="Junction 4") ``` -------------------------------- ### Add Sinks and Pipes to the Network Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/temperature_calculation.ipynb Creates two sink components and three pipes with specified parameters including length, diameter, sections, heat transfer coefficient, and ambient temperature. Note that 'sections' and 'u_w_per_m2k' are crucial for temperature calculations. ```python # create sinks pandapipes.create_sink(net, junction=junction3, mdot_kg_per_s=1, name="Sink 1") pandapipes.create_sink(net, junction=junction4, mdot_kg_per_s=2, name="Sink 2") # create pipes pandapipes.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=0.1, inner_diameter_mm=75, k_mm=0.025, sections=5, u_w_per_m2k=100, text_k=298.15, name="Pipe 1") pandapipes.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=2, inner_diameter_mm=50, k_mm=0.025, sections=4, u_w_per_m2k=100, text_k=298.15, name="Pipe 2") pandapipes.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction4, length_km=1, inner_diameter_mm=100, k_mm=0.025, sections=8, u_w_per_m2k=50, text_k=298.15, name="Pipe 3") ``` -------------------------------- ### Prepare Time Series Data and Controllers Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/simple_time_series_example.ipynb Reads time series data from CSV files, prepares it using DFData, and sets up ConstControl controllers for sinks and sources. This configures how component parameters change over time. ```python profiles_sink = pd.read_csv(os.path.join('files', 'simple_time_series_example_sink_profiles.csv'), index_col=0) profiles_source = pd.read_csv(os.path.join('files', 'simple_time_series_example_source_profiles.csv'), index_col=0) ds_sink = DFData(profiles_sink) ds_source = DFData(profiles_source) const_sink = control.ConstControl(net, element='sink', variable='mdot_kg_per_s', element_index=net.sink.index.values, data_source=ds_sink, profile_name=net.sink.index.values.astype(str)) const_source = control.ConstControl(net, element='source', variable='mdot_kg_per_s', element_index=net.source.index.values, data_source=ds_source, profile_name=net.source.index.values.astype(str)) ``` -------------------------------- ### Create a Source Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/creating_a_simple_network.ipynb Adds a source element to model gas generation. The `mdot_kg_per_s` parameter specifies the constant mass flow rate. ```python source = pp.create_source(net, junction=junction3, mdot_kg_per_s=0.234, name="Source 1") ``` -------------------------------- ### Add and Commit Changes Source: https://github.com/e2niee/pandapipes/blob/develop/CONTRIBUTING.rst Stage all changes and commit them with a descriptive message. Reference an issue number if applicable. ```bash git add --all git commit -m"commit message" ``` ```bash git commit -m"commit message #3" ``` -------------------------------- ### Configure and Run Time Series Simulation Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/district_heating/time_series_in_a_circular_district_heating_grid.ipynb Set up the OutputWriter to log specific network variables and then run the time series simulation using run_timeseries. This function iterates through time steps, updating network parameters based on defined profiles and controllers. ```python from pandapipes.timeseries import run_time_series from pandapower.timeseries import OutputWriter log_variables = [ ('res_junction', 'p_bar'), ('res_junction', 't_k'), ('heat_consumer', 'qext_w'), ('res_heat_consumer', 'vdot_m3_per_s'), ('res_heat_consumer', 't_from_k'), ('res_heat_consumer', 't_to_k'), ('res_heat_consumer', 'mdot_from_kg_per_s'), ('res_circ_pump_pressure', 'mdot_from_kg_per_s'), ('res_circ_pump_pressure', 'p_to_bar'), ('res_circ_pump_pressure', 'p_from_bar'), ('res_circ_pump_pressure', 't_to_k'), ('res_circ_pump_pressure', 't_from_k') ] ow = OutputWriter(net, time_steps, output_path=None, log_variables=log_variables) run_time_series.run_timeseries(net, time_steps, mode="bidirectional", iter=100, alpha=0.5) ``` -------------------------------- ### Create pipes from parameters Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/height_difference_example.ipynb Add pipe components to the network, defining their connections to junctions, length, inner diameter, and optionally roughness (k_mm). The 'from_junction' and 'to_junction' parameters determine flow direction. ```python pipe1 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=0.545, inner_diameter_mm=200, name="Pipe 1") pipe2 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=0.095, inner_diameter_mm=150, name="Pipe 2") pipe3 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction4, length_km=0.285, inner_diameter_mm=150, name="Pipe 3") pipe4 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction5, length_km=0.43, inner_diameter_mm=150, k_mm=0.5, name="Pipe 4") ``` -------------------------------- ### Implement time_step Method for Storage Controller Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/building_a_storage_controller.ipynb Manage the mass storage's state over time steps, calculating mass changes and updating flow rates based on profiles. ```python # In a time-series simulation the mass storage should read new flow values from a profile and keep track # of its amount of stored mass as depicted below. def time_step(self, net, time): # keep track of the stored mass (the duration of one time step is given as input to the controller) if self.last_time_step is not None: # The amount of mass that flowed into or out of the storage in the last timestep is added # requested change of mass: self.delta_m_kg_req = (self.mdot_kg_per_s * (time - self.last_time_step) * self.duration_ts_sec) # limit by available mass and free capacity in the storage: if self.delta_m_kg_req > 0: # "charging" self.delta_m_kg_real = min(self.delta_m_kg_req, self.max_m_kg - self.m_stored_kg) else: # "discharging", delta < 0 self.delta_m_kg_real = max(self.delta_m_kg_req, self.min_m_kg - self.m_stored_kg) self.m_stored_kg += self.delta_m_kg_real self.mdot_kg_per_s = self.delta_m_kg_real / ((time - self.last_time_step) * self.duration_ts_sec) self.last_time_step = time # read new values from a profile if self.data_source: if self.mdot_profile is not None: self.mdot_kg_per_s = self.data_source.get_time_step_value(time_step=time, profile_name=self.mdot_profile) self.m_stored_kg *= self.scaling * self.in_service self.applied = False # reset applied variable ``` -------------------------------- ### Load Investment Options Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Loads the investment options for oemof-solph components, typically exported from DHNx investment data. ```python invest_opt = load_invest_options('invest_data') ``` -------------------------------- ### Configure Output Writer Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/simple_time_series_example.ipynb Initializes an OutputWriter to log specified variables at each time step. This is crucial for accessing simulation results after the run. ```python log_variables = [('res_junction', 'p_bar'), ('res_pipe', 'v_mean_m_per_s'), ('res_pipe', 'reynolds'), ('res_pipe', 'lambda'), ('res_sink', 'mdot_kg_per_s'), ('res_source', 'mdot_kg_per_s'), ('res_ext_grid', 'mdot_kg_per_s')] ow = OutputWriter(net, time_steps, output_path=None, log_variables=log_variables) ``` -------------------------------- ### Define StorageController Class Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials/building_a_storage_controller.ipynb Inherit from `Controller` and initialize storage attributes. This class models an abstract mass storage. ```python import pandapipes as pp from pandapower.control.basic_controller import Controller class StorageController(Controller): """ Example class of a Storage-Controller. Models an abstract mass storage. """ def __init__(self, net, sid, data_source=None, mdot_profile=None, in_service=True, recycle=False, order=0, level=0, duration_timestep_h=1, **kwargs): super().__init__(net, in_service=in_service, recycle=recycle, order=order, level=level, initial_run=True, **kwargs) # read storage attributes from net self.sid = sid # index of the controlled storage self.junction = net.mass_storage.at[sid, "junction"] self.mdot_kg_per_s = net.mass_storage.at[sid, "mdot_kg_per_s"] self.name = net.mass_storage.at[sid, "name"] self.storage_type = net.mass_storage.at[sid, "type"] self.in_service = net.mass_storage.at[sid, "in_service"] self.scaling = net.mass_storage.at[sid, "scaling"] self.applied = False # specific attributes self.max_m_kg = net.mass_storage.at[sid, "max_m_stored_kg"] self.min_m_kg = net.mass_storage.at[sid, "min_m_stored_kg"] self.m_stored_kg = net.mass_storage.at[sid, "init_m_stored_kg"] # profile attributes self.data_source = data_source self.mdot_profile = mdot_profile self.last_time_step = 0 self.duration_ts_sec = duration_timestep_h * 3600 ``` -------------------------------- ### Initialize ThermalNetwork Source: https://github.com/e2niee/pandapipes/blob/develop/tutorials_extended/tutorial_dhnx_pandapipes/tutorial_dhnx_pandapipes.ipynb Initializes an empty ThermalNetwork object. This is the first step before adding any network components. ```python network = ThermalNetwork() ```