damyarou

python, GMT などのプログラム

Python 逆調整池運用解析修正版(Flood Routine)

逆調整池運用解析プログラムの修正版

  • 関数FLOODの中の収束計算で、前回貯水池水位のみを既知としていたが、本来貯水池水位と放流量はペアなので、前回放流量も既知とした。プログラム作成時になぜ収束計算の中で前回流量を既知として確定していなかったのかは思い出せない。
  • 関連出力は、データフレームにして一気に書き出すことにした。

以下最新版プログラム(2020.08.08)

# ==============================================
# Flood Routine Analysis
# ==============================================
import sys
import numpy as np
import pandas as pd
from scipy import interpolate


def FLOOD(iOFC,fnameR1,fnameR2,fnameR3,ram,qrel):
    nr,rh,rv=INP_HV(fnameR1)                   # reservoir H-V
    nd,ti,q_in,ELini,Qoini=INP_INFLOW(fnameR2) # inflow time history
    no,elof,qof=INP_OUTFLOW(fnameR3)           # outflow capacity

    pEL=np.zeros(nd,dtype=np.float64) # storage of reervoir water level
    pQo=np.zeros(nd,dtype=np.float64) # storage of outflow
    pDE=np.zeros(nd,dtype=np.float64) # storage of error
    pVO=np.zeros(nd,dtype=np.float64) # storage of reservoir volume
    pRA=np.zeros(nd,dtype=np.float64) # storage of ramp up rate
    pUD=np.zeros(nd,dtype=int)        # storage of indicator od water level
    
    Vin=np.sum(q_in)*(ti[2]-ti[1])/2 # total volume of inflow
    Qimax=np.max(q_in)
    # Initial setting
    elv=ELini
#    elv=WLINI(q_in[0],elof,qof,no)     # Initial reservoir water level
    EL=elv
    VOL=RET_V(nr,rh,rv,elv)           # Initial reservoir volume
    q_out=Qoini
    qout0=Qoini
    print('q_in0={0:10.3f}'.format(q_in[0]))
    print('elv_ini={0:10.3f}'.format(EL))
    print('q_ini={0:10.3f}'.format(q_out))
    i=0
    iUD=0
    pUD[i]=iUD
    pEL[i]=EL
    pQo[i]=q_out
    pDE[i]=EL-elv
    pVO[i]=VOL
    pRA[i]=0
    # Iterative calculation
    iUD=1        # Assume reservoir water level increase
    dh=0.0005    # Water level increment for searching equilibrium point
    eps=0.001    # Convergence criteria
    itmax=int(1.0/dh)*100
    Vf=RET_V(nr,rh,rv,60.0)
    Vz=0
    Vin2=0
    Vot2=0
    q1=q_out
    for i in range(0,nd-1):
        dt=ti[i+1]-ti[i]             # Time interval
        Qin=0.5*(q_in[i]+q_in[i+1])  # Average inflow rate during dt
        hh=0.0                       # Zero set of water level increment
        k=0
        j=0
        while 1:
            k=k+1
            j=j+1;
            hh=hh+float(iUD)*dh      # Update waler level increment
            elv1=EL
            elv2=EL+hh
            if iOFC==8: q2=OFC8(q1,qout0,elv2,elof,qof,no,ti[i],ram,qrel)
            Qout=0.5*(q1+q2)         # Average outflow rate during dt
            dS=(Qin-Qout)*dt*3600.0  # Storage accumulated during dt
            R=VOL+dS                 # Total reservoir volume
            elv=RET_H(nr,rh,rv,R)    # Reservoir water level at reservoir volume R
            if iUD==1 and j==10:  # 10 times trial assuming reservoir water level increase
                if EL+hh>elv:     # if reservoir water level is less than assumed water level,
                    iUD=-1        # assume water level decrease
                    hh=0.0
                    j=0
            if iUD==-1 and j==10: # 10 times trial assuming reservoir water level decrease
                if EL+hh<elv:     # if reservoir water level is greater than assumed water level,
                    iUD=1         # assume water level decrease
                    hh=0.0
                    j=0
            if np.abs(EL+hh-elv)<eps: break  # Judgement of convergence
            if itmax<k: break
        VOL=R    # Cumulative volume
        EL=EL+hh # Elevation
        q_out=q2 # Outflow
        q1=q2
        
        pUD[i+1]=iUD
        pEL[i+1]=EL
        pQo[i+1]=q_out
        pDE[i+1]=EL-elv
        pVO[i+1]=VOL
        pRA[i+1]=(pQo[i+1]-pQo[i])/(ti[i+1]-ti[i])

    hmax=max(pEL)-ELini
    sys.stdout.write('Time: %10.3f\n'% np.max(ti))
    sys.stdout.write('h   : %10.3f\n'% hmax)
    sys.stdout.write('Qin : %10.3f %10.3f\n'% (np.min(q_in),np.max(q_in)))
    sys.stdout.write('Qout: %10.3f %10.3f\n'% (np.min(pQo),np.max(pQo)))
    sys.stdout.write('EL  : %10.3f %10.3f\n'% (np.min(pEL),np.max(pEL)))
    sys.stdout.write('\n')

    # TWC of 80m downstream of Re-Regulating Dam
    fnameR='inp_twc.txt'
    data=np.loadtxt(fnameR,skiprows=0,usecols=(0,1))
    qq=data[:,0]
    ee=data[:,1]
    ff=interpolate.interp1d(qq,ee)
    el_ds=ff(pQo)
    
    df = pd.DataFrame({ 'i'  : np.arange(0,nd), # numper
                        'iUD': pUD,   # indicator for water level
                        'ti' : ti,    # time
                        'EL' : pEL,   # water level of reservoir
                        'dEL': pDE,   # error
                        'VOL': pVO,   # reservoir volume
                        'Qi' : q_in,  # inflow to reservoir
                        'Qo' : pQo,   # outflow from reservoir
                        'RA' : pRA,   # ramp up rate
                        'ELD': el_ds  # downstream water level
                      })
    df = df.set_index('i')
    return df 


