end of day commit - working on turbine class

This commit is contained in:
Brantegger Georg
2022-07-19 15:51:57 +02:00
parent 5654a41d48
commit 7e67979a82
9 changed files with 1149 additions and 230 deletions

File diff suppressed because one or more lines are too long

274
Pegelregler_test.ipynb Normal file

File diff suppressed because one or more lines are too long

View File

@@ -42,33 +42,35 @@ def ITAE_fun(error_history,timestep):
return itae return itae
class P_controller_class: class P_controller_class:
def __init__(self,setpoint,proportionality_constant): # def __init__(self,setpoint,proportionality_constant):
self.SP = setpoint # self.SP = setpoint
self.Kp = proportionality_constant # self.Kp = proportionality_constant
self.error_history = [] # self.error_history = []
self.control_variable = 0.1 # self.control_variable = 0.1
self.lower_limit = -0.1 # default # self.lower_limit = -0.1 # default
self.upper_limit = +0.1 # default # self.upper_limit = +0.1 # default
def set_control_variable_limits(self,lower_limit,upper_limit): # def set_control_variable_limits(self,lower_limit,upper_limit):
self.lower_limit = lower_limit # self.lower_limit = lower_limit
self.upper_limit = upper_limit # self.upper_limit = upper_limit
def calculate_error(self,process_variable): # def calculate_error(self,process_variable):
self.error = self.SP-process_variable # self.error = self.SP-process_variable
self.error_history.append(self.error) # self.error_history.append(self.error)
def get_control_variable(self): # def get_control_variable(self):
new_control = self.control_variable+self.Kp*(self.error_history[-1]-self.error_history[-2]) # new_control = self.control_variable+self.Kp*(self.error_history[-1]-self.error_history[-2])
if new_control < self.lower_limit: # if new_control < self.lower_limit:
new_control = self.lower_limit # new_control = self.lower_limit
if new_control > self.upper_limit: # if new_control > self.upper_limit:
new_control = self.upper_limit # new_control = self.upper_limit
self.control_variable = new_control # self.control_variable = new_control
# print(new_control) # # print(new_control)
return new_control # return new_control
def __init__(self):
pass
class PI_controller_class: class PI_controller_class:
@@ -77,21 +79,25 @@ class PI_controller_class:
self.Kp = proportionality_constant self.Kp = proportionality_constant
self.Ti = Ti self.Ti = Ti
self.dt = timestep self.dt = timestep
self.error_history = [0,0] self.error_history = [0]
self.control_variable = 0.0 self.control_variable = 0.0
self.lower_limit = -1.3 # default self.cv_lower_limit = -1 # default
self.upper_limit = +1.3 # default self.cv_upper_limit = +1 # default
def set_control_variable_limits(self,lower_limit,upper_limit): def set_control_variable_limits(self,lower_limit,upper_limit):
self.lower_limit = lower_limit self.cv_lower_limit = lower_limit
self.upper_limit = upper_limit self.cv_upper_limit = upper_limit
def calculate_error(self,process_variable): def calculate_error(self,process_variable):
self.error = self.SP-process_variable self.error = self.SP-process_variable
self.error_history.append(self.error) self.error_history.append(self.error)
def get_control_variable(self): def get_control_variable(self):
# if np.isclose(self.error,0,atol = 0.1):
# self.control_variable = 0
cv = self.control_variable cv = self.control_variable
Kp = self.Kp Kp = self.Kp
Ti = self.Ti Ti = self.Ti
@@ -100,15 +106,14 @@ class PI_controller_class:
e0 = self.error_history[-1] e0 = self.error_history[-1]
e1 = self.error_history[-2] e1 = self.error_history[-2]
new_control = cv+Kp*(e0-e1)+dt/Ti*e0 new_control = cv+Kp*(e0-e1)+dt/Ti*e0
if new_control < self.lower_limit: if new_control < self.cv_lower_limit:
new_control = self.lower_limit new_control = self.cv_lower_limit
if new_control > self.upper_limit: if new_control > self.cv_upper_limit:
new_control = self.upper_limit new_control = self.cv_upper_limit
self.control_variable = new_control self.control_variable = new_control
# print(new_control) return self.control_variable
return new_control
def get_performance_indicators(self,ISE=True,IAE=True,ITSE=True,ITAE=True): def get_performance_indicators(self,ISE=True,IAE=True,ITSE=True,ITAE=True):
ise = np.nan ise = np.nan
@@ -116,14 +121,16 @@ class PI_controller_class:
itse = np.nan itse = np.nan
itae = np.nan itae = np.nan
# self.error_history[1:] because the first value of the error history is set to [0]
# to avoid special case handling in the calculation of the controll variable
if ISE == True: if ISE == True:
ise = ISE_fun(self.error_history[2:],self.dt) ise = ISE_fun(self.error_history[1:],self.dt)
if IAE == True: if IAE == True:
iae = IAE_fun(self.error_history[2:],self.dt) iae = IAE_fun(self.error_history[1:],self.dt)
if ITSE == True: if ITSE == True:
itse = ITSE_fun(self.error_history[2:],self.dt) itse = ITSE_fun(self.error_history[1:],self.dt)
if ITAE == True: if ITAE == True:
itae = ITAE_fun(self.error_history[2:],self.dt) itae = ITAE_fun(self.error_history[1:],self.dt)
return ise,iae,itse,itae return ise,iae,itse,itae

