def test_sed_dep(): input_file = os.path.join(_THIS_DIR, "sed_dep_params.txt") inputs = ModelParameterDictionary(input_file, auto_type=True) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") uplift_rate = inputs.read_float("uplift_rate") runtime = inputs.read_float("total_time") dt = inputs.read_float("dt") nt = int(runtime // dt) uplift_per_step = uplift_rate * dt mg = RasterModelGrid((nrows, ncols), xy_spacing=(dx, dx)) mg.add_zeros("topographic__elevation", at="node") z = np.loadtxt(os.path.join(_THIS_DIR, "seddepinit.txt")) mg["node"]["topographic__elevation"] = z mg.set_closed_boundaries_at_grid_edges(True, False, True, False) fr = FlowAccumulator(mg, flow_director="D8") sde = SedDepEroder(mg, **inputs) for i in range(nt): mg.at_node["topographic__elevation"][mg.core_nodes] += uplift_per_step mg = fr.run_one_step() mg, _ = sde.erode(dt) z_tg = np.loadtxt(os.path.join(_THIS_DIR, "seddepz_tg.txt")) assert_array_almost_equal( mg.at_node["topographic__elevation"][mg.core_nodes], z_tg[mg.core_nodes] )
def __init__(self, grid, input_stream): self.grid = grid inputs = ModelParameterDictionary(input_stream) # User sets: self.K = inputs.read_float("K_sp") self.m = inputs.read_float("m_sp") try: self.n = inputs.read_float("n_sp") except: self.n = 1.0 try: self.dt = inputs.read_float("dt") except: # if dt isn't supplied, it must be set by another module, so look in the grid print "Set dynamic timestep from the grid. You must call gear_timestep() to set dt each iteration." else: try: self.r_i = inputs.read_float("dt") except: self.r_i = 1.0 try: self.value_field = inputs.read_str("value_field") except: self.value_field = "planet_surface__elevation" # make storage variables self.A_to_the_m = grid.create_node_array_zeros() self.alpha = grid.empty(centering="node") if self.n != 1.0: raise ValueError("The Braun Willett stream power algorithm requires n==1. at the moment, sorry...")
def __init__(self, grid, input_stream): #grid here is a true model field. i.e., we should be able to do grid.at_node['topographic__elevation'] #input_stream is a text file, entered in format './my_file.txt' self.grid = grid inputs = ModelParameterDictionary(input_stream) self.n = inputs.read_float('n') # roughness coefficient (Manning's n) self.g = inputs.read_float('g') # gravitational acceleration (m/s2) self.alpha = inputs.read_float('alpha') # time-step factor (ND; from Bates et al., 2010) self.tau_crit = inputs.read_float('tau_crit') # critical shear stress, pascals self.mpm = inputs.read_float('mpm') # sed trans coefficient self.erode_start_time = inputs.read_float('erode_start_time') # allows an offset between when flow starts and when we start to allow erosion #test the necessary fields are all already present: try: self.z = grid.at_node['topographic__elevation'] except: warnings.warn('elevations not found in grid!') try: self.h = grid.at_node['planet_surface__water_depth'] except: warnings.warn('initial water depths not found in grid!') #build the internally necessary params: self.rhog = 9810. # water unit weight, kg/m2s2 (N/m3) self.q = grid.zeros(at='active_link') # unit discharge (m2/s) self.dhdt = grid.zeros(at='node') # rate of water-depth change self.tau = grid.zeros(at='active_link') # shear stress (Pa) self.qs = grid.zeros(at='active_link') # sediment flux (m2/s) self.dqsds = grid.zeros(at='node') self.dzdt = self.dhdt self.dzaccum = grid.zeros(at='node') self.zm = grid.zeros(at='node') self.zm[:] = self.z[:]
def test_storms(): input_file_string = os.path.join(_THIS_DIR, 'drive_sp_params_storms.txt') inputs = ModelParameterDictionary(input_file_string) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') uplift = inputs.read_float('uplift_rate') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') mg['node']['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.add_zeros('water__unit_flux_in', at='node') precip = PrecipitationDistribution(input_file=input_file_string) fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) for (interval_duration, rainfall_rate) in \ precip.yield_storm_interstorm_duration_intensity(): if rainfall_rate != 0.: mg.at_node['water__unit_flux_in'].fill(rainfall_rate) mg = fr.route_flow() sp.run_one_step(dt) mg.at_node['topographic__elevation'][ mg.core_nodes] += uplift * interval_duration
def __init__(self, grid, input_stream): self.grid = grid inputs = ModelParameterDictionary(input_stream) #User sets: self.K = inputs.read_float('K_sp') self.m = inputs.read_float('m_sp') try: self.n = inputs.read_float('n_sp') except: self.n = 1. try: self.dt = inputs.read_float('dt') except: #if dt isn't supplied, it must be set by another module, so look in the grid print 'Set dynamic timestep from the grid. You must call gear_timestep() to set dt each iteration.' else: try: self.r_i = inputs.read_float('rainfall_intensity') except: self.r_i = 1. try: self.value_field = inputs.read_str('value_field') except: self.value_field = 'planet_surface__elevation' #make storage variables self.A_to_the_m = grid.create_node_array_zeros() self.alpha = grid.empty(centering='node') if self.n != 1.: raise ValueError('The Braun Willett stream power algorithm requires n==1. at the moment, sorry...')
def initialize(self, input_stream): # Create a ModelParameterDictionary for the inputs if type(input_stream)==ModelParameterDictionary: inputs = input_stream else: inputs = ModelParameterDictionary(input_stream) # Read input/configuration parameters self.kd = inputs.read_float('DIFMOD_KD') try: self.uplift_rate = inputs.read_float('DIFMOD_UPLIFT_RATE') except: self.uplift_rate = inputs.read_float('uplift_rate') try: self.values_to_diffuse = inputs.read_str('values_to_diffuse') except: self.values_to_diffuse = 'planet_surface__elevation' try: self.timestep_in = inputs.read_float('dt') except: print 'No fixed timestep supplied, it must be set dynamically somewhere else. Be sure to call input_timestep(timestep_in) as part of your run loop.' # Create grid if one doesn't already exist if self.grid==None: self.grid = create_and_initialize_grid(input_stream) # Set internal time step # ..todo: # implement mechanism to compute time-steps dynamically if grid is # adaptive/changing dx = self.grid.min_active_link_length() # smallest active link length self.dt = _ALPHA*dx*dx/self.kd # CFL condition try: self.tstep_ratio = self.timestep_in/self.dt except: pass # Get a list of interior cells self.interior_cells = self.grid.get_core_cell_node_ids() # Here we're experimenting with different approaches: with # 'make_all_data', we create and manage all the data we need and embed # it all in the grid. With 'explicit', we require the caller/user to # provide data. if _VERSION=='make_all_data': #print 'creating internal data' self.z = self.grid.add_zeros('node', 'landscape_surface__elevation') self.g = self.grid.add_zeros('active_link', 'landscape_surface__gradient') # surface gradients self.qs = self.grid.add_zeros('active_link','unit_sediment_flux') # unit sediment flux self.dqds = self.grid.add_zeros('node', 'sediment_flux_divergence') # sed flux derivative elif _VERSION=='explicit': pass else: # Create data arrays for variables that won't (?) be shared with other # components self.g = self.grid.create_active_link_array_zeros() # surface gradients self.qs = self.grid.create_active_link_array_zeros() # unit sediment flux self.dqds = self.grid.create_node_array_zeros() # sed flux derivative
def initialize( self ): MPD = ModelParameterDictionary() MPD.read_from_file( _DEFAULT_INPUT_FILE ) # Reading Input Parameters self._N = MPD.read_float( 'CLOUDINESS' ) self._latitude = MPD.read_float( 'LATITUDE' ) self._A = MPD.read_float( 'ALBEDO' )
def __init__(self, input_file=None, mean_storm=None, mean_interstorm=None, mean_storm_depth=None, total_t=None, delta_t=None): """ This reads in information from the input_file (either default or user assigned, and creates an instantaneous storm event drawn from the Poisson distribution """ # First we create an instance of the Model Parameter Dictionary MPD = ModelParameterDictionary() # If no input_file is given,the default file is used if input_file is None: input_file = _DEFAULT_INPUT_FILE # This reads in the file information MPD.read_from_file(input_file) # And now we set our different parameters # using the model parameter dictionary... if mean_storm == None: self.mean_storm = MPD.read_float( 'MEAN_STORM') else: self.mean_storm = mean_storm if mean_interstorm == None: self.mean_interstorm = MPD.read_float( 'MEAN_INTERSTORM') else: self.mean_interstorm =mean_interstorm if mean_storm_depth== None: self.mean_storm_depth = MPD.read_float( 'MEAN_DEPTH') else: self.mean_storm_depth =mean_storm_depth if total_t== None: self.run_time = MPD.read_float( 'RUN_TIME') else: self.run_time =total_t if delta_t== None: self.delta_t = MPD.read_int( 'DELTA_T') else: self.detla_t =delta_t # Mean_intensity is not set by the MPD, but can be drawn from # the mean storm depth and mean storm duration. self.mean_intensity = self.mean_storm_depth / self.mean_storm # If a time series is created later, this blank list will be used. self.storm_time_series =[] # Given the mean values assigned above using either the model # parameter dictionary or the init function, we can call the # different methods to assign values from the Poisson distribution. self.storm_duration = self.get_precipitation_event_duration() self.interstorm_duration = self.get_interstorm_event_duration() self.storm_depth = self.get_storm_depth() self.intensity = self.get_storm_intensity()
def initialize(self, grid=None, input_file=None, intensity=None, stormduration=None): self.grid = grid if self.grid==None: self.grid = create_and_initialize_grid(input_file) ##self.current_time = current_time <- this isn't being used yet. # Create a ModelParameterDictionary for the inputs MPD = ModelParameterDictionary() ## I am not sure we want to use an instance of MPD as an input_file. I'm confused about this. SO for ## now I changed this to reflect other component types if input_file is None: input_file = _DEFAULT_INPUT_FILE MPD.read_from_file(input_file) ## This was the old way... where an instance of MPD is an input_file #if type(input_file)==MPD: # inputs = input_file #else: # inputs = MPD(input_file) # Read input/configuration parameters self.m_n = MPD.read_float('MANNINGS_N') if intensity == None: self.rainfall_mmhr = MPD.read_float( 'RAINFALL_RATE') else: self.rainfall_mmhr = intensity if stormduration == None: self.rain_duration = MPD.read_float( 'RAIN_DURATION' ) else: self.rain_duration = stormduration #self.h_init = 0.001 # initial thin layer of water (m) #self.g = 9.8 # gravitational acceleration (m/s2) #self.alpha = 0.2 # time-step factor (ND; from Bates et al., 2010) #self.m_n_sq = self.m_n*self.m_n # manning's n squared #self.rho = 1000 # density of water, kg/m^3 # Derived parameters ## THIS IS IMPORTANT - UNITS!!!! Double check precip component... self.rainfall_rate = (self.rainfall_mmhr/1000.)/3600. # rainfall in m/s # Set up state variables self.hstart = grid.zeros(centering='node') + self.h_init self.h = grid.zeros(centering='node') + self.h_init # water depth (m) #NG why is water depth at each node and not at cells, which are only active self.q = grid.zeros(centering='active_link') # unit discharge (m2/s) self.dhdt = grid.zeros(centering='active_cell') # rate of water-depth change
def __init__(self, grid, input_stream): self.grid = grid inputs = ModelParameterDictionary(input_stream) #User sets: try: self.K = inputs.read_float('K_sp') except ParameterValueError: self.use_K = True else: self.use_K = False self.m = inputs.read_float('m_sp') try: self.n = inputs.read_float('n_sp') except: self.n = 1. try: self.dt = inputs.read_float('dt') except: #if dt isn't supplied, it must be set by another module, so look in the grid print('Set dynamic timestep from the grid. You must call gear_timestep() to set dt each iteration.') try: self.r_i = inputs.read_float('rainfall_intensity') except: self.r_i = 1. try: self.value_field = inputs.read_str('value_field') except: self.value_field = 'topographic__elevation' #make storage variables self.A_to_the_m = grid.create_node_array_zeros() self.alpha = grid.empty(centering='node') self.alpha_by_flow_link_lengthtothenless1 = numpy.empty_like(self.alpha) self.grid.node_diagonal_links() #calculates the number of diagonal links if self.n != 1.: #raise ValueError('The Braun Willett stream power algorithm requires n==1. at the moment, sorry...') self.nonlinear_flag = True if self.n<1.: print("***WARNING: With n<1 performance of the Fastscape algorithm is slow!***") else: self.nonlinear_flag = False def func_for_newton(x, last_step_elev, receiver_elev, alpha_by_flow_link_lengthtothenless1, n): y = x - last_step_elev + alpha_by_flow_link_lengthtothenless1*(x-receiver_elev)**n return y def func_for_newton_diff(x, last_step_elev, receiver_elev, alpha_by_flow_link_lengthtothenless1, n): y = 1. + n*alpha_by_flow_link_lengthtothenless1*(x-receiver_elev)**(n-1.) return y self.func_for_newton = func_for_newton self.func_for_newton_diff = func_for_newton_diff
def test_sp_new(): """ Tests new style component instantiation and run. """ input_str = os.path.join(_THIS_DIR, 'drive_sp_params.txt') inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') uplift = inputs.read_float('uplift_rate') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid((nrows, ncols), spacing=(dx, dx)) mg.set_closed_boundaries_at_grid_edges(False, False, True, True) mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev numpy.random.seed(0) mg['node']['topographic__elevation'] = z + \ numpy.random.rand(len(z)) / 1000. fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) elapsed_time = 0. while elapsed_time < time_to_run: if elapsed_time + dt > time_to_run: dt = time_to_run - elapsed_time fr.route_flow() sp.run_one_step(dt) mg.at_node['topographic__elevation'][mg.core_nodes] += uplift * dt elapsed_time += dt z_trg = numpy.array([5.48813504e-04, 7.15189366e-04, 6.02763376e-04, 5.44883183e-04, 4.23654799e-04, 6.45894113e-04, 1.02783376e-02, 9.66667235e-03, 6.15060782e-03, 3.83441519e-04, 7.91725038e-04, 1.00905776e-02, 8.98955843e-03, 5.32836181e-03, 7.10360582e-05, 8.71292997e-05, 9.96377080e-03, 9.63738797e-03, 7.31213677e-03, 8.70012148e-04, 9.78618342e-04, 1.02124693e-02, 8.78386002e-03, 4.88161060e-03, 1.18274426e-04, 6.39921021e-04, 1.00377580e-02, 9.54340293e-03, 6.05173814e-03, 4.14661940e-04, 2.64555612e-04, 1.02160196e-02, 8.61600088e-03, 4.77005225e-03, 1.87898004e-05, 6.17635497e-04, 9.30445558e-03, 9.48713993e-03, 7.25689742e-03, 6.81820299e-04, 3.59507901e-04, 5.79161813e-03, 6.83777542e-03, 6.18063842e-03, 6.66766715e-04, 6.70637870e-04, 2.10382561e-04, 1.28926298e-04, 3.15428351e-04, 3.63710771e-04]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_trg)
def test_sp_new(): """ Tests new style component instantiation and run. """ input_str = os.path.join(_THIS_DIR, 'drive_sp_params.txt') inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') uplift = inputs.read_float('uplift_rate') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid((nrows, ncols), spacing=(dx, dx)) mg.set_closed_boundaries_at_grid_edges(False, False, True, True) mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev numpy.random.seed(0) mg['node']['topographic__elevation'] = z + \ numpy.random.rand(len(z)) / 1000. fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) elapsed_time = 0. while elapsed_time < time_to_run: if elapsed_time + dt > time_to_run: dt = time_to_run - elapsed_time fr.route_flow() sp.run_one_step(dt) mg.at_node['topographic__elevation'][mg.core_nodes] += uplift * dt elapsed_time += dt z_trg = numpy.array([5.48813504e-04, 7.15189366e-04, 6.02763376e-04, 5.44883183e-04, 4.23654799e-04, 6.45894113e-04, 1.01830760e-02, 9.58036770e-03, 6.55865452e-03, 3.83441519e-04, 7.91725038e-04, 1.00142749e-02, 8.80798884e-03, 5.78387585e-03, 7.10360582e-05, 8.71292997e-05, 9.81911417e-03, 9.52243406e-03, 7.55093226e-03, 8.70012148e-04, 9.78618342e-04, 1.00629755e-02, 8.49253798e-03, 5.33216680e-03, 1.18274426e-04, 6.39921021e-04, 9.88956320e-03, 9.47119567e-03, 6.43790696e-03, 4.14661940e-04, 2.64555612e-04, 1.00450743e-02, 8.37262908e-03, 5.21540904e-03, 1.87898004e-05, 6.17635497e-04, 9.21286940e-03, 9.34022513e-03, 7.51114450e-03, 6.81820299e-04, 3.59507901e-04, 6.19166921e-03, 7.10456176e-03, 6.62585507e-03, 6.66766715e-04, 6.70637870e-04, 2.10382561e-04, 1.28926298e-04, 3.15428351e-04, 3.63710771e-04]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_trg)
def initialize(self): """ Reading data from input file """ MPD = ModelParameterDictionary() MPD.read_from_file(_DEFAULT_INPUT_FILE) """ Priestly Taylor Constant """ self._alpha = MPD.read_float("alpha") """ Surface Albedo """ self._a = MPD.read_float("a") """ Latent Heat of Vaporization """ self._pwhv = MPD.read_float("pwhv") """ Psychometric Constant """ self._y = MPD.read_float("y") """ Stefan Boltzmann Constant """ self._sigma = MPD.read_float("sigma") """ Solar Constant """ self._Gsc = MPD.read_float("Gsc") """ Latitude of Location under Study """ self._lat = MPD.read_float("lat") """ Elevation of Location under Study """ self._z = MPD.read_float("z") """ Adjustment Coefficient """ self._Krs = MPD.read_float("Krs") """ Initialize Arrays """ """ Net Short Wave Radiation """ self._Rns = 0 """ Net Radiation """ self._Rn = 0 """ Clear Sky Solar Radiation """ self._Rso = 0 """ Short Wave Radiation """ self._Rs = 0 """ Relative cloudiness factor """ self._u = 0 """ Priestly Taylor evapotranspiration """ self._ETp = 0 """ Extraterrestrial Radiation """ self._Ra = 0 """ Julian Day """ self._J = 0 """ Sunset hour angle """ self._ws = 0 self._x = 0 """ Solar declination angle """ self._sdecl = 0 """ Inverse relative distance factor """ self._dr = 0 """ Cloudiness function """ self._fcd = 0 """ Latitude in radians """ self._phi = (3.14 / 180) * self._lat
def __init__(self, input_file=None): """All initial values are set to zero until initalized using the initialize() method which reads in data using the ModelParameterDictionary and sets the random variables according to their respective distribution. REQUIRED PARAMETERS ------------------ Shape Parameter: Describes the skew of the Weibull distribution. If shape < 3.5, data skews left. If shape == 3.5, data is normal. If shape > 3.5, data skews right. Scale Parameter: Describes the peak of the Weibull distribution, located at 63.5% value of the cumulative distribution function. If unknown, it can be found using mean fire recurrence value and the get_scale_parameter() method described later. Mean Fire Recurrence : Average recurrence for a given area, elevation, veg type, etc. Total Run Time : Total model run time Delta T : Model time step. ------- Time to Next Fire: Value generated from the random.weibullvariate() function based on the scale and shape parameters """ # We import methods from ModelParameterDictionary # to read the parameters from the input file. #If the scale parameter is unknown, it can be found using the mean # fire recurrence value, which MUST be known or estimated to run the # get_scale_parameter() method.""" MPD = ModelParameterDictionary() if input_file is None: input_file = _DEFAULT_INPUT_FILE MPD.read_from_file(input_file) self.shape_parameter = MPD.read_float("SHAPE_PARAMETER") self.scale_parameter = MPD.read_float("SCALE_PARAMETER") self.mean_fire_recurrence = MPD.read_float("MEAN_FIRE_RECURRENCE") self.total_run_time = MPD.read_float("RUN_TIME") self.delta_t = MPD.read_int("DELTA_T") self.time_to_next_fire = 0.0
def __init__(self, grid, input_file=None, rain_duration=None, rainfall_intensity=None, model_run_time=None): self.h_init = 0.001 self.g = 9.8 self.alpha = 0.2 self.rho = 1000 self.ten_thirds = 10./3. # Create a ModelParameterDictionary instance for the inputs MPD = ModelParameterDictionary() if input_file is None: input_file = _DEFAULT_INPUT_FILE MPD.read_from_file(input_file) self.current_time = 0.0 self.m_n = MPD.read_float('MANNINGS_N') self.m_n_sq = self.m_n*self.m_n if rainfall_intensity == None: self.rainfall_mmhr = MPD.read_float( 'RAINFALL_RATE') if rain_duration == None: self.rain_duration = MPD.read_float( 'RAIN_DURATION' ) if model_run_time == None: self.total_time = self.rain_duration # Conversion to m/s from mm/hr self.rainfall_rate = (self.rainfall_mmhr/1000.)/3600. # Set up grid arrays for state variables # Water Depth self.hstart = grid.zeros(centering='node') + self.h_init self.h = grid.zeros(centering='node') + self.h_init self.dhdt = grid.zeros(centering='cell') # Discharge self.q = grid.zeros(centering='active_link') # unit discharge (m2/s) # Tau self.tau = grid.zeros(centering='node') # shear stress (Pascals)
def test_sp_discharges_new(): input_str = os.path.join(_THIS_DIR, 'test_sp_params_discharge_new.txt') inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = np.array([5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5.]) mg['node']['topographic__elevation'] = z fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) # perform the loop (once!) for i in range(1): fr.route_flow() sp.run_one_step(dt) z_tg = np.array([5. , 5. , 0. , 5. , 5. , 5. , 1.47759225, 0.43050087, 1.47759225, 5. , 5. , 2.32883687, 1.21525044, 2.32883687, 5. , 5. , 3.27261262, 3.07175015, 3.27261262, 5. , 5. , 5. , 5. , 5. , 5. ]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_tl_fluvial(): input_file = os.path.join(_THIS_DIR, 'stream_power_params_ideal.txt') inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') uplift_rate = inputs.read_float('uplift_rate') runtime = inputs.read_float('total_time') dt = inputs.read_float('dt') nt = int(runtime // dt) uplift_per_step = uplift_rate * dt mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('node', 'topographic__elevation') z = np.loadtxt(os.path.join(_THIS_DIR, 'tl_init.txt')) mg['node']['topographic__elevation'] = z mg.set_closed_boundaries_at_grid_edges(True, False, True, False) mg.set_fixed_value_boundaries_at_grid_edges( False, True, False, True, value_of='topographic__elevation') fr = FlowRouter(mg) tl = TransportLimitedEroder(mg, input_file) for i in range(nt): mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_per_step mg = fr.route_flow() mg, _ = tl.erode(mg, dt, stability_condition='loose') z_tg = np.loadtxt(os.path.join(_THIS_DIR, 'tlz_tg.txt')) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def initialize(self, input_file=None): MPD = ModelParameterDictionary() """We imported methods from ModelParameterDictionary to read the parameters from the input file. Necessary parameters to run this code include: mean_storm (type: float) mean_intensity (type: float) mean_interstorm (type: float) mean_storm_depth is calculated using mean storm and intensity data The random variables of storm_duration, interstorm_duration, storm_depth and intensity are found using methods declared later in the class """ if input_file is None: input_file = _DEFAULT_INPUT_FILE MPD.read_from_file(input_file) self.mean_storm = MPD.read_float( "MEAN_STORM" ) self.mean_interstorm = MPD.read_float( "MEAN_INTERSTORM" ) self.mean_storm_depth = MPD.read_float( "MEAN_DEPTH" ) self.mean_intensity = self.mean_storm_depth / self.mean_storm self.storm_duration = self.get_precipitation_event_duration() self.interstorm_duration = self.get_interstorm_event_duration() self.storm_depth = self.get_storm_depth() self.intensity = self.get_storm_intensity() self.run_time = MPD.read_float("RUN_TIME") try: #DEJH thinks this is redundant self.delta_t = MPD.read_int("DELTA_T") except: pass
def initialize( self ): MPD = ModelParameterDictionary() MPD.read_from_file(_DEFAULT_INPUT_FILE) self._vegcover = MPD.read_float( 'VEG_COV' ) self._WUE = MPD.read_float( 'WUE' ) self._LAI_max = MPD.read_float( 'LAI_MAX' ) self._cb = MPD.read_float( 'CB' ) self._cd = MPD.read_float( 'CD' ) self._ksg = MPD.read_float( 'KSG' ) self._kdd = MPD.read_float( 'KDD' ) self._Blive_ini = MPD.read_float( 'BLIVE_INI' ) self._Bdead_ini = MPD.read_float( 'BDEAD_INI' )
def test_sp_widths(): input_str = os.path.join(_THIS_DIR, 'test_sp_params_widths.txt') inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') mg = RasterModelGrid(nrows, ncols, dx) widths = np.ones(mg.number_of_nodes, dtype=float) mg.add_zeros('topographic__elevation', at='node') z = np.array([5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5.]) mg['node']['topographic__elevation'] = z fr = FlowRouter(mg) sp = StreamPowerEroder(mg, use_W=widths, **inputs) # perform the loop (once!) for i in range(1): fr.route_flow() sqrt_A = mg.at_node['drainage_area']**0.5 widths[mg.core_nodes] = sqrt_A[mg.core_nodes]/sqrt_A[ mg.core_nodes].mean() # so widths has mean=1. # note the issue with drainage_area not defined at perimeter => nans # if not careful... sp.run_one_step(dt) z_tg = np.array([ 5. , 5. , 0. , 5. , 5. , 5. , 1.37222369, 0.36876358, 1.37222369, 5. , 5. , 2.17408606, 1.07986038, 2.17408606, 5. , 5. , 3.08340277, 2.85288049, 3.08340277, 5. , 5. , 5. , 5. , 5. , 5. ]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_storms(): input_file_string = os.path.join(_THIS_DIR, "drive_sp_params_storms.txt") inputs = ModelParameterDictionary(input_file_string, auto_type=True) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") uplift = inputs.read_float("uplift_rate") mean_duration = inputs.read_float("mean_storm") mean_interstorm = inputs.read_float("mean_interstorm") mean_depth = inputs.read_float("mean_depth") storm_run_time = inputs.read_float("storm_run_time") delta_t = inputs.read_float("delta_t") mg = RasterModelGrid(nrows, ncols, xy_spacing=dx) mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") mg["node"]["topographic__elevation"] = z + np.random.rand(len(z)) / 1000. mg.add_zeros("water__unit_flux_in", at="node") precip = PrecipitationDistribution( mean_storm_duration=mean_duration, mean_interstorm_duration=mean_interstorm, mean_storm_depth=mean_depth, total_t=storm_run_time, delta_t=delta_t, ) fr = FlowAccumulator(mg, flow_director="D8") sp = StreamPowerEroder(mg, **inputs) for ( interval_duration, rainfall_rate, ) in precip.yield_storm_interstorm_duration_intensity(): if rainfall_rate != 0.: mg.at_node["water__unit_flux_in"].fill(rainfall_rate) fr.run_one_step() sp.run_one_step(dt) mg.at_node["topographic__elevation"][mg.core_nodes] += ( uplift * interval_duration )
def test_storms(): input_file_string = os.path.join(_THIS_DIR, 'drive_sp_params_storms.txt') inputs = ModelParameterDictionary(input_file_string, auto_type=True) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') uplift = inputs.read_float('uplift_rate') mean_duration = inputs.read_float('mean_storm') mean_interstorm = inputs.read_float('mean_interstorm') mean_depth = inputs.read_float('mean_depth') storm_run_time = inputs.read_float('storm_run_time') delta_t = inputs.read_float('delta_t') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') mg['node']['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.add_zeros('water__unit_flux_in', at='node') precip = PrecipitationDistribution(mean_storm_duration = mean_duration, mean_interstorm_duration = mean_interstorm, mean_storm_depth = mean_depth, total_t = storm_run_time, delta_t = delta_t) fr = FlowAccumulator(mg, flow_director='D8') sp = StreamPowerEroder(mg, **inputs) for (interval_duration, rainfall_rate) in \ precip.yield_storm_interstorm_duration_intensity(): if rainfall_rate != 0.: mg.at_node['water__unit_flux_in'].fill(rainfall_rate) fr.run_one_step() sp.run_one_step(dt) mg.at_node['topographic__elevation'][ mg.core_nodes] += uplift * interval_duration
def test_sp_discharges(): input_str = os.path.join(_THIS_DIR, 'test_sp_params_discharge.txt') inputs = ModelParameterDictionary(input_str) nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = np.array([5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5.]) mg['node']['topographic__elevation'] = z fr = FlowRouter(mg) sp = StreamPowerEroder(mg, input_str) # perform the loop (once!) for i in range(1): fr.route_flow(method='D8') my_Q = mg.at_node['water__volume_flux'] * 1. sp.erode(mg, dt, node_drainage_areas='drainage_area', slopes_at_nodes='topographic__steepest_slope', Q_if_used=my_Q) z_tg = np.array([5.00000000e+00, 5.00000000e+00, 0.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 1.29289322e+00, 1.00000000e-06, 1.29289322e+00, 5.00000000e+00, 5.00000000e+00, 2.29289322e+00, 1.00000000e+00, 2.29289322e+00, 5.00000000e+00, 5.00000000e+00, 3.29289322e+00, 3.00000000e+00, 3.29289322e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_sp_discharges_new(): input_str = os.path.join(_THIS_DIR, 'test_sp_params_discharge_new.txt') inputs = ModelParameterDictionary(input_str) nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = np.array([5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5.]) mg['node']['topographic__elevation'] = z fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) # perform the loop (once!) for i in range(1): fr.route_flow() sp.run_one_step(dt) z_tg = np.array([5.00000000e+00, 5.00000000e+00, 0.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 1.29289322e+00, 1.00000000e-06, 1.29289322e+00, 5.00000000e+00, 5.00000000e+00, 2.29289322e+00, 1.00000000e+00, 2.29289322e+00, 5.00000000e+00, 5.00000000e+00, 3.29289322e+00, 3.00000000e+00, 3.29289322e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00, 5.00000000e+00]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_sp_discharges_old(): input_str = os.path.join(_THIS_DIR, 'test_sp_params_discharge.txt') inputs = ModelParameterDictionary(input_str) nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = np.array([5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5.]) mg['node']['topographic__elevation'] = z fr = FlowAccumulator(mg, flow_director='D8') my_Q = mg.at_node['surface_water__discharge'] sp = StreamPowerEroder(mg, input_str, use_Q=my_Q) # perform the loop (once!) for i in range(1): fr.run_one_step() my_Q[:] = mg.at_node['surface_water__discharge'] * 1. sp.run_one_step(dt) z_tg = np.array([5. , 5. , 0. , 5. , 5. , 5. , 1.47759225, 0.43050087, 1.47759225, 5. , 5. , 2.32883687, 1.21525044, 2.32883687, 5. , 5. , 3.27261262, 3.07175015, 3.27261262, 5. , 5. , 5. , 5. , 5. , 5. ]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_sed_dep(): input_file = os.path.join(_THIS_DIR, 'sed_dep_params.txt') inputs = ModelParameterDictionary(input_file, auto_type=True) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') uplift_rate = inputs.read_float('uplift_rate') runtime = inputs.read_float('total_time') dt = inputs.read_float('dt') nt = int(runtime // dt) uplift_per_step = uplift_rate * dt mg = RasterModelGrid((nrows, ncols), (dx, dx)) mg.add_zeros('topographic__elevation', at='node') z = np.loadtxt(os.path.join(_THIS_DIR, 'seddepinit.txt')) mg['node']['topographic__elevation'] = z mg.set_closed_boundaries_at_grid_edges(True, False, True, False) fr = FlowAccumulator(mg, flow_director='D8') sde = SedDepEroder(mg, **inputs) for i in range(nt): mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_per_step mg = fr.run_one_step() mg, _ = sde.erode(dt) z_tg = np.loadtxt(os.path.join(_THIS_DIR, 'seddepz_tg.txt')) assert_array_almost_equal(mg.at_node['topographic__elevation'][ mg.core_nodes], z_tg[mg.core_nodes])
def test_sp_widths(): input_str = os.path.join(_THIS_DIR, "test_sp_params_widths.txt") inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = 5 ncols = 5 dx = inputs.read_float("dx") dt = inputs.read_float("dt") mg = RasterModelGrid(nrows, ncols, xy_spacing=dx) widths = np.ones(mg.number_of_nodes, dtype=float) mg.add_zeros("topographic__elevation", at="node") z = np.array( [ 5.0, 5.0, 0.0, 5.0, 5.0, 5.0, 2.0, 1.0, 2.0, 5.0, 5.0, 3.0, 2.0, 3.0, 5.0, 5.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, ] ) mg["node"]["topographic__elevation"] = z fr = FlowAccumulator(mg, flow_director="D8") sp = StreamPowerEroder(mg, use_W=widths, **inputs) # perform the loop (once!) for i in range(1): fr.run_one_step() sqrt_A = mg.at_node["drainage_area"] ** 0.5 widths[mg.core_nodes] = sqrt_A[mg.core_nodes] / sqrt_A[mg.core_nodes].mean() # so widths has mean=1. # note the issue with drainage_area not defined at perimeter => nans # if not careful... sp.run_one_step(dt) z_tg = np.array( [ 5.0, 5.0, 0.0, 5.0, 5.0, 5.0, 1.37222369, 0.36876358, 1.37222369, 5.0, 5.0, 2.17408606, 1.07986038, 2.17408606, 5.0, 5.0, 3.08340277, 2.85288049, 3.08340277, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, ] ) assert_array_almost_equal(mg.at_node["topographic__elevation"], z_tg)
from landlab import RasterModelGrid from landlab import ModelParameterDictionary from landlab.utils import structured_grid as sgrid from landlab.components.sed_trp_shallow_flow.transport_sed_in_shallow_flow import SurfaceFlowTransport import time import pylab import numpy as np #get the needed properties to build the grid: inputs = ModelParameterDictionary('./stof_params_basin.txt') nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') h_init = inputs.read_float('h_init') z_boundary = inputs.read_float('z_boundary') #now the outlet height drop_ht = inputs.read_float('drop_ht') #Now the inlet gradient initial_slope = inputs.read_float('initial_slope') time_to_run = inputs.read_int('run_time') inlet_nodes = [0, 1, 2, ncols, 2 * ncols] mg = RasterModelGrid(nrows, ncols, dx) mg.set_inactive_boundaries(False, True, False, True) #mg.node_status[inlet_nodes] = 1 #mg.node_status[-5] = 1 #Fixed lip outlet #print sgrid.node_tolink_index(mg.shape)[1] #mg.reset_list_of_active_links() #node_distances_to_inlet = mg.get_distances_of_nodes_to_point((mg.node_x[0], mg.node_y[0])) #z0 = initial_slope*(np.amax(node_distances_to_inlet) - node_distances_to_inlet)
def initialize(self, grid=None, input_file=None, intensity=None, stormduration=None): """ Initialize the model and grid using either an input file or default values. """ self.grid = grid if self.grid == None: self.grid = create_and_initialize_grid( input_file ) ##<- this is the same input file used for parameters. ## this seems wrong to me... ##self.current_time = current_time <- this isn't being used yet. # Create a ModelParameterDictionary for the inputs MPD = ModelParameterDictionary() ## I am not sure we want to use an instance of MPD as an input_file. I'm confused about this. SO for ## now I changed this to reflect other component types if input_file is None: input_file = _DEFAULT_INPUT_FILE MPD.read_from_file(input_file) ## This was the old way... where an instance of MPD is an input_file #if type(input_file)==MPD: # inputs = input_file #else: # inputs = MPD(input_file) # Read input/configuration parameters self.m_n = MPD.read_float('MANNINGS_N') if intensity == None: self.rainfall_mmhr = MPD.read_float('RAINFALL_RATE') else: self.rainfall_mmhr = intensity if stormduration == None: self.rain_duration = MPD.read_float('RAIN_DURATION') else: self.rain_duration = stormduration #self.h_init = 0.001 # initial thin layer of water (m) #self.g = 9.8 # gravitational acceleration (m/s2) #self.alpha = 0.2 # time-step factor (ND; from Bates et al., 2010) #self.m_n_sq = self.m_n*self.m_n # manning's n squared #self.rho = 1000 # density of water, kg/m^3 # Derived parameters ## THIS IS IMPORTANT - UNITS!!!! Double check precip component... ## IF WE CLEARLY STATE UNIT REQUIREMENTS IN DOCS, THIS SHOULDN'T BE A PROBLEM ## BUT IT MUST BE CLEAR THAT ALL INPUT FILES HAVE STANDARD UNITS THROUGHOUT. self.rainfall_rate = (self.rainfall_mmhr / 1000.) / 3600. # rainfall in m/s # Set up state variables self.hstart = grid.zeros(centering='node') + self.h_init self.h = grid.zeros(centering='node') + self.h_init # water depth (m) #NG why is water depth at each node and not at cells, which are only active self.q = grid.zeros(centering='active_link') # unit discharge (m2/s) self.dhdt = grid.zeros(centering='cell') # rate of water-depth change self.tau = grid.zeros(centering='node') # shear stress (Pascals)
def initialize(self, grid, params_file): ''' params_file is the name of the text file containing the parameters needed for this stream power component. ***Parameters for input file*** OBLIGATORY: * Qc -> String. Controls how to set the carrying capacity. Either 'MPM', or a string giving the name of the model field where capacity values are stored on nodes. At the moment, only 'MPM' is permitted as a way to set the capacity automatically, but expansion would be trivial. If 'from_array', the module will attempt to set the capacity Note capacities must be specified as volume flux. * ...Then, assuming you set Qc=='MPM': * b_sp, c_sp -> Floats. These are the powers on discharge and drainage area in the equations used to control channel width and basin hydrology, respectively: W = k_w * Q**b_sp Q = k_Q * A**c_sp These parameters are used to constrain flow depth, and may be omitted if use_W or use_Q are set. *k_Q, k_w, mannings_n -> floats. These are the prefactors on the basin hydrology and channel width-discharge relations, and n from the Manning's equation, respectively. These are needed to allow calculation of shear stresses and hence carrying capacities from the local slope and drainage area alone. The equation for depth used to derive shear stress and hence carrying capacity contains a prefactor: mannings_n*(k_Q**(1-b)/K_w)**0.6 (so shear = fluid_density*g*depth_equation_prefactor*A**(0.6*c*(1-b)*S**0.7 !) Don't know what to set these values to? k_w=0.002, k_Q=1.e-9, mannings_n=0.03 give vaguely plausible numbers (e.g., for a drainage area ~400km2, like Boulder Creek at Boulder, => depth~2.5m, width~35m, shear stress ~O(1000Pa)). *Dchar -> float. The characteristic grain diameter in meters (==D50 in most cases) used to calculate Shields numbers in the channel. If you want to define Dchar values at each node, don't set, and use the Dchar_if_used argument in erode() instead. OPTIONS: *rock_density -> in kg/m3 (defaults to 2700) *sediment_density -> in kg/m3 (defaults to 2700) *fluid_density -> in most cases water density, in kg/m3 (defaults to 1000) *g -> acceleration due to gravity, in m/s**2 (defaults to 9.81) *threshold_shields -> +ve float; the threshold taustar_crit. Defaults to 0.047, or if 'slope_sensitive_threshold' is set True, becomes a weak function of local slope following Lamb et al (2008): threshold_shields=0.15*S**0.25 *slope_sensitive_threshold -> bool, defaults to 'False'. If true, threshold_shields is set according to the Lamb equation. An exception will be raised if threshold_shields is also set. *Parker_epsilon -> float, defaults to 0.4. This is Parker's (1978) epsilon, which is used in the relation tau - tauc = tau * (epsilon/(epsilon+1)) The 0.4 default is appropriate for coarse (gravelly) channels. The value approaches infinity as the river banks become more cohesive. *dt -> +ve float. If set, this is the fixed timestep for this component. Can be overridden easily as a parameter in erode(). If not set (default), this parameter MUST be set in erode(). *use_W -> Bool; if True, component will look for node-centered data describing channel width in grid.at_node['channel_width'], and use it to implement incision ~ stream power per unit width. Defaults to False. *use_Q -> Bool. Overrides the basin hydrology relation, using an local water discharge value assumed already calculated and stored in grid.at_node['discharge']. *C_MPM -> float. Defaults to 1. Allows tuning of the MPM prefactor, which is calculated as Qc = 8.*C_MPM*(taustar - taustarcrit)**1.5 In almost all cases, tuning depth_equation_prefactor' is preferred to tuning this parameter. *return_capacity -> bool (default False). NOT YET IMPLEMENTED. If True, this component will save the calculated capacity in the field 'fluvial_sediment_transport_capacity'. (Requires some additional math, so is suppressed for speed by default). ''' self.grid = grid # needs to be filled with values in execution self.link_S_with_trailing_blank = np.zeros(grid.number_of_links + 1) self.count_active_links = np.zeros_like( self.link_S_with_trailing_blank, dtype=int) self.count_active_links[:-1] = 1 inputs = ModelParameterDictionary(params_file) try: self.g = inputs.read_float('g') except MissingKeyError: self.g = 9.81 try: self.rock_density = inputs.read_float('rock_density') except MissingKeyError: self.rock_density = 2700. try: self.sed_density = inputs.read_float('sediment_density') except MissingKeyError: self.sed_density = 2700. try: self.fluid_density = inputs.read_float('fluid_density') except MissingKeyError: self.fluid_density = 1000. self.rho_g = self.fluid_density * self.g try: self.Qc = inputs.read_string('Qc') except MissingKeyError: raise MissingKeyError("Qc must be 'MPM' or a grid field name!") else: if self.Qc == 'MPM': self.calc_cap_flag = True else: self.calc_cap_flag = False try: self.lamb_flag = inputs.read_bool('slope_sensitive_threshold') except: self.lamb_flag = False try: self.shields_crit = inputs.read_float('threshold_shields') # flag for sed_flux_dep_incision to see if the threshold was # manually set. self.set_threshold = True # print("Found a threshold to use: ", self.shields_crit) assert self.lamb_flag == False except MissingKeyError: if not self.lamb_flag: self.shields_crit = 0.047 self.set_threshold = False try: self.tstep = inputs.read_float('dt') except MissingKeyError: pass try: self.use_W = inputs.read_bool('use_W') except MissingKeyError: self.use_W = False try: self.use_Q = inputs.read_bool('use_Q') except MissingKeyError: self.use_Q = False try: self.return_capacity = inputs.read_bool('return_capacity') except MissingKeyError: self.return_capacity = False try: self._b = inputs.read_float('b_sp') except MissingKeyError: if self.use_W: self._b = 0. else: if self.calc_cap_flag: raise NameError('b was not set') try: self._c = inputs.read_float('c_sp') except MissingKeyError: if self.use_Q: self._c = 1. else: if self.calc_cap_flag: raise NameError('c was not set') try: self.Dchar_in = inputs.read_float('Dchar') except MissingKeyError: pass # assume Manning's equation to set the power on A for shear stress: self.shear_area_power = 0.6 * self._c * (1. - self._b) self.k_Q = inputs.read_float('k_Q') self.k_w = inputs.read_float('k_w') mannings_n = inputs.read_float('mannings_n') if mannings_n < 0. or mannings_n > 0.2: warnings.warn("Manning's n outside it's typical range") self.depth_prefactor = self.rho_g * mannings_n * \ (self.k_Q**(1. - self._b) / self.k_w)**0.6 # Note the depth_prefactor we store already holds rho*g try: epsilon = inputs.read_float('Parker_epsilon') except MissingKeyError: epsilon = 0.4 try: self.C_MPM = inputs.read_float('C_MPM') except MissingKeyError: self.C_MPM = 1. try: self.shields_prefactor = 1. / \ ((self.sed_density - self.fluid_density) * self.g * self.Dchar_in) self.MPM_prefactor = 8. * self.C_MPM * \ np.sqrt(self.relative_weight * self.Dchar_in * self.Dchar_in * self.Dchar_in) self.MPM_prefactor_alt = 4. * \ self.g**(-2. / 3.) / self.excess_SG / \ self.fluid_density / self.sed_density except AttributeError: # have to set these manually as needed self.shields_prefactor_noD = 1. / \ ((self.sed_density - self.fluid_density) * self.g) self.diffusivity_prefactor = 8. * np.sqrt( 8. * self.g) / (self.sed_density / self.fluid_density - 1.) * ( epsilon / (epsilon + 1.) )**1.5 * mannings_n**(5. / 6.) * self.k_w**-0.9 * self.k_Q**( 0.9 * (1. - self._b)) # ...this is multiplied by A**c(1-0.1*(1-b)) # we consciously skip out a factor of S**0.05-->1. in the diffusion prefactor, to avoid delinearizing the diffusion. Only a possible problem at tiny S (20% error @S==0.01; 37% error @S==10**-4) # we could include this as a static adjustment in the actual looping code (i.e., just multiply by S**0.05, and don't work with it as part of the problem) # in reality, Manning's n changes downstream too, so... whatever self.diffusivity_power_on_A = 0.9 * self._c * \ (1. - self._b) # i.e., q/D**(1/6) self.cell_areas = np.empty(grid.number_of_nodes) self.cell_areas.fill(np.mean(grid.area_of_cell)) self.cell_areas[grid.node_at_cell] = grid.area_of_cell self.dx2 = grid.dx**2 self.dy2 = grid.dy**2 self.bad_neighbor_mask = np.equal( grid.get_active_neighbors_at_node(bad_index=-1), -1)
""" from __future__ import print_function import numpy as np import pylab from landlab import ModelParameterDictionary, RasterModelGrid from landlab.components.flow_routing import FlowAccumulator from landlab.components.gFlex.flexure import gFlex from landlab.components.stream_power import FastscapeEroder, StreamPowerEroder from landlab.plot.imshow import imshow_node_grid inputs = ModelParameterDictionary("./coupled_SP_gflex_params.txt") nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") init_elev = inputs.read_float("init_elev") uplift_perstep = inputs.read_float("uplift_rate") * dt rock_stress_param = inputs.read_float("rock_density") * 9.81 mg = RasterModelGrid(nrows, ncols, xy_spacing=dx) # create the fields in the grid mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev mg["node"]["topographic__elevation"] = z + np.random.rand(len(z)) / 1000. # make some surface load stresses in a field to test mg.at_node["surface_load__stress"] = np.zeros(nrows * ncols, dtype=float)
from landlab.plot import channel_profile as prf from landlab import RasterModelGrid import numpy as np import pylab from time import time import random #get the needed properties to build the grid: input_file = './drive_sp_params.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') uplift_rate = inputs.read_float('uplift_rate') runtime = inputs.read_float('run_time') dt = inputs.read_float('dt') nt = int(runtime // dt) uplift_per_step = uplift_rate * dt #instantiate the grid object mg = RasterModelGrid(nrows, ncols, dx) boundary_node_list = mg.get_boundary_nodes() #set up its boundary conditions (bottom, right, top, left is inactive) mg.set_inactive_boundaries(True, True, True, True) mg.set_closed_boundaries_at_grid_edges(False, False, False, False) mg.set_fixed_value_boundaries(20)
def test_diffusion(): infile = os.path.join(_THIS_DIR, 'diffusion_params.txt') inputs = ModelParameterDictionary(infile, auto_type=True) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid((nrows, ncols), (dx, dx)) uplift_rate = mg.node_y[mg.core_cells] / 100000. # create the fields in the grid mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev np.random.seed(0) mg['node']['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.set_fixed_value_boundaries_at_grid_edges(True, True, True, True) # instantiate: dfn = LinearDiffuser(mg, **inputs) # perform the loop: elapsed_time = 0. # total time in simulation while elapsed_time < time_to_run: if elapsed_time + dt > time_to_run: dt = time_to_run - elapsed_time dfn.run_one_step(dt) mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_rate * dt elapsed_time += dt z_target = np.array([ 5.48813504e-04, 7.15189366e-04, 6.02763376e-04, 5.44883183e-04, 4.23654799e-04, 6.45894113e-04, 4.37587211e-04, 8.91773001e-04, 9.63662761e-04, 3.83441519e-04, 7.91725038e-04, 9.18166135e-04, 1.02015039e-03, 1.10666198e-03, 1.14866514e-03, 1.20224288e-03, 1.12953135e-03, 1.12966219e-03, 1.00745155e-03, 8.70012148e-04, 9.78618342e-04, 1.12628772e-03, 1.41663596e-03, 2.66338249e-03, 2.80420703e-03, 2.82445061e-03, 2.69263914e-03, 2.44620140e-03, 2.04237613e-03, 4.14661940e-04, 2.64555612e-04, 2.15073330e-03, 2.77965579e-03, 3.22134736e-03, 3.45859244e-03, 4.47224671e-03, 4.25371135e-03, 3.82941648e-03, 3.25127747e-03, 6.81820299e-04, 3.59507901e-04, 3.36577718e-03, 4.20490812e-03, 4.81467159e-03, 5.14099588e-03, 5.15029835e-03, 4.83533539e-03, 5.22312276e-03, 4.37284689e-03, 3.63710771e-04, 5.70196770e-04, 4.65122535e-03, 5.67854747e-03, 6.44757828e-03, 6.85985389e-03, 6.86464781e-03, 6.45159799e-03, 5.65255723e-03, 4.54258827e-03, 2.44425592e-04, 1.58969584e-04, 5.85971567e-03, 7.16648352e-03, 8.10954246e-03, 8.61082386e-03, 8.61350727e-03, 8.10597021e-03, 7.12594182e-03, 5.75483957e-03, 9.60984079e-05, 9.76459465e-04, 6.29476234e-03, 7.70594852e-03, 9.79504842e-03, 1.03829367e-02, 1.03869062e-02, 9.79374998e-03, 8.65447904e-03, 7.07179252e-03, 1.18727719e-04, 3.17983179e-04, 7.43078552e-03, 9.18353155e-03, 1.04682910e-02, 1.11542648e-02, 1.21643980e-02, 1.14930584e-02, 1.02184219e-02, 8.53727126e-03, 9.29296198e-04, 3.18568952e-04, 8.68034110e-03, 1.06702554e-02, 1.21275181e-02, 1.29049224e-02, 1.29184938e-02, 1.21616788e-02, 1.17059081e-02, 9.66728348e-03, 4.69547619e-06, 6.77816537e-04, 1.00128306e-02, 1.21521279e-02, 1.37494046e-02, 1.46053573e-02, 1.46205669e-02, 1.37908840e-02, 1.22146332e-02, 1.01165765e-02, 9.52749012e-04, 4.47125379e-04, 1.12069867e-02, 1.35547122e-02, 1.52840440e-02, 1.62069802e-02, 1.62196380e-02, 1.53169489e-02, 1.35997836e-02, 1.12818577e-02, 6.92531590e-04, 7.25254280e-04, 1.14310516e-02, 1.38647655e-02, 1.66771925e-02, 1.76447108e-02, 1.76515649e-02, 1.66885162e-02, 1.48507549e-02, 1.23206170e-02, 2.90077607e-04, 6.18015429e-04, 1.24952067e-02, 1.49924260e-02, 1.68435913e-02, 1.78291009e-02, 1.88311310e-02, 1.78422046e-02, 1.59665841e-02, 1.34122052e-02, 4.31418435e-04, 8.96546596e-04, 1.34612553e-02, 1.58763600e-02, 1.76887976e-02, 1.86526609e-02, 1.86492669e-02, 1.76752679e-02, 1.68480793e-02, 1.44368883e-02, 9.98847007e-04, 1.49448305e-04, 1.40672989e-02, 1.64140227e-02, 1.81162514e-02, 1.90091351e-02, 1.89959971e-02, 1.80757625e-02, 1.63425116e-02, 1.39643530e-02, 6.91669955e-05, 6.97428773e-04, 1.47340964e-02, 1.66453353e-02, 1.80835612e-02, 1.88335770e-02, 1.88048458e-02, 1.80022362e-02, 1.65110248e-02, 1.44854151e-02, 1.71629677e-04, 5.21036606e-04, 1.40633664e-02, 1.54867652e-02, 1.75865008e-02, 1.81309867e-02, 1.80760242e-02, 1.74501109e-02, 1.63343931e-02, 1.48208186e-02, 3.18389295e-05, 1.64694156e-04, 1.41550038e-02, 1.49870334e-02, 1.57563641e-02, 1.60213295e-02, 1.69074625e-02, 1.64888825e-02, 1.58787450e-02, 1.50671910e-02, 3.11944995e-04, 3.98221062e-04, 2.09843749e-04, 1.86193006e-04, 9.44372390e-04, 7.39550795e-04, 4.90458809e-04, 2.27414628e-04, 2.54356482e-04, 5.80291603e-05, 4.34416626e-04 ]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_target)
def initialize(self, grid, params_file): """ This module implements sediment flux dependent channel incision following: E = f(Qs, Qc) * stream_power - sp_crit, where stream_power is the stream power (often ==K*A**m*S**n) provided by the stream_power.py component. Note that under this incision paradigm, sp_crit is assumed to be controlled exclusively by sediment mobility, i.e., it is not a function of bedrock resistance. If you want it to represent a bedrock resistance term, be sure to set Dchar if you use the MPM transport capacity relation, and do not use the flag 'slope_sensitive_threshold'. The component currently assumes that the threshold on bed incision is controlled by the threshold of motion of its sediment cover. This means there is assumed interplay between the supplied Shields number, characteristic grain size, and shear stress threshold. This calculation has a tendency to be slow, and can easily result in numerical instabilities. These instabilities are suppressed by retaining a memory of what the sediment flux was in the last time step, and weighting the next timestep by that value. XXXmore detail needed. Possibilities: 1. weight by last timestep/2timesteps (what about early ones?) 2. do it iteratively; only do incision one the sed flux you are using stabilises (so the previous iter "seed" becomes less important) Parameters needed in the initialization file follow those for stream_power.py. However, we now require additional input terms for the f(Qs,Qc) term: REQUIRED: *Set the stream power terms using a, b, and c NOT m, n. *...remember, any threshold set is set as tau**a, not just tau. *k_Q, k_w, mannings_n -> floats. These are the prefactors on the basin hydrology and channel width-discharge relations, and n from the Manning's equation, respectively. These are needed to allow calculation of shear stresses and hence carrying capacities from the local slope and drainage area alone. Don't know what to set these values to? k_w=2.5, k_Q=2.5e-7, mannings_n=0.05 give vaguely plausible numbers with b=0.5, c = 1.(e.g., for a drainage area ~350km2, like Boulder Creek at Boulder, => depth~1.3m, width~23m, shear stress ~O(200Pa) for an "annual-ish" flood). [If you want to continue playing with calibration, the ?50yr return time 2013 floods produced depths ~2.3m with Q~200m3/s] *sed_dependency_type -> 'None', 'linear_decline', 'parabolic', 'almost_parabolic', 'generalized_humped'. For definitions, see Gasparini et al., 2006; Hobley et al., 2011. *Qc -> This input controls the sediment capacity used by the component. It can calculate sediment carrying capacity for itself if this parameter is a string 'MPM', which will cause the component to use a slightly modified version of the Meyer-Peter Muller equation (again, see Hobley et al., 2011). Alternatively, it can be another string denoting the grid field name in which a precalculated capacity is stored. Depending on which options are specified above, further parameters may be required: *If sed_dependency_type=='generalized_humped', need the shape parameters used by Hobley et al: kappa_hump nu_hump phi_hump c_hump Note the onus is on the user to ensure that these parameters result in a viable shape, i.e., one where the maximum is 1 and there is indeed a hump in the profile. If these parameters are NOT specified, they will default to the form of the curve for Leh valley as found in Hobley et al 2011: nu=1.13; phi=4.24; c=0.00181; kappa=13.683. *If Qc=='MPM', these parameters may optionally be provided: Dchar -> characteristic grain size (i.e., D50) on the bed, in m. C_MPM -> the prefactor in the MPM relation. Defaults to 1, as in the relation sensu stricto, but can be modified to "tune" the equations to a known point where sediment deposition begins. In cases where k_Q and k_w are not known from real data, it is recommended these parameters be tuned in preference to C. *...if Dchar is NOT provided, the component will attempt to set (and will report) an appropriate characteristic grain size, such that it is consistent both with the threshold provided *and* a critical Shields number of 0.05. (If you really, really want to, you can override this critical Shields number too; use parameter *threshold_Shields*). OPTIONAL: *rock_density -> in kg/m3 (defaults to 2700) *sediment_density -> in kg/m3 (defaults to 2700) *fluid_density -> in most cases water density, in kg/m3 (defaults to 1000) *g -> acceleration due to gravity, in m/s**2 (defaults to 9.81) *threshold_shear_stress -> a float. If not provided, may be overridden by the following parameters. If it is not, defaults to 0. *slope_sensitive_threshold -> a boolean, defaults to FALSE. In steep mountain environments, the critical Shields number for particle motion appears to be weakly sensitive to the local slope, as taustar_c=0.15*S**0.25 (Lamb et al, 2008). If this flag is set to TRUE, the critical threshold in the landscape is allowed to become slope sensitive as well, in order to be consistent with this equation. This modification was used by Hobley et al., 2011. *set_threshold_from_Dchar -> a boolean, defaults to FALSE. Use this flag to force an appropriate threshold value from a provided Dchar. i.e., this is the inverse of the procedure that is used to find Dchar if it isn't provided. No threshold can be specified in the parameter file, and Dchar must be specified. *return_stream_properties -> bool (default False). If True, this component will save the calculations for 'channel_width', 'channel_depth', and 'channel_discharge' in those grid fields. (Requires some additional math, so is suppressed for speed by default). """ #this is the fraction we allow any given slope in the grid to evolve by in one go (suppresses numerical instabilities) self.fraction_gradient_change = 0.25 self.pseudoimplicit_repeats = 5 self.grid = grid self.link_S_with_trailing_blank = np.zeros( grid.number_of_links + 1) #needs to be filled with values in execution self.count_active_links = np.zeros_like( self.link_S_with_trailing_blank, dtype=int) self.count_active_links[:-1] = 1 inputs = ModelParameterDictionary(params_file) try: self.thresh = inputs.read_float('threshold_shear_stress') self.set_threshold = True #flag for sed_flux_dep_incision to see if the threshold was manually set. print "Found a shear stress threshold to use: ", self.thresh except MissingKeyError: print "Found no incision threshold to use." self.thresh = 0. self.set_threshold = False try: self._a = inputs.read_float('a_sp') except: print "a not supplied. Setting power on shear stress to 1..." self._a = 1. try: self._b = inputs.read_float('b_sp') except MissingKeyError: #if self.use_W: # self._b = 0. #else: raise NameError('b was not set') try: self._c = inputs.read_float('c_sp') except MissingKeyError: #if self.use_Q: # self._c = 1. #else: raise NameError( 'c was not set') #we need to restore this functionality later #'To use the sed flux dependent model, you must set a,b,c not m,n. Try a=1,b=0.5,c=1...?' self._K_unit_time = inputs.read_float( 'K_sp') / 31557600. #...because we work with dt in seconds #set gravity try: self.g = inputs.read_float('g') except MissingKeyError: self.g = 9.81 try: self.rock_density = inputs.read_float('rock_density') except MissingKeyError: self.rock_density = 2700. try: self.sed_density = inputs.read_float('sediment_density') except MissingKeyError: self.sed_density = 2700. try: self.fluid_density = inputs.read_float('fluid_density') except MissingKeyError: self.fluid_density = 1000. self.relative_weight = ( self.sed_density - self.fluid_density ) / self.fluid_density * self.g #to accelerate MPM calcs self.rho_g = self.fluid_density * self.g self.k_Q = inputs.read_float('k_Q') self.k_w = inputs.read_float('k_w') mannings_n = inputs.read_float('mannings_n') self.mannings_n = mannings_n if mannings_n < 0. or mannings_n > 0.2: print "***STOP. LOOK. THINK. You appear to have set Manning's n outside its typical range. Did you mean it? Proceeding...***" sleep(2) self.diffusivity_power_on_A = 0.9 * self._c * (1. - self._b ) #i.e., q/D**(1/6) self.type = inputs.read_string('sed_dependency_type') try: self.Qc = inputs.read_string('Qc') except MissingKeyError: self.Qc = None else: if self.Qc == 'MPM': self.calc_cap_flag = True else: self.calc_cap_flag = False try: self.override_threshold = inputs.read_bool( 'set_threshold_from_Dchar') except MissingKeyError: self.override_threshold = False try: self.shields_crit = inputs.read_float('threshold_Shields') except MissingKeyError: self.shields_crit = 0.05 try: self.return_ch_props = inputs.read_bool('return_stream_properties') except MissingKeyError: self.return_ch_props = False #now conditional inputs if self.type == 'generalized_humped': try: self.kappa = inputs.read_float('kappa_hump') self.nu = inputs.read_float('nu_hump') self.phi = inputs.read_float('phi_hump') self.c = inputs.read_float('c_hump') except MissingKeyError: self.kappa = 13.683 self.nu = 1.13 self.phi = 4.24 self.c = 0.00181 print 'Adopting inbuilt parameters for the humped function form...' try: self.lamb_flag = inputs.read_bool('slope_sensitive_threshold') #this is going to be a nightmare to implement... except: self.lamb_flag = False if self.Qc == 'MPM': try: self.Dchar_in = inputs.read_float('Dchar') except MissingKeyError: assert self.thresh > 0., "Can't automatically set characteristic grain size if threshold is 0 or unset!" #remember the threshold getting set is already tau**a self.Dchar_in = self.thresh / self.g / ( self.sed_density - self.fluid_density) / self.shields_crit print 'Setting characteristic grain size from the Shields criterion...' print 'Characteristic grain size is: ', self.Dchar_in try: self.C_MPM = inputs.read_float('C_MPM') except MissingKeyError: self.C_MPM = 1. if self.override_threshold: print "Overriding any supplied threshold..." try: self.thresh = self.shields_crit * self.g * ( self.sed_density - self.fluid_density) * self.Dchar_in except AttributeError: self.thresh = self.shields_crit * self.g * ( self.sed_density - self.fluid_density) * inputs.read_float('Dchar') print "Threshold derived from grain size and Shields number is: ", self.thresh self.cell_areas = np.empty(grid.number_of_nodes) self.cell_areas.fill(np.mean(grid.cell_areas)) self.cell_areas[grid.cell_node] = grid.cell_areas #new 11/12/14 self.point6onelessb = 0.6 * (1. - self._b) self.shear_stress_prefactor = self.fluid_density * self.g * ( self.mannings_n / self.k_w)**0.6 if self.set_threshold is False or self.override_threshold: try: self.shields_prefactor_to_shear = ( self.sed_density - self.fluid_density) * self.g * self.Dchar_in except AttributeError: #no Dchar self.shields_prefactor_to_shear_noDchar = ( self.sed_density - self.fluid_density) * self.g twothirds = 2. / 3. self.Qs_prefactor = 4. * self.C_MPM**twothirds * self.fluid_density**twothirds / ( self.sed_density - self.fluid_density)**twothirds * self.g**( twothirds / 2.) * mannings_n**0.6 * self.k_w**(1. / 15.) * self.k_Q**( 0.6 + self._b / 15.) / self.sed_density**twothirds self.Qs_thresh_prefactor = 4. * ( self.C_MPM * self.k_w * self.k_Q**self._b / self.fluid_density**0.5 / (self.sed_density - self.fluid_density) / self.g / self.sed_density)**twothirds #both these are divided by sed density to give a vol flux self.Qs_power_onA = self._c * (0.6 + self._b / 15.) self.Qs_power_onAthresh = twothirds * self._b * self._c
import copy import time import numpy import pylab from landlab import ModelParameterDictionary, RasterModelGrid from landlab.components import FlowAccumulator, StreamPowerEroder from landlab.components.stream_power import FastscapeEroder as Fsc from landlab.plot import channel_profile as prf, imshow as llplot from landlab.plot.video_out import VideoPlotter inputs = ModelParameterDictionary("./drive_sp_params.txt") nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") # nt needs defining uplift = inputs.read_float("uplift_rate") init_elev = inputs.read_float("init_elev") mg = RasterModelGrid(nrows, ncols, dx) # create the fields in the grid mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev mg["node"]["topographic__elevation"] = z + numpy.random.rand(len(z)) / 1000. # make some K values in a field to test mg.at_node["K_values"] = 1.e-6 + numpy.random.rand(nrows * ncols) * 1.e-8
@author: danhobley """ from __future__ import print_function import numpy as np import pylab from landlab import ModelParameterDictionary, RasterModelGrid from landlab.components.gflex.flexure import gFlex from landlab.plot.imshow import imshow_node_grid inputs = ModelParameterDictionary("./AW_gflex_params.txt") nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") init_elev = inputs.read_float("init_elev") mg = RasterModelGrid(nrows, ncols, dx) # create the fields in the grid mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev mg["node"]["topographic__elevation"] = z + np.random.rand(len(z)) / 1000. # make some surface load stresses in a field to test mg.at_node["surface_load__stress"] = np.zeros(nrows * ncols, dtype=float) square_qs = mg.at_node["surface_load__stress"].view().reshape((nrows, ncols)) square_qs[10:40, 10:40] += 1.e6
def initialize(self, grid, params_file): ''' params_file is the name of the text file containing the parameters needed for this stream power component. Module erodes where channels are, implemented as E = K * A**m * S**n - sp_crit, and if E<0, E=0. If 'use_W' is declared and True, the module instead implements: E = K * A**m * S**n / W - sp_crit ***Parameters for input file*** OBLIGATORY: K_sp -> positive float, the prefactor. This is defined per unit time, not per tstep. ALTERNATIVES: *either* m_sp -> positive float, the power on A and n_sp -> positive float, the power on S *or* sp_type -> String. Must be one of 'Total', 'Unit', or 'Shear_stress'. and (following Whipple & Tucker 1999) a_sp -> +ve float. The power on the SP/shear term to get the erosion rate. b_sp -> +ve float. The power on discharge to get width, "hydraulic geometry". Unnecessary if sp_type='Total'. c_sp -> +ve float. The power on area to get discharge, "basin hydology". ... If 'Total', m=a*c, n=a. ... If 'Unit', m=a*c*(1-b), n=a. ... If 'Shear_stress', m=2*a*c*(1-b)/3, n = 2*a/3. OPTIONS: threshold_sp -> +ve float; the threshold sp_crit. Defaults to 0. dt -> +ve float. If set, this is the fixed timestep for this component. Can be overridden easily as a parameter in erode(). If not set (default), this parameter MUST be set in erode(). use_W -> Bool; if True, component will look for node-centered data describing channel width in grid.at_node['channel_width'], and use it to implement incision ~ stream power per unit width. Defaults to False. If you set sp_m and sp_n, follows the equation given above. If you set sp_type, it will be ignored if 'Total', but used directly if you want 'Unit' or 'Shear_stress'. use_Q -> Bool. If true, the equation becomes E=K*Q**m*S**n. Effectively sets c=1 in Wh&T's 1999 derivation, if you are setting m and n through a, b, and c. prevent_erosion -> Bool. If True, stream powers are calculated and stored in the grid, but incision is NOT IMPLEMENTED. i.e., values of elevation are NOT updated. Use if you wish to derive stream power values for some other purpose, but do not wish to actually model stream power dependent incision. Defaults to False. ''' self.grid = grid self.link_S_with_trailing_blank = np.zeros(grid.number_of_links+1) #needs to be filled with values in execution self.count_active_links = np.zeros_like(self.link_S_with_trailing_blank, dtype=int) self.count_active_links[:-1] = 1 inputs = ModelParameterDictionary(params_file) self._K_unit_time = inputs.read_float('K_sp') try: self.sp_crit = inputs.read_float('threshold_sp') print "Found a threshold to use: ", self.sp_crit except MissingKeyError: self.sp_crit = 0. try: self.tstep = inputs.read_float('dt') except MissingKeyError: pass try: self.use_W = inputs.read_bool('use_W') except MissingKeyError: self.use_W = False try: self.use_Q = inputs.read_bool('use_Q') except MissingKeyError: self.use_Q = False try: self.no_erode = inputs.read_bool('prevent_erosion') except MissingKeyError: self.no_erode = False try: self._m = inputs.read_float('m_sp') except MissingKeyError: self._type = inputs.read_string('sp_type') self._a = inputs.read_float('a_sp') try: self._b = inputs.read_float('b_sp') except MissingKeyError: if self.use_W: self._b = 0. else: raise NameError('b was not set') try: self._c = inputs.read_float('c_sp') except MissingKeyError: if self.use_Q: self._c = 1. else: raise NameError('c was not set') if self._type == 'Total': self._n = self._a self._m = self._a*self._c #==_a if use_Q elif self._type == 'Unit': self._n = self._a self._m = self._a*self._c*(1.-self._b) #==_a iff use_Q&use_W etc elif self._type == 'Shear_stress': self._m = 2.*self._a*self._c*(1.-self._b)/3. self._n = 2.*self._a/3. else: raise MissingKeyError('Not enough information was provided on the exponents to use!') else: self._n = inputs.read_float('n_sp') #m and n will always be set, but care needs to be taken to include Q and W directly if appropriate self.stream_power_erosion = grid.zeros(centering='node')
from landlab.components.diffusion.diffusion import LinearDiffuser from landlab import RasterModelGrid, CLOSED_BOUNDARY, FIXED_VALUE_BOUNDARY from landlab import ModelParameterDictionary from landlab.io.netcdf import write_netcdf import numpy as np #get needed properties to build grid: input_file = 'create_topo.txt' #initialize an object that will supply the parameters: inputs = ModelParameterDictionary(input_file) #load grid properties nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') total_t = inputs.read_float('total_time') uplift_rate = inputs.read_float('uplift_rate') nt = int(total_t // dt) #this is how many loops we'll need uplift_per_step = uplift_rate * dt #build the grid mg = RasterModelGrid((nrows, ncols), dx) z = mg.add_zeros('node', 'topographic__elevation') # add some roughness as the initial topography, this lets "natural" channel planforms arise initial_roughness = np.random.rand(z.size) / 100000. z += initial_roughness #set the boundary conditions - here we have closed boundaries at the top/bottom and fixed boundaries at the left/right
##elapsed_time = 0. #total time in simulation ##while elapsed_time < time_to_run: ## #add uplift ## mg.at_node['topographic__elevation'][mg.core_nodes] += uplift*dt ## print elapsed_time ## if elapsed_time+dt>time_to_run: ## print "Short step!" ## dt = time_to_run - elapsed_time ## mg = fr.route_flow(grid=mg) ## mg,_,_ = sp.erode(mg) ## elapsed_time += dt inputs = ModelParameterDictionary("./pot_fr_params.txt") nrows = 200 # inputs.read_int('nrows') ncols = 200 # inputs.read_int('ncols') dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") # nt needs defining uplift = inputs.read_float("uplift_rate") init_elev = inputs.read_float("init_elev") mg = RasterModelGrid(nrows, ncols, dx) # create the fields in the grid mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev mg["node"]["topographic__elevation"] = z + np.random.rand(len(z)) / 1000.0 # make some K values in a field to test mg.at_node["K_values"] = 0.00001 + np.random.rand(nrows * ncols) / 100000.0
def initialize(self, input_stream): # Create a ModelParameterDictionary for the inputs if type(input_stream)==ModelParameterDictionary: inputs = input_stream else: inputs = ModelParameterDictionary(input_stream) # Read input/configuration parameters self.kd = inputs.read_float('linear_diffusivity') try: self.uplift_rate = inputs.read_float('uplift_rate') except MissingKeyError: self.uplift_rate = 0. try: self.values_to_diffuse = inputs.read_string('values_to_diffuse') except MissingKeyError: self.values_to_diffuse = 'topographic__elevation' else: #take switch in the new field name in the class properties for mysets in (self._input_var_names, self._output_var_names): mysets.remove('topographic__elevation') mysets.add(self.values_to_diffuse) for mydicts in (self._var_units, self._var_mapping, self._var_doc): mydicts[self.values_to_diffuse] = mydicts.pop('topographic__elevation') try: self.timestep_in = inputs.read_float('dt') except MissingKeyError: pass # Create grid if one doesn't already exist if self._grid is None: self._grid = create_and_initialize_grid(input_stream) # Set internal time step # ..todo: # implement mechanism to compute time-steps dynamically if grid is # adaptive/changing dx = self._grid.min_active_link_length() # smallest active link length self.dt = _ALPHA*dx*dx/self.kd # CFL condition try: self.tstep_ratio = self.timestep_in/self.dt except AttributeError: pass # Get a list of interior cells self.interior_cells = self._grid.node_at_core_cell ##DEJH bites the bullet and forces the 2015 style with fields # # Here we're experimenting with different approaches: with # # 'make_all_data', we create and manage all the data we need and embed # # it all in the grid. With 'explicit', we require the caller/user to # # provide data. # if _VERSION=='make_all_data': # #print('creating internal data') # self.z = self._grid.add_zeros('node', 'landscape_surface__elevation') # self.g = self._grid.add_zeros('active_link', 'landscape_surface__gradient') # surface gradients # self.qs = self._grid.add_zeros('active_link','unit_sediment_flux') # unit sediment flux # self.dqds = self._grid.add_zeros('node', 'sediment_flux_divergence') # sed flux derivative # elif _VERSION=='explicit': # pass # else: # # Create data arrays for variables that won't (?) be shared with other # # components # self.g = self._grid.create_active_link_array_zeros() # surface gradients # self.qs = self._grid.create_active_link_array_zeros() # unit sediment flux # self.dqds = self._grid.create_node_array_zeros() # sed flux derivative self.z = self._grid.at_node[self.values_to_diffuse] g = self._grid.zeros(centering='link') qs = self._grid.zeros(centering='link') try: self.g = self._grid.add_field('link', 'surface__gradient', g, noclobber=True) #note this will object if this exists already except FieldError: pass #field exists, so no problem try: self.qs = self._grid.add_field('link', 'unit_flux', qs, noclobber=True) except FieldError: pass
import pylab from pylab import colorbar, figure, loglog, plot, show from six.moves import range from landlab import ModelParameterDictionary, RasterModelGrid from landlab.components import FlowAccumulator, SedDepEroder from landlab.plot import channel_profile as prf, imshow from landlab.plot.imshow import imshow_node_grid from landlab.plot.video_out import VideoPlotter # get the needed properties to build the grid: input_file = "./sed_dep_params_reliable.txt" # './sed_dep_NMGparams2.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") leftmost_elev = inputs.read_float("leftmost_elevation") initial_slope = inputs.read_float("initial_slope") uplift_rate = inputs.read_float("uplift_rate") runtime = inputs.read_float("total_time") dt = inputs.read_float("dt") nt = int(runtime // dt) uplift_per_step = uplift_rate * dt print("uplift per step: ", uplift_per_step) # instantiate the grid object mg = RasterModelGrid(nrows, ncols, dx) ##create the elevation field in the grid:
from landlab import ModelParameterDictionary from landlab.plot import channel_profile as prf from landlab.plot.imshow import imshow_node_grid from landlab import RasterModelGrid import numpy as np import pylab from time import time #get the needed properties to build the grid: input_file = './stream_power_params.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') uplift_rate = inputs.read_float('uplift_rate') runtime = inputs.read_float('total_time') dt = inputs.read_float('dt') nt = int(runtime // dt) uplift_per_step = uplift_rate * dt #instantiate the grid object mg = RasterModelGrid(nrows, ncols, dx) ##create the elevation field in the grid: #create the field mg.create_node_array_zeros('topographic_elevation') z = mg.create_node_array_zeros() + leftmost_elev
def test_sp_discharges_new(): input_str = os.path.join(_THIS_DIR, "test_sp_params_discharge_new.txt") inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = 5 ncols = 5 dx = inputs.read_float("dx") dt = inputs.read_float("dt") mg = RasterModelGrid(nrows, ncols, xy_spacing=dx) mg.add_zeros("topographic__elevation", at="node") z = np.array( [ 5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5., ] ) mg["node"]["topographic__elevation"] = z fr = FlowAccumulator(mg, flow_director="D8") sp = StreamPowerEroder(mg, **inputs) # perform the loop (once!) for i in range(1): fr.run_one_step() sp.run_one_step(dt) z_tg = np.array( [ 5., 5., 0., 5., 5., 5., 1.47759225, 0.43050087, 1.47759225, 5., 5., 2.32883687, 1.21525044, 2.32883687, 5., 5., 3.27261262, 3.07175015, 3.27261262, 5., 5., 5., 5., 5., 5., ] ) assert_array_almost_equal(mg.at_node["topographic__elevation"], z_tg)
def test_sp_discharges_old(): input_str = os.path.join(_THIS_DIR, "test_sp_params_discharge.txt") inputs = ModelParameterDictionary(input_str) nrows = 5 ncols = 5 dx = inputs.read_float("dx") dt = inputs.read_float("dt") mg = RasterModelGrid((nrows, ncols), xy_spacing=dx) mg.add_zeros("topographic__elevation", at="node") z = np.array([ 5.0, 5.0, 0.0, 5.0, 5.0, 5.0, 2.0, 1.0, 2.0, 5.0, 5.0, 3.0, 2.0, 3.0, 5.0, 5.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, ]) mg["node"]["topographic__elevation"] = z fr = FlowAccumulator(mg, flow_director="D8") my_Q = mg.at_node["surface_water__discharge"] sp = StreamPowerEroder(mg, input_str, use_Q=my_Q) # perform the loop (once!) for i in range(1): fr.run_one_step() my_Q[:] = mg.at_node["surface_water__discharge"] * 1.0 sp.run_one_step(dt) z_tg = np.array([ 5.0, 5.0, 0.0, 5.0, 5.0, 5.0, 1.47759225, 0.43050087, 1.47759225, 5.0, 5.0, 2.32883687, 1.21525044, 2.32883687, 5.0, 5.0, 3.27261262, 3.07175015, 3.27261262, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, ]) assert_array_almost_equal(mg.at_node["topographic__elevation"], z_tg)
def __init__(self, input_stream): """ Reads in parameters and initializes the model. Example ------- >>> from six import StringIO >>> p = StringIO(''' ... model_grid_row__count: number of rows in grid ... 4 ... model_grid_column__count: number of columns in grid ... 4 ... plot_interval: interval for plotting to display, s ... 2.0 ... model__run_time: duration of model run, s ... 1.0 ... model__report_interval: time interval for reporting progress, real-time seconds ... 1.0e6 ... surface_bleaching_time_scale: time scale for OSL bleaching, s ... 2.42 ... light_attenuation_length: length scale for light attenuation, cells (1 cell = 1 mm) ... 2.0 ... ''') >>> tsbm = TurbulentSuspensionAndBleachingModel(p) >>> tsbm.node_state array([1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]) >>> tsbm.grid.at_node['osl'] array([ 1., 1., 1., 1., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]) >>> tsbm.n_xn array([0, 1, 1, 0, 0, 1, 1, 0]) >>> tsbm.fluid_surface_height 3.5 """ # Get a source for input parameters. params = ModelParameterDictionary(input_stream) # Read user-defined parameters nr = params.read_int('model_grid_row__count' ) # number of rows (CSDMS Standard Name [CSN]) nc = params.read_int( 'model_grid_column__count') # number of cols (CSN) self.plot_interval = params.read_float( 'plot_interval') # interval for plotting output, s self.run_duration = params.read_float( 'model__run_time') # duration of run, sec (CSN) self.report_interval = params.read_float( 'model__report_interval') # report interval, in real-time seconds self.bleach_T0 = params.read_float( 'surface_bleaching_time_scale' ) # time scale for bleaching at fluid surface, s self.zstar = params.read_float( 'light_attenuation_length' ) # length scale for light attenuation in fluid, CELLS # Derived parameters self.fluid_surface_height = nr - 0.5 # Calculate when we next want to report progress. self.next_report = time.time() + self.report_interval # Create grid mg = RasterModelGrid(nr, nc, 1.0) # Make the boundaries be walls mg.set_closed_boundaries_at_grid_edges(True, True, True, True) # Set up the states and pair transitions. ns_dict = {0: 'fluid', 1: 'particle'} xn_list = self.setup_transition_list() # Create the node-state array and attach it to the grid node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int) # For visual display purposes, set all boundary nodes to fluid node_state_grid[mg.closed_boundary_nodes] = 0 # Initialize the node-state array: here, the initial condition is a pile of # resting grains at the bottom of a container. bottom_rows = where(mg.node_y < 0.4 * nr)[0] node_state_grid[bottom_rows] = 1 # Create a data array for bleaching. # Here, osl=optically stimulated luminescence, normalized to the original # signal (hence, initially all unity). Over time this signal may get # bleached out due to exposure to light. self.osl = mg.add_zeros('node', 'osl') self.osl[bottom_rows] = 1.0 self.osl_display = mg.add_zeros('node', 'osl_display') self.osl_display[bottom_rows] = 1.0 # We'll need an array to track the last time any given node was # updated, so we can figure out the duration of light exposure between # update events self.last_update_time = mg.add_zeros('node', 'last_update_time') # Call the base class (RasterCTS) init method super(TurbulentSuspensionAndBleachingModel, \ self).__init__(mg, ns_dict, xn_list, node_state_grid, prop_data=self.osl) # Set up plotting (if plotting desired) if self.plot_interval <= self.run_duration: self.initialize_plotting()
from six.moves import range from landlab import RasterModelGrid, ModelParameterDictionary from landlab.plot.imshow import imshow_node_grid import numpy as np from pylab import imshow, show, contour, figure, clabel, quiver, plot, close from landlab.components.potentiality_flowrouting import PotentialityFlowRouter from landlab.components.flow_routing import FlowRouter from landlab.components.stream_power import FastscapeEroder from landlab.grid.mappers import map_link_end_node_max_value_to_link inputs = ModelParameterDictionary('./pot_fr_params.txt') nrows = 50 #inputs.read_int('nrows') ncols = 50 #inputs.read_int('ncols') dx = inputs.read_float('dx') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid(nrows, ncols, dx) # attempt to implement diffusion with flow routing... #modify the fields in the grid z = mg.zeros(at='node') + init_elev mg.at_node['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.add_zeros('water__unit_flux_in', at='node') #Set boundary conditions mg.set_closed_boundaries_at_grid_edges(False, True, True, True) mg.set_fixed_value_boundaries_at_grid_edges(False, False, False, True) inlet_node = np.array((mg.number_of_node_columns + 1))
from landlab.components.craters.dig_craters import impactor from landlab import ModelParameterDictionary from landlab import RasterModelGrid import numpy as np import time import pylab #get the needed properties to build the grid: input_file = './craters_params.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') nt = inputs.read_int('number_of_craters_per_loop') loops = inputs.read_int('number_of_loops') mg = RasterModelGrid(nrows, ncols, dx) mg.set_inactive_boundaries(False, False, False, False) #create the fields in the grid mg.create_node_array_zeros('topographic_elevation') mg['node']['topographic_elevation'] = np.load('init.npy') # Display a message print('Running ...') start_time = time.time() #instantiate the component:
@author: danhobley """ from __future__ import print_function from landlab.components.gflex.flexure import gFlex import numpy as np import pylab from landlab import RasterModelGrid from landlab import ModelParameterDictionary from landlab.plot.imshow import imshow_node_grid inputs = ModelParameterDictionary('./AW_gflex_params.txt') nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid(nrows, ncols, dx) #create the fields in the grid mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev mg['node']['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. #make some surface load stresses in a field to test mg.at_node['surface_load__stress'] = np.zeros(nrows * ncols, dtype=float) square_qs = mg.at_node['surface_load__stress'].view().reshape((nrows, ncols)) square_qs[10:40, 10:40] += 1.e6
def run_model(input_file=None, savepath=None, initial_topo_file=None, initial_seed_file=None): from landlab.components.flow_routing.route_flow_dn_JL import FlowRouter from landlab.components.stream_power.fastscape_stream_power_JL import FastscapeEroder #from landlab.components.stream_power.stream_power import StreamPowerEroder from landlab.components.sink_fill.pit_fill_pf import PitFiller from landlab.components.diffusion.diffusion import LinearDiffuser from landlab import ModelParameterDictionary #from landlab.plot import channel_profile as prf from landlab.plot.imshow import imshow_node_grid from landlab.io.esri_ascii import write_esri_ascii from landlab.io.esri_ascii import read_esri_ascii from landlab import RasterModelGrid #from analysis_method import analyze_drainage_percentage #from analysis_method import analyze_drainage_percentage_each_grid #from analysis_method import analyze_mean_erosion #from analysis_method import elev_diff_btwn_moraine_upland #from analysis_method import label_catchment #from analysis_method import cross_section #from analysis_method import analyze_node_below_threshold #from analysis_method import identify_drained_area #from analysis_method import save_result from analysis_method import shiftColorMap import copy import numpy as np import matplotlib import matplotlib.pyplot as plt import os import time import sys import shutil sys.setrecursionlimit(5000) #=============================================================================== #get the needed properties to build the grid: if input_file is None: input_file = './coupled_params_sp.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') initial_slope = inputs.read_float('initial_slope') rightmost_elevation = initial_slope * ncols * dx #rightmost_elevation = inputs.read_float('rightmost_elevation') uplift_rate = inputs.read_float('uplift_rate') incision_rate = inputs.read_float('incision_rate') runtime = inputs.read_float('total_time') dt = inputs.read_float('dt') nt = int(runtime // dt) k_sp = inputs.read_float('K_sp') m_sp = inputs.read_float('m_sp') uplift_per_step = uplift_rate * dt incision_per_step = incision_rate * dt moraine_height = inputs.read_float('moraine_height') moraine_width = inputs.read_float('moraine_width') #valley_width = inputs.read_float('valley_width') valley_depth = inputs.read_float('valley_depth') num_outs = inputs.read_int('number_of_outputs') output_interval = int(nt // num_outs) diff = inputs.read_float('linear_diffusivity') #threshold_stream_power = inputs.read_float('threshold_stream_power') threshold_AS = inputs.read_float('threshold_AS') #threshold_erosion = dt*threshold_stream_power gw_coeff = inputs.read_float('gw_coeff') all_dry = inputs.read_bool('all_dry') fill_sink_with_water = inputs.read_bool('fill_sink_with_water') #=============================================================================== #=============================================================================== if initial_topo_file is None: #instantiate the grid object mg = RasterModelGrid(nrows, ncols, dx) ##create the elevation field in the grid: #create the field #specifically, this field has a triangular ramp #moraine at the north edge of the domain. mg.add_zeros('node', 'topographic__elevation', units='m') z = mg.at_node['topographic__elevation'] moraine_start_y = np.max(mg.node_y) - moraine_width moraine_ys = np.where(mg.node_y > moraine_start_y) z[moraine_ys] += (mg.node_y[moraine_ys] - np.min( mg.node_y[moraine_ys])) * (moraine_height / moraine_width) #set valley #valley_start_x = np.min(mg.node_x)+valley_width #valley_ys = np.where((mg.node_x<valley_start_x)&(mg.node_y<moraine_start_y-valley_width)) #z[valley_ys] -= (np.max(mg.node_x[valley_ys])-mg.node_x[valley_ys])*(valley_depth/valley_width) #set ramp (towards valley) upland = np.where(mg.node_y < moraine_start_y) z[upland] -= (np.max(mg.node_x[upland]) - mg.node_x[upland]) * (rightmost_elevation / (ncols * dx)) z += rightmost_elevation #set ramp (away from moraine) #upland = np.where(mg.node_y<moraine_start_y) #z[upland] -= (moraine_start_y-mg.node_y[upland])*initial_slope #put these values plus roughness into that field if initial_seed_file is None: z += np.random.rand(len(z)) / 1 else: (seedgrid, seed) = read_esri_ascii(initial_seed_file, name='topographic__elevation_seed') z += seed mg.at_node['topographic__elevation'] = z #set river valley river_valley, = np.where( np.logical_and( mg.node_x == 0, np.logical_or(mg.status_at_node == 1, mg.status_at_node == 2))) mg.at_node['topographic__elevation'][river_valley] = -valley_depth else: (mg, z) = read_esri_ascii(initial_topo_file, name='topographic__elevation') #set river valley river_valley, = np.where( np.logical_and( mg.node_x == 0, np.logical_or(mg.status_at_node == 1, mg.status_at_node == 2))) mg.at_node['topographic__elevation'][river_valley] = -valley_depth #set up grid's boundary conditions (right, top, left, bottom) is inactive mg.set_closed_boundaries_at_grid_edges(True, True, False, True) #set up boundary along moraine #moraine_start_y = np.max(mg.node_y)-moraine_width #bdy_moraine_ids = np.where((mg.node_y > moraine_start_y) & (mg.node_x == 0)) #mg.status_at_node[bdy_moraine_ids]=4 #mg._update_links_nodes_cells_to_new_BCs() #=============================================================================== #=============================================================================== #instantiate the components: fr = FlowRouter(mg) pf = PitFiller(mg) sp = FastscapeEroder(mg, input_file, threshold_sp=threshold_AS * k_sp) #sp = StreamPowerEroder(mg, input_file, threshold_sp=threshold_erosion, use_Q=True) #diffuse = PerronNLDiffuse(mg, input_file) #lin_diffuse = LinearDiffuser(mg, input_file, method='on_diagonals') lin_diffuse = LinearDiffuser(mg, input_file) #=============================================================================== #=============================================================================== #instantiate plot setting plt.close('all') output_time = output_interval plot_num = 0 mycmap = shiftColorMap(matplotlib.cm.gist_earth, 'mycmap') #folder name if savepath is None: if all_dry: name_tag = 'All_dry' elif fill_sink_with_water: name_tag = 'Not_all_dry_no_sink' else: name_tag = 'Not_all_dry_sink' savepath = 'results/sensitivity_test_threshold_same_seed/'+name_tag+'_dt=' + str(dt) + '_total_time=' + str(runtime) + '_k_sp=' + str(k_sp) + \ '_uplift_rate=' + str(uplift_rate) + '_incision_rate=' + str(incision_rate) + '_initial_slope=' + str(initial_slope) + \ '_threshold=' + str(threshold_stream_power) if not os.path.isdir(savepath): os.makedirs(savepath) #copy params_file if not os.path.isfile(savepath + '/coupled_params_sp.txt'): shutil.copy(input_file, savepath + '/coupled_params_sp.txt') # Display a message print 'Running ...' print savepath #save initial topography write_esri_ascii(savepath + '/Topography_t=0.0.txt', mg, 'topographic__elevation') #time start_time = time.time() #=============================================================================== #=============================================================================== #perform the loops: for i in xrange(nt): #note the input arguments here are not totally standardized between modules ''' # simulate changing climate if (((i+1)*dt // 5000.) % 2) == 0.: all_dry = False else: all_dry = True ''' #sp = FastscapeEroder(mg, input_file, threshold_sp = threshold_stream_power) #update elevation mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_per_step mg.at_node['topographic__elevation'][river_valley] -= incision_per_step #mg = lin_diffuse.diffuse(dt) #route and erode original_topo = mg.at_node['topographic__elevation'].copy() slope = mg.at_node['topographic__steepest_slope'].copy() filled_nodes = None if all_dry or fill_sink_with_water: mg = pf.pit_fill() filled_nodes, = np.where( (mg.at_node['topographic__elevation'] - original_topo) > 0) mg = fr.route_flow(routing_flat=all_dry) old_topo = mg.at_node['topographic__elevation'].copy() #mg, temp_z, temp_sp = sp.erode(mg, dt, Q_if_used='water__volume_flux') mg = sp.erode(mg, dt, flooded_nodes=filled_nodes) new_topo = mg.at_node['topographic__elevation'].copy() mg.at_node[ 'topographic__elevation'] = original_topo + new_topo - old_topo #diffuse #for j in range(10): # mg = lin_diffuse.diffuse(dt/10) mg = lin_diffuse.diffuse(dt) if i + 1 == output_time: print 'Saving data...' plot_num += 1 plt.figure(plot_num) im = imshow_node_grid(mg, 'topographic__elevation', plot_name='t = '+str(int((i+1)*dt))+' years', \ grid_units = ['m','m'], cmap=mycmap, allow_colorbar=True, \ vmin=0-valley_depth-incision_rate*runtime, vmax=5.+moraine_height+uplift_rate*runtime) plt.savefig(savepath + '/Topography_t=' + str( (i + 1) * dt) + '.jpg', dpi=300) write_esri_ascii( savepath + '/Topography_t=' + str((i + 1) * dt) + '.txt', mg, 'topographic__elevation') output_time += output_interval plt.close('all') print("--- %.2f minutes ---" % ((time.time() - start_time) / 60)), 'Completed loop', i + 1 plt.close('all') print 'Finished simulating.' #=============================================================================== #=============================================================================== #analyze_drainage_percentage(savepath, True) #analyze_mean_erosion(savepath, True) #elev_diff_btwn_moraine_upland(savepath, True) #label_catchment(savepath) #cross_section(savepath) #=============================================================================== print 'Done!' print '\n'
from landlab.components.flow_routing import (FlowAccumulator, DepressionFinderAndRouter) from landlab.components.stream_power import StreamPowerEroder, FastscapeEroder import numpy from landlab import RasterModelGrid from landlab import ModelParameterDictionary from landlab.plot.imshow import imshow_node_grid import pylab import time inputs = ModelParameterDictionary('./drive_sp_params.txt') nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') #nt needs defining uplift = 10. * inputs.read_float('uplift_rate') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid(nrows, ncols, dx) #create the fields in the grid mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev #z += mg.node_x*0.001 mg['node']['topographic__elevation'] = z + numpy.random.rand(len(z)) / 1000. #make some K values in a field to test
from time import time import numpy as np import pylab from six.moves import range from landlab import FIXED_VALUE_BOUNDARY, ModelParameterDictionary, RasterModelGrid from landlab.components import FastscapeEroder, FlowAccumulator from landlab.plot import channel_profile as prf # get the needed properties to build the grid: input_file = "./drive_sp_params.txt" inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") uplift_rate = inputs.read_float("uplift_rate") runtime = inputs.read_float("run_time") dt = inputs.read_float("dt") nt = int(runtime // dt) uplift_per_step = uplift_rate * dt # instantiate the grid object mg = RasterModelGrid(nrows, ncols, dx) boundary_node_list = mg.boundary_nodes # set up its boundary conditions (bottom, right, top, left is inactive) mg.set_inactive_boundaries(True, True, True, True) mg.set_closed_boundaries_at_grid_edges(False, False, False, False) mg.status_at_node[20] = FIXED_VALUE_BOUNDARY
def initialize(self, grid, params_file): ''' params_file is the name of the text file containing the parameters needed for this stream power component. ***Parameters for input file*** OBLIGATORY: * Qc -> String. Controls how to set the carrying capacity. Either 'MPM', or a string giving the name of the model field where capacity values are stored on nodes. At the moment, only 'MPM' is permitted as a way to set the capacity automatically, but expansion would be trivial. If 'from_array', the module will attempt to set the capacity Note capacities must be specified as volume flux. * ...Then, assuming you set Qc=='MPM': * b_sp, c_sp -> Floats. These are the powers on discharge and drainage area in the equations used to control channel width and basin hydrology, respectively: W = k_w * Q**b_sp Q = k_Q * A**c_sp These parameters are used to constrain flow depth, and may be omitted if use_W or use_Q are set. *k_Q, k_w, mannings_n -> floats. These are the prefactors on the basin hydrology and channel width-discharge relations, and n from the Manning's equation, respectively. These are needed to allow calculation of shear stresses and hence carrying capacities from the local slope and drainage area alone. The equation for depth used to derive shear stress and hence carrying capacity contains a prefactor: mannings_n*(k_Q**(1-b)/K_w)**0.6 (so shear = fluid_density*g*depth_equation_prefactor*A**(0.6*c*(1-b)*S**0.7 !) Don't know what to set these values to? k_w=0.002, k_Q=1.e-9, mannings_n=0.03 give vaguely plausible numbers (e.g., for a drainage area ~400km2, like Boulder Creek at Boulder, => depth~2.5m, width~35m, shear stress ~O(1000Pa)). *Dchar -> float. The characteristic grain diameter in meters (==D50 in most cases) used to calculate Shields numbers in the channel. If you want to define Dchar values at each node, don't set, and use the Dchar_if_used argument in erode() instead. OPTIONS: *rock_density -> in kg/m3 (defaults to 2700) *sediment_density -> in kg/m3 (defaults to 2700) *fluid_density -> in most cases water density, in kg/m3 (defaults to 1000) *g -> acceleration due to gravity, in m/s**2 (defaults to 9.81) *threshold_shields -> +ve float; the threshold taustar_crit. Defaults to 0.047, or if 'slope_sensitive_threshold' is set True, becomes a weak function of local slope following Lamb et al (2008): threshold_shields=0.15*S**0.25 *slope_sensitive_threshold -> bool, defaults to 'False'. If true, threshold_shields is set according to the Lamb equation. An exception will be raised if threshold_shields is also set. *dt -> +ve float. If set, this is the fixed timestep for this component. Can be overridden easily as a parameter in erode(). If not set (default), this parameter MUST be set in erode(). *use_W -> Bool; if True, component will look for node-centered data describing channel width in grid.at_node['channel_width'], and use it to implement incision ~ stream power per unit width. Defaults to False. *use_Q -> Bool. Overrides the basin hydrology relation, using an local water discharge value assumed already calculated and stored in grid.at_node['discharge']. *C_MPM -> float. Defaults to 1. Allows tuning of the MPM prefactor, which is calculated as Qc = 8.*C_MPM*(taustar - taustarcrit)**1.5 In almost all cases, tuning depth_equation_prefactor' is preferred to tuning this parameter. ''' self.grid = grid self.link_S_with_trailing_blank = np.zeros(grid.number_of_links+1) #needs to be filled with values in execution self.count_active_links = np.zeros_like(self.link_S_with_trailing_blank, dtype=int) self.count_active_links[:-1] = 1 inputs = ModelParameterDictionary(params_file) try: self.g = inputs.read_float('g') except MissingKeyError: self.g = 9.81 try: self.rock_density = inputs.read_float('rock_density') except MissingKeyError: self.rock_density = 2700. try: self.sed_density = inputs.read_float('sediment_density') except MissingKeyError: self.sed_density = 2700. try: self.fluid_density = inputs.read_float('fluid_density') except MissingKeyError: self.fluid_density = 1000. self.relative_weight = (self.sed_density-self.fluid_density)/self.fluid_density*self.g #to accelerate MPM calcs self.excess_SG = (self.sed_density-self.fluid_density)/self.fluid_density self.rho_g = self.fluid_density*self.g try: self.Qc = inputs.read_string('Qc') except MissingKeyError: raise MissingKeyError("Qc must be 'MPM' or a grid field name!") else: if self.Qc=='MPM': self.calc_cap_flag = True else: self.calc_cap_flag = False try: self.lamb_flag = inputs.read_bool('slope_sensitive_threshold') except: self.lamb_flag = False try: self.shields_crit = inputs.read_float('threshold_shields') self.set_threshold = True #flag for sed_flux_dep_incision to see if the threshold was manually set. print "Found a threshold to use: ", self.shields_crit assert self.lamb_flag == False except MissingKeyError: if not self.lamb_flag: self.shields_crit = 0.047 self.set_threshold = False try: self.tstep = inputs.read_float('dt') except MissingKeyError: pass try: self.use_W = inputs.read_bool('use_W') except MissingKeyError: self.use_W = False try: self.use_Q = inputs.read_bool('use_Q') except MissingKeyError: self.use_Q = False try: self._b = inputs.read_float('b_sp') except MissingKeyError: if self.use_W: self._b = 0. else: if self.calc_cap_flag: raise NameError('b was not set') try: self._c = inputs.read_float('c_sp') except MissingKeyError: if self.use_Q: self._c = 1. else: if self.calc_cap_flag: raise NameError('c was not set') try: self.Dchar_in = inputs.read_float('Dchar') except MissingKeyError: pass #assume Manning's equation to set the power on A for shear stress: self.shear_area_power = 0.6*self._c*(1.-self._b) try: self.k_Q = inputs.read_float('k_Q') except MissingKeyError: self.depth_prefactor = self.rho_g*inputs.read_float('depth_equation_prefactor') else: self.k_w = inputs.read_float('k_w') mannings_n = inputs.read_float('mannings_n') if mannings_n<0. or mannings_n>0.2: print "***STOP. LOOK. THINK. You appear to have set Manning's n outside it's typical range. Did you mean it? Proceeding...***" sleep(2) self.depth_prefactor = self.rho_g*mannings_n*(self.k_Q**(1.-self._b)/self.k_w)**0.6 ##Note the depth_prefactor we store already holds rho*g try: self.C_MPM = inputs.read_float('C_MPM') except MissingKeyError: self.C_MPM = 1. try: self.shields_prefactor = 1./((self.sed_density-self.fluid_density)*self.g*self.Dchar_in) self.MPM_prefactor = 8.*self.C_MPM*np.sqrt(self.relative_weight*self.Dchar_in*self.Dchar_in*self.Dchar_in) self.MPM_prefactor_alt = 4.*self.g**(-2./3.)/self.excess_SG/self.fluid_density/self.sed_density except AttributeError: #have to set these manually as needed self.shields_prefactor_noD = 1./((self.sed_sensity-self.fluid_density)*self.g) self.cell_areas = np.empty(grid.number_of_nodes) self.cell_areas.fill(np.mean(grid.cell_areas)) self.cell_areas[grid.cell_node] = grid.cell_areas
def initialize(self, input_stream): # Create a ModelParameterDictionary for the inputs if type(input_stream) == ModelParameterDictionary: inputs = input_stream else: inputs = ModelParameterDictionary(input_stream) # Read input/configuration parameters self.kd = inputs.read_float('DIFMOD_KD') try: self.uplift_rate = inputs.read_float('DIFMOD_UPLIFT_RATE') except: self.uplift_rate = inputs.read_float('uplift_rate') try: self.values_to_diffuse = inputs.read_str('values_to_diffuse') except: self.values_to_diffuse = 'planet_surface__elevation' try: self.timestep_in = inputs.read_float('dt') except: print 'No fixed timestep supplied, it must be set dynamically somewhere else. Be sure to call input_timestep(timestep_in) as part of your run loop.' # Create grid if one doesn't already exist if self.grid == None: self.grid = create_and_initialize_grid(input_stream) # Set internal time step # ..todo: # implement mechanism to compute time-steps dynamically if grid is # adaptive/changing dx = self.grid.min_active_link_length() # smallest active link length self.dt = _ALPHA * dx * dx / self.kd # CFL condition try: self.tstep_ratio = self.timestep_in / self.dt except: pass # Get a list of interior cells self.interior_cells = self.grid.get_core_cell_node_ids() # Here we're experimenting with different approaches: with # 'make_all_data', we create and manage all the data we need and embed # it all in the grid. With 'explicit', we require the caller/user to # provide data. if _VERSION == 'make_all_data': #print 'creating internal data' self.z = self.grid.add_zeros('node', 'landscape_surface__elevation') self.g = self.grid.add_zeros( 'active_link', 'landscape_surface__gradient') # surface gradients self.qs = self.grid.add_zeros( 'active_link', 'unit_sediment_flux') # unit sediment flux self.dqds = self.grid.add_zeros( 'node', 'sediment_flux_divergence') # sed flux derivative elif _VERSION == 'explicit': pass else: # Create data arrays for variables that won't (?) be shared with other # components self.g = self.grid.create_active_link_array_zeros( ) # surface gradients self.qs = self.grid.create_active_link_array_zeros( ) # unit sediment flux self.dqds = self.grid.create_node_array_zeros( ) # sed flux derivative
def __init__(self, input_file=None, mean_storm=None, mean_interstorm=None, mean_storm_depth=None, total_t=None, delta_t=None): """ This reads in information from the input_file (either default or user assigned, and creates an instantaneous storm event drawn from the Poisson distribution """ # First we create an instance of the Model Parameter Dictionary MPD = ModelParameterDictionary() # If no input_file is given,the default file is used if input_file is None: input_file = _DEFAULT_INPUT_FILE # This reads in the file information MPD.read_from_file(input_file) # And now we set our different parameters # using the model parameter dictionary... if mean_storm == None: self.mean_storm = MPD.read_float('MEAN_STORM') else: self.mean_storm = mean_storm if mean_interstorm == None: self.mean_interstorm = MPD.read_float('MEAN_INTERSTORM') else: self.mean_interstorm = mean_interstorm if mean_storm_depth == None: self.mean_storm_depth = MPD.read_float('MEAN_DEPTH') else: self.mean_storm_depth = mean_storm_depth if total_t == None: self.run_time = MPD.read_float('RUN_TIME') else: self.run_time = total_t if delta_t == None: if input_file != _DEFAULT_INPUT_FILE: try: self.delta_t = MPD.read_float('DELTA_T') except MissingKeyError: self.delta_t = None else: self.delta_t = None else: self.delta_t = delta_t # Mean_intensity is not set by the MPD, but can be drawn from # the mean storm depth and mean storm duration. self.mean_intensity = self.mean_storm_depth / self.mean_storm # If a time series is created later, this blank list will be used. self.storm_time_series = [] # Given the mean values assigned above using either the model # parameter dictionary or the init function, we can call the # different methods to assign values from the Poisson distribution. self.storm_duration = self.get_precipitation_event_duration() self.interstorm_duration = self.get_interstorm_event_duration() self.storm_depth = self.get_storm_depth() self.intensity = self.get_storm_intensity() self._elapsed_time = 0.
def initialize(self, grid, params_file): ''' params_file is the name of the text file containing the parameters needed for this stream power component. Module erodes where channels are, implemented as E = K * A**m * S**n - sp_crit, and if E<0, E=0. If 'use_W' is declared and True, the module instead implements: E = K * A**m * S**n / W - sp_crit ***Parameters for input file*** OBLIGATORY: K_sp -> positive float, the prefactor. This is defined per unit time, not per tstep. Type the string 'array' to cause the component's erode method to look for an array of values of K (see documentation for 'erode'). ALTERNATIVES: *either* m_sp -> positive float, the power on A and n_sp -> positive float, the power on S *or* sp_type -> String. Must be one of 'Total', 'Unit', or 'Shear_stress'. and (following Whipple & Tucker 1999) a_sp -> +ve float. The power on the SP/shear term to get the erosion rate. b_sp -> +ve float. The power on discharge to get width, "hydraulic geometry". Unnecessary if sp_type='Total'. c_sp -> +ve float. The power on area to get discharge, "basin hydology". ... If 'Total', m=a*c, n=a. ... If 'Unit', m=a*c*(1-b), n=a. ... If 'Shear_stress', m=2*a*c*(1-b)/3, n = 2*a/3. OPTIONS: threshold_sp -> +ve float; the threshold sp_crit. Defaults to 0. This threshold is assumed to be in "stream power" units, i.e., if 'Shear_stress', the value should be tau**a. dt -> +ve float. If set, this is the fixed timestep for this component. Can be overridden easily as a parameter in erode(). If not set (default), this parameter MUST be set in erode(). use_W -> Bool; if True, component will look for node-centered data describing channel width in grid.at_node['channel_width'], and use it to implement incision ~ stream power per unit width. Defaults to False. If you set sp_m and sp_n, follows the equation given above. If you set sp_type, it will be ignored if 'Total', but used directly if you want 'Unit' or 'Shear_stress'. use_Q -> Bool. If true, the equation becomes E=K*Q**m*S**n. Effectively sets c=1 in Wh&T's 1999 derivation, if you are setting m and n through a, b, and c. ''' self.grid = grid self.fraction_gradient_change = 1. self.link_S_with_trailing_blank = np.zeros( grid.number_of_links + 1) #needs to be filled with values in execution self.count_active_links = np.zeros_like( self.link_S_with_trailing_blank, dtype=int) self.count_active_links[:-1] = 1 inputs = ModelParameterDictionary(params_file) try: self._K_unit_time = inputs.read_float('K_sp') except ParameterValueError: #it was a string self.use_K = True else: self.use_K = False try: self.sp_crit = inputs.read_float('threshold_sp') self.set_threshold = True #flag for sed_flux_dep_incision to see if the threshold was manually set. print "Found a threshold to use: ", self.sp_crit except MissingKeyError: self.sp_crit = 0. self.set_threshold = False try: self.tstep = inputs.read_float('dt') except MissingKeyError: pass try: self.use_W = inputs.read_bool('use_W') except MissingKeyError: self.use_W = False try: self.use_Q = inputs.read_bool('use_Q') except MissingKeyError: self.use_Q = False try: self._m = inputs.read_float('m_sp') except MissingKeyError: self._type = inputs.read_string('sp_type') self._a = inputs.read_float('a_sp') try: self._b = inputs.read_float('b_sp') except MissingKeyError: if self.use_W: self._b = 0. else: raise NameError('b was not set') try: self._c = inputs.read_float('c_sp') except MissingKeyError: if self.use_Q: self._c = 1. else: raise NameError('c was not set') if self._type == 'Total': self._n = self._a self._m = self._a * self._c #==_a if use_Q elif self._type == 'Unit': self._n = self._a self._m = self._a * self._c * (1. - self._b ) #==_a iff use_Q&use_W etc elif self._type == 'Shear_stress': self._m = 2. * self._a * self._c * (1. - self._b) / 3. self._n = 2. * self._a / 3. else: raise MissingKeyError( 'Not enough information was provided on the exponents to use!' ) else: self._n = inputs.read_float('n_sp') #m and n will always be set, but care needs to be taken to include Q and W directly if appropriate self.stream_power_erosion = grid.zeros(centering='node') ##Flags for self-building of derived data: #self.made_link_gradients = False ##This will us the MPD once finalized ##Now perform checks for existance of needed data items: #try: # _ = self.grid.at_link['planet_surface__derivative_of_elevation'] #except FieldError: # self.made_link_gradients = True self.weave_flag = grid.weave_flag
def initialize(self, grid, params_file): ''' params_file is the name of the text file containing the parameters needed for this stream power component. ***Parameters for input file*** OBLIGATORY: * Qc -> String. Controls how to set the carrying capacity. Either 'MPM', or a string giving the name of the model field where capacity values are stored on nodes. At the moment, only 'MPM' is permitted as a way to set the capacity automatically, but expansion would be trivial. If 'from_array', the module will attempt to set the capacity Note capacities must be specified as volume flux. * ...Then, assuming you set Qc=='MPM': * b_sp, c_sp -> Floats. These are the powers on discharge and drainage area in the equations used to control channel width and basin hydrology, respectively: W = k_w * Q**b_sp Q = k_Q * A**c_sp These parameters are used to constrain flow depth, and may be omitted if use_W or use_Q are set. *k_Q, k_w, mannings_n -> floats. These are the prefactors on the basin hydrology and channel width-discharge relations, and n from the Manning's equation, respectively. These are needed to allow calculation of shear stresses and hence carrying capacities from the local slope and drainage area alone. Don't know what to set these values to? k_w=2.5, k_Q=2.5e-7, mannings_n=0.05 give vaguely plausible numbers with b=0.5, c = 1.(e.g., for a drainage area ~350km2, like Boulder Creek at Boulder, => depth~1.3m, width~23m, shear stress ~O(200Pa) for an "annual-ish" flood). [If you want to continue playing with calibration, the ?50yr return time 2013 floods produced depths ~2.3m with Q~200m3/s] *Dchar -> float. The characteristic grain diameter in meters (==D50 in most cases) used to calculate Shields numbers in the channel. If you want to define Dchar values at each node, don't set, and use the Dchar_if_used argument in erode() instead. OPTIONS: *rock_density -> in kg/m3 (defaults to 2700) *sediment_density -> in kg/m3 (defaults to 2700) *fluid_density -> in most cases water density, in kg/m3 (defaults to 1000) *g -> acceleration due to gravity, in m/s**2 (defaults to 9.81) *threshold_shields -> +ve float; the threshold taustar_crit. Defaults to 0.047, or if 'slope_sensitive_threshold' is set True, becomes a weak function of local slope following Lamb et al (2008): threshold_shields=0.15*S**0.25 *slope_sensitive_threshold -> bool, defaults to 'False'. If true, threshold_shields is set according to the Lamb equation, An exception will be raised if threshold_shields is also set. *dt -> +ve float. If set, this is the fixed timestep for this component. Can be overridden easily as a parameter in erode(). If not set (default), this parameter MUST be set in erode(). *use_W -> Bool; if True, component will look for node-centered data describing channel width in grid.at_node['channel_width'], and use it to implement incision ~ stream power per unit width. Defaults to False. NOT YET IMPLEMENTED *use_Q -> Bool. Overrides the basin hydrology relation, using an local water discharge value assumed already calculated and stored in grid.at_node['discharge']. NOT YET IMPLEMENTED *C_MPM -> float. Defaults to 1. Allows tuning of the MPM prefactor, which is calculated as Qc = 8.*C_MPM*(taustar - taustarcrit)**1.5 In almost all cases, tuning depth_equation_prefactor' is preferred to tuning this parameter. *return_stream_properties -> bool (default False). If True, this component will save the calculations for 'channel_width', 'channel_depth', and 'channel_discharge' in those grid fields. (Requires some additional math, so is suppressed for speed by default). ''' #this is the fraction we allow any given slope in the grid to evolve by in one go (suppresses numerical instabilities) self.fraction_gradient_change = 0.25 self.grid = grid self.link_S_with_trailing_blank = np.zeros(grid.number_of_links+1) #needs to be filled with values in execution self.count_active_links = np.zeros_like(self.link_S_with_trailing_blank, dtype=int) self.count_active_links[:-1] = 1 inputs = ModelParameterDictionary(params_file) try: self.g = inputs.read_float('g') except MissingKeyError: self.g = 9.81 try: self.rock_density = inputs.read_float('rock_density') except MissingKeyError: self.rock_density = 2700. try: self.sed_density = inputs.read_float('sediment_density') except MissingKeyError: self.sed_density = 2700. try: self.fluid_density = inputs.read_float('fluid_density') except MissingKeyError: self.fluid_density = 1000. self.rho_g = self.fluid_density * self.g try: self.Qc = inputs.read_string('Qc') except MissingKeyError: raise MissingKeyError("Qc must be 'MPM' or a grid field name!") else: if self.Qc=='MPM': self.calc_cap_flag = True else: self.calc_cap_flag = False try: self.return_ch_props = inputs.read_bool('return_stream_properties') except MissingKeyError: self.return_ch_props = False try: self.lamb_flag = inputs.read_bool('slope_sensitive_threshold') except: self.lamb_flag = False try: self.shields_crit = inputs.read_float('threshold_shields') self.set_threshold = True #flag for sed_flux_dep_incision to see if the threshold was manually set. print "Found a threshold to use: ", self.shields_crit assert self.lamb_flag == False except MissingKeyError: if not self.lamb_flag: self.shields_crit = 0.047 self.set_threshold = False try: self.tstep = inputs.read_float('dt') except MissingKeyError: pass try: self.use_W = inputs.read_bool('use_W') except MissingKeyError: self.use_W = False try: self.use_Q = inputs.read_bool('use_Q') except MissingKeyError: self.use_Q = False try: self.return_capacity = inputs.read_bool('return_capacity') except MissingKeyError: self.return_capacity = False try: self._b = inputs.read_float('b_sp') except MissingKeyError: if self.use_W: self._b = 0. else: if self.calc_cap_flag: raise NameError('b was not set') try: self._c = inputs.read_float('c_sp') except MissingKeyError: if self.use_Q: self._c = 1. else: if self.calc_cap_flag: raise NameError('c was not set') try: self.Dchar_in = inputs.read_float('Dchar') except MissingKeyError: pass #assume Manning's equation to set the power on A for shear stress: self.shear_area_power = 0.6*self._c*(1.-self._b) self.k_Q = inputs.read_float('k_Q') self.k_w = inputs.read_float('k_w') mannings_n = inputs.read_float('mannings_n') self.mannings_n = mannings_n if mannings_n<0. or mannings_n>0.2: print "***STOP. LOOK. THINK. You appear to have set Manning's n outside its typical range. Did you mean it? Proceeding...***" sleep(2) try: self.C_MPM = inputs.read_float('C_MPM') except MissingKeyError: self.C_MPM = 1. self.diffusivity_power_on_A = 0.9*self._c*(1.-self._b) #i.e., q/D**(1/6) #new for v3: #set thresh in shear stress if poss at this stage: try: #fails if no Dchar provided, or shields crit is being set dynamically from slope self.thresh = self.shields_crit*(self.sed_density-self.fluid_density)*self.g*self.Dchar_in except AttributeError: try: self.shields_prefactor_to_shear = (self.sed_density-self.fluid_density)*self.g*self.Dchar_in except AttributeError: #no Dchar self.shields_prefactor_to_shear_noDchar = (self.sed_density-self.fluid_density)*self.g twothirds = 2./3. self.Qs_prefactor = 4.*self.C_MPM**twothirds*self.fluid_density**twothirds/(self.sed_density-self.fluid_density)**twothirds*self.g**(twothirds/2.)*mannings_n**0.6*self.k_w**(1./15.)*self.k_Q**(0.6+self._b/15.)/self.sed_density**twothirds self.Qs_thresh_prefactor = 4.*(self.C_MPM*self.k_w*self.k_Q**self._b/self.fluid_density**0.5/(self.sed_density-self.fluid_density)/self.g/self.sed_density)**twothirds #both these are divided by sed density to give a vol flux self.Qs_power_onA = self._c*(0.6+self._b/15.) self.Qs_power_onAthresh = twothirds*self._b*self._c if RasterModelGrid in inspect.getmro(grid.__class__): self.cell_areas = grid.node_spacing_horizontal*grid.node_spacing_vertical else: self.cell_areas = np.empty(grid.number_of_nodes) self.cell_areas.fill(np.mean(grid.cell_areas)) self.cell_areas[grid.cell_node] = grid.cell_areas self.bad_neighbor_mask = np.equal(grid.get_neighbor_list(bad_index=-1),-1) self.routing_code = """
from pylab import colorbar, show, plot, loglog, figure from landlab import RasterModelGrid import numpy as np import pylab from pylab import show from copy import copy, deepcopy from time import time #get the needed properties to build the grid: input_file = './sed_dep_params.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') uplift_rate = inputs.read_float('uplift_rate') runtime = inputs.read_float('total_time') dt = inputs.read_float('dt') nt = int(runtime//dt) uplift_per_step = uplift_rate * dt print 'uplift per step: ', uplift_per_step #instantiate the grid object mg = RasterModelGrid(nrows, ncols, dx) ##create the elevation field in the grid:
def test_fastscape(): input_str = os.path.join(_THIS_DIR, "drive_sp_params.txt") inputs = ModelParameterDictionary(input_str) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") uplift = inputs.read_float("uplift_rate") init_elev = inputs.read_float("init_elev") mg = RasterModelGrid(nrows, ncols, dx) mg.set_closed_boundaries_at_grid_edges(False, False, True, True) mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev numpy.random.seed(0) mg["node"]["topographic__elevation"] = z + numpy.random.rand(len(z)) / 1000. fr = FlowAccumulator(mg, flow_director="D8") fsp = Fsc(mg, input_str, method="D8") elapsed_time = 0. while elapsed_time < time_to_run: if elapsed_time + dt > time_to_run: dt = time_to_run - elapsed_time mg = fr.run_one_step() mg = fsp.erode(mg, dt=dt) mg.at_node["topographic__elevation"][mg.core_nodes] += uplift * dt elapsed_time += dt z_trg = numpy.array( [ 5.48813504e-04, 7.15189366e-04, 6.02763376e-04, 5.44883183e-04, 4.23654799e-04, 6.45894113e-04, 1.01830760e-02, 9.58036770e-03, 6.55865452e-03, 3.83441519e-04, 7.91725038e-04, 1.00142749e-02, 8.80798884e-03, 5.78387585e-03, 7.10360582e-05, 8.71292997e-05, 9.81911417e-03, 9.52243406e-03, 7.55093226e-03, 8.70012148e-04, 9.78618342e-04, 1.00629755e-02, 8.49253798e-03, 5.33216680e-03, 1.18274426e-04, 6.39921021e-04, 9.88956320e-03, 9.47119567e-03, 6.43790696e-03, 4.14661940e-04, 2.64555612e-04, 1.00450743e-02, 8.37262908e-03, 5.21540904e-03, 1.87898004e-05, 6.17635497e-04, 9.21286940e-03, 9.34022513e-03, 7.51114450e-03, 6.81820299e-04, 3.59507901e-04, 6.19166921e-03, 7.10456176e-03, 6.62585507e-03, 6.66766715e-04, 6.70637870e-04, 2.10382561e-04, 1.28926298e-04, 3.15428351e-04, 3.63710771e-04, ] ) assert_array_almost_equal(mg.at_node["topographic__elevation"], z_trg)
from __future__ import print_function from landlab.components.craters.dig_craters import impactor from landlab import ModelParameterDictionary from landlab import RasterModelGrid import numpy as np import time import pylab #get the needed properties to build the grid: input_file = './craters_params_degrade.txt' inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') nt = inputs.read_int('number_of_craters_per_loop') loops = inputs.read_int('number_of_loops') mg = RasterModelGrid(nrows, ncols, dx) mg.set_looped_boundaries(True, True) #create the fields in the grid mg.create_node_array_zeros('topographic__elevation') mg['node'][ 'topographic__elevation'] = np.load('init_topo.npy') # Display a message print( 'Running ...' ) start_time = time.time()
from __future__ import print_function import numpy as np import pylab from landlab.components.gFlex.flexure import gFlex from landlab.components.flow_routing import FlowAccumulator from landlab.components.stream_power import StreamPowerEroder, FastscapeEroder from landlab import RasterModelGrid from landlab import ModelParameterDictionary from landlab.plot.imshow import imshow_node_grid inputs = ModelParameterDictionary('./coupled_SP_gflex_params.txt') nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') init_elev = inputs.read_float('init_elev') uplift_perstep = inputs.read_float('uplift_rate')*dt rock_stress_param = inputs.read_float('rock_density')*9.81 mg = RasterModelGrid(nrows, ncols, dx) #create the fields in the grid mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev mg['node'][ 'topographic__elevation'] = z + np.random.rand(len(z))/1000. #make some surface load stresses in a field to test mg.at_node['surface_load__stress'] = np.zeros(nrows*ncols, dtype=float)