Exemple #1
0
def example_parcels(example_nmg):
    element_id = np.array(
        [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6], dtype=int,
    )  # current link for each parcel

    element_id = np.expand_dims(element_id, axis=1)
    starting_link = np.squeeze(element_id)  # starting link for each parcel

    np.random.seed(0)

    time_arrival_in_link = np.random.rand(
        np.size(element_id), 1
    )  # time of arrival in each link -- larger numbers are younger
    volume = np.ones(np.shape(element_id))  # (m3) the volume of each parcel
    D = 0.05 * np.ones(
        np.shape(element_id)
    )  # (m) the diameter of grains in each parcel
    abrasion_rate = 0.0001 * np.ones(
        np.size(element_id)
    )  # 0 = no abrasion; abrasion rates are positive mass loss coefficients (mass loss / METER)
    active_layer = np.ones(
        np.shape(element_id)
    )  # 1 = active/surface layer; 0 = subsurface layer

    density = 2650 * np.ones(np.size(element_id))  # (kg/m3)

    location_in_link = np.zeros(
        np.shape(element_id)
    )  # [0 1], 0 is upstream end of link, 1 is downstream end

    D[0] = 0.075
    D[5] = 0.0001  # make one of them sand

    volume[2] = 0.3

    time = [0.0]  # probably not the sensible way to do this...

    items = {"grid_element": "link", "element_id": element_id}

    variables = {
        "starting_link": (["item_id"], starting_link),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], density),
        "time_arrival_in_link": (["item_id", "time"], time_arrival_in_link),
        "active_layer": (["item_id", "time"], active_layer),
        "location_in_link": (["item_id", "time"], location_in_link),
        "D": (["item_id", "time"], D),
        "volume": (["item_id", "time"], volume),
    }

    parcels = DataRecord(
        example_nmg,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )
    return parcels
