pandapipes
pandapipes copied to clipboard
Hydraulics of hot water in pipe: Unexpected effects of temperatures on pressure drop
Describe the bug When simulating hot water in a pipe via pp.pipeflow(net, mode="all"), the results for velocity and re-Number => lambda and in final consequence the pressure drop have unexpected (in)dependencies on the temperatures. Probably, this comes from the way density and viscosity are calculated and the fact that hydraulic and thermal calculation are fully separated.
-
Density Apparently the density does not depend at all on the temperatures in the net. It is apparently set at t=273.15 K (999.9 kg/m³). In consequence, the flow velocity in res_pipes does not at all depend on the temperatures in the net, it just depends on mdot.
-
Viscosity The viscosity seems to be calculated according to tfluid_k at junctions - or, if applicable, the temperature of external grid. In consequence, reynolds numbers => lambda => pressure drop in the pipes depend on these temperatures.
To Reproduce I set up an example, external grid => pipe1 => pipe2 => sink, with four different configurations of temperatures (tfluid_k at junctions and the t_k from the external grid are either 300 or 350).
import math
import pandas as pd
import pandapipes as pp
def example_hot_water():
net = pp.create_empty_network("network", fluid="water")
mdot_kg_per_s = 10
temps_k = [300, 350]
d_pipe = 0.1
l_pipe = 1
for t_fluid in temps_k:
for t_j_k in temps_k:
create_source_2pipes_sink(net,t_source_k=t_fluid, t_junctions_k=t_j_k,
pipe_name_suffix=f"_tj_{t_j_k}_tf_{t_fluid}",
mdot_kg_per_s=mdot_kg_per_s, diameter_m=d_pipe, length_km=l_pipe)
pp.pipeflow(net, mode="all", friction_model="colebrook")
results = pd.DataFrame.join(
net.pipe.loc[:,["name"]],
net.res_pipe.loc[:,["t_from_k","v_mean_m_per_s","reynolds","lambda"]]
)
results.loc[:,'dp'] = net.res_pipe.p_from_bar - net.res_pipe.p_to_bar
# Density (for velocity calculation) is calculated at 273.15 K, which is not the same as the actual temperature of the fluid
velocities_equal = net.res_pipe['v_mean_m_per_s'].nunique() == 1
print(f"All flow velocities equal: {velocities_equal}")
rho_from_v_mean = round(mdot_kg_per_s / (net.res_pipe.loc[:,"v_mean_m_per_s"] * math.pi * d_pipe**2 / 4),2)
print(f"Calculated densities from v_mean: {set(rho_from_v_mean)}")
for t_k in [273.15]+temps_k:
print(f"Actual density at {t_k} K: {net.fluid.get_density(t_k)}")
# dp is really calculated from v_mean, the default density and the various lambdas
dp_calc = net.res_pipe.loc[:,'lambda'] * l_pipe*1000 / d_pipe * 0.5 * rho_from_v_mean * net.res_pipe.loc[:,"v_mean_m_per_s"]**2 /10**5
results.loc[:,'dp_calc'] = dp_calc
print(results)
return net
def create_source_2pipes_sink(net,t_source_k, t_junctions_k, mdot_kg_per_s, length_km, diameter_m, pipe_name_suffix='', k_mm=0.1):
j1, j2, j3 = pp.create_junctions(net, nr_junctions=3, pn_bar=1, tfluid_k=t_junctions_k)
pp.create_pipe_from_parameters(net, from_junction=j1, to_junction=j2, name="pipe1"+pipe_name_suffix,
length_km=length_km, diameter_m=diameter_m, k_mm=k_mm)
pp.create_pipe_from_parameters(net, from_junction=j2, to_junction=j3, name="pipe2"+pipe_name_suffix,
length_km=length_km, diameter_m=diameter_m, k_mm=k_mm)
pp.create_ext_grid(net, junction=j1, p_bar=10, t_k=t_source_k)
pp.create_sink(net, junction=j3, mdot_kg_per_s=mdot_kg_per_s)
if __name__ == "__main__":
net = example_hot_water()
Output:
All flow velocities equal: True
Calculated densities from v_mean: {999.88}
Actual density at 273.15 K: 999.8801666666666
Actual density at 300 K: 996.49
Actual density at 350 K: 973.62
name t_from_k v_mean_m_per_s reynolds lambda \
0 pipe1_tj_300_tf_300 300.0 1.273392 149231.076504 0.021434
1 pipe2_tj_300_tf_300 300.0 1.273392 149231.076504 0.021434
2 pipe1_tj_350_tf_300 300.0 1.273392 240324.564880 0.020810
3 pipe2_tj_350_tf_300 300.0 1.273392 345613.340048 0.020473
4 pipe1_tj_300_tf_350 350.0 1.273392 240324.564880 0.020810
5 pipe2_tj_300_tf_350 350.0 1.273392 149231.076504 0.021434
6 pipe1_tj_350_tf_350 350.0 1.273392 345613.340048 0.020473
7 pipe2_tj_350_tf_350 350.0 1.273392 345613.340048 0.020473
dp dp_calc
0 1.737575 1.737575
1 1.737575 1.737575
2 1.686985 1.686985
3 1.659683 1.659683
4 1.686985 1.686985
5 1.737575 1.737575
6 1.659683 1.659683
7 1.659683 1.659683
The output demonstrates:
- v_mean_m_per_s does not depend on the temperatures and is calculated with the density at 273.15 K.
- reynolds and in consequence lambda depend on the tfluid_k at the junctions and from the external grid.
- reynolds for pipe1 has three different values: When both temperatures are low => lowest value; when one of the mentioned temperatures is high => medium value; when both temperature are high => highest value.
- reynolds for pipe2 has only two values, depending on tfluid_k at the junctions and ignores the actual fluid temperature totally. I guess, that this is an effect of using tfluid_k and t_k at external grids for the calculation of the viscosity (instead of the actual temperature of the fluid in the pipes).
- The last column in the output dataframe 'dp_calc' shows, that these unexpected values for velocity and lambda are actually used for the pressure drop calculation.
Expected behavior Use the actual temperatures of the fluid in the pipe to calculate the fluid properties and results, that depend on those (velocity, reynolds, lambda, pressure drop).
Python environment (please complete the following information):
- OS: Windows 10
- pandapipes version 0.10.0
- Note that in pandapipes version 0.9.0 the output of the above example is somewhat different: (probably related to #625) Here velocity and reynolds only depend on tfluid_k at junctions: (which is somewhat more consistent than the pp 0.10.0 behavior)
All flow velocities equal: False
Calculated densities from v_mean: {996.49, 973.62}
Actual density at 273.15 K: 999.8801666666666
Actual density at 300 K: 996.49
Actual density at 350 K: 973.62
name t_from_k v_mean_m_per_s reynolds lambda \
0 pipe1_tj_300_tf_300 300.0 1.277724 149231.076504 0.021413
1 pipe2_tj_300_tf_300 300.0 1.277724 149231.076504 0.021413
2 pipe1_tj_350_tf_300 300.0 1.307738 345613.340048 0.020463
3 pipe2_tj_350_tf_300 300.0 1.307738 345613.340048 0.020463
4 pipe1_tj_300_tf_350 350.0 1.277724 149231.076504 0.021413
5 pipe2_tj_300_tf_350 350.0 1.277724 149231.076504 0.021413
6 pipe1_tj_350_tf_350 350.0 1.307738 345613.340048 0.020463
7 pipe2_tj_350_tf_350 350.0 1.307738 345613.340048 0.020463
dp dp_calc
0 1.741814 1.741814
1 1.741814 1.741814
2 1.703636 1.703636
3 1.703636 1.703636
4 1.741814 1.741814
5 1.741814 1.741814
6 1.703636 1.703636
7 1.703636 1.703636
Additional context This issue is related to #384, and illustrates, that the fully separated hydraulic and thermal calculation as implemented now leads to confusing results.