<jupyter_start><jupyter_text>Script to size Kaplan turbine runnerThis script implements the sizing methodology as presented by Abeykoon & Hantsch [1].[1] <NAME>., & <NAME>. (2017). [Design and analysis of a Kaplan turbine runner wheel](https://doi.org/10.11159/htff17.151). Proceedings of the 3rd World Congress on Mechanical, Chemical, and Material Engineering (MCM'17) Rome, Italy, June 8–10, 2017 ISSN: 2369-8136 DOI: 10.11159/htff17.151 Step 0 - Defining constantsSome constants such as PI need to be defined for the calculations.<jupyter_code>import math
# Some constants
g = 9.81 # Gravitational acceleration 9.81 m.s-2
PI = math.pi # PI
patm = 101300 # Atmospheric pressure in Pa
pv = 1279 # Vapour pressure of water at 15 deg Celsius in Pa
rho = 999 # Density of water at 15 deg Celsius in kg.m-3<jupyter_output><empty_output><jupyter_text>Step 1 - Define main design characteristicsThe main design characteristics of a turbine are:- _H_ head in m, defined as the height difference between the headwater and the tailwater;- _Q_ volumetric flow rate in m3.s-1, is the assumed amount of water flowing through the turbine;- _etat_ - expected turbine efficiency.<jupyter_code># Set head H, volumetric flow rate Q and assumed turbine efficiency according to your preferences
H = 6 # in m
Q = 5 # in m3.s-1
etat = 0.94 # dimensionless

if H > 20:
    print( "CAUTION: You have high head conditions, consider using a different turbine type such as Francis or Pelton." )<jupyter_output><empty_output><jupyter_text>Step 2 - Choose SigmaDependend on the head of the intended turbine placement, turbine type and a characteristic dimensionless parameter _sigma_ can be chosen. This can be done graphically looking up figure 3 in [[1]](https://doi.org/10.11159/htff17.151) or by piecewise linear interpolation as done below.The original source of figure 3 in [[1]](https://doi.org/10.11159/htff17.151) original source [[2]](https://doi.org/10.1007/978-3-8351-9035-1).[2] <NAME>, [Strömungsmaschinen – Hydraulische und thermische Kraft- und Arbeitsmaschinen](https://doi.org/10.1007/978-3-8351-9035-1), Springer, Germany, 2006.<jupyter_code># Interpolates sigma value from head
import numpy as np

xp = [0.023,0.037,0.047,0.063,0.094,0.125,0.153,0.182,0.223,
          0.260,0.286,0.321,0.358,0.383,0.419,0.464,0.534,0.604,
          0.694,0.784,0.900,1.005,1.119,1.230,1.316,1.408,1.487,
          1.547,1.570,1.580,1.600]

fp = [1429.267,1096.191,815.387,651.425,499.617,442.034,346.013,282.134,220.848,172.874,
            140.959,118.509,98.623,85.494,71.148,62.309,55.127,49.779,42.280,35.186,28.399,22.458,
            17.224,13.761,10.882,8.177,6.401,4.909,4.086,2.000,1.000]

sigma = np.interp( H , list( reversed( fp ) ) , list( reversed( xp ) ) )
print( "The dimensionless number sigma for runner is" , format( sigma ,".3f" ) )<jupyter_output>The dimensionless number sigma for runner is 1.503<jupyter_text>Hack to reproduce Abeykoon and Hatsch<jupyter_code># Setting value of sigma to 1.45 as stated by Abeykoon and Hatsch
sigma = 1.45
sigma<jupyter_output><empty_output><jupyter_text>Step 3 - Calculate rotational speed and specific speedThe rotational _N_ speed of the turbine in revolutions per minute can be obtained from the following equation [2]:![s](https://latex.codecogs.com/svg.latex?N=\frac{\sigma*(2*g*H)^{0.75}}{2*\sqrt{\pi*Q}}*60)<jupyter_code># Calculated using Eq. (2) from [1]

N = ( sigma * math.pow( 2 * g * H , 0.75 ) )/( 2 * math.sqrt(PI * Q) ) * 60

print( "The rotational speed of the runner is " , format( N ,".3f" ) , " min-1" )<jupyter_output>The rotational speed of the runner is  392.254  min-1<jupyter_text>The specific speed _Ns_ of the runner is calculated from equation![s](https://latex.codecogs.com/svg.latex?N_s=\frac{N*\sqrt{Q}}{H^{0.75}})<jupyter_code># Calculated using Eq. (3) from [1]

Ns = ( N * math.sqrt( Q ) ) / math.pow( H , 0.75 )

print( "The specific speed of the runner is " , format( Ns ,".3f" ) , " 1/min" )

if Ns > 250:
    print( "CAUTION: Runners with a specific speed larger then 250 tend to have bad performance; consider reducing Q by creating two identical turbines or change N by using a gear box." )<jupyter_output>The specific speed of the runner is  228.791  1/min<jupyter_text>Step 4 - Determine Hub-Tip-Ratio, number of blades and diameter numberUsing the sigma parameter again from a graph (Figure 6 in [[1]](https://doi.org/10.11159/htff17.151); original source [[2]](https://doi.org/10.1007/978-3-8351-9035-1)) the following values can be obtained:- The hub-tip ratio _Dh_/_Dt_ in m/m, where is the hub diameter and Dt is the diameter and the tip- The number of blades _z_ unitless- The diameter number _delta_ unitless, a dimensionless specific parameter<jupyter_code># Interpolates hub tip ratio htr value from sigma
xp = [0.595,0.663,0.734,0.804,0.871,0.947,1.008,1.078,1.140,1.197,1.253,1.313,1.380,1.430,1.488,1.542,1.587,1.649]

fp = [0.546,0.531,0.511,0.501,0.489,0.475,0.463,0.453,0.446,0.437,0.432,0.426,0.419,0.416,0.410,0.403,0.401,0.396]

htr = np.interp( sigma , xp , fp )
print( "The hub tip ratio is" , format( htr , ".3f" ) )
# Determines number of blades z
if 0.60 <= sigma <= 0.85:
    print( "The number of blades suitable can be 8" )
    z = 8
if 0.60 <= sigma <= 1.05:
    print( "The number of blades suitable can be 7" )
    z = 7
if 0.75 <= sigma <= 1.20:
    print( "The number of blades suitable can be 6" )
    z = 6
if 0.90 <= sigma <= 1.41:
    print( "The number of blades suitable can be 5" )
    z = 5
if 1.2  <= sigma <= 1.65:
    print( "The number of blades suitable can be 4" )
    z = 4

print( "Script picked lowest possible number of blades:" , z )
# Interpolates delta from sigma

xp = [0.595,0.638,0.697,0.761,0.820,0.865,0.912,
      0.957,1.021,1.057,1.095,1.142,1.190,1.246,
      1.302,1.351,1.401,1.465,1.526,1.582,1.634]

fp = [2.002,1.947,1.884,1.816,1.754,1.711,1.665,
      1.614,1.575,1.543,1.519,1.479,1.446,1.423,
      1.391,1.361,1.343,1.301,1.285,1.253,1.236]

delta = np.interp( sigma , xp , fp )
print( "The specific parameter delta is" , format( delta ,".3f" ) )<jupyter_output>The specific parameter delta is 1.311<jupyter_text>Hack to reproduce Abeykoon and Hatsch<jupyter_code># Changing to values stated by Abeykoon and Hatsch
htr = 0.4
delta = 1.3
z = 4<jupyter_output><empty_output><jupyter_text>Step 5 - Determine hub and tip diameterFrom the values obtained in the previous step _Dh_ the hub diameter and _Dt_ is the diameter and the tip can be calculated as follows.![s](https://latex.codecogs.com/svg.latex?D_t=\frac{2*\delta}{\sqrt{\pi}}*\sqrt[4]{\frac{Q^2}{2*g*H}})![s](https://latex.codecogs.com/svg.latex?D_h=\frac{D_h}{D_t}*D_t)![s](https://latex.codecogs.com/svg.latex?H_{smax}=\frac{p_{atm}}{\rho*g}-\frac{p_v}{\rho*g}-\sigma_c*H)<jupyter_code>Dt = (2 * delta) / math.sqrt( PI ) * math.pow( ( math.pow( Q , 2 ) / (2 * g * H) ) , 1/4 )
print( "The diameter at the tip is" , format( Dt , ".3f" ) , " m" )
Dh = htr * Dt
print( "The diameter at the hub is" , format( Dh , ".3f" ) , " m" )
Hsmax = patm / ( rho * g) - pv / ( rho * g ) - 1.3 * H
print( "The maximal suction head is" , format( Hsmax , ".3f" ) , " m" )
Hs = Hsmax - 0.2
print( "Suction head is set to" , format( Hs , ".3f" ) , " m" )<jupyter_output>The maximal suction head is 2.406  m
Suction head is set to 2.206  m<jupyter_text>Hack to reproduce Abeykoon and Hatsch<jupyter_code># Setting values as stated by Abeykoon and Hatsch
Hs = 2
H1 = -0.82
H2 = 4.82<jupyter_output><empty_output><jupyter_text>Step 7 - Turbine blade designWith the obtained values the blade design can be calculated as described in [1]. The values are calculated for five different diameters: _Dt_, _1_, _2_, _3_, Dh. In addition, the values are calculated at the inlet (index 1), at the blade middle (index inf) and at the outlet (index 2).- _u_ - Rotational speed in m.s-1- _wm_ - Relative velocity in meridian direction in m.s-1- _cuinf_ - Tangential velocity of the fluid flow in m.s-1- _deltawu_ - Difference of tangential velocity in m.s-1- _wuinf_ - Relative velocity in the tangential direction in m.s-1- _winf_ - Relative velocity at the middle of the blade in m.s-1- _betainf_ - Angle at the middle of the blade in degree- _t_ - Blade partition in m- _s_ - chord length in m, s/t ratios as given in [1] Setup of empty data structure (pandas df)<jupyter_code># Setup empty pandas df
import pandas as pd

diameterNames = [ "t" , "1", "2" , "3" , "h" ]
diameterValues = [ Dt , 0.846 , 0.697 , 0.548 , Dh ]
diameterStoTRatios = [ 0.75 , 0.888 , 1.025 , 1.163 , 1.3 ]

setup_dict = {
     "D": diameterValues ,
     "u": [ None , None , None , None , None ] ,
     "cu1": [ None , None , None , None , None ] ,
     "cu2": [ None , None , None , None , None ] ,
     "cuinf" : [ None , None , None , None , None ] ,
     "wu1" : [ None , None , None , None , None ] ,
     "wu2" : [ None , None , None , None , None ] ,
     "winf" : [ None , None , None , None , None ] ,
     "wm" : [ None , None , None , None , None ] ,
     "wuinf" : [ None , None , None , None , None ] ,
     "deltawu" : [ None , None , None , None , None ] ,
     "betainf" : [ None , None , None , None , None ] ,
     "alpha" : [ None , None , None , None , None ] ,
     "beta1" : [ None , None , None , None , None ] ,
     "beta2" : [ None , None , None , None , None ] ,
     "StoTRatio" : diameterStoTRatios ,
     "t" : [ None , None , None , None , None ] ,
     "s" : [ None , None , None , None , None ]
    }

# Setup df
df = pd.DataFrame.from_dict( setup_dict , orient = 'index' , columns = diameterNames )
df.head( 18 )<jupyter_output><empty_output><jupyter_text>Calculate rotational speed u at different diameters in m.s-1![s](https://latex.codecogs.com/svg.latex?u=\frac{\pi*D*N}{60})<jupyter_code>for diameterName in diameterNames:
    D = df.loc[ "D" , diameterName ]
    df.at[ "u" , diameterName ] = PI * D * N / 60
df.head( 18 )<jupyter_output><empty_output><jupyter_text>Calculate cu1 and cu2 in m.s-1<jupyter_code># Calculate cu1
print( "Calculation of cu1 not yet implemented" )
# Calculate cu2
print( "Calculation of cu2 not yet implemented" )<jupyter_output>Calculation of cu1 not yet implemented
Calculation of cu2 not yet implemented<jupyter_text>Calculate tangential velocity cuinf in m.s-1![s](https://latex.codecogs.com/svg.latex?c_{u\infty}=\frac{(H-H_s)*g}{u})<jupyter_code>for diameterName in diameterNames:
    u = df.loc[ "u" , diameterName ]
    df.at[ "cuinf" , diameterName ] = ( ( H - Hs ) * g ) / u
print( "\n Calculated tangential velocity of the fluid flow at all diameters in m.s-1:" )
df.head( 18 )<jupyter_output>Calculated tangential velocity of the fluid flow at all diameters in m.s-1:<jupyter_text>Calculate wu1 and wu2 (not yet implemented)<jupyter_code># Calculate wu1
# Calculate wu2<jupyter_output><empty_output><jupyter_text>Calculate wuinf at all diameters in m.s-1:![s](https://latex.codecogs.com/svg.latex?w_{u\infty}=c_{u\infty}-u)<jupyter_code># Calculate wuinf
for diameterName in diameterNames:
    u = df.loc[ "u" , diameterName ]
    cuinf = df.loc[ "cuinf" , diameterName ]
    df.at[ "wuinf" , diameterName ] = cuinf - u
print( "Calculated wuinf at all diameters in m.s-1:" )
df.head( 18 )<jupyter_output>Calculated wuinf at all diameters in m.s-1:<jupyter_text>Calculate wm relative velocity in meridian direction at all diameters in m.s-1![s](https://latex.codecogs.com/svg.latex?w_{m}=\frac{Q}{\frac{\pi}{4}*(D_t^2-D_h^2)})<jupyter_code># Calculate wm
for diameterName in diameterNames:
    Dt = df.loc[ "D" , "t" ]
    Dh = df.loc[ "D" , "h" ]
    df.at[ "wm" , diameterName ] = Q / ( PI / 4 * ( math.pow( Dt , 2 ) - math.pow( Dh , 2 ) ) )
print( "Calculated wm relative velocity in meridian direction at all diameters in m.s-1:" )
df.head( 18 )<jupyter_output>Calculated wm relative velocity in meridian direction at all diameters in m.s-1:<jupyter_text>Calculate _winf_ relative velocity at the middle of the blade at all diameters in m.s-1![s](https://latex.codecogs.com/svg.latex?w_{\infty}=\sqrt{w_{u\infty}^2+w_m^2})<jupyter_code># Calculate winf
for diameterName in diameterNames:
    wuinf = df.loc[ "wuinf" , diameterName ]
    wm = df.loc[ "wm" , diameterName ]
    df.at[ "winf" , diameterName ] = math.pow( ( math.pow( wuinf , 2 ) + math.pow( wm , 2 ) ) , 0.5 )
print( "\n Calculated relative velocity at the middle of the blade at all diameters in m.s-1:" )
df.head( 18 )<jupyter_output>Calculated relative velocity at the middle of the blade at all diameters in m.s-1:<jupyter_text>Calculate _deltawu_ difference of tangential velocity of the fluid flow![s](https://latex.codecogs.com/svg.latex?\Delta_{wu}=\frac{H*g*\eta_t}{u})<jupyter_code># Calculate deltawu difference of tangential velocity of the fluid flow
for diameterName in diameterNames:
    u = df.loc[ "u" , diameterName ]
    df.at[ "deltawu" , diameterName ] = ( H * g * etat ) / u
print( "\n Calculated difference of tangential velocity of the fluid flow at all diameters in m.s-1:" )
df.head( 18 )<jupyter_output>Calculated difference of tangential velocity of the fluid flow at all diameters in m.s-1:<jupyter_text>Calculate _betainf_ angle at the middle of the blade in degree at all diameters![s](https://latex.codecogs.com/svg.latex?\beta_{\infty}=90-arctan\left(\frac{w_{u\infty}}{w_m}\right)*\frac{180}{\pi})<jupyter_code># Calculate betainf angle at the middle of the blade at all diameters
for diameterName in diameterNames:
    wuinf = df.loc[ "wuinf" , diameterName ]
    wm = df.loc[ "wm" , diameterName ]
    df.at[ "betainf" , diameterName ] = 90 - math.atan( wuinf / wm ) * 180 / PI
print( "\n Calculated angle at the middle of the blade in degree:" )
df.head( 18 )<jupyter_output>Calculated angle at the middle of the blade in degree:<jupyter_text>alpha, beta1, beta2 not yet implemented<jupyter_code># Calculate alpha at all diameters

# Calculate beta1 at all diameters
#for diameterName in diameterNames:
#    wu1 = df.loc[ "wu1" , diameterName ]
#    wm = df.loc[ "wm" , diameterName ]
#    df.at[ "beta1" , diameterName ] = 90 - math.atan( wu1 / wm ) * 180 / PI
#print( "\n Calculated angle at the inlet 1 of the blade in degree:" )
#print( df )

# Calculate beta2 at all diameters
#for diameterName in diameterNames:
#    wu2 = df.loc[ "wu2" , diameterName ]
#    wm = df.loc[ "wm" , diameterName ]
#    df.at[ "beta2" , diameterName ] = 90 - math.atan( wu2 / wm ) * 180 / PI
#print( "\n Calculated angle at the outlet 2 of the blade in degree:" )
#print( df )<jupyter_output><empty_output><jupyter_text>Calculate blade partition t in m at all diameters![s](https://latex.codecogs.com/svg.latex?t=\frac{\pi*D}{z})<jupyter_code>for diameterName in diameterNames:
    D = df.loc[ "D" , diameterName ]
    df.at[ "t" , diameterName ] = ( PI * D ) / z
print( "Calculated blade partition t at all diameters in m:" )
df.head( 18 )<jupyter_output>Calculated blade partition t at all diameters in m:<jupyter_text>Calculate chord length in m at all diameters![s](https://latex.codecogs.com/svg.latex?s=\frac{s}{t}*t)<jupyter_code># Calculate chord length in m at all diameters
for diameterName in diameterNames:
    stratio = df.loc[ "StoTRatio" , diameterName ]
    t       = df.loc[ "t" , diameterName ]
    df.at[ "s" , diameterName ] = stratio * t
print( "Calculated chord length s at all diameters in m:" )
df.head( 18 )<jupyter_output>Calculated chord length s at all diameters in m:
{'fraction_non_alphanumeric': 0.138872673023286, 'fraction_numerical': 0.07063631056625802, 'mean_word_length': 3.8377784750549107, 'pattern_counts': {'":': 4, '<': 92, '<?xml version=': 0, '>': 84, 'https://': 21, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '265436', 'license': 'Apache-2.0', 'n_tokens_mistral': 6398, 'n_tokens_neox': 5585, 'n_words': 1725, 'path': 'script.ipynb', 'repo_name': 'GeorgFerdinandSchneider/KaplanTurbineRunnerSizingTool', 'size': '15428'}