def test_grainsize_active_layer(example_nmg, example_parcels,
                                example_flow_director):
    time = [0.0]  # probably not the sensible way to do this...

    items = {"grid_element": "link", "element_id": np.array([[6], [6]])}

    initial_volume = np.array([[1], [1]])
    abrasion_rate = np.array([0, 0])

    variables = {
        "starting_link": (["item_id"], np.array([6, 6])),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], np.array([2650, 2650])),
        "time_arrival_in_link": (["item_id", "time"], np.array([[0.5], [0]])),
        "active_layer": (["item_id", "time"], np.array([[1], [1]])),
        "location_in_link": (["item_id", "time"], np.array([[0], [0]])),
        "D": (["item_id", "time"], np.array([[0.05], [0.05]])),
        "volume": (["item_id", "time"], initial_volume),
    }

    two_parcels = DataRecord(
        example_nmg,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    timesteps = 8

    example_nmg.at_link["flow_depth"] = (example_nmg.at_link["flow_depth"] * 5
                                         )  # high transport rate

    nst = NetworkSedimentTransporter(
        example_nmg,
        two_parcels,
        example_flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
        active_layer_method="GrainSizeDependent",
        active_layer_d_multiplier=3,
    )

    dt = 60 * 60 * 24  # (seconds) daily timestep

    for t in range(0, (timesteps * dt), dt):
        nst.run_one_step(dt)

    # Active layer thickness should be 3*d_mean
    active_layer_thickness_should_be = 3 * 0.05

    assert_array_almost_equal(active_layer_thickness_should_be,
                              nst._active_layer_thickness[0])
Exemple #3
0
def test_abrasion(example_nmg, example_parcels, example_flow_director):
    time = [0.0]  # probably not the sensible way to do this...

    items = {"grid_element": "link", "element_id": np.array([[6], [6]])}

    initial_volume = np.array([[1], [1]])
    abrasion_rate = np.array([0.0001, 0])

    variables = {
        "starting_link": (["item_id"], np.array([6, 6])),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], np.array([2650, 90000])),
        "time_arrival_in_link": (["item_id", "time"], np.array([[0.5], [0]])),
        "active_layer": (["item_id", "time"], np.array([[1], [1]])),
        "location_in_link": (["item_id", "time"], np.array([[0], [0]])),
        "D": (["item_id", "time"], np.array([[0.05], [0.05]])),
        "volume": (["item_id", "time"], initial_volume),
    }

    two_parcels = DataRecord(
        example_nmg,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    timesteps = 8

    example_nmg.at_link["flow_depth"] = (example_nmg.at_link["flow_depth"] * 5
                                         )  # high transport rate

    nst = NetworkSedimentTransporter(
        example_nmg,
        two_parcels,
        example_flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )

    dt = 60 * 60 * 24  # (seconds) daily timestep

    for t in range(0, (timesteps * dt), dt):
        nst.run_one_step(dt)

    # Parcel volume should decrease according to abrasion rate
    volume_after_transport = np.squeeze(np.transpose(initial_volume)) * np.exp(
        nst._distance_traveled_cumulative * -abrasion_rate)

    assert_array_almost_equal(volume_after_transport,
                              two_parcels.dataset.volume[0:2, -1])
Exemple #4
0
def test_parcel_leaves(example_nmg, example_flow_director):

    example_nmg.at_link["reach_length"] = ([
        10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0
    ], )

    time = [0.0]

    items = {"grid_element": "link", "element_id": np.array([[6]])}

    initial_volume = np.array([[1]])
    abrasion_rate = np.array([0.0001])

    variables = {
        "starting_link": (["item_id"], np.array([6])),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], np.array([2650])),
        "time_arrival_in_link": (["item_id",
                                  "time"], np.array([[0.71518937]])),
        "active_layer": (["item_id", "time"], np.array([[1]])),
        "location_in_link": (["item_id", "time"], np.array([[0]])),
        "D": (["item_id", "time"], np.array([[0.05]])),
        "volume": (["item_id", "time"], initial_volume),
    }

    one_parcel = DataRecord(
        example_nmg,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    timesteps = 10

    example_nmg.at_link["flow_depth"] = example_nmg.at_link["flow_depth"] * 20

    nst = NetworkSedimentTransporter(
        example_nmg,
        one_parcel,
        example_flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )

    dt = 60 * 60 * 24  # (seconds) daily timestep

    # Parcel should exit, then runtime error is raised
    with pytest.raises(RuntimeError):
        for _ in range(timesteps):
            nst.run_one_step(dt)
Exemple #5
0
def test_bad_dummy_init(dmmy):
    grid = RasterModelGrid((3, 3))
    element_id = [0, 0, 0, -9999, 1, 2, 3, 4, 5]
    volumes = [4, 5, 1, 2, 3, 4, 5, 6, 7]
    with pytest.raises(ValueError):
        DataRecord(
            grid,
            dummy_elements={"node": [dmmy]},
            items={
                "grid_element": "node",
                "element_id": np.array(element_id)
            },
            data_vars={"volumes": (["item_id"], np.array(volumes))},
        )
Exemple #6
0
def dr_2dim():
    time = [0.]
    my_items3 = {
        "grid_element": np.array([["node"], ["link"]]),
        "element_id": np.array([[1], [3]]),
    }
    my_data_vars = {
        "mean_elevation": (["time"], [110.]),
        "item_size": (["item_id", "time"], np.array([[0.3], [0.4]])),
    }
    return DataRecord(grid=grid,
                      time=time,
                      items=my_items3,
                      data_vars=my_data_vars)
Exemple #7
0
def dr_2dim():
    time = [0.]
    my_items3 = {
        'grid_element': np.array([['node'], ['link']]),
        'element_id': np.array([[1], [3]])
    }
    my_data_vars = {
        'mean_elevation': (['time'], [110.]),
        'item_size': (['item_id', 'time'], np.array([[0.3], [0.4]]))
    }
    return DataRecord(grid=grid,
                      time=time,
                      items=my_items3,
                      data_vars=my_data_vars)
Exemple #8
0
def test_ok_dummy():
    grid = RasterModelGrid((3, 3))
    element_id = [0, 0, 0, -9999, 1, 2, 3, 4, 5]
    volumes = [4, 5, 1, 2, 3, 4, 5, 6, 7]
    dr = DataRecord(
        grid,
        dummy_elements={
            "link": [9999, 1234, -9999],
            "node": [9999, 1234, -9999]
        },
        items={
            "grid_element": "node",
            "element_id": np.array(element_id)
        },
        data_vars={"volumes": (["item_id"], np.array(volumes))},
    )

    dr.add_item(
        new_item={
            "grid_element": np.array(["node"]),
            "element_id": np.array([9999])
        },
        new_item_spec={"volumes": (["item_id"], [5])},
    )
Exemple #9
0
def dr_nodim():
    return DataRecord(grid=grid)
Exemple #10
0
def dr_item():
    my_items2 = {
        'grid_element': np.array(('node', 'link'), dtype=str),
        'element_id': np.array([1, 3])
    }
    return DataRecord(grid=grid, items=my_items2)
Exemple #11
0
def test_defined_parcel_transport():

    y_of_node = (0, 0, 0, 0)
    x_of_node = (0, 100, 200, 300)
    nodes_at_link = ((0, 1), (1, 2), (2, 3))

    nmg_constant_slope = NetworkModelGrid((y_of_node, x_of_node),
                                          nodes_at_link)

    # add variables to nmg
    nmg_constant_slope.at_node["topographic__elevation"] = [3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_node["bedrock__elevation"] = [3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_link["channel_slope"] = [0.001, 0.001, 0.001]
    nmg_constant_slope.at_link["reach_length"] = [100.0, 100.0, 100.0]  # m
    nmg_constant_slope.at_link["channel_width"] = 15 * np.ones(
        nmg_constant_slope.size("link"))
    nmg_constant_slope.at_link["flow_depth"] = 2 * np.ones(
        nmg_constant_slope.size("link"))

    flow_director = FlowDirectorSteepest(nmg_constant_slope)
    flow_director.run_one_step()

    timesteps = 11

    time = [0.0]

    items = {"grid_element": "link", "element_id": np.array([[0]])}

    initial_volume = np.array([[1]])
    abrasion_rate = np.array([0])

    variables = {
        "starting_link": (["item_id"], np.array([0])),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], np.array([2650])),
        "time_arrival_in_link": (["item_id",
                                  "time"], np.array([[0.71518937]])),
        "active_layer": (["item_id", "time"], np.array([[1]])),
        "location_in_link": (["item_id", "time"], np.array([[0]])),
        "D": (["item_id", "time"], np.array([[0.05]])),
        "volume": (["item_id", "time"], initial_volume),
    }

    one_parcel = DataRecord(
        nmg_constant_slope,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    nst = NetworkSedimentTransporter(
        nmg_constant_slope,
        one_parcel,
        flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )

    dt = 60  # (seconds) 1 min timestep

    distance_traveled = np.arange(0.0, timesteps)
    # distance_traveled = np.arange(0.,timesteps)

    for t in range(0, (timesteps * dt), dt):
        nst.run_one_step(dt)
        distance_traveled[np.int(t / dt)] = nst._distance_traveled_cumulative
    # NEED TO CALCULATE THINGS HERE.
    # Transport distance should match?
    Distance_Traveled_Should_Be = [
        21.61998527,
        43.23997054,
        64.85995581,
        86.47994109,
        108.09992636,
        129.71991163,
        151.3398969,
        172.95988217,
        194.57986744,
        216.19985272,
        237.81983799,
    ]

    assert_array_almost_equal(Distance_Traveled_Should_Be,
                              distance_traveled,
                              decimal=-1)
Exemple #12
0
def methow():
    example_data_dir = ExampleData("io/shapefile", case="methow").base
    shp_file = example_data_dir / "MethowSubBasin.shp"
    points_shapefile = example_data_dir / "MethowSubBasin_Nodes_4.shp"

    grid2 = read_shapefile(
        shp_file,
        points_shapefile=points_shapefile,
        node_fields=["usarea_km2", "Elev_m"],
        link_fields=["usarea_km2", "Length_m"],
        link_field_conversion={
            "usarea_km2": "drainage_area",
            "Slope": "channel_slope",
            "Length_m": "reach_length",
        },
        node_field_conversion={
            "usarea_km2": "drainage_area",
            "Elev_m": "topographic__elevation",
        },
        threshold=0.01,
    )
    grid2.at_node["bedrock__elevation"] = grid2.at_node[
        "topographic__elevation"].copy()
    grid2.at_link["channel_width"] = 1 * np.ones(grid2.number_of_links)
    grid2.at_link["flow_depth"] = 0.5 * np.ones(grid2.number_of_links)

    # element_id is the link on which the parcel begins.
    element_id = np.repeat(np.arange(grid2.number_of_links), 50)
    element_id = np.expand_dims(element_id, axis=1)

    volume = 1 * np.ones(np.shape(element_id))  # (m3)
    active_layer = np.ones(np.shape(element_id))  # 1= active, 0 = inactive
    density = 2650 * np.ones(np.size(element_id))  # (kg/m3)
    abrasion_rate = 0 * np.ones(np.size(element_id))  # (mass loss /m)

    # Lognormal GSD
    medianD = 0.15  # m
    mu = np.log(medianD)
    sigma = np.log(2)  # assume that D84 = sigma*D50
    np.random.seed(0)
    D = np.random.lognormal(
        mu, sigma,
        np.shape(element_id))  # (m) the diameter of grains in each parcel

    time_arrival_in_link = np.random.rand(np.size(element_id), 1)
    location_in_link = np.random.rand(np.size(element_id), 1)

    lithology = ["quartzite"] * np.size(element_id)

    variables = {
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], density),
        "lithology": (["item_id"], lithology),
        "time_arrival_in_link": (["item_id", "time"], time_arrival_in_link),
        "active_layer": (["item_id", "time"], active_layer),
        "location_in_link": (["item_id", "time"], location_in_link),
        "D": (["item_id", "time"], D),
        "volume": (["item_id", "time"], volume),
    }

    items = {"grid_element": "link", "element_id": element_id}

    parcels2 = DataRecord(
        grid2,
        items=items,
        time=[0.0],
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    fd2 = FlowDirectorSteepest(grid2, "topographic__elevation")
    fd2.run_one_step()

    nst2 = NetworkSedimentTransporter(
        grid2,
        parcels2,
        fd2,
        bed_porosity=0.3,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )
    timesteps = 2  # total number of timesteps
    dt = 60 * 60 * 24 * 1  # length of timestep (seconds)
    for t in range(0, (timesteps * dt), dt):
        nst2.run_one_step(dt)

    return nst2
Exemple #13
0
def synthetic():
    y_of_node = (0, 100, 200, 200, 300, 400, 400, 125)
    x_of_node = (0, 0, 100, -50, -100, 50, -150, -100)

    nodes_at_link = ((1, 0), (2, 1), (1, 7), (3, 1), (3, 4), (4, 5), (4, 6))

    grid1 = NetworkModelGrid((y_of_node, x_of_node), nodes_at_link)
    grid1.at_node["topographic__elevation"] = [
        0.0,
        0.08,
        0.25,
        0.15,
        0.25,
        0.4,
        0.8,
        0.8,
    ]
    grid1.at_node["bedrock__elevation"] = [
        0.0, 0.08, 0.25, 0.15, 0.25, 0.4, 0.8, 0.8
    ]
    grid1.at_link["flow_depth"] = 2.5 * np.ones(grid1.number_of_links)
    grid1.at_link["channel_slope"] = np.ones(
        grid1.number_of_links)  # AP ?? Does it get overwritten?? check
    grid1.at_link["reach_length"] = 200 * np.ones(grid1.number_of_links)  # m
    grid1.at_link["channel_width"] = 1 * np.ones(grid1.number_of_links)

    # element_id is the link on which the parcel begins.
    element_id = np.repeat(np.arange(grid1.number_of_links), 30)
    element_id = np.expand_dims(element_id, axis=1)

    volume = 0.05 * np.ones(np.shape(element_id))  # (m3)
    active_layer = np.ones(np.shape(element_id))  # 1= active, 0 = inactive
    density = 2650 * np.ones(np.size(element_id))  # (kg/m3)
    abrasion_rate = 0 * np.ones(np.size(element_id))  # (mass loss /m)

    # Lognormal GSD
    medianD = 0.085  # m
    mu = np.log(medianD)
    sigma = np.log(2)  # assume that D84 = sigma*D50
    np.random.seed(0)
    D = np.random.lognormal(
        mu, sigma,
        np.shape(element_id))  # (m) the diameter of grains in each parcel

    time_arrival_in_link = np.random.rand(np.size(element_id), 1)
    location_in_link = np.random.rand(np.size(element_id), 1)

    lithology = ["quartzite"] * np.size(element_id)

    variables = {
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], density),
        "lithology": (["item_id"], lithology),
        "time_arrival_in_link": (["item_id", "time"], time_arrival_in_link),
        "active_layer": (["item_id", "time"], active_layer),
        "location_in_link": (["item_id", "time"], location_in_link),
        "D": (["item_id", "time"], D),
        "volume": (["item_id", "time"], volume),
    }

    items = {"grid_element": "link", "element_id": element_id}

    parcels1 = DataRecord(
        grid1,
        items=items,
        time=[0.0],
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    fd1 = FlowDirectorSteepest(grid1, "topographic__elevation")
    fd1.run_one_step()

    nst1 = NetworkSedimentTransporter(
        grid1,
        parcels1,
        fd1,
        bed_porosity=0.3,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )
    timesteps = 2  # total number of timesteps
    dt = 60 * 60 * 24 * 1  # length of timestep (seconds)
    for t in range(0, (timesteps * dt), dt):
        nst1.run_one_step(dt)

    return nst1
Exemple #14
0
def dr_item():
    my_items2 = {
        "grid_element": np.array(("node", "link"), dtype=str),
        "element_id": np.array([1, 3]),
    }
    return DataRecord(grid=grid, items=my_items2)
Exemple #15
0
def test_first_in_last_out():
    y_of_node = (0, 0, 0, 0, 0, 0)
    x_of_node = (0, 100, 200, 300, 400, 500)
    nodes_at_link = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5))

    nmg_constant_slope = NetworkModelGrid((y_of_node, x_of_node), nodes_at_link)

    # add variables to nmg
    nmg_constant_slope.at_node["topographic__elevation"] = [
        5.0,
        4.0,
        3.0,
        2.0,
        1.0,
        0.0,
    ]
    nmg_constant_slope.at_node["bedrock__elevation"] = [5.0, 4.0, 3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_link["channel_slope"] = [0.001, 0.001, 0.001, 0.001, 0.001]
    nmg_constant_slope.at_link["flow_depth"] = [1.75, 1.75, 1.75, 1.75, 1.75]
    nmg_constant_slope.at_link["reach_length"] = [
        100.0,
        100.0,
        100.0,
        100.0,
        100.0,
    ]  # m
    nmg_constant_slope.at_link["channel_width"] = 15 * np.ones(
        nmg_constant_slope.size("link")
    )

    flow_director = FlowDirectorSteepest(nmg_constant_slope)
    flow_director.run_one_step()

    timesteps = 20

    time = [0.0]

    element_id = np.zeros(100, dtype=int)
    element_id = np.expand_dims(element_id, axis=1)

    items = {"grid_element": "link", "element_id": element_id}

    abrasion_rate = np.zeros(np.size(element_id))
    initial_volume = np.ones(np.shape(element_id))
    time_arrival_in_link = np.arange(0, 0.1, 0.001)
    time_arrival_in_link = np.expand_dims(time_arrival_in_link, axis=1)

    variables = {
        "starting_link": (["item_id"], np.squeeze(element_id)),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], 2650 * np.ones(np.size(element_id))),
        "time_arrival_in_link": (["item_id", "time"], time_arrival_in_link),
        "active_layer": (["item_id", "time"], initial_volume),
        "location_in_link": (["item_id", "time"], element_id),
        "D": (["item_id", "time"], initial_volume * 0.05),
        "volume": (["item_id", "time"], initial_volume),
    }

    hundred_boring_parcels = DataRecord(
        nmg_constant_slope,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    nst = NetworkSedimentTransporter(
        nmg_constant_slope,
        hundred_boring_parcels,
        flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )

    dt = 60 * 60  # (seconds) 1 hour timestep

    for t in range(0, (timesteps * dt), dt):
        nst.run_one_step(dt)

    first_in_parcel = np.argmin(time_arrival_in_link)
    last_in_parcel = np.argmax(time_arrival_in_link)
    link_of_first_in_parcel = hundred_boring_parcels.dataset.element_id.values[
        first_in_parcel, :
    ]
    link_of_last_in_parcel = hundred_boring_parcels.dataset.element_id.values[
        last_in_parcel, :
    ]

    First_in_lags_behind = np.greater_equal(
        link_of_last_in_parcel, link_of_first_in_parcel
    )
    SO_TRUE = np.ones(np.shape(First_in_lags_behind), dtype=bool)

    assert_array_equal(SO_TRUE, First_in_lags_behind)
Exemple #16
0
def test_misc():
    grid = RasterModelGrid((3, 3))

    # test bad dimension:
    with pytest.raises(ValueError):
        DataRecord(
            grid,
            time=[0.0],
            data_vars={"mean_elev": (["time"], [100.0]), "test": (["bad_dim"], [12])},
        )
    # should return ValueError('Data variable dimensions must be time and/or'
    #                              'item_id')
    # test bad time format:
    with pytest.raises(TypeError):
        DataRecord(grid=grid, time="bad_time")
    # should return TypeError: Time must be a list or an array of length 1

    # test bad datavars format:
    with pytest.raises(TypeError):
        DataRecord(grid, time=[0.0], data_vars=["not a dict"])
    # should return TypeError(('Data variables (data_vars) passed to'
    #                                 ' DataRecord must be a dictionary (see '
    #                                 'documentation for valid structure)'))

    # test bad items format:
    with pytest.raises(TypeError):
        DataRecord(
            grid,
            time=[0.0],
            items=["not a dict"],
            data_vars={"mean_elevation": (["time"], np.array([100]))},
            attrs={"time_units": "y"},
        )
    # Should return TypeError(('You must provide an ''items'' dictionary '
    #                                 '(see documentation for required format)'))
    #
    with pytest.raises(TypeError):
        """Test bad items keys"""
        DataRecord(
            grid,
            time=[0.0],
            items={
                "grid_element": np.array([["node"], ["link"]]),
                "bad_key": np.array([[1], [3]]),
            },
            data_vars={"mean_elevation": (["time"], np.array([100]))},
            attrs={"time_units": "y"},
        )
    # Should return TypeError(('You must provide an ''items'' dictionary '
    #                                  '(see documentation for required format)'))
    with pytest.raises(TypeError):
        """Test bad attrs"""
        DataRecord(
            grid,
            time=[0.0],
            items={
                "grid_element": np.array([["node"], ["link"]]),
                "element_id": np.array([[1], [3]]),
            },
            data_vars={"mean_elevation": (["time"], np.array([100]))},
            attrs=["not a dict"],
        )
    # Should return except AttributeError:
    #                 raise TypeError(('Attributes (attrs) passed to DataRecord'
    #                                 'must be a dictionary'))
    #
    # test bad loc and id:
    rmg = RasterModelGrid((3, 3))
    hmg = HexModelGrid((3, 2), spacing=1.0)
    radmg = RadialModelGrid(n_rings=1, nodes_in_first_ring=5, xy_of_center=(0.0, 0.0))
    vdmg = VoronoiDelaunayGrid(np.random.rand(25), np.random.rand(25))
    my_items_bad_loc = {
        "grid_element": np.array(["node", "bad_loc"]),
        "element_id": np.array([1, 3]),
    }
    my_items_bad_loc2 = {"grid_element": "bad_loc", "element_id": np.array([1, 3])}
    my_items_bad_loc3 = {
        "grid_element": np.array(["node", "node", "node"]),
        "element_id": np.array([1, 3]),
    }
    my_items_bad_id = {
        "grid_element": np.array(["node", "link"]),
        "element_id": np.array([1, 300]),
    }
    my_items_bad_id2 = {
        "grid_element": np.array(["node", "link"]),
        "element_id": np.array([1, -300]),
    }
    my_items_bad_id3 = {
        "grid_element": np.array(["node", "link"]),
        "element_id": np.array([1, 2.0]),
    }
    my_items_bad_id4 = {
        "grid_element": np.array(["node", "link"]),
        "element_id": np.array([1, 2, 3]),
    }
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_loc)
    with pytest.raises(ValueError):
        DataRecord(hmg, items=my_items_bad_loc)
    with pytest.raises(ValueError):
        DataRecord(radmg, items=my_items_bad_loc)
    with pytest.raises(ValueError):
        DataRecord(vdmg, items=my_items_bad_loc)
    # should return ValueError(('One or more of the grid elements provided is/are'
    #                             ' not permitted location for this grid type.'))
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_loc2)
    # should return ValueError: Location provided: bad_loc is not a permitted
    #  location for this grid type.
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_loc3)
    # should return ValueError(('grid_element passed to DataRecord must be '
    #  ' the same length as the number of items or 1.'))
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_id)
    with pytest.raises(ValueError):
        DataRecord(hmg, items=my_items_bad_id)
    with pytest.raises(ValueError):
        DataRecord(radmg, items=my_items_bad_id)
    with pytest.raises(ValueError):
        DataRecord(vdmg, items=my_items_bad_id)
    # should return ValueError(('An item residing at ' + at + ' has an '
    #  'element_id larger than the number of'+ at + 'on the grid.'))
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_id2)
    #  should return ValueError(('An item residing at ' + at + ' has '
    # 'an element id below zero. This is not permitted.'))
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_id3)
    # should return ValueError(('You have passed a non-integer element_id to '
    #                              'DataRecord, this is not permitted.'))
    with pytest.raises(ValueError):
        DataRecord(rmg, items=my_items_bad_id4)