File diff suppressed because one or more lines are too long

View File

@@ -1,22 +1,22 @@
,11.4,11.2,11,10.8,10.6,10.4,10.2,10,9.8 ,11.4,11.2,11,10.8,10.6,10.4,10.2,10,9.8
0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0
0.05,44.6719225,43.934144,43.3914212,43.005945,42.7411852,42.5620659,42.4351104,42.3285595,42.2124611 0.05,44.6719225,43.934144,43.3914212,43.005945,42.7411852,42.5620659,42.4351104,42.3285595,42.2124611
0.1,93.5257218,92.1813802,91.0120507,89.9819869,89.0566946,88.2030946,87.3896575,86.5865116,85.7655241 0.1,93.5257218,92.1813802,91.0120507,89.9819869,89.0566946,88.2030946,87.3896575,86.5865116,85.7655241
0.15,142.455373,140.502298,138.703994,137.026824,135.438371,133.907593,132.404945,130.902474,129.373898 0.15,142.455373,140.502298,138.703994,137.026824,135.438371,133.907593,132.404945,130.902474,129.373898
0.2,191.35358,188.792245,186.365298,184.041241,181.789769,179.581903,177.390108,175.188376,172.952294 0.2,191.35358,188.792245,186.365298,184.041241,181.789769,179.581903,177.390108,175.188376,172.952294
0.25,240.112708,236.946245,233.893698,230.92573,228.014163,225.132101,222.254034,219.355912,216.415204 0.25,240.112708,236.946245,233.893698,230.92573,228.014163,225.132101,222.254034,219.355912,216.415204
0.3,288.625576,284.85976,281.187353,277.581187,274.01522,270.464644,266.905977,263.31713,259.677456 0.3,288.625576,284.85976,281.187353,277.581187,274.01522,270.464644,266.905977,263.31713,259.677456
0.35,336.786234,332.429439,328.145567,323.909615,319.697669,315.487006,311.256165,306.985012,302.654777 0.35,336.786234,332.429439,328.145567,323.909615,319.697669,315.487006,311.256165,306.985012,302.654777
0.4,384.490739,379.553866,374.669505,369.814802,364.967956,360.108307,355.216403,350.274048,345.264331 0.4,384.490739,379.553866,374.669505,369.814802,364.967956,360.108307,355.216403,350.274048,345.264331
0.45,431.637894,426.134271,420.662881,415.202987,409.734875,404.239922,398.700655,393.100789,387.425251 0.45,431.637894,426.134271,420.662881,415.202987,409.734875,404.239922,398.700655,393.100789,387.425251
0.5,478.129951,472.075209,466.032607,459.983487,453.910176,447.796055,441.625591,435.384378,429.059145 0.5,478.129951,472.075209,466.032607,459.983487,453.910176,447.796055,441.625591,435.384378,429.059145
0.55,523.873268,517.285198,510.689413,504.069281,497.409128,490.694283,483.911113,477.047044,470.090565 0.55,523.873268,517.285198,510.689413,504.069281,497.409128,490.694283,483.911113,477.047044,470.090565
0.6,568.778912,561.677293,554.548395,547.377555,540.151033,532.856054,525.480827,518.014558,510.447451 0.6,568.778912,561.677293,554.548395,547.377555,540.151033,532.856054,525.480827,518.014558,510.447451
0.65,612.763186,605.169605,597.529525,589.830179,582.059697,574.207132,566.262474,558.216649,550.061519 0.65,612.763186,605.169605,597.529525,589.830179,582.059697,574.207132,566.262474,558.216649,550.061519
0.7,655.7481,647.685753,639.558081,631.354134,623.063835,614.677994,606.188309,597.587364,588.868614 0.7,655.7481,647.685753,639.558081,631.354134,623.063835,614.677994,606.188309,597.587364,588.868614
0.75,697.661758,689.155243,680.565018,671.881864,663.097416,654.204159,645.195426,636.065384,626.809013 0.75,697.661758,689.155243,680.565018,671.881864,663.097416,654.204159,645.195426,636.065384,626.809013
0.8,738.438667,729.51377,720.487263,711.35157,702.099947,692.726469,683.226022,673.594278,663.827671 0.8,738.438667,729.51377,720.487263,711.35157,702.099947,692.726469,683.226022,673.594278,663.827671
0.85,778.019972,768.703447,759.267942,749.707427,740.016685,730.191293,720.227602,710.122707,699.874419 0.85,778.019972,768.703447,759.267942,749.707427,740.016685,730.191293,720.227602,710.122707,699.874419
0.9,816.35361,806.672962,796.856534,786.899741,776.798797,766.550685,756.153132,745.604572,734.904109 0.9,816.35361,806.672962,796.856534,786.899741,776.798797,766.550685,756.153132,745.604572,734.904109
0.95,853.394385,843.377654,833.208949,822.885029,812.403437,801.762466,790.961126,779.999101,768.876705 0.95,853.394385,843.377654,833.208949,822.885029,812.403437,801.762466,790.961126,779.999101,768.876705
1,889.103974,878.779525,868.287549,857.626044,846.793778,835.790258,824.615682,813.270891,801.757325 1,889.103974,878.779525,868.287549,857.626044,846.793778,835.790258,824.615682,813.270891,801.757325
1 11.4 11.2 11 10.8 10.6 10.4 10.2 10 9.8
2 0 0 0 0 0 0 0 0 0 0
3 0.05 44.6719225 43.934144 43.3914212 43.005945 42.7411852 42.5620659 42.4351104 42.3285595 42.2124611
4 0.1 93.5257218 92.1813802 91.0120507 89.9819869 89.0566946 88.2030946 87.3896575 86.5865116 85.7655241
5 0.15 142.455373 140.502298 138.703994 137.026824 135.438371 133.907593 132.404945 130.902474 129.373898
6 0.2 191.35358 188.792245 186.365298 184.041241 181.789769 179.581903 177.390108 175.188376 172.952294
7 0.25 240.112708 236.946245 233.893698 230.92573 228.014163 225.132101 222.254034 219.355912 216.415204
8 0.3 288.625576 284.85976 281.187353 277.581187 274.01522 270.464644 266.905977 263.31713 259.677456
9 0.35 336.786234 332.429439 328.145567 323.909615 319.697669 315.487006 311.256165 306.985012 302.654777
10 0.4 384.490739 379.553866 374.669505 369.814802 364.967956 360.108307 355.216403 350.274048 345.264331
11 0.45 431.637894 426.134271 420.662881 415.202987 409.734875 404.239922 398.700655 393.100789 387.425251
12 0.5 478.129951 472.075209 466.032607 459.983487 453.910176 447.796055 441.625591 435.384378 429.059145
13 0.55 523.873268 517.285198 510.689413 504.069281 497.409128 490.694283 483.911113 477.047044 470.090565
14 0.6 568.778912 561.677293 554.548395 547.377555 540.151033 532.856054 525.480827 518.014558 510.447451
15 0.65 612.763186 605.169605 597.529525 589.830179 582.059697 574.207132 566.262474 558.216649 550.061519
16 0.7 655.7481 647.685753 639.558081 631.354134 623.063835 614.677994 606.188309 597.587364 588.868614
17 0.75 697.661758 689.155243 680.565018 671.881864 663.097416 654.204159 645.195426 636.065384 626.809013
18 0.8 738.438667 729.51377 720.487263 711.35157 702.099947 692.726469 683.226022 673.594278 663.827671
19 0.85 778.019972 768.703447 759.267942 749.707427 740.016685 730.191293 720.227602 710.122707 699.874419
20 0.9 816.35361 806.672962 796.856534 786.899741 776.798797 766.550685 756.153132 745.604572 734.904109
21 0.95 853.394385 843.377654 833.208949 822.885029 812.403437 801.762466 790.961126 779.999101 768.876705
22 1 889.103974 878.779525 868.287549 857.626044 846.793778 835.790258 824.615682 813.270891 801.757325

