Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pipeflow cancellation if all nodes are out-of-service after the connectivity check #564

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Change Log
-------------------------------
- [ADDED] multiple creation of heat exchanger
- [ADDED] support Python 3.11 (now included in test pipeline)
- [ADDED] after the connectivity check, intercept the pipeflow if no more nodes are in-service
- [CHANGED] dropped support for Python 3.7 (no longer included in test pipeline)
- [CHANGED] connectivity check now separated by hydraulics and heat_transfer calculation, so that also results can differ in some rows (NaN or not)
- [CHANGED] dynamic creation of lookups for getting pit as pandas tables
Expand Down
2 changes: 0 additions & 2 deletions pandapipes/multinet/create_multinet.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import logging

logger = logging.getLogger(__name__)
logger.setLevel(level=logging.WARNING)


def create_empty_multinet(name=""):
"""
Expand Down
1 change: 0 additions & 1 deletion pandapipes/multinet/timeseries/run_time_series_multinet.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import logging as pplog

logger = pplog.getLogger(__name__)
logger.setLevel(level=pplog.WARNING)


def _call_output_writer(multinet, time_step, pf_converged, ctrl_converged, ts_variables):
Expand Down
1 change: 1 addition & 0 deletions pandapipes/pf/pipeflow_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ def identify_active_nodes_branches(net, branch_pit, node_pit, hydraulic=True):
mode = "hydraulics" if hydraulic else "heat_transfer"
net["_lookups"]["node_active_" + mode] = nodes_connected
net["_lookups"]["branch_active_" + mode] = branches_connected
return node_pit[nodes_connected], branch_pit[branches_connected]


def branches_connected_flow(branch_pit):
Expand Down
17 changes: 12 additions & 5 deletions pandapipes/pipeflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import numpy as np
from numpy import linalg
from pandapower.auxiliary import ppException
from scipy.sparse.linalg import spsolve

from pandapipes.idx_branch import FROM_NODE, TO_NODE, FROM_NODE_T, TO_NODE_T, VINIT, TOUTINIT, VINIT_T
Expand All @@ -16,6 +15,7 @@
initialize_pit, reduce_pit, set_user_pf_options, init_all_result_tables, \
identify_active_nodes_branches
from pandapipes.pf.result_extraction import extract_all_results, extract_results_active_pit
from pandapower.auxiliary import ppException

try:
import pandaplan.core.pplog as logging
Expand Down Expand Up @@ -70,15 +70,22 @@

create_lookups(net)
node_pit, branch_pit = initialize_pit(net)
if (len(node_pit) == 0) & (len(branch_pit) == 0):
logger.warning("There are no node and branch entries defined. This might mean that your net"
" is empty")
if len(node_pit) == 0:
logger.warning("There are no nodes defined. "

Check warning on line 74 in pandapipes/pipeflow.py

View check run for this annotation

Codecov / codecov/patch

pandapipes/pipeflow.py#L74

Added line #L74 was not covered by tests
"You need at least one node! "
"Without any nodes, you are not able to conduct a pipeflow!")
return

calculation_mode = get_net_option(net, "mode")
calculate_hydraulics = calculation_mode in ["hydraulics", "all"]
calculate_heat = calculation_mode in ["heat", "all"]

identify_active_nodes_branches(net, branch_pit, node_pit)
active_node_pit, active_branch_pit = identify_active_nodes_branches(net, branch_pit, node_pit)

if (len(active_node_pit) == 0):
logger.warning(" All nodes are out of service. Probably they are not supplied."
" Have you forgotten to define an external grid?")
return

if calculation_mode == "heat":
if not net.user_pf_options["hyd_flag"]:
Expand Down
57 changes: 46 additions & 11 deletions pandapipes/test/pipeflow_internals/test_inservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import pandapipes
from pandapipes.pf.pipeflow_setup import get_lookup
from pandapipes.pipeflow import logger as pf_logger
from pandapipes.pipeflow import PipeflowNotConverged
from pandapipes.pipeflow import logger as pf_logger

try:
import pandaplan.core.pplog as logging
Expand Down Expand Up @@ -125,6 +125,29 @@ def create_mixed_indexing_grid():
return net


@pytest.fixture
def create_net_wo_external_hydraulic_grid():
net = pandapipes.create_empty_network("net", add_stdtypes=False)
pandapipes.create_fluid_from_lib(net, "hgas", overwrite=True)
pandapipes.create_junction(net, index=3, pn_bar=16, tfluid_k=283, height_m=0,
name="Junction 3", in_service=True,
type="junction", geodata=(0, 0))
pandapipes.create_junction(net, index=9, pn_bar=16, tfluid_k=283, height_m=0,
name="Junction 9", in_service=True,
type="junction", geodata=(1, 0))
pandapipes.create_junction(net, index=10, pn_bar=16, tfluid_k=283, height_m=0,
name="Junction 10", in_service=True,
type="junction", geodata=(2, 0))
pandapipes.create_pipe_from_parameters(net, 9, 10, length_km=1, diameter_m=0.03, k_mm=.1, sections=10,
alpha_w_per_m2k=1, name="Pipe 6")
pandapipes.create_sink(net, 9, mdot_kg_per_s=0.01, name="Sink 3")
pandapipes.create_source(net, junction=10, mdot_kg_per_s=0.04, name="Source 3")
pandapipes.create_compressor(net, from_junction=9, to_junction=3, pressure_ratio=1.1,
name="Compressor 0", index=None, in_service=True)
pandapipes.create_ext_grid(net, junction=3, t_k=300)
return net


@pytest.mark.parametrize("use_numba", [True, False])
def test_inservice_gas(create_test_net, use_numba):
"""
Expand All @@ -146,7 +169,7 @@ def test_inservice_gas(create_test_net, use_numba):
assert np.all(np.isnan(net.res_junction.p_bar.loc[~net.junction.in_service].values))

