1

这可能更像是一个算法问题,但我是用 Python 编写的。

我有一组关于管道的数据,随着它的进展,它会增加和减少高度。我的数据是两列,沿管道的测量值和该测量值的高程。我的数据集中有数万行。(这些将是列而不是行)

测量:1、2、3、4、5、6、7、8、9、10

海拔:5、7、9、15、12、13、18、14、23、9

在此脚本中,假定管道的两端都加盖。目标是计算从管道中任何一点的泄漏处排出的液体总量。压力/流速无关紧要。我试图解释的主要部分是所有的捕获/山谷(如浴室水槽中),即使在其余管道排水时,液体也会保留在其中,如下所示:

https://www.youtube.com/watch?v=o82yNzLIKYo

管道半径和泄漏位置将是用户设置的参数。

我真的在寻找正确的方向,我想尽可能自己解决这个问题。我对编程很好,但任何关于实际逻辑的建议都会有所帮助,谢谢你。 在此处输入图像描述

假设在该 中,泄漏出现在 x 轴上的点 9 处,并且管道具有已知的半径r。我试图弄清楚如何让我的脚本输出以r表示的液体总量,无论时间如何,都将被清空。如果由于管道中出现的损坏导致泄漏,空气会进来,水会流出,但不是所有的水,因为管道的不同捕获和不同的高度。

4

2 回答 2

1

如果我正确理解了这个问题,我认为这可以通过从泄漏点左右遍历管道来实现。在每个点,将当前水位与管道标高进行比较,要么导致水位保持不变的淹没点,要么形成海滩和新的干峰。插值对于计算海滩的位置是必要的。

下面显示了一个实现。算法的大部分在 traverse函数中。希望评论提供充分的描述。

#!/usr/bin/python3

import numpy as np
import matplotlib.pyplot as pp

# Positions and elevations
n = 25
h = np.random.random((n, ))
x = np.linspace(0, 1, h.size)

# Index of leak
leak = np.random.randint(0, h.size)

# Traverse a pipe with positions (x) and elevations (h) from a leak index
# (leak) in a direction (step, +1 or -1). Return the positions of the changes
# in water level (y) the elevations at these changes (g) and the water level
# values (w).
def traverse(x, h, leak, step):
    # End of the index range for the traversal
    end = h.size if step == 1 else -1
    # Initialise 1-element output arrays with values at the leak
    y, g, w = [x[leak]], [h[leak]], [h[leak]]
    # Loop from the index adjacent to the leak
    for i in range(leak + step, end, step):
        if w[-1] > h[i]:
            # The new height is less than the old water level. Location i is
            # submerged. No new points are created and the water level stays
            # the same.
            y.append(x[i])
            g.append(h[i])
            w.append(w[-1])
        else:
            # The new height is greater than the old water level. We have a
            # "beach" and a "dry peak".
            # ...
            # Calculate the location of the beach as the position where the old
            # water level intersects the pipe section from [i-step] to [i].
            # This is added as a new point. The elevation and water level are
            # the same as the old water level.
            # ...
            # The if statement is not strictly necessary. It just prevents
            # duplicate points being generated.
            if w[-1] != h[i-step]:
                t = (w[-1] - h[i-step])/(h[i] - h[i-step])
                b = x[i-step] + (x[i] - x[i-step])*t
                y.append(b)
                g.append(w[-1])
                w.append(w[-1])
            # ...
            # Add the dry peak.
            y.append(x[i])
            g.append(h[i])
            w.append(h[i])
    # Convert from list to numpy array and return
    return np.array(y), np.array(g), np.array(w)

# Traverse left and right
yl, gl, wl = traverse(x, h, leak, -1)
yr, gr, wr = traverse(x, h, leak, 1)

# Combine, reversing the left arrays and deleting the repeated start point
y = np.append(yl[:0:-1], yr)
g = np.append(gl[:0:-1], gr)
w = np.append(wl[:0:-1], wr)

# Output the total volume of water by integrating water level minus elevation
print('Total volume =', np.trapz(w - g, y), 'm^3 per unit cross sectional area')

# Display
pp.plot(x, h, '.-', label='elevation')
pp.plot(y, w, '.-', label='water level')
pp.plot([x[leak]], [h[leak]], 'o', label='leak')
pp.legend()
pp.show()

样本输出

于 2018-07-20T15:46:47.363 回答
0

对于半径恒定且半径远小于海拔变化的管道,即管道的截面总是充满水。我认为,在这种情况下,如果管子的末端被盖住,那是行不通的,必须让一些空气进入才能让水流出。管道中仍充满水的部分位于左侧自由表面(绿色圆圈)和右侧自由表面(红色正方形)之间。为简单起见,假设管道的两端是最大高程点,否则管道将自行清空。平衡可能不稳定。

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def find_first_intersection(x, y, y_leak):
    for i in range(len(x)-1):
        dy_left = y[i] - y_leak
        dy_right = y[i+1] -  y_leak

        if  dy_left*dy_right < 0:
            x_free = x[i] + (y_leak - y[i])*(x[i+1] - x[i])/(y[i+1] - y[i])
            break

    return x_free

# Generate random data
x = np.linspace(0, 1, 10)
y = np.random.rand(*np.shape(x))
y[0], y[-1] = 1.1, 1.1
x_leak = np.random.rand(1)

# Look for the free surfaces
y_leak = np.interp(x_leak, x, y)

x_free_left = find_first_intersection(x, y, y_leak)
x_free_right =  find_first_intersection(x[::-1], y[::-1], y_leak)

# Plot
plt.plot(x, y, '-', label='pipe');
plt.plot(x_leak, y_leak, 'sk', label='leak')
plt.axhline(y=y_leak, linestyle=':', label='surface level');

plt.plot(x_free_left, y_leak, 'o', label="left free surface");
plt.plot(x_free_right, y_leak, 's', label="right free surface");

plt.legend(bbox_to_anchor=(1.5, 1.)); plt.xlabel('x'); plt.ylabel('y');

例子

我在图表上添加了一些注释。我认为水会留在“令人困惑的部分”是令人困惑的,因为我认为这仅适用于直径非常小的管道。对于较大的管道​​,这里的水将流过泄漏点,然后估计管道的剩余填充部分更加复杂......

于 2018-07-13T23:32:19.150 回答