Exemple #17
0
import pytest
import numpy as np
from landlab import (RasterModelGrid,
                     HexModelGrid,
                     RadialModelGrid,
                     VoronoiDelaunayGrid)
from landlab.data_record import DataRecord

grid = RasterModelGrid((3,3))


#test bad dimension:
with pytest.raises(ValueError):
    DataRecord(grid,
               time=[0.],
               data_vars={'mean_elev' : (['time'], [100.]), 'test' : (['bad_dim'], [12])})
# should return ValueError('Data variable dimensions must be time and/or'
#                              'item_id')
# test bad time format:
with pytest.raises(TypeError):
    DataRecord(grid=grid, time='bad_time')
#should return TypeError: Time must be a list or an array of length 1

#test bad datavars format:
with pytest.raises(TypeError):
    DataRecord(grid, time=[0.], data_vars=['not a dict'])
# should return TypeError(('Data variables (data_vars) passed to'
#                                 ' DataRecord must be a dictionary (see '
#                                 'documentation for valid structure)'))
Exemple #18
0
def test_recycling():
    y_of_node = (0, 0, 0, 0)
    x_of_node = (0, 100, 200, 300)
    nodes_at_link = ((0, 1), (1, 2), (2, 3))

    nmg_constant_slope = NetworkModelGrid((y_of_node, x_of_node), nodes_at_link)

    # add variables to nmg
    nmg_constant_slope.at_node["topographic__elevation"] = [3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_node["bedrock__elevation"] = [3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_link["channel_slope"] = [0.001, 0.001, 0.001]
    nmg_constant_slope.at_link["reach_length"] = [100.0, 100.0, 100.0]  # m
    nmg_constant_slope.at_link["channel_width"] = 15 * np.ones(
        nmg_constant_slope.size("link")
    )
    nmg_constant_slope.at_link["flow_depth"] = 3 * np.ones(
        nmg_constant_slope.size("link")
    )

    flow_director = FlowDirectorSteepest(nmg_constant_slope)
    flow_director.run_one_step()

    time = [0.0]

    items = {"grid_element": "link", "element_id": np.array([[0]])}

    initial_volume = np.array([[1]])
    abrasion_rate = np.array([0])

    variables = {
        "starting_link": (["item_id"], np.array([0])),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], np.array([2650])),
        "time_arrival_in_link": (["item_id", "time"], np.array([[0.71518937]])),
        "active_layer": (["item_id", "time"], np.array([[1]])),
        "location_in_link": (["item_id", "time"], np.array([[0]])),
        "D": (["item_id", "time"], np.array([[0.05]])),
        "volume": (["item_id", "time"], initial_volume),
    }

    parcels = DataRecord(
        nmg_constant_slope,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    nst = NetworkSedimentTransporter(
        nmg_constant_slope,
        parcels,
        flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )

    dt = 60  # (seconds) 1 min timestep

    timesteps = 8

    for t in range(0, (timesteps * dt), dt):
        # RECYCLE sediment: what left the network gets added back in at top.
        parcels.dataset.location_in_link.values[
            parcels.dataset.element_id.values
            == NetworkSedimentTransporter.OUT_OF_NETWORK
        ] = 0
        parcels.dataset.element_id.values[
            parcels.dataset.element_id.values
            == NetworkSedimentTransporter.OUT_OF_NETWORK
        ] = 0
        nst.run_one_step(dt)

        print("done with another timestep")
        print(parcels.dataset.element_id.values)

    Parcel_element_id = parcels.dataset.element_id.values

    Parcel_element_id_Should_Be = np.array(
        [[0.0, 0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 0.0, 0.0]]
    )

    assert_array_almost_equal(
        Parcel_element_id_Should_Be, Parcel_element_id, decimal=-1
    )
Exemple #19
0
    def __call__(self):

        if self._discharge is not None:  # d50 = f(dominant discharge), Snyder

            if np.max(np.abs(self._mannings_n - 0.035)) > 0.3:
                msg = (
                    "BedParcelInitializer: Manning's n value is unrealistic. Value given = "
                    + str(self._mannings_n))
                warnings.warn(msg)

            d50 = calc_d50_discharge(
                self._grid.at_link["channel_width"],
                self._grid.at_link["channel_slope"],
                discharge=self._discharge,
                mannings_n=self._mannings_n,
                gravity=self._gravity,
                rho_water=self._rho_water,
                rho_sediment=self._rho_sediment,
                tau_c_50=self._tau_c_50,
            )

        elif self._flow_depth is not None:  # d50 = f(dominant flow depth), Pfeiffer

            d50 = calc_d50_depth(
                self._grid.at_link["channel_slope"],
                flow_depth=self._flow_depth,
                tau_c_multiplier=self._tau_c_multiplier,
                rho_water=self._rho_water,
                rho_sediment=self._rho_sediment,
                tau_c_50=self._tau_c_50,
            )

        elif self._drainage_area_coefficient is not None:  # d50 = f(drainage area)

            d50 = calc_d50_dArea_scaling(self._grid.at_link["drainage_area"],
                                         a=self._drainage_area_coefficient,
                                         n=self._drainage_area_exponent)

        elif self._user_d50 is not None:

            if np.size(self._user_d50) == 1:  # one d50, all links

                d50 = np.full_like(self._grid.length_of_link,
                                   self._user_d50,
                                   dtype=float)
                print('d50 at each link..', d50)

            elif np.size(self._user_d50) == (
                    self._grid.number_of_links):  # different d50 each link

                d50 = self._user_d50

            else:
                msg = (
                    "BedParcelInitializer: user defined D50 must be either" +
                    "a scalar or size(element_id)")
                raise ValueError(msg)

        else:
            msg = "BedParcelInitializer: user must pass depth, discharge, drainage area scaling, or uniform d50"
            raise ValueError(msg)

        self.D50 = d50
        d84 = d50 * self._std_dev

        total_parcel_volume_at_link = calc_total_parcel_volume(
            self._grid.at_link["channel_width"],
            self._grid.at_link["reach_length"],
            d84 * self._sed_thickness,
        )
        max_parcel_volume = _determine_approx_parcel_volume(
            total_parcel_volume_at_link,
            self._median_number_of_starting_parcels)

        variables, items = _parcel_characteristics(
            total_parcel_volume_at_link, max_parcel_volume, d50, self._std_dev,
            self._rho_sediment, self._abrasion_rate,
            self._extra_parcel_attributes)

        if np.min(self._sed_thickness) < 0.05:
            msg = (
                "BedParcelInitializer: Sediment thickness is unrealistically low. Minimum link sediment thickness = "
                + str(self._sed_thickness) + " m")
            warnings.warn(msg)

        if np.max(d50) > 0.5:
            msg = (
                "BedParcelInitializer: Median grain sizes are too large for physically realistic application of the NST. Maximum link D50 = "
                + str(d50) + " m")
            warnings.warn(msg)

        if np.min(d50) < 0.002:
            msg = (
                "BedParcelInitializer: The equations used in this initializer are intended for gravel bedded rivers."
                "Calculated median grain sizes are too small. Minimum link D50 = "
                + str(d50) + " m")
            warnings.warn(msg)

        if np.max(np.abs(self._tau_c_50 - 0.055)) > 0.35:
            msg = (
                "BedParcelInitializer: Shields stress value is unrealistic. Value given = "
                + str(self._sed_thickness))
            warnings.warn(msg)

        if max_parcel_volume < 0.05:
            msg = (
                "BedParcelInitializer: Careful! Default parcel volume is extremely small: "
                + str(max_parcel_volume) + ' m')
            warnings.warn(msg)

        return DataRecord(
            self._grid,
            items=items,
            time=self._time,
            data_vars=variables,
            dummy_elements={"link": [_OUT_OF_NETWORK]},
        )
Exemple #20
0
def dr_time():
    time = [0.]
    data_vars = {'mean_elevation': (['time'], np.array([100]))}
    attrs = {'time_units': 'y'}
    return DataRecord(grid=grid, time=time, data_vars=data_vars, attrs=attrs)
Exemple #21
0
"""

import numpy as np
import pytest

from landlab import HexModelGrid, RadialModelGrid, RasterModelGrid, VoronoiDelaunayGrid
from landlab.data_record import DataRecord

grid = RasterModelGrid((3, 3))

# test bad dimension:
with pytest.raises(ValueError):
    DataRecord(
        grid,
        time=[0.0],
        data_vars={
            "mean_elev": (["time"], [100.0]),
            "test": (["bad_dim"], [12])
        },
    )
# should return ValueError('Data variable dimensions must be time and/or'
#                              'item_id')
# test bad time format:
with pytest.raises(TypeError):
    DataRecord(grid=grid, time="bad_time")
# should return TypeError: Time must be a list or an array of length 1

# test bad datavars format:
with pytest.raises(TypeError):
    DataRecord(grid, time=[0.0], data_vars=["not a dict"])
# should return TypeError(('Data variables (data_vars) passed to'
#                                 ' DataRecord must be a dictionary (see '
Exemple #22
0
def test_add_pulse():

    y_of_node = (0, 0, 0, 0)
    x_of_node = (0, 100, 200, 300)
    nodes_at_link = ((0, 1), (1, 2), (2, 3))

    nmg_constant_slope = NetworkModelGrid((y_of_node, x_of_node), nodes_at_link)

    # add variables to nmg
    nmg_constant_slope.at_node["topographic__elevation"] = [3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_node["bedrock__elevation"] = [3.0, 2.0, 1.0, 0.0]
    nmg_constant_slope.at_link["channel_slope"] = [0.001, 0.001, 0.001]
    nmg_constant_slope.at_link["reach_length"] = [100.0, 100.0, 100.0]  # m
    nmg_constant_slope.at_link["channel_width"] = 15 * np.ones(
        nmg_constant_slope.size("link")
    )
    nmg_constant_slope.at_link["flow_depth"] = 2 * np.ones(
        nmg_constant_slope.size("link")
    )

    flow_director = FlowDirectorSteepest(nmg_constant_slope)
    flow_director.run_one_step()

    time = [0.0]

    items = {"grid_element": "link", "element_id": np.array([[0]])}

    initial_volume = np.array([[1]])
    abrasion_rate = np.array([0])

    variables = {
        "starting_link": (["item_id"], np.array([0])),
        "abrasion_rate": (["item_id"], abrasion_rate),
        "density": (["item_id"], np.array([2650])),
        "time_arrival_in_link": (["item_id", "time"], np.array([[0.71518937]])),
        "active_layer": (["item_id", "time"], np.array([[1]])),
        "location_in_link": (["item_id", "time"], np.array([[0]])),
        "D": (["item_id", "time"], np.array([[0.05]])),
        "volume": (["item_id", "time"], initial_volume),
    }

    parcels = DataRecord(
        nmg_constant_slope,
        items=items,
        time=time,
        data_vars=variables,
        dummy_elements={"link": [NetworkSedimentTransporter.OUT_OF_NETWORK]},
    )

    nst = NetworkSedimentTransporter(
        nmg_constant_slope,
        parcels,
        flow_director,
        bed_porosity=0.03,
        g=9.81,
        fluid_density=1000,
        transport_method="WilcockCrowe",
    )

    dt = 60  # (seconds) 1 min timestep

    nst.run_one_step(dt)

    # ONE TIMESTEP BEFORE PULSE
    # TIMESTEP 1 should have NANS.

    num_pulse_parcels = 2

    newpar_element_id = np.zeros(num_pulse_parcels, dtype=int)
    newpar_element_id = np.expand_dims(newpar_element_id, axis=1)

    new_starting_link = np.squeeze(newpar_element_id)

    np.random.seed(0)

    new_time_arrival_in_link = nst._time * np.ones(np.shape(newpar_element_id))

    new_volume = 0.5 * np.ones(
        np.shape(newpar_element_id)
    )  # (m3) the volume of each parcel

    new_lithology = ["pulse_material"] * np.size(
        newpar_element_id
    )  # a lithology descriptor for each parcel

    new_active_layer = np.ones(
        np.shape(newpar_element_id)
    )  # 1 = active/surface layer; 0 = subsurface layer

    new_density = 2650 * np.ones(np.size(newpar_element_id))  # (kg/m3)

    new_location_in_link = np.random.rand(np.size(newpar_element_id), 1)

    new_abrasion_rate = 0 * np.ones(np.size(newpar_element_id))

    new_D = 0.03 * np.ones(np.shape(newpar_element_id))

    newpar_grid_elements = np.array(
        np.empty((np.shape(newpar_element_id)), dtype=object)
    )  # BUG: should be able to pass ["link"], but datarecord fills it into an incorrect array shape-- the length of parcels (NOT new parcels)
    newpar_grid_elements.fill("link")

    new_parcels = {
        "grid_element": newpar_grid_elements,
        "element_id": newpar_element_id,
    }

    new_variables = {
        "starting_link": (["item_id"], new_starting_link),
        "abrasion_rate": (["item_id"], new_abrasion_rate),
        "density": (["item_id"], new_density),
        "lithology": (["item_id"], new_lithology),
        "time_arrival_in_link": (["item_id", "time"], new_time_arrival_in_link),
        "active_layer": (["item_id", "time"], new_active_layer),
        "location_in_link": (["item_id", "time"], new_location_in_link),
        "D": (["item_id", "time"], new_D),
        "volume": (["item_id", "time"], new_volume),
    }

    parcels.add_item(
        time=[nst._time], new_item=new_parcels, new_item_spec=new_variables
    )

    nst.run_one_step(dt)

    print(parcels.dataset.element_id.values)
    Parcel_element_id = parcels.dataset.element_id.values

    Parcel_element_id_Should_Be = np.array(
        [[0.0, 0.0, 0.0], [np.nan, 0.0, 0.0], [np.nan, 0.0, 0.0]]
    )

    assert_array_almost_equal(
        Parcel_element_id_Should_Be, Parcel_element_id, decimal=-1
    )
Exemple #23
0
def dr_time():
    time = [0.]
    data_vars = {"mean_elevation": (["time"], np.array([100]))}
    attrs = {"time_units": "y"}
    return DataRecord(grid=grid, time=time, data_vars=data_vars, attrs=attrs)