def test_deAlm_analytical():
    from landlab import RasterModelGrid
    grid = RasterModelGrid((32, 240), spacing = 25)
    grid.add_zeros('node', 'surface_water__depth')
    grid.add_zeros('node', 'topographic__elevation')
    grid.set_closed_boundaries_at_grid_edges(True, True, True, True)
    left_inactive_ids = left_edge_horizontal_ids(grid.shape)
    deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001)
    time = 0.0

    while time < 500.:
        grid['link']['surface_water__discharge'][left_inactive_ids] = (
            grid['link']['surface_water__discharge'][left_inactive_ids + 1])
        dt = deAlm.calc_time_step()
        deAlm.overland_flow(dt)
        h_boundary = (((7./3.) * (0.01**2) * (0.4**3) *
                      time) ** (3./7.))
        grid.at_node['surface_water__depth'][grid.nodes[1: -1, 1]] = h_boundary
        time += dt

    x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx)
    h_analytical = (-(7./3.) * (0.01**2) * (0.4**2) * (x - (0.4 * 500)))

    h_analytical[np.where(h_analytical > 0)] = (h_analytical[np.where(
        h_analytical > 0)] ** (3./7.))
    h_analytical[np.where(h_analytical < 0)] = 0.0

    hdeAlm = deAlm.h.reshape(grid.shape)
    hdeAlm = hdeAlm[1][1:]
    hdeAlm = np.append(hdeAlm, [0])
    np.testing.assert_almost_equal(h_analytical, hdeAlm, decimal=1)
Example #2
0
def test_deAlm_analytical_imposed_dt_short():
    grid = RasterModelGrid((32, 240), xy_spacing=25)
    grid.add_zeros("surface_water__depth", at="node")
    grid.add_zeros("topographic__elevation", at="node")
    grid.set_closed_boundaries_at_grid_edges(True, True, True, True)
    left_inactive_ids = _left_edge_horizontal_ids(grid.shape)
    deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001)
    time = 0.0

    while time < 500.0:
        grid.at_link["surface_water__discharge"][
            left_inactive_ids] = grid.at_link["surface_water__discharge"][
                left_inactive_ids + 1]
        dt = 10.0
        deAlm.overland_flow(dt)
        h_boundary = ((7.0 / 3.0) * (0.01**2) * (0.4**3) * time)**(3.0 / 7.0)
        grid.at_node["surface_water__depth"][grid.nodes[1:-1, 1]] = h_boundary
        time += dt

    x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx)
    h_analytical = -(7.0 / 3.0) * (0.01**2) * (0.4**2) * (x - (0.4 * 500))

    h_analytical[np.where(h_analytical > 0)] = h_analytical[np.where(
        h_analytical > 0)]**(3.0 / 7.0)
    h_analytical[np.where(h_analytical < 0)] = 0.0

    hdeAlm = deAlm.h.reshape(grid.shape)
    hdeAlm = hdeAlm[1][1:]
    hdeAlm = np.append(hdeAlm, [0])
    np.testing.assert_almost_equal(h_analytical, hdeAlm, decimal=1)
def test_deAlm_analytical():
    from landlab import RasterModelGrid
    grid = RasterModelGrid((32, 240), spacing=25)
    grid.add_zeros('node', 'water__depth')
    grid.add_zeros('node', 'topographic__elevation')
    grid.set_closed_boundaries_at_grid_edges(True, True, True, True)
    left_inactive_ids = left_edge_horizontal_ids(grid.shape)
    deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001)
    time = 0.0

    while time < 500:
        grid['link']['water__discharge'][left_inactive_ids] = (
            grid['link']['water__discharge'][left_inactive_ids + 1])
        dt = deAlm.calc_time_step()
        deAlm.overland_flow(dt)
        h_boundary = (((7. / 3.) * (0.01**2) * (0.4**3) * time)**(3. / 7.))
        grid.at_node['water__depth'][grid.nodes[1:-1, 1]] = h_boundary
        time += dt

    x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx)
    h_analytical = (-(7. / 3.) * (0.01**2) * (0.4**2) * (x - (0.4 * 500)))

    h_analytical[np.where(h_analytical > 0)] = (h_analytical[np.where(
        h_analytical > 0)]**(3. / 7.))
    h_analytical[np.where(h_analytical < 0)] = 0.0

    hdeAlm = deAlm.h.reshape(grid.shape)
    hdeAlm = hdeAlm[1][1:]
    hdeAlm = np.append(hdeAlm, [0])
    np.testing.assert_almost_equal(h_analytical, hdeAlm, decimal=1)