View File

@@ -1,19 +1,30 @@
def turbine_flux(p,LA,p_exp,cubic_coeff,quadratic_coeff,linear_coeff,const_coeff): from matplotlib.pyplot import fill
return (p*1e-5)**p_exp*(cubic_coeff*LA**3+quadratic_coeff*LA**2+linear_coeff*LA+const_coeff) import numpy as np
from scipy.interpolate import interp2d
#importing pressure conversion function
import sys
import os
current = os.path.dirname(os.path.realpath(__file__))
parent = os.path.dirname(current)
sys.path.append(parent)
from functions.pressure_conversion import pressure_conversion
class Francis_turbine_class: class Francis_turbine_class:
def __init__(self): def __init__(self,CSV_name='Durchflusskennlinie.csv'):
pass self.raw_csv = np.genfromtxt(CSV_name,delimiter=',')
def extract_csv(self,CSV_pressure_unit='bar'):
self.raw_ps_vec,_ = pressure_conversion(self.raw_csv[0,1:],CSV_pressure_unit,'Pa')
self.raw_LA_vec = self.raw_csv[1:,0]
self.raw_Qs_mat = self.raw_csv[1:,1:]
def get_Q_fun(self):
Q_fun = interp2d(self.raw_ps_vec,self.raw_LA_vec,self.raw_Qs_mat,bounds_error=False,fill_value=None)
return Q_fun
def set_turbine_flux_parameters(self,p_exp,cubic_coeff,quadratic_coeff,linear_coeff,const_coeff):
# extracted from the Muschelkurve of the Turbine and used to calculate the turbine flux for a given pressure
self.p_exp = p_exp
self.cubic_coeff = cubic_coeff
self.quadratic_coeff = quadratic_coeff
self.linear_coeff = linear_coeff
self.const_coeff = const_coeff
def get_turbine_flux(self,pressure,Leitapparatöffnung):
self.flux = turbine_flux(pressure,Leitapparatöffnung,self.p_exp,self.cubic_coeff,self.quadratic_coeff,self.linear_coeff,self.const_coeff)
return self.flux