oos_sinks = np.isin(net.sink.junction.values, net.junction.index[~net.junction.in_service]) \
| ~net.sink.in_service.values
| ~net.sink.in_service.values
assert np.all(np.isnan(net.res_sink.loc[oos_sinks, :].values))

assert not np.any(np.isnan(net.res_pipe.v_mean_m_per_s.loc[net.pipe.in_service].values))
Expand Down Expand Up @@ -179,7 +202,7 @@ def test_inservice_water(create_test_net, use_numba):
assert np.all(np.isnan(net.res_junction.p_bar.loc[~net.junction.in_service].values))

oos_sinks = np.isin(net.sink.junction.values, net.junction.index[~net.junction.in_service]) \
| ~net.sink.in_service.values
| ~net.sink.in_service.values
assert np.all(np.isnan(net.res_sink.loc[oos_sinks, :].values))

assert not any(np.isnan(net.res_pipe.v_mean_m_per_s.loc[net.pipe.in_service].values))
Expand Down Expand Up @@ -214,8 +237,8 @@ def test_connectivity_hydraulic(create_test_net, use_numba):
assert np.all(np.isnan(net.res_pipe.loc[[1, 2, 3], :].values))
assert not np.any(np.isnan(net.res_junction.loc[[0, 1, 3, 4], :].values))
assert not np.any(np.isnan(net.res_pipe.loc[[0, 4],
["v_mean_m_per_s", "p_from_bar",
"p_to_bar"]].values))
["v_mean_m_per_s", "p_from_bar",
"p_to_bar"]].values))
assert not np.any(np.isnan(net.res_sink.loc[[0, 2], "mdot_kg_per_s"].values))
assert np.all(np.isnan(net.res_sink.loc[[1, 3, 4], "mdot_kg_per_s"].values))

