AMBHAS
gw.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 """
00003 Created on Wed Nov 16 14:25:50 2011
00004 
00005 @author: Sat Kumar Tomer
00006 @website: www.ambhas.com
00007 @email: satkumartomer@gmail.com
00008 """
00009 from __future__ import division
00010 import numpy as np
00011 from ambhas.errlib import L
00012 from osgeo import gdal
00013 from osgeo.gdalconst import *
00014 from ambhas.xls import xlsread
00015 
00016 class GW_1D():
00017     """
00018     This class perform the groundwater modelling
00019     """
00020     
00021     def __init__(self, R, Dnet=0):
00022         """
00023         R: rainfall
00024         Dnet: net groundwater draft
00025         """
00026         self.R = R
00027         self.Dnet = Dnet
00028         
00029     def set_parameters(self, F, G, r, hmin=0):
00030         """
00031         F: model parameter
00032         G: model parameter
00033         r: recharge factor
00034         hmin: groundwater level at which base flow ceases
00035         
00036         sy: specific yield
00037         lam: decay constant
00038         """
00039         self.F = F
00040         self.G = G
00041         self.r = r
00042         self.hmin = hmin
00043         
00044         #self.lam = (1-F)**2/G
00045         #self.sy = (1-F)/G
00046         
00047         self.sy = F/G
00048         self.lam = (1-F)*self.sy
00049             
00050     def run_model(self, hini, t):
00051         """
00052         hini: initial groundwater level
00053         t: time
00054         """
00055         u = self.r*self.R-self.Dnet # net input
00056         
00057         h = np.empty(t+1) # create empty array
00058         h[0] = hini  - self.hmin       # set the initial condition
00059                 
00060         for k in range(t):
00061             h[k+1] = self.F*h[k] + self.G*u[k]
00062             
00063             
00064         self.h = h + self.hmin # simulated gw levels
00065         self.discharge = u[:t] - self.sy*np.diff(h) # simulated discharge
00066         
00067  
00068     
00069     def ens(self, F_lim, G_lim, r_lim, hmin_lim, ens, hini, h_obs, t):
00070         """
00071         generate ensemble based on ensemble of parameters
00072         Input:
00073             F: min and max of F
00074             G: min and max of G
00075             r: min and max of r
00076             hmin: min and max of hmin
00077             ens: no. of ensembles
00078             hini: initial gw level
00079             t: final time
00080         """
00081         F_ens = F_lim[0] + (F_lim[1]-F_lim[0]) * np.random.rand(ens)
00082         G_ens = G_lim[0] + (G_lim[1]-G_lim[0]) * np.random.rand(ens)
00083         r_ens = r_lim[0] + (r_lim[1]-r_lim[0]) * np.random.rand(ens)
00084         hmin_ens = hmin_lim[0] + (hmin_lim[1]-hmin_lim[0]) * np.random.rand(ens)
00085 
00086         self.F_ens = F_ens
00087         self.G_ens = G_ens
00088         self.r_ens = r_ens
00089         self.hmin_ens = hmin_ens        
00090         
00091         self.L = np.empty(ens)
00092         for i in range(ens):
00093             self.set_parameters(F_ens[i], G_ens[i], r_ens[i], hmin_ens[i])
00094             self.run_model(hini, t)
00095             self.L[i] = L(self.h, h_obs[:t+1])
00096     
00097         # select best ensembles        
00098         ind = self.L.argmax()
00099                 
00100         self.set_parameters(F_ens[ind], G_ens[ind], r_ens[ind], hmin_ens[ind])
00101         self.run_model(hini, t)
00102         self.best_h = self.h
00103         self.best_ind = ind
00104   
00105 
00106 class GW_2D_yz():
00107     """
00108     This class perform the groundwater modelling
00109     """
00110     
00111     def __init__(self, R, Dnet=0):
00112         """
00113         R: rainfall
00114         Dnet: net groundwater draft
00115         """
00116         self.R = R
00117         self.Dnet = 0
00118     
00119     def set_parameters(self, lam, sy, r, hmin=0):
00120         """
00121         F: model parameter
00122         G: model parameter
00123         r: recharge factor
00124         hmin: groundwater level at which based flow ceases
00125         
00126         sy: specific yield
00127         lam: decay constant
00128         """
00129         if len(lam) != len(sy):
00130             raise ValueError('The lenght of F and G should be same')
00131         
00132         nlayer = len(lam) # number of verticle profiles
00133         self.nlayer = nlayer
00134         
00135         F = np.zeros((nlayer, nlayer))
00136         G = np.zeros(nlayer)
00137         for i in range(nlayer):
00138             F[i,i] = 1 - lam[i]/sy[i]
00139             G[i] = lam[i]/sy[i]**2
00140             if i>0:
00141                 F[i, i-1] = lam[i-1]/sy[i]
00142                 G[i] = -lam[i-1]/(sy[i-1]*sy[i]) + lam[i]/sy[i]**2
00143         
00144         self.F = F
00145         self.G = G
00146         self.r = r
00147         self.hmin = hmin
00148         
00149     def run_model(self, hini, t):
00150         """
00151         hini: initial groundwater level
00152         t: time
00153         """
00154         u = self.r*self.R-self.Dnet # net input
00155         
00156         h = np.empty((t+1, self.nlayer)) # create empty array
00157         h[0,:] = np.array(hini)  - self.hmin       # set the initial condition
00158                 
00159         for k in range(t):
00160             h[k+1] = np.dot(self.F,h[k,:]) + self.G*u[k]
00161            
00162         self.h = h + self.hmin
00163 
00164     def ens(self, lam_lim, sy_lim, r_lim, hmin_lim, ens, hini, h_obs, t):
00165         """
00166         generate ensemble based on ensemble of parameters
00167         Input:
00168             F: min and max of F
00169             G: min and max of G
00170             r: min and max of r
00171             hmin: min and max of hmin
00172             ens: no. of ensembles
00173             hini: initial gw level
00174             t: final time
00175         """
00176         lam_lim = np.array(lam_lim)
00177         sy_lim = np.array(sy_lim)
00178         r_lim = np.array(r_lim)
00179         hmin_lim = np.array(hmin_lim)
00180         
00181         nlayer = lam_lim.shape[1]
00182         self.nlayer = nlayer
00183         
00184         R_v = np.random.rand(ens,nlayer)
00185         lam_ens = np.tile(lam_lim[0,:],(ens,1)) + \
00186             (np.tile(lam_lim[1,:],(ens,1)) - np.tile(lam_lim[0,:],(ens,1)))* R_v
00187         
00188         R_v = np.random.rand(ens,nlayer)
00189         sy_ens = np.tile(sy_lim[0,:],(ens,1)) + \
00190             (np.tile(sy_lim[1,:],(ens,1)) - np.tile(sy_lim[0,:],(ens,1)))* R_v
00191         
00192         r_ens = r_lim[0] + (r_lim[1]-r_lim[0]) * np.random.rand(ens)
00193         
00194         hmin_ens = hmin_lim[0] + (hmin_lim[1]-hmin_lim[0]) * np.random.rand(ens)
00195             
00196         self.lam_ens = lam_ens
00197         self.sy_ens = sy_ens
00198         self.r_ens = r_ens
00199         self.hmin_ens = hmin_ens
00200         
00201         eff = np.empty((ens, nlayer))
00202         for i in range(ens):
00203             self.set_parameters(lam_ens[i], sy_ens[i], r_ens[i], hmin_ens[i])
00204             self.run_model(hini, t)
00205             for j in range(nlayer):
00206                 eff[i,j] = L(self.h[:,j], h_obs[:t+1,j])
00207         
00208         self.eff = eff.mean(axis=1)
00209         # select best ensembles        
00210         ind = self.eff.argmax()
00211                 
00212         self.set_parameters(lam_ens[ind], sy_ens[ind], r_ens[ind], hmin_ens[ind])
00213         self.run_model(hini, t)
00214         self.best_h = self.h
00215         self.best_ind = ind
00216 
00217 class GW_2D_xy():
00218     """
00219     this class performs the 2 dimensinoal groundwater modelling in horizonal 
00220     plane using the 2 dimensional groundwater flow equation
00221     """
00222     def __init__(self, watershed, hini, D, dt, dx, hmin, F, outlet):
00223         """
00224         watershed: map of watershed in tiff format, 1 means inside watershed
00225         hini: initial groundwater level
00226         D:  T/Sy
00227         """
00228         self.watershed = watershed
00229         self.hini = hini
00230         self.D = D
00231         self.dt = dt
00232         self.dx = dx
00233         self.hmin = hmin
00234         self.F = F
00235         self.outlet = outlet
00236         self.mac_cormack()
00237         
00238         
00239     def mac_cormack(self):
00240         """
00241         this uses the mac cormack scheme
00242         """        
00243         h = self.hini
00244         dt = self.dt
00245         dx = self.dx
00246         hmin = self.hmin
00247         F = self.F
00248         outlet = self.outlet
00249         n_outlet = watershed[outlet].sum()
00250         discharge = F*(h[watershed].mean()-hmin)
00251         
00252         grid_D = D*dt/dx**2
00253         hstar = np.zeros(h.shape)
00254         for i in range(h.shape[0]):
00255             for j in range(h.shape[1]):
00256                 if watershed[i,j]:
00257                     d2h_dx2 = h[i+2,j] -2*h[i+1,j] + h[i,j]
00258                     d2h_dy2 = h[i,j+2] -2*h[i,j+1] + h[i,j]
00259                     if watershed[i+1,j]*watershed[i+2,j]  == 0:
00260                         d2h_dx2 = 0
00261                     if watershed[i,j+1]*watershed[i,j+2] == 0:
00262                         d2h_dy2 = 0
00263                     hstar[i,j] = h[i,j] + grid_D*(d2h_dx2+ d2h_dy2)
00264         
00265         hnew = np.zeros(h.shape)
00266         for i in range(h.shape[0]):
00267             for j in range(h.shape[1]):
00268                 if watershed[i,j]:
00269                     d2h_dx2 = h[i-2,j] -2*hstar[i-1,j] + hstar[i,j]
00270                     d2h_dy2 = h[i,j-2] -2*hstar[i,j-1] + hstar[i,j]
00271                     if watershed[i-1,j]*watershed[i-2,j] == 0:
00272                         d2h_dx2 = 0
00273                     if watershed[i,j-1]*watershed[i,j-2] == 0:
00274                         d2h_dy2 = 0
00275                     hnew[i,j] = 0.5*(h[i,j]+hstar[i,j] + grid_D*(d2h_dx2+ d2h_dy2))
00276                            
00277         self.hnew = hnew        
00278         
00279 if __name__ == "__main__":
00280     from scipy.interpolate import Rbf
00281     from random import sample
00282     import matplotlib.pyplot as plt
00283     
00284     ################## horizontal 2d grounwater model ##############
00285     # read the watershed in tiff format
00286     dataset = gdal.Open('/home/tomer/south_gundal/geospatial_data/watershed_500.tif',GA_ReadOnly)
00287     watershed = dataset.GetRasterBand(1).ReadAsArray()
00288     watershed[-2,:] = 0
00289     GT = dataset.GetGeoTransform()
00290     # read the initial groundwater level data from xls file
00291     fname = '/home/tomer/south_gundal/gw_level.xls'    
00292     xls_file = xlsread(fname)
00293     sample_id = sample(xrange(23908), 500)
00294     gw_x = xls_file.get_cells('A1:A23908', 'dec2009')[sample_id].flatten()
00295     gw_y = xls_file.get_cells('B1:B23908', 'dec2009')[sample_id].flatten()
00296     gw_ini = xls_file.get_cells('E1:E23908', 'dec2009')[sample_id].flatten()
00297     # convert the point value of groundwater levels into a map having the same 
00298     #extent and size as of watershed
00299     rbfi = Rbf(gw_x, gw_y, gw_ini, function='linear')
00300     xi = np.linspace(GT[0]+GT[1]/2, GT[0]+GT[1]*(dataset.RasterXSize-0.5), 
00301                         dataset.RasterXSize)
00302     yi = np.linspace(GT[3]+GT[5]/2, GT[3]+GT[5]*(dataset.RasterYSize-0.5),
00303                         dataset.RasterYSize)
00304     XI, YI = np.meshgrid(xi,yi)
00305     hini = rbfi(XI, YI)
00306 
00307     #run the model
00308     dt = 1
00309     D = 20/0.008
00310     dx = 500
00311     hmin = 500
00312     F = 0.999
00313     outlet = [[5],[43,44,45,46]]
00314     foo = GW_2D_xy(watershed, hini, D, dt, dx, hmin, F, outlet)
00315     
00316     print hini[watershed==1].mean()
00317     print foo.hnew[watershed==1].mean()
00318     
00319     plt.imshow(foo.hnew, vmin=650)
00320     plt.colorbar()
00321     plt.show()
00322     ############ lumped (1D) model ##################3
00323     # forcing
00324     R = np.random.rand(100)
00325     foo = GW_1D(R)
00326     
00327     # parameter
00328     F = 0.8
00329     G = 10
00330     r = 0.1
00331     #foo.set_parameters(F, G, r)
00332     
00333     # initial condition
00334     h_ini = 10
00335     
00336     # run the model    
00337     #foo.run_model(h_ini, 100)
00338     
00339     # get the simulated data
00340     #h_sim = foo.h
00341     
00342     # ensemble
00343     h_obs = np.random.rand(101)
00344     foo.ens([0.5, 1.0], [1, 20], [0, 0.2], [50,70], 2, 20, h_obs, 10)
00345     #print(foo.L)
00346     
00347     ################### hill slope groundwater modelling ######################
00348     foo = GW_2D_yz(R)
00349     lam = [0.00008, 0.00009, 0.0001, 0.0002]
00350     sy = [0.001, 0.001, 0.001, 0.001]
00351     r = 0.2
00352     foo.set_parameters(lam, sy, r)
00353     hini = [10,7,5,3]
00354     foo.run_model(hini, 50)
00355     
00356     lam_lim = [[0.2, 0.3, 0.4, 0.5], [0.3, 0.4, 0.5, 0.6]]
00357     sy_lim = [[0.2, 0.3, 0.4, 0.5], [0.3, 0.4, 0.5, 0.6]]
00358     r_lim = [0.2,0.3]
00359     hmin_lim = [2,5]
00360     ens = 10
00361     t = 10
00362     h_obs = np.random.rand(t+1,4)
00363     foo.ens(lam_lim, sy_lim, r_lim, hmin_lim, ens, hini, h_obs, t)
00364     
00365     
00366     
00367     
 All Classes Namespaces Files Functions Variables