Skip to content

Commit

Permalink
Added test to capture errors and warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
lisawim committed Oct 27, 2023
1 parent 2904b0d commit 2f359f3
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 18 deletions.
24 changes: 12 additions & 12 deletions pySDC/implementations/problem_classes/AllenCahn_1D_FD.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,13 @@ def solve_system(self, rhs, factor, u0, t):
# u -= gmres(dg, g, x0=z, tol=self.lin_tol)[0]
# increase iteration count
n += 1
self.work_counters['newton']
self.work_counters['newton']()

if np.isnan(res) and self.stop_at_nan:
raise ProblemError('Newton got nan after %i iterations, aborting...' % n)
elif np.isnan(res):
self.logger.warning('Newton got nan after %i iterations...' % n)

print(f'{type(self).__name__}')
if n == self.newton_maxiter:
self.logger.warning('Newton did not converge after %i iterations, error is %s' % (n, res))

Expand Down Expand Up @@ -221,7 +221,7 @@ def eval_f(self, u, t):
- 2.0 / self.eps**2 * u * (1.0 - u) * (1.0 - 2 * u)
- 6.0 * self.dw * u * (1.0 - u)
)
self.work_counters['rhs']
self.work_counters['rhs']()
return f

def u_exact(self, t):
Expand Down Expand Up @@ -293,7 +293,7 @@ def eval_f(self, u, t):
f = self.dtype_f(self.init)
f.impl[:] = self.A.dot(self.uext)[1:-1]
f.expl[:] = -2.0 / self.eps**2 * u * (1.0 - u) * (1.0 - 2 * u) - 6.0 * self.dw * u * (1.0 - u)
self.work_counters['rhs']
self.work_counters['rhs']()
return f

def solve_system(self, rhs, factor, u0, t):
Expand Down Expand Up @@ -424,7 +424,7 @@ def solve_system(self, rhs, factor, u0, t):
# u -= cg(dg, g, x0=z, tol=self.lin_tol)[0]
# increase iteration count
n += 1
self.work_counters['newton']
self.work_counters['newton']()

if np.isnan(res) and self.stop_at_nan:
raise ProblemError('Newton got nan after %i iterations, aborting...' % n)
Expand Down Expand Up @@ -466,7 +466,7 @@ def eval_f(self, u, t):
gprim = 1.0 / self.dx**2 * ((1.0 - a2) / (1.0 - a2 * (2.0 * u - 1.0) ** 2) - 1) * (2.0 * u - 1.0)
f = self.dtype_f(self.init)
f[:] = self.A.dot(self.uext)[1:-1] - 1.0 * gprim - 6.0 * self.dw * u * (1.0 - u)
self.work_counters['rhs']
self.work_counters['rhs']()

Check warning on line 469 in pySDC/implementations/problem_classes/AllenCahn_1D_FD.py

View check run for this annotation

Codecov / codecov/patch

pySDC/implementations/problem_classes/AllenCahn_1D_FD.py#L469

Added line #L469 was not covered by tests
return f


Expand Down Expand Up @@ -627,7 +627,7 @@ def solve_system(self, rhs, factor, u0, t):
# u -= gmres(dg, g, x0=z, tol=self.lin_tol)[0]
# increase iteration count
n += 1
self.work_counters['newton']
self.work_counters['newton']()

if np.isnan(res) and self.stop_at_nan:
raise ProblemError('Newton got nan after %i iterations, aborting...' % n)
Expand Down Expand Up @@ -660,7 +660,7 @@ def eval_f(self, u, t):
"""
f = self.dtype_f(self.init)
f[:] = self.A.dot(u) - 2.0 / self.eps**2 * u * (1.0 - u) * (1.0 - 2 * u) - 6.0 * self.dw * u * (1.0 - u)
self.work_counters['rhs']
self.work_counters['rhs']()
return f

def u_exact(self, t):
Expand Down Expand Up @@ -717,7 +717,7 @@ def __init__(
stop_at_nan=True,
):
super().__init__(nvars, dw, eps, newton_maxiter, newton_tol, interval, radius, stop_at_nan)
self.A -= sp.eye(nvars) * 0.0 / self.eps**2
self.A -= sp.eye(self.nvars) * 0.0 / self.eps**2

def solve_system(self, rhs, factor, u0, t):
r"""
Expand Down Expand Up @@ -767,7 +767,7 @@ def eval_f(self, u, t):
- 6.0 * self.dw * u * (1.0 - u)
+ 0.0 / self.eps**2 * u
)
self.work_counters['rhs']
self.work_counters['rhs']()
return f