def WLINI(q,elof,qof,no):
    # To obtain initial water level at oitflow discharge q
    for i in range(0,no-1):
        if qof[i]<=q and q<=qof[i+1]: break
    if qof[no-1]<q: i=no-2
    x1=qof[i]
    y1=elof[i]
    x2=qof[i+1]
    y2=elof[i+1]
    a=(y2-y1)/(x2-x1)
    b=(x2*y1-x1*y2)/(x2-x1)
    elv=a*q+b
    if q<0.0: elv=elof[0]
    return elv


def OFC8(q1,qout0,elv2,elof,qof,no,tii,ram,qrel):
    Qlim=300.0
    if   5.0<tii and tii<= 29.0 :qout0=qrel
    if  29.0<tii and tii<= 53.0 :qout0=qrel
    if  53.0<tii and tii<= 77.0 :qout0=qrel
    if  77.0<tii and tii<=101.0 :qout0=qrel
    if 101.0<tii: qout0=39.0
    q2=OFC(elv2,elof,qof,no)
    rq2=q2
    if q2<qout0: qout0=q2
    q2=qout0
    st=0.01
    ts1=0.0
    ts2=24.0
    ts3=48.0
    ts4=72.0
    ts5=96.0
    if ts1+st<=tii and tii<=ts1+5.0+st:
        if elv2<68.0:
            q2=q1+ram*st
            if rq2<q2: q2=rq2
            if Qlim<=q2: q2=Qlim
        else:
            q2=rq2
    if ts2+st<=tii and tii<=ts2+5.0+st:
        if elv2<68.0:
            q2=q1+ram*st
            if rq2<q2: q2=rq2
            if Qlim<=q2: q2=Qlim
        else:
            q2=rq2
    if ts3+st<=tii and tii<=ts3+5.0+st:
        if elv2<68.0:
            q2=q1+ram*st
            if rq2<q2: q2=rq2
            if Qlim<=q2: q2=Qlim
        else:
            q2=rq2
    if ts4+st<=tii and tii<=ts4+5.0+st:
        if elv2<68.0:
            q2=q1+ram*st
            if rq2<q2: q2=rq2
            if Qlim<=q2: q2=Qlim
        else:
            q2=rq2
    if ts5+st<=tii and tii<=ts5+5.0+st:
        if elv2<68.0:
            q2=q1+ram*st
            if rq2<q2: q2=rq2
            if Qlim<=q2: q2=Qlim
        else:
            q2=rq2

    return q2


