Example #1
0
def test_out_of_phase_interval_fails(clock_08, almost_default_grid):
    ncnblh = NotCoreNodeBaselevelHandler(almost_default_grid,
                                         modify_core_nodes=True,
                                         lowering_rate=-1)

    # construct and run model
    times = [
        0.0,
        1.0,
        1.01,  # next time is set to 2. Divisible warning
        1.02,  # new time < 2. Starting skips. Skipping warning
        1.10,
        1.11,
        1.12,
        1.13,
        1.14,
        1.15,
        1.16,
        1.17,
        1.18,
        2.00,  # 10 skips. Loop exits. Raises Assertion Error
        3.0,  # Does not get this far
    ]
    model = Basic(
        clock_08,
        almost_default_grid,
        water_erodibility=0.0,
        regolith_transport_parameter=0.0,
        boundary_handlers={"NotCoreNodeBaselevelHandler": ncnblh},
        output_writers={
            "out-of-phase-ow-fails": {
                "class": OWStaticWrapper,
                "kwargs": {
                    "add_id": False,
                    "times": times,
                },
            },
        },
        # output_interval=6.0,
        output_dir=_TEST_OUTPUT_DIR,
        output_prefix="",
        save_first_timestep=True,
        save_last_timestep=True,
    )
    skip_warning_msg = "next time that is less than or equal to the current"
    divisible_warning_msg = "time that is not divisible by the model step"

    # Copied from ErosionModel.run() so I can control the steps
    model._itters = []

    if model.save_first_timestep:
        model.iteration = 0
        model._itters.append(0)
        model.write_output()
    model.iteration = 1

    def run_one_iteration():
        time_now = model._model_time
        next_run_pause = min(
            # time_now + model.output_interval, model.clock.stop,
            model.next_output_time,
            model.clock.stop,
        )
        assert next_run_pause > time_now
        print(f"Iteration {model.iteration:05d} Model time {model.model_time}")
        print(
            f"  Run for {next_run_pause - time_now}, (step = {model.clock.step})"
        )
        model.run_for(model.clock.step, next_run_pause - time_now)
        time_now = model._model_time
        model._itters.append(model.iteration)
        model.write_output()
        model.iteration += 1

    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 0.0 and model.next_output_time == 1.0

    warning_msg_sample = "time that is not divisible by the model step"
    with pytest.warns(UserWarning, match=warning_msg_sample):
        run_one_iteration()
    # times_iter returns 1.01, which is then delayed to 2.0
    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 1.00 and model.next_output_time == 2.0

    # time_iter returns 1.02, which triggers skips and eventually fails
    with pytest.warns(UserWarning) as all_warnings, pytest.raises(
            AssertionError):
        run_one_iteration()
    ignored_warnings = [RuntimeWarning]
    for warn_info in all_warnings:
        warn_type = warn_info.category
        if warn_type in ignored_warnings:
            continue
        try:
            assert warn_type == UserWarning
            message = warn_info.message.args[0]
            is_skip_warning = skip_warning_msg in message
            is_divisible_warning = divisible_warning_msg in message
            assert is_skip_warning or is_divisible_warning
        except AssertionError:
            print(warn_info)  # So I can see other warnings
            raise

    model.remove_output()
Example #2
0
def test_out_of_phase_interval_warns(clock_08, almost_default_grid):
    ncnblh = NotCoreNodeBaselevelHandler(almost_default_grid,
                                         modify_core_nodes=True,
                                         lowering_rate=-1)

    # construct and run model
    times = [
        0.0,
        1.0,
        1.01,  # next time is set to 2. Divisible warning
        1.02,  # new time < 2. Starting skips. Skipping warning
        1.10,
        1.11,
        1.12,
        1.13,
        1.14,
        1.15,
        1.16,
        1.17,
        1.18,
        3.00,  # Finds suitable time on 10th skip.
    ]
    model = Basic(
        clock_08,
        almost_default_grid,
        water_erodibility=0.0,
        regolith_transport_parameter=0.0,
        boundary_handlers={"NotCoreNodeBaselevelHandler": ncnblh},
        output_writers={
            "out-of-phase-skipping-ow": {
                "class": OWStaticWrapper,
                "kwargs": {
                    "add_id": False,
                    "times": times,
                },
            },
        },
        # output_interval=6.0,
        output_dir=_TEST_OUTPUT_DIR,
        output_prefix="",
        save_first_timestep=True,
        save_last_timestep=True,
    )
    skip_warning_msg = "next time that is less than or equal to the current"
    divisible_warning_msg = "time that is not divisible by the model step"

    # Copied from ErosionModel.run() so I can control the steps
    model._itters = []
    if model.save_first_timestep:
        model.iteration = 0
        model._itters.append(0)
        model.write_output()
    model.iteration = 1

    def run_one_iteration():
        time_now = model._model_time
        next_run_pause = min(
            model.next_output_time,
            model.clock.stop,
        )
        assert next_run_pause > time_now
        print(f"Iteration {model.iteration:05d} Model time {model.model_time}")
        print(
            f"  Run for {next_run_pause - time_now}, (step = {model.clock.step})"
        )
        model.run_for(model.clock.step, next_run_pause - time_now)
        time_now = model._model_time
        model._itters.append(model.iteration)
        model.write_output()
        model.iteration += 1

    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 0.0 and model.next_output_time == 1.0

    warning_msg_sample = "time that is not divisible by the model step"
    with pytest.warns(UserWarning, match=warning_msg_sample):
        run_one_iteration()
    # times_iter returns 1.01, which is then delayed to 2.0
    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 1.00 and model.next_output_time == 2.0

    # time_iter returns 1.02, which triggers skips but eventually finds 3.0
    with pytest.warns(UserWarning) as all_warnings:
        run_one_iteration()
    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 2.0 and model.next_output_time == 3.0
    ignored_warnings = [RuntimeWarning]
    for warn_info in all_warnings:
        warn_type = warn_info.category
        if warn_type in ignored_warnings:
            continue
        try:
            assert warn_type == UserWarning
            message = warn_info.message.args[0]
            is_skip_warning = skip_warning_msg in message
            is_divisible_warning = divisible_warning_msg in message
            assert is_skip_warning or is_divisible_warning
        except AssertionError:
            print(warn_info)  # So I can see other warnings
            raise

    run_one_iteration()
    # times_iter returns 20.0
    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 3.0 and model.next_output_time == 20.0

    run_one_iteration()
    # Model finishes
    print(f"t={model.model_time}, nt={model.next_output_time}")
    assert model.model_time == 20.0 and model.next_output_time == np.inf

    # now that the model is finished running, execute finalize.
    model.finalize()

    # Check that there is a file for t=3.0
    good_filename = f"out-of-phase-skipping-ow_time-{3.0:012.1f}.txt"
    good_filepath = get_output_filepath(good_filename)
    assert os.path.isfile(good_filepath), f"{good_filepath} should exist"

    model.remove_output()