Expand Down Expand Up @@ -855,7 +855,7 @@ def eval_f(self, u, t):
- 6.0 * self.dw * u * (1.0 - u)
+ 0.0 / self.eps**2 * u
)
self.work_counters['rhs']
self.work_counters['rhs']()
return f

def solve_system_2(self, rhs, factor, u0, t):
Expand Down Expand Up @@ -915,7 +915,7 @@ def solve_system_2(self, rhs, factor, u0, t):
# u -= gmres(dg, g, x0=z, tol=self.lin_tol)[0]
# increase iteration count
n += 1
self.work_counters['newton']
self.work_counters['newton']()

Check warning on line 918 in pySDC/implementations/problem_classes/AllenCahn_1D_FD.py

View check run for this annotation

Codecov / codecov/patch

pySDC/implementations/problem_classes/AllenCahn_1D_FD.py#L918

Added line #L918 was not covered by tests

if np.isnan(res) and self.stop_at_nan:
raise ProblemError('Newton got nan after %i iterations, aborting...' % n)
Expand Down
122 changes: 116 additions & 6 deletions pySDC/tests/test_problems/test_AllenCahn_1D_FD.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ def test_front_imex_vs_fully_implicit():
f_imex = f_tmp.impl + f_tmp.expl
f_full = full.eval_f(u0, t0)

assert np.allclose(f_imex, f_full), "Evaluation of right-hand side in semi-implicit case and in fully-implicit case do not match!"
assert np.allclose(
f_imex, f_full
), "Evaluation of right-hand side in semi-implicit case and in fully-implicit case do not match!"

# perform one time step and test the error
dt = 1e-4
Expand Down Expand Up @@ -56,7 +58,9 @@ def test_front_imex_vs_fully_implicit():
rhs_count_imex = imex.work_counters['rhs'].niter
rhs_count_full = full.work_counters['rhs'].niter

assert rhs_count_imex == rhs_count_full, "Number of right-hand side evaluations for semi-implicit vs fully-implicit do not match!"
assert (
rhs_count_imex == rhs_count_full
), "Number of right-hand side evaluations for semi-implicit vs fully-implicit do not match!"


@pytest.mark.base
Expand Down Expand Up @@ -87,8 +91,12 @@ def test_periodic_imex_vs_fully_implicit_vs_multi_implicit():
f_tmp_multi = multi.eval_f(u0, t0)
f_multi = f_tmp_multi.comp1 + f_tmp_multi.comp2

assert np.allclose(f_imex, f_full), "Evaluation of right-hand side in semi-implicit case and in fully-implicit case do not match!"
assert np.allclose(f_full, f_multi), "Evaluation of right-hand side in fully-implicit case and in multi-implicit case do not match!"
assert np.allclose(
f_imex, f_full
), "Evaluation of right-hand side in semi-implicit case and in fully-implicit case do not match!"
assert np.allclose(
f_full, f_multi
), "Evaluation of right-hand side in fully-implicit case and in multi-implicit case do not match!"

# perform one time step and check errors
dt = 1e-4
Expand Down Expand Up @@ -118,6 +126,108 @@ def test_periodic_imex_vs_fully_implicit_vs_multi_implicit():
rhs_count_full = full.work_counters['rhs'].niter
rhs_count_multi = multi.work_counters['rhs'].niter