def OFC(elv,elof,qof,no):
    # Free overflow discharge
    for i in range(0,no-1):
        if elof[i]<=elv and elv<=elof[i+1]: break
    if elof[no-1]<elv: i=no-2
    x1=elof[i]
    y1=qof[i]
    x2=elof[i+1]
    y2=qof[i+1]
    a=(y2-y1)/(x2-x1)
    b=(x2*y1-x1*y2)/(x2-x1)
    q=a*elv+b
    if elv<=elof[0]: q=0.0
    return q

def RET_V(nr,rh,rv,elv):
    # To obtain reservoir cumulative volume from the water level
    for i in range(0,nr-1):
        if rh[i]<=elv and elv<=rh[i+1]: break
    if rh[nr-1]<elv: i=nr-2
    x1=rv[i]
    y1=rh[i]
    x2=rv[i+1]
    y2=rh[i+1]
    a=(y2-y1)/(x2-x1)
    b=(x2*y1-x1*y2)/(x2-x1)
    v=(elv-b)/a
    return v

def RET_H(nr,rh,rv,v):
    # To obtain reservoir water level from cumulative volume
    for i in range(0,nr-1):
        if rv[i]<=v and v<=rv[i+1]: break
    if rv[nr-1]<v: i=nr-2
    x1=rv[i]
    y1=rh[i]
    x2=rv[i+1]
    y2=rh[i+1]
    a=(y2-y1)/(x2-x1)
    b=(x2*y1-x1*y2)/(x2-x1)
    elv=a*v+b
    return elv

def INP_HV(fnameR1):
    # Input reservoir H-V data
    fin=open(fnameR1,'r')
    dat=fin.readlines()
    fin.close()
    n=len(dat)
    text=dat[0]
    text=text.strip()
    text=text.split()
    vcoef=float(text[0])
    rh=np.zeros(n-1,dtype=np.float64)
    rv=np.zeros(n-1,dtype=np.float64)
    for i in range(0,n-1):
        text=dat[i+1]
        text=text.strip()
        text=text.split()
        rh[i]=float(text[0])
        rv[i]=float(text[1])*vcoef
    nr=len(rh)
    return nr,rh,rv

def INP_INFLOW(fnameR2):
    # Input time sequence of inflow
    fin=open(fnameR2,'r')
    dat=fin.readlines()
    fin.close()
    n=len(dat)
    text=dat[0]
    text=text.strip()
    text=text.split()
    ELini=float(text[0])
    Qoini=float(text[1])
    ti  =np.zeros(n-1,dtype=np.float64)
    q_in=np.zeros(n-1,dtype=np.float64)
    for i in range(0,n-1):
        text=dat[i+1]
        text=text.strip()
        text=text.split()
        ti[i]  =float(text[0])
        q_in[i]=float(text[1])
    nd=len(ti)
    return nd,ti,q_in,ELini,Qoini

def INP_OUTFLOW(fnameR3):
    # Input outflow capacity (water level-discharge curve)
    fin=open(fnameR3,'r')
    dat=fin.readlines()
    fin.close()
    n=len(dat)
    elof=np.zeros(n,dtype=np.float64)
    qof =np.zeros(n,dtype=np.float64)
    for i in range(0,n):
        text=dat[i]
        text=text.strip()
        text=text.split()
        elof[i]=float(text[0])
        qof[i] =float(text[1])
    no=len(elof)
    return no,elof,qof


def main():
    lout=['out_150.csv','out_175.csv','out_200.csv','out_225.csv','out_250.csv']
    lram=[150,175,200,225,250]
    lqrel=[89.0,87.1,82.9,81.5,80.7]
    for out,ram,qrel in zip(lout,lram,lqrel):
        iOFC=8
        fnameR1='inp_RHV.txt' # H-V data of reservoir
        fnameR2='inp_c00.txt' # Inflow time history (Hydrograph)
        fnameR3='inp_OF8.txt' # Outflow capacity
        fnameW = out # Output file name
        df=FLOOD(iOFC,fnameR1,fnameR2,fnameR3,ram,qrel)
        df.to_csv(fnameW, sep=",")
    

#============================    
if __name__ == '__main__':
    main()

以 上