@@ -6,6 +6,7 @@ def get_composite_collocation_problem(L, M, N, alpha=0, dt=1e-1, problem='Dahlqu
66 from pySDC .implementations .hooks .log_errors import (
77 LogGlobalErrorPostRun ,
88 LogGlobalErrorPostStep ,
9+ LogGlobalErrorPostIter ,
910 )
1011
1112 if ParaDiag :
@@ -74,7 +75,7 @@ def get_composite_collocation_problem(L, M, N, alpha=0, dt=1e-1, problem='Dahlqu
7475
7576 controller_params = {}
7677 controller_params ['logger_level' ] = 15
77- controller_params ['hook_class' ] = [LogGlobalErrorPostRun , LogGlobalErrorPostStep ]
78+ controller_params ['hook_class' ] = [LogGlobalErrorPostRun , LogGlobalErrorPostStep , LogGlobalErrorPostIter ]
7879 controller_params ['mssdc_jac' ] = False
7980 controller_params ['alpha' ] = alpha
8081 controller_params ['average_jacobian' ] = average_jacobian
@@ -223,8 +224,45 @@ def test_ParaDiag_order(L, M, N, alpha):
223224 ), f'Got unexpected numerical order { num_order } instead of { expected_order } in ParaDiag'
224225
225226
227+ @pytest .mark .base
228+ @pytest .mark .parametrize ('L' , [4 , 12 ])
229+ @pytest .mark .parametrize ('M' , [2 , 3 ])
230+ @pytest .mark .parametrize ('N' , [1 ])
231+ @pytest .mark .parametrize ('alpha' , [1e-4 , 1e-2 ])
232+ def test_ParaDiag_convergence_rate (L , M , N , alpha ):
233+ r"""
234+ Test that the error in ParaDiag contracts as fast as expected.
235+
236+ The upper bound is \|u^{k+1} - u^*\| / \|u^k - u^*\| < \alpha / (1-\alpha).
237+ Here, we compare to the exact solution to the continuous problem rather than the exact solution of the collocation
238+ problem, which means the error stalls at time-discretization level. Therefore, we only check the contraction in the
239+ first ParaDiag iteration.
240+ """
241+ import numpy as np
242+ from pySDC .helpers .stats_helper import get_sorted
243+
244+ dt = 1e-2
245+ controller , prob = get_composite_collocation_problem (L , M , N , alpha , dt = dt , problem = 'Dahlquist' )
246+
247+ # setup initial conditions
248+ u0 = prob .u_exact (0 )
249+
250+ uend , stats = controller .run (u0 = u0 , t0 = 0 , Tend = L * dt )
251+
252+ # test that the convergence rate in the first iteration is sufficiently small.
253+ errors = get_sorted (stats , type = 'e_global_post_iteration' , sortby = 'iter' , time = (L - 1 ) * dt )
254+ convergence_rates = [errors [i + 1 ][1 ] / errors [i ][1 ] for i in range (len (errors ) - 1 )]
255+ convergence_rate = convergence_rates [0 ]
256+ convergence_bound = alpha / (1 - alpha )
257+
258+ assert (
259+ convergence_rate < convergence_bound
260+ ), f'Convergence rate { convergence_rate } exceeds upper bound of { convergence_bound } !'
261+
262+
226263if __name__ == '__main__' :
227- test_ParaDiag_vs_PFASST (4 , 3 , 2 , 'Dahlquist' )
264+ test_ParaDiag_convergence_rate (4 , 3 , 1 , 1e-4 )
265+ # test_ParaDiag_vs_PFASST(4, 3, 2, 'Dahlquist')
228266 # test_ParaDiag_convergence(4, 3, 1, 1e-4, 'vdp')
229267 # test_IMEX_ParaDiag_convergence(4, 3, 64, 1e-4)
230268 # test_ParaDiag_order(3, 3, 1, 1e-4)
0 commit comments