source: palm/trunk/SOURCE/disturb_field.f90 @ 4478

Last change on this file since 4478 was 4457, checked in by raasch, 5 years ago

ghost point exchange modularized, bugfix for wrong 2d-exchange

  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1!> @file disturb_field.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-2020 Leibniz Universitaet Hannover
18!------------------------------------------------------------------------------!
19!
20! Current revisions:
21! ------------------
22!
23!
24! Former revisions:
25! -----------------
26! $Id: disturb_field.f90 4457 2020-03-11 14:20:43Z monakurppa $
27! use statement for exchange horiz added
28!
29! 4360 2020-01-07 11:25:50Z suehring
30! Introduction of wall_flags_total_0, which currently sets bits based on static
31! topography information used in wall_flags_static_0
32!
33! 4329 2019-12-10 15:46:36Z motisi
34! Renamed wall_flags_0 to wall_flags_static_0
35!
36! 4237 2019-09-25 11:33:42Z knoop
37! Added missing OpenMP directives
38!
39! 4182 2019-08-22 15:20:23Z scharf
40! Corrected "Former revisions" section
41!
42! 3849 2019-04-01 16:35:16Z knoop
43! Corrected "Former revisions" section
44!
45! Revision 1.1  1998/02/04 15:40:45  raasch
46! Initial revision
47!
48!
49! Description:
50! ------------
51!> Imposing a random perturbation on a 3D-array.
52!> On parallel computers, the random number generator is as well called for all
53!> gridpoints of the total domain to ensure, regardless of the number of PEs
54!> used, that the elements of the array have the same values in the same
55!> order in every case. The perturbation range is steered by dist_range.
56!------------------------------------------------------------------------------!
57 SUBROUTINE disturb_field( var_char, dist1, field )
58 
59
60    USE control_parameters,                                                    &
61        ONLY:  dist_nxl, dist_nxr, dist_nyn, dist_nys, dist_range,             &
62               disturbance_amplitude, disturbance_created,                     &
63               disturbance_level_ind_b, disturbance_level_ind_t, iran,         &
64               random_generator, topography
65               
66    USE cpulog,                                                                &
67        ONLY:  cpu_log, log_point
68       
69    USE exchange_horiz_mod,                                                    &
70        ONLY:  exchange_horiz
71
72    USE indices,                                                               &
73        ONLY:  nbgp, nxl, nxlg, nxr, nxrg, nyn, nyng, nys, nysg, nzb, nzb_max, &
74               nzt, wall_flags_total_0
75       
76    USE kinds
77   
78    USE random_function_mod,                                                   &
79        ONLY: random_function
80       
81    USE random_generator_parallel,                                             &
82        ONLY:  random_number_parallel, random_seed_parallel, random_dummy,     &
83               seq_random_array
84
85    IMPLICIT NONE
86
87    CHARACTER (LEN = *) ::  var_char !< flag to distinguish betwenn u- and v-component
88
89    INTEGER(iwp) ::  flag_nr !< number of respective flag for u- or v-grid
90    INTEGER(iwp) ::  i       !< index variable
91    INTEGER(iwp) ::  j       !< index variable
92    INTEGER(iwp) ::  k       !< index variable
93
94    REAL(wp) ::  randomnumber  !<
95   
96    REAL(wp) ::  dist1(nzb:nzt+1,nysg:nyng,nxlg:nxrg)  !<
97    REAL(wp) ::  field(nzb:nzt+1,nysg:nyng,nxlg:nxrg)  !<
98   
99    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  dist2  !<
100
101
102    CALL cpu_log( log_point(20), 'disturb_field', 'start' )
103!
104!-- Set flag number, 20 for u-grid, 21 for v-grid, required to mask topography
105    flag_nr = MERGE( 20, 21, TRIM(var_char) == 'u' )
106!
107!-- Create an additional temporary array and initialize the arrays needed
108!-- to store the disturbance
109    ALLOCATE( dist2(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
110!$ACC DATA CREATE(dist2(nzb:nzt+1,nysg:nyng,nxlg:nxrg))
111
112!
113!-- dist1 is initialized on the host (see below) and then updated on the device.
114    dist1 = 0.0_wp
115    !$ACC KERNELS PRESENT(dist2)
116    dist2 = 0.0_wp
117    !$ACC END KERNELS
118
119!
120!-- Create the random perturbation and store it on temporary array
121    IF ( random_generator == 'numerical-recipes' )  THEN
122       DO  i = dist_nxl(dist_range), dist_nxr(dist_range)
123          DO  j = dist_nys(dist_range), dist_nyn(dist_range)
124             DO  k = disturbance_level_ind_b, disturbance_level_ind_t
125                randomnumber = 3.0_wp * disturbance_amplitude *                &
126                               ( random_function( iran ) - 0.5_wp )
127                IF ( nxl <= i  .AND.  nxr >= i  .AND.  nys <= j  .AND.         &
128                     nyn >= j )                                                &
129                THEN
130                   dist1(k,j,i) = randomnumber
131                ENDIF
132             ENDDO
133          ENDDO
134       ENDDO
135    ELSEIF ( random_generator == 'random-parallel' )  THEN
136       DO  i = dist_nxl(dist_range), dist_nxr(dist_range)
137          DO  j = dist_nys(dist_range), dist_nyn(dist_range)
138             CALL random_seed_parallel( put=seq_random_array(:, j, i) )
139             DO  k = disturbance_level_ind_b, disturbance_level_ind_t
140                CALL random_number_parallel( random_dummy )
141                randomnumber = 3.0_wp * disturbance_amplitude *                &
142                               ( random_dummy - 0.5_wp )
143                IF ( nxl <= i  .AND.  nxr >= i  .AND.  nys <= j  .AND.         &
144                     nyn >= j )                                                &
145                THEN
146                   dist1(k,j,i) = randomnumber
147                ENDIF
148             ENDDO
149             CALL random_seed_parallel( get=seq_random_array(:, j, i) )
150          ENDDO
151       ENDDO
152    ELSEIF ( random_generator == 'system-specific' )  THEN
153       DO  i = dist_nxl(dist_range), dist_nxr(dist_range)
154          DO  j = dist_nys(dist_range), dist_nyn(dist_range)
155             DO  k = disturbance_level_ind_b, disturbance_level_ind_t
156                CALL RANDOM_NUMBER( randomnumber )
157                randomnumber = 3.0_wp * disturbance_amplitude *                &
158                                ( randomnumber - 0.5_wp )
159                IF ( nxl <= i .AND. nxr >= i .AND. nys <= j .AND. nyn >= j )   &
160                THEN
161                   dist1(k,j,i) = randomnumber
162                ENDIF
163             ENDDO
164          ENDDO
165       ENDDO
166
167    ENDIF
168
169!
170!-- Update dist1 on the device, this is expected by exchange_horiz!
171    !$ACC UPDATE DEVICE(dist1(nzb:nzt+1,nysg:nyng,nxlg:nxrg))
172
173!
174!-- Exchange of ghost points for the random perturbation
175
176    CALL exchange_horiz( dist1, nbgp )
177!
178!-- Applying the Shuman filter in order to smooth the perturbations.
179!-- Neighboured grid points in all three directions are used for the
180!-- filter operation.
181!-- Loop has been splitted to make runs reproducible on HLRN systems using
182!-- compiler option -O3
183     !$ACC PARALLEL LOOP COLLAPSE(2) PRIVATE(i, j, k) PRESENT(dist1, dist2)
184     !$OMP PARALLEL DO PRIVATE(i, j, k)
185     DO  i = nxl, nxr
186        DO  j = nys, nyn
187          DO  k = disturbance_level_ind_b-1, disturbance_level_ind_t+1
188             dist2(k,j,i) = ( dist1(k,j,i-1) + dist1(k,j,i+1)                  &
189                            + dist1(k,j+1,i) + dist1(k+1,j,i)                  &
190                            ) / 12.0_wp
191          ENDDO
192          DO  k = disturbance_level_ind_b-1, disturbance_level_ind_t+1
193              dist2(k,j,i) = dist2(k,j,i) + ( dist1(k,j-1,i) + dist1(k-1,j,i)  &
194                            + 6.0_wp * dist1(k,j,i)                            &
195                            ) / 12.0_wp
196          ENDDO
197        ENDDO
198     ENDDO
199
200!
201!-- Exchange of ghost points for the filtered perturbation.
202!-- Afterwards, filter operation and exchange of ghost points are repeated.
203    CALL exchange_horiz( dist2, nbgp )
204
205    !$ACC PARALLEL LOOP COLLAPSE(2) PRIVATE(i, j, k) PRESENT(dist1, dist2)
206    !$OMP PARALLEL DO PRIVATE(i, j, k)
207    DO  i = nxl, nxr
208       DO  j = nys, nyn
209          DO  k = disturbance_level_ind_b-2, disturbance_level_ind_t+2
210             dist1(k,j,i) = ( dist2(k,j,i-1) + dist2(k,j,i+1) + dist2(k,j-1,i) &
211                            + dist2(k,j+1,i) + dist2(k+1,j,i) + dist2(k-1,j,i) &
212                            + 6.0_wp * dist2(k,j,i)                            &
213                            ) / 12.0_wp
214          ENDDO
215       ENDDO
216    ENDDO
217
218    CALL exchange_horiz( dist1, nbgp )
219
220!
221!-- Remove perturbations below topography (including one gridpoint above it
222!-- in order to allow for larger timesteps at the beginning of the simulation
223!-- (diffusion criterion))
224    IF ( TRIM( topography ) /= 'flat' )  THEN
225       DO  i = nxlg, nxrg
226          DO  j = nysg, nyng
227             DO  k = nzb, nzb_max
228                dist1(k,j,i) = MERGE( dist1(k,j,i), 0.0_wp,                    &
229                                  BTEST( wall_flags_total_0(k,j,i), flag_nr )  &
230                                    )
231             ENDDO
232          ENDDO
233       ENDDO
234    ENDIF
235
236!
237!-- Random perturbation is added to the array to be disturbed.
238    !$ACC PARALLEL LOOP COLLAPSE(3) PRIVATE(i, j, k) PRESENT(field, dist1)
239    !$OMP PARALLEL DO PRIVATE(i, j, k)
240    DO  i = nxlg, nxrg
241       DO  j = nysg, nyng
242          DO  k = disturbance_level_ind_b-2, disturbance_level_ind_t+2
243             field(k,j,i) = field(k,j,i) + dist1(k,j,i)
244          ENDDO
245       ENDDO
246    ENDDO
247
248!$ACC END DATA
249
250!
251!-- Deallocate the temporary array
252    DEALLOCATE( dist2 )
253
254!
255!-- Set a flag, which indicates that a random perturbation is imposed
256    disturbance_created = .TRUE.
257
258
259    CALL cpu_log( log_point(20), 'disturb_field', 'stop' )
260
261
262 END SUBROUTINE disturb_field
Note: See TracBrowser for help on using the repository browser.