def test_deAlm_analytical_imposed_dt_short():
    grid = RasterModelGrid((32, 240), xy_spacing=25)
    grid.add_zeros("node", "surface_water__depth")
    grid.add_zeros("node", "topographic__elevation")
    grid.set_closed_boundaries_at_grid_edges(True, True, True, True)
    left_inactive_ids = left_edge_horizontal_ids(grid.shape)
    deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001)
    time = 0.0

    while time < 500.0:
        grid.at_link["surface_water__discharge"][left_inactive_ids] = grid.at_link[
            "surface_water__discharge"
        ][left_inactive_ids + 1]
        dt = 10.0
        deAlm.overland_flow(dt)
        h_boundary = ((7.0 / 3.0) * (0.01 ** 2) * (0.4 ** 3) * time) ** (3.0 / 7.0)
        grid.at_node["surface_water__depth"][grid.nodes[1:-1, 1]] = h_boundary
        time += dt

    x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx)
    h_analytical = -(7.0 / 3.0) * (0.01 ** 2) * (0.4 ** 2) * (x - (0.4 * 500))

    h_analytical[np.where(h_analytical > 0)] = h_analytical[
        np.where(h_analytical > 0)
    ] ** (3.0 / 7.0)
    h_analytical[np.where(h_analytical < 0)] = 0.0

    hdeAlm = deAlm.h.reshape(grid.shape)
    hdeAlm = hdeAlm[1][1:]
    hdeAlm = np.append(hdeAlm, [0])
    np.testing.assert_almost_equal(h_analytical, hdeAlm, decimal=1)
# Running the overland flow component.
while elapsed_time < model_run_time:

    # The storm starts when the model starts. While the elapsed time is less
    # than the storm duration, we add water to the system as rainfall.
    if elapsed_time < storm_duration:

        of.rainfall_intensity = 4.07222 * (10**-7)  # Rainfall intensity (m/s)

    # Then the elapsed time exceeds the storm duration, rainfall ceases.
    else:

        of.rainfall_intensity = 0.0

    # Generating overland flow based on the deAlmeida solution.
    of.overland_flow()

    # Append time and discharge to their lists to save data and for plotting.
    hydrograph_time_sec.append(elapsed_time)
    hydrograph_time_hrs.append(round(elapsed_time / 3600., 2))
    discharge_at_outlet.append(of.q[link_to_sample])

    # Add the time step, repeat until elapsed time >= model_run_time
    print(elapsed_time)
    elapsed_time += of.dt

plt.figure(1)
plt.imshow(z.reshape(rmg.shape), origin="left", cmap="pink")
plt.tick_params(axis="both", labelbottom="off", labelleft="off")
cb = plt.colorbar()
cb.set_label("Elevation (m)", rotation=270, labelpad=15)
left_inactive_ids = links.left_edge_horizontal_ids(rmg.shape)

# Let's see how long this run takes...
starttime = time()

while elapsed_time < run_time:

    # Now we are going to set the left edge horizontal links to their
    # neighboring discharge value

    rmg["link"]["surface_water__discharge"][left_inactive_ids] = rmg["link"][
        "surface_water__discharge"
    ][left_inactive_ids + 1]

    # Now, we can generate overland flow.
    of.overland_flow()

    # Recalculate water depth at the boundary ...

    # water depth at left side (m)
    h_boundary = (
        seven_over_three * n * n * u * u * u * elapsed_time
    ) ** three_over_seven

    # And now we input that water depth along the left-most interior column,
    # in all rows that are not boundary rows.
    rmg.at_node["surface_water__depth"][inside_left_edge] = h_boundary

    # Increased elapsed time
    elapsed_time += of.dt
