Skip to content

Commit f36a3d6

Browse files
committed
Merge branch 'feature/add-performance-mode' into develop
2 parents 753967b + cc57e35 commit f36a3d6

17 files changed

+1867
-242
lines changed

src/lib/foodie_integrand_object.f90

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ module foodie_integrand_object
4949
procedure(assignment_integrand), pass(lhs), deferred, public :: assign_integrand !< `=` operator.
5050
procedure(assignment_real), pass(lhs), deferred, public :: assign_real !< `= real` operator.
5151
generic, public :: assignment(=) => assign_integrand, assign_real !< Overloading `=` assignament.
52+
! public methods for fast operational mode, must be overridden
53+
procedure, pass(self), public :: t_fast !< Time derivative, residuals, fast mode.
54+
procedure, pass(opr), public :: integrand_add_integrand_fast !< `+` fast operator.
55+
generic, public :: add_fast => integrand_add_integrand_fast !< Overloading `add_fast` method.
56+
procedure, pass(opr), public :: integrand_multiply_integrand_fast !< `*` fast operator.
57+
procedure, pass(opr), public :: integrand_multiply_real_scalar_fast !< `* real_scalar` fast operator.
58+
generic, public :: multiply_fast => integrand_multiply_integrand_fast, &
59+
integrand_multiply_real_scalar_fast !< Overloading `multiply_fast` method.
60+
procedure, pass(opr), public :: integrand_subtract_integrand_fast !< `-` fast operator.
61+
generic, public :: subtract_fast => integrand_subtract_integrand_fast !< Overloading `subtract_fast` method.
5262
endtype integrand_object
5363

5464
abstract interface
@@ -57,9 +67,9 @@ module foodie_integrand_object
5767
function time_derivative(self, t) result(dState_dt)
5868
!< Time derivative function of integrand class, i.e. the residuals function.
5969
import :: integrand_object, R_P
60-
class(integrand_object), intent(in) :: self !< Integrand field.
61-
real(R_P), optional, intent(in) :: t !< Time.
62-
real(R_P), allocatable :: dState_dt(:) !< Result of the time derivative function of integrand field.
70+
class(integrand_object), intent(in) :: self !< Integrand field.
71+
real(R_P), intent(in), optional :: t !< Time.
72+
real(R_P), allocatable :: dState_dt(:) !< Result of the time derivative function of integrand field.
6373
endfunction time_derivative
6474

6575
! operators
@@ -125,4 +135,54 @@ pure subroutine assignment_real(lhs, rhs)
125135
real(R_P), intent(in) :: rhs(1:) !< Right hand side.
126136
endsubroutine assignment_real
127137
endinterface
138+
139+
contains
140+
! fast operators
141+
! time derivative
142+
subroutine t_fast(self, t)
143+
!< Time derivative function of integrand class, i.e. the residuals function. Fast mode acting directly on self.
144+
!<
145+
!< @note This procedure must be overridden, it does not implement anything.
146+
class(integrand_object), intent(inout) :: self !< Integrand field.
147+
real(R_P), intent(in), optional :: t !< Time.
148+
endsubroutine t_fast
149+
150+
! +
151+
pure subroutine integrand_add_integrand_fast(opr, lhs, rhs)
152+
!< `+` fast operator.
153+
!<
154+
!< @note This procedure must be overridden, it does not implement anything.
155+
class(integrand_object), intent(inout) :: opr !< Operator result.
156+
class(integrand_object), intent(in) :: lhs !< Left hand side.
157+
class(integrand_object), intent(in) :: rhs !< Right hand side.
158+
endsubroutine integrand_add_integrand_fast
159+
160+
! *
161+
pure subroutine integrand_multiply_integrand_fast(opr, lhs, rhs)
162+
!< `*` fast operator.
163+
!<
164+
!< @note This procedure must be overridden, it does not implement anything.
165+
class(integrand_object), intent(inout) :: opr !< Operator result.
166+
class(integrand_object), intent(in) :: lhs !< Left hand side.
167+
class(integrand_object), intent(in) :: rhs !< Right hand side.
168+
endsubroutine integrand_multiply_integrand_fast
169+
170+
pure subroutine integrand_multiply_real_scalar_fast(opr, lhs, rhs)
171+
!< `* real_scalar` fast operator.
172+
!<
173+
!< @note This procedure must be overridden, it does not implement anything.
174+
class(integrand_object), intent(inout) :: opr !< Operator result.
175+
class(integrand_object), intent(in) :: lhs !< Left hand side.
176+
real(R_P), intent(in) :: rhs !< Right hand side.
177+
endsubroutine integrand_multiply_real_scalar_fast
178+
179+
! -
180+
pure subroutine integrand_subtract_integrand_fast(opr, lhs, rhs)
181+
!< `-` fast operator.
182+
!<
183+
!< @note This procedure must be overridden, it does not implement anything.
184+
class(integrand_object), intent(inout) :: opr !< Operator result.
185+
class(integrand_object), intent(in) :: lhs !< Left hand side.
186+
class(integrand_object), intent(in) :: rhs !< Right hand side.
187+
endsubroutine integrand_subtract_integrand_fast
128188
endmodule foodie_integrand_object

