├── .gitignore ├── README.md ├── scripts ├── diffusion │ ├── diffusion_input_file.txt │ ├── scarp_diffusion_no_component.py │ └── scarp_diffusion_with_component.py ├── flexure │ ├── example_point_load.py │ ├── example_two_point_load.py │ ├── example_loading_everywhere.py │ └── example_random_point_loads.py └── ecohydrology_flat_surface │ ├── run_driver.py │ ├── ecohyd_functions_flat.py │ └── inputs_vegetation_ca.yaml ├── component_drivers ├── diffusion │ ├── diffusion_params.txt │ └── diffusion_driver.py ├── gFlex │ ├── AW_gflex_params.txt │ ├── coupled_SP_gflex_params.txt │ └── gflex_driver.py ├── nonlinear_diffusion │ ├── drive_perron_params.txt │ ├── drive_perron.py │ └── drive_explicit_nl.py ├── flow_routing │ ├── test_script_for_route_flow_dn.py │ └── west_bijou_gully.asc ├── overland_flow │ ├── deAlmeida_LongBasin.py │ └── deAlmeida_SquareBasin.py └── cellular_automata │ ├── diffusion_in_gravity.py │ ├── rock_weathering.py │ ├── cts_lattice_gas.py │ └── cts_lattice_gas_with_gravity.py ├── coupled ├── coupled_params.txt └── coupled_driver.py └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # drivers 2 | Example drivers for Landlab 3 | -------------------------------------------------------------------------------- /scripts/diffusion/diffusion_input_file.txt: -------------------------------------------------------------------------------- 1 | linear_diffusivity: in m2 per year 2 | 0.01 3 | -------------------------------------------------------------------------------- /component_drivers/diffusion/diffusion_params.txt: -------------------------------------------------------------------------------- 1 | #These values are for building the grid- 2 | nrows: 3 | 100 4 | ncols: 5 | 100 6 | dx: 7 | 100. 8 | dt: 9 | 1. 10 | uplift_rate: #per time, not per timestep 11 | 0.1 12 | run_time: 13 | 300 14 | init_elev: 15 | 0. 16 | 17 | #These values are for running the process- 18 | rock_density: 19 | 2.7 20 | sed_density: 21 | 2.7 22 | linear_diffusivity: 23 | 50000. 24 | -------------------------------------------------------------------------------- /coupled/coupled_params.txt: -------------------------------------------------------------------------------- 1 | nrows: 2 | 100 3 | ncols: 4 | 100 5 | dx: 6 | 0.02 7 | leftmost_elevation: 8 | 1. 9 | initial_slope: 10 | 0. 11 | dt: 12 | 0.1 13 | total_time: 14 | 100. 15 | uplift_rate: 16 | 0.001 17 | K_sp: 18 | 0.3 19 | m_sp: 20 | 0.5 21 | n_sp: 22 | 1. 23 | rock_density: 24 | 2.7 25 | sed_density: 26 | 2.7 27 | kappa: 28 | 0.0001 29 | S_crit: 30 | 0.56 31 | 32 | linear_diffusivity: 33 | 0.0001 34 | -------------------------------------------------------------------------------- /component_drivers/gFlex/AW_gflex_params.txt: -------------------------------------------------------------------------------- 1 | #These values are for building the grid- 2 | nrows: 3 | 50 4 | ncols: 5 | 50 6 | dx: 7 | 5000. 8 | dt: 9 | 1. 10 | run_time: 11 | 3. 12 | init_elev: 13 | 0. 14 | 15 | #These values are for running the process- 16 | E: 17 | 6.5e11 18 | nu: 19 | 0.25 20 | rho_m: 21 | 3300. 22 | rho_fill: 23 | 0. 24 | Te: 25 | 35000. 26 | BC_W: 27 | 0Moment0Shear 28 | BC_E: 29 | 0Moment0Shear 30 | BC_N: 31 | Periodic 32 | BC_S: 33 | Periodic -------------------------------------------------------------------------------- /component_drivers/nonlinear_diffusion/drive_perron_params.txt: -------------------------------------------------------------------------------- 1 | #These values are for building the grid- 2 | nrows: 3 | 100 4 | ncols: 5 | 100 6 | dx: 7 | 100. 8 | dt: 9 | 1. 10 | uplift_rate: #per time, not per timestep 11 | 30. 12 | run_time: 13 | 30 14 | init_elev: 15 | 0. 16 | 17 | #These values are for running the process- 18 | rock_density: 19 | 2.7 20 | sed_density: 21 | 2.7 22 | kappa: 23 | 50000. 24 | S_crit: 25 | 0.56 26 | 27 | nonlinear_diffusivity: 28 | 50000. 29 | critical_diffusive_gradient: 30 | 0.56 -------------------------------------------------------------------------------- /component_drivers/gFlex/coupled_SP_gflex_params.txt: -------------------------------------------------------------------------------- 1 | #These values are for building the grid- 2 | nrows: 3 | 200 4 | ncols: 5 | 100 6 | dx: 7 | 5000. 8 | dt: 9 | 25000. 10 | run_time: 11 | 4000000. 12 | init_elev: 13 | 0. 14 | uplift_rate: 15 | 0.001 16 | 17 | #These values are for running the process- 18 | E: 19 | 6.5e11 20 | nu: 21 | 0.25 22 | rho_m: 23 | 3300. 24 | rho_fill: 25 | 0. 26 | Te: 27 | 40000. 28 | BC_W: 29 | Periodic 30 | BC_E: 31 | Periodic 32 | BC_N: 33 | 0Slope0Shear 34 | BC_S: 35 | 0Slope0Shear 36 | rock_density: 37 | 2700 38 | sed_density: 39 | 2700 40 | K_sp: 41 | 0.000003 42 | m_sp: 43 | 0.5 44 | n_sp: 45 | 1. 46 | threshold_sp: 47 | 0. 48 | -------------------------------------------------------------------------------- /scripts/flexure/example_point_load.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | from landlab.components.flexure import FlexureComponent 4 | from landlab import RasterModelGrid 5 | 6 | 7 | def add_load_to_middle_of_grid(grid, load): 8 | shape = grid.shape 9 | 10 | load_array = grid.field_values( 11 | 'node', 'lithosphere__overlying_pressure').view() 12 | load_array.shape = shape 13 | load_array[shape[0] / 2, shape[1] / 2] = load 14 | 15 | 16 | def main(): 17 | (n_rows, n_cols) = (100, 100) 18 | (dy, dx) = (10e3, 10e3) 19 | 20 | grid = RasterModelGrid(n_rows, n_cols, dx) 21 | 22 | flex = FlexureComponent(grid, method='flexure') 23 | 24 | add_load_to_middle_of_grid(grid, 1e9) 25 | 26 | flex.update() 27 | 28 | grid.imshow('node', 'lithosphere__elevation', symmetric_cbar=True, 29 | show=True) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /component_drivers/flow_routing/test_script_for_route_flow_dn.py: -------------------------------------------------------------------------------- 1 | #! /usr/env/python 2 | 3 | """ 4 | test_script_for_route_flow_dn.py: 5 | 6 | Tests and illustrates use of route_flow_dn component. 7 | """ 8 | 9 | from landlab.components.flow_routing.route_flow_dn import FlowRouter 10 | from landlab.io import read_esri_ascii 11 | from landlab.plot.imshow import imshow_node_grid 12 | import os 13 | import pylab 14 | 15 | dem_name = './west_bijou_gully.asc' 16 | outlet_row = 82 17 | outlet_column = 38 18 | 19 | # Read in a DEM and set its boundaries 20 | DATA_FILE = os.path.join(os.path.dirname(__file__), dem_name) 21 | (grid, z) = read_esri_ascii(DATA_FILE, name='topographic__elevation') 22 | grid.set_nodata_nodes_to_closed(z, 0.) # set nodata nodes to inactive bounds 23 | outlet_node = grid.grid_coords_to_node_id(outlet_row, outlet_column) 24 | 25 | # Route flow 26 | flow_router = FlowRouter(grid) 27 | flow_router.route_flow() 28 | 29 | # Create a shaded image 30 | pylab.close() # clear any pre-existing plot 31 | pylab.figure(1) 32 | im = imshow_node_grid(grid, 'water__volume_flux', cmap = pylab.cm.RdBu) 33 | 34 | # add a title and axis labels 35 | pylab.title('Discharge') 36 | pylab.xlabel('Distance (m)') 37 | pylab.ylabel('Distance (m)') 38 | 39 | pylab.figure(2) 40 | im = imshow_node_grid(grid, 'topographic__elevation') 41 | pylab.title('DEM') 42 | pylab.xlabel('Distance (m)') 43 | pylab.ylabel('Distance (m)') 44 | 45 | # Display the plot 46 | pylab.show() 47 | 48 | import numpy as np 49 | print np.sum(grid.node_status!=4) 50 | -------------------------------------------------------------------------------- /scripts/flexure/example_two_point_load.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import numpy as np 4 | 5 | from landlab.components.flexure import FlexureComponent 6 | from landlab import RasterModelGrid 7 | from landlab.plot import imshow_field 8 | 9 | 10 | SHAPE = (100, 100) 11 | SPACING = (10e3, 10e3) 12 | LOAD_LOCS = [ 13 | (SHAPE[0] / 2, SHAPE[1] / 2), 14 | (SHAPE[0] / 4, SHAPE[1] * 3 / 4), 15 | ] 16 | 17 | 18 | def put_two_point_loads_on_grid(grid): 19 | load = grid.field_values('node', 'lithosphere__overlying_pressure') 20 | load = load.view() 21 | load.shape = grid.shape 22 | for loc in LOAD_LOCS: 23 | load[loc] = 1e15 24 | 25 | 26 | def create_lithosphere_elevation_with_bulge(grid): 27 | grid.add_zeros('node', 'lithosphere__elevation') 28 | 29 | z = grid.field_values('node', 'lithosphere__elevation').view() 30 | z.shape = grid.shape 31 | 32 | (y, x) = np.meshgrid(np.linspace(0, np.pi * .5, grid.shape[0]), 33 | np.linspace(0, np.pi * .5, grid.shape[1])) 34 | (x0, y0) = (np.pi / 3, np.pi / 8) 35 | np.sin((x - x0) ** 2 + (y - y0) ** 2, out=z) 36 | 37 | 38 | def main(): 39 | 40 | grid = RasterModelGrid(SHAPE[0], SHAPE[1], SPACING[0]) 41 | 42 | create_lithosphere_elevation_with_bulge(grid) 43 | 44 | flex = FlexureComponent(grid, method='flexure') 45 | 46 | put_two_point_loads_on_grid(grid) 47 | 48 | flex.update() 49 | 50 | grid.imshow('node', 'lithosphere__elevation', symmetric_cbar=False, 51 | show=True) 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /scripts/diffusion/scarp_diffusion_no_component.py: -------------------------------------------------------------------------------- 1 | #Import statements so that you will have access to the necessary functions 2 | import numpy 3 | from landlab import RasterModelGrid 4 | from landlab.plot.imshow import imshow_node_grid 5 | from pylab import show, figure 6 | 7 | #Create a raster grid with 25 rows, 40 columns, and cell spacing of 10 m 8 | mg = RasterModelGrid(25, 40, 10.0) 9 | 10 | #Create a field of node data (an array) on the grid called elevation. 11 | #Initially populate this array with zero values. 12 | z = mg.add_zeros('node', 'elevation') 13 | 14 | #Check the size of the array 15 | len(z) 16 | 17 | #Create a diagonal fault across the grid 18 | fault_y = 50.0 + 0.25*mg.node_x 19 | upthrown_nodes = numpy.where(mg.node_y>fault_y) 20 | z[upthrown_nodes] += 10.0 + 0.01*mg.node_x[upthrown_nodes] 21 | 22 | #Illustrate the grid 23 | imshow_node_grid(mg, z, cmap='jet', grid_units=['m','m']) 24 | show() 25 | 26 | #Define paramaters 27 | kd = 0.01 # 0.01 m2 per year 28 | dt = 0.2*mg.dx*mg.dx/kd # CFL condition 29 | 30 | #Set boundary conditions 31 | mg.set_closed_boundaries_at_grid_edges(False, True, False, True) 32 | 33 | #Get id values of the cord nodes on which you will operate 34 | interior_nodes = mg.get_core_nodes() 35 | 36 | #Evolve landscape 37 | for i in range(25): 38 | g = mg.calculate_gradients_at_active_links(z) 39 | qs = -kd*g 40 | dqsdx = mg.calculate_flux_divergence_at_nodes(qs) 41 | dzdt = -dqsdx 42 | z[interior_nodes] += dzdt[interior_nodes]*dt 43 | 44 | #Plot new landscape 45 | figure() 46 | imshow_node_grid(mg, z, cmap='jet', grid_units=['m','m']) 47 | show() 48 | -------------------------------------------------------------------------------- /scripts/diffusion/scarp_diffusion_with_component.py: -------------------------------------------------------------------------------- 1 | #Import statements so that you will have access to the necessary functions 2 | import numpy 3 | from landlab import RasterModelGrid 4 | from landlab.components.diffusion.diffusion import LinearDiffuser 5 | from landlab.plot.imshow import imshow_node_grid 6 | from pylab import show, figure 7 | 8 | 9 | #Create a raster grid with 25 rows, 40 columns, and cell spacing of 10 m 10 | mg = RasterModelGrid(25, 40, 10.0) 11 | 12 | #Create a field of node data (an array) on the grid called elevation. 13 | #Initially populate this array with zero values. 14 | #The component wants the elevation field to be called 'topographic__elevation' 15 | z = mg.add_zeros('node', 'topographic__elevation') 16 | 17 | #Check the size of the array 18 | len(z) 19 | 20 | #Create a diagonal fault across the grid 21 | fault_y = 50.0 + 0.25*mg.node_x 22 | upthrown_nodes = numpy.where(mg.node_y>fault_y) 23 | z[upthrown_nodes] += 10.0 + 0.01*mg.node_x[upthrown_nodes] 24 | 25 | #Illustrate the grid 26 | imshow_node_grid(mg, 'topographic__elevation', cmap='jet', grid_units=['m','m']) 27 | show() 28 | 29 | #Instantiate the diffusion component: 30 | linear_diffuse = LinearDiffuser(grid=mg, input_stream='./diffusion_input_file.txt') 31 | 32 | #Set boundary conditions 33 | mg.set_closed_boundaries_at_grid_edges(False, True, False, True) 34 | 35 | #set a model timestep 36 | #(the component will subdivide this as needed to keep things stable) 37 | dt = 2000. 38 | 39 | #Evolve landscape 40 | for i in range(25): 41 | linear_diffuse.diffuse(dt) 42 | 43 | #Plot new landscape 44 | figure() 45 | imshow_node_grid(mg, 'topographic__elevation', cmap='jet', grid_units=['m','m']) 46 | show() 47 | -------------------------------------------------------------------------------- /scripts/flexure/example_loading_everywhere.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import numpy as np 4 | 5 | from landlab.components.flexure import FlexureComponent 6 | from landlab import RasterModelGrid 7 | 8 | 9 | def get_random_load_magnitudes(n_loads): 10 | return np.random.normal(1e9, 1e12, n_loads) 11 | 12 | 13 | def put_loads_on_grid(grid, load_sizes): 14 | load = grid.at_node['lithosphere__overlying_pressure'] 15 | load[:] = load_sizes 16 | 17 | #for (loc, size) in zip(load_locations, load_sizes): 18 | # load.flat[loc] = size 19 | 20 | 21 | def main(): 22 | import argparse 23 | 24 | parser = argparse.ArgumentParser() 25 | parser.add_argument('--shape', type=int, default=200, 26 | help='Number rows and columns') 27 | parser.add_argument('--spacing', type=int, default=5e3, 28 | help='Spading between rows and columns (m)') 29 | parser.add_argument('--n-procs', type=int, default=1, 30 | help='Number of processors to use') 31 | parser.add_argument('--plot', action='store_true', default=False, 32 | help='Plot an image of the total deflection') 33 | 34 | args = parser.parse_args() 35 | 36 | shape = (args.shape, args.shape) 37 | spacing = (args.spacing, args.spacing) 38 | 39 | load_sizes = get_random_load_magnitudes(args.shape * args.shape) 40 | 41 | grid = RasterModelGrid(shape[0], shape[1], spacing[0]) 42 | 43 | flex = FlexureComponent(grid, method='flexure') 44 | 45 | put_loads_on_grid(grid, load_sizes) 46 | 47 | flex.update(n_procs=args.n_procs) 48 | 49 | if args.plot: 50 | grid.imshow('node', 'lithosphere__elevation', 51 | symmetric_cbar=False, cmap='spectral', show=True) 52 | 53 | if __name__ == '__main__': 54 | main() 55 | -------------------------------------------------------------------------------- /component_drivers/gFlex/gflex_driver.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | A driver for our version of AW's gFlex component. 4 | 5 | Created on Fri Feb 20 11:17:52 2015 6 | 7 | @author: danhobley 8 | """ 9 | 10 | from landlab.components.gFlex.flexure import gFlex 11 | import numpy as np 12 | import pylab 13 | from landlab import RasterModelGrid 14 | from landlab import ModelParameterDictionary 15 | from landlab.plot.imshow import imshow_node_grid 16 | 17 | inputs = ModelParameterDictionary('./AW_gflex_params.txt') 18 | nrows = inputs.read_int('nrows') 19 | ncols = inputs.read_int('ncols') 20 | dx = inputs.read_float('dx') 21 | dt = inputs.read_float('dt') 22 | time_to_run = inputs.read_float('run_time') 23 | init_elev = inputs.read_float('init_elev') 24 | 25 | mg = RasterModelGrid(nrows, ncols, dx) 26 | 27 | #create the fields in the grid 28 | mg.create_node_array_zeros('topographic__elevation') 29 | z = mg.create_node_array_zeros() + init_elev 30 | mg['node'][ 'topographic__elevation'] = z + np.random.rand(len(z))/1000. 31 | 32 | #make some surface load stresses in a field to test 33 | mg.at_node['surface_load__stress'] = np.zeros(nrows*ncols, dtype=float) 34 | square_qs = mg.at_node['surface_load__stress'].view().reshape((nrows,ncols)) 35 | square_qs[10:40, 10:40] += 1.e6 36 | 37 | #instantiate: 38 | gf = gFlex(mg, './AW_gflex_params.txt') 39 | 40 | #perform the loop: 41 | elapsed_time = 0. #total time in simulation 42 | while elapsed_time < time_to_run: 43 | print elapsed_time 44 | if elapsed_time+dt>time_to_run: 45 | print "Short step!" 46 | dt = time_to_run - elapsed_time 47 | gf.flex_lithosphere() 48 | elapsed_time += dt 49 | 50 | pylab.figure(1) 51 | im = imshow_node_grid(mg, 'topographic__elevation') # display a colored image 52 | 53 | pylab.figure(2) 54 | im = imshow_node_grid(mg, 'lithosphere__vertical_displacement') -------------------------------------------------------------------------------- /component_drivers/diffusion/diffusion_driver.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | A driver for our version of AW's gFlex component. 4 | 5 | Created on Fri Feb 20 11:17:52 2015 6 | 7 | @author: danhobley 8 | """ 9 | 10 | from landlab.components.diffusion.diffusion import LinearDiffuser 11 | import numpy as np 12 | import pylab 13 | from pylab import show 14 | from landlab import RasterModelGrid 15 | from landlab import ModelParameterDictionary 16 | from landlab.plot.imshow import imshow_node_grid 17 | 18 | inputs = ModelParameterDictionary('./diffusion_params.txt') 19 | nrows = inputs.read_int('nrows') 20 | ncols = inputs.read_int('ncols') 21 | dx = inputs.read_float('dx') 22 | dt = inputs.read_float('dt') 23 | time_to_run = inputs.read_float('run_time') 24 | init_elev = inputs.read_float('init_elev') 25 | uplift_rate = inputs.read_float('uplift_rate') 26 | 27 | mg = RasterModelGrid(nrows, ncols, dx) 28 | 29 | #create the fields in the grid 30 | mg.create_node_array_zeros('topographic__elevation') 31 | z = mg.create_node_array_zeros() + init_elev 32 | mg['node'][ 'topographic__elevation'] = z + np.random.rand(len(z))/1000. 33 | 34 | mg.set_fixed_value_boundaries_at_grid_edges(True, True, True, True) 35 | 36 | #instantiate: 37 | dfn = LinearDiffuser(mg, './diffusion_params.txt') 38 | 39 | #perform the loop: 40 | elapsed_time = 0. #total time in simulation 41 | while elapsed_time < time_to_run: 42 | print elapsed_time 43 | if elapsed_time+dt>time_to_run: 44 | print "Short step!" 45 | dt = time_to_run - elapsed_time 46 | dfn.diffuse(dt) 47 | mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_rate*dt 48 | elapsed_time += dt 49 | 50 | pylab.figure(1) 51 | im = imshow_node_grid(mg, 'topographic__elevation') # display a colored image 52 | 53 | pylab.figure(2) 54 | im2 = pylab.plot(mg.node_vector_to_raster(mg.at_node['topographic__elevation'])[:,ncols//2]) 55 | pylab.xlabel('Horizontal distance') 56 | pylab.ylabel('Elevation') 57 | pylab.title('Cross section') 58 | -------------------------------------------------------------------------------- /scripts/flexure/example_random_point_loads.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import numpy as np 4 | 5 | from landlab.components.flexure import FlexureComponent 6 | from landlab import RasterModelGrid 7 | 8 | 9 | def get_random_load_locations(shape, n_loads): 10 | return np.random.random_integers(0, shape[0] * shape[1] - 1, n_loads) 11 | 12 | 13 | def get_random_load_magnitudes(n_loads): 14 | return np.random.normal(1e9, 1e12, n_loads) 15 | 16 | 17 | def put_loads_on_grid(grid, load_locations, load_sizes): 18 | load = grid.at_node['lithosphere__overlying_pressure'].view() 19 | for (loc, size) in zip(load_locations, load_sizes): 20 | load.flat[loc] = size 21 | 22 | 23 | def main(): 24 | import argparse 25 | 26 | parser = argparse.ArgumentParser() 27 | parser.add_argument('--n-loads', type=int, default=16, 28 | help='Number of loads to apply') 29 | parser.add_argument('--shape', type=int, default=200, 30 | help='Number rows and columns') 31 | parser.add_argument('--spacing', type=int, default=5e3, 32 | help='Spading between rows and columns (m)') 33 | parser.add_argument('--n-procs', type=int, default=1, 34 | help='Number of processors to use') 35 | parser.add_argument('--plot', action='store_true', default=False, 36 | help='Plot an image of the total deflection') 37 | 38 | args = parser.parse_args() 39 | 40 | shape = (args.shape, args.shape) 41 | spacing = (args.spacing, args.spacing) 42 | 43 | load_locs = get_random_load_locations(shape, args.n_loads) 44 | load_sizes = get_random_load_magnitudes(args.n_loads) 45 | 46 | grid = RasterModelGrid(shape[0], shape[1], spacing[0]) 47 | 48 | flex = FlexureComponent(grid, method='flexure') 49 | 50 | put_loads_on_grid(grid, load_locs, load_sizes) 51 | 52 | flex.update(n_procs=args.n_procs) 53 | 54 | if args.plot: 55 | grid.imshow('node', 'lithosphere__elevation', 56 | symmetric_cbar=False, cmap='spectral', show=True) 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /component_drivers/nonlinear_diffusion/drive_perron.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | from landlab import RasterModelGrid 3 | from landlab import ModelParameterDictionary 4 | from landlab.plot.imshow import imshow_node_grid 5 | from landlab.components.nonlinear_diffusion.Perron_nl_diffuse import PerronNLDiffuse 6 | import pylab 7 | import time 8 | 9 | inputs = ModelParameterDictionary('./drive_perron_params.txt') 10 | nrows = inputs.read_int('nrows') 11 | ncols = inputs.read_int('ncols') 12 | dx = inputs.read_float('dx') 13 | dt = inputs.read_float('dt') 14 | time_to_run = inputs.read_float('run_time') 15 | # nt needs defining 16 | uplift = inputs.read_float('uplift_rate') 17 | init_elev = inputs.read_float('init_elev') 18 | 19 | mg = RasterModelGrid(nrows, ncols, dx) 20 | # mg.set_looped_boundaries(True, True) 21 | mg.set_closed_boundaries_at_grid_edges(True,True,True,True) 22 | 23 | #create the fields in the grid 24 | mg.create_node_array_zeros('topographic__elevation') 25 | z = mg.create_node_array_zeros() + init_elev 26 | mg.at_node[ 'topographic__elevation'] = z + numpy.random.rand(len(z))/1000. 27 | 28 | # Display a message 29 | print( 'Running ...' ) 30 | start_time = time.time() 31 | 32 | #instantiate the component: 33 | diffusion_component = PerronNLDiffuse(mg, './drive_perron_params.txt') 34 | 35 | #perform the loop: 36 | elapsed_time = 0. #total time in simulation 37 | while elapsed_time < time_to_run: 38 | print elapsed_time 39 | if elapsed_time+dttime_to_run: 42 | dt = elapsed_time - time_to_run 43 | mg = diffusion_component.diffuse(dt) 44 | elapsed_time += dt 45 | 46 | print('Total run time = '+str(time.time()-start_time)+' seconds.') 47 | 48 | # Clear previous plots 49 | pylab.figure(1) 50 | pylab.close() 51 | 52 | # Plot topography 53 | pylab.figure(1) 54 | im = imshow_node_grid(mg, 'topographic__elevation') 55 | pylab.title('Topography') 56 | 57 | elev_r = mg.node_vector_to_raster(mg.at_node['topographic__elevation']) 58 | pylab.figure(2) 59 | im = pylab.plot(dx*numpy.arange(nrows), elev_r[:,int(ncols//2)]) # display a colored image 60 | pylab.title('Vertical cross section') 61 | 62 | pylab.show() 63 | 64 | print('Done.') 65 | -------------------------------------------------------------------------------- /coupled/coupled_driver.py: -------------------------------------------------------------------------------- 1 | from landlab.components.flow_routing.route_flow_dn import FlowRouter 2 | from landlab.components.stream_power.fastscape_stream_power import FastscapeEroder 3 | from landlab.components.nonlinear_diffusion.Perron_nl_diffuse import PerronNLDiffuse 4 | from landlab.components.diffusion.diffusion import LinearDiffuser 5 | from landlab import ModelParameterDictionary 6 | from landlab.plot import channel_profile as prf 7 | from landlab.plot.imshow import imshow_node_grid 8 | 9 | from landlab import RasterModelGrid 10 | import numpy as np 11 | import pylab 12 | 13 | #get the needed properties to build the grid: 14 | input_file = './coupled_params.txt' 15 | inputs = ModelParameterDictionary(input_file) 16 | nrows = inputs.read_int('nrows') 17 | ncols = inputs.read_int('ncols') 18 | dx = inputs.read_float('dx') 19 | leftmost_elev = inputs.read_float('leftmost_elevation') 20 | initial_slope = inputs.read_float('initial_slope') 21 | uplift_rate = inputs.read_float('uplift_rate') 22 | runtime = inputs.read_float('total_time') 23 | dt = inputs.read_float('dt') 24 | nt = int(runtime//dt) 25 | uplift_per_step = uplift_rate * dt 26 | 27 | #instantiate the grid object 28 | mg = RasterModelGrid(nrows, ncols, dx) 29 | 30 | ##create the elevation field in the grid: 31 | #create the field 32 | mg.create_node_array_zeros('topographic__elevation') 33 | z = mg.create_node_array_zeros() + leftmost_elev 34 | z += initial_slope*np.amax(mg.node_y) - initial_slope*mg.node_y 35 | #put these values plus roughness into that field 36 | mg.at_node[ 'topographic__elevation'] = z + np.random.rand(len(z))/100000. 37 | 38 | #set up grid's boundary conditions (bottom, right, top, left is inactive) 39 | mg.set_closed_boundaries_at_grid_edges(False, True, False, True) 40 | 41 | # Display a message 42 | print 'Running ...' 43 | 44 | #instantiate the components: 45 | fr = FlowRouter(mg) 46 | sp = FastscapeEroder(mg, input_file) 47 | diffuse = PerronNLDiffuse(mg, input_file) 48 | lin_diffuse = LinearDiffuser(grid=mg, input_stream=input_file) 49 | 50 | #perform the loops: 51 | for i in xrange(nt): 52 | #note the input arguments here are not totally standardized between modules 53 | #mg = diffuse.diffuse(mg, i*dt) 54 | mg = lin_diffuse.diffuse(dt) 55 | mg = fr.route_flow() 56 | mg = sp.erode(mg, dt) 57 | mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_per_step 58 | 59 | ##plot long profiles along channels 60 | pylab.figure(6) 61 | profile_IDs = prf.channel_nodes(mg, mg.at_node['topographic__steepest_slope'], 62 | mg.at_node['drainage_area'], mg.at_node['flow_receiver']) 63 | dists_upstr = prf.get_distances_upstream(mg, len(mg.at_node['topographic__steepest_slope']), 64 | profile_IDs, mg.at_node['links_to_flow_receiver']) 65 | prf.plot_profiles(dists_upstr, profile_IDs, mg.at_node['topographic__elevation']) 66 | 67 | print 'Completed loop ', i 68 | 69 | print 'Completed the simulation. Plotting...' 70 | 71 | 72 | #Finalize and plot 73 | # Clear previous plots 74 | pylab.figure(1) 75 | pylab.close() 76 | pylab.figure(1) 77 | im = imshow_node_grid(mg, 'water__volume_flux', cmap='PuBu') # display a colored image 78 | 79 | pylab.figure(2) 80 | im = imshow_node_grid(mg, 'topographic__elevation') # display a colored image 81 | 82 | elev = mg['node']['topographic__elevation'] 83 | elev_r = mg.node_vector_to_raster(elev) 84 | pylab.figure(3) 85 | im = pylab.plot(mg.dx*np.arange(nrows), elev_r[:,int(ncols//2)]) 86 | pylab.title('N-S cross_section') 87 | 88 | pylab.figure(4) 89 | im = pylab.plot(mg.dx*np.arange(ncols), elev_r[int(nrows//4),:]) 90 | pylab.title('E-W cross_section') 91 | 92 | drainage_areas = mg['node']['drainage_area'][mg.get_interior_nodes()] 93 | steepest_slopes = mg['node']['topographic__steepest_slope'][mg.get_interior_nodes()] 94 | pylab.figure(5) 95 | pylab.loglog(drainage_areas, steepest_slopes, 'x') 96 | pylab.xlabel('Upstream drainage area, m^2') 97 | pylab.ylabel('Maximum slope') 98 | 99 | print('Done.') 100 | 101 | pylab.show() 102 | -------------------------------------------------------------------------------- /component_drivers/overland_flow/deAlmeida_LongBasin.py: -------------------------------------------------------------------------------- 1 | #! /usr/env/python 2 | """ deAlmeida_SquareBasin.py 3 | 4 | This is a example driver which utilizes the 5 | OverlandFlow class from generate_overland_flow_deAlmeida.py 6 | 7 | The driver reads in a long watershed run to steady state using a simple 8 | stream power driver. 9 | 10 | It then routes a storm across the square watershed. Storm parameters taken from 11 | Hawk and Eagleson (1992) Poisson parameters for the Denver, CO station. 12 | 13 | After the storm, additional time is needed to drain the water from the system. 14 | At the end of the storm, total water depth mass is calculated and compared 15 | against the predicted water mass under steady state conditions. The hydrograph 16 | is plotted and percent error is output. 17 | 18 | Written by Jordan M. Adams, November 2015. 19 | 20 | 21 | """ 22 | from __future__ import print_function 23 | 24 | from landlab.components.overland_flow.generate_overland_flow_deAlmeida import OverlandFlow 25 | from landlab.io import read_esri_ascii 26 | from matplotlib import pyplot as plt 27 | import os 28 | import time 29 | import numpy as np 30 | 31 | 32 | # This provides us with an initial time. At the end, it gives us total 33 | # model run time in seconds. 34 | start_time = time.time() 35 | 36 | ## This is a steady-state landscape generated by simple stream power 37 | ## This is a 400 x 100 grid with an outlet at center of the bottom edge. 38 | dem_name ='Long_TestBasin_Outlet50.asc' 39 | 40 | ## Now we can create and initialize a raster model grid by reading a DEM 41 | ## First, this looks for the DEM in the overland_flow folder in Landlab 42 | DATA_FILE = os.path.join(os.path.dirname(__file__), dem_name) 43 | 44 | ## Now the ASCII is read, assuming that it is standard ESRI format. 45 | (rmg, z) = read_esri_ascii(DATA_FILE) 46 | 47 | ## Start time 1 second 48 | elapsed_time = 1.0 49 | 50 | ## Model Run Time in seconds 51 | model_run_time = 500000.0 52 | 53 | ## Lists for saving data 54 | discharge_at_outlet = [] 55 | hydrograph_time_sec = [] 56 | hydrograph_time_hrs = [] 57 | 58 | ## Setting initial fields... 59 | rmg['node']['topographic__elevation'] = z 60 | rmg['link']['water_discharge'] = np.zeros(rmg.number_of_links) 61 | rmg['node']['water_depth'] = np.zeros(rmg.number_of_nodes) 62 | 63 | ## and fixed link boundary conditions... 64 | rmg.set_fixed_link_boundaries_at_grid_edges(True, True, True, True, fixed_link_value_of='water_discharge') 65 | 66 | ## Setting the outlet node to OPEN_BOUNDARY 67 | rmg.status_at_node[50] = 1 68 | 69 | 70 | ## Initialize the OverlandFlow() class. 71 | of = OverlandFlow(rmg, use_fixed_links=True) 72 | 73 | ## Record the start time so we know how long it runs. 74 | start_time = time.time() 75 | 76 | ## Link to sample at the outlet 77 | link_to_sample = 149 78 | 79 | ## Storm duration in seconds 80 | storm_duration = 7200.0 81 | 82 | 83 | ## Running the overland flow component. 84 | while elapsed_time < model_run_time: 85 | 86 | ## At the start of each loop, we calculate a new time step. 87 | #of.dt = of.gear_time_step(rmg) 88 | 89 | ## The storm starts when the model starts. While the elapsed time is less 90 | ## than the storm duration, we add water to the system as rainfall. 91 | if elapsed_time < storm_duration: 92 | 93 | of.rainfall_intensity = 4.07222 * (10 ** -7) # Rainfall intensity in m/s 94 | 95 | ## Then the elapsed time exceeds the storm duration, rainfall ceases. 96 | else: 97 | 98 | of.rainfall_intensity = 0.0 99 | 100 | ## Generating overland flow based on the deAlmeida solution. 101 | of.overland_flow() 102 | 103 | ## Append time and discharge to their lists to save data and for plotting. 104 | hydrograph_time_sec.append(elapsed_time) 105 | hydrograph_time_hrs.append(round(elapsed_time/3600., 2)) 106 | discharge_at_outlet.append(of.q[link_to_sample]) 107 | 108 | ## Add the time step, repeat until elapsed time >= model_run_time 109 | elapsed_time += of.dt 110 | 111 | 112 | plt.figure(1) 113 | plt.plot(hydrograph_time_hrs, (np.abs(discharge_at_outlet)*rmg.dx), 'b-') 114 | plt.xlabel('Time (hrs)') 115 | plt.ylabel('Discharge (cms)') 116 | plt.title('Hydrograph at Outlet') 117 | 118 | calc_water_mass = round(np.abs((np.trapz(hydrograph_time_sec, (np.abs( 119 | discharge_at_outlet) * rmg.dx)))), 2) 120 | theoretical_water_mass = round(((rmg.number_of_core_nodes * rmg.cellarea) * 121 | (4.07222 * (10 ** -7)) * storm_duration), 2) 122 | percent_error = round(((np.abs(calc_water_mass) - theoretical_water_mass) / 123 | theoretical_water_mass * 100), 2) 124 | 125 | print('\n', 'Total calculated water mass: ', calc_water_mass) 126 | print('\n', 'Theoretical water mass (Q = P * A): ', theoretical_water_mass) 127 | print('\n', 'Percent Error: ', percent_error, ' %') 128 | 129 | endtime = time.time() 130 | print('\n', 'Total run time: ', round(endtime - start_time, 2), ' seconds') -------------------------------------------------------------------------------- /component_drivers/overland_flow/deAlmeida_SquareBasin.py: -------------------------------------------------------------------------------- 1 | #! /usr/env/python 2 | """ deAlmeida_SquareBasin.py 3 | 4 | This is a example driver which utilizes the 5 | OverlandFlow class from generate_overland_flow_deAlmeida.py 6 | 7 | The driver reads in a square watershed run to steady state using a simple 8 | stream power driver. 9 | 10 | It then routes a storm across the square watershed. Storm parameters taken from 11 | Hawk and Eagleson (1992) Poisson parameters for the Denver, CO station. 12 | 13 | After the storm, additional time is needed to drain the water from the system. 14 | At the end of the storm, total water depth mass is calculated and compared 15 | against the predicted water mass under steady state conditions. The hydrograph 16 | is plotted and percent error is output. 17 | 18 | Written by Jordan M. Adams, November 2015. 19 | 20 | 21 | """ 22 | from __future__ import print_function 23 | 24 | from landlab.components.overland_flow.generate_overland_flow_deAlmeida import OverlandFlow 25 | from landlab.io import read_esri_ascii 26 | from matplotlib import pyplot as plt 27 | import os 28 | import time 29 | import numpy as np 30 | 31 | 32 | # This provides us with an initial time. At the end, it gives us total 33 | # model run time in seconds. 34 | start_time = time.time() 35 | 36 | ## This is a steady-state landscape generated by simple stream power 37 | ## This is a 200 x 200 grid with an outlet at center of the bottom edge. 38 | dem_name ='Square_TestBasin_Outlet100.asc' 39 | 40 | ## Now we can create and initialize a raster model grid by reading a DEM 41 | ## First, this looks for the DEM in the overland_flow folder in Landlab 42 | DATA_FILE = os.path.join(os.path.dirname(__file__), dem_name) 43 | 44 | ## Now the ASCII is read, assuming that it is standard ESRI format. 45 | (rmg, z) = read_esri_ascii(DATA_FILE) 46 | 47 | ## Start time 1 second 48 | elapsed_time = 1.0 49 | 50 | ## Model Run Time in seconds 51 | model_run_time = 500000.0 52 | 53 | ## Lists for saving data 54 | discharge_at_outlet = [] 55 | hydrograph_time_sec = [] 56 | hydrograph_time_hrs = [] 57 | 58 | ## Setting initial fields... 59 | rmg['node']['topographic__elevation'] = z 60 | rmg['link']['water_discharge'] = np.zeros(rmg.number_of_links) 61 | rmg['node']['water_depth'] = np.zeros(rmg.number_of_nodes) 62 | 63 | ## and fixed link boundary conditions... 64 | rmg.set_fixed_link_boundaries_at_grid_edges(True, True, True, True, fixed_link_value_of='water_discharge') 65 | 66 | ## Setting the outlet node to OPEN_BOUNDARY 67 | rmg.status_at_node[100] = 1 68 | 69 | 70 | ## Initialize the OverlandFlow() class. 71 | of = OverlandFlow(rmg, use_fixed_links=True) 72 | 73 | ## Record the start time so we know how long it runs. 74 | start_time = time.time() 75 | 76 | ## Link to sample at the outlet 77 | link_to_sample = 299 78 | 79 | ## Storm duration in seconds 80 | storm_duration = 7200.0 81 | 82 | 83 | ## Running the overland flow component. 84 | while elapsed_time < model_run_time: 85 | 86 | ## At the start of each loop, we calculate a new time step. 87 | #of.dt = of.gear_time_step()#rmg) 88 | 89 | ## The storm starts when the model starts. While the elapsed time is less 90 | ## than the storm duration, we add water to the system as rainfall. 91 | if elapsed_time < storm_duration: 92 | 93 | of.rainfall_intensity = 4.07222 * (10 ** -7) # Rainfall intensity in m/s 94 | 95 | ## Then the elapsed time exceeds the storm duration, rainfall ceases. 96 | else: 97 | 98 | of.rainfall_intensity = 0.0 99 | 100 | ## Generating overland flow based on the deAlmeida solution. 101 | of.overland_flow()#rmg) 102 | 103 | ## Append time and discharge to their lists to save data and for plotting. 104 | hydrograph_time_sec.append(elapsed_time) 105 | hydrograph_time_hrs.append(round(elapsed_time/3600., 2)) 106 | discharge_at_outlet.append(of.q[link_to_sample]) 107 | 108 | ## Add the time step, repeat until elapsed time >= model_run_time 109 | elapsed_time += of.dt 110 | 111 | 112 | plt.figure(2) 113 | plt.plot(hydrograph_time_hrs, (np.abs(discharge_at_outlet)*rmg.dx), 'k-') 114 | plt.xlabel('Time (hrs)') 115 | plt.ylabel('Discharge (cms)') 116 | plt.title('Hydrograph') 117 | 118 | calc_water_mass = round(np.abs((np.trapz(hydrograph_time_sec, (np.abs( 119 | discharge_at_outlet) * rmg.dx)))), 2) 120 | theoretical_water_mass = round(((rmg.number_of_core_nodes * rmg.cellarea) * 121 | (4.07222 * (10 ** -7)) * storm_duration), 2) 122 | percent_error = round(((np.abs(calc_water_mass) - theoretical_water_mass) / 123 | theoretical_water_mass * 100), 2) 124 | 125 | print('\n', 'Total calculated water mass: ', calc_water_mass) 126 | print('\n', 'Theoretical water mass (Q = P * A): ', theoretical_water_mass) 127 | print('\n', 'Percent Error: ', percent_error, ' %') 128 | 129 | endtime = time.time() 130 | print('\n', 'Total run time: ', round(endtime - start_time, 2), ' seconds') -------------------------------------------------------------------------------- /scripts/ecohydrology_flat_surface/run_driver.py: -------------------------------------------------------------------------------- 1 | """ 2 | Created on Wed Jul 20 2016 3 | 4 | This tutorial is on: 5 | landlab/tutorials/ecohydrology/cellular_automaton_vegetation_flat_surface.ipynb 6 | 7 | Creating a (.py) version of the same. 8 | 9 | @author: Sai Nudurupati & Erkan Istanbulluoglu 10 | """ 11 | 12 | import os 13 | import time 14 | 15 | import numpy as np 16 | 17 | from landlab import RasterModelGrid, load_params 18 | from ecohyd_functions_flat import (initialize, empty_arrays, 19 | create_pet_lookup, save, plot) 20 | 21 | 22 | grid1 = RasterModelGrid((100, 100), spacing=(5., 5.)) 23 | grid = RasterModelGrid((5, 4), spacing=(5., 5.)) 24 | 25 | # Create dictionary that holds the inputs 26 | data = load_params('inputs_vegetation_ca.yaml') 27 | 28 | (precip_dry, precip_wet, radiation, pet_tree, pet_shrub, 29 | pet_grass, soil_moisture, vegetation, vegca) = initialize(data, grid, grid1) 30 | 31 | n_years = 2000 # Approx number of years for model to run 32 | 33 | # Calculate approximate number of storms per year 34 | fraction_wet = (data['doy__end_of_monsoon'] - 35 | data['doy__start_of_monsoon']) / 365. 36 | fraction_dry = 1 - fraction_wet 37 | no_of_storms_wet = 8760 * fraction_wet / (data['mean_interstorm_wet'] + 38 | data['mean_storm_wet']) 39 | no_of_storms_dry = 8760 * fraction_dry / (data['mean_interstorm_dry'] + 40 | data['mean_storm_dry']) 41 | n = int(n_years * (no_of_storms_wet + no_of_storms_dry)) 42 | 43 | (precip, inter_storm_dt, storm_dt, time_elapsed, veg_type, daily_pet, 44 | rad_factor, EP30, pet_threshold) = empty_arrays(n, grid, grid1) 45 | 46 | create_pet_lookup(radiation, pet_tree, pet_shrub, pet_grass, daily_pet, 47 | rad_factor, EP30, grid) 48 | 49 | # Represent current time in years 50 | current_time = 0 # Start from first day of Jan 51 | 52 | # Keep track of run time for simulation - optional 53 | wallclock_start = time.clock() # Recording time taken for simulation 54 | 55 | # declaring few variables that will be used in the storm loop 56 | time_check = 0. # Buffer to store current_time at previous storm 57 | yrs = 0 # Keep track of number of years passed 58 | water_stress = 0. # Buffer for Water Stress 59 | Tg = 270 # Growing season in days 60 | 61 | # Run storm Loop 62 | for i in range(n): 63 | # Update objects 64 | 65 | # Calculate Day of Year (DOY) 66 | julian = np.int(np.floor((current_time - np.floor(current_time)) * 365.)) 67 | 68 | # Generate seasonal storms 69 | # Wet Season - Jul to Sep - NA Monsoon 70 | if data['doy__start_of_monsoon'] <= julian <= data['doy__end_of_monsoon']: 71 | precip_wet.update() 72 | precip[i] = precip_wet.storm_depth 73 | storm_dt[i] = precip_wet.storm_duration 74 | inter_storm_dt[i] = precip_wet.interstorm_duration 75 | else: # for Dry season 76 | precip_dry.update() 77 | precip[i] = precip_dry.storm_depth 78 | storm_dt[i] = precip_dry.storm_duration 79 | inter_storm_dt[i] = precip_dry.interstorm_duration 80 | 81 | # Spatially distribute PET and its 30-day-mean (analogous to degree day) 82 | grid.at_cell['surface__potential_evapotranspiration_rate'] = daily_pet[julian] 83 | grid.at_cell['surface__potential_evapotranspiration_30day_mean'] = EP30[julian] 84 | 85 | # Assign spatial rainfall data 86 | grid.at_cell['rainfall__daily_depth'] = np.full(grid.number_of_cells, precip[i]) 87 | 88 | # Update soil moisture component 89 | current_time = soil_moisture.update(current_time, Tr=storm_dt[i], 90 | Tb=inter_storm_dt[i]) 91 | 92 | # Decide whether its growing season or not 93 | if julian != 364: 94 | if EP30[julian + 1, 0] > EP30[julian, 0]: 95 | pet_threshold = 1 96 | # 1 corresponds to ETThresholdup (begin growing season) 97 | else: 98 | pet_threshold = 0 99 | # 0 corresponds to ETThresholddown (end growing season) 100 | 101 | # Update vegetation component 102 | vegetation.update(PETThreshold_switch=pet_threshold, Tb=inter_storm_dt[i], 103 | Tr=storm_dt[i]) 104 | 105 | # Update yearly cumulative water stress data 106 | water_stress += (grid.at_cell['vegetation__water_stress'] * 107 | inter_storm_dt[i] / 24.) 108 | 109 | # Record time (optional) 110 | time_elapsed[i] = current_time 111 | 112 | # Update spatial PFTs with Cellular Automata rules 113 | if (current_time - time_check) >= 1.: 114 | if yrs % 100 == 0: 115 | print 'Elapsed time = ', yrs, ' years' 116 | veg_type[yrs] = grid1.at_cell['vegetation__plant_functional_type'] 117 | WS_ = np.choose(veg_type[yrs], water_stress) 118 | grid1.at_cell['vegetation__cumulative_water_stress'] = WS_ / Tg 119 | vegca.update() 120 | time_check = current_time 121 | water_stress = 0 122 | yrs += 1 123 | 124 | veg_type[yrs] = grid1.at_cell['vegetation__plant_functional_type'] 125 | 126 | wallclock_stop = time.clock() 127 | walltime = (wallclock_stop - wallclock_start) / 60. # in minutes 128 | print 'Time_consumed = ', walltime, ' minutes' 129 | 130 | # Saving 131 | try: 132 | os.mkdir('output') 133 | except OSError: 134 | pass 135 | finally: 136 | os.chdir('output') 137 | 138 | save('veg', inter_storm_dt, storm_dt, precip, veg_type, yrs, 139 | walltime, time_elapsed) 140 | 141 | plot('veg', grid1, veg_type, yrs, yr_step=100) 142 | -------------------------------------------------------------------------------- /component_drivers/cellular_automata/diffusion_in_gravity.py: -------------------------------------------------------------------------------- 1 | #!/usr/env/python 2 | 3 | """ 4 | diffusion_in_gravity.py 5 | 6 | Example of a continuous-time, stochastic, pair-based cellular automaton model, 7 | which simulates diffusion by random particle motion in a gravitational field. 8 | The purpose of the example is to demonstrate the use of an OrientedRasterLCA. 9 | 10 | GT, September 2014 11 | """ 12 | from __future__ import print_function 13 | 14 | _DEBUG = False 15 | 16 | import time 17 | from numpy import where, bitwise_and 18 | from landlab import RasterModelGrid 19 | from landlab.components.cellular_automata.celllab_cts import Transition, CAPlotter 20 | from landlab.components.cellular_automata.oriented_raster_cts import OrientedRasterCTS 21 | 22 | 23 | def setup_transition_list(): 24 | """ 25 | Creates and returns a list of Transition() objects to represent state 26 | transitions for a biased random walk, in which the rate of downward 27 | motion is greater than the rate in the other three directions. 28 | 29 | Parameters 30 | ---------- 31 | (none) 32 | 33 | Returns 34 | ------- 35 | xn_list : list of Transition objects 36 | List of objects that encode information about the link-state transitions. 37 | 38 | Notes 39 | ----- 40 | State 0 represents fluid and state 1 represents a particle (such as a 41 | sediment grain or dissolved heavy particle). 42 | 43 | The states and transitions are as follows: 44 | 45 | Pair state Transition to Process Rate 46 | ========== ============= ======= ==== 47 | 0 (0-0) (none) - - 48 | 1 (0-1) 2 (1-0) left motion 1.0 49 | 2 (1-0) 1 (0-1) right motion 1.0 50 | 3 (1-1) (none) - - 51 | 4 (0/0) (none) - - 52 | 5 (0/1) 6 (1/0) down motion 1.1 53 | 6 (1/0) 5 (0/1) up motion 0.9 54 | 7 (1/1) (none) - - 55 | 56 | """ 57 | xn_list = [] 58 | 59 | xn_list.append( Transition((0,1,0), (1,0,0), 1., 'left motion') ) 60 | xn_list.append( Transition((1,0,0), (0,1,0), 1., 'right motion') ) 61 | xn_list.append( Transition((0,1,1), (1,0,1), 1.1, 'down motion') ) 62 | xn_list.append( Transition((1,0,1), (0,1,1), 0.9, 'up motion') ) 63 | 64 | if _DEBUG: 65 | print() 66 | print('setup_transition_list(): list has',len(xn_list),'transitions:') 67 | for t in xn_list: 68 | print(' From state',t.from_state,'to state',t.to_state,'at rate',t.rate,'called',t.name) 69 | 70 | return xn_list 71 | 72 | 73 | def main(): 74 | 75 | # INITIALIZE 76 | 77 | # User-defined parameters 78 | nr = 80 79 | nc = 80 80 | plot_interval = 2 81 | run_duration = 200 82 | report_interval = 5.0 # report interval, in real-time seconds 83 | 84 | # Remember the clock time, and calculate when we next want to report 85 | # progress. 86 | current_real_time = time.time() 87 | next_report = current_real_time + report_interval 88 | 89 | # Create grid 90 | mg = RasterModelGrid(nr, nc, 1.0) 91 | 92 | # Make the boundaries be walls 93 | mg.set_closed_boundaries_at_grid_edges(True, True, True, True) 94 | 95 | # Set up the states and pair transitions. 96 | ns_dict = { 0 : 'fluid', 1 : 'particle' } 97 | xn_list = setup_transition_list() 98 | 99 | # Create the node-state array and attach it to the grid 100 | node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int) 101 | 102 | # Initialize the node-state array 103 | middle_rows = where(bitwise_and(mg.node_y>0.45*nr, mg.node_y<0.55*nr))[0] 104 | node_state_grid[middle_rows] = 1 105 | 106 | # Create the CA model 107 | ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid) 108 | 109 | # Debug output if needed 110 | if _DEBUG: 111 | n = ca.grid.number_of_nodes 112 | for r in range(ca.grid.number_of_node_rows): 113 | for c in range(ca.grid.number_of_node_columns): 114 | n -= 1 115 | print('{0:.0f}'.format(ca.node_state[n]), end=' ') 116 | print() 117 | 118 | # Create a CAPlotter object for handling screen display 119 | ca_plotter = CAPlotter(ca) 120 | 121 | # Plot the initial grid 122 | ca_plotter.update_plot() 123 | 124 | # RUN 125 | current_time = 0.0 126 | while current_time < run_duration: 127 | 128 | # Once in a while, print out simulation and real time to let the user 129 | # know that the sim is running ok 130 | current_real_time = time.time() 131 | if current_real_time >= next_report: 132 | print('Current sim time',current_time,'(',100*current_time/run_duration,'%)') 133 | next_report = current_real_time + report_interval 134 | 135 | # Run the model forward in time until the next output step 136 | ca.run(current_time+plot_interval, ca.node_state, 137 | plot_each_transition=False) #, plotter=ca_plotter) 138 | current_time += plot_interval 139 | 140 | # Plot the current grid 141 | ca_plotter.update_plot() 142 | 143 | # for debugging 144 | if _DEBUG: 145 | n = ca.grid.number_of_nodes 146 | for r in range(ca.grid.number_of_node_rows): 147 | for c in range(ca.grid.number_of_node_columns): 148 | n -= 1 149 | print('{0:.0f}'.format(ca.node_state[n]), end=' ') 150 | print() 151 | 152 | 153 | # FINALIZE 154 | 155 | # Plot 156 | ca_plotter.finalize() 157 | 158 | 159 | if __name__ == "__main__": 160 | main() 161 | -------------------------------------------------------------------------------- /component_drivers/cellular_automata/rock_weathering.py: -------------------------------------------------------------------------------- 1 | #!/usr/env/python 2 | 3 | """ 4 | rock_weathering.py 5 | 6 | CellLab-CTS model that simulates the weathering of rock to saprolite around 7 | a network of fractures. 8 | 9 | Created (and translated from earlier code by) by Greg Tucker, Jul 2015 10 | """ 11 | from __future__ import print_function 12 | 13 | import time 14 | import numpy as np 15 | from landlab import RasterModelGrid 16 | from landlab.components.cellular_automata.celllab_cts import Transition, CAPlotter 17 | from landlab.components.cellular_automata.raster_cts import RasterCTS 18 | from landlab.components.fracture_grid.fracture_grid import make_frac_grid 19 | import matplotlib 20 | from landlab.io.netcdf import write_netcdf 21 | 22 | 23 | def setup_transition_list(): 24 | """ 25 | Creates and returns a list of Transition() objects to represent the 26 | grain-by-grain transformation of bedrock to saprolite. 27 | 28 | Returns 29 | ------- 30 | xn_list : list of Transition objects 31 | List of objects that encode information about the link-state transitions. 32 | 33 | Notes 34 | ----- 35 | Weathering here is treated very simply: a bedrock particle adjacent to a 36 | saprolite particle has a specified probability (rate) of weathering to 37 | saprolite; in other words, a rock-saprolite pair can turn into a 38 | saprolite-saprolite pair. 39 | 40 | The states and transitions are as follows: 41 | 42 | Pair state Transition to Process Rate (cells/s) 43 | ========== ============= ======= ============== 44 | 0 (0-0) 1 (0-1) 0.5 45 | 2 (1-0) 0.5 46 | 1 (0-1) 3 (1-1) 1.0 47 | 2 (1-0) 3 (1-1) 1.0 48 | 3 (1-1) (none) - 49 | 50 | """ 51 | 52 | # Create an empty transition list 53 | xn_list = [] 54 | 55 | # Append two transitions to the list. 56 | # Note that the arguments to the Transition() object constructor are: 57 | # - Tuple representing starting pair state 58 | # (left/bottom cell, right/top cell, orientation) 59 | # - Tuple representing new pair state 60 | # (left/bottom cell, right/top cell, orientation) 61 | # - Transition rate (cells per time step, in this case 1 sec) 62 | # - Name for transition 63 | xn_list.append( Transition((0,1,0), (1,1,0), 1., 'weathering') ) 64 | xn_list.append( Transition((1,0,0), (1,1,0), 1., 'weathering') ) 65 | 66 | return xn_list 67 | 68 | 69 | def main(): 70 | 71 | # INITIALIZE 72 | 73 | # User-defined parameters 74 | nr = 200 # number of rows in grid 75 | nc = 200 # number of columns in grid 76 | plot_interval = 0.05 # time interval for plotting (unscaled) 77 | run_duration = 5.0 # duration of run (unscaled) 78 | report_interval = 10.0 # report interval, in real-time seconds 79 | frac_spacing = 10 # average fracture spacing, nodes 80 | outfilename = 'wx' # name for netCDF files 81 | 82 | # Remember the clock time, and calculate when we next want to report 83 | # progress. 84 | current_real_time = time.time() 85 | next_report = current_real_time + report_interval 86 | 87 | # Counter for output files 88 | time_slice = 0 89 | 90 | # Create grid 91 | mg = RasterModelGrid(nr, nc, 1.0) 92 | 93 | # Make the boundaries be walls 94 | mg.set_closed_boundaries_at_grid_edges(True, True, True, True) 95 | 96 | # Set up the states and pair transitions. 97 | ns_dict = { 0 : 'rock', 1 : 'saprolite' } 98 | xn_list = setup_transition_list() 99 | 100 | # Create the node-state array and attach it to the grid. 101 | # (Note use of numpy's uint8 data type. This saves memory AND allows us 102 | # to write output to a netCDF3 file; netCDF3 does not handle the default 103 | # 64-bit integer type) 104 | node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=np.uint8) 105 | 106 | node_state_grid[:] = make_frac_grid(frac_spacing, model_grid=mg) 107 | 108 | # Create the CA model 109 | ca = RasterCTS(mg, ns_dict, xn_list, node_state_grid) 110 | 111 | # Set up the color map 112 | rock_color = (0.8, 0.8, 0.8) 113 | sap_color = (0.4, 0.2, 0) 114 | clist = [rock_color, sap_color] 115 | my_cmap = matplotlib.colors.ListedColormap(clist) 116 | 117 | # Create a CAPlotter object for handling screen display 118 | ca_plotter = CAPlotter(ca, cmap=my_cmap) 119 | 120 | # Plot the initial grid 121 | ca_plotter.update_plot() 122 | 123 | # Output the initial grid to file 124 | write_netcdf((outfilename+str(time_slice)+'.nc'), mg, 125 | #format='NETCDF3_64BIT', 126 | names='node_state_map') 127 | 128 | # RUN 129 | current_time = 0.0 130 | while current_time < run_duration: 131 | 132 | # Once in a while, print out simulation and real time to let the user 133 | # know that the sim is running ok 134 | current_real_time = time.time() 135 | if current_real_time >= next_report: 136 | print('Current sim time', current_time, '(', 137 | 100 * current_time/run_duration, '%)') 138 | next_report = current_real_time + report_interval 139 | 140 | # Run the model forward in time until the next output step 141 | ca.run(current_time+plot_interval, ca.node_state, 142 | plot_each_transition=False) 143 | current_time += plot_interval 144 | 145 | # Plot the current grid 146 | ca_plotter.update_plot() 147 | 148 | # Output the current grid to a netCDF file 149 | time_slice += 1 150 | write_netcdf((outfilename+str(time_slice)+'.nc'), mg, 151 | #format='NETCDF3_64BIT', 152 | names='node_state_map') 153 | 154 | 155 | # FINALIZE 156 | 157 | # Plot 158 | ca_plotter.finalize() 159 | 160 | 161 | 162 | # If user runs this file, activate the main() function 163 | if __name__ == "__main__": 164 | main() 165 | -------------------------------------------------------------------------------- /scripts/ecohydrology_flat_surface/ecohyd_functions_flat.py: -------------------------------------------------------------------------------- 1 | # Authors: Sai Nudurupati & Erkan Istanbulluoglu, 21May15 2 | # Edited: 15Jul16 - to conform to Landlab version 1. 3 | import numpy as np 4 | import matplotlib as mpl 5 | import matplotlib.pyplot as plt 6 | 7 | from landlab import load_params 8 | from landlab.plot import imshow_grid 9 | from landlab.components import (PrecipitationDistribution, Radiation, 10 | PotentialEvapotranspiration, SoilMoisture, 11 | Vegetation, VegCA) 12 | 13 | GRASS = 0 14 | SHRUB = 1 15 | TREE = 2 16 | BARE = 3 17 | SHRUBSEEDLING = 4 18 | TREESEEDLING = 5 19 | 20 | 21 | def compose_veg_grid(grid, percent_bare=0.4, percent_grass=0.2, 22 | percent_shrub=0.2, percent_tree=0.2): 23 | """Compose spatially distribute PFT.""" 24 | no_cells = grid.number_of_cells 25 | shrub_point = int(percent_bare * no_cells) 26 | tree_point = int((percent_bare + percent_shrub) * no_cells) 27 | grass_point = int((1 - percent_grass) * no_cells) 28 | 29 | veg_grid = np.full(grid.number_of_cells, BARE, dtype=int) 30 | veg_grid[shrub_point:tree_point] = SHRUB 31 | veg_grid[tree_point:grass_point] = TREE 32 | veg_grid[grass_point:] = GRASS 33 | 34 | np.random.shuffle(veg_grid) 35 | return veg_grid 36 | 37 | 38 | def initialize(data, grid, grid1): 39 | """Initialize random plant type field. 40 | 41 | Plant types are defined as the following: 42 | 43 | * GRASS = 0 44 | * SHRUB = 1 45 | * TREE = 2 46 | * BARE = 3 47 | * SHRUBSEEDLING = 4 48 | * TREESEEDLING = 5 49 | """ 50 | grid1.at_cell['vegetation__plant_functional_type'] = compose_veg_grid( 51 | grid1, percent_bare=data['percent_bare_initial'], 52 | percent_grass=data['percent_grass_initial'], 53 | percent_shrub=data['percent_shrub_initial'], 54 | percent_tree=data['percent_tree_initial']) 55 | 56 | # Assign plant type for representative ecohydrologic simulations 57 | grid.at_cell['vegetation__plant_functional_type'] = np.arange(6) 58 | grid1.at_node['topographic__elevation'] = np.full(grid1.number_of_nodes, 59 | 1700.) 60 | grid.at_node['topographic__elevation'] = np.full(grid.number_of_nodes, 61 | 1700.) 62 | precip_dry = PrecipitationDistribution( 63 | mean_storm_duration=data['mean_storm_dry'], 64 | mean_interstorm_duration=data['mean_interstorm_dry'], 65 | mean_storm_depth=data['mean_storm_depth_dry']) 66 | precip_wet = PrecipitationDistribution( 67 | mean_storm_duration=data['mean_storm_wet'], 68 | mean_interstorm_duration=data['mean_interstorm_wet'], 69 | mean_storm_depth=data['mean_storm_depth_wet']) 70 | 71 | radiation = Radiation(grid) 72 | pet_tree = PotentialEvapotranspiration(grid, method=data['PET_method'], 73 | MeanTmaxF=data['MeanTmaxF_tree'], 74 | delta_d=data['DeltaD']) 75 | pet_shrub = PotentialEvapotranspiration(grid, method=data['PET_method'], 76 | MeanTmaxF=data['MeanTmaxF_shrub'], 77 | delta_d=data['DeltaD']) 78 | pet_grass = PotentialEvapotranspiration(grid, method=data['PET_method'], 79 | MeanTmaxF=data['MeanTmaxF_grass'], 80 | delta_d=data['DeltaD']) 81 | soil_moisture = SoilMoisture(grid, **data) # Soil Moisture object 82 | vegetation = Vegetation(grid, **data) # Vegetation object 83 | vegca = VegCA(grid1, **data) # Cellular automaton object 84 | 85 | # Initializing inputs for Soil Moisture object 86 | grid.at_cell['vegetation__live_leaf_area_index'] = ( 87 | 1.6 * np.ones(grid.number_of_cells)) 88 | grid.at_cell['soil_moisture__initial_saturation_fraction'] = ( 89 | 0.59 * np.ones(grid.number_of_cells)) 90 | 91 | return (precip_dry, precip_wet, radiation, pet_tree, pet_shrub, 92 | pet_grass, soil_moisture, vegetation, vegca) 93 | 94 | 95 | def empty_arrays(n, grid, grid1): 96 | precip = np.empty(n) # Record precipitation 97 | inter_storm_dt = np.empty(n) # Record inter storm duration 98 | storm_dt = np.empty(n) # Record storm duration 99 | time_elapsed = np.empty(n) # To record time elapsed from the start of simulation 100 | 101 | # Cumulative Water Stress 102 | veg_type = np.empty([n / 55, grid1.number_of_cells], dtype=int) 103 | daily_pet = np.zeros([365, grid.number_of_cells]) 104 | rad_factor = np.empty([365, grid.number_of_cells]) 105 | EP30 = np.empty([365, grid.number_of_cells]) 106 | 107 | # 30 day average PET to determine season 108 | pet_threshold = 0 # Initializing pet_threshold to ETThresholddown 109 | return (precip, inter_storm_dt, storm_dt, time_elapsed, veg_type, 110 | daily_pet, rad_factor, EP30, pet_threshold) 111 | 112 | 113 | def create_pet_lookup(radiation, pet_tree, pet_shrub, pet_grass, daily_pet, 114 | rad_factor, EP30, grid): 115 | for i in range(0, 365): 116 | pet_tree.update(float(i) / 365.25) 117 | pet_shrub.update(float(i) / 365.25) 118 | pet_grass.update(float(i) / 365.25) 119 | daily_pet[i] = [pet_grass._PET_value, pet_shrub._PET_value, 120 | pet_tree._PET_value, 0., pet_shrub._PET_value, 121 | pet_tree._PET_value] 122 | radiation.update(float(i) / 365.25) 123 | rad_factor[i] = grid.at_cell['radiation__ratio_to_flat_surface'] 124 | 125 | if i < 30: 126 | if i == 0: 127 | EP30[0] = daily_pet[0] 128 | else: 129 | EP30[i] = np.mean(daily_pet[:i], axis=0) 130 | else: 131 | EP30[i] = np.mean(daily_pet[i - 30:i], axis=0) 132 | 133 | 134 | def save(sim, inter_storm_dt, storm_dt, precip, veg_type, yrs, 135 | walltime, time_elapsed): 136 | np.save(sim + '_Tb', inter_storm_dt) 137 | np.save(sim + '_Tr', storm_dt) 138 | np.save(sim + '_P', precip) 139 | np.save(sim + '_VegType', veg_type) 140 | np.save(sim + '_Years', yrs) 141 | np.save(sim + '_Time_Consumed_minutes', walltime) 142 | np.save(sim + '_CurrentTime', time_elapsed) 143 | 144 | 145 | def plot(sim, grid, veg_type, yrs, yr_step=10): 146 | pic = 0 147 | years = range(0, yrs) 148 | cmap = mpl.colors.ListedColormap( 149 | ['green', 'red', 'black', 'white', 'red', 'black']) 150 | bounds = [-0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5] 151 | norm = mpl.colors.BoundaryNorm(bounds, cmap.N) 152 | print 'Plotting cellular field of Plant Functional Type' 153 | print 'Green - Grass; Red - Shrubs; Black - Trees; White - Bare' 154 | 155 | # Plot images to make gif. 156 | for year in range(0, yrs, yr_step): 157 | filename = 'year_' + "%05d" % year 158 | pic += 1 159 | plt.figure(pic, figsize=(10, 8)) 160 | imshow_grid(grid, veg_type[year], values_at='cell', cmap=cmap, 161 | grid_units=('m', 'm'), norm=norm, limits=[0, 5], 162 | allow_colorbar=False) 163 | plt.title(filename, weight='bold', fontsize=22) 164 | plt.xlabel('X (m)', weight='bold', fontsize=18) 165 | plt.ylabel('Y (m)', weight='bold', fontsize=18) 166 | plt.xticks(fontsize=14, weight='bold') 167 | plt.yticks(fontsize=14, weight='bold') 168 | plt.savefig(sim + '_' + filename) 169 | 170 | grass_cov = np.empty(yrs) 171 | shrub_cov = np.empty(yrs) 172 | tree_cov = np.empty(yrs) 173 | grid_size = float(veg_type.shape[1]) 174 | 175 | for x in range(0, yrs): 176 | grass_cov[x] = (veg_type[x][veg_type[x] == GRASS].size / grid_size) * 100 177 | shrub_cov[x] = ((veg_type[x][veg_type[x] == SHRUB].size / grid_size) * 178 | 100 + (veg_type[x][veg_type[x] == SHRUBSEEDLING].size / 179 | grid_size) * 100) 180 | tree_cov[x] = ((veg_type[x][veg_type[x] == TREE].size / grid_size) * 181 | 100 + (veg_type[x][veg_type[x] == TREESEEDLING].size / 182 | grid_size) * 100) 183 | 184 | pic += 1 185 | plt.figure(pic, figsize=(10, 8)) 186 | plt.plot(years, grass_cov, '-g', label='Grass', linewidth=4) 187 | plt.hold(True) 188 | plt.plot(years, shrub_cov, '-r', label='Shrub', linewidth=4) 189 | plt.hold(True) 190 | plt.plot(years, tree_cov, '-k', label='Tree', linewidth=4) 191 | plt.ylabel('% Area Covered by Plant Type', weight='bold', fontsize=18) 192 | plt.xlabel('Time in years', weight='bold', fontsize=18) 193 | plt.xticks(fontsize=12, weight='bold') 194 | plt.yticks(fontsize=12, weight='bold') 195 | plt.legend(loc=0, prop={'size': 16, 'weight': 'bold'}) 196 | plt.savefig(sim + '_percent_cover') 197 | -------------------------------------------------------------------------------- /scripts/ecohydrology_flat_surface/inputs_vegetation_ca.yaml: -------------------------------------------------------------------------------- 1 | ### All inputs for Vegetation Cellular Automaton Model built on The Landlab 2 | ### can be given here. 3 | ### 14Feb2015 - Sai Nudurupati & Erkan Istanbulluoglu 4 | ### 15Jul2016 - Updated to comply with Landlab Version 1 naming conventions. 5 | 6 | ### Vegetation Cellular Automaton Model Input File: 7 | 8 | n_short: 6600 # Number of storms for short simulation that plots hydrologic parameters 9 | n_long_DEM: 1320 # Number of storms for long simulation that operates on single grid for sloped surface 10 | n_long_flat: 660000 # Number of storms for long simulation that operates on two grids - flat surface 11 | 12 | ## Initial Plant Functional Types (PFT) distribution 13 | percent_bare_initial: 0.7 # Initial percentage of cells occupied by bare soil 14 | percent_grass_initial: 0.1 # Initial percentage of cells occupied by grass 15 | percent_shrub_initial: 0.1 # Initial percentage of cells occupied by shrubs 16 | percent_tree_initial: 0.1 # Initial percentage of cells occupied by trees 17 | 18 | ## Precipitation: 19 | 20 | # Dry Season 21 | mean_storm_dry: 2.016 # Mean storm duration (hours) 22 | mean_interstorm_dry: 159.36 # Mean interstorm duration (hours) 23 | mean_storm_depth_dry: 3.07 # Mean storm depth (mm) 24 | 25 | # Wet Season 26 | mean_storm_wet: 1.896 # Mean storm duration (hours) 27 | mean_interstorm_wet: 84.24 # Mean interstorm duration (hours) 28 | mean_storm_depth_wet: 4.79 # Mean storm depth (mm) 29 | doy__start_of_monsoon: 182 # Day of the year when the monsoon starts 30 | doy__end_of_monsoon: 273 # Day of the year when the monsoon ends 31 | 32 | ## PotentialEvapotranspiration: 33 | # Cosine Method 34 | PET_method: Cosine 35 | LT: 0 # Lag between peak TmaxF estimated by cosine method and solar forcing (days) 36 | DeltaD: 7. # Calibrated difference between 37 | ND: 365. # Number of days in the year (days) 38 | MeanTmaxF_grass: 5.15 # Mean annual rate of TmaxF (mm/d) 39 | MeanTmaxF_shrub: 3.77 # Mean annual rate of TmaxF (mm/d) 40 | MeanTmaxF_tree: 4.96 # Mean annual rate of TmaxF (mm/d) 41 | 42 | # TmaxF - Estimated maximum evapotranspiration as a function of DOY 43 | # using Penman Monteith method for historical weather 44 | 45 | ## Soil Moisture: 46 | 47 | runon: 0. # Runon from higher elevations (mm) 48 | f_bare: 0.7 # Fraction to partition PET for bare soil (None) 49 | 50 | # Grass 51 | 52 | VEGTYPE_grass: 0 # Integer value to infer Vegetation Type 53 | intercept_cap_grass: 1. # Full canopy interception capacity (mm) 54 | zr_grass: 0.3 # Root depth (m) 55 | I_B_grass: 20. # Infiltration capacity of bare soil (mm/h) 56 | I_V_grass: 24. # Infiltration capacity of vegetated soil (mm/h) 57 | pc_grass: 0.43 # Soil porosity (None) 58 | fc_grass: 0.56 # Soil saturation degree at field capacity (None) 59 | sc_grass: 0.33 # Soil saturation degree at stomatal closure (None) 60 | wp_grass: 0.13 # Soil saturation degree at wilting point (None) 61 | hgw_grass: 0.1 # Soil saturation degree at hygroscopic point (None) 62 | beta_grass: 13.8 # Deep percolation constant = 2*b+4 where b is water retention parameter 63 | 64 | # Shrub 65 | 66 | VEGTYPE_shrub: 1 # Integer value to infer Vegetation Type 67 | intercept_cap_shrub: 1.5 # Full canopy interception capacity (mm) 68 | zr_shrub: 0.5 # Root depth (m) 69 | I_B_shrub: 20. # Infiltration capacity of bare soil (mm/h) 70 | I_V_shrub: 40. # Infiltration capacity of vegetated soil (mm/h) 71 | pc_shrub: 0.43 # Soil porosity (None) 72 | fc_shrub: 0.56 # Soil saturation degree at field capacity (None) 73 | sc_shrub: 0.24 # Soil saturation degree at stomatal closure (None) 74 | wp_shrub: 0.13 # Soil saturation degree at wilting point (None) 75 | hgw_shrub: 0.1 # Soil saturation degree at hygroscopic point (None) 76 | beta_shrub: 13.8 # Deep percolation constant = 2*b+4 where b is water retention parameter 77 | 78 | # Tree 79 | 80 | VEGTYPE_tree: 2 # Integer value to infer Vegetation Type 81 | intercept_cap_tree: 2. # Full canopy interception capacity (mm) 82 | zr_tree: 1.3 # Root depth (m) 83 | I_B_tree: 20. # Infiltration capacity of bare soil (mm/h) 84 | I_V_tree: 40. # Infiltration capacity of vegetated soil (mm/h) 85 | pc_tree: 0.43 # Soil porosity (None) 86 | fc_tree: 0.56 # Soil saturation degree at field capacity (None) 87 | sc_tree: 0.22 # Soil saturation degree at stomatal closure (None) 88 | wp_tree: 0.15 # Soil saturation degree at wilting point (None) 89 | hgw_tree: 0.1 # Soil saturation degree at hygroscopic point (None) 90 | beta_tree: 13.8 # Deep percolation constant = 2*b+4 where b is water retention parameter 91 | 92 | # Bare Soil 93 | 94 | VEGTYPE_bare: 3 # Integer value to infer Vegetation Type 95 | intercept_cap_bare: 1. # Full canopy interception capacity (mm) 96 | zr_bare: 0.15 # Root depth (m) 97 | I_B_bare: 20. # Infiltration capacity of bare soil (mm/h) 98 | I_V_bare: 20. # Infiltration capacity of vegetated soil (mm/h) 99 | pc_bare: 0.43 # Soil porosity (None) 100 | fc_bare: 0.56 # Soil saturation degree at field capacity (None) 101 | sc_bare: 0.33 # Soil saturation degree at stomatal closure (None) 102 | wp_bare: 0.13 # Soil saturation degree at wilting point (None) 103 | hgw_bare: 0.1 # Soil saturation degree at hygroscopic point (None) 104 | beta_bare: 13.8 # Deep percolation constant 105 | 106 | 107 | ## Vegetation Dynamics: 108 | 109 | Blive_init: 102. 110 | Bdead_init: 450. 111 | PET_growth_threshold: 3.8 # PET threshold for growing season (mm/d) 112 | PET_dormancy_threshold: 6.8 # PET threshold for dormant season (mm/d) 113 | Tdmax: 10. # Constant for dead biomass loss adjustment (mm/d) 114 | w: 0.55 # Conversion factor of CO2 to dry biomass (Kg DM/Kg CO2) 115 | 116 | # Grass 117 | 118 | WUE_grass: 0.01 # Water use efficiency KgCO2Kg-1H2O 119 | cb_grass: 0.0047 # Specific leaf area for green/live biomass (m2 leaf g-1 DM) 120 | cd_grass: 0.009 # Specific leaf area for dead biomass (m2 leaf g-1 DM) 121 | ksg_grass: 0.012 # Senescence coefficient of green/live biomass (d-1) 122 | kdd_grass: 0.013 # Decay coefficient of aboveground dead biomass (d-1) 123 | kws_grass: 0.02 # Maximum drought induced foliage loss rate (d-1) 124 | LAI_max_grass: 2. # Maximum leaf area index (m2/m2) 125 | LAIR_max_grass: 2.88 # Reference leaf area index (m2/m2) 126 | 127 | # Shrub 128 | 129 | WUE_shrub: 0.0025 # Water use efficiency KgCO2Kg-1H2O 130 | cb_shrub: 0.004 # Specific leaf area for green/live biomass (m2 leaf g-1 DM) 131 | cd_shrub: 0.01 # Specific leaf area for dead biomass (m2 leaf g-1 DM) 132 | ksg_shrub: 0.002 # Senescence coefficient of green/live biomass (d-1) 133 | kdd_shrub: 0.013 # Decay coefficient of aboveground dead biomass (d-1) 134 | kws_shrub: 0.02 # Maximum drought induced foliage loss rate (d-1) 135 | LAI_max_shrub: 2. # Maximum leaf area index (m2/m2) 136 | LAIR_max_shrub: 2. # Reference leaf area index (m2/m2) 137 | 138 | # Tree 139 | 140 | WUE_tree: 0.0045 # Water use efficiency KgCO2Kg-1H2O 141 | cb_tree: 0.004 # Specific leaf area for green/live biomass (m2 leaf g-1 DM) 142 | cd_tree: 0.01 # Specific leaf area for dead biomass (m2 leaf g-1 DM) 143 | ksg_tree: 0.002 # Senescence coefficient of green/live biomass (d-1) 144 | kdd_tree: 0.013 # Decay coefficient of aboveground dead biomass (d-1) 145 | kws_tree: 0.01 # Maximum drought induced foliage loss rate (d-1) 146 | LAI_max_tree: 4. # Maximum leaf area index (m2/m2) 147 | LAIR_max_tree: 4. # Reference leaf area index (m2/m2) 148 | 149 | # Bare 150 | 151 | WUE_bare: 0.01 # Water use efficiency KgCO2Kg-1H2O 152 | cb_bare: 0.0047 # Specific leaf area for green/live biomass (m2 leaf g-1 DM) 153 | cd_bare: 0.009 # Specific leaf area for dead biomass (m2 leaf g-1 DM) 154 | ksg_bare: 0.012 # Senescence coefficient of green/live biomass (d-1) 155 | kdd_bare: 0.013 # Decay coefficient of aboveground dead biomass (d-1) 156 | kws_bare: 0.02 # Maximum drought induced foliage loss rate (d-1) 157 | LAI_max_bare: 0.01 # Maximum leaf area index (m2/m2) 158 | LAIR_max_bare: 0.01 # Reference leaf area index (m2/m2) 159 | 160 | 161 | ## Cellular Automaton Vegetation: 162 | 163 | # Grass 164 | 165 | Pemaxg: 0.35 # Maximal establishment probability 166 | ING: 2 # Parameter to define allelopathic effect on grass from cresotebush 167 | ThetaGrass: 0.62 # Drought resistant threshold 168 | PmbGrass: 0.05 # Background mortality probability 169 | 170 | # Shrub 171 | 172 | Pemaxsh: 0.2 # Maximal establishment probability 173 | ThetaShrub: 0.78 # Drought resistant threshold 174 | PmbShrub: 0.03 # Background mortality probability 175 | tpmaxShrub: 600 # Maximum age (yr) 176 | 177 | # Tree 178 | 179 | Pemaxtr: 0.25 # Maximal establishment probability 180 | ThetaTree: 0.72 # Drought resistant threshold 181 | PmbTree: 0.01 # Background mortality probability 182 | tpmaxTree: 350 # Maximum age (yr) 183 | 184 | # ShrubSeedling 185 | 186 | ThetaShrubSeedling: 0.64 # Drought resistant threshold 187 | PmbShrubSeedling: 0.03 # Background mortality probability 188 | tpmaxShrubSeedling: 18 # Maximum age (yr) 189 | 190 | # TreeSeedling 191 | 192 | ThetaTreeSeedling: 0.64 # Drought resistant threshold 193 | PmbTreeSeedling: 0.03 # Background mortality probability 194 | tpmaxTreeSeedling: 18 # Maximum age (yr) 195 | -------------------------------------------------------------------------------- /component_drivers/cellular_automata/cts_lattice_gas.py: -------------------------------------------------------------------------------- 1 | #!/usr/env/python 2 | """ 3 | cts_lattice_gas.py: continuous-time stochastic version of a lattice-gas cellular 4 | automaton model. 5 | 6 | GT Sep 2014 7 | """ 8 | from __future__ import print_function 9 | 10 | _DEBUG = False 11 | 12 | import time 13 | import random 14 | from numpy import zeros, bincount, arange 15 | from pylab import subplots, plot, show, xlabel, ylabel, title, axis 16 | from landlab import HexModelGrid 17 | from landlab.components.cellular_automata.celllab_cts import Transition, CAPlotter 18 | from landlab.components.cellular_automata.oriented_hex_cts import OrientedHexCTS 19 | 20 | 21 | def setup_transition_list(): 22 | """ 23 | Creates and returns a list of Transition() objects to represent state 24 | transitions for simple granular mechanics model. 25 | 26 | Parameters 27 | ---------- 28 | (none) 29 | 30 | Returns 31 | ------- 32 | xn_list : list of Transition objects 33 | List of objects that encode information about the link-state transitions. 34 | """ 35 | xn_list = [] 36 | 37 | # Transitions for particle movement into an empty cell 38 | xn_list.append( Transition((1,0,0), (0,1,0), 1., 'motion') ) 39 | xn_list.append( Transition((2,0,1), (0,2,1), 1., 'motion') ) 40 | xn_list.append( Transition((3,0,2), (0,3,2), 1., 'motion') ) 41 | xn_list.append( Transition((0,4,0), (4,0,0), 1., 'motion') ) 42 | xn_list.append( Transition((0,5,1), (5,0,1), 1., 'motion') ) 43 | xn_list.append( Transition((0,6,2), (6,0,2), 1., 'motion') ) 44 | 45 | # Transitions for wall impact 46 | xn_list.append( Transition((1,8,0), (4,8,0), 1.0, 'wall rebound') ) 47 | xn_list.append( Transition((2,8,1), (5,8,1), 1.0, 'wall rebound') ) 48 | xn_list.append( Transition((3,8,2), (6,8,2), 1.0, 'wall rebound') ) 49 | xn_list.append( Transition((8,4,0), (8,1,0), 1.0, 'wall rebound') ) 50 | xn_list.append( Transition((8,5,1), (8,2,1), 1.0, 'wall rebound') ) 51 | xn_list.append( Transition((8,6,2), (8,3,2), 1.0, 'wall rebound') ) 52 | 53 | # Transitions for head-on collision 54 | xn_list.append( Transition((1,4,0), (3,6,0), 0.5, 'head-on collision') ) 55 | xn_list.append( Transition((1,4,0), (5,2,0), 0.5, 'head-on collision') ) 56 | xn_list.append( Transition((2,5,1), (4,1,1), 0.5, 'head-on collision') ) 57 | xn_list.append( Transition((2,5,1), (6,3,1), 0.5, 'head-on collision') ) 58 | xn_list.append( Transition((3,6,2), (1,4,2), 0.5, 'head-on collision') ) 59 | xn_list.append( Transition((3,6,2), (5,2,2), 0.5, 'head-on collision') ) 60 | 61 | # Transitions for glancing collision 62 | xn_list.append( Transition((1,3,0), (3,1,0), 1.0, 'glancing collision') ) 63 | xn_list.append( Transition((1,5,0), (5,1,0), 1.0, 'glancing collision') ) 64 | xn_list.append( Transition((2,4,0), (4,2,0), 1.0, 'glancing collision') ) 65 | xn_list.append( Transition((6,4,0), (4,6,0), 1.0, 'glancing collision') ) 66 | xn_list.append( Transition((2,4,1), (4,2,1), 1.0, 'glancing collision') ) 67 | xn_list.append( Transition((2,6,1), (6,2,1), 1.0, 'glancing collision') ) 68 | xn_list.append( Transition((1,5,1), (5,1,1), 1.0, 'glancing collision') ) 69 | xn_list.append( Transition((3,5,1), (5,3,1), 1.0, 'glancing collision') ) 70 | xn_list.append( Transition((3,1,2), (1,3,2), 1.0, 'glancing collision') ) 71 | xn_list.append( Transition((3,5,2), (5,3,2), 1.0, 'glancing collision') ) 72 | xn_list.append( Transition((2,6,2), (6,2,2), 1.0, 'glancing collision') ) 73 | xn_list.append( Transition((4,6,2), (6,4,2), 1.0, 'glancing collision') ) 74 | 75 | # Transitions for oblique-from-behind collisions 76 | xn_list.append( Transition((1,2,0), (2,1,0), 1.0, 'oblique') ) 77 | xn_list.append( Transition((1,6,0), (6,1,0), 1.0, 'oblique') ) 78 | xn_list.append( Transition((3,4,0), (4,3,0), 1.0, 'oblique') ) 79 | xn_list.append( Transition((5,4,0), (4,5,0), 1.0, 'oblique') ) 80 | xn_list.append( Transition((2,1,1), (1,2,1), 1.0, 'oblique') ) 81 | xn_list.append( Transition((2,3,1), (3,2,1), 1.0, 'oblique') ) 82 | xn_list.append( Transition((4,5,1), (5,4,1), 1.0, 'oblique') ) 83 | xn_list.append( Transition((6,5,1), (5,6,1), 1.0, 'oblique') ) 84 | xn_list.append( Transition((3,2,2), (2,3,2), 1.0, 'oblique') ) 85 | xn_list.append( Transition((3,4,2), (4,3,2), 1.0, 'oblique') ) 86 | xn_list.append( Transition((1,6,2), (6,1,2), 1.0, 'oblique') ) 87 | xn_list.append( Transition((5,6,2), (6,5,2), 1.0, 'oblique') ) 88 | 89 | # Transitions for direct-from-behind collisions 90 | xn_list.append( Transition((1,1,0), (2,6,0), 0.5, 'behind') ) 91 | xn_list.append( Transition((1,1,0), (6,2,0), 0.5, 'behind') ) 92 | xn_list.append( Transition((4,4,0), (3,5,0), 0.5, 'behind') ) 93 | xn_list.append( Transition((4,4,0), (5,3,0), 0.5, 'behind') ) 94 | xn_list.append( Transition((2,2,1), (1,3,1), 0.5, 'behind') ) 95 | xn_list.append( Transition((2,2,1), (3,1,1), 0.5, 'behind') ) 96 | xn_list.append( Transition((5,5,1), (4,6,1), 0.5, 'behind') ) 97 | xn_list.append( Transition((5,5,1), (6,4,1), 0.5, 'behind') ) 98 | xn_list.append( Transition((3,3,2), (2,4,2), 0.5, 'behind') ) 99 | xn_list.append( Transition((3,3,2), (4,2,2), 0.5, 'behind') ) 100 | xn_list.append( Transition((6,6,2), (1,5,2), 0.5, 'behind') ) 101 | xn_list.append( Transition((6,6,2), (5,1,2), 0.5, 'behind') ) 102 | 103 | # Transitions for collision with stationary (resting) particle 104 | xn_list.append( Transition((1,7,0), (7,2,0), 0.5, 'rest') ) 105 | xn_list.append( Transition((1,7,0), (7,6,0), 0.5, 'rest') ) 106 | xn_list.append( Transition((7,4,0), (3,7,0), 0.5, 'rest') ) 107 | xn_list.append( Transition((7,4,0), (5,7,0), 0.5, 'rest') ) 108 | xn_list.append( Transition((2,7,1), (7,1,1), 0.5, 'rest') ) 109 | xn_list.append( Transition((2,7,1), (7,3,1), 0.5, 'rest') ) 110 | xn_list.append( Transition((7,5,1), (4,7,1), 0.5, 'rest') ) 111 | xn_list.append( Transition((7,5,1), (6,7,1), 0.5, 'rest') ) 112 | xn_list.append( Transition((3,7,2), (7,2,2), 0.5, 'rest') ) 113 | xn_list.append( Transition((3,7,2), (7,4,2), 0.5, 'rest') ) 114 | xn_list.append( Transition((7,6,2), (1,7,2), 0.5, 'rest') ) 115 | xn_list.append( Transition((7,6,2), (5,7,2), 0.5, 'rest') ) 116 | 117 | if _DEBUG: 118 | print() 119 | print('setup_transition_list(): list has',len(xn_list),'transitions:') 120 | for t in xn_list: 121 | print(' From state',t.from_state,'to state',t.to_state,'at rate',t.rate,'called',t.name) 122 | 123 | return xn_list 124 | 125 | 126 | def main(): 127 | 128 | # INITIALIZE 129 | 130 | # User-defined parameters 131 | nr = 41 132 | nc = 61 133 | plot_interval = 1.0 134 | run_duration = 100.0 135 | report_interval = 5.0 # report interval, in real-time seconds 136 | p_init = 0.1 # probability that a cell is occupied at start 137 | plot_every_transition = False 138 | 139 | # Remember the clock time, and calculate when we next want to report 140 | # progress. 141 | current_real_time = time.time() 142 | next_report = current_real_time + report_interval 143 | 144 | # Create a grid 145 | hmg = HexModelGrid(nr, nc, 1.0, orientation='vertical', reorient_links=True) 146 | 147 | # Close the grid boundaries 148 | #hmg.set_closed_nodes(hmg.open_boundary_nodes) 149 | 150 | # Set up the states and pair transitions. 151 | # Transition data here represent particles moving on a lattice: one state 152 | # per direction (for 6 directions), plus an empty state, a stationary 153 | # state, and a wall state. 154 | ns_dict = { 0 : 'empty', 155 | 1 : 'moving up', 156 | 2 : 'moving right and up', 157 | 3 : 'moving right and down', 158 | 4 : 'moving down', 159 | 5 : 'moving left and down', 160 | 6 : 'moving left and up', 161 | 7 : 'rest', 162 | 8 : 'wall'} 163 | xn_list = setup_transition_list() 164 | 165 | # Create data and initialize values. 166 | node_state_grid = hmg.add_zeros('node', 'node_state_grid', dtype=int) 167 | 168 | # Make the grid boundary all wall particles 169 | node_state_grid[hmg.boundary_nodes] = 8 170 | 171 | # Seed the grid interior with randomly oriented particles 172 | for i in hmg.core_nodes: 173 | if random.random()= next_report: 197 | print('Current sim time',current_time,'(',100*current_time/run_duration,'%)') 198 | next_report = current_real_time + report_interval 199 | 200 | # Run the model forward in time until the next output step 201 | ca.run(current_time+plot_interval, ca.node_state, 202 | plot_each_transition=plot_every_transition, plotter=ca_plotter) 203 | current_time += plot_interval 204 | 205 | # Plot the current grid 206 | ca_plotter.update_plot() 207 | 208 | # Record numbers in each state 209 | nstates[:,k] = bincount(node_state_grid) 210 | k += 1 211 | 212 | # FINALIZE 213 | 214 | # Plot 215 | ca_plotter.finalize() 216 | 217 | # Display the numbers of each state 218 | fig, ax = subplots() 219 | for i in range(1, 8): 220 | plot(arange(plot_interval, run_duration+plot_interval, plot_interval), nstates[i,:], label=ns_dict[i]) 221 | ax.legend() 222 | xlabel('Time') 223 | ylabel('Number of particles in state') 224 | title('Particle distribution by state') 225 | axis([0, run_duration, 0, 2*nstates[7,0]]) 226 | show() 227 | 228 | 229 | if __name__=='__main__': 230 | main() 231 | -------------------------------------------------------------------------------- /component_drivers/cellular_automata/cts_lattice_gas_with_gravity.py: -------------------------------------------------------------------------------- 1 | #!/usr/env/python 2 | """ 3 | cts_lattice_gas_with_gravity.py: 4 | continuous-time stochastic version of a lattice-gas cellular 5 | automaton model. 6 | 7 | GT Sep 2014 8 | """ 9 | from __future__ import print_function 10 | 11 | _DEBUG = False 12 | 13 | import time 14 | import random 15 | from landlab import HexModelGrid 16 | from landlab.components.cellular_automata.celllab_cts import Transition, CAPlotter 17 | from landlab.components.cellular_automata.oriented_hex_cts import OrientedHexCTS 18 | 19 | 20 | def setup_transition_list(g=1.0): 21 | """ 22 | Creates and returns a list of Transition() objects to represent state 23 | transitions for simple granular mechanics model. 24 | 25 | Parameters 26 | ---------- 27 | (none) 28 | 29 | Returns 30 | ------- 31 | xn_list : list of Transition objects 32 | List of objects that encode information about the link-state transitions. 33 | """ 34 | xn_list = [] 35 | 36 | # Transitions for particle movement into an empty cell 37 | xn_list.append( Transition((1,0,0), (0,1,0), 1., 'motion') ) 38 | xn_list.append( Transition((2,0,1), (0,2,1), 1., 'motion') ) 39 | xn_list.append( Transition((3,0,2), (0,3,2), 1., 'motion') ) 40 | xn_list.append( Transition((0,4,0), (4,0,0), 1., 'motion') ) 41 | xn_list.append( Transition((0,5,1), (5,0,1), 1., 'motion') ) 42 | xn_list.append( Transition((0,6,2), (6,0,2), 1., 'motion') ) 43 | 44 | # Transitions for wall impact 45 | xn_list.append( Transition((1,8,0), (4,8,0), 1.0, 'wall rebound') ) 46 | xn_list.append( Transition((2,8,1), (5,8,1), 1.0, 'wall rebound') ) 47 | xn_list.append( Transition((3,8,2), (6,8,2), 1.0, 'wall rebound') ) 48 | xn_list.append( Transition((8,4,0), (8,1,0), 1.0, 'wall rebound') ) 49 | xn_list.append( Transition((8,5,1), (8,2,1), 1.0, 'wall rebound') ) 50 | xn_list.append( Transition((8,6,2), (8,3,2), 1.0, 'wall rebound') ) 51 | 52 | # Transitions for head-on collision 53 | xn_list.append( Transition((1,4,0), (3,6,0), 0.5, 'head-on collision') ) 54 | xn_list.append( Transition((1,4,0), (5,2,0), 0.5, 'head-on collision') ) 55 | xn_list.append( Transition((2,5,1), (4,1,1), 0.5, 'head-on collision') ) 56 | xn_list.append( Transition((2,5,1), (6,3,1), 0.5, 'head-on collision') ) 57 | xn_list.append( Transition((3,6,2), (1,4,2), 0.5, 'head-on collision') ) 58 | xn_list.append( Transition((3,6,2), (5,2,2), 0.5, 'head-on collision') ) 59 | 60 | # Transitions for glancing collision 61 | xn_list.append( Transition((1,3,0), (3,1,0), 1.0, 'glancing collision') ) 62 | xn_list.append( Transition((1,5,0), (5,1,0), 1.0, 'glancing collision') ) 63 | xn_list.append( Transition((2,4,0), (4,2,0), 1.0, 'glancing collision') ) 64 | xn_list.append( Transition((6,4,0), (4,6,0), 1.0, 'glancing collision') ) 65 | xn_list.append( Transition((2,4,1), (4,2,1), 1.0, 'glancing collision') ) 66 | xn_list.append( Transition((2,6,1), (6,2,1), 1.0, 'glancing collision') ) 67 | xn_list.append( Transition((1,5,1), (5,1,1), 1.0, 'glancing collision') ) 68 | xn_list.append( Transition((3,5,1), (5,3,1), 1.0, 'glancing collision') ) 69 | xn_list.append( Transition((3,1,2), (1,3,2), 1.0, 'glancing collision') ) 70 | xn_list.append( Transition((3,5,2), (5,3,2), 1.0, 'glancing collision') ) 71 | xn_list.append( Transition((2,6,2), (6,2,2), 1.0, 'glancing collision') ) 72 | xn_list.append( Transition((4,6,2), (6,4,2), 1.0, 'glancing collision') ) 73 | 74 | # Transitions for oblique-from-behind collisions 75 | xn_list.append( Transition((1,2,0), (2,1,0), 1.0, 'oblique') ) 76 | xn_list.append( Transition((1,6,0), (6,1,0), 1.0, 'oblique') ) 77 | xn_list.append( Transition((3,4,0), (4,3,0), 1.0, 'oblique') ) 78 | xn_list.append( Transition((5,4,0), (4,5,0), 1.0, 'oblique') ) 79 | xn_list.append( Transition((2,1,1), (1,2,1), 1.0, 'oblique') ) 80 | xn_list.append( Transition((2,3,1), (3,2,1), 1.0, 'oblique') ) 81 | xn_list.append( Transition((4,5,1), (5,4,1), 1.0, 'oblique') ) 82 | xn_list.append( Transition((6,5,1), (5,6,1), 1.0, 'oblique') ) 83 | xn_list.append( Transition((3,2,2), (2,3,2), 1.0, 'oblique') ) 84 | xn_list.append( Transition((3,4,2), (4,3,2), 1.0, 'oblique') ) 85 | xn_list.append( Transition((1,6,2), (6,1,2), 1.0, 'oblique') ) 86 | xn_list.append( Transition((5,6,2), (6,5,2), 1.0, 'oblique') ) 87 | 88 | # Transitions for direct-from-behind collisions 89 | xn_list.append( Transition((1,1,0), (2,6,0), 0.5, 'behind') ) 90 | xn_list.append( Transition((1,1,0), (6,2,0), 0.5, 'behind') ) 91 | xn_list.append( Transition((4,4,0), (3,5,0), 0.5, 'behind') ) 92 | xn_list.append( Transition((4,4,0), (5,3,0), 0.5, 'behind') ) 93 | xn_list.append( Transition((2,2,1), (1,3,1), 0.5, 'behind') ) 94 | xn_list.append( Transition((2,2,1), (3,1,1), 0.5, 'behind') ) 95 | xn_list.append( Transition((5,5,1), (4,6,1), 0.5, 'behind') ) 96 | xn_list.append( Transition((5,5,1), (6,4,1), 0.5, 'behind') ) 97 | xn_list.append( Transition((3,3,2), (2,4,2), 0.5, 'behind') ) 98 | xn_list.append( Transition((3,3,2), (4,2,2), 0.5, 'behind') ) 99 | xn_list.append( Transition((6,6,2), (1,5,2), 0.5, 'behind') ) 100 | xn_list.append( Transition((6,6,2), (5,1,2), 0.5, 'behind') ) 101 | 102 | # Transitions for collision with stationary (resting) particle 103 | xn_list.append( Transition((1,7,0), (7,2,0), 0.5, 'rest') ) 104 | xn_list.append( Transition((1,7,0), (7,6,0), 0.5, 'rest') ) 105 | xn_list.append( Transition((7,4,0), (3,7,0), 0.5, 'rest') ) 106 | xn_list.append( Transition((7,4,0), (5,7,0), 0.5, 'rest') ) 107 | xn_list.append( Transition((2,7,1), (7,1,1), 0.5, 'rest') ) 108 | xn_list.append( Transition((2,7,1), (7,3,1), 0.5, 'rest') ) 109 | xn_list.append( Transition((7,5,1), (4,7,1), 0.5, 'rest') ) 110 | xn_list.append( Transition((7,5,1), (6,7,1), 0.5, 'rest') ) 111 | xn_list.append( Transition((3,7,2), (7,2,2), 0.5, 'rest') ) 112 | xn_list.append( Transition((3,7,2), (7,4,2), 0.5, 'rest') ) 113 | xn_list.append( Transition((7,6,2), (1,7,2), 0.5, 'rest') ) 114 | xn_list.append( Transition((7,6,2), (5,7,2), 0.5, 'rest') ) 115 | 116 | # Gravity rules 117 | xn_list.append( Transition((1,0,0), (7,0,0), g, 'up to rest') ) 118 | xn_list.append( Transition((1,1,0), (7,1,0), g, 'up to rest') ) 119 | xn_list.append( Transition((1,2,0), (7,2,0), g, 'up to rest') ) 120 | xn_list.append( Transition((1,3,0), (7,3,0), g, 'up to rest') ) 121 | xn_list.append( Transition((1,4,0), (7,4,0), g, 'up to rest') ) 122 | xn_list.append( Transition((1,5,0), (7,5,0), g, 'up to rest') ) 123 | xn_list.append( Transition((1,6,0), (7,6,0), g, 'up to rest') ) 124 | xn_list.append( Transition((1,7,0), (7,7,0), g, 'up to rest') ) 125 | xn_list.append( Transition((0,1,0), (0,7,0), g, 'up to rest') ) 126 | xn_list.append( Transition((1,1,0), (1,7,0), g, 'up to rest') ) 127 | xn_list.append( Transition((2,1,0), (2,7,0), g, 'up to rest') ) 128 | xn_list.append( Transition((3,1,0), (3,7,0), g, 'up to rest') ) 129 | xn_list.append( Transition((4,1,0), (4,7,0), g, 'up to rest') ) 130 | xn_list.append( Transition((5,1,0), (5,7,0), g, 'up to rest') ) 131 | xn_list.append( Transition((6,1,0), (6,7,0), g, 'up to rest') ) 132 | xn_list.append( Transition((7,1,0), (7,7,0), g, 'up to rest') ) 133 | 134 | xn_list.append( Transition((7,0,0), (4,0,0), g, 'rest to down') ) 135 | xn_list.append( Transition((7,1,0), (4,1,0), g, 'rest to down') ) 136 | xn_list.append( Transition((7,2,0), (4,2,0), g, 'rest to down') ) 137 | xn_list.append( Transition((7,3,0), (4,3,0), g, 'rest to down') ) 138 | xn_list.append( Transition((7,4,0), (4,4,0), g, 'rest to down') ) 139 | xn_list.append( Transition((7,5,0), (4,5,0), g, 'rest to down') ) 140 | xn_list.append( Transition((7,6,0), (4,6,0), g, 'rest to down') ) 141 | xn_list.append( Transition((7,7,0), (4,7,0), g, 'rest to down') ) 142 | xn_list.append( Transition((0,7,0), (0,4,0), g, 'rest to down') ) 143 | xn_list.append( Transition((1,7,0), (1,4,0), g, 'rest to down') ) 144 | xn_list.append( Transition((2,7,0), (2,4,0), g, 'rest to down') ) 145 | xn_list.append( Transition((3,7,0), (3,4,0), g, 'rest to down') ) 146 | xn_list.append( Transition((4,7,0), (4,4,0), g, 'rest to down') ) 147 | xn_list.append( Transition((5,7,0), (5,4,0), g, 'rest to down') ) 148 | xn_list.append( Transition((6,7,0), (6,4,0), g, 'rest to down') ) 149 | xn_list.append( Transition((7,7,0), (7,4,0), g, 'rest to down') ) 150 | 151 | xn_list.append( Transition((2,0,1), (3,0,1), g, 'right up to right down') ) 152 | xn_list.append( Transition((2,1,1), (3,1,1), g, 'right up to right down') ) 153 | xn_list.append( Transition((2,2,1), (3,2,1), g, 'right up to right down') ) 154 | xn_list.append( Transition((2,3,1), (3,3,1), g, 'right up to right down') ) 155 | xn_list.append( Transition((2,4,1), (3,4,1), g, 'right up to right down') ) 156 | xn_list.append( Transition((2,5,1), (3,5,1), g, 'right up to right down') ) 157 | xn_list.append( Transition((2,6,1), (3,6,1), g, 'right up to right down') ) 158 | xn_list.append( Transition((2,7,1), (3,7,1), g, 'right up to right down') ) 159 | xn_list.append( Transition((0,2,1), (0,3,1), g, 'right up to right down') ) 160 | xn_list.append( Transition((1,2,1), (1,3,1), g, 'right up to right down') ) 161 | xn_list.append( Transition((2,2,1), (2,3,1), g, 'right up to right down') ) 162 | xn_list.append( Transition((3,2,1), (3,3,1), g, 'right up to right down') ) 163 | xn_list.append( Transition((4,2,1), (4,3,1), g, 'right up to right down') ) 164 | xn_list.append( Transition((5,2,1), (5,3,1), g, 'right up to right down') ) 165 | xn_list.append( Transition((6,2,1), (6,3,1), g, 'right up to right down') ) 166 | xn_list.append( Transition((7,2,1), (7,3,1), g, 'right up to right down') ) 167 | 168 | xn_list.append( Transition((6,0,2), (5,0,2), g, 'left up to left down') ) 169 | xn_list.append( Transition((6,1,2), (5,1,2), g, 'left up to left down') ) 170 | xn_list.append( Transition((6,2,2), (5,2,2), g, 'left up to left down') ) 171 | xn_list.append( Transition((6,3,2), (5,3,2), g, 'left up to left down') ) 172 | xn_list.append( Transition((6,4,2), (5,4,2), g, 'left up to left down') ) 173 | xn_list.append( Transition((6,5,2), (5,5,2), g, 'left up to left down') ) 174 | xn_list.append( Transition((6,6,2), (5,6,2), g, 'left up to left down') ) 175 | xn_list.append( Transition((6,7,2), (5,7,2), g, 'left up to left down') ) 176 | xn_list.append( Transition((0,6,2), (0,5,2), g, 'left up to left down') ) 177 | xn_list.append( Transition((1,6,2), (1,5,2), g, 'left up to left down') ) 178 | xn_list.append( Transition((2,6,2), (2,5,2), g, 'left up to left down') ) 179 | xn_list.append( Transition((3,6,2), (3,5,2), g, 'left up to left down') ) 180 | xn_list.append( Transition((4,6,2), (4,5,2), g, 'left up to left down') ) 181 | xn_list.append( Transition((5,6,2), (5,5,2), g, 'left up to left down') ) 182 | xn_list.append( Transition((6,6,2), (6,5,2), g, 'left up to left down') ) 183 | xn_list.append( Transition((7,6,2), (7,5,2), g, 'left up to left down') ) 184 | 185 | if _DEBUG: 186 | print() 187 | print('setup_transition_list(): list has',len(xn_list),'transitions:') 188 | for t in xn_list: 189 | print(' From state',t.from_state,'to state',t.to_state,'at rate',t.rate,'called',t.name) 190 | 191 | return xn_list 192 | 193 | 194 | def main(): 195 | 196 | # INITIALIZE 197 | 198 | # User-defined parameters 199 | nr = 41 200 | nc = 61 201 | g = 0.05 202 | plot_interval = 1.0 203 | run_duration = 100.0 204 | report_interval = 5.0 # report interval, in real-time seconds 205 | p_init = 0.1 # probability that a cell is occupied at start 206 | plot_every_transition = False 207 | 208 | # Remember the clock time, and calculate when we next want to report 209 | # progress. 210 | current_real_time = time.time() 211 | next_report = current_real_time + report_interval 212 | 213 | # Create a grid 214 | hmg = HexModelGrid(nr, nc, 1.0, orientation='vertical', reorient_links=True) 215 | 216 | # Close the grid boundaries 217 | #hmg.set_closed_nodes(hmg.open_boundary_nodes) 218 | 219 | # Set up the states and pair transitions. 220 | # Transition data here represent particles moving on a lattice: one state 221 | # per direction (for 6 directions), plus an empty state, a stationary 222 | # state, and a wall state. 223 | ns_dict = { 0 : 'empty', 224 | 1 : 'moving up', 225 | 2 : 'moving right and up', 226 | 3 : 'moving right and down', 227 | 4 : 'moving down', 228 | 5 : 'moving left and down', 229 | 6 : 'moving left and up', 230 | 7 : 'rest', 231 | 8 : 'wall'} 232 | xn_list = setup_transition_list(g) 233 | 234 | # Create data and initialize values. 235 | node_state_grid = hmg.add_zeros('node', 'node_state_grid') 236 | 237 | # Make the grid boundary all wall particles 238 | node_state_grid[hmg.boundary_nodes] = 8 239 | 240 | # Seed the grid interior with randomly oriented particles 241 | for i in hmg.core_nodes: 242 | if random.random()= next_report: 262 | print('Current sim time',current_time,'(',100*current_time/run_duration,'%)') 263 | next_report = current_real_time + report_interval 264 | 265 | # Run the model forward in time until the next output step 266 | ca.run(current_time+plot_interval, ca.node_state, 267 | plot_each_transition=plot_every_transition, plotter=ca_plotter) 268 | current_time += plot_interval 269 | 270 | # Plot the current grid 271 | ca_plotter.update_plot() 272 | 273 | 274 | # FINALIZE 275 | 276 | # Plot 277 | ca_plotter.finalize() 278 | 279 | 280 | if __name__=='__main__': 281 | main() 282 | -------------------------------------------------------------------------------- /component_drivers/flow_routing/west_bijou_gully.asc: -------------------------------------------------------------------------------- 1 | ncols 43 2 | nrows 89 3 | xllcorner 559705.000000000000 4 | yllcorner 4380220.000000000000 5 | cellsize 3 6 | NODATA_value 0 7 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1725.327880859375 1725.3796657986110858 1725.4326307508681566 1725.4298638237846717 0 0 0 0 0 0 0 0 0 0 0 0 0 10 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1725.1664360894096717 1725.1727701822917425 1725.215576171875 1725.1695285373264142 1725.1681722005207575 1725.1734483506943434 1725.1377360026042425 1725.1137017144096717 1725.1219211154514142 1725.1885579427082575 1725.2088351779514142 0 0 0 0 0 0 0 0 0 0 0 0 0 11 | 0 0 0 0 0 0 0 0 0 0 0 1724.9294162326389142 1724.9854871961806566 1725.0215250651042425 1724.9936794704860858 1724.9440782335068434 1724.958740234375 1724.9488389756943434 1724.9932454427082575 1724.9902750651042425 1724.9135199652778283 1724.9725070529514142 1724.9480794270832575 1724.9366455078125 1724.9648844401042425 1724.9749620225693434 1724.9956868489582575 1725.0102674696181566 1725.0416395399306566 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 | 0 0 0 1724.9108344184028283 1724.8993733723957575 1724.9203016493056566 1724.9041205512153283 1724.8005913628471717 1724.8034261067707575 1724.8104654947917425 1724.8192138671875 1724.7483588324653283 1724.7342393663193434 1724.7847764756943434 1724.7853054470485858 1724.7525906032985858 1724.7488471137153283 1724.7973090277778283 1724.8196072048610858 1724.8692762586806566 1724.8685438368056566 1724.8877631293403283 1724.888916015625 1724.9320203993056566 1724.96484375 1724.9940049913193434 1725.0080023871528283 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 | 0 0 0 0 1724.7576904296875 1724.740966796875 1724.7379014756943434 1724.6211615668403283 1724.643310546875 1724.6748318142360858 1724.6609564887153283 1724.6252170138889142 1724.6266276041667425 1724.6512179904514142 1724.6937662760417425 1724.7205810546875 1724.7455647786457575 1724.7714165581596717 1724.7921006944443434 1724.8413764105903283 1724.8824055989582575 1724.8994411892360858 1724.9225124782985858 1724.9560275607639142 1724.9703233506943434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 | 0 0 0 0 1724.65380859375 1724.6312120225693434 1724.6107584635417425 1724.586669921875 1724.5927327473957575 1724.6016845703125 1724.6134575737846717 1724.6299506293403283 1724.6279839409721717 1724.6713731553818434 1724.6994900173610858 1724.7123345269096717 1724.7406277126735858 1724.7704671223957575 1724.8231201171875 1724.8500298394096717 1724.8778347439235858 1724.9214138454860858 1724.9571397569443434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 | 0 0 0 0 1724.6637369791667425 1724.6770155164931566 1724.6376817491318434 1724.6252034505207575 1724.6275227864582575 1724.6267768012153283 1724.6091172960068434 1724.6401638454860858 1724.6434326171875 1724.6646185980903283 1724.6895751953125 1724.712890625 1724.7542453342014142 1724.7705891927082575 1724.8131781684028283 1724.8583984375 1724.8923746744792425 1724.9347330729167425 1724.9653862847221717 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 | 0 0 0 0 1724.6991644965278283 1724.7009141710068434 1724.6662326388889142 1724.6500108506943434 1724.6143798828125 1724.6034342447917425 1724.6157362196181566 1724.6296251085068434 1724.6313340928818434 1724.6609564887153283 1724.6898600260417425 1724.7357855902778283 1724.7693413628471717 1724.7863633897568434 1724.7959526909721717 1724.8228624131943434 1724.8474934895832575 1724.8468424479167425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 17 | 0 0 0 0 0 1724.6874050564235858 1724.6629909939235858 1724.6446261935764142 1724.6225992838542425 1724.6322699652778283 1724.6204155815971717 1724.6361219618056566 1724.6530083550346717 1724.6782497829860858 1724.6928982204860858 1724.7342936197917425 1724.7264268663193434 1724.7134195963542425 1724.6945393880207575 1724.6967909071181566 1724.7123345269096717 1724.7411973741318434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 | 0 0 0 0 0 1724.6845974392360858 1724.66455078125 1724.6757541232639142 1724.6500651041667425 1724.6506754557292425 1724.6376410590278283 1724.6262071397568434 1724.615478515625 1724.5947943793403283 1724.5804578993056566 1724.5861680772568434 1724.594970703125 1724.5918375651042425 1724.5899115668403283 1724.5802815755207575 1724.5925971137153283 1724.6141628689235858 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 | 0 0 0 0 0 0 0 0 0 1724.6344265407985858 1724.6142442491318434 1724.5864800347221717 1724.5442030164931566 1724.4873046875 1724.3771701388889142 1724.3724365234375 1724.4303249782985858 1724.4863145616318434 1724.4732394748264142 1724.4560004340278283 1724.4438747829860858 1724.4478081597221717 1724.4714219835068434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 | 0 0 0 0 0 0 0 0 0 0 1724.5794542100693434 1724.5664876302082575 1724.4817572699653283 1724.3051350911457575 1723.9934895833332575 1723.8614637586806566 1724.1145833333332575 1724.2222357855903283 1724.2690836588542425 1724.2164849175346717 1724.2049018012153283 1724.247802734375 1724.2692735460068434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 | 0 0 0 0 0 0 0 0 0 0 1724.5185411241318434 1724.4838324652778283 1724.3662109375 1723.9183892144096717 1723.2799207899306566 1723.2913411458332575 1723.6253933376735858 1723.7467447916667425 1723.8695339626735858 1723.8842502170139142 1723.924560546875 1724.0401340060764142 1724.1198187934028283 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 | 0 0 0 0 0 0 0 0 0 0 1724.4550374348957575 1724.4258490668403283 1724.1976996527778283 1723.5954047309028283 1722.5508355034721717 1722.448486328125 1722.9941134982639142 1723.0316297743056566 1723.3699951171875 1723.4041476779514142 1723.6048990885417425 1723.8713921440971717 1723.9734429253471717 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23 | 0 0 0 0 0 0 0 0 0 0 1724.3397623697917425 1724.3039822048610858 1724.0161946614582575 1723.2945149739582575 1721.908447265625 1721.5245632595485858 1721.8724229600693434 1722.0199245876735858 1722.6533881293403283 1722.5182156032985858 1723.1644422743056566 1723.62939453125 1723.8130832248264142 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 | 0 0 0 0 0 0 0 0 0 0 1724.2105441623264142 1724.1339518229167425 1723.8480631510417425 1723.1540256076389142 1721.5650092230903283 1720.6193712022568434 1720.5929633246528283 1721.008056640625 1721.7361246744792425 1721.6935628255207575 1722.7528483072917425 1723.2023654513889142 1723.4574652777778283 1723.5338134765625 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 | 0 0 0 0 0 0 0 0 0 0 1724.0035264756943434 1723.8485921223957575 1723.5982394748264142 1722.9389512803818434 1721.3691813151042425 1720.2937689887153283 1719.9842800564235858 1720.2165798611110858 1720.6435275607639142 1721.1689588758681566 1722.1593017578125 1722.560302734375 1722.8619113498264142 1723.0050455729167425 1722.9528944227431566 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 | 0 0 0 0 0 0 0 0 0 0 1723.7515055338542425 1723.4979654947917425 1723.2133246527778283 1722.6841091579860858 1721.4326443142360858 1720.1888292100693434 1719.5903455946181566 1719.5604654947917425 1719.8655056423610858 1720.3567843967014142 1721.1360677083332575 1721.6462809244792425 1722.2388102213542425 1722.4430881076389142 1722.4413655598957575 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 | 0 0 0 0 0 0 0 0 0 0 1723.4055718315971717 1723.2036946614582575 1722.8151584201389142 1722.2238633897568434 1721.3134223090278283 1720.32373046875 1719.2827419704860858 1719.1546495225693434 1719.3154296875 1719.5720079210068434 1720.0170491536457575 1720.6550428602431566 1721.5587565104167425 1721.8858235677082575 1721.9624565972221717 1721.8906928168403283 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 | 0 0 0 0 0 0 0 0 0 0 1723.0595567491318434 1722.9231092664931566 1722.4589165581596717 1721.6538357204860858 1720.7524142795139142 1720.0796440972221717 1719.0667046440971717 1718.6754828559028283 1718.799072265625 1718.9571533203125 1719.3939615885417425 1720.0376112196181566 1720.9454752604167425 1721.2995741102431566 1721.4987386067707575 1721.4379611545139142 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 | 0 0 0 0 0 0 0 0 0 0 1722.7090793185764142 1722.6402587890625 1722.1329752604167425 1721.3496636284721717 1720.5191107855903283 1719.6287977430556566 1718.8032497829860858 1717.9062364366318434 1718.0196533203125 1718.4168836805556566 1719.0705837673610858 1719.7451985677082575 1720.3676079644096717 1720.6446940104167425 1720.8958333333332575 1720.8971354166667425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 | 0 0 0 0 0 0 0 0 0 0 1722.2454833984375 1722.2427571614582575 1721.7591959635417425 1721.0527750651042425 1720.3543023003471717 1719.3641899956596717 1718.2753634982639142 1716.8658582899306566 1716.9353434244792425 1717.9583197699653283 1718.8154161241318434 1719.3369683159721717 1719.7926432291667425 1719.947998046875 1720.2853325737846717 1720.4128824869792425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 | 0 0 0 0 0 0 0 0 0 0 1721.7824435763889142 1721.7554524739582575 1721.3704020182292425 1720.5371500651042425 1719.7842475043403283 1718.6368815104167425 1717.4453803168403283 1716.1234809027778283 1715.9847954644096717 1716.9427083333332575 1717.6509195963542425 1718.2186279296875 1718.7170545789931566 1719.22021484375 1719.6755913628471717 1719.9052598741318434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 | 0 0 0 0 0 0 0 0 0 0 1721.4228515625 1721.2625596788193434 1720.8514268663193434 1720.0603976779514142 1718.98828125 1717.6429985894096717 1716.4921196831596717 1715.5383707682292425 1715.1554497612846717 1715.9425862630207575 1716.3478054470485858 1716.8336452907985858 1717.3730604383681566 1718.1935221354167425 1718.9506429036457575 1719.2177734375 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 33 | 0 0 0 0 0 0 0 0 0 0 1721.2725694444443434 1720.9745686848957575 1720.2786322699653283 1719.2612711588542425 1718.1032443576389142 1716.7450493706596717 1715.7544487847221717 1714.9114990234375 1714.3142225477431566 1714.8424479166667425 1715.1625162760417425 1715.6611735026042425 1716.1859402126735858 1716.8865966796875 1717.8937581380207575 1718.4811604817707575 1718.6801893446181566 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34 | 0 0 0 0 0 0 0 0 0 0 1721.0031195746528283 1720.5629204644096717 1719.6596137152778283 1718.5925971137153283 1717.2508951822917425 1716.0653211805556566 1715.1530626085068434 1714.3822157118056566 1713.7011990017360858 1713.4847276475693434 1714.0871446397568434 1714.547607421875 1715.2330593532985858 1715.9049343532985858 1716.7040879991318434 1717.4824490017360858 1718.0035400390625 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 35 | 0 0 0 0 0 0 0 0 0 0 1720.4812418619792425 1719.9135064019096717 1718.9418809678818434 1717.7739393446181566 1716.5005832248264142 1715.4380560980903283 1714.5751681857639142 1713.8063015407985858 1713.1425645616318434 1712.4737141927082575 1713.0088026258681566 1713.1607530381943434 1713.8041720920139142 1714.7550591362846717 1715.6854654947917425 1716.2811008029514142 1716.9241807725693434 1717.0500895182292425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 | 0 0 0 0 0 0 0 0 0 0 1720.0945773654514142 1719.2906087239582575 1718.1848551432292425 1716.9702555338542425 1715.9063991970485858 1714.9222547743056566 1713.8907741970485858 1713.3168131510417425 1712.6304931640625 1711.8365614149306566 1711.9180094401042425 1712.0348307291667425 1712.3902723524306566 1713.4413519965278283 1714.5630425347221717 1715.3038872612846717 1715.9070909288193434 1716.0565999348957575 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 37 | 0 0 0 0 0 0 0 0 0 0 1719.8331027560764142 1719.0099419487846717 1717.5961235894096717 1716.3779296875 1715.4490559895832575 1714.3029242621528283 1713.2950575086806566 1712.8182779947917425 1712.1448160807292425 1711.4169108072917425 1710.6785074869792425 1710.4125027126735858 1710.9724527994792425 1712.0271267361110858 1713.3980305989582575 1714.30224609375 1714.6754286024306566 1714.8848876953125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 38 | 0 0 0 0 0 0 0 0 0 0 1719.4056532118056566 1718.5609944661457575 1717.2272271050346717 1716.0296223958332575 1714.9414469401042425 1713.6992458767360858 1712.8857014973957575 1712.2865939670139142 1711.7068277994792425 1711.0296359592014142 1710.2366265190971717 1709.1111653645832575 1709.0472276475693434 1710.4793836805556566 1712.0504150390625 1713.0401611328125 1713.6486138237846717 1713.9726426866318434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 | 0 0 0 0 0 0 0 0 0 0 1718.8013916015625 1718.0917154947917425 1716.9509955512153283 1715.7340087890625 1714.5799696180556566 1713.4619818793403283 1712.6126437717014142 1711.9916585286457575 1711.2398410373264142 1710.5976698133681566 1709.8963487413193434 1708.8565945095485858 1707.8693169487846717 1709.0721164279514142 1710.5419379340278283 1711.8994140625 1712.6829698350693434 1713.0132107204860858 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 | 0 0 0 0 0 0 0 0 0 0 0 1717.4628634982639142 1716.5958387586806566 1715.5449490017360858 1714.3208143446181566 1713.2874077690971717 1712.40576171875 1711.5517171223957575 1710.56103515625 1709.8899603949653283 1708.9705674913193434 1707.9748128255207575 1706.9321560329860858 1707.8479410807292425 1709.2332763671875 1710.7737630208332575 1711.610107421875 1712.0199924045139142 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 | 0 0 0 0 0 0 0 0 0 0 0 1716.5718858506943434 1715.907470703125 1715.08740234375 1714.0081515842014142 1712.9883083767360858 1712.0071343315971717 1710.8733181423610858 1709.8178846571181566 1708.9723036024306566 1708.1259358723957575 1707.1204020182292425 1706.0155707465278283 1706.6439751519096717 1708.2647705078125 1709.6626654730903283 1710.2530381944443434 1710.9777967664931566 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 | 0 0 0 0 0 0 0 0 0 0 0 0 1715.0561116536457575 1714.3817003038193434 1713.4635145399306566 1712.5172390407985858 1711.4142659505207575 1710.2290717230903283 1709.2598605685764142 1708.4725884331596717 1707.4701199001735858 1706.3752577039931566 1705.2900797526042425 1705.4552951388889142 1707.2010904947917425 1708.2975531684028283 1709.1338026258681566 1709.9591878255207575 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 | 0 0 0 0 0 0 0 0 0 0 0 0 1714.1806233723957575 1713.6025390625 1712.7591010199653283 1711.8837483723957575 1710.8291829427082575 1709.6530490451389142 1708.7497829861110858 1707.9746907552082575 1707.1103922526042425 1705.8567030164931566 1704.5051947699653283 1704.3737114800346717 1705.8925509982639142 1707.3014729817707575 1708.4352891710068434 1709.0553249782985858 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 | 0 0 0 0 0 0 0 0 0 0 0 0 0 1712.7054172092014142 1711.9420166015625 1711.1392008463542425 1710.3253038194443434 1709.3257378472221717 1708.3008626302082575 1707.4716389973957575 1706.5391981336806566 1705.2779269748264142 1703.8847520616318434 1703.5160861545139142 1704.9329427083332575 1706.7179497612846717 1707.8617214626735858 1708.2633734809028283 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 | 0 0 0 0 0 0 0 0 0 0 0 0 0 1711.7397867838542425 1711.1797010633681566 1710.4414333767360858 1709.6114230685764142 1708.8521999782985858 1707.8282606336806566 1706.9011094835068434 1705.9296332465278283 1704.6424967447917425 1703.2015380859375 1702.8967692057292425 1704.5143364800346717 1706.2320692274306566 1707.2439643012153283 1707.754150390625 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 46 | 0 0 0 0 0 0 0 0 0 0 0 0 0 1710.9453260633681566 1710.5184733072917425 1709.6636013454860858 1708.9400092230903283 1708.2615424262153283 1707.3226996527778283 1706.4162055121528283 1705.4792344835068434 1704.0521104600693434 1702.6683349609375 1702.1893039279514142 1703.6816813151042425 1705.1247016059028283 1706.3945990668403283 1707.4703640407985858 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 | 0 0 0 0 0 0 0 0 0 0 0 0 0 1710.19677734375 1709.7902289496528283 1709.1159532335068434 1708.4556206597221717 1707.6989474826389142 1706.8100992838542425 1705.8601752387153283 1704.8273383246528283 1703.5316162109375 1702.0192464192707575 1701.4881049262153283 1702.5916612413193434 1704.0558403862846717 1705.7550998263889142 1706.6457248263889142 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1709.2462293836806566 1708.7106391059028283 1708.0661349826389142 1707.1905653211806566 1706.3565673828125 1705.2787000868056566 1704.2097846137153283 1703.0242377387153283 1701.5547417534721717 1700.9225124782985858 1701.8450385199653283 1703.6017388237846717 1705.2251383463542425 1705.8055284288193434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 49 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1708.5633273654514142 1708.1765950520832575 1707.5593397352431566 1706.6377224392360858 1705.5782335069443434 1704.5905490451389142 1703.6009657118056566 1702.1191541883681566 1700.8752170138889142 1700.3285997178818434 1701.5285373263889142 1703.234375 1704.7396918402778283 1705.1233995225693434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1707.7525363498264142 1707.4918891059028283 1706.8551974826389142 1706.018310546875 1704.9135470920139142 1703.8472086588542425 1702.8601888020832575 1701.4645724826389142 1700.0899929470485858 1699.9150254991318434 1701.2681884765625 1702.8164605034721717 1704.1192626953125 1704.3783637152778283 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1706.9817572699653283 1706.7670627170139142 1706.1201578776042425 1705.2107069227431566 1704.2768690321181566 1703.1937798394096717 1702.3689100477431566 1701.2779947916667425 1699.7960340711806566 1699.3758680555556566 1700.5330403645832575 1702.1791585286457575 1703.3574490017360858 1703.4670952690971717 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 52 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1706.3554009331596717 1706.0933295355903283 1705.5389946831596717 1704.5030246310764142 1703.6185167100693434 1702.5752766927082575 1701.63525390625 1700.7506646050346717 1699.3755425347221717 1698.9113362630207575 1700.0447862413193434 1701.6923014322917425 1702.5039469401042425 1702.7008327907985858 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 53 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1705.7840711805556566 1705.5123291015625 1705.0748155381943434 1704.1380886501735858 1703.0619574652778283 1701.9446343315971717 1700.7975124782985858 1699.6540798611110858 1698.6469590928818434 1698.6181504991318434 1699.653076171875 1701.0964898003471717 1701.9044596354167425 1702.0099283854167425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1705.16162109375 1704.9552544487846717 1704.7228597005207575 1704.0487196180556566 1702.9350314670139142 1701.7044406467014142 1700.3276909722221717 1698.7464192708332575 1697.9560682508681566 1698.459716796875 1699.591796875 1700.9696316189235858 1701.3356255425346717 1701.3186442057292425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 55 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1704.5198432074653283 1704.1465386284721717 1704.0650770399306566 1703.6644829644096717 1702.7474229600693434 1701.2846544053818434 1699.4936794704860858 1698.0910101996528283 1697.4894748263889142 1698.2613661024306566 1699.7705620659721717 1700.8624810112846717 1700.6375325520832575 1700.6408555772568434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 56 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1704.0888943142360858 1703.5688205295139142 1703.3792317708332575 1703.34716796875 1702.4720052083332575 1700.7524142795139142 1698.9142659505207575 1697.7548014322917425 1697.2244601779514142 1697.8592393663193434 1699.0421278211806566 1700.2887776692707575 1700.1658528645832575 1700.1132676866318434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1702.8607720269096717 1702.9217393663193434 1702.3077256944443434 1700.8331705729167425 1698.88916015625 1697.6215006510417425 1696.8874782986110858 1697.1137152777778283 1698.0837266710068434 1699.4532335069443434 1699.4284803602431566 1699.55517578125 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1702.2784830729167425 1701.9506700303818434 1700.8743082682292425 1698.9923366970485858 1697.4398193359375 1696.62646484375 1696.6144883897568434 1697.626220703125 1698.6334906684028283 1698.3102620442707575 1698.9097222222221717 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1701.5534261067707575 1700.3925645616318434 1698.437255859375 1696.9653727213542425 1696.2904866536457575 1696.1731499565971717 1696.5682644314235858 1697.0301106770832575 1697.2556966145832575 1698.4644232855903283 1698.5563286675346717 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1701.2017144097221717 1700.4589029947917425 1698.6928032769096717 1697.0513509114582575 1696.0424533420139142 1695.6423882378471717 1695.5541178385417425 1695.7568630642360858 1696.8571912977431566 1697.9033745659721717 1698.2731526692707575 0 0 0 0 0 0 0 0 0 0 0 0 0 0 61 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1700.443115234375 1699.4595675998264142 1697.9677327473957575 1696.6608344184028283 1695.3149685329860858 1695.1410319010417425 1695.238037109375 1695.7620578342014142 1696.8738742404514142 1697.7728814019096717 1697.6554090711806566 0 0 0 0 0 0 0 0 0 0 0 0 0 62 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1700.1007351345485858 1699.5104844835068434 1698.6266954210068434 1697.2621934678818434 1695.5772026909721717 1694.7674153645832575 1694.7152099609375 1694.8738335503471717 1695.7092963324653283 1696.9045545789931566 1697.1845838758681566 1697.2279866536457575 0 0 0 0 0 0 0 0 0 0 0 0 63 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1699.7836507161457575 1699.3254123263889142 1698.5239122178818434 1697.2740207248264142 1695.7722981770832575 1694.4321153428818434 1694.2405734592014142 1694.3496365017360858 1695.0180257161457575 1696.2320285373264142 1696.5437147352431566 1696.8875732421875 0 0 0 0 0 0 0 0 0 0 0 0 64 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1699.3751491970485858 1699.1637098524306566 1698.6000298394096717 1697.3208957248264142 1695.5687255859375 1694.0984022352431566 1693.9825168185764142 1693.9430745442707575 1694.5095621744792425 1695.4391276041667425 1695.6144748263889142 1696.4530978732639142 1696.6286892361110858 0 0 0 0 0 0 0 0 0 0 0 65 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1698.9237331814235858 1698.4304470486110858 1697.2316080729167425 1695.1554633246528283 1693.8280571831596717 1693.7030843098957575 1693.5836317274306566 1693.723388671875 1694.1901719835068434 1694.4262017144096717 1695.6616889105903283 1696.2007378472221717 0 0 0 0 0 0 0 0 0 0 0 66 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1698.6138780381943434 1698.2380642361110858 1697.4486490885417425 1695.4631076388889142 1693.6867811414931566 1693.3930257161457575 1693.3082953559028283 1693.1921793619792425 1693.3468017578125 1693.6610921223957575 1694.51806640625 1695.4678955078125 1695.8051486545139142 0 0 0 0 0 0 0 0 0 0 67 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1698.2888454861110858 1697.8732503255207575 1697.0044759114582575 1695.2225884331596717 1693.5362955729167425 1693.0967339409721717 1692.9549153645832575 1692.9225667317707575 1692.8997395833332575 1693.0844319661457575 1693.7205946180556566 1694.4670003255207575 1695.0801323784721717 0 0 0 0 0 0 0 0 0 0 68 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1697.6702338324653283 1696.5976426866318434 1694.9422878689235858 1693.5306667751735858 1692.8388400607639142 1692.6274956597221717 1692.5518934461806566 1692.5071478949653283 1692.6162380642360858 1693.0322401258681566 1693.5346950954860858 1694.5177001953125 0 0 0 0 0 0 0 0 0 0 69 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1697.3702256944443434 1696.6799858940971717 1695.2829047309028283 1693.7834201388889142 1692.7346598307292425 1692.3958740234375 1692.1973198784721717 1692.1389024522568434 1692.1649576822917425 1692.3592529296875 1692.7770046657985858 1693.8050401475693434 0 0 0 0 0 0 0 0 0 0 70 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1696.7704806857639142 1695.8088514539931566 1694.2267659505207575 1692.931640625 1692.0875922309028283 1691.6842719184028283 1691.6820203993056566 1691.7095675998264142 1691.7905951605903283 1692.0048285590278283 1692.7119818793403283 1693.45556640625 0 0 0 0 0 0 0 0 0 71 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1696.5431722005207575 1696.2789306640625 1695.3225640190971717 1693.5539957682292425 1692.0462103949653283 1690.3745930989582575 1690.4183078342014142 1691.0443793402778283 1691.1913384331596717 1691.0456949869792425 1691.1929660373264142 1692.3657497829860858 0 0 0 0 0 0 0 0 0 72 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1696.2253689236110858 1695.8186848958332575 1694.1161566840278283 1692.4212782118056566 1690.1856960720485858 1688.7996826171875 1689.0563693576389142 1689.8946533203125 1690.2475450303818434 1690.3601616753471717 1690.8602430555556566 0 0 0 0 0 0 0 0 0 73 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1695.8826497395832575 1694.4805636935764142 1692.9233262803818434 1690.9331868489582575 1688.5021701388889142 1687.0550672743056566 1687.8854437934028283 1689.0975884331596717 1689.7725016276042425 1689.8442789713542425 0 0 0 0 0 0 0 0 0 74 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1695.7979329427082575 1694.9156087239582575 1693.7088216145832575 1692.0029703776042425 1689.6083170572917425 1687.397705078125 1686.4125840928818434 1687.7562798394096717 1688.6048583984375 1689.1580810546875 1689.0781114366318434 0 0 0 0 0 0 0 0 75 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1695.5347222222221717 1694.8674723307292425 1693.6110704210068434 1691.9372829861110858 1689.9446072048610858 1687.9744601779514142 1686.0688612196181566 1685.8537462022568434 1686.7009548611110858 1688.1842041015625 1688.6637912326389142 0 0 0 0 0 0 0 0 76 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1694.6692979600693434 1694.2921006944443434 1693.2130262586806566 1691.8417561848957575 1690.0952012803818434 1688.6193440755207575 1687.0364040798610858 1685.5988633897568434 1685.3848198784721717 1687.0279676649306566 1688.2724745008681566 0 0 0 0 0 0 0 0 77 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1693.6574164496528283 1692.8848470052082575 1691.6687147352431566 1690.4942355685764142 1689.3889702690971717 1688.2326524522568434 1686.0978597005207575 1684.8136800130207575 1686.1381157769096717 1687.8999565972221717 0 0 0 0 0 0 0 0 78 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1692.6839463975693434 1691.8258463541667425 1690.8307020399306566 1689.98095703125 1688.5146484375 1686.5322536892360858 1684.5194091796875 1685.5528157552082575 1687.5737575954860858 1687.6481119791667425 0 0 0 0 0 0 0 79 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1692.0260552300346717 1691.5570610894096717 1690.7380642361110858 1688.8936631944443434 1686.7040744357639142 1684.5474310980903283 1684.4905598958332575 1686.7299126519096717 1687.3989122178818434 1687.1919487847221717 0 0 0 0 0 0 80 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1691.5058729383681566 1691.0706244574653283 1689.4648980034721717 1686.9405110677082575 1684.7039116753471717 1683.7988688151042425 1685.0236545138889142 1686.3155517578125 1686.6791178385417425 1686.7975938585068434 0 0 0 0 0 81 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1691.2808702256943434 1690.9715169270832575 1689.8931206597221717 1687.3805202907985858 1684.9350721571181566 1683.5683322482639142 1683.5365261501735858 1684.3345404730903283 1685.0164523654514142 1686.2761908637153283 0 0 0 0 0 82 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1690.8021782769096717 1689.8979627821181566 1687.7268744574653283 1685.3213161892360858 1683.4559597439235858 1683.0840793185764142 1682.9517550998264142 1683.4820827907985858 1685.3744981553818434 0 0 0 0 0 83 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1690.5067816840278283 1690.0622016059028283 1688.4264865451389142 1685.9880642361110858 1683.8839111328125 1682.8961046006943434 1682.6816270616318434 1682.7320827907985858 1684.3772650824653283 1685.3087700737846717 0 0 0 0 84 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1690.0673692491318434 1689.0286865234375 1686.9899224175346717 1684.9485541449653283 1683.1221381293403283 1682.4302978515625 1682.3260633680556566 1683.1706814236110858 1684.4051242404514142 0 0 0 0 85 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1689.9119330512153283 1689.4986572265625 1688.1433241102431566 1686.2119276258681566 1684.031005859375 1682.4030490451389142 1681.9775119357639142 1682.4678955078125 1683.8755696614582575 0 0 0 0 86 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1689.4774848090278283 1688.7395697699653283 1687.3233506944443434 1684.8388400607639142 1682.6728651258681566 1681.7469211154514142 1681.8909640842014142 1683.0718722873264142 0 0 0 0 87 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1688.8149820963542425 1687.5709771050346717 1685.1551784939235858 1682.8880208333332575 1681.5922987196181566 1681.4881049262153283 1682.1737603081596717 0 0 0 0 88 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1681.1861572265625 1681.40625 0 0 0 0 89 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1680.7793918185764142 0 0 0 0 90 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 92 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 93 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 94 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 95 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 | --------------------------------------------------------------------------------