Expand Down Expand Up @@ -496,7 +519,7 @@ def test_mixed_indexing_oos2(create_mixed_indexing_grid, use_numba):
assert all(np.all(net["res_" + tbl].loc[~oos_func(net, tbl, oos_juncs)].notnull())
for tbl, oos_func in all_tbls_funcs.items())
assert all(np.all(net["res_" + tbl].loc[oos_func(net, tbl, oos_juncs),
get_col_slice_null(tbl)].isnull())
get_col_slice_null(tbl)].isnull())
for tbl, oos_func in all_tbls_funcs.items())
assert check_mass_flows(net)

Expand All @@ -514,7 +537,7 @@ def test_mixed_indexing_oos3(create_mixed_indexing_grid, use_numba):
assert all(np.all(net["res_" + tbl].loc[~oos_func(net, tbl, oos_juncs)].notnull())
for tbl, oos_func in all_tbls_funcs.items())
assert all(np.all(net["res_" + tbl].loc[oos_func(net, tbl, oos_juncs),
get_col_slice_null(tbl)].isnull())
get_col_slice_null(tbl)].isnull())
for tbl, oos_func in all_tbls_funcs.items())
assert check_mass_flows(net)

Expand All @@ -532,7 +555,7 @@ def test_mixed_indexing_oos4(create_mixed_indexing_grid, use_numba):
assert all(np.all(net["res_" + tbl].loc[~oos_func(net, tbl, oos_juncs)].notnull())
for tbl, oos_func in all_tbls_funcs.items())
assert all(np.all(net["res_" + tbl].loc[oos_func(net, tbl, oos_juncs),
get_col_slice_null(tbl)].isnull())
get_col_slice_null(tbl)].isnull())
for tbl, oos_func in all_tbls_funcs.items())
assert check_mass_flows(net)

Expand All @@ -550,7 +573,7 @@ def test_mixed_indexing_oos5(create_mixed_indexing_grid, use_numba):
assert all(np.all(net["res_" + tbl].loc[~oos_func(net, tbl, oos_juncs)].notnull())
for tbl, oos_func in all_tbls_funcs.items())
assert all(np.all(net["res_" + tbl].loc[oos_func(net, tbl, oos_juncs),
get_col_slice_null(tbl)].isnull())
get_col_slice_null(tbl)].isnull())
for tbl, oos_func in all_tbls_funcs.items())
assert check_mass_flows(net)

Expand All @@ -568,7 +591,7 @@ def test_mixed_indexing_oos6(create_mixed_indexing_grid, use_numba):
assert all(np.all(net["res_" + tbl].loc[~oos_func(net, tbl, oos_juncs)].notnull())
for tbl, oos_func in all_tbls_funcs.items())
assert all(np.all(net["res_" + tbl].loc[oos_func(net, tbl, oos_juncs),
get_col_slice_null(tbl)].isnull())
get_col_slice_null(tbl)].isnull())
for tbl, oos_func in all_tbls_funcs.items())
assert check_mass_flows(net)

Expand All @@ -577,10 +600,22 @@ def test_mixed_indexing_oos6(create_mixed_indexing_grid, use_numba):
assert all(np.all(net["res_" + tbl].loc[~oos_func(net, tbl, oos_juncs)].notnull())
for tbl, oos_func in all_tbls_funcs.items())
assert all(np.all(net["res_" + tbl].loc[oos_func(net, tbl, oos_juncs),
get_col_slice_null(tbl)].isnull())
get_col_slice_null(tbl)].isnull())
for tbl, oos_func in all_tbls_funcs.items())
assert check_mass_flows(net)


@pytest.mark.parametrize("use_numba", [True, False])
def test_pipeflow_cancellation(create_net_wo_external_hydraulic_grid, use_numba):
net = create_net_wo_external_hydraulic_grid
pandapipes.pipeflow(net)
assert np.all(np.isnan(net.res_junction))
assert np.all(np.isnan(net.res_pipe))
assert np.all(np.isnan(net.res_ext_grid))
assert np.all(np.isnan(net.res_sink))
assert np.all(np.isnan(net.res_source))
assert np.all(np.isnan(net.res_compressor))


if __name__ == "__main__":
pytest.main([r'pandapipes/test/pipeflow_internals/test_inservice.py'])
Loading