def __init__(self, par): cmf.set_parallel_threads(1) # run the model self.project = cmf.project() self.cell = self.project.NewCell(x=0, y=0, z=238.628, area=1000, with_surfacewater=True) c = self.cell r_curve = cmf.VanGenuchtenMualem(Ksat=10**par.pKsat, phi=par.porosity, alpha=par.alpha, n=par.n) # Make the layer boundaries and create soil layers lthickness = [.01] * 5 + [0.025] * 6 + [0.05] * 6 + [0.1] * 5 ldepth = np.cumsum(lthickness) # Create soil layers and pick the new soil layers if they are inside of the evaluation depth's for d in ldepth: c.add_layer(d, r_curve) # Use a Richards model c.install_connection(cmf.Richards) # Use shuttleworth wallace self.ET = c.install_connection(cmf.ShuttleworthWallace) c.saturated_depth = 0.5 self.gw = self.project.NewOutlet('groundwater', x=0, y=0, z=.9) cmf.Richards(c.layers[-1], self.gw) self.gw.potential = c.z - 0.5 #IMPORTANT self.gw.is_source = True self.gwhead = cmf.timeseries.from_scalar(c.z - 0.5) self.solver = cmf.CVodeIntegrator(self.project, 1e-9)
def canopyStorage(): import cmf import pylab as plt p = cmf.project() c = p.NewCell(0, 0, 0, 1000, True) # Add a single layer of 1 m depth l = c.add_layer(1.0, cmf.VanGenuchtenMualem()) # Use GreenAmpt infiltration from surface water c.install_connection(cmf.GreenAmptInfiltration) # Add a groundwater boundary condition gw = p.NewOutlet('gw', 0, 0, -2) # Use a free drainage connection to the groundwater cmf.FreeDrainagePercolation(l, gw) # Add some rainfall c.set_rainfall(5.0) # Make c.canopy a water storage c.add_storage('Canopy', 'C') # Split the rainfall from the rain source (RS) between # intercepted rainfall (RS->canopy) and throughfall (RS-surface) cmf.Rainfall(c.canopy, c, False, True) # RS->canopy, only intercepted rain cmf.Rainfall(c.surfacewater, c, True, False) # RS->surface, only throughfall # Use an overflow mechanism, eg. the famous Rutter-Interception Model cmf.RutterInterception(c.canopy, c.surfacewater, c) # And now the evaporation from the wet canopy (using a classical Penman equation) cmf.CanopyStorageEvaporation(c.canopy, c.evaporation, c) solver = cmf.CVodeIntegrator(p, 1e-9) res = [l.volume for t in solver.run(solver.t, solver.t + cmf.day, cmf.min * 15)] plt.figure() plt.plot(res) plt.show()
def make_vgm(params): try: vgm = cmf.VanGenuchtenMualem(1.0) vgm.Phi = params[0] vgm.alpha = params[1] vgm.n = params[2] if len(params) > 3: vgm.theta_r = params[3] return vgm except RuntimeError: return None
def retention_curve(r_curve_: dict): """ Converts a dict of retention curve parameters into a CMF van Genuchten-Mualem retention curve. :param r_curve_: dict :return: CMF retention curve """ curve = cmf.VanGenuchtenMualem(r_curve_['K_sat'], r_curve_['phi'], r_curve_['alpha'], r_curve_['n'], r_curve_['m']) curve.l = r_curve_['l'] return curve
def cell_setup(self): """ Creates a cmf cell with all its layers and DECOMP pools :return: decomp.cmfconnector.CmfConnector """ p = self.project c = p.NewCell(0, area=1000, with_surfacewater=True) vgm = cmf.VanGenuchtenMualem() vgm.fit_w0() for d in self.depth: vgm.Ksat = 10 * 2**-d c.add_layer(d, vgm) c.install_connection(cmf.Richards) c.install_connection(cmf.GreenAmptInfiltration) return CmfConnector(c, 5)
def set_parameters(self, par): """ Sets the parameters of the model :param par: The parameter value object (named tuple) :return: """ try: for l in self.cell.layers: r_curve = cmf.VanGenuchtenMualem(Ksat=10**par.pKsat, phi=par.porosity, alpha=par.alpha, n=par.n) r_curve.w0 = r_curve.fit_w0() l.soil = r_curve self.cell.saturated_depth = 0.5 self.gw.potential = self.cell.z - 0.5 except RuntimeError as e: sys.stderr.write('Set parameters failed with:\n' + str(par) + '\n' + str(e)) raise
def create_retention_curve(retention_curve: dict) -> cmf.VanGenuchtenMualem: """ Converts a dict of retention curve parameters into a CMF van Genuchten-Mualem retention curve. :param retention_curve: dict :return: CMF retention curve """ curve = cmf.VanGenuchtenMualem(retention_curve['k_sat'], retention_curve['phi'], retention_curve['alpha'], retention_curve['n'], retention_curve['m']) curve.l = retention_curve['l'] logger.debug(f'Created retention curve.') return curve
def fit_vgm(pF, theta, variable_m=False, count=20, fitlevel=None, verbose=False): """Fits a Van Genuchten / Mualem retention curve into data pF: a sequence of pF values theta: an array of water contents alpha_range: a 2-sequence holding the range for alpha values n_range: a 2-sequence holding the range for n values """ theta_mean = np.mean(theta) ns_denom = np.sum((theta - theta_mean)**2) best_f = 1e120 vgm = None for i in range(count): x0 = [ random.uniform(0.01, 0.99), random.uniform(0.0001, 1.9), random.uniform(1.01, 3.9), random.uniform() ] x0[-1] *= x0[0] if variable_m: x0.append(1 - 1 / random.uniform(1.01, 5)) x_opt, f_opt, n_iter, n_eval, warn = opt.fmin(get_error_vgm, x0=np.array(x0), args=(pF, theta), full_output=True, disp=False) if f_opt < best_f: if verbose: print("%i: x=%s f=%0.12g iter=%i, eval=%i" % (i, x_opt, f_opt, n_iter, n_eval)) vgm = cmf.VanGenuchtenMualem(1, *x_opt) best_f = f_opt if fitlevel and best_f < fitlevel: break theta_mean = np.mean(theta) return vgm, best_f
def soiltype(depth): return cmf.VanGenuchtenMualem(Ksat=15 * exp(-d), phi=0.5, n=1.5, alpha=0.3 )
@author: kraft-p """ import cmf # Create project with space delimited tracer names p = cmf.project('X Y Z') # Get the tracers as variables X, Y, Z = p.solutes # Create a single cell c with a surfacewater storage, which references 3 solute storages c = p.NewCell(0, 0, 0, 1000, with_surfacewater=True) # Create 50 layers with 2cm thickness for i in range(50): # Add a layer. Each layer will reference 3 solute storages l = c.add_layer((i + 1) * 0.02, cmf.VanGenuchtenMualem()) # Add a 10% decay per day for Tracer z l.Solute(Z).decay = 0.25 # Use Richards equation c.install_connection(cmf.Richards) # Use a constant rainfall of 50 mm c.set_rainfall(100.) # Make a groundwater boundary condition gw = p.NewOutlet('gw', 0, 0, -1.5) cmf.Richards(c.layers[-1], gw) # Template for the water solver #wsolver = cmf.CVodeIntegrator(1e-9) # Template for the solute solver #ssolver = cmf.ImplicitEuler(1e-9)
def create_layers(self, soil_horizons, params, based_on_spotpy=False): """ Creates a list of layers with attributes taken from a csv file (created via Brook90). :param params: class containing all parameters :param based_on_spotpy: :param soil_horizons: data frame including Van-Genuchten-Mualem soil parameters :return: A list of the lower boundaries of all created layer """ layer_boundary = [] layer_type = [] for i, row in soil_horizons.iterrows(): depth = -soil_horizons['Depth(m)'][i] # for positive values if depth > 0: layer_boundary.append(depth) layer_type.append(row['HorId']) if row['HorId'] == 'Ah': phi = params.porosity_mx_ah w0 = params.w0_ah elif row['HorId'] == 'Bv1': phi = params.porosity_mx_bv1 w0 = params.w0_bv1 elif row['HorId'] == 'Bv2': phi = params.porosity_mx_bv2 w0 = params.w0_bv2 else: phi = (params.porosity_mx_ah + params.porosity_mx_bv1 + params.porosity_mx_bv2) / 3 w0 = (params.w0_ah + params.w0_bv1 + params.w0_bv2) / 3 if based_on_spotpy: if row['HorId'] == 'Ah': k = params.ksat_mx_ah alpha = params.alpha_ah n = params.n_ah m = params.m_ah elif row['HorId'] == 'Bv1': k = params.ksat_mx_bv1 alpha = params.alpha_bv1 n = params.n_bv1 m = params.m_bv1 elif row['HorId'] == 'Bv2': k = params.ksat_mx_bv2 alpha = params.alpha_bv2 n = params.n_bv2 m = params.m_bv2 else: k = (params.ksat_mx_ah + params.ksat_mx_bv1 + params.ksat_mx_bv2) / 3 alpha = (params.alpha_ah + params.alpha_bv1 + params.alpha_bv2) / 3 n = (params.n_ah + params.n_bv1 + params.n_bv2) / 3 m = (params.m_ah + params.m_bv1 + params.m_bv2) / 3 else: k = row['KS/KF[m/d]'] alpha = row['Alfa/PsiF[m-1]/[kPa]'] / 100 n = row['n/b'] m = 1 - 1 / n vgm = cmf.VanGenuchtenMualem(Ksat=k, phi=phi, alpha=alpha, n=n, m=m, w0=w0) self.c.add_layer(depth, vgm) return layer_boundary, layer_type
import cmf from cmf.geos_shapereader import Shapefile as cmf_shape p = cmf.project() r_curve = cmf.VanGenuchtenMualem() # Load cell polygons from file path = r'C:\Users\Christian\Desktop\Livestock\shapefiles\shape_mesh.shp' polygons = cmf_shape(path) # create cell mesh from polygons cells = p.cells_from_polygons(polygons) for c in p.cells: # Add ten layers for i in range(10): c.AddLayer((i + 1) * 0.1, r_curve) cmf.Richards.use_for_cell(c) c.surfacewater_as_storage() # subsurface flow cmf.connect_cells_with_flux(p, cmf.Richards_lateral) # surface runoff cmf.connect_cells_with_flux(p, cmf.Manning_Kinematic)
# create a project p = cmf.project() for i in range(20): x = i * 10. # create a cell with surface storage c = p.NewCell(x,0,z(x),100,True) for c_upper, c_lower in zip(p[:-1], p[1:]): c_upper.topology.AddNeighbor(c_lower, 10.) # Customize cells for c in p: # create layers for d in [0.02,0.05,0.1,0.2,0.3,0.5,0.75,1.0,1.25,1.5,1.75,2.]: rc = cmf.VanGenuchtenMualem(Ksat=50*np.exp(-d),alpha=0.1,n=2.0,phi=0.5) rc.w0 = 0.9996 c.add_layer(d,rc) # set initial conditions c.saturated_depth=2. # use Richards connection c.install_connection(cmf.Richards) c.install_connection(cmf.GreenAmptInfiltration) # Add more connections here... (eg. ET, snowmelt, canopy overflow) cmf.connect_cells_with_flux(p,cmf.Darcy) cmf.connect_cells_with_flux(p,cmf.KinematicSurfaceRunoff) for c in p: c.set_rainfall(10.)
def aggregate_infiltration(self, t): return np.array([mp.flux_to(mp.layer, t) for mp in self]) # Create project and a cell with surfacewater if 'X' in sys.argv: p = cmf.project('X') X, = p.solutes else: p = cmf.project() X = None c = p.NewCell(0, 0, 0, 1000, True) # Add some layers vgm = cmf.VanGenuchtenMualem(Ksat=Ksat_mx, phi=0.5) for d in np.arange(0, 1, 0.02): c.add_layer(d + .02, vgm) # Use Richards equation for matrix transport c.install_connection(cmf.Richards) c.install_connection(cmf.MatrixInfiltration) # Create Macropore storages for each layer macropores = MacroPoreList( cmf.MacroPore.create( l, porefraction=porefraction, Ksat=Ksat_mp, density=0.1) for l in c.layers) # Macro pore infiltration cmf.KinematicMacroFlow(c.surfacewater, macropores[0]) # Macro pore percolation
if i: c.topology.AddNeighbor(cells[i-1,j],length*.75) if j: c.topology.AddNeighbor(cells[i,j-1],length*.75) #if i and j: #c.topology.AddNeighbor(cells[i,j-1],length*.5) for c in p: c.surfacewater_as_storage() # 1mm puddle depth c.surfacewater.puddledepth = 0.001 #np.random.uniform(0.0,0.001) #c.surfacewater.depth = 0.002 # Asphalt c.surfacewater.nManning = 0.015 c.add_layer(0.1, cmf.VanGenuchtenMualem(Ksat=0.005)) c.install_connection(cmf.GreenAmptInfiltration) cmf.DiffusiveSurfaceRunoff.set_linear_slope(1e-8) cmf.connect_cells_with_flux(p, cmf.DiffusiveSurfaceRunoff) outlet = p.NewOutlet('outlet',-length,0,-slope*length) #for j in range(size[1]): # for i in range(size[0]): # is_border = i in [0,size[0]-1] or j in [0, size[1]-1] # if is_border: # cmf.waterbalance_connection(cells[i,j].surfacewater,outlet) cmf.DiffusiveSurfaceRunoff(cells[0,0].surfacewater, outlet,length) def setrain(rainfall): for c in p: c.set_rainfall(rainfall)
def simple1D(): from matplotlib import pyplot as plt import cmf from datetime import datetime, timedelta project = cmf.project() # Add one cell at position (0,0,0), Area=1000m2 cell = project.NewCell(0, 0, 0, 1000, with_surfacewater=True) # Create a retention curve r_curve = cmf.VanGenuchtenMualem(Ksat=1, phi=0.5, alpha=0.01, n=2.0) # Add ten layers of 10cm thickness for i in range(10): depth = (i + 1) * 0.1 cell.add_layer(depth, r_curve) # Connect layers with Richards perc. # this can be shorten as cell.install_connection(cmf.Richards) # Create solver solver = cmf.CVodeIntegrator(project, 1e-6) solver.t = cmf.Time(1, 1, 2011) # Create groundwater boundary (uncomment to use it) # Create the boundary condition gw = project.NewOutlet('groundwater', x=0, y=0, z=-1.1) # Set the potential gw.potential = -2 # Connect the lowest layer to the groundwater using Richards percolation gw_flux=cmf.Richards(cell.layers[-1],gw) # Set inital conditions # Set all layers to a potential of -2 m cell.saturated_depth = 2. # 100 mm water in the surface water storage cell.surfacewater.depth = 0.1 # The run time loop, run for 72 hours # Save potential and soil moisture for each layer potential = [cell.layers.potential] moisture = [cell.layers.theta] for t in solver.run(solver.t, solver.t + timedelta(days=7), timedelta(hours=1)): potential.append(cell.layers.potential) moisture.append(cell.layers.theta) """ # Plot results plt.subplot(211) plt.plot(moisture) plt.ylabel(r'Soil moisture $\theta [m^3/m^3]$') plt.xlabel(r'$time [h]$') plt.grid() plt.subplot(212) plt.plot(potential) plt.ylabel(r'Water head $\Psi_{tot} [m]$') plt.xlabel(r'$time [h]$') plt.grid() plt.show() """ print(cell.vegetation)
def _run(self, alpha=None, n=None, porosity=None, ksat=None): #return alpha,n,porosity,ksat ''' Runs the model instance Input: Parameter set (in this case VAN-Genuchten Parameter alpha,n,porosity,ksat) Output: Simulated values on given observation days ''' #Check if given parameter set is in realistic boundaries if alpha<self.bound[0][0] or alpha>self.bound[0][1] or ksat<self.bound[1][0] \ or ksat>self.bound[1][1] or n<self.bound[2][0] or n>self.bound[2][1] or \ porosity<self.bound[3][0] or porosity>self.bound[3][1]: print('The following combination was ignored') text = 'n= ' + str(n) print(text) text = 'alpha=' + str(alpha) print(text) text = 'ksat= ' + str(ksat) print(text) text = 'porosity= ' + str(porosity) print(text) print('##############################') return self.observations * -np.inf else: project = cmf.project() cell = project.NewCell(x=0, y=0, z=0, area=1000, with_surfacewater=True) text = 'n= ' + str(n) print(text) text = 'alpha=' + str(alpha) print(text) text = 'ksat= ' + str(ksat) print(text) text = 'porosity= ' + str(porosity) print(text) print('##############################') r_curve = cmf.VanGenuchtenMualem(Ksat=ksat, phi=porosity, alpha=alpha, n=n) layers = 5 ldepth = .01 for i in range(layers): depth = (i + 1) * ldepth cell.add_layer(depth, r_curve) cell.install_connection(cmf.Richards) cell.install_connection(cmf.ShuttleworthWallace) cell.saturated_depth = .5 solver = cmf.CVodeIntegrator(project, 1e-6) self._load_meteo(project) gw = project.NewOutlet('groundwater', x=0, y=0, z=.9) #layers*ldepth) cmf.Richards(cell.layers[-1], gw) gw.potential = -.5 #IMPORTANT gw.is_source = True solver.t = self.datastart Evalstep, evallist = 0, [] rundays = (self.dataend - self.datastart).days for t in solver.run(solver.t, solver.t + timedelta(days=rundays), timedelta(hours=1)): if self.gw_array['Date'].__contains__(t) == True: Gw_Index = np.where(self.gw_array['Date'] == t) gw.potential = self.gw_array[self.piezometer][Gw_Index] print(gw.potential ) #TO DO: CHECK IF SOMETHING HAPPENS HERE!!!! if t > self.analysestart: if Evalstep != len(self.eval_dates ) and t == self.eval_dates[Evalstep]: evallist.append(cell.layers.wetness[0] * cell.layers.porosity[0] * 100) Evalstep += 1 return evallist