@@ -51,6 +51,7 @@ module oscillation_test_t
5151 real (R_P), allocatable :: tolerance(:) ! < Tolerance(s) exercised on local truncation error.
5252 logical :: errors_analysis= .false. ! < Flag for activating errors analysis.
5353 logical :: results= .false. ! < Flag for activating results saving.
54+ logical :: is_fast= .false. ! < Flag for activating fast schemes.
5455 contains
5556 ! public methods
5657 procedure , pass(self) :: execute ! < Execute selected test(s).
@@ -119,6 +120,7 @@ subroutine set_cli()
119120 examples = [" oscillation --scheme euler_explicit --save_results " , &
120121 " oscillation --scheme all -r " ])
121122 call cli% add(switch= ' --scheme' , switch_ab= ' -s' , help= ' integrator scheme used' , required= .false. , def= ' all' , act= ' store' )
123+ call cli% add(switch= ' --fast' , help= ' activate fast solvers' , required= .false. , act= ' store_true' , def= ' .false.' )
122124 call cli% add(switch= ' --iterations' , help= ' number of iterations for implicit schemes' , required= .false. , act= ' store' , def= ' 5' )
123125 call cli% add(switch= ' --frequency' , switch_ab= ' -f' , help= ' oscillation frequency' , required= .false. , def= ' 1e-4' , act= ' store' )
124126 call cli% add(switch= ' --time_step' , switch_ab= ' -Dt' , nargs= ' +' , help= ' time step' , required= .false. , def= ' 100.d0' , act= ' store' )
@@ -140,6 +142,7 @@ subroutine parse_cli()
140142
141143 call self% cli% parse(error= self% error)
142144 call self% cli% get(switch= ' -s' , val= self% scheme, error= self% error) ; if (self% error/= 0 ) stop
145+ call self% cli% get(switch= ' --fast' , val= self% is_fast, error= self% error) ; if (self% error/= 0 ) stop
143146 call self% cli% get(switch= ' --iterations' , val= self% implicit_iterations, error= self% error) ; if (self% error/= 0 ) stop
144147 call self% cli% get(switch= ' --stages' , val= self% stages, error= self% error) ; if (self% error/= 0 ) stop
145148 call self% cli% get(switch= ' -f' , val= self% frequency, error= self% error) ; if (self% error/= 0 ) stop
@@ -277,39 +280,78 @@ subroutine initialize_test
277280 type (integrator_runge_kutta_lssp) :: int_runge_kutta_lssp ! < Linear Runge-Kutta SSP integrator.
278281 type (integrator_runge_kutta_ssp) :: int_runge_kutta_ssp ! < Runge Kutta-SSP integrator.
279282
280- if (index (trim (adjustl (scheme)), trim (int_adams_bashforth_moulton% class_name())) > 0 ) then
281- integrate = > integrate_adams_bashforth_moulton
282- elseif (index (trim (adjustl (scheme)), trim (int_adams_bashforth% class_name())) > 0 ) then
283- integrate = > integrate_adams_bashforth
284- elseif (index (trim (adjustl (scheme)), trim (int_adams_moulton% class_name())) > 0 ) then
285- integrate = > integrate_adams_moulton
286- elseif (index (trim (adjustl (scheme)), trim (int_back_df% class_name())) > 0 ) then
287- integrate = > integrate_back_df
288- elseif (index (trim (adjustl (scheme)), trim (int_euler_explicit% class_name())) > 0 ) then
289- integrate = > integrate_euler_explicit
290- elseif (index (trim (adjustl (scheme)), trim (int_leapfrog% class_name())) > 0 ) then
291- integrate = > integrate_leapfrog
292- elseif (index (trim (adjustl (scheme)), trim (int_lmm_ssp_vss% class_name())) > 0 ) then
293- integrate = > integrate_lmm_ssp_vss
294- elseif (index (trim (adjustl (scheme)), trim (int_lmm_ssp% class_name())) > 0 ) then
295- integrate = > integrate_lmm_ssp
296- elseif (index (trim (adjustl (scheme)), trim (int_ms_runge_kutta_ssp% class_name())) > 0 ) then
297- integrate = > integrate_ms_runge_kutta_ssp
298- elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_emd% class_name())) > 0 ) then
299- integrate = > integrate_runge_kutta_emd
300- elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_lssp% class_name())) > 0 ) then
301- integrate = > integrate_runge_kutta_lssp
302- elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_ls% class_name())) > 0 ) then
303- integrate = > integrate_runge_kutta_ls
304- elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_ssp% class_name())) > 0 ) then
305- integrate = > integrate_runge_kutta_ssp
306- endif
307- if (index (trim (adjustl (scheme)), trim (int_runge_kutta_emd% class_name())) > 0 ) then
308- if (allocated (error)) deallocate (error) ; allocate (error(1 :space_dimension, 1 :size (self% tolerance)))
309- if (allocated (Dt_mean)) deallocate (Dt_mean) ; allocate (Dt_mean(1 :size (error, dim= 2 )))
283+ if (self% is_fast) then
284+ if (index (trim (adjustl (scheme)), trim (int_adams_bashforth_moulton% class_name())) > 0 ) then
285+ integrate = > integrate_adams_bashforth_moulton
286+ elseif (index (trim (adjustl (scheme)), trim (int_adams_bashforth% class_name())) > 0 ) then
287+ integrate = > integrate_adams_bashforth_fast
288+ elseif (index (trim (adjustl (scheme)), trim (int_adams_bashforth% class_name())) > 0 ) then
289+ integrate = > integrate_adams_bashforth
290+ elseif (index (trim (adjustl (scheme)), trim (int_adams_moulton% class_name())) > 0 ) then
291+ integrate = > integrate_adams_moulton
292+ elseif (index (trim (adjustl (scheme)), trim (int_back_df% class_name())) > 0 ) then
293+ integrate = > integrate_back_df
294+ elseif (index (trim (adjustl (scheme)), trim (int_euler_explicit% class_name())) > 0 ) then
295+ integrate = > integrate_euler_explicit
296+ elseif (index (trim (adjustl (scheme)), trim (int_leapfrog% class_name())) > 0 ) then
297+ integrate = > integrate_leapfrog
298+ elseif (index (trim (adjustl (scheme)), trim (int_lmm_ssp_vss% class_name())) > 0 ) then
299+ integrate = > integrate_lmm_ssp_vss
300+ elseif (index (trim (adjustl (scheme)), trim (int_lmm_ssp% class_name())) > 0 ) then
301+ integrate = > integrate_lmm_ssp
302+ elseif (index (trim (adjustl (scheme)), trim (int_ms_runge_kutta_ssp% class_name())) > 0 ) then
303+ integrate = > integrate_ms_runge_kutta_ssp
304+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_emd% class_name())) > 0 ) then
305+ integrate = > integrate_runge_kutta_emd
306+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_lssp% class_name())) > 0 ) then
307+ integrate = > integrate_runge_kutta_lssp
308+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_ls% class_name())) > 0 ) then
309+ integrate = > integrate_runge_kutta_ls
310+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_ssp% class_name())) > 0 ) then
311+ integrate = > integrate_runge_kutta_ssp
312+ endif
313+ if (index (trim (adjustl (scheme)), trim (int_runge_kutta_emd% class_name())) > 0 ) then
314+ if (allocated (error)) deallocate (error) ; allocate (error(1 :space_dimension, 1 :size (self% tolerance)))
315+ if (allocated (Dt_mean)) deallocate (Dt_mean) ; allocate (Dt_mean(1 :size (error, dim= 2 )))
316+ else
317+ if (allocated (error)) deallocate (error) ; allocate (error(1 :space_dimension, 1 :size (self% Dt)))
318+ endif
310319 else
311- if (allocated (error)) deallocate (error) ; allocate (error(1 :space_dimension, 1 :size (self% Dt)))
320+ if (index (trim (adjustl (scheme)), trim (int_adams_bashforth_moulton% class_name())) > 0 ) then
321+ integrate = > integrate_adams_bashforth_moulton
322+ elseif (index (trim (adjustl (scheme)), trim (int_adams_bashforth% class_name())) > 0 ) then
323+ integrate = > integrate_adams_bashforth
324+ elseif (index (trim (adjustl (scheme)), trim (int_adams_moulton% class_name())) > 0 ) then
325+ integrate = > integrate_adams_moulton
326+ elseif (index (trim (adjustl (scheme)), trim (int_back_df% class_name())) > 0 ) then
327+ integrate = > integrate_back_df
328+ elseif (index (trim (adjustl (scheme)), trim (int_euler_explicit% class_name())) > 0 ) then
329+ integrate = > integrate_euler_explicit
330+ elseif (index (trim (adjustl (scheme)), trim (int_leapfrog% class_name())) > 0 ) then
331+ integrate = > integrate_leapfrog
332+ elseif (index (trim (adjustl (scheme)), trim (int_lmm_ssp_vss% class_name())) > 0 ) then
333+ integrate = > integrate_lmm_ssp_vss
334+ elseif (index (trim (adjustl (scheme)), trim (int_lmm_ssp% class_name())) > 0 ) then
335+ integrate = > integrate_lmm_ssp
336+ elseif (index (trim (adjustl (scheme)), trim (int_ms_runge_kutta_ssp% class_name())) > 0 ) then
337+ integrate = > integrate_ms_runge_kutta_ssp
338+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_emd% class_name())) > 0 ) then
339+ integrate = > integrate_runge_kutta_emd
340+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_lssp% class_name())) > 0 ) then
341+ integrate = > integrate_runge_kutta_lssp
342+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_ls% class_name())) > 0 ) then
343+ integrate = > integrate_runge_kutta_ls
344+ elseif (index (trim (adjustl (scheme)), trim (int_runge_kutta_ssp% class_name())) > 0 ) then
345+ integrate = > integrate_runge_kutta_ssp
346+ endif
347+ if (index (trim (adjustl (scheme)), trim (int_runge_kutta_emd% class_name())) > 0 ) then
348+ if (allocated (error)) deallocate (error) ; allocate (error(1 :space_dimension, 1 :size (self% tolerance)))
349+ if (allocated (Dt_mean)) deallocate (Dt_mean) ; allocate (Dt_mean(1 :size (error, dim= 2 )))
350+ else
351+ if (allocated (error)) deallocate (error) ; allocate (error(1 :space_dimension, 1 :size (self% Dt)))
352+ endif
312353 endif
354+
313355 error = 0.0_R_P
314356 if (self% errors_analysis) then
315357 if (allocated (order)) deallocate (order) ; allocate (order(1 :space_dimension, 1 :size (error, dim= 2 )- 1 ))
@@ -373,6 +415,63 @@ subroutine integrate_adams_bashforth(scheme, frequency, final_time, solution, er
373415 error = error_L2(frequency= frequency, solution= solution(:, 0 :last_step))
374416 end subroutine integrate_adams_bashforth
375417
418+ subroutine integrate_adams_bashforth_fast (scheme , frequency , final_time , solution , error , last_step , iterations , Dt , tolerance , &
419+ stages )
420+ ! < Integrate domain by means of the Adams-Bashforth scheme.
421+ character (* ), intent (in ) :: scheme ! < Selected scheme.
422+ real (R_P), intent (in ) :: frequency ! < Oscillation frequency.
423+ real (R_P), intent (in ) :: final_time ! < Final integration time.
424+ real (R_P), allocatable , intent (out ) :: solution(:,:) ! < Solution at each time step, X-Y.
425+ real (R_P), intent (out ) :: error(1 :) ! < Error (norm L2) with respect the exact solution.
426+ integer (I_P), intent (out ) :: last_step ! < Last time step computed.
427+ integer (I_P), intent (in ), optional :: iterations ! < Number of fixed point iterations.
428+ real (R_P), intent (in ), optional :: Dt ! < Time step.
429+ real (R_P), intent (in ), optional :: tolerance ! < Local error tolerance.
430+ integer (I_P), intent (in ), optional :: stages ! < Number of stages.
431+ type (integrator_adams_bashforth) :: integrator ! < The integrator.
432+ type (integrator_runge_kutta_ssp) :: integrator_rk ! < RK integrator for starting non self-starting integrators.
433+ type (oscillator) :: domain ! < Oscillation field.
434+ type (oscillator), allocatable :: rk_stage(:) ! < Runge-Kutta stages.
435+ type (oscillator), allocatable :: previous(:) ! < Previous time steps solutions.
436+ type (oscillator) :: buffer ! < Buffer oscillation field.
437+ integer :: step ! < Time steps counter.
438+
439+ call domain% init(initial_state= initial_state, frequency= frequency)
440+
441+ if (allocated (solution)) deallocate (solution) ; allocate (solution(0 :space_dimension, 0 :int (final_time/ Dt)))
442+ solution = 0.0_R_P
443+ solution(1 :, 0 ) = domain% output()
444+
445+ call integrator% initialize(scheme= scheme)
446+ if (allocated (previous)) deallocate (previous) ; allocate (previous(1 :integrator% steps))
447+
448+ call integrator_rk% initialize(scheme= ' runge_kutta_ssp_stages_5_order_4' )
449+ if (allocated (rk_stage)) deallocate (rk_stage) ; allocate (rk_stage(1 :integrator_rk% stages))
450+
451+ step = 0
452+ do while (solution(0 , step) < final_time .and. step < ubound (solution, dim= 2 ))
453+ step = step + 1
454+
455+ if (integrator% steps >= step) then
456+ call integrator_rk% integrate(U= domain, stage= rk_stage, Dt= Dt, t= solution(0 , step))
457+ previous(step) = domain
458+ else
459+ call integrator% integrate_fast(U= domain, &
460+ previous= previous, &
461+ buffer= buffer, &
462+ Dt= Dt, &
463+ t= solution(0 , step- integrator% steps:step-1 ))
464+ endif
465+
466+ solution(0 , step) = step * Dt
467+
468+ solution(1 :, step) = domain% output()
469+ enddo
470+ last_step = step
471+
472+ error = error_L2(frequency= frequency, solution= solution(:, 0 :last_step))
473+ end subroutine integrate_adams_bashforth_fast
474+
376475 subroutine integrate_adams_bashforth_moulton (scheme , frequency , final_time , solution , error , last_step , iterations , Dt , &
377476 tolerance , stages )
378477 ! < Integrate domain by means of the Adams-Bashforth-Moulton scheme.
0 commit comments