src/lib/foodie_integrator_adams_bashforth.f90

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ module foodie_integrator_adams_bashforth
5353
trim(class_name_)//'_15', &
5454
trim(class_name_)//'_16'] !< List of supported schemes.
5555

56+
logical, parameter :: has_fast_mode_=.true. !< Flag to check if integrator provides *fast mode* integrate.
57+
5658
type, extends(integrator_object) :: integrator_adams_bashforth
5759
!< FOODIE integrator: provide an explicit class of Adams-Bashforth multi-step schemes, from 1st to 16th order accurate.
5860
!<
@@ -64,13 +66,15 @@ module foodie_integrator_adams_bashforth
6466
! deferred methods
6567
procedure, pass(self) :: class_name !< Return the class name of schemes.
6668
procedure, pass(self) :: description !< Return pretty-printed object description.
69+
procedure, pass(self) :: has_fast_mode !< Return .true. if the integrator class has *fast mode* integrate.
6770
procedure, pass(lhs) :: integr_assign_integr !< Operator `=`.
6871
procedure, pass(self) :: is_supported !< Return .true. if the integrator class support the given scheme.
6972
procedure, pass(self) :: supported_schemes !< Return the list of supported schemes.
7073
! public methods
7174
procedure, pass(self) :: destroy !< Destroy the integrator.
7275
procedure, pass(self) :: initialize !< Initialize (create) the integrator.
7376
procedure, pass(self) :: integrate !< Integrate integrand field.
77+
procedure, pass(self) :: integrate_fast !< Integrate integrand field, fast mode.
7478
procedure, pass(self) :: update_previous !< Cyclic update previous time steps.
7579
endtype integrator_adams_bashforth
7680

@@ -103,6 +107,14 @@ pure function description(self, prefix) result(desc)
103107
desc = desc//prefix_//' + '//supported_schemes_(ubound(supported_schemes_, dim=1))
104108
endfunction description
105109

110+
elemental function has_fast_mode(self)
111+
!< Return .true. if the integrator class has *fast mode* integrate.
112+
class(integrator_adams_bashforth), intent(in) :: self !< Integrator.
113+
logical :: has_fast_mode !< Inquire result.
114+
115+
has_fast_mode = has_fast_mode_
116+
endfunction has_fast_mode
117+
106118
pure subroutine integr_assign_integr(lhs, rhs)
107119
!< Operator `=`.
108120
class(integrator_adams_bashforth), intent(inout) :: lhs !< Left hand side.
@@ -351,11 +363,33 @@ subroutine integrate(self, U, previous, Dt, t, autoupdate)
351363

352364
autoupdate_ = .true. ; if (present(autoupdate)) autoupdate_ = autoupdate
353365
do s=1, self%steps
354-
U = U + previous(s)%t(t=t(s)) * (Dt * self%b(s))
366+
U = U + (previous(s)%t(t=t(s)) * (Dt * self%b(s)))
355367
enddo
356368
if (autoupdate_) call self%update_previous(U=U, previous=previous)
357369
endsubroutine integrate
358370

