From 045da22a4a941f0101180e71c420f382381f40a2 Mon Sep 17 00:00:00 2001 From: Riley Hales PhD <39097632+rileyhales@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:26:44 -0600 Subject: [PATCH] allow specifying solver tolerances, smaller default (#30) --- README.md | 14 ++++---------- config_files/config.json | 19 ------------------- config_files/config.yaml | 2 ++ config_files/descriptions.csv | 1 + river_route/_MuskingumCunge.py | 10 +++++++++- river_route/__metadata__.py | 2 +- 6 files changed, 17 insertions(+), 31 deletions(-) delete mode 100644 config_files/config.json diff --git a/README.md b/README.md index 5b71945..f21106b 100644 --- a/README.md +++ b/README.md @@ -63,17 +63,11 @@ You can modify how the routing computations are performed with these parameters: See [Time Parameters](#time-parameters). - `dt_outflows` - an integer time in seconds for the outflow time step. Will default to the inflow time step. See [Time Parameters](#time-parameters). -- `min_q` - a float for the minimum flow value enforced after each routing calculation. -- `max_q` - a float for the maximum flow value enforced after each routing calculation. You can provide initial conditions/state and save final conditions/state with these parameters: -- `qinit_file` - path to the initial flows file (parquet). Defaults to 0.0 for all rivers. -- `rinit_file` - path to the initial runoff file (netCDF). Defaults to 0.0 for all rivers. -- `qfinal_file` - path where the final flows file will be saved (parquet). It will not be saved if a path is not - provided. -- `rfinal_file` - path where the final runoff file will be saved (netCDF). It will not be saved if a path is not - provided. +- `initial_state_file` - path to the initial state file (parquet). It will not be loaded if a path is not provided. +- `final_state_file` - path where the final flows file will be saved (parquet). It will not be saved if a path is not provided. You can provide logging options with these parameters: @@ -150,7 +144,7 @@ graph LR | var_runoff_volume | False | String | File Management | Name of the variable in files containing runoff volumes | | var_river_id | False | String | File Management | Name of the variable in all files that contains the river IDs. | | var_outflow | False | String | File Management | Name of the variable in the outflows file that contains the outflows. | - +| solver_atol | False | Float | Solver Options | Absolute tolerance for the solver. | ## Input File Schemas ### Routing Parameters @@ -168,7 +162,7 @@ The rows (rivers) **must be sorted in topological order** from upstream to downs | x | float | the x parameter of the MuskingumCunge Cunge routing equation. x : [0, 0.5] | | k_1 | float | Optional, the k parameter of the MuskingumCunge Cunge routing equation at Q_1 | | x_1 | float | Optional, the x parameter of the MuskingumCunge Cunge routing equation at Q_1 | -| q_1 | float | Optional, the minimu value of Q at which to start using use k_1 and x_1 | +| q_1 | float | Optional, the minimum value of Q at which to start using use k_1 and x_1 | ### Connectivity File diff --git a/config_files/config.json b/config_files/config.json deleted file mode 100644 index 925b132..0000000 --- a/config_files/config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "routing_params_file": "", - "connectivity_file": "", - "runoff_volumes_file": "", - "outflow_file": "", - "routing": "", - "dt_routing": "", - "dt_outflows": "", - "initial_state_file": "", - "final_state_file": "", - "log": false, - "progress_bar": "", - "job_name": "", - "log_level": "", - "log_stream": "", - "var_runoff_volume": "ro_vol", - "var_river_id": "river_id", - "var_outflow": "Q" -} \ No newline at end of file diff --git a/config_files/config.yaml b/config_files/config.yaml index 236bf61..48a329b 100644 --- a/config_files/config.yaml +++ b/config_files/config.yaml @@ -12,6 +12,8 @@ var_outflow: 'Q' routing: 'linear' dt_routing: 0 dt_outflows: 0 +# Solver Options - Optional +solver_atol: 0.00001 # initial and final state files - Optional initial_state_file: '' final_state_file: '' diff --git a/config_files/descriptions.csv b/config_files/descriptions.csv index 1412002..848fb15 100644 --- a/config_files/descriptions.csv +++ b/config_files/descriptions.csv @@ -6,6 +6,7 @@ outflow_file,string,Path where the outflows file should be saved. dt_routing,number,Time interval in seconds between routing computations. dt_outflows,number,Time interval in seconds between writing flows to disc. routing,string,Either 'linear' or 'nonlinear' routing- default 'linear'. +solver_atol,number,Absolute tolerance for the solver. initial_state_file,string,Path to the file with initial state values. final_state_file,string,Path to the file with final state values. log,boolean,whether to display log messages defaulting to False diff --git a/river_route/_MuskingumCunge.py b/river_route/_MuskingumCunge.py index bbd68bb..bffa2ea 100644 --- a/river_route/_MuskingumCunge.py +++ b/river_route/_MuskingumCunge.py @@ -56,6 +56,9 @@ class MuskingumCunge: num_routing_steps_per_runoff: int num_runoff_steps_per_outflow: int + # Solver options + _solver_atol: float = 1e-5 + # Calibration variables _calibration_iteration_number: int @@ -106,6 +109,11 @@ def set_configs(self, config_file, **kwargs) -> None: self.conf['routing'] = self.conf.get('routing', 'linear') assert self.conf['routing'] in ['linear', 'nonlinear'], 'Routing method not recognized' + # update solver options if given + self._solver_atol = self.conf.get('solver_atol', self._solver_atol) + if 'solver_atol' in self.conf: + del self.conf['solver_atol'] + # type and path checking on file paths if isinstance(self.conf['runoff_volumes_file'], str): self.conf['runoff_volumes_file'] = [self.conf['runoff_volumes_file'], ] @@ -483,7 +491,7 @@ def _router(self, dates: np.array, runoffs: np.array, q_init: np.array, r_init: return outflow_array def _solver(self, rhs: np.array, q_t: np.array) -> np.array: - return scipy.sparse.linalg.cgs(self.lhs, rhs, x0=q_t, atol=1e-3, rtol=1e-3)[0] + return scipy.sparse.linalg.cgs(self.lhs, rhs, x0=q_t, atol=self._solver_atol)[0] def _calibration_objective(self, iteration: np.array, *, observed: pd.DataFrame, diff --git a/river_route/__metadata__.py b/river_route/__metadata__.py index f0542a8..55ec9c8 100644 --- a/river_route/__metadata__.py +++ b/river_route/__metadata__.py @@ -1,3 +1,3 @@ -__version__ = '0.10.0' +__version__ = '0.11.0' __author__ = 'Riley Hales PhD' __url__ = 'https://github.com/rileyhales/river-route'