@@ -53,16 +53,17 @@ module foodie_integrator_lmm_ssp_vss
5353 trim (class_name_)// ' _steps_4_order_3' , &
5454 trim (class_name_)// ' _steps_5_order_3' ] ! < List of supported schemes.
5555
56- logical , parameter :: has_fast_mode_= .false . ! < Flag to check if integrator provides *fast mode* integrate.
56+ logical , parameter :: has_fast_mode_= .true . ! < Flag to check if integrator provides *fast mode* integrate.
5757
5858type, extends(integrator_object) :: integrator_lmm_ssp_vss
5959 ! < FOODIE integrator: provide an explicit class of Linear Multi-step Methods (LLM) with Strong Stability Preserving property and
6060 ! < variable stepsize (VSS), from 2nd to 3rd order accurate.
6161 ! <
6262 ! < @note The integrator must be created or initialized before used.
6363 private
64- integer (I_P), public :: steps= 0 ! < Number of time steps.
65- procedure (integrate_interface), pointer :: integrate_ = > integrate_order_2 ! < Integrate integrand field.
64+ integer (I_P), public :: steps= 0 ! < Number of time steps.
65+ procedure (integrate_interface), pointer :: integrate_ = > integrate_order_2 ! < Integrate integrand field.
66+ procedure (integrate_fast_interface), pointer :: integrate_fast_ = > integrate_order_2_fast ! < Integrate integrand field, fast.
6667 contains
6768 ! deferred methods
6869 procedure , pass(self) :: class_name ! < Return the class name of schemes.
@@ -75,10 +76,13 @@ module foodie_integrator_lmm_ssp_vss
7576 procedure , pass(self) :: destroy ! < Destroy the integrator.
7677 procedure , pass(self) :: initialize ! < Initialize (create) the integrator.
7778 procedure , pass(self) :: integrate ! < Integrate integrand field.
79+ procedure , pass(self) :: integrate_fast ! < Integrate integrand field, fast mode.
7880 procedure , pass(self) :: update_previous ! < Cyclic update previous time steps.
7981 ! private methods
80- procedure , pass(self), private :: integrate_order_2 ! < Integrate integrand field by 2nd order formula.
81- procedure , pass(self), private :: integrate_order_3 ! < Integrate integrand field by 3rd order formula.
82+ procedure , pass(self), private :: integrate_order_2 ! < Integrate integrand field by 2nd order formula.
83+ procedure , pass(self), private :: integrate_order_3 ! < Integrate integrand field by 3rd order formula.
84+ procedure , pass(self), private :: integrate_order_2_fast ! < Integrate integrand field by 2nd order formula, fast mode.
85+ procedure , pass(self), private :: integrate_order_3_fast ! < Integrate integrand field by 3rd order formula, fast mode.
8286endtype integrator_lmm_ssp_vss
8387
8488abstract interface
@@ -93,6 +97,18 @@ subroutine integrate_interface(self, U, previous, Dt, t, autoupdate)
9397 real (R_P), intent (in ) :: t(:) ! < Times.
9498 logical , optional , intent (in ) :: autoupdate ! < Perform cyclic autoupdate of previous time steps.
9599 end subroutine integrate_interface
100+
101+ subroutine integrate_fast_interface (self , U , previous , buffer , Dt , t , autoupdate )
102+ ! < Integrate field with LMM-SSP class scheme.
103+ import :: integrand_object, integrator_lmm_ssp_vss, R_P
104+ class(integrator_lmm_ssp_vss), intent (in ) :: self ! < Integrator.
105+ class(integrand_object), intent (inout ) :: U ! < Field to be integrated.
106+ class(integrand_object), intent (inout ) :: previous(1 :) ! < Previous time steps solutions of integrand field.
107+ class(integrand_object), intent (inout ) :: buffer ! < Temporary buffer for doing fast operation.
108+ real (R_P), intent (inout ) :: Dt(:) ! < Time steps.
109+ real (R_P), intent (in ) :: t(:) ! < Times.
110+ logical , optional , intent (in ) :: autoupdate ! < Perform cyclic autoupdate of previous time steps.
111+ end subroutine integrate_fast_interface
96112endinterface
97113
98114contains
@@ -195,18 +211,23 @@ subroutine initialize(self, scheme, stop_on_fail)
195211 case (' lmm_ssp_vss_steps_2_order_2' )
196212 self% steps = 2
197213 self% integrate_ = > integrate_order_2
214+ self% integrate_fast_ = > integrate_order_2_fast
198215 case (' lmm_ssp_vss_steps_3_order_2' )
199216 self% steps = 3
200217 self% integrate_ = > integrate_order_2
218+ self% integrate_fast_ = > integrate_order_2_fast
201219 case (' lmm_ssp_vss_steps_3_order_3' )
202220 self% steps = 3
203221 self% integrate_ = > integrate_order_3
222+ self% integrate_fast_ = > integrate_order_3_fast
204223 case (' lmm_ssp_vss_steps_4_order_3' )
205224 self% steps = 4
206225 self% integrate_ = > integrate_order_3
226+ self% integrate_fast_ = > integrate_order_3_fast
207227 case (' lmm_ssp_vss_steps_5_order_3' )
208228 self% steps = 5
209229 self% integrate_ = > integrate_order_3
230+ self% integrate_fast_ = > integrate_order_3_fast
210231 endselect
211232 else
212233 call self% trigger_error(error= ERROR_UNSUPPORTED_SCHEME, &
@@ -227,6 +248,19 @@ subroutine integrate(self, U, previous, Dt, t, autoupdate)
227248 call self% integrate_(U= U, previous= previous, Dt= Dt, t= t, autoupdate= autoupdate)
228249 end subroutine integrate
229250
251+ subroutine integrate_fast (self , U , previous , buffer , Dt , t , autoupdate )
252+ ! < Integrate field with LMM-SSP class scheme.
253+ class(integrator_lmm_ssp_vss), intent (in ) :: self ! < Integrator.
254+ class(integrand_object), intent (inout ) :: U ! < Field to be integrated.
255+ class(integrand_object), intent (inout ) :: previous(1 :) ! < Previous time steps solutions of integrand field.
256+ class(integrand_object), intent (inout ) :: buffer ! < Temporary buffer for doing fast operation.
257+ real (R_P), intent (inout ) :: Dt(:) ! < Time steps.
258+ real (R_P), intent (in ) :: t(:) ! < Times.
259+ logical , optional , intent (in ) :: autoupdate ! < Perform cyclic autoupdate of previous time steps.
260+
261+ call self% integrate_fast_(U= U, previous= previous, buffer= buffer, Dt= Dt, t= t, autoupdate= autoupdate)
262+ end subroutine integrate_fast
263+
230264 subroutine update_previous (self , U , previous , Dt )
231265 ! < Cyclic update previous time steps.
232266 class(integrator_lmm_ssp_vss), intent (in ) :: self ! < Integrator.
@@ -283,6 +317,54 @@ subroutine integrate_order_3(self, U, previous, Dt, t, autoupdate)
283317 if (autoupdate_) call self% update_previous(U= U, previous= previous, Dt= Dt)
284318 end subroutine integrate_order_3
285319
320+ subroutine integrate_order_2_fast (self , U , previous , buffer , Dt , t , autoupdate )
321+ ! < Integrate field with LMM-SSP-VSS 2nd order class scheme.
322+ class(integrator_lmm_ssp_vss), intent (in ) :: self ! < Integrator.
323+ class(integrand_object), intent (inout ) :: U ! < Field to be integrated.
324+ class(integrand_object), intent (inout ) :: previous(1 :) ! < Previous time steps solutions of integrand field.
325+ class(integrand_object), intent (inout ) :: buffer ! < Temporary buffer for doing fast operation.
326+ real (R_P), intent (inout ) :: Dt(:) ! < Time steps.
327+ real (R_P), intent (in ) :: t(:) ! < Times.
328+ logical , optional , intent (in ) :: autoupdate ! < Perform cyclic autoupdate of previous time steps.
329+ logical :: autoupdate_ ! < Perform cyclic autoupdate of previous time steps, dummy var.
330+ real (R_P) :: omega_ ! < Omega coefficient.
331+ real (R_P) :: omega_sq ! < Square of omega coefficient.
332+
333+ autoupdate_ = .true. ; if (present (autoupdate)) autoupdate_ = autoupdate
334+ omega_ = omega(Dt= Dt, s= self% steps-1 )
335+ omega_sq = omega_ * omega_
336+ call U% multiply_fast(lhs= previous(1 ), rhs= 1._R_P / omega_sq)
337+ call buffer% multiply_fast(lhs= previous(self% steps), rhs= (omega_sq - 1._R_P ) / omega_sq)
338+ call U% add_fast(lhs= U, rhs= buffer)
339+ buffer = previous(self% steps)
340+ call buffer% t_fast(t= t(self% steps))
341+ call buffer% multiply_fast(lhs= buffer, rhs= Dt(self% steps) * (omega_ + 1._R_P ) / omega_)
342+ call U% add_fast(lhs= U, rhs= buffer)
343+ if (autoupdate_) call self% update_previous(U= U, previous= previous, Dt= Dt)
344+ end subroutine integrate_order_2_fast
345+
346+ subroutine integrate_order_3_fast (self , U , previous , buffer , Dt , t , autoupdate )
347+ ! < Integrate field with LMM-SSP-VSS 3rd order class scheme, fast mode.
348+ class(integrator_lmm_ssp_vss), intent (in ) :: self ! < Integrator.
349+ class(integrand_object), intent (inout ) :: U ! < Field to be integrated.
350+ class(integrand_object), intent (inout ) :: previous(1 :) ! < Previous time steps solutions of integrand field.
351+ class(integrand_object), intent (inout ) :: buffer ! < Temporary buffer for doing fast operation.
352+ real (R_P), intent (inout ) :: Dt(:) ! < Time steps.
353+ real (R_P), intent (in ) :: t(:) ! < Times.
354+ logical , optional , intent (in ) :: autoupdate ! < Perform cyclic autoupdate of previous time steps.
355+ logical :: autoupdate_ ! < Perform cyclic autoupdate of previous time steps, dummy var.
356+ real (R_P) :: omega_ ! < Omega coefficient.
357+
358+ autoupdate_ = .true. ; if (present (autoupdate)) autoupdate_ = autoupdate
359+ omega_= omega(Dt= Dt, s= self% steps-1 )
360+ ! @TODO to be completed
361+ U = (previous(1 ) * ((3._R_P * omega_ + 2._R_P ) / omega_ ** 3 )) + &
362+ (previous(self% steps) * (((omega_ + 1._R_P ) ** 2 ) * (omega_ - 2._R_P ) / omega_ ** 3 )) + &
363+ (previous(1 )% t(t= t(1 )) * (Dt(self% steps) * (omega_ + 1._R_P ) / omega_ ** 2 )) + &
364+ (previous(self% steps)% t(t= t(self% steps)) * (Dt(self% steps) * (omega_ + 1._R_P ) ** 2 / omega_ ** 2 ))
365+ if (autoupdate_) call self% update_previous(U= U, previous= previous, Dt= Dt)
366+ end subroutine integrate_order_3_fast
367+
286368 ! private non TBP
287369 pure function dt_ratio (Dt , s ) result(ratio)
288370 ! < Return `Dt(n+s)/Dt(n+Ns)` ratio.
0 commit comments