371+
subroutine integrate_fast(self, U, previous, buffer, Dt, t, autoupdate)
372+
!< Integrate field with Adams-Bashforth class scheme.
373+
class(integrator_adams_bashforth), intent(in) :: self !< Integrator.
374+
class(integrand_object), intent(inout) :: U !< Field to be integrated.
375+
class(integrand_object), intent(inout) :: previous(1:) !< Previous time steps solutions of integrand field.
376+
class(integrand_object), intent(inout) :: buffer !< Temporary buffer for doing fast operation.
377+
real(R_P), intent(in) :: Dt !< Time steps.
378+
real(R_P), intent(in) :: t(:) !< Times.
379+
logical, optional, intent(in) :: autoupdate !< Perform cyclic autoupdate of previous time steps.
380+
logical :: autoupdate_ !< Perform cyclic autoupdate of previous time steps, dummy var.
381+
integer(I_P) :: s !< Steps counter.
382+
383+
autoupdate_ = .true. ; if (present(autoupdate)) autoupdate_ = autoupdate
384+
do s=1, self%steps
385+
buffer = previous(s)
386+
call buffer%t_fast(t=t(s))
387+
call buffer%multiply_fast(lhs=buffer, rhs=Dt * self%b(s))
388+
call U%add_fast(lhs=U, rhs=buffer)
389+
enddo
390+
if (autoupdate_) call self%update_previous(U=U, previous=previous)
391+
endsubroutine integrate_fast
392+
359393
subroutine update_previous(self, U, previous)
360394
!< Cyclic update previous time steps.
361395
class(integrator_adams_bashforth), intent(in) :: self !< Integrator.

src/lib/foodie_integrator_adams_bashforth_moulton.f90

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ module foodie_integrator_adams_bashforth_moulton
105105
trim(class_name_)//'_15', &
106106
trim(class_name_)//'_16'] !< List of supported schemes.
107107

108+
logical, parameter :: has_fast_mode_=.true. !< Flag to check if integrator provides *fast mode* integrate.
109+
108110
type, extends(integrator_object) :: integrator_adams_bashforth_moulton
109111
!< FOODIE integrator: provide an explicit class of Adams-Bashforth-Moulton multi-step schemes, from 1st to 4rd order accurate.
110112
!<
@@ -117,14 +119,16 @@ module foodie_integrator_adams_bashforth_moulton
117119
! deferred methods
118120
procedure, pass(self) :: class_name !< Return the class name of schemes.
119121
procedure, pass(self) :: description !< Return pretty-printed object description.
122+
procedure, pass(self) :: has_fast_mode !< Return .true. if the integrator class has *fast mode* integrate.
120123
procedure, pass(lhs) :: integr_assign_integr !< Operator `=`.
121124
procedure, pass(self) :: is_supported !< Return .true. if the integrator class support the given scheme.
122125
procedure, pass(self) :: supported_schemes !< Return the list of supported schemes.
123126
! public methods
124-
procedure, pass(self) :: destroy !< Destroy the integrator.
125-
procedure, pass(self) :: initialize !< Initialize (create) the integrator.
126-
procedure, pass(self) :: integrate !< Integrate integrand field.
127-
procedure, pass(self) :: scheme_number !< Return the scheme number in the list of supported schemes.
127+
procedure, pass(self) :: destroy !< Destroy the integrator.
128+
procedure, pass(self) :: initialize !< Initialize (create) the integrator.
129+
procedure, pass(self) :: integrate !< Integrate integrand field.
130+
procedure, pass(self) :: integrate_fast !< Integrate integrand field.
131+
procedure, pass(self) :: scheme_number !< Return the scheme number in the list of supported schemes.
128132
endtype integrator_adams_bashforth_moulton
129133

130134
contains
@@ -156,6 +160,14 @@ pure function description(self, prefix) result(desc)
156160
desc = desc//prefix_//' + '//supported_schemes_(ubound(supported_schemes_, dim=1))
157161
endfunction description
158162

163+
elemental function has_fast_mode(self)
164+
!< Return .true. if the integrator class has *fast mode* integrate.
165+
class(integrator_adams_bashforth_moulton), intent(in) :: self !< Integrator.
166+
logical :: has_fast_mode !< Inquire result.
167+
168+
has_fast_mode = has_fast_mode_
169+
endfunction has_fast_mode
170+
159171
pure subroutine integr_assign_integr(lhs, rhs)
160172
!< Operator `=`.
161173
class(integrator_adams_bashforth_moulton), intent(inout) :: lhs !< Left hand side.
@@ -243,6 +255,22 @@ subroutine integrate(self, U, previous, Dt, t, iterations)
243255
call self%predictor%update_previous(U=U, previous=previous)
244256
endsubroutine integrate
245257

