source: palm/trunk/SOURCE/timestep.f90 @ 4185

Last change on this file since 4185 was 4182, checked in by scharf, 5 years ago
  • corrected "Former revisions" section
  • minor formatting in "Former revisions" section
  • added "Author" section
  • Property svn:keywords set to Id
File size: 15.2 KB
Line 
1!> @file timestep.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 1997-2019 Leibniz Universitaet Hannover
18!------------------------------------------------------------------------------!
19!
20! Current revisions:
21! ------------------
22!
23!
24! Former revisions:
25! -----------------
26! $Id: timestep.f90 4182 2019-08-22 15:20:23Z oliver.maas $
27! Corrected "Former revisions" section
28!
29! 4101 2019-07-17 15:14:26Z gronemeier
30! - consider 2*Km within diffusion criterion as Km is considered twice within
31!   the diffusion of e,
32! - in RANS mode, instead of considering each wind component individually use
33!   the wind speed of 3d wind vector in CFL criterion
34! - do not limit the increase of dt based on its previous value in RANS mode
35!
36! 3658 2019-01-07 20:28:54Z knoop
37! OpenACC port for SPEC
38!
39! Revision 1.1  1997/08/11 06:26:19  raasch
40! Initial revision
41!
42!
43! Description:
44! ------------
45!> Compute the time step under consideration of the FCL and diffusion criterion.
46!------------------------------------------------------------------------------!
47 SUBROUTINE timestep
48 
49
50    USE arrays_3d,                                                             &
51        ONLY:  dzu, dzw, kh, km, u, u_stokes_zu, v, v_stokes_zu, w
52
53    USE control_parameters,                                                    &
54        ONLY:  cfl_factor, coupling_mode, dt_3d, dt_fixed, dt_max,             &
55               galilei_transformation, message_string, rans_mode,              &
56               stop_dt, terminate_coupled, terminate_coupled_remote,           &
57               timestep_reason, u_gtrans, use_ug_for_galilei_tr, v_gtrans
58
59    USE cpulog,                                                                &
60        ONLY:  cpu_log, log_point
61
62    USE grid_variables,                                                        &
63        ONLY:  dx, dx2, dy, dy2
64
65    USE indices,                                                               &
66        ONLY:  nxl, nxlg, nxr, nxrg, nyn, nyng, nys, nysg, nzb, nzt
67
68    USE interfaces
69
70    USE kinds
71
72    USE bulk_cloud_model_mod,                                                  &
73        ONLY:  dt_precipitation
74
75    USE pegrid
76
77    USE pmc_interface,                                                         &
78        ONLY:  nested_run
79
80    USE statistics,                                                            &
81        ONLY:  flow_statistics_called, hom, u_max, u_max_ijk, v_max, v_max_ijk,&
82               w_max, w_max_ijk
83
84    USE vertical_nesting_mod,                                                  &
85        ONLY:  vnested, vnest_timestep_sync
86
87    IMPLICIT NONE
88
89    INTEGER(iwp) ::  i !<
90    INTEGER(iwp) ::  j !<
91    INTEGER(iwp) ::  k !<
92    INTEGER(iwp) ::  km_max_ijk(3) = -1  !< index values (i,j,k) of location where km_max occurs
93    INTEGER(iwp) ::  kh_max_ijk(3) = -1  !< index values (i,j,k) of location where kh_max occurs
94
95    LOGICAL ::  stop_dt_local !< local switch for controlling the time stepping
96
97    REAL(wp) ::  div               !<
98    REAL(wp) ::  dt_diff           !<
99    REAL(wp) ::  dt_diff_l         !<
100    REAL(wp) ::  dt_u              !<
101    REAL(wp) ::  dt_u_l            !<
102    REAL(wp) ::  dt_v              !<
103    REAL(wp) ::  dt_v_l            !<
104    REAL(wp) ::  dt_w              !<
105    REAL(wp) ::  dt_w_l            !<
106    REAL(wp) ::  km_max            !< maximum of Km in entire domain
107    REAL(wp) ::  kh_max            !< maximum of Kh in entire domain
108    REAL(wp) ::  u_gtrans_l        !<
109    REAL(wp) ::  v_gtrans_l        !<
110 
111    REAL(wp), DIMENSION(2)         ::  uv_gtrans   !<
112    REAL(wp), DIMENSION(2)         ::  uv_gtrans_l !<
113    REAL(wp), DIMENSION(3)         ::  reduce      !<
114    REAL(wp), DIMENSION(3)         ::  reduce_l    !<
115    REAL(wp), DIMENSION(nzb+1:nzt) ::  dxyz2_min   !< 
116    !$ACC DECLARE CREATE(dxyz2_min)
117
118
119    CALL cpu_log( log_point(12), 'calculate_timestep', 'start' )
120
121    !$ACC UPDATE &
122    !$ACC HOST(u(nzb:nzt+1,nysg:nyng,nxlg:nxrg)) &
123    !$ACC HOST(v(nzb:nzt+1,nysg:nyng,nxlg:nxrg)) &
124    !$ACC HOST(w(nzb:nzt+1,nysg:nyng,nxlg:nxrg)) &
125    !$ACC HOST(kh(nzb:nzt+1,nysg:nyng,nxlg:nxrg)) &
126    !$ACC HOST(km(nzb:nzt+1,nysg:nyng,nxlg:nxrg))
127
128!
129!-- In case of Galilei-transform not using the geostrophic wind as translation
130!-- velocity, compute the volume-averaged horizontal velocity components, which
131!-- will then be subtracted from the horizontal wind for the time step and
132!-- horizontal advection routines.
133    IF ( galilei_transformation  .AND. .NOT.  use_ug_for_galilei_tr )  THEN
134       IF ( flow_statistics_called )  THEN
135!
136!--       Horizontal averages already existent, just need to average them
137!--       vertically.
138          u_gtrans = 0.0_wp
139          v_gtrans = 0.0_wp
140          DO  k = nzb+1, nzt
141             u_gtrans = u_gtrans + hom(k,1,1,0)
142             v_gtrans = v_gtrans + hom(k,1,2,0)
143          ENDDO
144          u_gtrans = u_gtrans / REAL( nzt - nzb, KIND=wp )
145          v_gtrans = v_gtrans / REAL( nzt - nzb, KIND=wp )
146       ELSE
147!
148!--       Averaging over the entire model domain.
149          u_gtrans_l = 0.0_wp
150          v_gtrans_l = 0.0_wp
151          DO  i = nxl, nxr
152             DO  j = nys, nyn
153                DO  k = nzb+1, nzt
154                   u_gtrans_l = u_gtrans_l + u(k,j,i)
155                   v_gtrans_l = v_gtrans_l + v(k,j,i)
156                ENDDO
157             ENDDO
158          ENDDO
159          uv_gtrans_l(1) = u_gtrans_l /                                        &
160                           REAL( (nxr-nxl+1)*(nyn-nys+1)*(nzt-nzb), KIND=wp )
161          uv_gtrans_l(2) = v_gtrans_l /                                        &
162                           REAL( (nxr-nxl+1)*(nyn-nys+1)*(nzt-nzb), KIND=wp )
163#if defined( __parallel )
164          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
165          CALL MPI_ALLREDUCE( uv_gtrans_l, uv_gtrans, 2, MPI_REAL, MPI_SUM,    &
166                              comm2d, ierr )
167          u_gtrans = uv_gtrans(1) / REAL( numprocs, KIND=wp )
168          v_gtrans = uv_gtrans(2) / REAL( numprocs, KIND=wp )
169#else
170          u_gtrans = uv_gtrans_l(1)
171          v_gtrans = uv_gtrans_l(2)
172#endif
173       ENDIF
174    ENDIF
175
176!
177!-- Determine the maxima of the velocity components, including their
178!-- grid index positions.
179    CALL global_min_max( nzb, nzt+1, nysg, nyng, nxlg, nxrg, u, 'abs', 0.0_wp, &
180                         u_max, u_max_ijk )
181    CALL global_min_max( nzb, nzt+1, nysg, nyng, nxlg, nxrg, v, 'abs', 0.0_wp, &
182                         v_max, v_max_ijk )
183    CALL global_min_max( nzb, nzt+1, nysg, nyng, nxlg, nxrg, w, 'abs', 0.0_wp, &
184                         w_max, w_max_ijk )
185
186    IF ( .NOT. dt_fixed )  THEN
187!
188!--    Variable time step:
189!--    Calculate the maximum time step according to the CFL-criterion
190       dt_u_l = 999999.9_wp
191       dt_v_l = 999999.9_wp
192       dt_w_l = 999999.9_wp
193
194       IF ( .NOT. rans_mode )  THEN
195!
196!--       Consider each velocity component individually
197
198          !$ACC PARALLEL LOOP COLLAPSE(3) PRIVATE(i,j,k) &
199          !$ACC COPY(dt_u_l, dt_v_l, dt_w_l, u_stokes_zu, v_stokes_zu) &
200          !$ACC REDUCTION(MIN: dt_u_l, dt_v_l, dt_w_l) &
201          !$ACC PRESENT(u, v, w, dzu)
202          DO  i = nxl, nxr
203             DO  j = nys, nyn
204                DO  k = nzb+1, nzt
205                   dt_u_l = MIN( dt_u_l, ( dx     /                               &
206                                    ( ABS( u(k,j,i) - u_gtrans + u_stokes_zu(k) ) &
207                                      + 1.0E-10_wp ) ) )
208                   dt_v_l = MIN( dt_v_l, ( dy     /                               &
209                                    ( ABS( v(k,j,i) - v_gtrans + v_stokes_zu(k) ) &
210                                      + 1.0E-10_wp ) ) )
211                   dt_w_l = MIN( dt_w_l, ( dzu(k) /                               &
212                                    ( ABS( w(k,j,i) )            + 1.0E-10_wp ) ) )
213                ENDDO
214             ENDDO
215          ENDDO
216
217       ELSE
218!
219!--       Consider the wind speed at the scalar-grid point
220!--       !> @note considering the wind speed instead of each individual wind
221!--       !>       component is only a workaround so far. This might has to be
222!--       !>       changed in the future.
223
224          !$ACC PARALLEL LOOP COLLAPSE(3) PRIVATE(i,j,k) &
225          !$ACC COPY(dt_u_l, u_stokes_zu, v_stokes_zu) &
226          !$ACC REDUCTION(MIN: dt_u_l) &
227          !$ACC PRESENT(u, v, w, dzu)
228          DO  i = nxl, nxr
229             DO  j = nys, nyn
230                DO  k = nzb+1, nzt
231                   dt_u_l = MIN( dt_u_l, ( MIN( dx, dy, dzu(k) ) / ( &
232                      SQRT(  ( 0.5 * ( u(k,j,i) + u(k,j,i+1) ) - u_gtrans + u_stokes_zu(k) )**2   &
233                           + ( 0.5 * ( v(k,j,i) + v(k,j+1,i) ) - v_gtrans + v_stokes_zu(k) )**2   &
234                           + ( 0.5 * ( w(k,j,i) + w(k-1,j,i) )                             )**2 ) &
235                      + 1.0E-10_wp ) ) )
236                ENDDO
237             ENDDO
238          ENDDO
239         
240          dt_v_l = dt_u_l
241          dt_w_l = dt_u_l
242
243       ENDIF
244
245#if defined( __parallel )
246       reduce_l(1) = dt_u_l
247       reduce_l(2) = dt_v_l
248       reduce_l(3) = dt_w_l
249       IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
250       CALL MPI_ALLREDUCE( reduce_l, reduce, 3, MPI_REAL, MPI_MIN, comm2d, ierr )
251       dt_u = reduce(1)
252       dt_v = reduce(2)
253       dt_w = reduce(3)
254#else
255       dt_u = dt_u_l
256       dt_v = dt_v_l
257       dt_w = dt_w_l
258#endif
259
260!
261!--    Compute time step according to the diffusion criterion.
262!--    First calculate minimum grid spacing which only depends on index k.
263!--    When using the dynamic subgrid model, negative km are possible.
264       dt_diff_l = 999999.0_wp
265
266       !$ACC PARALLEL LOOP PRESENT(dxyz2_min, dzw)
267       DO  k = nzb+1, nzt
268           dxyz2_min(k) = MIN( dx2, dy2, dzw(k)*dzw(k) ) * 0.125_wp
269       ENDDO
270
271       !$OMP PARALLEL private(i,j,k) reduction(MIN: dt_diff_l)
272       !$OMP DO
273       !$ACC PARALLEL LOOP COLLAPSE(3) PRIVATE(i,j,k) &
274       !$ACC COPY(dt_diff_l) REDUCTION(MIN: dt_diff_l) &
275       !$ACC PRESENT(dxyz2_min, kh, km)
276       DO  i = nxl, nxr
277          DO  j = nys, nyn
278             DO  k = nzb+1, nzt
279                dt_diff_l = MIN( dt_diff_l,                                       &
280                                 dxyz2_min(k) /                                   &
281                                    ( MAX( kh(k,j,i), 2.0_wp * ABS( km(k,j,i) ) ) &
282                                      + 1E-20_wp ) )
283             ENDDO
284          ENDDO
285       ENDDO
286       !$OMP END PARALLEL
287#if defined( __parallel )
288       IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
289       CALL MPI_ALLREDUCE( dt_diff_l, dt_diff, 1, MPI_REAL, MPI_MIN, comm2d,   &
290                           ierr )
291#else
292       dt_diff = dt_diff_l
293#endif
294
295!
296!--    The time step is the minimum of the 3-4 components and the diffusion time
297!--    step minus a reduction (cfl_factor) to be on the safe side.
298!--    The time step must not exceed the maximum allowed value.
299       dt_3d = cfl_factor * MIN( dt_diff, dt_u, dt_v, dt_w, dt_precipitation )
300       dt_3d = MIN( dt_3d, dt_max )
301
302!
303!--    Remember the restricting time step criterion for later output.
304       IF ( MIN( dt_u, dt_v, dt_w ) < dt_diff )  THEN
305          timestep_reason = 'A'
306       ELSE
307          timestep_reason = 'D'
308       ENDIF
309
310!
311!--    Set flag if the time step becomes too small.
312       IF ( dt_3d < ( 0.00001_wp * dt_max ) )  THEN
313          stop_dt = .TRUE.
314
315!
316!--       Determine the maxima of the diffusion coefficients, including their
317!--       grid index positions.
318          CALL global_min_max( nzb, nzt+1, nysg, nyng, nxlg, nxrg, km, 'abs',  &
319                               0.0_wp, km_max, km_max_ijk )
320          CALL global_min_max( nzb, nzt+1, nysg, nyng, nxlg, nxrg, kh, 'abs',  &
321                               0.0_wp, kh_max, kh_max_ijk )
322
323          WRITE( message_string, * ) 'Time step has reached minimum limit.',   &
324               '&dt              = ', dt_3d, ' s  Simulation is terminated.',  &
325               '&dt_u            = ', dt_u, ' s',                              &
326               '&dt_v            = ', dt_v, ' s',                              &
327               '&dt_w            = ', dt_w, ' s',                              &
328               '&dt_diff         = ', dt_diff, ' s',                           &
329               '&u_max           = ', u_max, ' m/s    k=', u_max_ijk(1),       &
330               '  j=', u_max_ijk(2), '  i=', u_max_ijk(3),                     &
331               '&v_max           = ', v_max, ' m/s    k=', v_max_ijk(1),       &
332               '  j=', v_max_ijk(2), '  i=', v_max_ijk(3),                     &
333               '&w_max           = ', w_max, ' m/s    k=', w_max_ijk(1),       &
334               '  j=', w_max_ijk(2), '  i=', w_max_ijk(3),                     &
335               '&km_max          = ', km_max, ' m2/s2  k=', km_max_ijk(1),     &
336               '  j=', km_max_ijk(2), '  i=', km_max_ijk(3),                   &
337               '&kh_max          = ', kh_max, ' m2/s2  k=', kh_max_ijk(1),     &
338                '  j=', kh_max_ijk(2), '  i=', kh_max_ijk(3)
339          CALL message( 'timestep', 'PA0312', 0, 1, 0, 6, 0 )
340!
341!--       In case of coupled runs inform the remote model of the termination
342!--       and its reason, provided the remote model has not already been
343!--       informed of another termination reason (terminate_coupled > 0) before.
344#if defined( __parallel )
345          IF ( coupling_mode /= 'uncoupled' .AND. terminate_coupled == 0 )  THEN
346             terminate_coupled = 2
347             IF ( myid == 0 )  THEN
348                CALL MPI_SENDRECV( &
349                     terminate_coupled,        1, MPI_INTEGER, target_id,  0,  &
350                     terminate_coupled_remote, 1, MPI_INTEGER, target_id,  0,  &
351                     comm_inter, status, ierr )
352             ENDIF
353             CALL MPI_BCAST( terminate_coupled_remote, 1, MPI_INTEGER, 0,      &
354                             comm2d, ierr)
355          ENDIF
356#endif
357       ENDIF
358
359!
360!--    In case of nested runs all parent/child processes have to terminate if
361!--    one process has set the stop flag, i.e. they need to set the stop flag
362!--    too.
363       IF ( nested_run )  THEN
364          stop_dt_local = stop_dt
365#if defined( __parallel )
366          CALL MPI_ALLREDUCE( stop_dt_local, stop_dt, 1, MPI_LOGICAL, MPI_LOR, &
367                              MPI_COMM_WORLD, ierr )
368#endif
369       ENDIF
370
371!
372!--    Ensure a smooth value (two significant digits) of the timestep.
373       div = 1000.0_wp
374       DO  WHILE ( dt_3d < div )
375          div = div / 10.0_wp
376       ENDDO
377       dt_3d = NINT( dt_3d * 100.0_wp / div ) * div / 100.0_wp
378
379    ENDIF
380
381!
382!-- Vertical nesting: coarse and fine grid timestep has to be identical   
383    IF ( vnested )  CALL vnest_timestep_sync
384
385    CALL cpu_log( log_point(12), 'calculate_timestep', 'stop' )
386
387 END SUBROUTINE timestep
Note: See TracBrowser for help on using the repository browser.