timedisc_modeuler.f90
Go to the documentation of this file.
1 !#############################################################################
2 !# #
3 !# fosite - 3D hydrodynamical simulation program #
4 !# module: timedisc_modeuler.f90 #
5 !# #
6 !# Copyright (C) 2007-2018 #
7 !# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
8 !# Björn Sperling <sperling@astrophysik.uni-kiel.de> #
9 !# Jannes Klee <jklee@astrophysik.uni-kiel.de> #
10 !# #
11 !# This program is free software; you can redistribute it and/or modify #
12 !# it under the terms of the GNU General Public License as published by #
13 !# the Free Software Foundation; either version 2 of the License, or (at #
14 !# your option) any later version. #
15 !# #
16 !# This program is distributed in the hope that it will be useful, but #
17 !# WITHOUT ANY WARRANTY; without even the implied warranty of #
18 !# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
19 !# NON INFRINGEMENT. See the GNU General Public License for more #
20 !# details. #
21 !# #
22 !# You should have received a copy of the GNU General Public License #
23 !# along with this program; if not, write to the Free Software #
24 !# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
25 !# #
26 !#############################################################################
27 
28 !----------------------------------------------------------------------------!
39 !----------------------------------------------------------------------------!
42  USE mesh_base_mod
44  USE marray_base_mod
45  USE fluxes_base_mod
49  USE common_dict
50 #ifdef PARALLEL
51 #ifdef HAVE_MPI_MOD
52  USE mpi
53 #endif
54 #endif
55  IMPLICIT NONE
56 #ifdef PARALLEL
57 #ifdef HAVE_MPIF_H
58  include 'mpif.h'
59 #endif
60 #endif
61  !--------------------------------------------------------------------------!
62  PRIVATE
63  TYPE, EXTENDS (timedisc_base) :: timedisc_modeuler
64  CONTAINS
65  PROCEDURE :: inittimedisc_modeuler
66  PROCEDURE :: computecvar_modeuler
67  generic :: computecvar => computecvar_modeuler
68  PROCEDURE :: solveode
69  PROCEDURE :: finalize
70  END TYPE timedisc_modeuler
71  !--------------------------------------------------------------------------!
72  CHARACTER(LEN=32), PARAMETER :: odesolver_name = "modified Euler"
73  REAL, PARAMETER :: eta(3,3) = &
74  reshape((/ 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.75, 1.0/3.0 /),(/3,3/))
75  REAL, PARAMETER :: zeta(3,3) = &
76  reshape((/ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.5 /),(/3,3/))
77  !--------------------------------------------------------------------------!
78  PUBLIC :: &
79  ! types
81  ! constants
85  !--------------------------------------------------------------------------!
86 
87 CONTAINS
88 
89  SUBROUTINE inittimedisc_modeuler(this,Mesh,Physics,config,IO)
90  IMPLICIT NONE
91  !------------------------------------------------------------------------!
92  CLASS(timedisc_modeuler), INTENT(INOUT) :: this
93  CLASS(mesh_base), INTENT(INOUT) :: Mesh
94  CLASS(physics_base), INTENT(IN) :: Physics
95  TYPE(Dict_TYP), POINTER :: config, IO
96  !------------------------------------------------------------------------!
97  ! set default order
98  CALL getattr(config, "order", this%order, 3)
99 
100  CALL this%InitTimedisc(mesh,physics,config,io,modified_euler,odesolver_name)
101 
102  SELECT CASE(this%GetOrder())
103  CASE(1)
104  ! set relative error tolarance to value > 1.0
105  ! to disable adaptive step size control
106  ! (not available for 1st order scheme)
107  this%tol_rel = 10.0
108  this%tol_abs(:) = 1.0
109  CALL this%Warning("InitTimedisc_modeuler", &
110  "adaptive step size control not supported in 1st order scheme",0)
111  CASE(2,3)
112  IF (this%tol_rel.GT.1.0) &
113  CALL this%Warning("InitTimedisc_modeuler", &
114  "adaptive step size control disabled (tol_rel>1)",0)
115  CASE DEFAULT
116  CALL this%Error("InitTimedisc_modeuler","time order must be one of 1,2,3")
117  END SELECT
118  IF ((this%tol_rel.LT.0.0).OR.minval(this%tol_abs(:)).LT.0.0) &
119  CALL this%Error("InitTimedisc_modeuler", &
120  "error tolerance levels must be greater than 0")
121 
122  END SUBROUTINE inittimedisc_modeuler
123 
124 
125  SUBROUTINE solveode(this,Mesh,Physics,Sources,Fluxes,time,dt,err)
126  IMPLICIT NONE
127  !------------------------------------------------------------------------!
128  CLASS(timedisc_modeuler), INTENT(INOUT) :: this
129  CLASS(mesh_base), INTENT(IN) :: Mesh
130  CLASS(physics_base), INTENT(INOUT) :: Physics
131  CLASS(sources_base), POINTER :: Sources
132  CLASS(fluxes_base), INTENT(INOUT) :: Fluxes
133  REAL :: time,dt,err
134  !------------------------------------------------------------------------!
135  INTEGER :: n
136  INTEGER :: order
137  REAL :: t
138  TYPE var_typ
139  CLASS(marray_compound), POINTER :: var
140  END TYPE var_typ
141  TYPE(var_typ) :: p(4),c(4)
142  !------------------------------------------------------------------------!
143  INTENT(IN) :: time
144  INTENT(INOUT) :: dt,err
145  !------------------------------------------------------------------------!
146  t = time
147  order = this%GetOrder()
148  ! check if adaptive step size control is enabled
149  IF (this%tol_rel.GE.1.0) THEN
150  ! no adaptive step size control
151 !NEC$ UNROLL(3)
152  DO n=1,order
153  ! update time variable
154  t = time+zeta(n,order)*dt
155  ! time step update of cvar and bfluxes
156  CALL this%ComputeCVar(mesh,physics,fluxes,eta(n,order), &
157  t,dt,this%cold,this%pvar,this%cvar,this%rhs,this%cvar)
158  ! compute right hand side for next time step update
159  CALL this%ComputeRHS(mesh,physics,sources,fluxes,t,dt,&
160  this%pvar,this%cvar,check_nothing,this%rhs)
161  END DO
162  err = 0.0
163  dt = huge(dt)
164  ELSE
165  ! with adaptive step size control (2nd / 3rd order scheme)
166  p(1)%var => this%pvar
167  p(2)%var => this%ptmp ! store intermediate result for error control
168  p(3)%var => this%pvar
169  p(4)%var => this%pvar
170  c(1)%var => this%cvar
171  c(2)%var => this%ctmp ! store intermediate result for error control
172  c(3)%var => this%cvar
173  c(4)%var => this%cvar
174 !NEC$ UNROLL(3)
175  DO n=1,order
176  ! update time variable
177  t = time+zeta(n,order)*dt
178  ! time step update of cvar and bfluxes
179  CALL this%ComputeCVar(mesh,physics,fluxes,eta(n,order), &
180  t,dt,this%cold,p(n)%var,c(n)%var,this%rhs,c(n+1)%var)
181  ! for 3rd order scheme compute the 2nd order result with the same RHS
182  ! and store it in this%ctmp, bfluxes are not required
183  IF (n.EQ.2.AND.order.EQ.3) &
184  this%ctmp%data4d(:,:,:,:) = updatetimestep_modeuler(eta(2,2),dt,this%cold%data4d(:,:,:,:), &
185  this%ctmp%data4d(:,:,:,:),this%rhs%data4d(:,:,:,:))
186  ! compute right hand side for next time step update
187  IF (n.LT.order) &
188  CALL this%ComputeRHS(mesh,physics,sources,fluxes,t,dt,p(n+1)%var,c(n+1)%var,&
189  check_nothing,this%rhs)
190  END DO
191 
192  err = this%ComputeError(mesh,physics,this%cvar,this%ctmp)
193  dt = this%AdjustTimestep(err,dt)
194 
195  END IF
196 
197  END SUBROUTINE solveode
198 
199 
202  SUBROUTINE computecvar_modeuler(this,Mesh,Physics,Fluxes,eta,time,dt, &
203  cold,pvar,cvar,rhs,cnew)
204  IMPLICIT NONE
205  !------------------------------------------------------------------------!
206  CLASS(timedisc_modeuler), INTENT(INOUT) :: this
207  CLASS(mesh_base), INTENT(IN) :: Mesh
208  CLASS(physics_base), INTENT(INOUT) :: Physics
209  CLASS(fluxes_base), INTENT(INOUT) :: Fluxes
210  CLASS(marray_compound), INTENT(INOUT) :: cold,pvar,cvar,cnew,rhs
211  REAL :: eta,time,dt
212  !------------------------------------------------------------------------!
213  INTEGER :: i,j,k,l
214  !------------------------------------------------------------------------!
215  INTENT(IN) :: eta,time,dt
216  !------------------------------------------------------------------------!
217 !NEC$ NOVECTOR
218  DO l=1,physics%VNUM
219  ! use collapsed arrays for better vector performance
220  ! ATTENTION: yields garbage in ghost zones
221  ! -> overwritten in CenterBoundary called in timedisc_base::ComputeRHS
222  cnew%data2d(:,l) = updatetimestep_modeuler(eta,dt, &
223  cold%data2d(:,l),cvar%data2d(:,l),rhs%data2d(:,l))
224 
225  IF(mesh%INUM.GT.1) THEN
226  ! western and eastern boundary fluxes
227 !NEC$ IVDEP
228  DO k=mesh%KMIN,mesh%KMAX
229 !NEC$ IVDEP
230  DO j=mesh%JMIN,mesh%JMAX
231  ! time step update of boundary fluxes
232  fluxes%bxflux(j,k,1,l) = updatetimestep_modeuler(eta,dt,fluxes%bxfold(j,k,1,l), &
233  fluxes%bxflux(j,k,1,l),rhs%data4d(mesh%IMIN-mesh%IP1,j,k,l))
234  fluxes%bxflux(j,k,2,l) = updatetimestep_modeuler(eta,dt,fluxes%bxfold(j,k,2,l), &
235  fluxes%bxflux(j,k,2,l),rhs%data4d(mesh%IMAX+mesh%IP1,j,k,l))
236  END DO
237  END DO
238  END IF
239  IF(mesh%JNUM.GT.1) THEN
240  ! southern and northern boundary fluxes
241 !NEC$ IVDEP
242  DO i=mesh%IMIN,mesh%IMAX
243 !NEC$ IVDEP
244  DO k=mesh%KMIN,mesh%KMAX
245  ! time step update of boundary fluxes
246  fluxes%byflux(k,i,1,l) = updatetimestep_modeuler(eta,dt,fluxes%byfold(k,i,1,l), &
247  fluxes%byflux(k,i,1,l),rhs%data4d(i,mesh%JMIN-mesh%Jp1,k,l))
248  fluxes%byflux(k,i,2,l) = updatetimestep_modeuler(eta,dt,fluxes%byfold(k,i,2,l), &
249  fluxes%byflux(k,i,2,l),rhs%data4d(i,mesh%JMAX+mesh%Jp1,k,l))
250  END DO
251  END DO
252  END IF
253 
254  IF(mesh%KNUM.GT.1) THEN
255  ! bottom and top boundary fluxes
256 !NEC$ IVDEP
257  DO j=mesh%JMIN,mesh%JMAX
258  ! time step update of boundary fluxes
259 !NEC$ IVDEP
260  DO i=mesh%IMIN,mesh%IMAX
261  fluxes%bzflux(i,j,1,l) = updatetimestep_modeuler(eta,dt,fluxes%bzfold(i,j,1,l), &
262  fluxes%bzflux(i,j,1,l),rhs%data4d(i,j,mesh%KMIN-mesh%Kp1,l))
263  fluxes%bzflux(i,j,2,l) = updatetimestep_modeuler(eta,dt,fluxes%bzfold(i,j,2,l), &
264  fluxes%bzflux(i,j,2,l),rhs%data4d(i,j,mesh%KMAX+mesh%Kp1,l))
265  END DO
266  END DO
267  END IF
268  END DO
269  END SUBROUTINE computecvar_modeuler
270 
271 
272  SUBROUTINE finalize(this)
273  IMPLICIT NONE
274  !------------------------------------------------------------------------!
275  CLASS(timedisc_modeuler) :: this
276  !------------------------------------------------------------------------!
277  CALL this%Finalize_base()
278  END SUBROUTINE finalize
279 
280 
281  ELEMENTAL FUNCTION updatetimestep_modeuler(eta_n,dt,y0,yn,rhs) RESULT(y)
282  IMPLICIT NONE
283  !------------------------------------------------------------------------!
284  REAL, INTENT(IN) :: eta_n,dt,y0,yn,rhs
285  REAL :: y
286  !------------------------------------------------------------------------!
287  ! ATTENTION:
288  ! The time step update is computed according to:
289  ! y = eta_n * y0 + (1.0 - eta_n) * (yn - dt * rhs)
290  ! but to minimize the truncation error it is essential to sort the terms
291  ! in this way:
292  y = yn-dt*rhs+eta_n*(y0-yn+dt*rhs)
293  END FUNCTION updatetimestep_modeuler
294 
295 END MODULE timedisc_modeuler_mod
integer, parameter, public check_pmin
integer, parameter, public check_all
character(len=32), parameter odesolver_name
generic source terms module providing functionaly common to all source terms
integer, parameter, public dtcause_cfl
derived class for compound of mesh arrays
base class for mesh arrays
Definition: marray_base.f90:36
elemental real function updatetimestep_modeuler(eta_n, dt, y0, yn, rhs)
real, dimension(3, 3), parameter zeta
subroutine solveode(this, Mesh, Physics, Sources, Fluxes, time, dt, err)
integer, parameter, public check_nothing
integer, parameter, public dtcause_smallerr
integer, parameter, public check_csound
integer, parameter, public check_tmin
real, dimension(3, 3), parameter eta
integer, parameter, public dtcause_erradj
integer, parameter, public modified_euler
Basic physics module.
integer, parameter, public check_invalid
Dictionary for generic data types.
Definition: common_dict.f90:61
subroutine computecvar_modeuler(this, Mesh, Physics, Fluxes, eta, time, dt, cold, pvar, cvar, rhs, cnew)
performs the time step update using the RHS
subroutines for modified Euler i.e. Runge-Kutta methods
base module for numerical flux functions
Definition: fluxes_base.f90:39
integer, parameter, public check_rhomin
subroutine inittimedisc_modeuler(this, Mesh, Physics, config, IO)