assert rhs_count_imex == rhs_count_full, "Number of right-hand side evaluations for semi-implicit vs fully-implicit do not match!"
assert rhs_count_full == rhs_count_multi, "Number of right-hand side evaluations for fully-implicit vs multi-implicit do not match!"
assert (
rhs_count_imex == rhs_count_full
), "Number of right-hand side evaluations for semi-implicit vs fully-implicit do not match!"
assert (
rhs_count_full == rhs_count_multi
), "Number of right-hand side evaluations for fully-implicit vs multi-implicit do not match!"


@pytest.mark.base
@pytest.mark.parametrize('stop_at_nan', [True, False])
def test_capture_errors_and_warnings(caplog, stop_at_nan):
"""
Test if errors and warnings are raised correctly.
"""
import numpy as np
from pySDC.core.Errors import ProblemError
from pySDC.implementations.problem_classes.AllenCahn_1D_FD import (
allencahn_front_fullyimplicit,
allencahn_front_semiimplicit,
allencahn_front_finel,
allencahn_periodic_fullyimplicit,
allencahn_periodic_semiimplicit,
allencahn_periodic_multiimplicit,
)

newton_maxiter = 1
problem_params = {
'stop_at_nan': stop_at_nan,
'newton_tol': 1e-13,
'newton_maxiter': newton_maxiter,
}

full_front = allencahn_front_fullyimplicit(**problem_params)
imex_front = allencahn_front_semiimplicit(**problem_params)
finel_front = allencahn_front_finel(**problem_params)

full_periodic = allencahn_periodic_fullyimplicit(**problem_params)
imex_periodic = allencahn_periodic_semiimplicit(**problem_params)
multi_periodic = allencahn_periodic_multiimplicit(**problem_params)

t0 = 0.0
dt = 1e-3

u0_front = full_front.u_exact(t0)
u0_periodic = full_periodic.u_exact(t0)

args_front = {
'rhs': u0_front,
'factor': np.nan,
'u0': u0_front,
't': t0,
}

args_periodic = {
'rhs': u0_periodic,
'factor': np.nan,
'u0': u0_periodic,
't': t0,
}

if stop_at_nan:
# test if ProblemError is raised
with pytest.raises(ProblemError):
full_front.solve_system(**args_front)
imex_front.solve_system(**args_front)
finel_front.solve_system(**args_front)

with pytest.raises(ProblemError):
full_periodic.solve_system(**args_periodic)
imex_periodic.solve_system(**args_periodic)
multi_periodic.solve_system(**args_periodic)

else:
# test if warnings are raised when nan values arise
full_front.solve_system(**args_front)
assert f'Newton got nan after {newton_maxiter} iterations...' in caplog.text
assert 'Newton did not converge after 1 iterations, error is nan' in caplog.text
assert (
full_front.work_counters['newton'].niter == newton_maxiter
), 'Number of Newton iterations in fully-implicit front case does not match with maximum number of iterations!'
caplog.clear()

finel_front.solve_system(**args_front)
assert f'Newton got nan after {newton_maxiter} iterations...' in caplog.text
assert 'Newton did not converge after 1 iterations, error is nan' in caplog.text
assert (
finel_front.work_counters['newton'].niter == newton_maxiter
), "Number of Newton iterations in case of using Finel's trick does not match with maximum number of iterations!"
caplog.clear()

full_periodic.solve_system(**args_periodic)
assert f'Newton got nan after {newton_maxiter} iterations...' in caplog.text
assert 'Newton did not converge after 1 iterations, error is nan' in caplog.text
assert (
full_periodic.work_counters['newton'].niter == newton_maxiter
), 'Number of Newton iterations in fully-implicit periodic case does not match with maximum number of iterations!'
caplog.clear()

multi_periodic.solve_system(**args_periodic)
assert f'Newton got nan after {newton_maxiter} iterations...' in caplog.text
assert 'Newton did not converge after 1 iterations, error is nan' in caplog.text
assert (
multi_periodic.work_counters['newton'].niter == newton_maxiter
), 'Number of Newton iterations in multi-implicit periodic case does not match with maximum number of iterations!'
caplog.clear()

0 comments on commit 2f359f3

Please sign in to comment.