Integrate domain by means of the given scheme.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
character(len=*), | intent(in) | :: | scheme | Selected scheme. |
||
real(kind=R_P), | intent(in) | :: | a | a coefficient. |
||
real(kind=R_P), | intent(in) | :: | b | b coefficient. |
||
real(kind=R_P), | intent(in) | :: | U0 | Initial state. |
||
real(kind=R_P), | intent(in) | :: | final_time | Final integration time. |
||
real(kind=R_P), | intent(in) | :: | Dt | Time step. |
||
integer(kind=I_P), | intent(in) | :: | iterations | Number of fixed point iterations. |
||
integer(kind=I_P), | intent(in) | :: | stages | Number of stages. |
||
logical, | intent(in) | :: | is_fast | Activate fast mode integration. |
||
real(kind=R_P), | intent(out), | allocatable | :: | solution(:,:) | Solution at each time step, X-Y. |
|
real(kind=R_P), | intent(out) | :: | error | Error (norm L2) with respect the exact solution. |
||
integer(kind=I_P), | intent(out) | :: | last_step | Last time step computed. |
subroutine integrate(scheme, a, b, U0, final_time, Dt, iterations, stages, is_fast, solution, error, last_step)
!< Integrate domain by means of the given scheme.
character(*), intent(in) :: scheme !< Selected scheme.
real(R_P), intent(in) :: a !< *a* coefficient.
real(R_P), intent(in) :: b !< *b* coefficient.
real(R_P), intent(in) :: U0 !< Initial state.
real(R_P), intent(in) :: final_time !< Final integration time.
real(R_P), intent(in) :: Dt !< Time step.
integer(I_P), intent(in) :: iterations !< Number of fixed point iterations.
integer(I_P), intent(in) :: stages !< Number of stages.
logical, intent(in) :: is_fast !< Activate fast mode integration.
real(R_P), allocatable, intent(out) :: solution(:,:) !< Solution at each time step, X-Y.
real(R_P), intent(out) :: error !< Error (norm L2) with respect the exact solution.
integer(I_P), intent(out) :: last_step !< Last time step computed.
class(integrator_object), allocatable :: integrator !< The integrator.
type(integrand_lcce) :: domain !< Linear constant coefficients equation field.
type(integrand_lcce), allocatable :: previous(:) !< Previous time steps solutions.
type(integrand_lcce), allocatable :: stage(:) !< Runge-Kutta stages.
type(integrand_lcce) :: buffer !< Buffer field.
type(integrand_lcce) :: filter !< Filter displacement.
integer :: step !< Time steps counter.
integer :: step_offset !< Time steps counter offset for slicing previous data array.
real(R_P), allocatable :: Dts(:) !< Time steps for variable stepsize.
real(R_P) :: Dt_a !< Adaptive time step.
call domain%initialize(a=a, b=b, U0=U0)
if (allocated(solution)) deallocate(solution) ; allocate(solution(0:domain%integrand_dimension(), 0:int(final_time/Dt)))
solution = 0.0_R_P
solution(1:, 0) = domain%output()
call foodie_integrator_factory(scheme=scheme, integrator=integrator, stages=stages, tolerance=1e2_R_P)
if (is_fast) call check_scheme_has_fast_mode(scheme=trim(adjustl(scheme)), integrator=integrator)
if (integrator%is_multistep()) allocate(previous(1:integrator%steps_number()))
if (integrator%is_multistage()) allocate(stage(1:integrator%stages_number()))
select type(integrator)
type is(integrator_adams_bashforth)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
else
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_adams_bashforth_moulton)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
else
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_adams_moulton)
if (allocated(previous)) deallocate(previous) ; allocate(previous(1:integrator%steps_number()+1))
if (integrator%steps_number()==0) then
step_offset = 1 ! for 0 step-(a convention)-solver offset is 1
else
step_offset = integrator%steps_number() ! for >0 step-solver offset is steps
endif
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
if (iterations>1) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dt, &
t=solution(0,step-step_offset:step-1), &
iterations=iterations)
else
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dt, &
t=solution(0,step-step_offset:step-1))
endif
else
if (iterations>1) then
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dt, &
t=solution(0,step-step_offset:step-1), &
iterations=iterations)
else
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dt, &
t=solution(0,step-step_offset:step-1))
endif
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_back_df)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
else
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_euler_explicit)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (is_fast) then
call integrator%integrate_fast(U=domain, buffer=buffer, Dt=Dt, t=solution(0, step))
else
call integrator%integrate(U=domain, Dt=Dt, t=solution(0, step))
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_leapfrog)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (index(scheme, 'raw') > 0 ) then
if (is_fast) then
call integrator%integrate_fast(U=domain, previous=previous, buffer=buffer, Dt=Dt, t=solution(0, step),filter=filter)
else
call integrator%integrate(U=domain, previous=previous, Dt=Dt, t=solution(0, step), filter=filter)
endif
else
if (is_fast) then
call integrator%integrate_fast(U=domain, previous=previous, buffer=buffer, Dt=Dt, t=solution(0, step))
else
call integrator%integrate(U=domain, previous=previous, Dt=Dt, t=solution(0, step))
endif
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_lmm_ssp)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
else
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_lmm_ssp_vss)
if (allocated(Dts)) deallocate(Dts) ; allocate(Dts(1:integrator%steps_number())) ; Dts = Dt
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
buffer=buffer, &
Dt=Dts, &
t=solution(0, step-integrator%steps_number():step-1))
else
call integrator%integrate(U=domain, &
previous=previous, &
Dt=Dts, &
t=solution(0, step-integrator%steps_number():step-1))
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_ms_runge_kutta_ssp)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (integrator%steps_number() >= step) then
domain = [domain%exact_solution(t=step * Dt)]
previous(step) = domain
else
if (is_fast) then
call integrator%integrate_fast(U=domain, &
previous=previous, &
stage=stage, &
buffer=buffer, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
else
call integrator%integrate(U=domain, &
previous=previous, &
stage=stage, &
Dt=Dt, &
t=solution(0, step-integrator%steps_number():step-1))
endif
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_runge_kutta_emd)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
Dt_a = Dt
if (is_fast) then
call integrator%integrate_fast(U=domain, stage=stage, buffer=buffer, Dt=Dt_a, t=solution(0, step))
else
call integrator%integrate(U=domain, stage=stage, Dt=Dt_a, t=solution(0, step))
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_runge_kutta_ls)
if (allocated(stage)) deallocate(stage) ; allocate(stage(1:integrator%registers_number()))
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (is_fast) then
call integrator%integrate_fast(U=domain, stage=stage, buffer=buffer, Dt=Dt, t=solution(0, step))
else
call integrator%integrate(U=domain, stage=stage, Dt=Dt, t=solution(0, step))
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_runge_kutta_lssp)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (is_fast) then
call integrator%integrate_fast(U=domain, stage=stage, buffer=buffer, Dt=Dt, t=solution(0, step))
else
call integrator%integrate(U=domain, stage=stage, Dt=Dt, t=solution(0, step))
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
type is(integrator_runge_kutta_ssp)
step = 0
do while(solution(0, step) < final_time .and. step < ubound(solution, dim=2))
step = step + 1
if (is_fast) then
call integrator%integrate_fast(U=domain, stage=stage, buffer=buffer, Dt=Dt, t=solution(0, step))
else
call integrator%integrate(U=domain, stage=stage, Dt=Dt, t=solution(0, step))
endif
solution(0, step) = step * Dt
solution(1:, step) = domain%output()
enddo
last_step = step
endselect
error = 0._R_P
do step=0, last_step
domain = solution(1:, step)
error = error + (domain%output() - domain%exact_solution(t=solution(0, step))) ** 2
enddo
error = sqrt(error)
endsubroutine integrate