258+
subroutine integrate_fast(self, U, previous, buffer, Dt, t, iterations)
259+
!< Integrate field with Adams-Bashforth-Moulton class scheme, fast mode.
260+
class(integrator_adams_bashforth_moulton), intent(in) :: self !< Integrator.
261+
class(integrand_object), intent(inout) :: U !< Field to be integrated.
262+
class(integrand_object), intent(inout) :: previous(1:) !< Previous time steps solutions of integrand.
263+
class(integrand_object), intent(inout) :: buffer !< Temporary buffer for doing fast operation.
264+
real(R_P), intent(in) :: Dt !< Time steps.
265+
real(R_P), intent(in) :: t(:) !< Times.
266+
integer(I_P), intent(in), optional :: iterations !< Fixed point iterations of AM scheme.
267+
268+
call self%predictor%integrate_fast(U=U, previous=previous, buffer=buffer, Dt=Dt, t=t, autoupdate=.false.)
269+
call self%corrector%integrate_fast(U=U, previous=previous(2:), buffer=buffer, Dt=Dt, t=t, iterations=iterations, &
270+
autoupdate=.false.)
271+
call self%predictor%update_previous(U=U, previous=previous)
272+
endsubroutine integrate_fast
273+
246274
elemental function scheme_number(self, scheme)
247275
!< Return the scheme number in the list of supported schemes.
248276
class(integrator_adams_bashforth_moulton), intent(in) :: self !< Integrator.

src/lib/foodie_integrator_adams_moulton.f90

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ module foodie_integrator_adams_moulton
5454
trim(class_name_)//'_14', &
5555
trim(class_name_)//'_15'] !< List of supported schemes.
5656

57+
logical, parameter :: has_fast_mode_=.true. !< Flag to check if integrator provides *fast mode* integrate.
58+
5759
type, extends(integrator_object) :: integrator_adams_moulton
5860
!< FOODIE integrator: provide an explicit class of Adams-Moulton multi-step schemes, from 1st to 16th order accurate.
5961
!<
@@ -66,12 +68,14 @@ module foodie_integrator_adams_moulton
6668
procedure, pass(self) :: class_name !< Return the class name of schemes.
6769
procedure, pass(self) :: description !< Return pretty-printed object description.
6870
procedure, pass(lhs) :: integr_assign_integr !< Operator `=`.
71+
procedure, pass(self) :: has_fast_mode !< Return .true. if the integrator class has *fast mode* integrate.
6972
procedure, pass(self) :: is_supported !< Return .true. if the integrator class support the given scheme.
7073
procedure, pass(self) :: supported_schemes !< Return the list of supported schemes.
7174
! public methods
7275
procedure, pass(self) :: destroy !< Destroy the integrator.
7376
procedure, pass(self) :: initialize !< Initialize (create) the integrator.
7477
procedure, pass(self) :: integrate !< Integrate integrand field.
78+
procedure, pass(self) :: integrate_fast !< Integrate integrand field, fast mode.
7579
procedure, pass(self) :: update_previous !< Cyclic update previous time steps.
7680
endtype integrator_adams_moulton
7781

@@ -104,6 +108,14 @@ pure function description(self, prefix) result(desc)
104108
desc = desc//prefix_//' + '//supported_schemes_(ubound(supported_schemes_, dim=1))
105109
endfunction description
106110

