00001
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
00045
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
00056
00057 h = np.empty(t+1)
00058 h[0] = hini - self.hmin
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
00065 self.discharge = u[:t] - self.sy*np.diff(h)
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
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)
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
00155
00156 h = np.empty((t+1, self.nlayer))
00157 h[0,:] = np.array(hini) - self.hmin
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
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
00285
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
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
00298
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
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
00323
00324 R = np.random.rand(100)
00325 foo = GW_1D(R)
00326
00327
00328 F = 0.8
00329 G = 10
00330 r = 0.1
00331
00332
00333
00334 h_ini = 10
00335
00336
00337
00338
00339
00340
00341
00342
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
00346
00347
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