File diff suppressed because one or more lines are too long

308
Untertweng.ipynb Normal file
View File

@@ -0,0 +1,308 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from functions.pressure_conversion import pressure_conversion\n",
"from Ausgleichsbecken.Ausgleichsbecken_class_file import Ausgleichsbecken_class\n",
"from Druckrohrleitung.Druckrohrleitung_class_file import Druckrohrleitung_class"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"#define constants\n",
"\n",
"# physics\n",
"g = 9.81 # gravitational acceleration [m/s²]\n",
"rho = 1000. # density of water [kg/m³]\n",
"\n",
"# pipeline\n",
"L = 1000. # length of pipeline [m]\n",
"D = 1. # pipe diameter [m]\n",
"A_pipe = D**2/4*np.pi # pipeline area\n",
"h_pipe = 200 # hydraulic head without reservoir [m] \n",
"alpha = np.arcsin(h_pipe/L) # Höhenwinkel der Druckrohrleitung \n",
"n = 50 # number of pipe segments in discretization\n",
"# consider replacing Q0 with a vector be be more flexible in initial conditions\n",
"Q0 = 2. # initial flow in whole pipe [m³/s]\n",
"v0 = Q0/A_pipe # initial flow velocity [m/s]\n",
"f_D = 0.01 # Darcy friction factor\n",
"c = 400. # propagation velocity of the pressure wave [m/s]\n",
"# consider prescribing a total simulation time and deducting the number of timesteps from that\n",
"nt = 500 # number of time steps after initial conditions\n",
"\n",
"# derivatives of the pipeline constants\n",
"dx = L/n # length of each pipe segment\n",
"dt = dx/c # timestep according to method of characterisitics\n",
"nn = n+1 # number of nodes\n",
"initial_level = 20. # water level in upstream reservoir [m]\n",
"p0 = rho*g*initial_level-v0**2*rho/2\n",
"pl_vec = np.arange(0,nn*dx,dx) # pl = pipe-length. position of the nodes on the pipeline\n",
"t_vec = np.arange(0,nt+1)*dt # time vector\n",
"h_vec = np.arange(0,n+1)*h_pipe/n # hydraulic head of pipeline at each node \n",
"v_init = np.full(nn,Q0/(D**2/4*np.pi)) # initial velocity distribution in pipeline\n",
"p_init = (rho*g*(initial_level+h_vec)-v_init**2*rho/2)-(f_D*pl_vec/D*rho/2*v_init**2) # ref Wikipedia: Darcy Weisbach\n",
"\n",
"\n",
"# reservoir\n",
"# replace influx by vector\n",
"initial_influx = 0. # initial influx of volume to the reservoir [m³/s]\n",
"initial_outflux = Q0 # initial outflux of volume from the reservoir to the pipeline [m³/s]\n",
"initial_pipeline_pressure = p0 # Initial condition for the static pipeline pressure at the reservoir (= hydrostatic pressure - dynamic pressure) \n",
"initial_pressure_unit = 'Pa' # DO NOT CHANGE! for pressure conversion in print statements and plot labels \n",
"conversion_pressure_unit = 'bar' # for pressure conversion in print statements and plot labels\n",
"area_base = 20. # total base are of the cuboid reservoir [m²] \n",
"area_outflux = A_pipe # outlfux area of the reservoir, given by pipeline area [m²]\n",
"critical_level_low = 0. # for yet-to-be-implemented warnings[m]\n",
"critical_level_high = np.inf # for yet-to-be-implemented warnings[m]\n",
"\n",
"# make sure e-RK4 method of reservoir has a small enough timestep to avoid runaway numerical error\n",
"nt_eRK4 = 1000 # number of simulation steps of reservoir in between timesteps of pipeline \n",
"simulation_timestep = dt/nt_eRK4\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Ideas for checks after constant definitions: \n",
"\n",
"- Check that the initial pressure is not negative:\n",
" - may happen, if there is too little hydraulic head to create the initial flow conditions with the given friction\n",
"<br>\n",
"<br>\n",
"- plausbility checks?\n",
" - area > area_outflux ?\n",
" - propable ranges for parameters?\n",
" - angle and height/length fit together?\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [],
"source": [
"# create objects\n",
"\n",
"V = Ausgleichsbecken_class(area_base,area_outflux,critical_level_low,critical_level_high,simulation_timestep)\n",
"V.set_initial_level(initial_level) \n",
"V.set_influx(initial_influx)\n",
"V.set_outflux(initial_outflux)\n",
"V.set_pressure(initial_pipeline_pressure,initial_pressure_unit,conversion_pressure_unit)\n",
"\n",
"pipe = Druckrohrleitung_class(L,D,n,alpha,f_D)\n",
"pipe.set_pressure_propagation_velocity(c)\n",
"pipe.set_number_of_timesteps(nt)\n",
"pipe.set_initial_pressure(p_init,initial_pressure_unit,conversion_pressure_unit)\n",
"pipe.set_initial_flow_velocity(v_init)\n",
"\n",
"# display the attributes of the created reservoir and pipeline object\n",
"# V.get_info(full=True)\n",
"# pipe.get_info()"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"# initialization for timeloop\n",
"\n",
"# prepare the vectors in which the pressure and velocity distribution in the pipeline from the previous timestep are stored\n",
"v_old = v_init.copy()\n",
"p_old = p_init.copy()\n",
"\n",
"# prepare the vectors in which the temporal evolution of the boundary conditions are stored\n",
" # keep in mind, that the velocity at the turbine and the pressure at the reservoir are set manually and\n",
" # through the time evolution of the reservoir respectively \n",
" # the pressure at the turbine and the velocity at the reservoir are calculated from the method of characteristics\n",
"v_boundary_res = np.empty_like(t_vec)\n",
"v_boundary_tur = np.empty_like(t_vec)\n",
"p_boundary_res = np.empty_like(t_vec)\n",
"p_boundary_tur = np.empty_like(t_vec)\n",
"\n",
"# prepare the vectors that store the temporal evolution of the level in the reservoir\n",
"level_vec = np.full(nt+1,initial_level) # level at the end of each pipeline timestep\n",
"level_vec_2 = np.empty([nt_eRK4]) # level throughout each reservoir timestep-used for plotting and overwritten afterwards\n",
"\n",
"# set the boudary conditions for the first timestep\n",
"v_boundary_res[0] = v_old[0]\n",
"v_boundary_tur[0] = v_old[-1] \n",
"v_boundary_tur[1:] = 0 # instantaneous closing\n",
"# v_boundary_tur[0:20] = np.linspace(v_old[-1],0,20) # overwrite for finite closing time - linear case\n",
"# const = int(np.min([100,round(nt/1.1)]))\n",
"# v_boundary_tur[0:const] = v_old[1]*np.cos(t_vec[0:const]*2*np.pi/5)**2\n",
"p_boundary_res[0] = p_old[0]\n",
"p_boundary_tur[0] = p_old[-1]\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib qt5\n",
"# time loop\n",
"\n",
"# create a figure and subplots to display the velocity and pressure distribution across the pipeline in each pipeline step\n",
"fig1,axs1 = plt.subplots(2,1)\n",
"fig1.suptitle(str(0) +' s / '+str(round(t_vec[-1],2)) + ' s' )\n",
"axs1[0].set_title('Pressure distribution in pipeline')\n",
"axs1[1].set_title('Velocity distribution in pipeline')\n",
"axs1[0].set_xlabel(r'$x$ [$\\mathrm{m}$]')\n",
"axs1[0].set_ylabel(r'$p$ ['+conversion_pressure_unit+']')\n",
"axs1[1].set_xlabel(r'$x$ [$\\mathrm{m}$]')\n",
"axs1[1].set_ylabel(r'$v$ [$\\mathrm{m} / \\mathrm{s}$]')\n",
"lo_00, = axs1[0].plot(pl_vec,pressure_conversion(pipe.p_old,initial_pressure_unit, conversion_pressure_unit)[0],marker='.')\n",
"lo_01, = axs1[1].plot(pl_vec,pipe.v_old,marker='.')\n",
"axs1[0].autoscale()\n",
"axs1[1].autoscale()\n",
"# displaying the reservoir level within each pipeline timestep\n",
"# axs1[2].set_title('Level reservoir')\n",
"# axs1[2].set_xlabel(r'$t$ [$\\mathrm{s}$]')\n",
"# axs1[2].set_ylabel(r'$h$ [m]')\n",
"# lo_02, = axs1[2].plot(level_vec_2)\n",
"# axs1[2].autoscale()\n",
"fig1.tight_layout()\n",
"fig1.show()\n",
"plt.pause(1)\n"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [],
"source": [
"# loop through time steps of the pipeline\n",
"for it_pipe in range(1,pipe.nt+1):\n",
"\n",
"# for each pipeline timestep, execute nt_eRK4 timesteps of the reservoir code\n",
" # set initial conditions for the reservoir time evolution calculted with e-RK4\n",
" V.pressure = p_old[0]\n",
" V.outflux_vel = v_old[0]\n",
" # calculate the time evolution of the reservoir level within each pipeline timestep to avoid runaway numerical error\n",
" for it_res in range(nt_eRK4):\n",
" V.e_RK_4() # call e-RK4 to update outflux\n",
" V.level = V.update_level(V.timestep) # \n",
" V.set_volume() # update volume in reservoir\n",
" level_vec_2[it_res] = V.level # save for plotting\n",
" if (V.level < critical_level_low) or (V.level > critical_level_high): # make sure to never exceed critical levels\n",
" i_max = it_pipe # for plotting only calculated values\n",
" break \n",
" level_vec[it_pipe] = V.level \n",
"\n",
" # set boundary conditions for the next timestep of the characteristic method\n",
" p_boundary_res[it_pipe] = rho*g*V.level-V.outflux_vel**2*rho/2\n",
" v_boundary_res[it_pipe] = v_old[1]+1/(rho*c)*(p_boundary_res[it_pipe]-p_old[1])-f_D*dt/(2*D)*abs(v_old[1])*v_old[1] \\\n",
" +dt*g*np.sin(alpha)\n",
"\n",
" # the the boundary conditions in the pipe.object and thereby calculate boundary pressure at turbine\n",
" pipe.set_boundary_conditions_next_timestep(v_boundary_res[it_pipe],p_boundary_res[it_pipe],v_boundary_tur[it_pipe])\n",
" p_boundary_tur[it_pipe] = pipe.p_boundary_tur\n",
"\n",
" # perform the next timestep via the characteristic method\n",
" pipe.timestep_characteristic_method()\n",
"\n",
" # plot some stuff\n",
" # remove line-objects to autoscale axes (there is definetly a better way, but this works ¯\\_(ツ)_/¯ )\n",
" lo_00.remove()\n",
" lo_01.remove()\n",
" # lo_02.remove()\n",
" # plot new pressure and velocity distribution in the pipeline\n",
" lo_00, = axs1[0].plot(pl_vec,pressure_conversion(pipe.p_old,initial_pressure_unit, conversion_pressure_unit)[0],marker='.',c='blue')\n",
" lo_01, = axs1[1].plot(pl_vec,pipe.v_old,marker='.',c='blue')\n",
" # lo_02, = axs1[2].plot(level_vec_2,c='blue')\n",
" fig1.suptitle(str(round(t_vec[it_pipe],2))+ ' s / '+str(round(t_vec[-1],2)) + ' s' )\n",
" fig1.canvas.draw()\n",
" fig1.tight_layout()\n",
" fig1.show()\n",
" plt.pause(0.00001) \n",
"\n",
" # prepare for next loop\n",
" p_old = pipe.p_old\n",
" v_old = pipe.v_old \n",
"\n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [],
"source": [
"# plot time evolution of boundary pressure and velocity as well as the reservoir level\n",
"\n",
"fig2,axs2 = plt.subplots(3,2)\n",
"axs2[0,0].plot(t_vec,pressure_conversion(p_boundary_res,initial_pressure_unit, conversion_pressure_unit)[0])\n",
"axs2[0,1].plot(t_vec,v_boundary_res)\n",
"axs2[1,0].plot(t_vec,pressure_conversion(p_boundary_tur,initial_pressure_unit, conversion_pressure_unit)[0])\n",
"axs2[1,1].plot(t_vec,v_boundary_tur)\n",
"axs2[2,0].plot(t_vec,level_vec)\n",
"axs2[0,0].set_title('Pressure reservoir')\n",
"axs2[0,1].set_title('Velocity reservoir')\n",
"axs2[1,0].set_title('Pressure turbine')\n",
"axs2[1,1].set_title('Velocity turbine')\n",
"axs2[2,0].set_title('Level reservoir')\n",
"axs2[0,0].set_xlabel(r'$t$ [$\\mathrm{s}$]')\n",
"axs2[0,0].set_ylabel(r'$p$ ['+conversion_pressure_unit+']')\n",
"axs2[0,1].set_xlabel(r'$t$ [$\\mathrm{s}$]')\n",
"axs2[0,1].set_ylabel(r'$v$ [$\\mathrm{m}/\\mathrm{s}$]')\n",
"axs2[1,0].set_xlabel(r'$t$ [$\\mathrm{s}$]')\n",
"axs2[1,0].set_ylabel(r'$p$ ['+conversion_pressure_unit+']')\n",
"axs2[1,1].set_xlabel(r'$t$ [$\\mathrm{s}$]')\n",
"axs2[1,1].set_ylabel(r'$v$ [$\\mathrm{m}/\\mathrm{s}$]')\n",
"axs2[2,0].set_xlabel(r'$t$ [$\\mathrm{s}$]')\n",
"axs2[2,0].set_ylabel(r'$h$ [m]')\n",
"axs2[2,1].axis('off')\n",
"fig2.tight_layout()\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.13 ('Georg_DT_Slot3')",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "84fb123bdc47ab647d3782661abcbe80fbb79236dd2f8adf4cef30e8755eb2cd"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

20
untertweng.txt Normal file
View File

@@ -0,0 +1,20 @@
L = 535 m dn 800 mm
478 m dn 1000 mm
Ersatzdurchmesser
h_pipe
h 851.78 Pegel + Leitungsgefälle
Leitungsgefälle: 113
Fläche 4.25x10.5 + 30m² = 74 m²
Pegelminimum: 851.18 m
Unterwasserpegel 738.56
Gesamtfallhöhe = 851.78-738.56
Rohrreibung: 0.014 f_D = lambda
c = 500 m/s
Q_0 = 100%*0.75+30%*0.75
Q_extrem = 30%*0.75