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

NonReturnValveController created, test in pipeflow_internals added and docu updated #118

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 12 additions & 1 deletion doc/source/controller/controller_classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,15 @@ This is used to read the data from a DataSource and write it to a network.

.. _ConstControl:
.. autoclass:: pandapower.control.controller.const_control.ConstControl
:members:
:members:

NonReturnValveController
========================

The NonReturnValveController makes it possible to implement a valve
which only allows flow in the connection direction. In the backward
direction the valve can be regarded as ideally closed.

.. _NonReturnValveController:
.. autoclass:: pandapipes.control.controller.non_return_valve_controller.NonReturnValveController
:members:
1 change: 1 addition & 0 deletions pandapipes/control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

from pandapipes.control.run_control import run_control
from pandapipes.control.controller.non_return_valve_controller import NonReturnValveController
110 changes: 110 additions & 0 deletions pandapipes/control/controller/non_return_valve_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Copyright (c) 2020 by Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

import pandapipes as pp
import numpy
from pandapower.control.basic_controller import Controller

try:
import pplog as logging
except ImportError:
import logging

logger = logging.getLogger(__name__)


class NonReturnValveController(Controller):
"""
Controller for implementing a non-return valve.

:param net: The net in which the controller resides
:type net: pandapipesNet
:param element_index: IDs of controlled valves
:type element_index: int[]
:param in_service: Indicates if the controller is currently in_service
:type in_service: bool, default True
:param recycle: Re-use of internal-data
:type recycle: bool, default True
:param drop_same_existing_ctrl: Indicates if already existing controllers of the same type and with the same matching parameters (e.g. at same element) should be dropped
:type drop_same_existing_ctrl: bool, default False
:param kwargs: Parameters for pipeflow
:type kwargs: dict

:Example:
>>> kwargs = {'stop_condition': 'tol', 'iter': 100, 'tol_p': 1e-7, 'tol_v': 1e-7, 'friction_model': 'colebrook',
>>> 'mode': 'hydraulics', 'only_update_hydraulic_matrix': False}
>>> NonReturnValveController(net, element_index=[0, 1, 3], **kwargs)
>>> run_control(net)

"""

def __init__(self, net, element_index, profile_name=None,
scale_factor=1.0, in_service=True, recycle=True, order=0, level=0,
drop_same_existing_ctrl=False, matching_params=None, initial_run=False,
**kwargs):

if matching_params is None:
matching_params = {"element_index": element_index}

# just calling init of the parent
super().__init__(net, in_service=in_service, recycle=recycle, order=order, level=level,
drop_same_existing_ctrl=drop_same_existing_ctrl,
matching_params=matching_params, initial_run=initial_run,
**kwargs)

self.matching_params = {"element_index": element_index}
if numpy.isscalar(element_index):
self.element_index = [element_index]
else:
self.element_index = element_index
self.values = None
self.profile_name = profile_name
self.scale_factor = scale_factor
self.initial_run = initial_run
self.kwargs = kwargs
self.v_m_per_s = [] # current flow velocities at valves
self.opened = [] # remember original user-defined values of opened

def initialize_control(self):
"""
Saving the user-defined values and adapt types.
"""
self.opened = self.net.valve.loc[self.element_index, "opened"]
self.net.valve.loc[self.element_index, "opened"] = True
self.net.valve.loc[self.element_index, "type"] = "non-return valve"

def is_converged(self):
"""
Convergence Condition: If all flow velocities at the non-return valves are >= 0 or opened equal False.
"""
if numpy.array(self.v_m_per_s).size == 0:
return False

if numpy.array(self.net.valve.loc[self.element_index, "opened"]).any() and \
numpy.array(self.v_m_per_s).any() < 0:
return False

return True

def control_step(self):
"""
Check whether negative flow velocities are present at non-return valves,
set opened to False for these.
"""
pp.pipeflow(self.net, self.kwargs)

self.v_m_per_s = numpy.array(self.net.res_valve.loc[self.element_index, "v_mean_m_per_s"])

ind_opened = numpy.where(self.net.valve.loc[self.element_index, "opened"])
# use the element indices, where opened = True, otherwise NaN would be in self.v_m_per_s

ind_negative_v = numpy.where(self.v_m_per_s[ind_opened[0]] < 0)

self.net.valve.loc[numpy.array(self.element_index)[ind_negative_v[0]], "opened"] = False

def finalize_control(self):
"""
Resetting the variable opened to user defaults.
"""
self.net.valve.loc[self.element_index, "opened"] = self.opened
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright (c) 2020 by Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

import pandapipes
import pytest
from pandapipes.control import NonReturnValveController, run_control


def test_nrv():
net = pandapipes.create_empty_network("net", fluid="water", add_stdtypes=True)

j0 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=293.15)
j1 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=293.15)
j2 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=293.15)
j3 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=283.15)
j4 = pandapipes.create_junction(net, pn_bar=3, tfluid_k=283.15)

pandapipes.create_ext_grid(net, j0, p_bar=3, t_k=293.15, type="pt")

pandapipes.create_sink(net, j1, mdot_kg_per_s=1)
pandapipes.create_sink(net, j4, mdot_kg_per_s=0.5)

pandapipes.create_source(net, j2, mdot_kg_per_s=0.05)
pandapipes.create_source(net, j3, mdot_kg_per_s=1)

pandapipes.create_pipe_from_parameters(net, j1, j0, diameter_m=0.75, k_mm=0.1, length_km=15)
pandapipes.create_pipe_from_parameters(net, j4, j2, diameter_m=0.1, k_mm=0.1, length_km=10)

pandapipes.create_valve(net, j4, j3, diameter_m=0.1, opened=True)
pandapipes.create_valve(net, j1, j3, diameter_m=0.07, opened=True)
pandapipes.create_valve(net, j1, j2, diameter_m=0.05, opened=True)
pandapipes.create_valve(net, j3, j0, diameter_m=0.01, opened=True)

kwargs = {'stop_condition': 'tol', 'iter': 100, 'tol_p': 1e-7, 'tol_v': 1e-7, 'friction_model': 'colebrook',
'mode': 'hydraulics', 'only_update_hydraulic_matrix': False}

NonReturnValveController(net, element_index=[1, 3], **kwargs)

run_control(net)


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