From 153d1359801a4a7061e8b0e028dbca4ec6ffa2cb Mon Sep 17 00:00:00 2001 From: Thomas Baumann <39156931+brownbaerchen@users.noreply.github.com> Date: Mon, 6 Nov 2023 16:31:11 +0100 Subject: [PATCH] Cosmetic changes --- pySDC/core/Controller.py | 15 ++++++++------- pySDC/core/ConvergenceController.py | 2 +- pySDC/core/Problem.py | 3 +++ pySDC/helpers/problem_helper.py | 2 +- .../estimate_embedded_error.py | 12 ++++++++++-- pySDC/implementations/hooks/log_errors.py | 4 ++-- pySDC/implementations/problem_classes/Lorenz.py | 13 ++++++++++--- .../problem_classes/Van_der_Pol_implicit.py | 1 + .../sweeper_classes/imex_1st_order.py | 2 +- .../projects/Resilience/collocation_adaptivity.py | 7 ------- 10 files changed, 37 insertions(+), 24 deletions(-) diff --git a/pySDC/core/Controller.py b/pySDC/core/Controller.py index f9db913397..20b1175f3c 100644 --- a/pySDC/core/Controller.py +++ b/pySDC/core/Controller.py @@ -160,7 +160,7 @@ def dump_setup(self, step, controller_params, description): self.logger.info(out) out = '----------------------------------------------------------------------------------------------------\n\n' out += 'Controller: %s\n' % self.__class__ - for k, v in vars(self.params).items(): + for k, v in sorted(vars(self.params).items()): if not k.startswith('_'): if k in controller_params: out += '--> %s = %s\n' % (k, v) @@ -168,24 +168,25 @@ def dump_setup(self, step, controller_params, description): out += ' %s = %s\n' % (k, v) out += '\nStep: %s\n' % step.__class__ - for k, v in vars(step.params).items(): + for k, v in sorted(vars(step.params).items()): if not k.startswith('_'): if k in description['step_params']: out += '--> %s = %s\n' % (k, v) else: out += ' %s = %s\n' % (k, v) + out += f' Number of steps: {step.status.time_size}\n' out += ' Level: %s\n' % step.levels[0].__class__ for L in step.levels: out += ' Level %2i\n' % L.level_index - for k, v in vars(L.params).items(): + for k, v in sorted(vars(L.params).items()): if not k.startswith('_'): if k in description['level_params']: out += '--> %s = %s\n' % (k, v) else: out += ' %s = %s\n' % (k, v) out += '--> Problem: %s\n' % L.prob.__class__ - for k, v in L.prob.params.items(): + for k, v in sorted(L.prob.params.items()): if k in description['problem_params']: out += '--> %s = %s\n' % (k, v) else: @@ -193,7 +194,7 @@ def dump_setup(self, step, controller_params, description): out += '--> Data type u: %s\n' % L.prob.dtype_u out += '--> Data type f: %s\n' % L.prob.dtype_f out += '--> Sweeper: %s\n' % L.sweep.__class__ - for k, v in vars(L.sweep.params).items(): + for k, v in sorted(vars(L.sweep.params).items()): if not k.startswith('_'): if k in description['sweeper_params']: out += '--> %s = %s\n' % (k, v) @@ -206,14 +207,14 @@ def dump_setup(self, step, controller_params, description): out += '--> Base Transfer: %s\n' % step.base_transfer.__class__ else: out += ' Base Transfer: %s\n' % step.base_transfer.__class__ - for k, v in vars(step.base_transfer.params).items(): + for k, v in sorted(vars(step.base_transfer.params).items()): if not k.startswith('_'): if k in description['base_transfer_params']: out += '--> %s = %s\n' % (k, v) else: out += ' %s = %s\n' % (k, v) out += '--> Space Transfer: %s\n' % step.base_transfer.space_transfer.__class__ - for k, v in vars(step.base_transfer.space_transfer.params).items(): + for k, v in sorted(vars(step.base_transfer.space_transfer.params).items()): if not k.startswith('_'): if k in description['space_transfer_params']: out += '--> %s = %s\n' % (k, v) diff --git a/pySDC/core/ConvergenceController.py b/pySDC/core/ConvergenceController.py index 879f4a5ee4..d7c87330bf 100644 --- a/pySDC/core/ConvergenceController.py +++ b/pySDC/core/ConvergenceController.py @@ -44,7 +44,7 @@ def __init__(self, controller, params, description, **kwargs): """ self.params = Pars(self.setup(controller, params, description)) params_ok, msg = self.check_parameters(controller, params, description) - assert params_ok, msg + assert params_ok, f'{type(self).__name__} -- {msg}' self.dependencies(controller, description) self.logger = logging.getLogger(f"{type(self).__name__}") diff --git a/pySDC/core/Problem.py b/pySDC/core/Problem.py index 40b0738f9a..72ca45556e 100644 --- a/pySDC/core/Problem.py +++ b/pySDC/core/Problem.py @@ -35,6 +35,9 @@ def __call__(self, *args, **kwargs): def decrement(self): self.niter -= 1 + def __str__(self): + return f'{self.niter}' + class ptype(RegisterParams): """ diff --git a/pySDC/helpers/problem_helper.py b/pySDC/helpers/problem_helper.py index 0a5552f39e..31d1caeca2 100644 --- a/pySDC/helpers/problem_helper.py +++ b/pySDC/helpers/problem_helper.py @@ -164,7 +164,7 @@ def get_finite_difference_matrix( neumann_bc_order = par.pop('neumann_bc_order') assert len(par) == 0, f"unused BCs parameters : {par}" - # -- halh stencil width + # -- half stencil width sWidth = -min(steps) if iS == 0 else max(steps) # -- loop over lines of A that have to be modified diff --git a/pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py b/pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py index ab594ddae7..a4b51b4d5d 100644 --- a/pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py +++ b/pySDC/implementations/convergence_controller_classes/estimate_embedded_error.py @@ -49,7 +49,11 @@ def setup(self, controller, params, description, **kwargs): Returns: dict: Updated parameters """ - sweeper_type = 'RK' if RungeKutta in description['sweeper_class'].__mro__ else 'SDC' + sweeper_type = 'SDC' + if RungeKutta in description['sweeper_class'].__mro__: + sweeper_type = 'RK' + elif 'SweeperMPI' in [me.__name__ for me in description['sweeper_class'].__mro__]: + sweeper_type = 'MPI' return { "control_order": -80, "sweeper_type": sweeper_type, @@ -94,10 +98,13 @@ def estimate_embedded_error_serial(self, L): elif self.params.sweeper_type == "SDC": # order rises by one between sweeps, making this so ridiculously easy return abs(L.uold[-1] - L.u[-1]) + elif self.params.sweeper_type == 'MPI': + comm = L.sweep.comm + return comm.bcast(abs(L.uold[comm.rank + 1] - L.u[comm.rank + 1]), root=comm.size - 1) else: raise NotImplementedError( f"Don't know how to estimate embedded error for sweeper type \ -{self.params.sweeper_type}" +\"{self.params.sweeper_type}\"" ) def setup_status_variables(self, controller, **kwargs): @@ -139,6 +146,7 @@ def post_iteration_processing(self, controller, S, **kwargs): if S.status.iter > 0 or self.params.sweeper_type == "RK": for L in S.levels: L.status.error_embedded_estimate = max([self.estimate_embedded_error_serial(L), np.finfo(float).eps]) + self.debug(f'L.status.error_embedded_estimate={L.status.error_embedded_estimate:.5e}', S) return None diff --git a/pySDC/implementations/hooks/log_errors.py b/pySDC/implementations/hooks/log_errors.py index 8d19112f28..93329ebc4a 100644 --- a/pySDC/implementations/hooks/log_errors.py +++ b/pySDC/implementations/hooks/log_errors.py @@ -48,7 +48,7 @@ def log_global_error(self, step, level_number, suffix=''): iter=step.status.iter, sweep=L.status.sweep, type=f'e_global_rel{suffix}', - value=abs((u_ref - L.uend / u_ref)), + value=abs(u_ref - L.uend) / abs(u_ref), ) def log_local_error(self, step, level_number, suffix=''): @@ -195,7 +195,7 @@ def post_run(self, step, level_number): iter=step.status.iter, sweep=L.status.sweep, type='e_global_rel_post_run', - value=abs((u_num - u_ref) / u_ref), + value=abs(u_num - u_ref) / abs(u_ref), ) diff --git a/pySDC/implementations/problem_classes/Lorenz.py b/pySDC/implementations/problem_classes/Lorenz.py index 192e7482c5..5e222b26e0 100644 --- a/pySDC/implementations/problem_classes/Lorenz.py +++ b/pySDC/implementations/problem_classes/Lorenz.py @@ -1,6 +1,7 @@ import numpy as np from pySDC.core.Problem import ptype, WorkCounter from pySDC.implementations.datatype_classes.mesh import mesh +from pySDC.core.Errors import ConvergenceError class LorenzAttractor(ptype): @@ -57,13 +58,13 @@ class LorenzAttractor(ptype): dtype_u = mesh dtype_f = mesh - def __init__(self, sigma=10.0, rho=28.0, beta=8.0 / 3.0, newton_tol=1e-9, newton_maxiter=99): + def __init__(self, sigma=10.0, rho=28.0, beta=8.0 / 3.0, newton_tol=1e-9, newton_maxiter=99, stop_at_nan=True): """Initialization routine""" nvars = 3 # invoke super init, passing number of dofs, dtype_u and dtype_f super().__init__(init=(nvars, None, np.dtype('float64'))) - self._makeAttributeAndRegister('nvars', localVars=locals(), readOnly=True) + self._makeAttributeAndRegister('nvars', 'stop_at_nan', localVars=locals(), readOnly=True) self._makeAttributeAndRegister( 'sigma', 'rho', 'beta', 'newton_tol', 'newton_maxiter', localVars=locals(), readOnly=False ) @@ -141,7 +142,13 @@ def solve_system(self, rhs, dt, u0, t): # compute the residual and determine if we are done res = np.linalg.norm(G, np.inf) - if res <= self.newton_tol or np.isnan(res): + if res <= self.newton_tol: + break + if np.isnan(res) and self.stop_at_nan: + self.logger.warning('Newton got nan after %i iterations...' % _n) + raise ConvergenceError('Newton got nan after %i iterations, aborting...' % _n) + elif np.isnan(res): + self.logger.warning('Newton got nan after %i iterations...' % _n) break # assemble inverse of Jacobian J of G diff --git a/pySDC/implementations/problem_classes/Van_der_Pol_implicit.py b/pySDC/implementations/problem_classes/Van_der_Pol_implicit.py index df83c24f8b..14f9f5a019 100755 --- a/pySDC/implementations/problem_classes/Van_der_Pol_implicit.py +++ b/pySDC/implementations/problem_classes/Van_der_Pol_implicit.py @@ -165,6 +165,7 @@ def solve_system(self, rhs, dt, u0, t): self.work_counters['newton']() if np.isnan(res) and self.stop_at_nan: + self.logger.warning('Newton got nan after %i iterations...' % n) raise ProblemError('Newton got nan after %i iterations, aborting...' % n) elif np.isnan(res): self.logger.warning('Newton got nan after %i iterations...' % n) diff --git a/pySDC/implementations/sweeper_classes/imex_1st_order.py b/pySDC/implementations/sweeper_classes/imex_1st_order.py index b2239ec21a..bc9805119d 100644 --- a/pySDC/implementations/sweeper_classes/imex_1st_order.py +++ b/pySDC/implementations/sweeper_classes/imex_1st_order.py @@ -28,7 +28,7 @@ def __init__(self, params): params['QE'] = 'EE' # call parent's initialization routine - super(imex_1st_order, self).__init__(params) + super().__init__(params) # IMEX integration matrices self.QI = self.get_Qdelta_implicit(coll=self.coll, qd_type=self.params.QI) diff --git a/pySDC/projects/Resilience/collocation_adaptivity.py b/pySDC/projects/Resilience/collocation_adaptivity.py index 2ec723c294..b6de627817 100644 --- a/pySDC/projects/Resilience/collocation_adaptivity.py +++ b/pySDC/projects/Resilience/collocation_adaptivity.py @@ -55,13 +55,6 @@ } -def get_collocation_order(quad_type, num_nodes, node_type): - """ - Compute the maximal order achievable by a given collocation method - """ - pass - - # define a few hooks class LogSweeperParams(hooks): """