1

This might be more of an algorithm question, but I'm writing it in Python.

I have a set of data on a pipeline that gains and loses altitude as it progresses. My data is two columns, the measure along the pipeline, and the elevation at that measure. There are tens of thousands of rows in my dataset. (these would be columns instead of rows)

Measure: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Elevation: 5, 7, 9, 15, 12, 13, 18, 14, 23, 9

In this script, the pipe would be assume to be capped at both ends. The goal is to calculate the total volume of liquid that would drain from a leak at any point in the pipe. Pressure/flow rate don't matter. The main part I'm trying to account for would be all of the catches/valleys (like in a bathroom sink) that liquid would remain in even while the rest of the pipe drains, like this:

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

The pipe radius, and location of the leak would be user-set parameters.

I'm really looking for a push in the right direction, I want to figure this out on my own as much as possible. I'm fine with the programming, but any advice on the actual logic would be helpful, thank you in advanced. enter image description here

Let's say in this graph that a leak appears at point 9 on the x-axis, and the pipe has a known radius r. I'm trying to figure out how to get my script to output the total quantity of liquid in terms of r will be emptied out, regardless of time. And if through damage a leak developed in a pipe, air would come in and water would come out, but not all of the water because of the various catches and different elevations of the pipeline.

Clive
  • 79
  • 1
  • 5
  • I do not understand how this is not a pressure/flow rate problem? Sounds to me like that's exactly what it is. Sounds like a related rates problem: flow out and volume decrements would be the rates you need to relate. Explain again how this is not a pressure/flow rate problem? – Rob Jul 12 '18 at 22:15
  • @Rob. Flow rate is not part of the problem: merely how much water would *evetually* make its way through that leak. For instance, if the pipe is 3cm in diameter, and I poke a hole 4cm above the bottom of the trap (just higher than the upper surface of the trap's lowest point), I'll drain out most of the water on *both* sides of the trap. – Prune Jul 12 '18 at 23:01
  • @Clive I don't understand what you need from us. The volume of liquid is dependent on the pipe diameter and shapes of the various pipes. Computing volumes of partially-drained pipes is not straightforward, even with this information. Most of all, this isn't a Stack Overflow question: it doesn't (yet) deal with programming, nor with a data-processing algorithm. So far, it's merely a practicum in 3D integration. – Prune Jul 12 '18 at 23:05
  • Also, your data set isn't clear. You list ten "measure" elements (whatever that means in implementation terms), but there are twelve "elevation" elements, including one null. Since we don't know the pipe shapes used to change elevations (there are many possibilities), we have no way of handling the math to compute partially-filled volumes. – Prune Jul 12 '18 at 23:07
  • I might be in over my head, I was asked to write this script because I know Python, not because I know the physics/geometry. – Clive Jul 13 '18 at 19:38
  • @Prune My apologies, I fixed the data, it was a formatting error on my part. In this case, "measure" is simply a linear unit of pipeline from the start, so in the sample data the pipe would be divided into 10 equal parts/points, and I would like to know how much fluid would drain from each point. The elevation is the Z value. The main task at hand is figuring out how to calculate the volume of fluid that would be "trapped" in the upward curving sections, and identifying those sections programmatically. My actual data has tens of thousands of rows. – Clive Jul 13 '18 at 19:50
  • No great problem; the data are now at least corresponding. However, I'm still seeing more complexity to this than you've specified. I've watched the video four times now. (1) I don't understand how even this simple pipe configuration would appear as data to this program. (2) Stop the video at time 0:11 - 0:13, when the outlet has drained all except the functional part of the trap. How do we get the physical dimensions necessary to compute the volume of white (drained) pipe -- or the blue area, to subtract from the total? – Prune Jul 13 '18 at 21:17
  • I feel that your posting perhaps focuses on an idealized problem: figure out which pipe segments will drain fully, not at all, and partially. Given an idealized pipe, we can certainly do that; it's a variation of the flooding problem. Is that the only part with which you really need help? – Prune Jul 13 '18 at 21:19

2 Answers2

1

If I understand the problem correctly, I think this can be achieved by traversing the pipe left and right from the point of the leak. At each point the current water level is compared with the pipe elevation, either resulting in a submersed point in which the water level remains the same, or a beach and a new dry peak. Interpolation is necessary to calculate the location of the beach.

An implementation is shown below. The bulk of the algorithm is in the traverse function. Hopefully the comments provide adequate description.

#!/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()

Sample output

Bill
  • 468
  • 3
  • 9
0

For a constant radius pipe and with a radius much smaller than the variation of elevation, i.e. the section of the pipe is always filled by water. I think, in this case, it doesn't work if the pipe is capped at the ends, some air have to get in to let the water get out. The part of the pipe remaining filled by water is between the left free surface (green circle) and the right free surface (red square). For simplicity, it is assumed that the both ends of the pipe are the points of maximum elevation, otherwise the pipe will empty itself. The equilibrium may be unstable.

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');

example

I added some annotations on the graph. I think it is confusing that the water will remain in the "confusing part" because I think this is valid only for very small diameter pipe. For a larger pipe the water here will flow through the leak and then estimating the remaining filled part of the pipe is more complicated...

xdze2
  • 3,986
  • 2
  • 12
  • 29
  • I'm confused about your output, would the two higher up end pieces not apply pressure and drain out all the water above the leak? Or would only the small middle triangular section leak out? For this, I can't assume the the pipeline would end at higher elevation, one end could be the lowest point. – Clive Jul 16 '18 at 21:16