Source code for tsnet.simulation.single

"""
The tsnet.simulation.single contains methods to perform MOC
transient simulation on a single pipe, including
1. inner pipe
2. left boundary pipe (without C- charateristic grid)
3. right boundary pipe (without C+ characteristic grid)

"""
import numpy as np
from tsnet.utils import calc_parabola_vertex
from tsnet.simulation.solver import (
    inner_node,
    valve_node,
    pump_node,
    source_pump,
    valve_end,
    dead_end,
    rev_end,
    add_leakage
)

[docs]def inner_pipe (linkp, pn, dt, links1, links2, utype, dtype, p, H0, V0, H, V, H10, V10, H20, V20, pump, valve): """MOC solution for an individual inner pipe. Parameters ---------- linkp : object Current pipe object pn : int Current pipe ID dt : float Time step H : numpy.ndarray Head of current pipe at current time step [m] V : numpy.ndarray Velocity of current pipe at current time step [m/s] links1 : list Upstream adjacent pipes links2 : list Downstream adjacent pipes utype : list Upstream adjacent link type, and if not pipe, their name dtype : list Downstream adjacent link type, and if not pipe, their name p : list pipe list n : int Number of discretization of current pipe H10 : list Head of left adjacent nodes at previous time step [m] V10 : list Velocity of left adjacent nodes at previous time step [m/s] H20 : list Head of right adjacent nodes at previous time step [m] V20 : list Velocity of right adjacent nodes at previous time step [m/s] pump : list Characteristics of the pump valve : list Characteristics of the valve Returns ------- H : numpy.ndarray Head results of the current pipe at current time step. [m] V : numpy.ndarray Velocity results of the current pipe at current time step. [m/s] """ # Properties of current pipe g = 9.8 # m/s^2 link1 = [p[abs(i)-1] for i in links1] link2 = [p[abs(i)-1] for i in links2] n = linkp.number_of_segments # spatial discretization for i in range(n+1): # Pipe start if i == 0: V1 = V10; H1 = H10 #list V2 = V0[i+1]; H2 = H0[i+1] if utype[0] == 'Pipe': elev = linkp.start_node.elevation emitter_coeff = linkp.start_node.emitter_coeff + linkp.start_node.demand_coeff H[i], V[i] = add_leakage(emitter_coeff, link1, linkp, elev, H1, V1, H2, V2, dt, g, i, np.sign(links1), [-1]) elif utype[0] == 'Pump': pumpc = calc_parabola_vertex(pump[0]) H[i], V[i] = pump_node(pumpc, link1, linkp, H1, V1, H2, V2, dt, g, i, np.sign(links1), [-1]) elif utype[0] == 'Valve': valvec = valve[0] H[i], V[i] = valve_node(valvec, link1, linkp, H1, V1, H2, V2, dt, g, i, np.sign(links1), [-1]) # Pipe end if i == n: V1 = V0[i-1]; H1 = H0[i-1] V2 = V20; H2 = H20 if dtype[0] == 'Pipe': elev = linkp.end_node.elevation emitter_coeff = linkp.end_node.emitter_coeff + linkp.end_node.demand_coeff H[i], V[i] = add_leakage(emitter_coeff, linkp, link2, elev, H1, V1, H2, V2, dt, g, i, [1], np.sign(links2)) elif dtype[0] == 'Pump': pumpc = calc_parabola_vertex(pump[1]) H[i], V[i] = pump_node(pumpc, linkp, link2, H1, V1, H2, V2, dt, g, i, [1], np.sign(links2)) elif dtype[0] == 'Valve': valvec = valve[1] H[i], V[i] = valve_node(valvec, linkp, link2, H1, V1, H2, V2, dt, g, i, [1], np.sign(links2)) # Interior points if (i > 0) and (i < n): V1 = V0[i-1]; H1 = H0[i-1] V2 = V0[i+1]; H2 = H0[i+1] H[i], V[i] = inner_node(linkp, linkp, 0, H1, V1, H2, V2, dt, g, i,[1],[-1]) return H, V
[docs]def left_boundary(linkp, pn, H, V, H0, V0, links2, p, pump, valve, dt, H20, V20, utype, dtype) : """MOC solution for an individual left boundary pipe. Parameters ---------- linkp : object Current pipe object pn : int Current pipe ID H : numpy.ndarray Head of current pipe at current time step [m] V : numpy.ndarray Velocity of current pipe at current time step [m/s] links2 : list Downstream adjacent pipes p : list pipe list pump : list Characteristics of the pump valve : list Characteristics of the valve n : int Number of discretization of current pipe dt : float Time step H0 : numpy.ndarray Head of current pipe at previous time step [m] V0 : numpy.ndarray Velocity of current pipe at previous time step [m/s] H20 : list Head of right adjacent nodes at previous time step [m] V20 : list Velocity of right adjacent nodes at previous time step [m/s] utype : list Upstream adjacent link type, and if not pipe, their name dtype : list Downstream adjacent link type, and if not pipe, their name Returns ------- H : numpy.ndarray Head results of the current pipe at current time step. [m] V : numpy.ndarray Velocity results of the current pipe at current time step. [m/s] """ link2 = [p[abs(i)-1] for i in links2] # Properties of current pipe f = linkp.roughness # unitless D = linkp.diameter # m g = 9.8 # m/s^2 a = linkp.wavev # m/s n = linkp.number_of_segments # spatial discretization for i in range(n+1): # Pipe start (outer boundayr conditions) if i == 0: V2 = V0[i+1]; H2 = H0[i+1] if utype[0] == 'Reservoir' or utype[0] == 'Tank': H[i], V[i] = rev_end (H2, V2, H[i], i, a, g, f, D, dt) elif utype[0] == 'Valve': H[i], V[i] = valve_end (H2, V2, V[i], i, a, g, f, D, dt) elif utype[0] == 'Junction': H[i], V[i] = dead_end (linkp , H2, V2, i, a, g, f, D, dt) elif utype[0] == 'Pump': #source pump pump[0][1] = calc_parabola_vertex(pump[0][1]) H[i], V[i] = source_pump(pump[0], linkp, H2, V2, dt, g, [-1]) # Pipe end (inner boundary conditions) if i == n: V1 = V0[i-1]; H1 = H0[i-1] # upstream node V2 = V20; H2 = H20 # downstream nodes if dtype[0] == 'Pipe': elev = linkp.end_node.elevation emitter_coeff = linkp.end_node.emitter_coeff + linkp.end_node.demand_coeff H[i], V[i] = add_leakage(emitter_coeff, linkp, link2, elev, H1, V1, H2, V2, dt, g, i, [1], np.sign(links2)) elif dtype[0] == 'Pump': pumpc = calc_parabola_vertex(pump[1]) H[i], V[i] = pump_node(pumpc, linkp, link2, H1, V1, H2, V2, dt, g, i, [1], np.sign(links2)) elif dtype[0] == 'Valve': valvec = valve[1] H[i], V[i] = valve_node(valvec, linkp, link2, H1, V1, H2, V2, dt, g, i, [1], np.sign(links2)) # Interior points if (i > 0) and (i < n): V1 = V0[i-1]; H1 = H0[i-1] V2 = V0[i+1]; H2 = H0[i+1] H[i], V[i] = inner_node(linkp, linkp, 0, H1, V1, H2, V2, dt, g, i,[1],[-1]) return H, V
[docs]def right_boundary(linkp, pn, H0, V0, H, V, links1, p, pump, valve, dt, H10, V10, utype, dtype): """MOC solution for an individual right boundary pipe. Parameters ---------- linkp : object Current pipe object pn : int Current pipe ID H : numpy.ndarray Head of current pipe at current time step [m] V : numpy.ndarray Velocity of current pipe at current time step [m/s] links1 : list Upstream adjacent pipes p : list pipe list pump : list Characteristics of the pump valve : list Characteristics of the valve n : int Number of discretization of current pipe dt : float Time step H0 : numpy.ndarray Head of current pipe at previous time step [m] V0 : numpy.ndarray Velocity of current pipe at previous time step [m/s] H10 : list Head of left adjacent nodes at previous time step [m] V10 : list Velocity of left adjacent nodes at previous time step [m/s] utype : list Upstream adjacent link type, and if not pipe, their name dtype : list Downstream adjacent link type, and if not pipe, their name Returns ------- H : numpy.ndarray Head results of the current pipe at current time step. [m] V : numpy.ndarray Velocity results of the current pipe at current time step. [m/s] """ # Properties of current pipe link1 = [p[abs(i)-1] for i in links1] f = linkp.roughness # unitless D = linkp.diameter # m g = 9.8 # m/s^2 a = linkp.wavev # m/s n = linkp.number_of_segments # spatial discretization for i in range(n+1): # Pipe start (inner boundary conditions) if i == 0: V1 = V10; H1 = H10 # upstream node V2 = V0[i+1]; H2 = H0[i+1] # downstream node if utype[0] == 'Pipe': elev = linkp.start_node.elevation emitter_coeff = linkp.start_node.emitter_coeff + linkp.start_node.demand_coeff H[i], V[i] = add_leakage(emitter_coeff, link1, linkp, elev, H1, V1, H2, V2, dt, g, i, np.sign(links1), [-1]) elif utype[0] == 'Pump': pumpc = calc_parabola_vertex(pump[0]) H[i], V[i] = pump_node(pumpc, link1, linkp, H1, V1, H2, V2, dt, g, i, np.sign(links1), [-1]) elif utype[0] == 'Valve': valvec = valve[0] H[i], V[i] = valve_node(valvec, link1, linkp, H1, V1, H2, V2, dt, g, i, np.sign(links1), [-1]) # Pipe end (outer boundary conditions ) if i == n: V1 = V0[i-1]; H1 = H0[i-1] if dtype[0] == 'Reservoir' or dtype[0] == 'Tank': H[i], V[i] = rev_end (H1, V1, H[i], i, a, g, f, D, dt) if dtype[0] == 'Valve': H[i], V[i] = valve_end (H1, V1, V[i], i, a, g, f, D, dt) if dtype[0] == 'Junction': H[i], V[i] = dead_end (linkp ,H1, V1, i, a, g, f, D, dt) # Interior points if (i > 0) and (i < n): V1 = V0[i-1]; H1 = H0[i-1] V2 = V0[i+1]; H2 = H0[i+1] H[i], V[i] = inner_node(linkp, linkp,0, H1, V1, H2, V2, dt, g, i,[1],[-1]) return H, V