Расходные характеристики регулирующего клапана (РК) в [1] были построены при условии неизменного напора насоса при различных значениях подачи (напорная характеристика насоса - горизонтальная линия).
Для большинства насосов при увеличении подачи его напор уменьшается.
Определим с помощью класса ControlValve
из [2] влияние наклона напорной характеристики насоса на форму расходной характеристики РК.
# Импортируем ControlValve и библиотеку для работы с массивами numpy
import sys
sys.path.append("../0029_Расчёт_параметров_РК")
from controlvalve import ControlValve as CV
import numpy as np
Q_max = 1 # расход (подача) насоса при условии полностью открытыого РК
H_min = 1 # напор насоса при Q = Q_max
Наклон напорной характеристики характеризуется отношением H_max/H_min, где H_max - напор насоса при нулевой подаче (режим работы насоса на закрытую задвижку).
# Моделирование напорных характеристик насоса с различным наклоном
from scipy.interpolate import interp1d # функция линейной интерполяции
koefs = np.array([1, 1.2, 1.5, 2, 5, 20]) # H_max/H_min
# fill_value = "extrapolate" необходима, т.к. функция newton при поиске решения
# может выходить за диапазон Q = [0; 1]
f = lambda koef: interp1d([0, Q_max], [koef * H_min, H_min], fill_value = "extrapolate")
pumps = list(map(f, koefs)) # напорные характеристики насоса
Qs = np.linspace(0, 1, 51) # массив значений расхода (подачи) для построения напорных характеристик насоса
import matplotlib.pyplot as plt # библиотека для построения графиков
plt.rcParams['font.size'] = 12.0
fig, axes = plt.subplots(1,2, figsize = (16, 5))
fig.suptitle ("Напорные характеристики насоса с различным наклоном", fontsize=16)
for ax in axes:
ax.grid(); ax.set_xlim(0,1)
ax.set_xlabel('$Q,\, м^3/ч$'); ax.set_ylabel('$H,\, Па$')
for i, pump in enumerate(pumps):
ax.plot(Qs, pump(Qs), label = koefs[i])
ax.legend(title = '$H_{max}/H_{min}$',ncol = 2);
axes[0].set_ylim(0,2); axes[1].set_ylim(0,20);
density = 200 # форма характеристик от плотности не зависит, от неё зависит величина Kvs
F0 = 1 / 50 # Диапазон регулирования РК Д = 50
m = 0.1 # Авторитет полностью открытого РК m = 0,1
char_types = ["линейной", "равнопроцентной"]
Kvs = CV.Kv_from_m_dp_Q(m, H_min * (1 - m), Q_max, density=density)
# Создаём два объекта РК с линейной и равнопроцентной пропускными характеристиками
cvs = [CV(Kvs, 0, F0, density=density), CV(Kvs, 1, F0, density=density)]
# При h = 1 гидравлические сопротивления РК с разными проходными характеристиками и одинаковыми Kvs равны
R_cv = cvs[0].get_R()
R = R_cv / m # Гидравлическое сопротивление всей сети при полностью открытом РК
# Гидравлическое сопротивление участка сети без РК (не будет изменяться при изменении положения штока РК)
R_other = R - R_cv
Что такое гидравлическое сопротивление сети см. в [3]
hs = np.linspace(0, 1, 51) # массив положений штока РК в диапазоне [0; 1]
Qs = np.zeros_like(hs) # массив для сохранения результата расчёта расхода (подачи) для каждого h из hs
from scipy.optimize import newton # ищет решение (Q) уравнения f(Q) = 0
# Функция f(Q) = 0
def f(Q, R, pump):
# Функция возвращает 0 при Q при котором пересекаются напорная характеристика
# насоса и характеристика сети
# R, pump - дополнительные аргументы, передаваемые в newton параметром args=(R, pump)
# R - гидравлическое сопротивление сети
# pump - напорная характеристика насоса: pump(Q) возврачает напор (H) для заданной плдачи (Q)
return R * Q * Q - pump(Q)
n = len(cvs) # количество графиков
Qs_test = np.zeros(len(pumps)) # используется при проверке
fig, axes = plt.subplots(1, n, figsize = (16, 5))
for k in range(n):
axes[k].grid(); axes[k].set_xlim(0,1); axes[k].set_ylim(0,1)
axes[k].set_xlabel('$\overline{h}$'); axes[k].set_ylabel('$Q,\, м^3/ч$')
axes[k].set_title(f"Расходная характеристика РК с {char_types[k]}\nпропускной характеристикой, "
f"авторитет РК m = {m}")
for i, pump in enumerate(pumps):
for j, h in enumerate(hs):
cvs[k].set_h(h) # устанавливаем положение штока РК
R = R_other + cvs[k].get_R() # гидравлическое сопротивление сети
Qs[j] = newton(f, Q_max/2, args=(R, pump)) # определение расхода (подачи)
axes[k].plot(hs,Qs, label = koefs[i])
Qs_test[i] = Qs[0] # используется при проверке
axes[k].legend(title = '$H_{max}/H_{min}$',ncol = 2);
Kv0 = Kvs * F0 # Kv при h = 0
R0_cv = CV.Kv2R(Kv0, density) # сопротивление РК при h = 0
R0 = R0_cv + R_other # сопротивление сети при h = 0
for i, pump in enumerate(pumps):
print((newton(f, Q_max/2, args=(R0, pump)) - Qs_test[i]) / Qs_test[i] * 100, end=" ")
#Относительное отклонение, %
0.0 0.0 0.0 0.0 0.0 0.0
for i, pump in enumerate(pumps):
print((CV.dp_from_Kv_Q(Kv0, Qs_test[i], density) + R_other * Qs_test[i] * Qs_test[i] -
pump(Qs_test[i]))* 100 / pump(Qs_test[i]))
#Относительное отклонение, %
2.220446049250313e-14 -5.6154686215793306e-14 3.8708786666371406e-10 5.305327450364095e-12 9.92319071483298e-12 2.3209700146362384e-14
Инженерные расчёты на Python, С.В. Медведев, 2020-2021
Использование Python и Jupyter Notebook для инженерных расчётов, С.В. Медведев, 2020-2021