def test_h0(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'h0': 7.5}) _delta = DeltaModel(input_file=p) assert _delta.h0 == 7.5 p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'h0': int(7)}) _delta = DeltaModel(input_file=p) assert _delta.h0 == 7
def test_no_clobber_error(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'save_eta_grids': True}) _model_1 = DeltaModel(input_file=p) _model_1.output_netcdf.close() # assert that model could not have clobbered a netcdf assert _model_1._clobber_netcdf is False # make a second model which raises error with pytest.raises(FileExistsError): _ = DeltaModel(input_file=p)
def test_clobbering(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'clobber_netcdf': True, 'save_eta_grids': True }) _model_1 = DeltaModel(input_file=p) _model_1.output_netcdf.close() # assert that model could have clobbered a netcdf assert _model_1._clobber_netcdf is True # make a second model which clobbers, raising eyebrows (and warning) with pytest.warns(UserWarning): _model_2 = DeltaModel(input_file=p) _model_2.output_netcdf.close() assert _model_2._clobber_netcdf is True
def test_save_figure_sequential(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_eta_figs': True, 'save_figs_sequential': False }) _delta = DeltaModel(input_file=p) # make a figure fig, ax = plt.subplots() ax.imshow(np.random.uniform(0, 1, size=(100, 100))) # save two figs with different timesteps _delta.save_figure(fig, directory=_delta.prefix, filename_root='eta_', timestep=0) _delta.save_figure(fig, directory=_delta.prefix, filename_root='eta_', timestep=1) exp_path_png0 = os.path.join(tmp_path / 'out_dir', 'eta_00000.png') exp_path_png0_latest = os.path.join(tmp_path / 'out_dir', 'eta_latest.png') assert not os.path.isfile(exp_path_png0) assert os.path.isfile(exp_path_png0_latest)
def test_save_metadata_no_grids(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_metadata': True }) _delta = DeltaModel(input_file=p) # mock the log_info _delta.log_info = mock.MagicMock() # mock the actual output routines _delta.make_figure = mock.MagicMock() _delta.save_figure = mock.MagicMock() _delta.save_grids = mock.MagicMock() exp_path_nc = os.path.join(tmp_path / 'out_dir', 'pyDeltaRCM_output.nc') assert os.path.isfile(exp_path_nc) for _t in range(0, 3): _delta.save_grids_and_figs() _delta._save_iter += 1 # close the file and connect _delta.output_netcdf.close() ds = netCDF4.Dataset(exp_path_nc, "r", format="NETCDF4") # assertions assert not ('eta' in ds.variables) assert ds['meta']['H_SL'].shape[0] == 4 # init + 3 assert ds['meta']['L0'][:] == 3
def test_save_one_fig_no_grids(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_eta_figs': True }) _delta = DeltaModel(input_file=p) # mock the log_info _delta.log_info = mock.MagicMock() # mock the actual output routines _delta.make_figure = mock.MagicMock() _delta.save_figure = mock.MagicMock() _delta.save_grids = mock.MagicMock() # check nothing created at the start _delta.make_figure.call_count == 0 _delta.save_figure.call_count == 0 _delta.save_grids.call_count == 0 assert (len(_delta._save_fig_list) > 0) assert (_delta._save_eta_figs is True) # update the delta a few times for _t in range(0, 5): _delta.save_grids_and_figs() _delta._save_iter += 1 _delta.make_figure.call_count == 5 _delta.save_figure.call_count == 5 _delta.save_grids.call_count == 0
def test_subsidence_in_update(self, tmp_path): # create a delta with subsidence parameters p = utilities.yaml_from_dict( tmp_path, 'input.yaml', { 'toggle_subsidence': True, 'subsidence_rate': 1e-8, 'start_subsidence': 0, 'save_eta_grids': True, 'seed': 0 }) _delta = DeltaModel(input_file=p) # mock the timestep computations _delta.solve_water_and_sediment_timestep = mock.MagicMock() assert _delta.dt == 25000 assert _delta.subsidence_rate == 1e-8 assert np.all( _delta.sigma[:_delta.L0, :] == 0.0) # outside the sigma mask assert np.all( _delta.sigma[_delta.L0:, :] == 0.00025) # inside the sigma mask assert np.all(_delta.eta[_delta.L0:, :] == -_delta.h0) _delta.update() assert np.all(_delta.eta[_delta.L0 - 1, :25] == 0.0) assert np.all(_delta.eta[_delta.L0:, :] == pytest.approx(-_delta.h0 - 0.00025)) _delta.output_netcdf.close()
def test_save_one_fig_one_grid(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_eta_grids': True, 'save_discharge_figs': True }) _delta = DeltaModel(input_file=p) # mock the timestep computations _delta.solve_water_and_sediment_timestep = mock.MagicMock() _delta.apply_subsidence = mock.MagicMock() _delta.finalize_timestep = mock.MagicMock() _delta.log_model_time = mock.MagicMock() _delta.output_checkpoint = mock.MagicMock() exp_path_nc = os.path.join(tmp_path / 'out_dir', 'pyDeltaRCM_output.nc') assert os.path.isfile(exp_path_nc) nc_size_before = os.path.getsize(exp_path_nc) assert nc_size_before > 0 # update a couple times, should increase on each save for _ in range(0, 2): _delta.update() nc_size_middle = os.path.getsize(exp_path_nc) assert _delta.time_iter == 2.0 assert nc_size_middle > nc_size_before # now finalize, and file size should stay the same _delta.finalize() nc_size_after = os.path.getsize(exp_path_nc) assert _delta.time_iter == 2.0 assert nc_size_after == nc_size_middle assert nc_size_after > nc_size_before
def test_plot_domain_velocity(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml') _delta = DeltaModel(input_file=p) fig, ax = plt.subplots(figsize=(5, 4)) _delta.show_attribute('ux') return plt.gcf()
def test_U_dep_mud(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'coeff_U_dep_mud': 0.4325, 'u0': 2.2 }) _delta = DeltaModel(input_file=p) assert _delta.U_dep_mud == 0.9515
def test_theta_mud(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'coeff_theta_mud': 0.8, 'theta_water': 1.3 }) _delta = DeltaModel(input_file=p) assert _delta.theta_mud == 1.04
def test_save_figs_sequential(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'save_figs_sequential': False}) _delta = DeltaModel(input_file=p) assert len(_delta._save_fig_list) == 0 assert _delta._save_any_grids is False assert _delta._save_figs_sequential is False
def test_save_sandfrac_grids(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'save_sandfrac_grids': True}) _delta = DeltaModel(input_file=p) assert _delta._save_any_grids is True assert len(_delta._save_fig_list) == 0 assert 'sandfrac' in _delta._save_var_list.keys()
def test_hb(self, tmp_path): # take default from h0 if not given: p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'h0': 7.5}) _delta = DeltaModel(input_file=p) assert _delta.h0 == 7.5 assert _delta.hb == 7.5 p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'hb': 7.5}) _delta = DeltaModel(input_file=p) assert _delta.h0 == 5 assert _delta.hb == 7.5 p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'hb': int(7)}) _delta = DeltaModel(input_file=p) assert _delta.h0 == 5 assert _delta.hb == 7
def test_load_already_open_netcdf_error(self, patched, tmp_path): """ Test that a checkpoint can be loaded when the load expects there to be a netcdf file. This will create a new netcdf file and raise a warning. """ # define a yaml with an output, and checkpoint p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_checkpoint': True, 'save_eta_grids': True }) _delta = DeltaModel(input_file=p) # make mocks _delta.log_info = mock.MagicMock() _delta.logger = mock.MagicMock() _delta.init_output_file = mock.MagicMock() # close the file so can be safely opened in load _delta.output_netcdf.close() # check that files exist, and then open the nc back up assert os.path.isfile( os.path.join(_delta.prefix, 'pyDeltaRCM_output.nc')) assert os.path.isfile(os.path.join(_delta.prefix, 'checkpoint.npz')) _ = Dataset(os.path.join(_delta.prefix, 'pyDeltaRCM_output.nc')) # now try to resume a model and should throw error with pytest.raises(RuntimeError): _delta.load_checkpoint()
def test_logger_random_seed_always_recorded(self, tmp_path): file_name = 'user_parameters.yaml' p, f = utilities.create_temporary_file(tmp_path, file_name) utilities.write_parameter_to_file(f, 'out_dir', tmp_path / 'out_dir') utilities.write_parameter_to_file(f, 'verbose', 0) # do not set the seed explicitly, let it be set by the model f.close() delta = DeltaModel(input_file=p) _logs = glob.glob(os.path.join(delta.prefix, '*.log')) assert len(_logs) == 1 # log file exists with open(_logs[0], 'r') as _logfile: _lines = _logfile.readlines() _joinedlines = ' '.join(_lines) # collapse to a single string assert 'Random seed is: ' in _joinedlines # determine the index of the line _idx = ['Random seed is: ' in _l for _l in _lines] assert sum(_idx) == 1 # one and only one True in list _idx = _idx.index(True) # try to covert to int, otherwise fail _seed = _lines[_idx].split(':')[-1] # pull the seed value try: _intseed = int(_seed) except ValueError: raise ValueError('Could not convert the seed to int') assert _intseed >= 0
def test_plot_domain_cell_type_no_grid(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml') _delta = DeltaModel(input_file=p) fig, ax = plt.subplots(figsize=(5, 4)) _delta.show_attribute('cell_type', grid=False) return plt.gcf()
def test_U_ero_mud(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'coeff_U_ero_mud': 1.67, 'u0': 2.2 }) _delta = DeltaModel(input_file=p) assert _delta.U_ero_mud == 3.674
def test_finalize_updated(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml') _delta = DeltaModel(input_file=p) # mock the top-level _delta.log_info = mock.MagicMock() _delta.output_data = mock.MagicMock() _delta.output_checkpoint = mock.MagicMock() # modify the save interval _t = 5 _delta._save_dt = _t * _delta._dt _delta._checkpoint_dt = _t * _delta._dt # run a mock update / save _delta._time = _t * _delta._dt _delta._save_iter += int(1) _delta._save_time_since_data = 0 _delta._save_time_since_checkpoint = 0 # run finalize _delta.finalize() # assert calls # should only hit top-levels assert _delta.log_info.call_count == 2 assert _delta.output_data.call_count == 0 assert _delta.output_checkpoint.call_count == 0 assert _delta._is_finalized is True
def test_L(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'Length': 1600, 'dx': 20 }) _delta = DeltaModel(input_file=p) assert _delta.L == 80
def test_save_metadata_no_grids(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_metadata': True }) _delta = DeltaModel(input_file=p) # mock the timestep computations _delta.solve_water_and_sediment_timestep = mock.MagicMock() _delta.apply_subsidence = mock.MagicMock() _delta.finalize_timestep = mock.MagicMock() _delta.log_model_time = mock.MagicMock() _delta.output_checkpoint = mock.MagicMock() exp_path_nc = os.path.join(tmp_path / 'out_dir', 'pyDeltaRCM_output.nc') assert os.path.isfile(exp_path_nc) for _ in range(0, 2): _delta.update() assert _delta.time_iter == 2.0 _delta.solve_water_and_sediment_timestep.call_count == 2 _delta.finalize() ds = netCDF4.Dataset(exp_path_nc, "r", format="NETCDF4") assert not ('eta' in ds.variables) assert ds['meta']['H_SL'].shape[0] == 3 assert ds['meta']['L0'][:] == 3
def test_W(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'Width': 1200, 'dx': 20 }) _delta = DeltaModel(input_file=p) assert _delta.W == 60
def test_save_no_figs_no_grids(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'save_dt': 1}) _delta = DeltaModel(input_file=p) # mock the log_info _delta.log_info = mock.MagicMock() # mock the actual output routines _delta.make_figure = mock.MagicMock() _delta.save_figure = mock.MagicMock() _delta.save_grids = mock.MagicMock() # check nothing created at the start _delta.make_figure.call_count == 0 _delta.save_figure.call_count == 0 _delta.save_grids.call_count == 0 # update the delta a few times for _t in range(0, 4): _delta._time = (_t * _delta._dt) _delta.save_grids_and_figs() # check nothing after a number of iterations, greater than dt assert _delta._time > _delta.save_dt _delta.make_figure.call_count == 0 _delta.save_figure.call_count == 0 _delta.save_grids.call_count == 0
def test_V0(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'h0': 3, 'dx': 15 }) _delta = DeltaModel(input_file=p) assert _delta.V0 == 675
def test_save_one_fig_one_grid(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_eta_grids': True, 'save_discharge_figs': True }) _delta = DeltaModel(input_file=p) # mock the log_info _delta.log_info = mock.MagicMock() # mock the actual output routines _delta.make_figure = mock.MagicMock() _delta.save_figure = mock.MagicMock() _delta.save_grids = mock.MagicMock() assert (_delta._save_eta_grids is True) assert (_delta._save_metadata is True) # check for the netcdf file exp_path_nc = os.path.join(tmp_path / 'out_dir', 'pyDeltaRCM_output.nc') assert os.path.isfile(exp_path_nc) nc_size_before = os.path.getsize(exp_path_nc) assert nc_size_before > 0 # saved once already / inited # update a couple times, should increase on each save for _t in range(0, 5): _delta.save_grids_and_figs() _delta._save_iter += 1 _delta.make_figure.call_count == 5 _delta.save_figure.call_count == 5 _delta.save_grids.call_count == 5
def test_qw0(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'u0': 0.8, 'h0': 3 }) _delta = DeltaModel(input_file=p) assert _delta.qw0 == pytest.approx(2.4)
def test_solve_water_and_sediment_timestep_itermax_10(self, tmp_path): # create a delta with different itermax p = utilities.yaml_from_dict(tmp_path, 'input.yaml', {'itermax': 10}) delta = DeltaModel(input_file=p) # mock top-level methods, verify call was made to each delta.log_info = mock.MagicMock() delta.init_water_iteration = mock.MagicMock() delta.run_water_iteration = mock.MagicMock() delta.compute_free_surface = mock.MagicMock() delta.finalize_water_iteration = mock.MagicMock() delta.route_sediment = mock.MagicMock() # run the timestep delta.solve_water_and_sediment_timestep() # assert that methods are called assert delta.init_water_iteration.called is True assert delta.run_water_iteration.called is True assert delta.compute_free_surface.called is True assert delta.finalize_water_iteration.called is True _calls = [mock.call(i) for i in range(10)] delta.finalize_water_iteration.assert_has_calls(_calls, any_order=False) assert delta.finalize_water_iteration.call_count == 10 assert (delta.route_sediment.called is True) assert (delta._is_finalized is False)
def test_route_sand_parcels(self, tmp_path): # create a delta with default settings p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'Np_sed': 1000, 'f_bedload': 0.6 }) _delta = DeltaModel(input_file=p) # mock top-level methods / objects _delta.log_info = mock.MagicMock() _delta._sr = mock.MagicMock() # mock the shared tools start indices def _patched_starts(inlet, inlet_weights, num_starts): return np.random.randint(0, 5, size=(num_starts, )) patcher = mock.patch('pyDeltaRCM.shared_tools.get_start_indices', new=_patched_starts) patcher.start() # run the method _delta.route_all_sand_parcels() # methods called assert (_delta._sr.run.call_count == 1) assert (_delta.log_info.call_count == 3) # stop the patch patcher.stop()
def test_save_sedflux_grids(self, tmp_path): p = utilities.yaml_from_dict(tmp_path, 'input.yaml', { 'save_dt': 1, 'save_sedflux_grids': True }) _delta = DeltaModel(input_file=p) # mock the log_info _delta.log_info = mock.MagicMock() exp_path_nc = os.path.join(tmp_path / 'out_dir', 'pyDeltaRCM_output.nc') assert os.path.isfile(exp_path_nc) for _t in range(0, 6): _delta.save_grids('sedflux', _delta.qs, _delta._save_iter) _delta._save_iter += 1 # close the file and connect _delta.output_netcdf.close() ds = netCDF4.Dataset(exp_path_nc, "r", format="NETCDF4") # assertions assert (_delta.log_info.call_count == 6) _arr = ds.variables['sedflux'] assert _arr.shape[1] == _delta.qs.shape[0] assert _arr.shape[2] == _delta.qs.shape[1] assert ('meta' in ds.groups) # if any grids, save meta too
def test_logger_has_initialization_lines(self, tmp_path): file_name = 'user_parameters.yaml' p, f = utilities.create_temporary_file(tmp_path, file_name) utilities.write_parameter_to_file(f, 'out_dir', tmp_path / 'out_dir') utilities.write_parameter_to_file(f, 'verbose', 1) utilities.write_parameter_to_file(f, 'seed', 10) f.close() _delta = DeltaModel(input_file=p) _logs = glob.glob(os.path.join(_delta.prefix, '*.log')) assert len(_logs) == 1 # log file exists with open(_logs[0], 'r') as _logfile: _lines = _logfile.readlines() _lines = ' '.join(_lines) # collapse to a single string assert 'Setting model constants' in _lines assert 'Random seed is: 10' in _lines assert 'Creating model domain' in _lines assert 'Initializing output NetCDF4 file' in _lines assert 'Model initialization complete' in _lines if sys.platform.startswith('linux'): assert 'Platform: Linux-' in _lines elif sys.platform == 'darwin': guess1 = 'Platform: Darwin-' in _lines guess2 = 'Platform: macOS-' in _lines assert (guess1 | guess2) elif sys.platform.startswith('win'): assert 'Platform: Windows-' in _lines else: raise RuntimeError('Platform type not recognized.') assert not os.path.isfile( os.path.join(tmp_path, 'out_dir', 'discharge_0.0.png')) assert not os.path.isfile( os.path.join(tmp_path, 'out_dir', 'eta_0.0.png'))