111+
elemental function has_fast_mode(self)
112+
!< Return .true. if the integrator class has *fast mode* integrate.
113+
class(integrator_adams_moulton), intent(in) :: self !< Integrator.
114+
logical :: has_fast_mode !< Inquire result.
115+
116+
has_fast_mode = has_fast_mode_
117+
endfunction has_fast_mode
118+
107119
pure subroutine integr_assign_integr(lhs, rhs)
108120
!< Operator `=`.
109121
class(integrator_adams_moulton), intent(inout) :: lhs !< Left hand side.
@@ -355,23 +367,75 @@ subroutine integrate(self, U, previous, Dt, t, iterations, autoupdate)
355367
allocate(delta, mold=U)
356368
delta = previous(self%steps)
357369
do s=0, self%steps - 1
358-
delta = delta + previous(s+1)%t(t=t(s+1)) * (Dt * self%b(s))
370+
delta = delta + (previous(s+1)%t(t=t(s+1)) * (Dt * self%b(s)))
359371
enddo
360372
do s=1, iterations
361-
U = delta + U%t(t=t(self%steps) + Dt) * (Dt * self%b(self%steps))
373+
U = delta + (U%t(t=t(self%steps) + Dt) * (Dt * self%b(self%steps)))
362374
enddo
363375
else
364-
U = previous(self%steps) + U%t(t=t(self%steps) + Dt) * (Dt * self%b(self%steps))
376+
U = previous(self%steps) + (U%t(t=t(self%steps) + Dt) * (Dt * self%b(self%steps)))
365377
do s=0, self%steps - 1
366-
U = U + previous(s+1)%t(t=t(s+1)) * (Dt * self%b(s))
378+
U = U + (previous(s+1)%t(t=t(s+1)) * (Dt * self%b(s)))
367379
enddo
368380
endif
369381
if (autoupdate_) call self%update_previous(U=U, previous=previous)
370382
else
371-
U = U + U%t(t=t(1)) * (Dt * self%b(0))
383+
U = U + (U%t(t=t(1)) * (Dt * self%b(0)))
372384
endif
373385
endsubroutine integrate
374386

387+
subroutine integrate_fast(self, U, previous, buffer, Dt, t, iterations, autoupdate)
388+
!< Integrate field with Adams-Moulton class scheme, fast mode.
389+
class(integrator_adams_moulton), intent(in) :: self !< Integrator.
390+
class(integrand_object), intent(inout) :: U !< Field to be integrated.
391+
class(integrand_object), intent(inout) :: previous(1:) !< Previous time steps solutions of integrand field.
392+
class(integrand_object), intent(inout) :: buffer !< Temporary buffer for doing fast operation.
393+
real(R_P), intent(in) :: Dt !< Time steps.
394+
real(R_P), intent(in) :: t(:) !< Times.
395+
integer(I_P), intent(in), optional :: iterations !< Fixed point iterations.
396+
logical, intent(in), optional :: autoupdate !< Cyclic autoupdate of previous time steps flag.
397+
logical :: autoupdate_ !< Cyclic autoupdate of previous time steps flag, dummy var.
398+
class(integrand_object), allocatable :: delta !< Delta RHS for fixed point iterations.
399+
integer(I_P) :: s !< Steps counter.
400+
401+
autoupdate_ = .true. ; if (present(autoupdate)) autoupdate_ = autoupdate
402+
if (self%steps>0) then
403+
if (present(iterations)) then ! perform fixed point iterations
404+
allocate(delta, mold=U)
405+
delta = previous(self%steps)
406+
do s=0, self%steps - 1
407+
buffer = previous(s+1)
408+
call buffer%t_fast(t=t(s+1))
409+
call buffer%multiply_fast(lhs=buffer, rhs=Dt * self%b(s))
410+
call delta%add_fast(lhs=delta, rhs=buffer)
411+
enddo
412+
do s=1, iterations
413+
buffer = U
414+
call buffer%t_fast(t=t(self%steps) + Dt)
415+
call buffer%multiply_fast(lhs=buffer, rhs=Dt * self%b(self%steps))
416+
call U%add_fast(lhs=delta, rhs=buffer)
417+
enddo
418+
else
419+
buffer = U
420+
call buffer%t_fast(t=t(self%steps) + Dt)
421+
call buffer%multiply_fast(lhs=buffer, rhs=Dt * self%b(self%steps))
422+
call U%add_fast(lhs=previous(self%steps), rhs=buffer)
423+
do s=0, self%steps - 1
424+
buffer = previous(s+1)
425+
call buffer%t_fast(t=t(s+1))
426+
call buffer%multiply_fast(lhs=buffer, rhs=Dt * self%b(s))
427+
call U%add_fast(lhs=U, rhs=buffer)
428+
enddo
429+
endif
430+
if (autoupdate_) call self%update_previous(U=U, previous=previous)
431+
else
432+
buffer = U
433+
call buffer%t_fast(t=t(1))
434+
call buffer%multiply_fast(lhs=buffer, rhs=Dt * self%b(0))
435+
call U%add_fast(lhs=U, rhs=buffer)
436+
endif
437+
endsubroutine integrate_fast
438+
375439
subroutine update_previous(self, U, previous)
376440
!< Cyclic update previous time steps.
377441
class(integrator_adams_moulton), intent(in) :: self !< Integrator.

0 commit comments

Comments
 (0)