Skip to content

Commit

Permalink
Test for AdvectionDiffusionEquation_1D_FFT.py (#372)
Browse files Browse the repository at this point in the history
* Added test for AdvectionDiffusionEquation_1D_FFT.py

* Removed empty test function

* Moved dicts for error thresholds to separate function
  • Loading branch information
lisawim authored Nov 6, 2023
1 parent 13e6fa6 commit 53da80b
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np

from pySDC.core.Errors import ParameterError, ProblemError
from pySDC.core.Problem import ptype
from pySDC.core.Problem import ptype, WorkCounter
from pySDC.implementations.datatype_classes.mesh import mesh, imex_mesh


Expand Down Expand Up @@ -70,6 +70,8 @@ def __init__(self, nvars=256, c=1.0, freq=-1, nu=0.02, L=1.0):
self.ddx = kx * 1j
self.lap = -(kx**2)

self.work_counters['rhs'] = WorkCounter()

def eval_f(self, u, t):
"""
Routine to evaluate the right-hand side of the problem.
Expand All @@ -94,6 +96,7 @@ def eval_f(self, u, t):
f.impl[:] = np.fft.irfft(tmp_impl)
f.expl[:] = np.fft.irfft(tmp_expl)

self.work_counters['rhs']()
return f

def solve_system(self, rhs, factor, u0, t):
Expand Down Expand Up @@ -153,6 +156,8 @@ def u_exact(self, t):
for i in range(self.init[0]):
x = self.xvalues[i] - self.c * t + k * self.L
me[i] += np.sqrt(t00) / np.sqrt(t00 + t) * np.exp(-(x**2) / (4.0 * self.nu * (t00 + t)))
else:
raise ParameterError("There is no exact solution implemented for negative frequency and negative nu!")
return me


Expand All @@ -177,6 +182,9 @@ class advectiondiffusion1d_implicit(advectiondiffusion1d_imex):
This class has the same attributes as the class it inherits from.
"""

dtype_u = mesh
dtype_f = mesh

def eval_f(self, u, t):
"""
Routine to evaluate the right-hand side of the problem.
Expand All @@ -199,6 +207,7 @@ def eval_f(self, u, t):
tmp = self.nu * self.lap * tmp_u - self.c * self.ddx * tmp_u
f[:] = np.fft.irfft(tmp)

self.work_counters['rhs']
return f

def solve_system(self, rhs, factor, u0, t):
Expand Down
110 changes: 110 additions & 0 deletions pySDC/tests/test_problems/test_AdvectionDiffusionEquation_1D_FFT.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import pytest


def get_error_thresholds(freq, nu):
r"""
Returns the error thresholds for parameters ``nu`` and ``freq``.
Parameters
----------
freq : int
Wave number.
nu : float
Diffusion coefficient.
"""
e_tol_imex = {
-1: {
0.02: 0.011,
},
0: {
-0.02: 0.076,
0.02: 0.055,
},
1: {
-0.02: 0.0063,
0.02: 0.0063,
},
}

e_tol_full = {
-1: {
0.02: 0.00021,
},
0: {
-0.02: 0.078,
0.02: 0.064,
},
1: {
-0.02: 2.01e-05,
0.02: 2e-05,
},
}
return e_tol_imex[freq][nu], e_tol_full[freq][nu]


@pytest.mark.base
@pytest.mark.parametrize('freq', [-1, 0, 1])
@pytest.mark.parametrize('nu', [0.02, -0.02])
def test_imex_vs_implicit(freq, nu):
import numpy as np
from pySDC.core.Errors import ParameterError, ProblemError
from pySDC.implementations.problem_classes.AdvectionDiffusionEquation_1D_FFT import (
advectiondiffusion1d_imex,
advectiondiffusion1d_implicit,
)

problem_params = {
'nvars': 32,
'c': 1.0,
'freq': freq,
'nu': nu,
'L': 1.0,
}

imex = advectiondiffusion1d_imex(**problem_params)
fully_impl = advectiondiffusion1d_implicit(**problem_params)

t0 = 0.0
if freq < 0 and nu < 0:
# check if ParameterError is raised correctly for freq < 0 and nu < 0
with pytest.raises(ParameterError):
imex.u_exact(t0)
else:
# test if evaluations of right-hand side do match
u0 = imex.u_exact(t0)

tmp = imex.eval_f(u0, t0)
f_imex = tmp.expl + tmp.impl
f_full = fully_impl.eval_f(u0, t0)

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

# test if solving one time step satisfies a specific error threshold
dt = 1e-3
args = {
'rhs': u0,
'factor': dt,
'u0': u0,
't': t0,
}

u_ex = imex.u_exact(t0 + dt)

u_imex = imex.solve_system(**args)
u_full = fully_impl.solve_system(**args)

e_imex = abs(u_ex - u_imex)
e_full = abs(u_ex - u_full)

e_tol_imex, e_tol_full = get_error_thresholds(freq, nu)

assert e_imex < e_tol_imex, "Error is too large in semi-explicit case!"
assert e_full < e_tol_full, "Error is too large in fully-implicit case!"

# check if ProblemError is raised correctly in case if nvars % 2 != 0
problem_params.update({'nvars': 31})
with pytest.raises(ProblemError):
imex_test = advectiondiffusion1d_imex(**problem_params)
fully_impl_test = advectiondiffusion1d_implicit(**problem_params)
7 changes: 0 additions & 7 deletions pySDC/tests/test_problems/test_AllenCahn_1D_FD.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,3 @@ def test_capture_errors_and_warnings(caplog, stop_at_nan):
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()


@pytest.mark.base
def test_solve_system_with_reference():
"""
Computes a solution using the Newton solver and compares it with a Newton-Krylov solver as reference.
"""

0 comments on commit 53da80b

Please sign in to comment.