Example #7
0
class FloodWorld(ActiveCellWorld):
    """
    FloodWorld class. This ActiveCellWorld implementation uses Landlab to simulate floods.

    :param world_size:
    :param grid_size:
    :param torus:
    :param agent_dynamic:
    """

    def __init__(self, world_size, grid_size, torus, agent_dynamic):
        super(FloodWorld, self).__init__(world_size, grid_size, torus, agent_dynamic)

        # World generation parameters
        self.vertical_scale = 200  # (m)

        self.inputs = {'nrows': 100, 'ncols': 100, 'dx': 0.02, 'dt': 0.5, 'total_time': 50.0, 'uplift_rate': 0.001,
                       'K_sp': 0.3, 'm_sp': 0.5, 'n_sp': 1.0, 'rock_density': 2.7, 'sed_density': 2.7,
                       'linear_diffusivity': 0.0001}

        # Flood parameters
        self.h_init = 5  # initial thin layer of water (m)
        self.n = 0.01  # roughness coefficient, (s/m^(1/3))
        self.alpha = 0.7  # time-step factor (nondimensional; from Bates et al., 2010)
        self.u = 0.4  # constant velocity (m/s, de Almeida et al., 2012)

        self.cell_update_period = 10  # (s)

        self.mg = None
        self.fr = None
        self.sp = None
        self.of = None
        self.swd = None

        self.z = None
        self.flood_threshold = 0.05  # minimum water depth detected as flood (m)

    def reset(self):
        """
        Reset function. Resets the world to its initial state.
        """

        super(FloodWorld, self).reset()

        # Terrain generation
        shape = (self.grid_size,) * 2
        size = self.grid_size * self.grid_size
        # Set initial simple topography
        z = self.vertical_scale * self.simple_topography(shape)

        # Create raster model if it does not exist
        if self.mg is None:
            self.mg = RasterModelGrid(shape, int(round(self.world_size/self.grid_size)))
            self.mg.set_closed_boundaries_at_grid_edges(True, True, True, True)
            self.z = self.mg.add_field('node', 'topographic__elevation', z)
            self.swd = self.mg.add_zeros('node', 'surface_water__depth')
        else:
            self.mg.at_node['topographic__elevation'] = z
            self.swd[:] = np.zeros(size)

        import matplotlib.pyplot as plt
        plt.figure()
        from landlab.plot import imshow_grid
        imshow_grid(self.mg, 'topographic__elevation',
                    colorbar_label='m')
        plt.draw()

        # Set evolution parameters
        uplift_rate = self.inputs['uplift_rate']
        total_t = self.inputs['total_time']
        dt = self.inputs['dt']

        nt = int(total_t // dt)  # Loops
        uplift_per_step = uplift_rate * dt

        self.fr = FlowAccumulator(self.mg, **self.inputs)
        self.sp = FastscapeEroder(self.mg, **self.inputs)

        # Erode terrain
        for i in range(nt):
            self.fr.run_one_step() # Not time sensitive
            self.sp.run_one_step(dt)
            self.mg.at_node['topographic__elevation'][self.mg.core_nodes] += uplift_per_step  # add the uplift
            if i % 10 == 0:
                print('Erode: Completed loop %d' % i)

        plt.figure()
        imshow_grid(self.mg, 'topographic__elevation',
                    colorbar_label='m')
        plt.draw()
        plt.show()

        # Setup surface water flow
        self.of = OverlandFlow(self.mg, steep_slopes=True, mannings_n=0.01)

        # Setup initial flood
        self.swd[[5050, 5051, 5150, 5151]] += self.h_init
        self.active = np.greater(np.flip(np.reshape(self.swd, shape), axis=0), self.flood_threshold)

    def update_cells(self):
        """
        Update cells function. Updates water level and cell status.
        """

        self.of.overland_flow(dt=self.cell_update_period)
        shape = (self.grid_size,) * 2
        self.active = np.greater(np.flip(np.reshape(self.swd, shape), axis=0), self.flood_threshold)

    @staticmethod
    def noise_octave(shape, f):
        """
        Noise octave function. Generates a noise map.

        :param shape: (array) shape of the map.
        :param f: (float) frequency bounds parameter.
        """

        return te3w_util.fbm(shape, -1, lower=f, upper=(2 * f))

    def simple_topography(self, shape):
        """
        Simple topography function. Generates an elevation map.

        :param shape: (array) shape of the map.
        """

        values = np.zeros(shape)
        for p in range(1, 10):
            a = 2 ** p
            values += np.abs(self.noise_octave(shape, a) - 0.5) / a
        result = (1.0 - te3w_util.normalize(values)) ** 2
        return result