Skip to content

Commit

Permalink
Added option to skip dt change if insignificant (#482)
Browse files Browse the repository at this point in the history
  • Loading branch information
brownbaerchen authored Sep 16, 2024
1 parent 32549d9 commit f1b8fbd
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def dependencies(self, controller, description, **kwargs):
Returns:
None
"""
step_limiter_keys = ['dt_min', 'dt_max', 'dt_slope_min', 'dt_slope_max']
step_limiter_keys = ['dt_min', 'dt_max', 'dt_slope_min', 'dt_slope_max', 'dt_rel_min_slope']
available_keys = [me for me in step_limiter_keys if me in self.params.__dict__.keys()]

if len(available_keys) > 0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def dependencies(self, controller, description, **kwargs):
Returns:
None
"""
slope_limiter_keys = ['dt_slope_min', 'dt_slope_max']
slope_limiter_keys = ['dt_slope_min', 'dt_slope_max', 'dt_rel_min_slope']
available_keys = [me for me in slope_limiter_keys if me in self.params.__dict__.keys()]

if len(available_keys) > 0:
Expand Down Expand Up @@ -90,7 +90,9 @@ class StepSizeSlopeLimiter(ConvergenceController):
"""
Class to set limits to adaptive step size computation during run time
Please supply dt_min or dt_max in the params to limit in either direction
Please supply `dt_slope_min` or `dt_slope_max` in the params to limit in either direction.
You can also supply `dt_rel_min_slope` in order to keep the old step size in case the relative change is smaller
than this minimum.
"""

def setup(self, controller, params, description, **kwargs):
Expand All @@ -109,6 +111,7 @@ def setup(self, controller, params, description, **kwargs):
"control_order": 91,
"dt_slope_min": 0,
"dt_slope_max": np.inf,
"dt_rel_min_slope": 0,
}
return {**defaults, **super().setup(controller, params, description, **kwargs)}

Expand Down Expand Up @@ -143,5 +146,11 @@ def get_new_step_size(self, controller, S, **kwargs):
S,
)
L.status.dt_new = dt_new
elif abs(L.status.dt_new / L.params.dt - 1) < self.params.dt_rel_min_slope:
L.status.dt_new = L.params.dt
self.log(
f"Step size did not change sufficiently to warrant step size change, keeping {L.status.dt_new:.2e}",
S,
)

return None
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def get_controller(dt, num_nodes, useMPI, adaptivity, adaptivity_params, **kwarg
adaptivity_params (dict): Parameters for convergence controller
Returns:
(dict): Stats object generated during the run
(pySDC.Controller.controller): Controller used in the run
"""
from pySDC.implementations.problem_classes.polynomial_test_problem import polynomial_testequation
Expand Down
112 changes: 112 additions & 0 deletions pySDC/tests/test_convergence_controllers/test_step_size_limiter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import pytest


def get_controller(step_size_limier_params):
"""
Runs a single advection problem with certain parameters
Args:
step_size_limier_params (dict): Parameters for convergence controller
Returns:
(pySDC.Controller.controller): Controller used in the run
"""
from pySDC.implementations.problem_classes.polynomial_test_problem import polynomial_testequation
from pySDC.implementations.controller_classes.controller_nonMPI import controller_nonMPI
from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter

level_params = {}
level_params['dt'] = 1.0
level_params['restol'] = 1.0

sweeper_params = {}
sweeper_params['quad_type'] = 'GAUSS'
sweeper_params['num_nodes'] = 1
sweeper_params['do_coll_update'] = True

problem_params = {'degree': 10}

step_params = {}
step_params['maxiter'] = 0

controller_params = {}
controller_params['logger_level'] = 30

description = {}
description['problem_class'] = polynomial_testequation
description['problem_params'] = problem_params
description['sweeper_class'] = generic_implicit
description['sweeper_params'] = sweeper_params
description['level_params'] = level_params
description['step_params'] = step_params
description['convergence_controllers'] = {StepSizeLimiter: step_size_limier_params}

controller = controller_nonMPI(num_procs=1, controller_params=controller_params, description=description)

controller.add_convergence_controller(StepSizeLimiter, description, step_size_limier_params)

return controller


@pytest.mark.base
def test_step_size_slope_limiter():
from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeSlopeLimiter

params = {'dt_slope_max': 2, 'dt_slope_min': 1e-3, 'dt_rel_min_slope': 1e-1}
controller = get_controller(params)

limiter = controller.convergence_controllers[
[type(me) for me in controller.convergence_controllers].index(StepSizeSlopeLimiter)
]

S = controller.MS[0]
S.status.slot = 0
L = S.levels[0]
L.status.time = 0

L.params.dt = 1
L.status.dt_new = 3
limiter.get_new_step_size(controller, S)
assert L.status.dt_new == 2

L.params.dt = 1
L.status.dt_new = 0
limiter.get_new_step_size(controller, S)
assert L.status.dt_new == 1e-3

L.params.dt = 1
L.status.dt_new = 1 + 1e-3
limiter.get_new_step_size(controller, S)
assert L.status.dt_new == 1


@pytest.mark.base
def test_step_size_limiter():
from pySDC.implementations.convergence_controller_classes.step_size_limiter import StepSizeLimiter

params = {'dt_max': 2, 'dt_min': 0.5}
controller = get_controller(params)

limiter = controller.convergence_controllers[
[type(me) for me in controller.convergence_controllers].index(StepSizeLimiter)
]

S = controller.MS[0]
S.status.slot = 0
L = S.levels[0]
L.status.time = 0

L.params.dt = 1
L.status.dt_new = 3
limiter.get_new_step_size(controller, S)
assert L.status.dt_new == 2

L.params.dt = 1
L.status.dt_new = 0
limiter.get_new_step_size(controller, S)
assert L.status.dt_new == 0.5


if __name__ == '__main__':
test_step_size_slope_limiter()

0 comments on commit f1b8fbd

Please sign in to comment.