Changeset 4648
- Timestamp:
- Aug 25, 2020 7:52:08 AM (5 years ago)
- Location:
- palm/trunk/SOURCE
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified palm/trunk/SOURCE/init_3d_model.f90 ¶
r4548 r4648 1 1 !> @file init_3d_model.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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/>. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 8 ! 9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 12 ! 13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ------------------ 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4548 2020-05-28 19:36:45Z suehring 27 29 ! Bugfix, move call for lsf_forcing_surf after lsf_init is called 28 ! 30 ! 29 31 ! 4514 2020-04-30 16:29:59Z suehring 30 ! Add possibility to initialize surface sensible and latent heat fluxes via 31 ! a static driver. 32 ! 32 ! Add possibility to initialize surface sensible and latent heat fluxes via a static driver. 33 ! 33 34 ! 4493 2020-04-10 09:49:43Z pavelkrc 34 ! Overwrite u_init, v_init, pt_init, q_init and s_init with hom for all 35 ! cyclic_fill-cases, not onlyfor turbulent_inflow = .TRUE.36 ! 35 ! Overwrite u_init, v_init, pt_init, q_init and s_init with hom for all cyclic_fill-cases, not only 36 ! for turbulent_inflow = .TRUE. 37 ! 37 38 ! 4360 2020-01-07 11:25:50Z suehring 38 ! Introduction of wall_flags_total_0, which currently sets bits based on static 39 ! topographyinformation used in wall_flags_static_040 ! 39 ! Introduction of wall_flags_total_0, which currently sets bits based on static topography 40 ! information used in wall_flags_static_0 41 ! 41 42 ! 4329 2019-12-10 15:46:36Z motisi 42 43 ! Renamed wall_flags_0 to wall_flags_static_0 43 ! 44 ! 44 45 ! 4286 2019-10-30 16:01:14Z resler 45 46 ! implement new palm_date_time_mod 46 ! 47 ! 47 48 ! 4223 2019-09-10 09:20:47Z gronemeier 48 ! Deallocate temporary string array since it may be re-used to read different 49 ! input data in othermodules50 ! 49 ! Deallocate temporary string array since it may be re-used to read different input data in other 50 ! modules 51 ! 51 52 ! 4186 2019-08-23 16:06:14Z suehring 52 ! Design change, use variables defined in netcdf_data_input_mod to read netcd 53 ! variables rather thandefine local ones.54 ! 53 ! Design change, use variables defined in netcdf_data_input_mod to read netcd variables rather than 54 ! define local ones. 55 ! 55 56 ! 4185 2019-08-23 13:49:38Z oliver.maas 56 57 ! For initializing_actions = ' cyclic_fill': 57 ! Overwrite u_init, v_init, pt_init, q_init and s_init with the 58 ! (temporally) and horizontally averaged vertical profiles from the end 59 ! of the prerun, because these profiles shall be used as the basic state 60 ! for the rayleigh damping and the pt_damping. 61 ! 58 ! Overwrite u_init, v_init, pt_init, q_init and s_init with the (temporally) and horizontally 59 ! averaged vertical profiles from the end of the prerun, because these profiles shall be used as the 60 ! basic state for the rayleigh damping and the pt_damping. 61 ! 62 62 ! 4182 2019-08-22 15:20:23Z scharf 63 63 ! Corrected "Former revisions" section 64 ! 64 ! 65 65 ! 4168 2019-08-16 13:50:17Z suehring 66 66 ! Replace function get_topography_top_index by topo_top_ind 67 ! 67 ! 68 68 ! 4151 2019-08-09 08:24:30Z suehring 69 69 ! Add netcdf directive around input calls (fix for last commit) 70 ! 70 ! 71 71 ! 4150 2019-08-08 20:00:47Z suehring 72 ! Input of additional surface variables independent on land- or urban-surface 73 ! model 74 ! 72 ! Input of additional surface variables independent on land- or urban-surface model 73 ! 75 74 ! 4131 2019-08-02 11:06:18Z monakurppa 76 75 ! Allocate sums and sums_l to allow profile output for salsa variables. 77 ! 76 ! 78 77 ! 4130 2019-08-01 13:04:13Z suehring 79 ! Effectively reduce 3D initialization to 1D initial profiles. This is because 80 ! 3D initialization produces structures in the w-component that are correlated81 ! with the processor grid for some unknown reason82 ! 78 ! Effectively reduce 3D initialization to 1D initial profiles. This is because 3D initialization 79 ! produces structures in the w-component that are correlated with the processor grid for some 80 ! unknown reason 81 ! 83 82 ! 4090 2019-07-11 15:06:47Z Giersch 84 83 ! Unused variables removed 85 ! 84 ! 86 85 ! 4088 2019-07-11 13:57:56Z Giersch 87 86 ! Pressure and density profile calculations revised using basic functions 88 ! 87 ! 89 88 ! 4048 2019-06-21 21:00:21Z knoop 90 89 ! Further modularization of particle code components 91 ! 90 ! 92 91 ! 4017 2019-06-06 12:16:46Z schwenkel 93 ! Convert most location messages to debug messages to reduce output in 94 ! job logfile to a minimum 95 ! 96 ! 92 ! Convert most location messages to debug messages to reduce output in job logfile to a minimum 93 ! 97 94 ! unused variable removed 98 ! 95 ! 99 96 ! 3937 2019-04-29 15:09:07Z suehring 100 ! Move initialization of synthetic turbulence generator behind initialization 101 ! of offline nesting. Remove call for stg_adjust, as this is now already done 102 ! in stg_init. 103 ! 97 ! Move initialization of synthetic turbulence generator behind initialization of offline nesting. 98 ! Remove call for stg_adjust, as this is now already done in stg_init. 99 ! 104 100 ! 3900 2019-04-16 15:17:43Z suehring 105 101 ! Fix problem with LOD = 2 initialization 106 ! 102 ! 107 103 ! 3885 2019-04-11 11:29:34Z kanani 108 ! Changes related to global restructuring of location messages and introduction 109 ! of additional debugmessages110 ! 104 ! Changes related to global restructuring of location messages and introduction of additional debug 105 ! messages 106 ! 111 107 ! 3849 2019-04-01 16:35:16Z knoop 112 108 ! Move initialization of rmask before initializing user_init_arrays 113 ! 109 ! 114 110 ! 3711 2019-01-31 13:44:26Z knoop 115 111 ! Introduced module_interface_init_checks for post-init checks in modules 116 ! 112 ! 117 113 ! 3700 2019-01-26 17:03:42Z knoop 118 114 ! Some interface calls moved to module_interface + cleanup 119 ! 115 ! 120 116 ! 3648 2019-01-02 16:35:46Z suehring 121 117 ! Rename subroutines for surface-data output … … 133 129 !> or 134 130 !> c) read values of a previous run 135 !------------------------------------------------------------------------------ !131 !--------------------------------------------------------------------------------------------------! 136 132 SUBROUTINE init_3d_model 137 133 … … 141 137 USE arrays_3d 142 138 143 USE basic_constants_and_equations_mod, &144 ONLY: c_p, g, l_v, pi, exner_function, exner_function_invers,&145 ideal_gas_law_rho, ideal_gas_law_rho_pt, barometric_formula146 147 USE bulk_cloud_model_mod, &139 USE basic_constants_and_equations_mod, & 140 ONLY: barometric_formula, c_p, exner_function, exner_function_invers, g, & 141 ideal_gas_law_rho, ideal_gas_law_rho_pt, l_v, pi 142 143 USE bulk_cloud_model_mod, & 148 144 ONLY: bulk_cloud_model 149 145 150 USE chem_modules, &146 USE chem_modules, & 151 147 ONLY: max_pr_cs ! ToDo: this dependency needs to be removed cause it is ugly #new_dom 152 148 153 149 USE control_parameters 154 150 155 USE grid_variables, &151 USE grid_variables, & 156 152 ONLY: dx, dy, ddx2_mg, ddy2_mg 157 153 … … 159 155 160 156 USE kinds 161 162 USE lsf_nudging_mod, &157 158 USE lsf_nudging_mod, & 163 159 ONLY: ls_forcing_surf 164 160 165 USE model_1d_mod, &161 USE model_1d_mod, & 166 162 ONLY: init_1d_model, l1d, u1d, v1d 167 163 168 USE module_interface, &169 ONLY: module_interface_init_arrays, &170 module_interface_init, &164 USE module_interface, & 165 ONLY: module_interface_init_arrays, & 166 module_interface_init, & 171 167 module_interface_init_checks 172 168 173 USE multi_agent_system_mod, &169 USE multi_agent_system_mod, & 174 170 ONLY: agents_active, mas_init 175 171 176 USE netcdf_interface, &172 USE netcdf_interface, & 177 173 ONLY: dots_max 178 174 179 USE netcdf_data_input_mod, &180 ONLY: char_fill, &181 check_existence, &182 close_input_file, &183 get_attribute, &184 get_variable, &185 init_3d, &186 input_pids_static, &187 inquire_num_variables, &188 inquire_variable_names, &189 input_file_static, &190 netcdf_data_input_init_3d, &191 num_var_pids, &192 open_read_file, &193 pids_id, &194 real_2d, &175 USE netcdf_data_input_mod, & 176 ONLY: char_fill, & 177 check_existence, & 178 close_input_file, & 179 get_attribute, & 180 get_variable, & 181 init_3d, & 182 input_pids_static, & 183 inquire_num_variables, & 184 inquire_variable_names, & 185 input_file_static, & 186 netcdf_data_input_init_3d, & 187 num_var_pids, & 188 open_read_file, & 189 pids_id, & 190 real_2d, & 195 191 vars_pids 196 197 USE nesting_offl_mod, &192 193 USE nesting_offl_mod, & 198 194 ONLY: nesting_offl_init 199 195 200 USE palm_date_time_mod, &196 USE palm_date_time_mod, & 201 197 ONLY: set_reference_date_time 202 198 … … 204 200 205 201 #if defined( __parallel ) 206 USE pmc_interface, &202 USE pmc_interface, & 207 203 ONLY: nested_run 208 204 #endif 209 205 210 USE random_function_mod 211 212 USE random_generator_parallel, &206 USE random_function_mod 207 208 USE random_generator_parallel, & 213 209 ONLY: init_parallel_random_generator 214 210 215 USE read_restart_data_mod, & 216 ONLY: rrd_read_parts_of_global, rrd_local 217 218 USE statistics, & 219 ONLY: hom, hom_sum, mean_surface_level_height, pr_palm, rmask, & 220 statistic_regions, sums, sums_divnew_l, sums_divold_l, sums_l, & 221 sums_l_l, sums_wsts_bc_l, ts_value, & 211 USE read_restart_data_mod, & 212 ONLY: rrd_local, rrd_read_parts_of_global 213 214 USE statistics, & 215 ONLY: hom, hom_sum, mean_surface_level_height, pr_palm, rmask, statistic_regions, sums, & 216 sums_divnew_l, sums_divold_l, sums_l, sums_l_l, sums_wsts_bc_l, ts_value, & 222 217 weight_pres, weight_substep 223 218 224 USE synthetic_turbulence_generator_mod, &219 USE synthetic_turbulence_generator_mod, & 225 220 ONLY: stg_init, use_syn_turb_gen 226 221 227 USE surface_layer_fluxes_mod, &222 USE surface_layer_fluxes_mod, & 228 223 ONLY: init_surface_layer_fluxes 229 224 230 USE surface_mod, &231 ONLY : init_single_surface_properties, &232 init_surface_arrays, &233 init_surfaces, &234 surf_def_h, &235 surf_def_v, &236 surf_lsm_h, &225 USE surface_mod, & 226 ONLY : init_single_surface_properties, & 227 init_surface_arrays, & 228 init_surfaces, & 229 surf_def_h, & 230 surf_def_v, & 231 surf_lsm_h, & 237 232 surf_usm_h 238 233 239 234 #if defined( _OPENACC ) 240 USE surface_mod, &235 USE surface_mod, & 241 236 ONLY : bc_h 242 237 #endif 243 238 244 USE surface_data_output_mod, &239 USE surface_data_output_mod, & 245 240 ONLY: surface_data_output_init 246 241 247 242 USE transpose_indices 248 243 244 249 245 IMPLICIT NONE 250 246 251 247 INTEGER(iwp) :: i !< grid index in x direction 252 248 INTEGER(iwp) :: ind_array(1) !< dummy used to determine start index for external pressure forcing … … 254 250 INTEGER(iwp) :: k !< grid index in z direction 255 251 INTEGER(iwp) :: k_surf !< surface level index 256 INTEGER(iwp) :: l !< running index over surface orientation 257 INTEGER(iwp) :: m !< index of surface element in surface data type 252 INTEGER(iwp) :: l !< running index over surface orientation 253 INTEGER(iwp) :: m !< index of surface element in surface data type 258 254 INTEGER(iwp) :: nz_u_shift !< topography-top index on u-grid, used to vertically shift initial profiles 259 255 INTEGER(iwp) :: nz_v_shift !< topography-top index on v-grid, used to vertically shift initial profiles … … 267 263 INTEGER(iwp) :: sr !< index of statistic region 268 264 269 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: ngp_2dh_l !< toal number of horizontal grid points in statistical region on subdomain 270 271 INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE :: ngp_2dh_outer_l !< number of horizontal non-wall bounded grid points on subdomain 272 INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE :: ngp_2dh_s_inner_l !< number of horizontal non-topography grid points on subdomain 273 274 275 276 REAL(wp), DIMENSION(:), ALLOCATABLE :: init_l !< dummy array used for averaging 3D data to obtain inital profiles 277 REAL(wp), DIMENSION(:), ALLOCATABLE :: p_hydrostatic !< hydrostatic pressure 265 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: ngp_2dh_l !< toal number of horizontal grid points in statistical region on 266 !< subdomain 267 268 INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE :: ngp_2dh_outer_l !< number of horizontal non-wall bounded grid points on 269 !< subdomain 270 INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE :: ngp_2dh_s_inner_l !< number of horizontal non-topography grid points on 271 !< subdomain 278 272 279 273 REAL(wp) :: dx_l !< grid spacing along x on different multigrid level 280 274 REAL(wp) :: dy_l !< grid spacing along y on different multigrid level 281 275 276 REAL(wp), DIMENSION(:), ALLOCATABLE :: init_l !< dummy array used for averaging 3D data to obtain 277 !< inital profiles 278 REAL(wp), DIMENSION(:), ALLOCATABLE :: mean_surface_level_height_l !< mean surface level height on subdomain 279 REAL(wp), DIMENSION(:), ALLOCATABLE :: ngp_3d_inner_l !< total number of non-topography grid points on subdomain 280 REAL(wp), DIMENSION(:), ALLOCATABLE :: ngp_3d_inner_tmp !< total number of non-topography grid points 281 REAL(wp), DIMENSION(:), ALLOCATABLE :: p_hydrostatic !< hydrostatic pressure 282 282 283 REAL(wp), DIMENSION(1:3) :: volume_flow_area_l !< area of lateral and top model domain surface on local subdomain 283 284 REAL(wp), DIMENSION(1:3) :: volume_flow_initial_l !< initial volume flow into model domain 284 285 285 REAL(wp), DIMENSION(:), ALLOCATABLE :: mean_surface_level_height_l !< mean surface level height on subdomain286 REAL(wp), DIMENSION(:), ALLOCATABLE :: ngp_3d_inner_l !< total number of non-topography grid points on subdomain287 REAL(wp), DIMENSION(:), ALLOCATABLE :: ngp_3d_inner_tmp !< total number of non-topography grid points288 289 286 TYPE(real_2d) :: tmp_2d !< temporary variable to input additional surface-data from static file 290 287 291 288 CALL location_message( 'model initialization', 'start' ) 292 289 ! … … 297 294 ! 298 295 !-- Allocate arrays 299 ALLOCATE( mean_surface_level_height(0:statistic_regions), &300 mean_surface_level_height_l(0:statistic_regions), &301 ngp_2dh(0:statistic_regions), ngp_2dh_l(0:statistic_regions), &302 ngp_3d(0:statistic_regions), &303 ngp_3d_inner(0:statistic_regions), &304 ngp_3d_inner_l(0:statistic_regions), &305 ngp_3d_inner_tmp(0:statistic_regions), &306 sums_divnew_l(0:statistic_regions), &296 ALLOCATE( mean_surface_level_height(0:statistic_regions), & 297 mean_surface_level_height_l(0:statistic_regions), & 298 ngp_2dh(0:statistic_regions), ngp_2dh_l(0:statistic_regions), & 299 ngp_3d(0:statistic_regions), & 300 ngp_3d_inner(0:statistic_regions), & 301 ngp_3d_inner_l(0:statistic_regions), & 302 ngp_3d_inner_tmp(0:statistic_regions), & 303 sums_divnew_l(0:statistic_regions), & 307 304 sums_divold_l(0:statistic_regions) ) 308 305 ALLOCATE( dp_smooth_factor(nzb:nzt), rdf(nzb+1:nzt), rdf_sc(nzb+1:nzt) ) 309 ALLOCATE( ngp_2dh_outer(nzb:nzt+1,0:statistic_regions), &310 ngp_2dh_outer_l(nzb:nzt+1,0:statistic_regions), &311 ngp_2dh_s_inner(nzb:nzt+1,0:statistic_regions), &312 ngp_2dh_s_inner_l(nzb:nzt+1,0:statistic_regions), &313 rmask(nysg:nyng,nxlg:nxrg,0:statistic_regions), &314 sums(nzb:nzt+1,pr_palm+max_pr_user+max_pr_cs+max_pr_salsa), &306 ALLOCATE( ngp_2dh_outer(nzb:nzt+1,0:statistic_regions), & 307 ngp_2dh_outer_l(nzb:nzt+1,0:statistic_regions), & 308 ngp_2dh_s_inner(nzb:nzt+1,0:statistic_regions), & 309 ngp_2dh_s_inner_l(nzb:nzt+1,0:statistic_regions), & 310 rmask(nysg:nyng,nxlg:nxrg,0:statistic_regions), & 311 sums(nzb:nzt+1,pr_palm+max_pr_user+max_pr_cs+max_pr_salsa), & 315 312 sums_l(nzb:nzt+1,pr_palm+max_pr_user+max_pr_cs+max_pr_salsa,0:threads_per_task-1), & 316 sums_l_l(nzb:nzt+1,0:statistic_regions,0:threads_per_task-1), &313 sums_l_l(nzb:nzt+1,0:statistic_regions,0:threads_per_task-1), & 317 314 sums_wsts_bc_l(nzb:nzt+1,0:statistic_regions) ) 318 315 ALLOCATE( ts_value(dots_max,0:statistic_regions) ) 319 316 ALLOCATE( ptdf_x(nxlg:nxrg), ptdf_y(nysg:nyng) ) 320 317 321 ALLOCATE( d(nzb+1:nzt,nys:nyn,nxl:nxr), &322 p(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &318 ALLOCATE( d(nzb+1:nzt,nys:nyn,nxl:nxr), & 319 p(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 323 320 tend(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 324 321 325 ALLOCATE( pt_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &326 pt_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &327 u_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &328 u_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &329 u_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &330 v_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &331 v_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &332 v_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &333 w_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &334 w_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &322 ALLOCATE( pt_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 323 pt_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 324 u_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 325 u_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 326 u_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 327 v_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 328 v_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 329 v_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 330 w_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 331 w_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 335 332 w_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 336 333 IF ( .NOT. neutral ) THEN … … 339 336 ! 340 337 !-- Pre-set masks for regional statistics. Default is the total model domain. 341 !-- Ghost points are excluded because counting values at the ghost boundaries 342 !-- would bias the statistics338 !-- Ghost points are excluded because counting values at the ghost boundaries would bias the 339 !-- statistics. 343 340 rmask = 1.0_wp 344 341 rmask(:,nxlg:nxl-1,:) = 0.0_wp; rmask(:,nxr+1:nxrg,:) = 0.0_wp 345 342 rmask(nysg:nys-1,:,:) = 0.0_wp; rmask(nyn+1:nyng,:,:) = 0.0_wp 346 343 ! 347 !-- Following array is required for perturbation pressure within the iterative 348 !-- pressure solvers. For the multistep schemes (Runge-Kutta), array p holds 349 !-- the weighted average of the substeps and cannot be used in the Poisson 350 !-- solver. 344 !-- Following array is required for perturbation pressure within the iterative pressure solvers. For 345 !-- the multistep schemes (Runge-Kutta), array p holds the weighted average of the substeps and 346 !-- cannot be used in the Poisson solver. 351 347 IF ( psolver == 'sor' ) THEN 352 348 ALLOCATE( p_loc(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) … … 367 363 ! 368 364 !-- 3D-humidity 369 ALLOCATE( q_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &370 q_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &371 q_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &372 vpt_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 373 ENDIF 374 365 ALLOCATE( q_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 366 q_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 367 q_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 368 vpt_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 369 ENDIF 370 375 371 IF ( passive_scalar ) THEN 376 372 377 373 ! 378 374 !-- 3D scalar arrays 379 ALLOCATE( s_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &380 s_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &375 ALLOCATE( s_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 376 s_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 381 377 s_3(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 382 378 … … 384 380 385 381 ! 386 !-- Allocate and set 1d-profiles for Stokes drift velocity. It may be set to 387 !-- non-zero values later in ocean_init388 ALLOCATE( u_stokes_zu(nzb:nzt+1), u_stokes_zw(nzb:nzt+1), &382 !-- Allocate and set 1d-profiles for Stokes drift velocity. It may be set to non-zero values later 383 !-- in ocean_init. 384 ALLOCATE( u_stokes_zu(nzb:nzt+1), u_stokes_zw(nzb:nzt+1), & 389 385 v_stokes_zu(nzb:nzt+1), v_stokes_zw(nzb:nzt+1) ) 390 386 u_stokes_zu(:) = 0.0_wp … … 401 397 ALLOCATE( drho_air_zw(nzb:nzt+1) ) 402 398 ! 403 !-- Density profile calculation for anelastic and Boussinesq approximation 404 !-- In case of a Boussinesq approximation, a constant density is calculated 405 !-- mainly for output purposes. This density do not need to be considered 406 !-- in the model's system of equations. 399 !-- Density profile calculation for anelastic and Boussinesq approximation. 400 !-- In case of a Boussinesq approximation, a constant density is calculated mainly for output 401 !-- purposes. This density does not need to be considered in the model's system of equations. 407 402 IF ( TRIM( approximation ) == 'anelastic' ) THEN 408 403 DO k = nzb, nzt+1 409 p_hydrostatic(k) = barometric_formula(zu(k), pt_surface * &410 exner_function(surface_pressure * 100.0_wp),&411 surface_pressure * 100.0_wp)412 404 p_hydrostatic(k) = barometric_formula(zu(k), pt_surface * & 405 exner_function(surface_pressure * 100.0_wp), & 406 surface_pressure * 100.0_wp) 407 413 408 rho_air(k) = ideal_gas_law_rho_pt(p_hydrostatic(k), pt_init(k)) 414 409 ENDDO 415 410 416 411 DO k = nzb, nzt 417 412 rho_air_zw(k) = 0.5_wp * ( rho_air(k) + rho_air(k+1) ) 418 413 ENDDO 419 420 rho_air_zw(nzt+1) = rho_air_zw(nzt) & 421 + 2.0_wp * ( rho_air(nzt+1) - rho_air_zw(nzt) ) 422 414 415 rho_air_zw(nzt+1) = rho_air_zw(nzt) + 2.0_wp * ( rho_air(nzt+1) - rho_air_zw(nzt) ) 416 423 417 ELSE 424 418 DO k = nzb, nzt+1 425 p_hydrostatic(k) = barometric_formula(zu(nzb), pt_surface * &426 exner_function(surface_pressure * 100.0_wp),&427 surface_pressure * 100.0_wp)419 p_hydrostatic(k) = barometric_formula(zu(nzb), pt_surface * & 420 exner_function(surface_pressure * 100.0_wp), & 421 surface_pressure * 100.0_wp) 428 422 429 423 rho_air(k) = ideal_gas_law_rho_pt(p_hydrostatic(k), pt_init(nzb)) 430 424 ENDDO 431 425 432 426 DO k = nzb, nzt 433 427 rho_air_zw(k) = 0.5_wp * ( rho_air(k) + rho_air(k+1) ) 434 428 ENDDO 435 436 rho_air_zw(nzt+1) = rho_air_zw(nzt) & 437 + 2.0_wp * ( rho_air(nzt+1) - rho_air_zw(nzt) ) 438 439 ENDIF 440 ! 441 !-- compute the inverse density array in order to avoid expencive divisions 429 430 rho_air_zw(nzt+1) = rho_air_zw(nzt) + 2.0_wp * ( rho_air(nzt+1) - rho_air_zw(nzt) ) 431 432 ENDIF 433 ! 434 !-- Compute the inverse density array in order to avoid expencive divisions 442 435 drho_air = 1.0_wp / rho_air 443 436 drho_air_zw = 1.0_wp / rho_air_zw … … 453 446 454 447 ! 455 !-- calculate flux conversion factors according to approximation and in-/output mode448 !-- Calculate flux conversion factors according to approximation and in-/output mode 456 449 DO k = nzb, nzt+1 457 450 … … 484 477 485 478 ! 486 !-- In case of multigrid method, compute grid lengths and grid factors for the 487 !-- grid levels with respective density on each grid479 !-- In case of multigrid method, compute grid lengths and grid factors for the grid levels with 480 !-- respective density on each grid. 488 481 IF ( psolver(1:9) == 'multigrid' ) THEN 489 482 … … 500 493 dzu_mg(:,maximum_grid_level) = dzu 501 494 rho_air_mg(:,maximum_grid_level) = rho_air 502 ! 503 !-- Next line to ensure an equally spaced grid. 495 ! 496 !-- Next line to ensure an equally spaced grid. 504 497 dzu_mg(1,maximum_grid_level) = dzu(2) 505 rho_air_mg(nzb,maximum_grid_level) = rho_air(nzb) + & 506 (rho_air(nzb) - rho_air(nzb+1)) 498 rho_air_mg(nzb,maximum_grid_level) = rho_air(nzb) + (rho_air(nzb) - rho_air(nzb+1)) 507 499 508 500 dzw_mg(:,maximum_grid_level) = dzw … … 512 504 dzu_mg(nzb+1,l) = 2.0_wp * dzu_mg(nzb+1,l+1) 513 505 dzw_mg(nzb+1,l) = 2.0_wp * dzw_mg(nzb+1,l+1) 514 rho_air_mg(nzb,l) = rho_air_mg(nzb,l+1) + (rho_air_mg(nzb,l+1) - rho_air_mg(nzb+1,l+1)) 515 rho_air_zw_mg(nzb,l) = rho_air_zw_mg(nzb,l+1) + (rho_air_zw_mg(nzb,l+1) - rho_air_zw_mg(nzb+1,l+1)) 506 rho_air_mg(nzb,l) = rho_air_mg(nzb,l+1) + ( rho_air_mg(nzb,l+1) - & 507 rho_air_mg(nzb+1,l+1) ) 508 rho_air_zw_mg(nzb,l) = rho_air_zw_mg(nzb,l+1) + ( rho_air_zw_mg(nzb,l+1) - & 509 rho_air_zw_mg(nzb+1,l+1) ) 516 510 rho_air_mg(nzb+1,l) = rho_air_mg(nzb+1,l+1) 517 511 rho_air_zw_mg(nzb+1,l) = rho_air_zw_mg(nzb+1,l+1) … … 534 528 f2_mg(k,l) = rho_air_zw_mg(k,l) / ( dzu_mg(k+1,l) * dzw_mg(k,l) ) 535 529 f3_mg(k,l) = rho_air_zw_mg(k-1,l) / ( dzu_mg(k,l) * dzw_mg(k,l) ) 536 f1_mg(k,l) = 2.0_wp * ( ddx2_mg(l) + ddy2_mg(l) ) &530 f1_mg(k,l) = 2.0_wp * ( ddx2_mg(l) + ddy2_mg(l) ) & 537 531 * rho_air_mg(k,l) + f2_mg(k,l) + f3_mg(k,l) 538 532 ENDDO … … 552 546 553 547 ! 554 !-- Arrays to store velocity data from t-dt and the phase speeds which 555 !-- are needed for radiation boundary conditions548 !-- Arrays to store velocity data from t-dt and the phase speeds which are needed for radiation 549 !-- boundary conditions. 556 550 IF ( bc_radiation_l ) THEN 557 ALLOCATE( u_m_l(nzb:nzt+1,nysg:nyng,1:2), &558 v_m_l(nzb:nzt+1,nysg:nyng,0:1), &551 ALLOCATE( u_m_l(nzb:nzt+1,nysg:nyng,1:2), & 552 v_m_l(nzb:nzt+1,nysg:nyng,0:1), & 559 553 w_m_l(nzb:nzt+1,nysg:nyng,0:1) ) 560 554 ENDIF 561 555 IF ( bc_radiation_r ) THEN 562 ALLOCATE( u_m_r(nzb:nzt+1,nysg:nyng,nx-1:nx), &563 v_m_r(nzb:nzt+1,nysg:nyng,nx-1:nx), &556 ALLOCATE( u_m_r(nzb:nzt+1,nysg:nyng,nx-1:nx), & 557 v_m_r(nzb:nzt+1,nysg:nyng,nx-1:nx), & 564 558 w_m_r(nzb:nzt+1,nysg:nyng,nx-1:nx) ) 565 559 ENDIF 566 560 IF ( bc_radiation_l .OR. bc_radiation_r ) THEN 567 ALLOCATE( c_u(nzb:nzt+1,nysg:nyng), c_v(nzb:nzt+1,nysg:nyng), & 568 c_w(nzb:nzt+1,nysg:nyng) ) 561 ALLOCATE( c_u(nzb:nzt+1,nysg:nyng), c_v(nzb:nzt+1,nysg:nyng), c_w(nzb:nzt+1,nysg:nyng) ) 569 562 ENDIF 570 563 IF ( bc_radiation_s ) THEN 571 ALLOCATE( u_m_s(nzb:nzt+1,0:1,nxlg:nxrg), &572 v_m_s(nzb:nzt+1,1:2,nxlg:nxrg), &564 ALLOCATE( u_m_s(nzb:nzt+1,0:1,nxlg:nxrg), & 565 v_m_s(nzb:nzt+1,1:2,nxlg:nxrg), & 573 566 w_m_s(nzb:nzt+1,0:1,nxlg:nxrg) ) 574 567 ENDIF 575 568 IF ( bc_radiation_n ) THEN 576 ALLOCATE( u_m_n(nzb:nzt+1,ny-1:ny,nxlg:nxrg), &577 v_m_n(nzb:nzt+1,ny-1:ny,nxlg:nxrg), &569 ALLOCATE( u_m_n(nzb:nzt+1,ny-1:ny,nxlg:nxrg), & 570 v_m_n(nzb:nzt+1,ny-1:ny,nxlg:nxrg), & 578 571 w_m_n(nzb:nzt+1,ny-1:ny,nxlg:nxrg) ) 579 572 ENDIF 580 573 IF ( bc_radiation_s .OR. bc_radiation_n ) THEN 581 ALLOCATE( c_u(nzb:nzt+1,nxlg:nxrg), c_v(nzb:nzt+1,nxlg:nxrg), & 582 c_w(nzb:nzt+1,nxlg:nxrg) ) 583 ENDIF 584 IF ( bc_radiation_l .OR. bc_radiation_r .OR. bc_radiation_s .OR. & 585 bc_radiation_n ) THEN 586 ALLOCATE( c_u_m_l(nzb:nzt+1), c_v_m_l(nzb:nzt+1), c_w_m_l(nzb:nzt+1) ) 574 ALLOCATE( c_u(nzb:nzt+1,nxlg:nxrg), c_v(nzb:nzt+1,nxlg:nxrg), c_w(nzb:nzt+1,nxlg:nxrg) ) 575 ENDIF 576 IF ( bc_radiation_l .OR. bc_radiation_r .OR. bc_radiation_s .OR. bc_radiation_n ) THEN 577 ALLOCATE( c_u_m_l(nzb:nzt+1), c_v_m_l(nzb:nzt+1), c_w_m_l(nzb:nzt+1) ) 587 578 ALLOCATE( c_u_m(nzb:nzt+1), c_v_m(nzb:nzt+1), c_w_m(nzb:nzt+1) ) 588 579 ENDIF … … 603 594 vpt => vpt_1 604 595 ENDIF 605 596 606 597 IF ( passive_scalar ) THEN 607 598 s => s_1; s_p => s_2; ts_m => s_3 608 ENDIF 599 ENDIF 609 600 610 601 ! … … 617 608 618 609 ! 619 !-- Allocate arrays containing the RK coefficient for calculation of 620 !-- perturbation pressure and turbulent fluxes. At this point values are 621 !-- set for pressure calculation during initialization (where no timestep 622 !-- is done). Further below the values needed within the timestep scheme 623 !-- will be set. 624 ALLOCATE( weight_substep(1:intermediate_timestep_count_max), & 610 !-- Allocate arrays containing the RK coefficient for calculation of perturbation pressure and 611 !-- turbulent fluxes. At this point values are set for pressure calculation during initialization 612 !-- (where no timestep is done). Further below the values needed within the timestep scheme will be 613 !-- set. 614 ALLOCATE( weight_substep(1:intermediate_timestep_count_max), & 625 615 weight_pres(1:intermediate_timestep_count_max) ) 626 616 weight_substep = 1.0_wp 627 617 weight_pres = 1.0_wp 628 618 intermediate_timestep_count = 0 ! needed when simulated_time = 0.0 629 619 630 620 IF ( debug_output ) CALL debug_message( 'allocating arrays', 'end' ) 631 621 … … 636 626 ! 637 627 !-- Initialize local summation arrays for routine flow_statistics. 638 !-- This is necessary because they may not yet have been initialized when they 639 !-- are called from flow_statistics (or - depending on the chosen model run - 640 !-- are never initialized) 641 sums_divnew_l = 0.0_wp 642 sums_divold_l = 0.0_wp 643 sums_l_l = 0.0_wp 644 sums_wsts_bc_l = 0.0_wp 645 628 !-- This is necessary because they may not yet have been initialized when they are called from 629 !-- flow_statistics (or - depending on the chosen model run - are never initialized) 630 sums_divnew_l = 0.0_wp 631 sums_divold_l = 0.0_wp 632 sums_l_l = 0.0_wp 633 sums_wsts_bc_l = 0.0_wp 634 646 635 ! 647 636 !-- Initialize model variables 648 IF ( TRIM( initializing_actions ) /= 'read_restart_data' .AND. &637 IF ( TRIM( initializing_actions ) /= 'read_restart_data' .AND. & 649 638 TRIM( initializing_actions ) /= 'cyclic_fill' ) THEN 650 639 ! … … 653 642 IF ( debug_output ) CALL debug_message( 'initializing with INIFOR', 'start' ) 654 643 ! 655 !-- Read initial 1D profiles or 3D data from NetCDF file, depending 656 !-- on the provided level-of-detail.657 !-- At the moment, only u, v, w, pt and q are provided. 644 !-- Read initial 1D profiles or 3D data from NetCDF file, depending on the provided 645 !-- level-of-detail. 646 !-- At the moment, only u, v, w, pt and q are provided. 658 647 CALL netcdf_data_input_init_3d 659 648 ! 660 !-- Please note, Inifor provides data from nzb+1 to nzt. 661 !-- Bottom and top boundary conditions for Inifor profiles are already 662 !-- set (just afterreading), so that this is not necessary here.663 !-- Depending on the provided level-of-detail, initial Inifor data is 664 !-- either stored on data type (lod=1), or directly on 3D arrays (lod=2).665 !-- In order to obtain also initial profiles in case of lod=2 (which 666 !-- is required for e.g.damping), average over 3D data.649 !-- Please note, Inifor provides data from nzb+1 to nzt. 650 !-- Bottom and top boundary conditions for Inifor profiles are already set (just after 651 !-- reading), so that this is not necessary here. 652 !-- Depending on the provided level-of-detail, initial Inifor data is either stored on data 653 !-- type (lod=1), or directly on 3D arrays (lod=2). 654 !-- In order to obtain also initial profiles in case of lod=2 (which is required for e.g. 655 !-- damping), average over 3D data. 667 656 IF( init_3d%lod_u == 1 ) THEN 668 657 u_init = init_3d%u_init 669 ELSEIF( init_3d%lod_u == 2 ) THEN 670 ALLOCATE( init_l(nzb:nzt+1) ) 658 ELSEIF( init_3d%lod_u == 2 ) THEN 659 ALLOCATE( init_l(nzb:nzt+1) ) 671 660 DO k = nzb, nzt+1 672 661 init_l(k) = SUM( u(k,nys:nyn,nxl:nxr) ) … … 675 664 676 665 #if defined( __parallel ) 677 CALL MPI_ALLREDUCE( init_l, u_init, nzt+1-nzb+1, & 678 MPI_REAL, MPI_SUM, comm2d, ierr ) 666 CALL MPI_ALLREDUCE( init_l, u_init, nzt+1-nzb+1, MPI_REAL, MPI_SUM, comm2d, ierr ) 679 667 #else 680 668 u_init = init_l … … 683 671 684 672 ENDIF 685 686 IF( init_3d%lod_v == 1 ) THEN 673 674 IF( init_3d%lod_v == 1 ) THEN 687 675 v_init = init_3d%v_init 688 ELSEIF( init_3d%lod_v == 2 ) THEN 689 ALLOCATE( init_l(nzb:nzt+1) ) 676 ELSEIF( init_3d%lod_v == 2 ) THEN 677 ALLOCATE( init_l(nzb:nzt+1) ) 690 678 DO k = nzb, nzt+1 691 679 init_l(k) = SUM( v(k,nys:nyn,nxl:nxr) ) … … 694 682 695 683 #if defined( __parallel ) 696 CALL MPI_ALLREDUCE( init_l, v_init, nzt+1-nzb+1, & 697 MPI_REAL, MPI_SUM, comm2d, ierr ) 684 CALL MPI_ALLREDUCE( init_l, v_init, nzt+1-nzb+1, MPI_REAL, MPI_SUM, comm2d, ierr ) 698 685 #else 699 686 v_init = init_l … … 704 691 IF( init_3d%lod_pt == 1 ) THEN 705 692 pt_init = init_3d%pt_init 706 ELSEIF( init_3d%lod_pt == 2 ) THEN 707 ALLOCATE( init_l(nzb:nzt+1) ) 693 ELSEIF( init_3d%lod_pt == 2 ) THEN 694 ALLOCATE( init_l(nzb:nzt+1) ) 708 695 DO k = nzb, nzt+1 709 696 init_l(k) = SUM( pt(k,nys:nyn,nxl:nxr) ) … … 712 699 713 700 #if defined( __parallel ) 714 CALL MPI_ALLREDUCE( init_l, pt_init, nzt+1-nzb+1, & 715 MPI_REAL, MPI_SUM, comm2d, ierr ) 701 CALL MPI_ALLREDUCE( init_l, pt_init, nzt+1-nzb+1, MPI_REAL, MPI_SUM, comm2d, ierr ) 716 702 #else 717 703 pt_init = init_l … … 725 711 IF( init_3d%lod_q == 1 ) THEN 726 712 q_init = init_3d%q_init 727 ELSEIF( init_3d%lod_q == 2 ) THEN 728 ALLOCATE( init_l(nzb:nzt+1) ) 713 ELSEIF( init_3d%lod_q == 2 ) THEN 714 ALLOCATE( init_l(nzb:nzt+1) ) 729 715 DO k = nzb, nzt+1 730 716 init_l(k) = SUM( q(k,nys:nyn,nxl:nxr) ) … … 733 719 734 720 #if defined( __parallel ) 735 CALL MPI_ALLREDUCE( init_l, q_init, nzt+1-nzb+1, & 736 MPI_REAL, MPI_SUM, comm2d, ierr ) 721 CALL MPI_ALLREDUCE( init_l, q_init, nzt+1-nzb+1, MPI_REAL, MPI_SUM, comm2d, ierr ) 737 722 #else 738 723 q_init = init_l … … 743 728 744 729 ! 745 !-- Write initial profiles onto 3D arrays. 746 !-- Work-around, 3D initialization of u,v,w creates artificial 747 !-- structures wich correlate with the processor grid. The reason 748 !-- for this is still unknown. To work-around this, 3D initialization 749 !-- will be effectively reduce to a 1D initialization where no such 750 !-- artificial structures appear. 730 !-- Write initial profiles onto 3D arrays. 731 !-- Work-around, 3D initialization of u,v,w creates artificial structures which correlate with 732 !-- the processor grid. The reason for this is still unknown. To work-around this, 3D 733 !-- initialization will be effectively reduce to a 1D initialization where no such artificial 734 !-- structures appear. 751 735 DO i = nxlg, nxrg 752 736 DO j = nysg, nyng 753 IF( init_3d%lod_u == 1 .OR. init_3d%lod_u == 2 ) & 754 u(:,j,i) = u_init(:) 755 IF( init_3d%lod_v == 1 .OR. init_3d%lod_u == 2 ) & 756 v(:,j,i) = v_init(:) 757 IF( .NOT. neutral .AND. & 758 ( init_3d%lod_pt == 1 .OR. init_3d%lod_pt == 2 ) ) & 737 IF( init_3d%lod_u == 1 .OR. init_3d%lod_u == 2 ) u(:,j,i) = u_init(:) 738 IF( init_3d%lod_v == 1 .OR. init_3d%lod_u == 2 ) v(:,j,i) = v_init(:) 739 IF( .NOT. neutral .AND. ( init_3d%lod_pt == 1 .OR. init_3d%lod_pt == 2 ) ) & 759 740 pt(:,j,i) = pt_init(:) 760 IF( humidity .AND. & 761 ( init_3d%lod_q == 1 .OR. init_3d%lod_q == 2 ) ) & 741 IF( humidity .AND. ( init_3d%lod_q == 1 .OR. init_3d%lod_q == 2 ) ) & 762 742 q(:,j,i) = q_init(:) 763 743 ENDDO 764 744 ENDDO 765 745 ! 766 !-- Set geostrophic wind components. 746 !-- Set geostrophic wind components. 767 747 IF ( init_3d%from_file_ug ) THEN 768 748 ug(:) = init_3d%ug_init(:) … … 790 770 791 771 ! 792 !-- Set velocity components at non-atmospheric / oceanic grid points to 793 !-- zero. 772 !-- Set velocity components at non-atmospheric / oceanic grid points to zero. 794 773 u = MERGE( u, 0.0_wp, BTEST( wall_flags_total_0, 1 ) ) 795 774 v = MERGE( v, 0.0_wp, BTEST( wall_flags_total_0, 2 ) ) 796 775 w = MERGE( w, 0.0_wp, BTEST( wall_flags_total_0, 3 ) ) 797 776 ! 798 !-- Initialize surface variables, e.g. friction velocity, momentum 799 !-- fluxes, etc. 800 CALL init_surfaces 801 802 IF ( debug_output ) CALL debug_message( 'initializing with INIFOR', 'end' ) 777 !-- Initialize surface variables, e.g. friction velocity, momentum fluxes, etc. 778 CALL init_surfaces 779 780 IF ( debug_output ) CALL debug_message( 'initializing with INIFOR', 'end' ) 803 781 ! 804 782 !-- Initialization via computed 1D-model profiles 805 783 ELSEIF ( INDEX( initializing_actions, 'set_1d-model_profiles' ) /= 0 ) THEN 806 784 807 IF ( debug_output ) CALL debug_message( 'initializing with 1D model profiles', 'start' )785 IF ( debug_output ) CALL debug_message( 'initializing with 1D model profiles', 'start' ) 808 786 ! 809 787 !-- Use solutions of the 1D model as initial profiles, … … 833 811 s(:,j,i) = s_init 834 812 ENDDO 835 ENDDO 813 ENDDO 836 814 ENDIF 837 815 ! … … 843 821 !-- Set velocities back to zero 844 822 u = MERGE( u, 0.0_wp, BTEST( wall_flags_total_0, 1 ) ) 845 v = MERGE( v, 0.0_wp, BTEST( wall_flags_total_0, 2 ) ) 846 ! 847 !-- WARNING: The extra boundary conditions set after running the 848 !-- ------- 1D model impose an error on the divergence one layer 849 !-- below the topography; need to correct later 850 !-- ATTENTION: Provisional correction for Piacsek & Williams 851 !-- --------- advection scheme: keep u and v zero one layer below 852 !-- the topography. 823 v = MERGE( v, 0.0_wp, BTEST( wall_flags_total_0, 2 ) ) 824 ! 825 !-- WARNING: The extra boundary conditions set after running the 1D model impose an error on 826 !-- -------- the divergence one layer below the topography; need to correct later 827 !-- ATTENTION: Provisional correction for Piacsek & Williams advection scheme: keep u and v 828 !-- ---------- zero one layer below the topography. 853 829 IF ( ibc_uv_b == 1 ) THEN 854 830 ! … … 863 839 ENDIF 864 840 ! 865 !-- Initialize surface variables, e.g. friction velocity, momentum 866 !-- fluxes, etc. 841 !-- Initialize surface variables, e.g. friction velocity, momentum fluxes, etc. 867 842 CALL init_surfaces 868 843 869 IF ( debug_output ) CALL debug_message( 'initializing with 1D model profiles', 'end' ) 870 871 ELSEIF ( INDEX(initializing_actions, 'set_constant_profiles') /= 0 ) & 872 THEN 873 874 IF ( debug_output ) CALL debug_message( 'initializing with constant profiles', 'start' ) 875 876 ! 877 !-- Use constructed initial profiles (velocity constant with height, 878 !-- temperature profile with constant gradient) 844 IF ( debug_output ) CALL debug_message( 'initializing with 1D model profiles', 'end' ) 845 846 ELSEIF ( INDEX(initializing_actions, 'set_constant_profiles') /= 0 ) THEN 847 848 IF ( debug_output ) CALL debug_message( 'initializing with constant profiles', 'start' ) 849 850 ! 851 !-- Use constructed initial profiles (velocity constant with height, temperature profile with 852 !-- constant gradient) 879 853 DO i = nxlg, nxrg 880 854 DO j = nysg, nyng … … 889 863 v = MERGE( v, 0.0_wp, BTEST( wall_flags_total_0, 2 ) ) 890 864 ! 891 !-- Set initial horizontal velocities at the lowest computational grid 892 !-- levels to zero in order to avoid too small time steps caused by the 893 !-- diffusion limit in the initial phase of a run (at k=1, dz/2 occurs 894 !-- in the limiting formula!). 895 !-- Please note, in case land- or urban-surface model is used and a 896 !-- spinup is applied, masking the lowest computational level is not 897 !-- possible as MOST as well as energy-balance parametrizations will not 898 !-- work with zero wind velocity. 899 IF ( ibc_uv_b /= 1 .AND. .NOT. spinup ) THEN 865 !-- Set initial horizontal velocities at the lowest computational grid levels to zero in order 866 !-- to avoid too small time steps caused by the diffusion limit in the initial phase of a run 867 !-- (at k=1, dz/2 occurs in the limiting formula!). 868 !-- Please note, in case land- or urban-surface model is used and a spinup is applied, masking 869 !-- the lowest computational level is not possible as MOST as well as energy-balance 870 !-- parametrizations will not work with zero wind velocity. 871 IF ( ibc_uv_b /= 1 .AND. .NOT. spinup ) THEN 900 872 DO i = nxlg, nxrg 901 873 DO j = nysg, nyng 902 874 DO k = nzb, nzt 903 u(k,j,i) = MERGE( u(k,j,i), 0.0_wp, & 904 BTEST( wall_flags_total_0(k,j,i), 20 ) ) 905 v(k,j,i) = MERGE( v(k,j,i), 0.0_wp, & 906 BTEST( wall_flags_total_0(k,j,i), 21 ) ) 875 u(k,j,i) = MERGE( u(k,j,i), 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 20 ) ) 876 v(k,j,i) = MERGE( v(k,j,i), 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 21 ) ) 907 877 ENDDO 908 878 ENDDO … … 917 887 ENDDO 918 888 ENDIF 919 889 920 890 IF ( passive_scalar ) THEN 921 891 DO i = nxlg, nxrg … … 927 897 928 898 ! 929 !-- Compute initial temperature field and other constants used in case 930 !-- of a sloping surface 899 !-- Compute initial temperature field and other constants used in case of a sloping surface. 931 900 IF ( sloping_surface ) CALL init_slope 932 901 ! 933 !-- Initialize surface variables, e.g. friction velocity, momentum 934 !-- fluxes, etc. 902 !-- Initialize surface variables, e.g. friction velocity, momentum fluxes, etc. 935 903 CALL init_surfaces 936 904 937 905 IF ( debug_output ) CALL debug_message( 'initializing with constant profiles', 'end' ) 938 906 939 ELSEIF ( INDEX(initializing_actions, 'by_user') /= 0 ) & 940 THEN 907 ELSEIF ( INDEX(initializing_actions, 'by_user') /= 0 ) THEN 941 908 942 909 IF ( debug_output ) CALL debug_message( 'initializing by user', 'start' ) 943 910 ! 944 !-- Pre-initialize surface variables, i.e. setting start- and end-indices 945 !-- at each (j,i)-location. Please note, this does not supersede946 !-- user-defined initialization of surface quantities.911 !-- Pre-initialize surface variables, i.e. setting start- and end-indices at each 912 !-- (j,i)-location. Please note, this does not supersede user-defined initialization of 913 !-- surface quantities. 947 914 CALL init_surfaces 948 915 ! … … 954 921 ENDIF 955 922 956 IF ( debug_output ) CALL debug_message( 'initializing statistics, boundary conditions, etc.', 'start' ) 923 IF ( debug_output ) THEN 924 CALL debug_message( 'initializing statistics, boundary conditions, etc.', 'start' ) 925 ENDIF 957 926 958 927 ! 959 928 !-- Bottom boundary 960 IF ( ibc_uv_b == 0 .OR.ibc_uv_b == 2 ) THEN929 IF ( ibc_uv_b == 0 .OR. ibc_uv_b == 2 ) THEN 961 930 u(nzb,:,:) = 0.0_wp 962 931 v(nzb,:,:) = 0.0_wp … … 975 944 976 945 ! 977 !-- Store initial profiles for output purposes etc.. Please note, in case of 978 !-- initialization of u, v, w, pt, and q via output data derived from larger 979 !-- scale models, data will not be horizontally homogeneous. Actually, a mean 980 !-- profile should be calculated before. 946 !-- Store initial profiles for output purposes etc.. Please note, in case of initialization of u, 947 !-- v, w, pt, and q via output data derived from larger scale models, data will not be 948 !-- horizontally homogeneous. Actually, a mean profile should be calculated before. 981 949 hom(:,1,5,:) = SPREAD( u(:,nys,nxl), 2, statistic_regions+1 ) 982 950 hom(:,1,6,:) = SPREAD( v(:,nys,nxl), 2, statistic_regions+1 ) … … 989 957 IF ( humidity ) THEN 990 958 ! 991 !-- Store initial profile of total water content, virtual potential 992 !-- temperature 959 !-- Store initial profile of total water content, virtual potential temperature 993 960 hom(:,1,26,:) = SPREAD( q(:,nys,nxl), 2, statistic_regions+1 ) 994 961 hom(:,1,29,:) = SPREAD( vpt(:,nys,nxl), 2, statistic_regions+1 ) 995 962 ! 996 !-- Store initial profile of mixing ratio and potential 997 !-- temperature 963 !-- Store initial profile of mixing ratio and potential temperature 998 964 IF ( bulk_cloud_model .OR. cloud_droplets ) THEN 999 965 hom(:,1,27,:) = SPREAD( q(:,nys,nxl), 2, statistic_regions+1 ) … … 1011 977 !-- Initialize the random number generators (from numerical recipes) 1012 978 CALL random_function_ini 1013 979 1014 980 IF ( random_generator == 'random-parallel' ) THEN 1015 981 CALL init_parallel_random_generator( nx, nys, nyn, nxl, nxr ) 1016 982 ENDIF 1017 983 ! 1018 !-- Set the reference state to be used in the buoyancy terms (for ocean runs 1019 !-- the reference state will be set (overwritten) in init_ocean)984 !-- Set the reference state to be used in the buoyancy terms (for ocean runs the reference state 985 !-- will be set (overwritten) in init_ocean). 1020 986 IF ( use_single_reference_value ) THEN 1021 IF ( .NOT.humidity ) THEN987 IF ( .NOT. humidity ) THEN 1022 988 ref_state(:) = pt_reference 1023 989 ELSE … … 1025 991 ENDIF 1026 992 ELSE 1027 IF ( .NOT.humidity ) THEN993 IF ( .NOT. humidity ) THEN 1028 994 ref_state(:) = pt_init(:) 1029 995 ELSE … … 1050 1016 1051 1017 ! 1052 !-- Impose temperature anomaly (advection test only) or warm air bubble 1053 !-- close to surface 1054 IF ( INDEX( initializing_actions, 'initialize_ptanom' ) /= 0 .OR. & 1018 !-- Impose temperature anomaly (advection test only) or warm air bubble close to surface. 1019 IF ( INDEX( initializing_actions, 'initialize_ptanom' ) /= 0 .OR. & 1055 1020 INDEX( initializing_actions, 'initialize_bubble' ) /= 0 ) THEN 1056 1021 CALL init_pt_anomaly 1057 1022 ENDIF 1058 1023 1059 1024 ! 1060 1025 !-- If required, change the surface temperature at the start of the 3D run … … 1066 1031 !-- If required, change the surface humidity/scalar at the start of the 3D 1067 1032 !-- run 1068 IF ( humidity .AND. q_surface_initial_change /= 0.0_wp ) &1033 IF ( humidity .AND. q_surface_initial_change /= 0.0_wp ) & 1069 1034 q(nzb,:,:) = q(nzb,:,:) + q_surface_initial_change 1070 1071 IF ( passive_scalar .AND. s_surface_initial_change /= 0.0_wp )&1035 1036 IF ( passive_scalar .AND. s_surface_initial_change /= 0.0_wp ) & 1072 1037 s(nzb,:,:) = s(nzb,:,:) + s_surface_initial_change 1073 1038 1074 1039 1075 1040 ! … … 1082 1047 q_p = q 1083 1048 ENDIF 1084 1049 1085 1050 IF ( passive_scalar ) THEN 1086 1051 ts_m = 0.0_wp 1087 1052 s_p = s 1088 ENDIF 1089 1090 IF ( debug_output ) CALL debug_message( 'initializing statistics, boundary conditions, etc.', 'end' ) 1053 ENDIF 1054 1055 IF ( debug_output ) THEN 1056 CALL debug_message( 'initializing statistics, boundary conditions, etc.', 'end' ) 1057 ENDIF 1091 1058 1092 1059 ELSEIF ( TRIM( initializing_actions ) == 'read_restart_data' .OR. & … … 1094 1061 THEN 1095 1062 1096 IF ( debug_output ) CALL debug_message( 'initializing in case of restart / cyclic_fill', 'start' ) 1097 ! 1098 !-- Initialize surface elements and its attributes, e.g. heat- and 1099 !-- momentumfluxes, roughness, scaling parameters. As number of surface 1100 !-- elements might be different between runs, e.g. in case of cyclic fill, 1101 !-- and not all surface elements are read, surface elements need to be 1102 !-- initialized before. 1103 !-- Please note, in case of cyclic fill, surfaces should be initialized 1104 !-- after restart data is read, else, individual settings of surface 1105 !-- parameters will be overwritten from data of precursor run, hence, 1106 !-- init_surfaces is called a second time after reading the restart data. 1107 CALL init_surfaces 1108 ! 1109 !-- When reading data for cyclic fill of 3D prerun data files, read 1110 !-- some of the global variables from the restart file which are required 1111 !-- for initializing the inflow 1063 IF ( debug_output ) THEN 1064 CALL debug_message( 'initializing in case of restart / cyclic_fill', 'start' ) 1065 ENDIF 1066 ! 1067 !-- Initialize surface elements and its attributes, e.g. heat- and momentumfluxes, roughness, 1068 !-- scaling parameters. As number of surface elements might be different between runs, e.g. in 1069 !-- case of cyclic fill, and not all surface elements are read, surface elements need to be 1070 !-- initialized before. 1071 !-- Please note, in case of cyclic fill, surfaces should be initialized after restart data is 1072 !-- read, else, individual settings of surface parameters will be overwritten from data of 1073 !-- precursor run, hence, init_surfaces is called a second time after reading the restart data. 1074 CALL init_surfaces 1075 ! 1076 !-- When reading data for cyclic fill of 3D prerun data files, read some of the global variables 1077 !-- from the restart file which are required for initializing the inflow 1112 1078 IF ( TRIM( initializing_actions ) == 'cyclic_fill' ) THEN 1113 1079 … … 1133 1099 #endif 1134 1100 ENDDO 1135 1136 1101 1102 1137 1103 IF ( TRIM( initializing_actions ) == 'cyclic_fill' ) THEN 1138 1104 1139 1105 ! 1140 !-- In case of cyclic fill, call init_surfaces a second time, so that 1141 !-- surface properties such as heat fluxes are initialized as prescribed.1106 !-- In case of cyclic fill, call init_surfaces a second time, so that surface properties such 1107 !-- as heat fluxes are initialized as prescribed. 1142 1108 CALL init_surfaces 1143 1109 1144 1110 ! 1145 !-- Overwrite u_init, v_init, pt_init, q_init and s_init with the 1146 !-- horizontally mean (hom) vertical profiles from the end 1147 !-- of the prerun, because these profiles shall be used as the reference 1148 !-- state for the rayleigh damping and the pt_damping. This is especially 1149 !-- important for the use of large_scale_subsidence, because the 1150 !-- reference temperature in the free atmosphere changes in time. 1111 !-- Overwrite u_init, v_init, pt_init, q_init and s_init with the horizontally mean (hom) 1112 !-- vertical profiles from the end of the prerun, because these profiles shall be used as the 1113 !-- reference state for the rayleigh damping and the pt_damping. This is especially important 1114 !-- for the use of large_scale_subsidence, because the reference temperature in the free 1115 !-- atmosphere changes in time. 1151 1116 u_init(:) = hom_sum(:,1,0) 1152 1117 v_init(:) = hom_sum(:,2,0) 1153 1118 pt_init(:) = hom_sum(:,4,0) 1154 IF ( humidity ) & 1155 q_init(:) = hom_sum(:,41,0) 1156 IF ( passive_scalar ) & 1157 s_init(:) = hom_sum(:,115,0) 1158 ENDIF 1159 ! 1160 !-- In case of complex terrain and cyclic fill method as initialization, 1161 !-- shift initial data in the vertical direction for each point in the 1162 !-- x-y-plane depending on local surface height 1163 IF ( complex_terrain .AND. & 1164 TRIM( initializing_actions ) == 'cyclic_fill' ) THEN 1119 IF ( humidity ) q_init(:) = hom_sum(:,41,0) 1120 IF ( passive_scalar ) s_init(:) = hom_sum(:,115,0) 1121 ENDIF 1122 ! 1123 !-- In case of complex terrain and cyclic fill method as initialization, shift initial data in 1124 !-- the vertical direction for each point in the x-y-plane depending on local surface height. 1125 IF ( complex_terrain .AND. TRIM( initializing_actions ) == 'cyclic_fill' ) THEN 1165 1126 DO i = nxlg, nxrg 1166 1127 DO j = nysg, nyng … … 1170 1131 nz_s_shift = topo_top_ind(j,i,0) 1171 1132 1172 u(nz_u_shift:nzt+1,j,i) = u(0:nzt+1-nz_u_shift,j,i) 1133 u(nz_u_shift:nzt+1,j,i) = u(0:nzt+1-nz_u_shift,j,i) 1173 1134 1174 1135 v(nz_v_shift:nzt+1,j,i) = v(0:nzt+1-nz_v_shift,j,i) … … 1183 1144 ! 1184 1145 !-- Initialization of the turbulence recycling method 1185 IF ( TRIM( initializing_actions ) == 'cyclic_fill' .AND. & 1186 turbulent_inflow ) THEN 1146 IF ( TRIM( initializing_actions ) == 'cyclic_fill' .AND. turbulent_inflow ) THEN 1187 1147 ! 1188 1148 !-- First store the profiles to be used at the inflow. 1189 !-- These profiles are the (temporally) and horizontally averaged vertical 1190 !-- profiles from the prerun. Alternatively, prescribed profiles 1191 !-- for u,v-components can be used. 1149 !-- These profiles are the (temporally) and horizontally averaged vertical profiles from the 1150 !-- prerun. Alternatively, prescribed profiles for u,v-components can be used. 1192 1151 ALLOCATE( mean_inflow_profiles(nzb:nzt+1,1:num_mean_inflow_profiles) ) 1193 1152 … … 1200 1159 ENDIF 1201 1160 mean_inflow_profiles(:,4) = hom_sum(:,4,0) ! pt 1202 IF ( humidity ) & 1203 mean_inflow_profiles(:,6) = hom_sum(:,41,0) ! q 1204 IF ( passive_scalar ) & 1205 mean_inflow_profiles(:,7) = hom_sum(:,115,0) ! s 1206 1207 ! 1208 !-- In case of complex terrain, determine vertical displacement at inflow 1209 !-- boundary and adjust mean inflow profiles 1161 IF ( humidity ) mean_inflow_profiles(:,6) = hom_sum(:,41,0) ! q 1162 IF ( passive_scalar ) mean_inflow_profiles(:,7) = hom_sum(:,115,0) ! s 1163 1164 ! 1165 !-- In case of complex terrain, determine vertical displacement at inflow boundary and adjust 1166 !-- mean inflow profiles 1210 1167 IF ( complex_terrain ) THEN 1211 IF ( nxlg <= 0 .AND. nxrg >= 0 .AND. nysg <= 0 .AND.nyng >= 0 ) THEN1168 IF ( nxlg <= 0 .AND. nxrg >= 0 .AND. nysg <= 0 .AND. nyng >= 0 ) THEN 1212 1169 nz_u_shift_l = topo_top_ind(j,i,1) 1213 1170 nz_v_shift_l = topo_top_ind(j,i,2) … … 1222 1179 1223 1180 #if defined( __parallel ) 1224 CALL MPI_ALLREDUCE(nz_u_shift_l, nz_u_shift, 1, MPI_INTEGER, & 1225 MPI_MAX, comm2d, ierr) 1226 CALL MPI_ALLREDUCE(nz_v_shift_l, nz_v_shift, 1, MPI_INTEGER, & 1227 MPI_MAX, comm2d, ierr) 1228 CALL MPI_ALLREDUCE(nz_w_shift_l, nz_w_shift, 1, MPI_INTEGER, & 1229 MPI_MAX, comm2d, ierr) 1230 CALL MPI_ALLREDUCE(nz_s_shift_l, nz_s_shift, 1, MPI_INTEGER, & 1231 MPI_MAX, comm2d, ierr) 1181 CALL MPI_ALLREDUCE( nz_u_shift_l, nz_u_shift, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr ) 1182 CALL MPI_ALLREDUCE( nz_v_shift_l, nz_v_shift, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr ) 1183 CALL MPI_ALLREDUCE( nz_w_shift_l, nz_w_shift, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr ) 1184 CALL MPI_ALLREDUCE( nz_s_shift_l, nz_s_shift, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr ) 1232 1185 #else 1233 1186 nz_u_shift = nz_u_shift_l … … 1248 1201 1249 1202 ! 1250 !-- If necessary, adjust the horizontal flow field to the prescribed 1251 !-- profiles 1203 !-- If necessary, adjust the horizontal flow field to the prescribed profiles 1252 1204 IF ( use_prescribed_profile_data ) THEN 1253 1205 DO i = nxlg, nxrg … … 1262 1214 1263 1215 ! 1264 !-- Use these mean profiles at the inflow (provided that Dirichlet 1265 !-- conditions are used) 1216 !-- Use these mean profiles at the inflow (provided that Dirichlet conditions are used) 1266 1217 IF ( bc_dirichlet_l ) THEN 1267 1218 DO j = nysg, nyng … … 1271 1222 w(k,j,nxlg:-1) = 0.0_wp 1272 1223 pt(k,j,nxlg:-1) = mean_inflow_profiles(k,4) 1273 IF ( humidity ) & 1274 q(k,j,nxlg:-1) = mean_inflow_profiles(k,6) 1275 IF ( passive_scalar ) & 1276 s(k,j,nxlg:-1) = mean_inflow_profiles(k,7) 1224 IF ( humidity ) q(k,j,nxlg:-1) = mean_inflow_profiles(k,6) 1225 IF ( passive_scalar ) s(k,j,nxlg:-1) = mean_inflow_profiles(k,7) 1277 1226 ENDDO 1278 1227 ENDDO … … 1280 1229 1281 1230 ! 1282 !-- Calculate the damping factors to be used at the inflow. For a 1283 !-- turbulent inflow the turbulent fluctuations have to be limited 1284 !-- vertically because otherwise the turbulent inflow layer will grow 1285 !-- in time. 1231 !-- Calculate the damping factors to be used at the inflow. For a turbulent inflow the 1232 !-- turbulent fluctuations have to be limited vertically because otherwise the turbulent 1233 !-- inflow layer will grow in time. 1286 1234 IF ( inflow_damping_height == 9999999.9_wp ) THEN 1287 1235 ! 1288 !-- Default: use the inversion height calculated by the prerun; if 1289 !-- this is zero, inflow_damping_height must be explicitly 1290 !-- specified. 1236 !-- Default: use the inversion height calculated by the prerun; if this is zero, 1237 !-- inflow_damping_height must be explicitly specified. 1291 1238 IF ( hom_sum(nzb+6,pr_palm,0) /= 0.0_wp ) THEN 1292 1239 inflow_damping_height = hom_sum(nzb+6,pr_palm,0) 1293 1240 ELSE 1294 WRITE( message_string, * ) 'inflow_damping_height must be ', &1295 'explicitly specified because&the inversion height ',&1296 'calculated by the prerun is zero.'1241 WRITE( message_string, * ) 'inflow_damping_height must be ', & 1242 'explicitly specified because&the inversion height ', & 1243 'calculated by the prerun is zero.' 1297 1244 CALL message( 'init_3d_model', 'PA0318', 1, 2, 0, 6, 0 ) 1298 1245 ENDIF … … 1302 1249 IF ( inflow_damping_width == 9999999.9_wp ) THEN 1303 1250 ! 1304 !-- Default for the transition range: one tenth of the undamped 1305 !-- layer 1251 !-- Default for the transition range: one tenth of the undamped layer 1306 1252 inflow_damping_width = 0.1_wp * inflow_damping_height 1307 1253 … … 1315 1261 inflow_damping_factor(k) = 1.0_wp 1316 1262 ELSEIF ( zu(k) <= ( inflow_damping_height + inflow_damping_width ) ) THEN 1317 inflow_damping_factor(k) = 1.0_wp - & 1318 ( zu(k) - inflow_damping_height ) / & 1319 inflow_damping_width 1263 inflow_damping_factor(k) = 1.0_wp - & 1264 ( zu(k) - inflow_damping_height ) / inflow_damping_width 1320 1265 ELSE 1321 1266 inflow_damping_factor(k) = 0.0_wp … … 1328 1273 ! 1329 1274 !-- Inside buildings set velocities back to zero 1330 IF ( TRIM( initializing_actions ) == 'cyclic_fill' .AND. & 1331 topography /= 'flat' ) THEN 1275 IF ( TRIM( initializing_actions ) == 'cyclic_fill' .AND. topography /= 'flat' ) THEN 1332 1276 ! 1333 1277 !-- Inside buildings set velocities back to zero. … … 1337 1281 DO j = nysg, nyng 1338 1282 DO k = nzb, nzt 1339 u(k,j,i) = MERGE( u(k,j,i), 0.0_wp, & 1340 BTEST( wall_flags_total_0(k,j,i), 1 ) ) 1341 v(k,j,i) = MERGE( v(k,j,i), 0.0_wp, & 1342 BTEST( wall_flags_total_0(k,j,i), 2 ) ) 1343 w(k,j,i) = MERGE( w(k,j,i), 0.0_wp, & 1344 BTEST( wall_flags_total_0(k,j,i), 3 ) ) 1283 u(k,j,i) = MERGE( u(k,j,i), 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 1 ) ) 1284 v(k,j,i) = MERGE( v(k,j,i), 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 2 ) ) 1285 w(k,j,i) = MERGE( w(k,j,i), 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 3 ) ) 1345 1286 ENDDO 1346 1287 ENDDO … … 1350 1291 1351 1292 ! 1352 !-- Calculate initial temperature field and other constants used in case 1353 !-- of a sloping surface 1293 !-- Calculate initial temperature field and other constants used in case of a sloping surface 1354 1294 IF ( sloping_surface ) CALL init_slope 1355 1295 1356 1296 ! 1357 !-- Initialize new time levels (only done in order to set boundary values 1358 !-- including ghost points) 1297 !-- Initialize new time levels (only done in order to set boundary values including ghost points) 1359 1298 pt_p = pt; u_p = u; v_p = v; w_p = w 1360 1299 IF ( humidity ) THEN … … 1363 1302 IF ( passive_scalar ) s_p = s 1364 1303 ! 1365 !-- Allthough tendency arrays are set in prognostic_equations, they have 1366 !-- have to be predefined here because they are used (but multiplied with 0) 1367 !-- there before they are set. 1304 !-- Allthough tendency arrays are set in prognostic_equations, they have have to be predefined 1305 !-- here because they are used (but multiplied with 0) there before they are set. 1368 1306 tpt_m = 0.0_wp; tu_m = 0.0_wp; tv_m = 0.0_wp; tw_m = 0.0_wp 1369 1307 IF ( humidity ) THEN … … 1372 1310 IF ( passive_scalar ) ts_m = 0.0_wp 1373 1311 1374 IF ( debug_output ) CALL debug_message( 'initializing in case of restart / cyclic_fill', 'end' ) 1312 IF ( debug_output ) THEN 1313 CALL debug_message( 'initializing in case of restart / cyclic_fill', 'end' ) 1314 ENDIF 1375 1315 1376 1316 ELSE … … 1405 1345 w_m_n(:,:,:) = w(:,ny-1:ny,:) 1406 1346 ENDIF 1407 1347 1408 1348 ENDIF 1409 1349 … … 1420 1360 DO j = nys, nyn 1421 1361 DO k = nzb+1, nzt 1422 volume_flow_initial_l(1) = volume_flow_initial_l(1) + &1423 u_init(k) * dzw(k) &1424 * MERGE( 1.0_wp, 0.0_wp,&1425 BTEST( wall_flags_total_0(k,j,nxr), 1 )&1426 )1427 1428 volume_flow_area_l(1) = volume_flow_area_l(1) + dzw(k) &1429 * MERGE( 1.0_wp, 0.0_wp,&1430 BTEST( wall_flags_total_0(k,j,nxr), 1 )&1431 )1362 volume_flow_initial_l(1) = volume_flow_initial_l(1) + & 1363 u_init(k) * dzw(k) & 1364 * MERGE( 1.0_wp, 0.0_wp, & 1365 BTEST( wall_flags_total_0(k,j,nxr), 1 ) & 1366 ) 1367 1368 volume_flow_area_l(1) = volume_flow_area_l(1) + dzw(k) & 1369 * MERGE( 1.0_wp, 0.0_wp, & 1370 BTEST( wall_flags_total_0(k,j,nxr), 1 ) & 1371 ) 1432 1372 ENDDO 1433 1373 ENDDO 1434 1374 ENDIF 1435 1375 1436 1376 IF ( nyn == ny ) THEN 1437 1377 DO i = nxl, nxr 1438 1378 DO k = nzb+1, nzt 1439 volume_flow_initial_l(2) = volume_flow_initial_l(2) + &1440 v_init(k) * dzw(k) &1441 * MERGE( 1.0_wp, 0.0_wp,&1442 BTEST( wall_flags_total_0(k,nyn,i), 2 )&1443 )1444 volume_flow_area_l(2) = volume_flow_area_l(2) + dzw(k) &1445 * MERGE( 1.0_wp, 0.0_wp,&1446 BTEST( wall_flags_total_0(k,nyn,i), 2 )&1447 )1379 volume_flow_initial_l(2) = volume_flow_initial_l(2) + & 1380 v_init(k) * dzw(k) & 1381 * MERGE( 1.0_wp, 0.0_wp, & 1382 BTEST( wall_flags_total_0(k,nyn,i), 2 ) & 1383 ) 1384 volume_flow_area_l(2) = volume_flow_area_l(2) + dzw(k) & 1385 * MERGE( 1.0_wp, 0.0_wp, & 1386 BTEST( wall_flags_total_0(k,nyn,i), 2 ) & 1387 ) 1448 1388 ENDDO 1449 1389 ENDDO … … 1451 1391 1452 1392 #if defined( __parallel ) 1453 CALL MPI_ALLREDUCE( volume_flow_initial_l(1), volume_flow_initial(1), &1454 2, MPI_REAL,MPI_SUM, comm2d, ierr )1455 CALL MPI_ALLREDUCE( volume_flow_area_l(1), volume_flow_area(1), 1456 2, MPI_REAL, MPI_SUM,comm2d, ierr )1393 CALL MPI_ALLREDUCE( volume_flow_initial_l(1), volume_flow_initial(1), 2, MPI_REAL, & 1394 MPI_SUM, comm2d, ierr ) 1395 CALL MPI_ALLREDUCE( volume_flow_area_l(1), volume_flow_area(1), 2, MPI_REAL, MPI_SUM, & 1396 comm2d, ierr ) 1457 1397 1458 1398 #else 1459 1399 volume_flow_initial = volume_flow_initial_l 1460 1400 volume_flow_area = volume_flow_area_l 1461 #endif 1401 #endif 1462 1402 1463 1403 ELSEIF ( TRIM( initializing_actions ) == 'cyclic_fill' ) THEN … … 1469 1409 DO j = nys, nyn 1470 1410 DO k = nzb+1, nzt 1471 volume_flow_initial_l(1) = volume_flow_initial_l(1) + &1472 hom_sum(k,1,0) * dzw(k) &1473 * MERGE( 1.0_wp, 0.0_wp,&1474 BTEST( wall_flags_total_0(k,j,nx), 1 )&1475 )1476 volume_flow_area_l(1) = volume_flow_area_l(1) + dzw(k) &1477 * MERGE( 1.0_wp, 0.0_wp,&1478 BTEST( wall_flags_total_0(k,j,nx), 1 )&1479 )1411 volume_flow_initial_l(1) = volume_flow_initial_l(1) + & 1412 hom_sum(k,1,0) * dzw(k) & 1413 * MERGE( 1.0_wp, 0.0_wp, & 1414 BTEST( wall_flags_total_0(k,j,nx), 1 ) & 1415 ) 1416 volume_flow_area_l(1) = volume_flow_area_l(1) + dzw(k) & 1417 * MERGE( 1.0_wp, 0.0_wp, & 1418 BTEST( wall_flags_total_0(k,j,nx), 1 ) & 1419 ) 1480 1420 ENDDO 1481 1421 ENDDO 1482 1422 ENDIF 1483 1423 1484 1424 IF ( nyn == ny ) THEN 1485 1425 DO i = nxl, nxr 1486 1426 DO k = nzb+1, nzt 1487 volume_flow_initial_l(2) = volume_flow_initial_l(2) + &1488 hom_sum(k,2,0) * dzw(k) &1489 * MERGE( 1.0_wp, 0.0_wp,&1490 BTEST( wall_flags_total_0(k,ny,i), 2 )&1491 )1492 volume_flow_area_l(2) = volume_flow_area_l(2) + dzw(k) &1493 * MERGE( 1.0_wp, 0.0_wp,&1494 BTEST( wall_flags_total_0(k,ny,i), 2 )&1495 )1427 volume_flow_initial_l(2) = volume_flow_initial_l(2) + & 1428 hom_sum(k,2,0) * dzw(k) & 1429 * MERGE( 1.0_wp, 0.0_wp, & 1430 BTEST( wall_flags_total_0(k,ny,i), 2 ) & 1431 ) 1432 volume_flow_area_l(2) = volume_flow_area_l(2) + dzw(k) & 1433 * MERGE( 1.0_wp, 0.0_wp, & 1434 BTEST( wall_flags_total_0(k,ny,i), 2 ) & 1435 ) 1496 1436 ENDDO 1497 1437 ENDDO … … 1499 1439 1500 1440 #if defined( __parallel ) 1501 CALL MPI_ALLREDUCE( volume_flow_initial_l(1), volume_flow_initial(1), &1502 2, MPI_REAL,MPI_SUM, comm2d, ierr )1503 CALL MPI_ALLREDUCE( volume_flow_area_l(1), volume_flow_area(1), 1504 2, MPI_REAL, MPI_SUM,comm2d, ierr )1441 CALL MPI_ALLREDUCE( volume_flow_initial_l(1), volume_flow_initial(1), 2, MPI_REAL, & 1442 MPI_SUM, comm2d, ierr ) 1443 CALL MPI_ALLREDUCE( volume_flow_area_l(1), volume_flow_area(1), 2, MPI_REAL, MPI_SUM, & 1444 comm2d, ierr ) 1505 1445 1506 1446 #else 1507 1447 volume_flow_initial = volume_flow_initial_l 1508 1448 volume_flow_area = volume_flow_area_l 1509 #endif 1449 #endif 1510 1450 1511 1451 ELSEIF ( TRIM( initializing_actions ) /= 'read_restart_data' ) THEN … … 1517 1457 DO j = nys, nyn 1518 1458 DO k = nzb+1, nzt 1519 volume_flow_initial_l(1) = volume_flow_initial_l(1) + &1520 u(k,j,nx) * dzw(k) &1521 * MERGE( 1.0_wp, 0.0_wp,&1522 BTEST( wall_flags_total_0(k,j,nx), 1 )&1523 )1524 volume_flow_area_l(1) = volume_flow_area_l(1) + dzw(k) &1525 * MERGE( 1.0_wp, 0.0_wp,&1526 BTEST( wall_flags_total_0(k,j,nx), 1 )&1527 )1459 volume_flow_initial_l(1) = volume_flow_initial_l(1) + & 1460 u(k,j,nx) * dzw(k) & 1461 * MERGE( 1.0_wp, 0.0_wp, & 1462 BTEST( wall_flags_total_0(k,j,nx), 1 ) & 1463 ) 1464 volume_flow_area_l(1) = volume_flow_area_l(1) + dzw(k) & 1465 * MERGE( 1.0_wp, 0.0_wp, & 1466 BTEST( wall_flags_total_0(k,j,nx), 1 ) & 1467 ) 1528 1468 ENDDO 1529 1469 ENDDO 1530 1470 ENDIF 1531 1471 1532 1472 IF ( nyn == ny ) THEN 1533 1473 DO i = nxl, nxr 1534 1474 DO k = nzb+1, nzt 1535 volume_flow_initial_l(2) = volume_flow_initial_l(2) + &1536 v(k,ny,i) * dzw(k) &1537 * MERGE( 1.0_wp, 0.0_wp,&1538 BTEST( wall_flags_total_0(k,ny,i), 2 )&1539 )1540 volume_flow_area_l(2) = volume_flow_area_l(2) + dzw(k) &1541 * MERGE( 1.0_wp, 0.0_wp,&1542 BTEST( wall_flags_total_0(k,ny,i), 2 )&1543 )1475 volume_flow_initial_l(2) = volume_flow_initial_l(2) + & 1476 v(k,ny,i) * dzw(k) & 1477 * MERGE( 1.0_wp, 0.0_wp, & 1478 BTEST( wall_flags_total_0(k,ny,i), 2 ) & 1479 ) 1480 volume_flow_area_l(2) = volume_flow_area_l(2) + dzw(k) & 1481 * MERGE( 1.0_wp, 0.0_wp, & 1482 BTEST( wall_flags_total_0(k,ny,i), 2 ) & 1483 ) 1544 1484 ENDDO 1545 1485 ENDDO … … 1547 1487 1548 1488 #if defined( __parallel ) 1549 CALL MPI_ALLREDUCE( volume_flow_initial_l(1), volume_flow_initial(1), &1550 2, MPI_REAL,MPI_SUM, comm2d, ierr )1551 CALL MPI_ALLREDUCE( volume_flow_area_l(1), volume_flow_area(1), 1552 2, MPI_REAL, MPI_SUM,comm2d, ierr )1489 CALL MPI_ALLREDUCE( volume_flow_initial_l(1), volume_flow_initial(1), 2, MPI_REAL, & 1490 MPI_SUM, comm2d, ierr ) 1491 CALL MPI_ALLREDUCE( volume_flow_area_l(1), volume_flow_area(1), 2, MPI_REAL, MPI_SUM, & 1492 comm2d, ierr ) 1553 1493 1554 1494 #else 1555 1495 volume_flow_initial = volume_flow_initial_l 1556 1496 volume_flow_area = volume_flow_area_l 1557 #endif 1558 1559 ENDIF 1560 1561 ! 1562 !-- In case of 'bulk_velocity' mode, volume_flow_initial is calculated 1563 !-- from u|v_bulk instead 1497 #endif 1498 1499 ENDIF 1500 1501 ! 1502 !-- In case of 'bulk_velocity' mode, volume_flow_initial is calculated from u|v_bulk instead 1564 1503 IF ( TRIM( conserve_volume_flow_mode ) == 'bulk_velocity' ) THEN 1565 1504 volume_flow_initial(1) = u_bulk * volume_flow_area(1) … … 1569 1508 ENDIF 1570 1509 ! 1571 !-- In the following, surface properties can be further initialized with 1572 !-- input from static driver file. 1573 !-- At the moment this affects only default surfaces. For example, 1574 !-- roughness length or sensible / latent heat fluxes can be initialized 1575 !-- heterogeneously for default surfaces. Therefore, a generic routine 1576 !-- from netcdf_data_input_mod is called to read a 2D array. 1510 !-- In the following, surface properties can be further initialized with input from static driver 1511 !-- file. 1512 !-- At the moment this affects only default surfaces. For example, roughness length or sensible / 1513 !-- latent heat fluxes can be initialized heterogeneously for default surfaces. Therefore, a generic 1514 !-- routine from netcdf_data_input_mod is called to read a 2D array. 1577 1515 IF ( input_pids_static ) THEN 1578 1516 ! … … 1583 1521 !-- Open the static input file 1584 1522 #if defined( __netcdf ) 1585 CALL open_read_file( TRIM( input_file_static ) // & 1586 TRIM( coupling_char ), & 1587 pids_id ) 1588 1523 CALL open_read_file( TRIM( input_file_static ) // & 1524 TRIM( coupling_char ), pids_id ) 1525 1589 1526 CALL inquire_num_variables( pids_id, num_var_pids ) 1590 1527 ! … … 1593 1530 CALL inquire_variable_names( pids_id, vars_pids ) 1594 1531 ! 1595 !-- Input roughness length. 1532 !-- Input roughness length. 1596 1533 IF ( check_existence( vars_pids, 'z0' ) ) THEN 1597 1534 ! 1598 1535 !-- Read _FillValue attribute 1599 CALL get_attribute( pids_id, char_fill, tmp_2d%fill, & 1600 .FALSE., 'z0' ) 1601 ! 1602 !-- Read variable 1603 CALL get_variable( pids_id, 'z0', tmp_2d%var, & 1604 nxl, nxr, nys, nyn ) 1605 ! 1606 !-- Initialize roughness length. Note, z0 will be only initialized at 1607 !-- default-type surfaces. At natural or urban z0 is implicitly 1608 !-- initialized by the respective parameter lists. 1609 !-- Initialize horizontal surface elements. 1610 CALL init_single_surface_properties( surf_def_h(0)%z0, & 1611 tmp_2d%var, & 1612 surf_def_h(0)%ns, & 1613 tmp_2d%fill, & 1614 surf_def_h(0)%i, & 1615 surf_def_h(0)%j ) 1616 ! 1617 !-- Initialize roughness also at vertical surface elements. 1618 !-- Note, the actual 2D input arrays are only defined on the 1619 !-- subdomain. Therefore, pass the index arrays with their respective 1620 !-- offset values. 1621 DO l = 0, 3 1622 CALL init_single_surface_properties( & 1623 surf_def_v(l)%z0, & 1624 tmp_2d%var, & 1625 surf_def_v(l)%ns, & 1626 tmp_2d%fill, & 1627 surf_def_v(l)%i + surf_def_v(l)%ioff, & 1628 surf_def_v(l)%j + surf_def_v(l)%joff ) 1536 CALL get_attribute( pids_id, char_fill, tmp_2d%fill, .FALSE., 'z0' ) 1537 ! 1538 !-- Read variable 1539 CALL get_variable( pids_id, 'z0', tmp_2d%var, nxl, nxr, nys, nyn ) 1540 ! 1541 !-- Initialize roughness length. Note, z0 will be only initialized at default-type surfaces. 1542 !-- At natural or urban z0 is implicitly initialized by the respective parameter lists. 1543 !-- Initialize horizontal surface elements. 1544 CALL init_single_surface_properties( surf_def_h(0)%z0, tmp_2d%var, surf_def_h(0)%ns, & 1545 tmp_2d%fill, surf_def_h(0)%i, surf_def_h(0)%j ) 1546 ! 1547 !-- Initialize roughness also at vertical surface elements. 1548 !-- Note, the actual 2D input arrays are only defined on the subdomain. Therefore, pass the 1549 !-- index arrays with their respective offset values. 1550 DO l = 0, 3 1551 CALL init_single_surface_properties( surf_def_v(l)%z0, tmp_2d%var, surf_def_v(l)%ns, & 1552 tmp_2d%fill, surf_def_v(l)%i+surf_def_v(l)%ioff, & 1553 surf_def_v(l)%j+surf_def_v(l)%joff ) 1629 1554 ENDDO 1630 1631 ENDIF 1632 ! 1633 !-- Input surface sensible heat flux. 1555 1556 ENDIF 1557 ! 1558 !-- Input surface sensible heat flux. 1634 1559 IF ( check_existence( vars_pids, 'shf' ) ) THEN 1635 1560 ! 1636 1561 !-- Read _FillValue attribute 1637 CALL get_attribute( pids_id, char_fill, tmp_2d%fill, & 1638 .FALSE., 'shf' ) 1562 CALL get_attribute( pids_id, char_fill, tmp_2d%fill, .FALSE., 'shf' ) 1639 1563 ! 1640 1564 !-- Read variable 1641 CALL get_variable( pids_id, 'shf', tmp_2d%var, & 1642 nxl, nxr, nys, nyn ) 1643 ! 1644 !-- Initialize heat flux. Note, shf will be only initialized at 1645 !-- default-type surfaces. At natural or urban shf is implicitly 1646 !-- initialized by the respective parameter lists. 1565 CALL get_variable( pids_id, 'shf', tmp_2d%var, nxl, nxr, nys, nyn ) 1566 ! 1567 !-- Initialize heat flux. Note, shf will be only initialized at default-type surfaces. At 1568 !-- natural or urban shf is implicitly initialized by the respective parameter lists. 1647 1569 !-- Initialize horizontal surface elements. 1648 CALL init_single_surface_properties( surf_def_h(0)%shf, & 1649 tmp_2d%var, & 1650 surf_def_h(0)%ns, & 1651 tmp_2d%fill, & 1652 surf_def_h(0)%i, & 1653 surf_def_h(0)%j ) 1570 CALL init_single_surface_properties( surf_def_h(0)%shf, tmp_2d%var, surf_def_h(0)%ns, & 1571 tmp_2d%fill, surf_def_h(0)%i, surf_def_h(0)%j ) 1654 1572 ! 1655 1573 !-- Initialize heat flux also at vertical surface elements. 1656 !-- Note, the actual 2D input arrays are only defined on the 1657 !-- subdomain. Therefore, pass the index arrays with their respective 1658 !-- offset values. 1574 !-- Note, the actual 2D input arrays are only defined on the subdomain. Therefore, pass the 1575 !-- index arrays with their respective offset values. 1659 1576 DO l = 0, 3 1660 CALL init_single_surface_properties( & 1661 surf_def_v(l)%shf, & 1662 tmp_2d%var, & 1663 surf_def_v(l)%ns, & 1664 tmp_2d%fill, & 1665 surf_def_v(l)%i + surf_def_v(l)%ioff, & 1666 surf_def_v(l)%j + surf_def_v(l)%joff ) 1577 CALL init_single_surface_properties( surf_def_v(l)%shf, tmp_2d%var, surf_def_v(l)%ns, & 1578 tmp_2d%fill, surf_def_v(l)%i+surf_def_v(l)%ioff, & 1579 surf_def_v(l)%j+surf_def_v(l)%joff ) 1667 1580 ENDDO 1668 1581 1669 1582 ENDIF 1670 1583 ! 1671 !-- Input surface sensible heat flux. 1584 !-- Input surface sensible heat flux. 1672 1585 IF ( check_existence( vars_pids, 'qsws' ) ) THEN 1673 1586 ! … … 1680 1593 nxl, nxr, nys, nyn ) 1681 1594 ! 1682 !-- Initialize latent heat flux. Note, qsws will be only initialized at 1683 !-- default-type surfaces. At natural or urban qsws is implicitly 1684 !-- initialized by the respective parameter lists. 1595 !-- Initialize latent heat flux. Note, qsws will be only initialized at default-type surfaces. 1596 !-- At natural or urban qsws is implicitly initialized by the respective parameter lists. 1685 1597 !-- Initialize horizontal surface elements. 1686 CALL init_single_surface_properties( surf_def_h(0)%qsws, & 1687 tmp_2d%var, & 1688 surf_def_h(0)%ns, & 1689 tmp_2d%fill, & 1690 surf_def_h(0)%i, & 1691 surf_def_h(0)%j ) 1598 CALL init_single_surface_properties( surf_def_h(0)%qsws, tmp_2d%var, surf_def_h(0)%ns, & 1599 tmp_2d%fill, surf_def_h(0)%i, surf_def_h(0)%j ) 1692 1600 ! 1693 1601 !-- Initialize latent heat flux also at vertical surface elements. 1694 !-- Note, the actual 2D input arrays are only defined on the 1695 !-- subdomain. Therefore, pass the index arrays with their respective 1696 !-- offset values. 1602 !-- Note, the actual 2D input arrays are only defined on the subdomain. Therefore, pass the 1603 !-- index arrays with their respective offset values. 1697 1604 DO l = 0, 3 1698 CALL init_single_surface_properties( & 1699 surf_def_v(l)%qsws, & 1700 tmp_2d%var, & 1701 surf_def_v(l)%ns, & 1702 tmp_2d%fill, & 1703 surf_def_v(l)%i + surf_def_v(l)%ioff, & 1704 surf_def_v(l)%j + surf_def_v(l)%joff ) 1605 CALL init_single_surface_properties( surf_def_v(l)%qsws, tmp_2d%var, surf_def_v(l)%ns,& 1606 tmp_2d%fill, surf_def_v(l)%i+surf_def_v(l)%ioff, & 1607 surf_def_v(l)%j+surf_def_v(l)%joff ) 1705 1608 ENDDO 1706 1609 1707 1610 ENDIF 1708 1611 ! 1709 !-- Additional variables, can be initialized the 1612 !-- Additional variables, can be initialized the 1710 1613 !-- same way. 1711 1614 … … 1713 1616 !-- Finally, close the input file and deallocate temporary arrays 1714 1617 DEALLOCATE( vars_pids ) 1715 1618 1716 1619 CALL close_input_file( pids_id ) 1717 1620 #endif … … 1719 1622 ENDIF 1720 1623 ! 1721 !-- Finally, if random_heatflux is set, disturb shf at horizontal 1722 !-- surfaces. Actually, this should be done in surface_mod, where all other 1723 !-- initializations of surface quantities are done. However, this 1724 !-- would create a ring dependency, hence, it is done here. Maybe delete 1725 !-- disturb_heatflux and tranfer the respective code directly into the 1726 !-- initialization in surface_mod. 1727 IF ( TRIM( initializing_actions ) /= 'read_restart_data' .AND. & 1624 !-- Finally, if random_heatflux is set, disturb shf at horizontal surfaces. Actually, this should be 1625 !-- done in surface_mod, where all other initializations of surface quantities are done. However, 1626 !-- this would create a ring dependency, hence, it is done here. Maybe delete disturb_heatflux and 1627 !-- tranfer the respective code directly into the initialization in surface_mod. 1628 IF ( TRIM( initializing_actions ) /= 'read_restart_data' .AND. & 1728 1629 TRIM( initializing_actions ) /= 'cyclic_fill' ) THEN 1729 1730 IF ( use_surface_fluxes .AND. constant_heatflux .AND. & 1731 random_heatflux ) THEN 1630 1631 IF ( use_surface_fluxes .AND. constant_heatflux .AND. random_heatflux ) THEN 1732 1632 IF ( surf_def_h(0)%ns >= 1 ) CALL disturb_heatflux( surf_def_h(0) ) 1733 1633 IF ( surf_lsm_h%ns >= 1 ) CALL disturb_heatflux( surf_lsm_h ) … … 1737 1637 1738 1638 ! 1739 !-- Compute total sum of grid points and the mean surface level height for each 1740 !-- statistic region. These are mainly used for horizontal averaging of 1741 !-- turbulence statistics. 1742 !-- ngp_2dh: number of grid points of a horizontal cross section through the 1743 !-- respective statistic region 1639 !-- Compute total sum of grid points and the mean surface level height for each statistic region. 1640 !-- These are mainly used for horizontal averaging of turbulence statistics. 1641 !-- ngp_2dh: number of grid points of a horizontal cross section through the respective statistic 1642 !-- region 1744 1643 !-- ngp_3d: number of grid points of the respective statistic region 1745 1644 ngp_2dh_outer_l = 0 … … 1766 1665 ngp_2dh_l(sr) = ngp_2dh_l(sr) + 1 1767 1666 ! 1768 !-- Determine mean surface-level height. In case of downward- 1769 !-- facing walls are present, more than one surface level exist. 1770 !-- In this case, use the lowest surface-level height. 1771 IF ( surf_def_h(0)%start_index(j,i) <= & 1772 surf_def_h(0)%end_index(j,i) ) THEN 1667 !-- Determine mean surface-level height. In case of downward-facing walls are present, 1668 !-- more than one surface level exist. 1669 !-- In this case, use the lowest surface-level height. 1670 IF ( surf_def_h(0)%start_index(j,i) <= surf_def_h(0)%end_index(j,i) ) THEN 1773 1671 m = surf_def_h(0)%start_index(j,i) 1774 1672 k = surf_def_h(0)%k(m) 1775 mean_surface_level_height_l(sr) = & 1776 mean_surface_level_height_l(sr) + zw(k-1) 1673 mean_surface_level_height_l(sr) = mean_surface_level_height_l(sr) + zw(k-1) 1777 1674 ENDIF 1778 IF ( surf_lsm_h%start_index(j,i) <= & 1779 surf_lsm_h%end_index(j,i) ) THEN 1675 IF ( surf_lsm_h%start_index(j,i) <= surf_lsm_h%end_index(j,i) ) THEN 1780 1676 m = surf_lsm_h%start_index(j,i) 1781 1677 k = surf_lsm_h%k(m) 1782 mean_surface_level_height_l(sr) = & 1783 mean_surface_level_height_l(sr) + zw(k-1) 1678 mean_surface_level_height_l(sr) = mean_surface_level_height_l(sr) + zw(k-1) 1784 1679 ENDIF 1785 IF ( surf_usm_h%start_index(j,i) <= & 1786 surf_usm_h%end_index(j,i) ) THEN 1680 IF ( surf_usm_h%start_index(j,i) <= surf_usm_h%end_index(j,i) ) THEN 1787 1681 m = surf_usm_h%start_index(j,i) 1788 1682 k = surf_usm_h%k(m) 1789 mean_surface_level_height_l(sr) = & 1790 mean_surface_level_height_l(sr) + zw(k-1) 1683 mean_surface_level_height_l(sr) = mean_surface_level_height_l(sr) + zw(k-1) 1791 1684 ENDIF 1792 1685 … … 1796 1689 ! 1797 1690 !-- xy-grid points above topography 1798 ngp_2dh_outer_l(k,sr) = ngp_2dh_outer_l(k,sr) + &1799 MERGE( 1, 0, BTEST( wall_flags_total_0(k,j,i), 24 ) )1800 1801 ngp_2dh_s_inner_l(k,sr) = ngp_2dh_s_inner_l(k,sr) + &1802 MERGE( 1, 0, BTEST( wall_flags_total_0(k,j,i), 22 ) )1691 ngp_2dh_outer_l(k,sr) = ngp_2dh_outer_l(k,sr) + & 1692 MERGE( 1, 0, BTEST( wall_flags_total_0(k,j,i), 24 ) ) 1693 1694 ngp_2dh_s_inner_l(k,sr) = ngp_2dh_s_inner_l(k,sr) + & 1695 MERGE( 1, 0, BTEST( wall_flags_total_0(k,j,i), 22 ) ) 1803 1696 1804 1697 ENDDO … … 1817 1710 #if defined( __parallel ) 1818 1711 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1819 CALL MPI_ALLREDUCE( ngp_2dh_l(0), ngp_2dh(0), sr, MPI_INTEGER, MPI_SUM, & 1712 CALL MPI_ALLREDUCE( ngp_2dh_l(0), ngp_2dh(0), sr, MPI_INTEGER, MPI_SUM, comm2d, ierr ) 1713 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1714 CALL MPI_ALLREDUCE( ngp_2dh_outer_l(0,0), ngp_2dh_outer(0,0), (nz+2)*sr, MPI_INTEGER, MPI_SUM, & 1820 1715 comm2d, ierr ) 1821 1716 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1822 CALL MPI_ALLREDUCE( ngp_2dh_ outer_l(0,0), ngp_2dh_outer(0,0), (nz+2)*sr,&1823 MPI_ INTEGER, MPI_SUM, comm2d, ierr )1717 CALL MPI_ALLREDUCE( ngp_2dh_s_inner_l(0,0), ngp_2dh_s_inner(0,0), (nz+2)*sr, MPI_INTEGER, & 1718 MPI_SUM, comm2d, ierr ) 1824 1719 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1825 CALL MPI_ALLREDUCE( ngp_2dh_s_inner_l(0,0), ngp_2dh_s_inner(0,0), & 1826 (nz+2)*sr, MPI_INTEGER, MPI_SUM, comm2d, ierr ) 1827 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1828 CALL MPI_ALLREDUCE( ngp_3d_inner_l(0), ngp_3d_inner_tmp(0), sr, MPI_REAL, & 1829 MPI_SUM, comm2d, ierr ) 1720 CALL MPI_ALLREDUCE( ngp_3d_inner_l(0), ngp_3d_inner_tmp(0), sr, MPI_REAL, MPI_SUM, comm2d, & 1721 ierr ) 1830 1722 ngp_3d_inner = INT( ngp_3d_inner_tmp, KIND = SELECTED_INT_KIND( 18 ) ) 1831 1723 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1832 CALL MPI_ALLREDUCE( mean_surface_level_height_l(0), & 1833 mean_surface_level_height(0), sr, MPI_REAL, & 1724 CALL MPI_ALLREDUCE( mean_surface_level_height_l(0), mean_surface_level_height(0), sr, MPI_REAL,& 1834 1725 MPI_SUM, comm2d, ierr ) 1835 1726 mean_surface_level_height = mean_surface_level_height / REAL( ngp_2dh ) … … 1842 1733 #endif 1843 1734 1844 ngp_3d = INT ( ngp_2dh, KIND = SELECTED_INT_KIND( 18 ) ) * &1735 ngp_3d = INT ( ngp_2dh, KIND = SELECTED_INT_KIND( 18 ) ) * & 1845 1736 INT ( (nz + 2 ), KIND = SELECTED_INT_KIND( 18 ) ) 1846 1737 1847 1738 ! 1848 !-- Set a lower limit of 1 in order to avoid zero divisions in flow_statistics, 1849 !-- buoyancy, etc. A zero value will occur for cases where all grid points of 1850 !-- the respective subdomain lie below the surface topography 1851 ngp_2dh_outer = MAX( 1, ngp_2dh_outer(:,:) ) 1852 ngp_3d_inner = MAX( INT(1, KIND = SELECTED_INT_KIND( 18 )), & 1853 ngp_3d_inner(:) ) 1854 ngp_2dh_s_inner = MAX( 1, ngp_2dh_s_inner(:,:) ) 1855 1856 DEALLOCATE( mean_surface_level_height_l, ngp_2dh_l, ngp_2dh_outer_l, & 1857 ngp_3d_inner_l, ngp_3d_inner_tmp ) 1858 1859 ! 1860 !-- Initializae 3D offline nesting in COSMO model and read data from 1739 !-- Set a lower limit of 1 in order to avoid zero divisions in flow_statistics, buoyancy, etc. A 1740 !-- zero value will occur for cases where all grid points of the respective subdomain lie below the 1741 !-- surface topography 1742 ngp_2dh_outer = MAX( 1, ngp_2dh_outer(:,:) ) 1743 ngp_3d_inner = MAX( INT(1, KIND = SELECTED_INT_KIND( 18 )), ngp_3d_inner(:) ) 1744 ngp_2dh_s_inner = MAX( 1, ngp_2dh_s_inner(:,:) ) 1745 1746 DEALLOCATE( mean_surface_level_height_l, ngp_2dh_l, ngp_2dh_outer_l, ngp_3d_inner_l, & 1747 ngp_3d_inner_tmp ) 1748 1749 ! 1750 !-- Initializae 3D offline nesting in COSMO model and read data from 1861 1751 !-- external NetCDF file. 1862 1752 IF ( nesting_offline ) CALL nesting_offl_init … … 1868 1758 !-- Impose random perturbation on the horizontal velocity field and then 1869 1759 !-- remove the divergences from the velocity field at the initial stage 1870 IF ( create_disturbances .AND. disturbance_energy_limit /= 0.0_wp .AND. &1871 TRIM( initializing_actions ) /= 'read_restart_data' .AND. &1760 IF ( create_disturbances .AND. disturbance_energy_limit /= 0.0_wp .AND. & 1761 TRIM( initializing_actions ) /= 'read_restart_data' .AND. & 1872 1762 TRIM( initializing_actions ) /= 'cyclic_fill' ) THEN 1873 1763 1874 IF ( debug_output ) CALL debug_message( 'creating disturbances + applying pressure solver', 'start' ) 1764 IF ( debug_output ) THEN 1765 CALL debug_message( 'creating disturbances + applying pressure solver', 'start' ) 1766 ENDIF 1875 1767 ! 1876 1768 !-- Needed for both disturb_field and pres … … 1905 1797 !$ACC END DATA 1906 1798 1907 IF ( debug_output ) CALL debug_message( 'creating disturbances + applying pressure solver', 'end' ) 1799 IF ( debug_output ) THEN 1800 CALL debug_message( 'creating disturbances + applying pressure solver', 'end' ) 1801 ENDIF 1908 1802 1909 1803 ENDIF … … 1918 1812 !-- Check temperature in case of too large domain height 1919 1813 DO k = nzb, nzt+1 1920 IF ( ( pt_surface * exner_function( surface_pressure * 100.0_wp) - g/c_p * zu(k) ) < 0.0_wp ) THEN1921 WRITE( message_string, * ) 'absolute temperature < 0.0 at zu(', k, &1922 1814 IF ( ( pt_surface * exner_function( surface_pressure * 100.0_wp ) - g/c_p * zu(k) ) & 1815 < 0.0_wp ) THEN 1816 WRITE( message_string, * ) 'absolute temperature < 0.0 at zu(', k, ') = ', zu(k) 1923 1817 CALL message( 'init_3d_model', 'PA0142', 1, 2, 0, 6, 0 ) 1924 1818 ENDIF … … 1927 1821 ! 1928 1822 !-- Calculate vertical profile of the hydrostatic pressure (hyp) 1929 hyp = barometric_formula(zu, pt_surface * exner_function(surface_pressure * 100.0_wp), surface_pressure * 100.0_wp) 1930 d_exner = exner_function_invers(hyp) 1931 exner = 1.0_wp / exner_function_invers(hyp) 1932 hyrho = ideal_gas_law_rho_pt(hyp, pt_init) 1823 hyp = barometric_formula( zu, pt_surface * exner_function( surface_pressure * 100.0_wp ),& 1824 surface_pressure * 100.0_wp ) 1825 d_exner = exner_function_invers( hyp ) 1826 exner = 1.0_wp / exner_function_invers( hyp ) 1827 hyrho = ideal_gas_law_rho_pt( hyp, pt_init ) 1933 1828 ! 1934 1829 !-- Compute reference density 1935 rho_surface = ideal_gas_law_rho(surface_pressure * 100.0_wp, pt_surface * exner_function(surface_pressure * 100.0_wp)) 1830 rho_surface = ideal_gas_law_rho( surface_pressure * 100.0_wp, & 1831 pt_surface * exner_function( surface_pressure * 100.0_wp ) ) 1936 1832 1937 1833 ENDIF … … 1947 1843 CALL module_interface_init 1948 1844 ! 1949 !-- Initialize surface layer (done after LSM as roughness length are required 1950 !-- for initialization 1845 !-- Initialize surface layer (done after LSM as roughness length are required for initialization 1951 1846 IF ( constant_flux_layer ) CALL init_surface_layer_fluxes 1952 1847 ! … … 1954 1849 IF ( surface_output ) CALL surface_data_output_init 1955 1850 ! 1956 !-- Initialize the ws-scheme. 1957 IF ( ws_scheme_sca .OR.ws_scheme_mom ) CALL ws_init1851 !-- Initialize the ws-scheme. 1852 IF ( ws_scheme_sca .OR. ws_scheme_mom ) CALL ws_init 1958 1853 ! 1959 1854 !-- Perform post-initializing checks for all other modules … … 1961 1856 1962 1857 ! 1963 !-- Initialize surface forcing corresponding to large-scale forcing. Therein, 1858 !-- Initialize surface forcing corresponding to large-scale forcing. Therein, 1964 1859 !-- initialize heat-fluxes, etc. via datatype. Revise it later! 1965 IF ( large_scale_forcing .AND.lsf_surf ) THEN1860 IF ( large_scale_forcing .AND. lsf_surf ) THEN 1966 1861 IF ( use_surface_fluxes .AND. constant_heatflux ) THEN 1967 CALL ls_forcing_surf 1968 ENDIF 1969 ENDIF 1970 ! 1971 !-- Setting weighting factors for calculation of perturbation pressure 1972 !-- and turbulent quantities from the RK substeps1973 IF ( TRIM( timestep_scheme) == 'runge-kutta-3' ) THEN ! for RK3-method1862 CALL ls_forcing_surf( simulated_time ) 1863 ENDIF 1864 ENDIF 1865 ! 1866 !-- Setting weighting factors for calculation of perturbation pressure and turbulent quantities from 1867 !-- the RK substeps. 1868 IF ( TRIM( timestep_scheme ) == 'runge-kutta-3' ) THEN ! for RK3-method 1974 1869 1975 1870 weight_substep(1) = 1._wp/6._wp … … 1981 1876 weight_pres(3) = 1._wp/4._wp 1982 1877 1983 ELSEIF ( TRIM( timestep_scheme) == 'runge-kutta-2' ) THEN ! for RK2-method1878 ELSEIF ( TRIM( timestep_scheme ) == 'runge-kutta-2' ) THEN ! for RK2-method 1984 1879 1985 1880 weight_substep(1) = 1._wp/2._wp 1986 1881 weight_substep(2) = 1._wp/2._wp 1987 1882 1988 1883 weight_pres(1) = 1._wp/2._wp 1989 weight_pres(2) = 1._wp/2._wp 1884 weight_pres(2) = 1._wp/2._wp 1990 1885 1991 1886 ELSE ! for Euler-method 1992 1887 1993 weight_substep(1) = 1.0_wp 1994 weight_pres(1) = 1.0_wp 1888 weight_substep(1) = 1.0_wp 1889 weight_pres(1) = 1.0_wp 1995 1890 1996 1891 ENDIF … … 2005 1900 DO k = nzb+1, nzt 2006 1901 IF ( zu(k) >= rayleigh_damping_height ) THEN 2007 rdf(k) = rayleigh_damping_factor * &2008 ( SIN( pi * 0.5_wp * ( zu(k) - rayleigh_damping_height )&2009 / ( zu(nzt) - rayleigh_damping_height ) )&2010 )**21902 rdf(k) = rayleigh_damping_factor * & 1903 ( SIN( pi * 0.5_wp * ( zu(k) - rayleigh_damping_height ) & 1904 / ( zu(nzt) - rayleigh_damping_height ) ) & 1905 )**2 2011 1906 ENDIF 2012 1907 ENDDO 2013 1908 ELSE 2014 1909 ! 2015 !-- In ocean mode, rayleigh damping is applied in the lower part of the 2016 !-- model domain 1910 !-- In ocean mode, rayleigh damping is applied in the lower part of the model domain 2017 1911 DO k = nzt, nzb+1, -1 2018 1912 IF ( zu(k) <= rayleigh_damping_height ) THEN 2019 rdf(k) = rayleigh_damping_factor * &2020 ( SIN( pi * 0.5_wp * ( rayleigh_damping_height - zu(k) )&2021 / ( rayleigh_damping_height - zu(nzb+1) ) )&2022 )**21913 rdf(k) = rayleigh_damping_factor * & 1914 ( SIN( pi * 0.5_wp * ( rayleigh_damping_height - zu(k) ) & 1915 / ( rayleigh_damping_height - zu(nzb+1) ) ) & 1916 )**2 2023 1917 ENDIF 2024 1918 ENDDO … … 2029 1923 2030 1924 ! 2031 !-- Initialize the starting level and the vertical smoothing factor used for 2032 !-- the external pressuregradient1925 !-- Initialize the starting level and the vertical smoothing factor used for the external pressure 1926 !-- gradient 2033 1927 dp_smooth_factor = 1.0_wp 2034 1928 IF ( dp_external ) THEN 2035 1929 ! 2036 !-- Set the starting level dp_level_ind_b only if it has not been set before 2037 !-- (e.g. in init_grid). 1930 !-- Set the starting level dp_level_ind_b only if it has not been set before (e.g. in init_grid). 2038 1931 IF ( dp_level_ind_b == 0 ) THEN 2039 1932 ind_array = MINLOC( ABS( dp_level_b - zu ) ) 2040 dp_level_ind_b = ind_array(1) - 1 + nzb 1933 dp_level_ind_b = ind_array(1) - 1 + nzb 2041 1934 ! MINLOC uses lower array bound 1 2042 1935 ENDIF … … 2044 1937 dp_smooth_factor(:dp_level_ind_b) = 0.0_wp 2045 1938 DO k = dp_level_ind_b+1, nzt 2046 dp_smooth_factor(k) = 0.5_wp * ( 1.0_wp + SIN( pi * &2047 ( REAL( k - dp_level_ind_b, KIND=wp ) /&2048 REAL( nzt - dp_level_ind_b, KIND=wp ) - 0.5_wp ) ) )1939 dp_smooth_factor(k) = 0.5_wp * ( 1.0_wp + SIN( pi * & 1940 ( REAL( k - dp_level_ind_b, KIND=wp ) / & 1941 REAL( nzt - dp_level_ind_b, KIND=wp ) - 0.5_wp ) ) ) 2049 1942 ENDDO 2050 1943 ENDIF … … 2052 1945 2053 1946 ! 2054 !-- Initialize damping zone for the potential temperature in case of 2055 !-- non-cyclic lateral boundaries. The damping zone has the maximum value2056 !-- at the inflow boundary and decreases to zero atpt_damping_width.1947 !-- Initialize damping zone for the potential temperature in case of non-cyclic lateral boundaries. 1948 !-- The damping zone has the maximum value at the inflow boundary and decreases to zero at 1949 !-- pt_damping_width. 2057 1950 ptdf_x = 0.0_wp 2058 1951 ptdf_y = 0.0_wp … … 2060 1953 DO i = nxl, nxr 2061 1954 IF ( ( i * dx ) < pt_damping_width ) THEN 2062 ptdf_x(i) = pt_damping_factor * ( SIN( pi * 0.5_wp * &2063 REAL( pt_damping_width - i * dx, KIND=wp ) / (&2064 REAL( pt_damping_width, KIND=wp ) ) ) )**22065 ENDIF1955 ptdf_x(i) = pt_damping_factor * ( SIN( pi * 0.5_wp * & 1956 REAL( pt_damping_width - i * dx, KIND=wp ) / & 1957 REAL( pt_damping_width, KIND=wp ) ) )**2 1958 ENDIF 2066 1959 ENDDO 2067 1960 ELSEIF ( bc_lr_raddir ) THEN 2068 1961 DO i = nxl, nxr 2069 1962 IF ( ( i * dx ) > ( nx * dx - pt_damping_width ) ) THEN 2070 ptdf_x(i) = pt_damping_factor * & 2071 SIN( pi * 0.5_wp * & 2072 ( ( i - nx ) * dx + pt_damping_width ) / & 2073 REAL( pt_damping_width, KIND=wp ) )**2 2074 ENDIF 2075 ENDDO 1963 ptdf_x(i) = pt_damping_factor * SIN( pi * 0.5_wp * & 1964 ( ( i - nx ) * dx + pt_damping_width ) / & 1965 REAL( pt_damping_width, KIND=wp ) )**2 1966 ENDIF 1967 ENDDO 2076 1968 ELSEIF ( bc_ns_dirrad ) THEN 2077 1969 DO j = nys, nyn 2078 1970 IF ( ( j * dy ) > ( ny * dy - pt_damping_width ) ) THEN 2079 ptdf_y(j) = pt_damping_factor * & 2080 SIN( pi * 0.5_wp * & 2081 ( ( j - ny ) * dy + pt_damping_width ) / & 2082 REAL( pt_damping_width, KIND=wp ) )**2 2083 ENDIF 2084 ENDDO 1971 ptdf_y(j) = pt_damping_factor * SIN( pi * 0.5_wp * & 1972 ( ( j - ny ) * dy + pt_damping_width ) / & 1973 REAL( pt_damping_width, KIND=wp ) )**2 1974 ENDIF 1975 ENDDO 2085 1976 ELSEIF ( bc_ns_raddir ) THEN 2086 1977 DO j = nys, nyn 2087 1978 IF ( ( j * dy ) < pt_damping_width ) THEN 2088 ptdf_y(j) = pt_damping_factor * & 2089 SIN( pi * 0.5_wp * & 2090 ( pt_damping_width - j * dy ) / & 2091 REAL( pt_damping_width, KIND=wp ) )**2 1979 ptdf_y(j) = pt_damping_factor * SIN( pi * 0.5_wp * & 1980 ( pt_damping_width - j * dy ) / & 1981 REAL( pt_damping_width, KIND=wp ) )**2 2092 1982 ENDIF 2093 1983 ENDDO … … 2095 1985 2096 1986 ! 2097 !-- Input binary data file is not needed anymore. This line must be placed 2098 !-- after call of user_init! 1987 !-- Input binary data file is not needed anymore. This line must be placed after call of user_init! 2099 1988 CALL close_file( 13 ) 2100 1989 ! 2101 !-- In case of nesting, put an barrier to assure that all parent and child 2102 !-- domains finished initialization.1990 !-- In case of nesting, put an barrier to assure that all parent and child domains finished 1991 !-- initialization. 2103 1992 #if defined( __parallel ) 2104 1993 IF ( nested_run ) CALL MPI_BARRIER( MPI_COMM_WORLD, ierr ) -
TabularUnified palm/trunk/SOURCE/init_advec.f90 ¶
r4360 r4648 1 1 !> @file init_advec.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 9 8 ! 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 FOR12 ! A PARTICULAR PURPOSE. See the GNU GeneralPublic License for more details.9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 13 12 ! 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/>.13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4360 2020-01-07 11:25:50Z suehring 27 29 ! Corrected "Former revisions" section 28 ! 30 ! 29 31 ! 3655 2019-01-07 16:51:22Z knoop 30 32 ! Corrected "Former revisions" section … … 37 39 ! ------------ 38 40 !> Initialize constant coefficients and parameters for certain advection schemes. 39 !------------------------------------------------------------------------------ !41 !--------------------------------------------------------------------------------------------------! 40 42 SUBROUTINE init_advec 41 42 43 43 USE advection, & 44 45 USE advection, & 44 46 ONLY: aex, bex, dex, eex 45 47 46 48 USE kinds 47 48 USE control_parameters, &49 50 USE control_parameters, & 49 51 ONLY: scalar_advec 50 52 … … 52 54 53 55 INTEGER(iwp) :: i !< 54 INTEGER(iwp) :: intervals !< 56 INTEGER(iwp) :: intervals !< 55 57 INTEGER(iwp) :: j !< 56 58 57 59 REAL(wp) :: delt !< 58 60 REAL(wp) :: dn !< … … 88 90 ex1 = dn * EXP( -dn ) - EXP( 0.5_wp * dn ) + EXP( -0.5_wp * dn ) 89 91 ex2 = EXP( dn ) - EXP( -dn ) 90 ex3 = EXP( -dn ) * ( 1.0_wp - dn ) - 0.5_wp * EXP( 0.5_wp * dn ) &92 ex3 = EXP( -dn ) * ( 1.0_wp - dn ) - 0.5_wp * EXP( 0.5_wp * dn ) & 91 93 - 0.5_wp * EXP( -0.5_wp * dn ) 92 94 ex4 = EXP( dn ) + EXP( -dn ) -
TabularUnified palm/trunk/SOURCE/init_coupling.f90 ¶
r4564 r4648 1 1 !> @file init_coupling.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 9 8 ! 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 FOR12 ! A PARTICULAR PURPOSE. See the GNU GeneralPublic License for more details.9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 13 12 ! 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/>.13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ------------------ 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4564 2020-06-12 14:03:36Z raasch 27 29 ! Vertical nesting method of Huq et al. (2019) removed 28 ! 30 ! 29 31 ! 4444 2020-03-05 15:59:50Z raasch 30 32 ! bugfix: cpp-directives for serial mode added 31 ! 33 ! 32 34 ! 4360 2020-01-07 11:25:50Z suehring 33 35 ! Corrected "Former revisions" section 34 ! 36 ! 35 37 ! 3655 2019-01-07 16:51:22Z knoop 36 38 ! references to mrun replaced by palmrun, and updated … … 41 43 ! Description: 42 44 ! ------------ 43 !> Initializing coupling via MPI-1 or MPI-2 if the coupled version of PALM is 44 !> called. 45 !------------------------------------------------------------------------------! 45 !> Initializing coupling via MPI-1 or MPI-2 if the coupled version of PALM is called. 46 !--------------------------------------------------------------------------------------------------! 46 47 SUBROUTINE init_coupling 47 48 48 49 USE control_parameters, & 49 50 USE control_parameters, & 50 51 ONLY: coupling_char, coupling_mode 51 52 52 53 USE kinds 53 54 54 55 USE pegrid 55 56 … … 62 63 INTEGER(iwp) :: inter_color !< 63 64 #endif 64 65 65 66 INTEGER(iwp), DIMENSION(:) :: bc_data(0:3) = 0 !< 66 67 67 68 ! 68 !-- Get information about the coupling mode from the environment variable 69 !-- which has been set by the mpiexec command. 70 !-- This method is currently not used because the mpiexec command is not 71 !-- available on some machines 69 !-- Get information about the coupling mode from the environment variable which has been set by the 70 !-- mpiexec command. 71 !-- This method is currently not used because the mpiexec command is not available on some machines. 72 72 ! CALL GET_ENVIRONMENT_VARIABLE( 'coupling_mode', coupling_mode, i ) 73 73 ! IF ( i == 0 ) coupling_mode = 'uncoupled' … … 75 75 76 76 ! 77 !-- Get information about the coupling mode from standard input (PE0 only) and 78 !-- distribute it to theother PEs. Distribute PEs to 2 new communicators.77 !-- Get information about the coupling mode from standard input (PE0 only) and distribute it to the 78 !-- other PEs. Distribute PEs to 2 new communicators. 79 79 !-- ATTENTION: numprocs will be reset according to the new communicators 80 80 #if defined ( __parallel ) … … 91 91 92 92 ! 93 !-- Check if '_O' has to be used as file extension in an uncoupled ocean 94 !-- run. This is required,if this run shall be continued as a coupled run.93 !-- Check if '_O' has to be used as file extension in an uncoupled ocean run. This is required, 94 !-- if this run shall be continued as a coupled run. 95 95 IF ( TRIM( coupling_mode ) == 'precursor_ocean' ) bc_data(3) = 1 96 96 … … 127 127 128 128 ! 129 !-- Write a flag file for the ocean model and the other atmosphere 130 !-- processes. 129 !-- Write a flag file for the ocean model and the other atmosphere processes. 131 130 OPEN( 90, FILE='COUPLING_PORT_OPENED', FORM='FORMATTED' ) 132 131 WRITE ( 90, '(''TRUE'')' ) … … 136 135 137 136 ! 138 !-- In case of a precursor ocean run (followed by a coupled run), or a 139 !-- coupled atmosphere-ocean run, set the file extension for the ocean files 140 IF ( TRIM( coupling_mode ) == 'ocean_to_atmosphere' .OR. bc_data(3) == 1 ) & 141 THEN 137 !-- In case of a precursor ocean run (followed by a coupled run), or a coupled atmosphere-ocean run, 138 !-- set the file extension for the ocean files. 139 IF ( TRIM( coupling_mode ) == 'ocean_to_atmosphere' .OR. bc_data(3) == 1 ) THEN 142 140 coupling_char = '_O' 143 141 ENDIF -
TabularUnified palm/trunk/SOURCE/init_grid.f90 ¶
r4630 r4648 1 1 !> @file init_grid.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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/>. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 8 ! 9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 12 ! 13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: … … 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4630 2020-07-30 14:54:34Z suehring 27 29 ! In case of ASCII topography input flag grid points as terrain and building. 28 30 ! 29 31 ! 4601 2020-07-14 12:06:09Z suehring 30 32 ! Minor formatting adjustments 31 ! 33 ! 32 34 ! 4564 2020-06-12 14:03:36Z raasch 33 35 ! Vertical nesting method of Huq et al. (2019) removed 34 ! 36 ! 35 37 ! 4543 2020-05-20 14:12:22Z gronemeier 36 38 ! Remove non-required check for canyon height 37 ! 39 ! 38 40 ! 4507 2020-04-22 18:21:45Z gronemeier 39 41 ! update origin_z with shifting height of orography (oro_min) 40 ! 42 ! 41 43 ! 4457 2020-03-11 14:20:43Z raasch 42 44 ! use statement for exchange horiz added, 43 45 ! bugfix for call of exchange horiz 2d 44 ! 46 ! 45 47 ! 4444 2020-03-05 15:59:50Z raasch 46 48 ! bugfix: cpp-directives for serial mode added 47 ! 49 ! 48 50 ! 4414 2020-02-19 20:16:04Z suehring 49 51 ! - Remove deprecated topography arrays nzb_s_inner, nzb_u_inner, etc. 50 ! - Move initialization of boundary conditions and multigrid into an extra 51 ! module interface. 52 ! 52 ! - Move initialization of boundary conditions and multigrid into an extra module interface. 53 ! 53 54 ! 4386 2020-01-27 15:07:30Z Giersch 54 ! Allocation statements, comments, naming of variables revised and _wp added to 55 ! real type values 56 ! 55 ! Allocation statements, comments, naming of variables revised and _wp added to real type values 56 ! 57 57 ! 4360 2020-01-07 11:25:50Z suehring 58 58 ! Revise error messages for generic tunnel setup. 59 ! 59 ! 60 60 ! 4346 2019-12-18 11:55:56Z motisi 61 ! Introduction of wall_flags_total_0, which currently sets bits based on static 62 ! topographyinformation used in wall_flags_static_063 ! 61 ! Introduction of wall_flags_total_0, which currently sets bits based on static topography 62 ! information used in wall_flags_static_0 63 ! 64 64 ! 4340 2019-12-16 08:17:03Z Giersch 65 65 ! Topography closed channel flow with symmetric boundaries implemented 66 ! 66 ! 67 67 ! 4329 2019-12-10 15:46:36Z motisi 68 68 ! Renamed wall_flags_0 to wall_flags_static_0 69 ! 69 ! 70 70 ! 4328 2019-12-09 18:53:04Z suehring 71 71 ! Minor change in nzb_max computation. Commentation added. 72 ! 72 ! 73 73 ! 4314 2019-11-29 10:29:20Z suehring 74 ! Set additional topography flag 4 to mark topography grid points emerged 75 ! from the filtering process. 76 ! 74 ! Set additional topography flag 4 to mark topography grid points emerged from the filtering process. 75 ! 77 76 ! 4294 2019-11-13 18:34:16Z suehring 78 ! Bugfix, always set bit 5 and 6 of wall_flags, indicating terrain- and 79 ! building surfaces in all cases, in order to enable terrain-following output80 ! a lso when no land- or urban-surface model is applied.81 ! 77 ! Bugfix, always set bit 5 and 6 of wall_flags, indicating terrain- and building surfaces in all 78 ! cases, in order to enable terrain-following output also when no land- or urban-surface model is 79 ! applied. 80 ! 82 81 ! 4265 2019-10-15 16:16:24Z suehring 83 ! Bugfix for last commit, exchange oro_max variable only when it is allocated 84 ! (not necessarily thecase when topography is input from ASCII file).85 ! 82 ! Bugfix for last commit, exchange oro_max variable only when it is allocated (not necessarily the 83 ! case when topography is input from ASCII file). 84 ! 86 85 ! 4245 2019-09-30 08:40:37Z pavelkrc 87 86 ! Store oro_max (building z-offset) in 2D for building surfaces 88 ! 87 ! 89 88 ! 4189 2019-08-26 16:19:38Z suehring 90 89 ! - Add check for proper setting of namelist parameter topography 91 90 ! - Set flag to indicate land surfaces in case no topography is provided 92 ! 91 ! 93 92 ! 4182 2019-08-22 15:20:23Z scharf 94 93 ! Corrected "Former revisions" section 95 ! 94 ! 96 95 ! 4168 2019-08-16 13:50:17Z suehring 97 ! Pre-calculate topography top index and store it on an array (replaces former 98 ! functionsget_topography_top_index)99 ! 96 ! Pre-calculate topography top index and store it on an array (replaces former functions 97 ! get_topography_top_index) 98 ! 100 99 ! 4159 2019-08-15 13:31:35Z suehring 101 ! Revision of topography processing. This was not consistent between 2D and 3D 102 ! buildings. 103 ! 100 ! Revision of topography processing. This was not consistent between 2D and 3D buildings. 101 ! 104 102 ! 4144 2019-08-06 09:11:47Z raasch 105 103 ! relational operators .EQ., .NE., etc. replaced by ==, /=, etc. 106 ! 104 ! 107 105 ! 4115 2019-07-24 12:50:49Z suehring 108 ! Bugfix in setting near-surface flag 24, inidicating wall-bounded grid points 109 ! 106 ! Bugfix in setting near-surface flag 24, inidicating wall-bounded grid points 107 ! 110 108 ! 4110 2019-07-22 17:05:21Z suehring 111 109 ! - Separate initialization of advection flags for momentum and scalars. 112 110 ! - Change subroutine interface for ws_init_flags_scalar to pass boundary flags 113 ! 111 ! 114 112 ! 4109 2019-07-22 17:00:34Z suehring 115 113 ! Fix bad commit 116 ! 114 ! 117 115 ! 3926 2019-04-23 12:56:42Z suehring 118 ! Minor bugfix in building mapping when all building IDs in the model domain 119 ! are missing 120 ! 116 ! Minor bugfix in building mapping when all building IDs in the model domain are missing 117 ! 121 118 ! 3857 2019-04-03 13:00:16Z knoop 122 ! In projection of non-building 3D objects onto numerical grid remove 123 ! dependency on building_type 124 ! 119 ! In projection of non-building 3D objects onto numerical grid remove dependency on building_type 120 ! 125 121 ! 3763 2019-02-25 17:33:49Z suehring 126 ! Replace work-around for ghost point exchange of 1-byte arrays with specific 127 ! routine as alreadydone in other routines128 ! 122 ! Replace work-around for ghost point exchange of 1-byte arrays with specific routine as already 123 ! done in other routines 124 ! 129 125 ! 3761 2019-02-25 15:31:42Z raasch 130 126 ! unused variables removed 131 ! 127 ! 132 128 ! 3661 2019-01-08 18:22:50Z suehring 133 ! Remove setting of nzb_max to nzt at non-cyclic boundary PEs, instead, 134 ! order degradation ofadvection scheme is handeled directly in advec_ws135 ! 129 ! Remove setting of nzb_max to nzt at non-cyclic boundary PEs, instead, order degradation of 130 ! advection scheme is handeled directly in advec_ws 131 ! 136 132 ! 3655 2019-01-07 16:51:22Z knoop 137 133 ! Comment added … … 142 138 ! 143 139 ! Description: 144 ! ----------------------------------------------------------------------------- !140 ! -------------------------------------------------------------------------------------------------! 145 141 !> Creating grid depending constants 146 142 !> @todo: Rearrange topo flag list 147 !> @todo: reference 3D buildings on top of orography is not tested and may need 148 !> f urther improvement for steep slopes149 !> @todo: Use more advanced setting of building type at filled holes 150 !------------------------------------------------------------------------------ !143 !> @todo: reference 3D buildings on top of orography is not tested and may need further improvement 144 !> for steep slopes 145 !> @todo: Use more advanced setting of building type at filled holes 146 !--------------------------------------------------------------------------------------------------! 151 147 SUBROUTINE init_grid 152 148 153 USE arrays_3d, &149 USE arrays_3d, & 154 150 ONLY: dd2zu, ddzu, ddzu_pres, ddzw, dzu, dzw, x, xu, y, yv, zu, zw 155 151 156 USE control_parameters, &157 ONLY: constant_flux_layer, dz, dz_max, dz_stretch_factor, &158 dz_stretch_factor_array, dz_stretch_level, dz_stretch_level_end, &159 dz_stretch_level_end_index, dz_stretch_level_start_index, &160 dz_stretch_level_start, ibc_uv_b, message_string, &161 number_stretch_level_end, &162 number_stretch_level_start, &163 ocean_mode, &164 psolver, &165 symmetry_flag, &166 topography, &152 USE control_parameters, & 153 ONLY: constant_flux_layer, dz, dz_max, dz_stretch_factor, & 154 dz_stretch_factor_array, dz_stretch_level, dz_stretch_level_end, & 155 dz_stretch_level_end_index, dz_stretch_level_start_index, & 156 dz_stretch_level_start, ibc_uv_b, message_string, & 157 number_stretch_level_end, & 158 number_stretch_level_start, & 159 ocean_mode, & 160 psolver, & 161 symmetry_flag, & 162 topography, & 167 163 use_surface_fluxes 168 164 169 USE grid_variables, &165 USE grid_variables, & 170 166 ONLY: ddx, ddx2, ddy, ddy2, dx, dx2, dy, dy2, zu_s_inner, zw_w_inner 171 167 172 USE indices, &173 ONLY: nbgp, &174 nx, &175 nxl, &176 nxlg, &177 nxr, &178 nxrg, &179 ny, &180 nyn, &181 nyng, &182 nys, &183 nysg, &184 nz, &185 nzb, &186 nzb_diff, &187 nzb_max, &188 nzt, &189 topo_top_ind, &168 USE indices, & 169 ONLY: nbgp, & 170 nx, & 171 nxl, & 172 nxlg, & 173 nxr, & 174 nxrg, & 175 ny, & 176 nyn, & 177 nyng, & 178 nys, & 179 nysg, & 180 nz, & 181 nzb, & 182 nzb_diff, & 183 nzb_max, & 184 nzt, & 185 topo_top_ind, & 190 186 topo_min_level 191 187 … … 196 192 IMPLICIT NONE 197 193 198 INTEGER(iwp) :: i !< index variable along x 194 INTEGER(iwp) :: i !< index variable along x 199 195 INTEGER(iwp) :: j !< index variable along y 200 196 INTEGER(iwp) :: k !< index variable along z 201 197 INTEGER(iwp) :: k_top !< topography top index on local PE 202 198 INTEGER(iwp) :: n !< loop variable for stretching 203 INTEGER(iwp) :: number_dz !< number of user-specified dz values 199 INTEGER(iwp) :: number_dz !< number of user-specified dz values 204 200 INTEGER(iwp) :: nzb_local_max !< vertical grid index of maximum topography height 205 201 INTEGER(iwp) :: nzb_local_min !< vertical grid index of minimum topography height … … 209 205 REAL(wp) :: dz_level_end !< distance between calculated height level for u/v-grid and user-specified end level for stretching 210 206 REAL(wp) :: dz_stretched !< stretched vertical grid spacing 211 212 REAL(wp), DIMENSION(:), ALLOCATABLE :: min_dz_stretch_level_end !< Array that contains all minimum heights where the stretching can end 207 208 REAL(wp), DIMENSION(:), ALLOCATABLE :: min_dz_stretch_level_end !< Array that contains all minimum heights where the stretching 209 !< can end 213 210 214 211 … … 224 221 ALLOCATE( x(0:nx) ) 225 222 ALLOCATE( xu(0:nx) ) 226 223 227 224 DO i = 0, nx 228 225 xu(i) = i * dx … … 232 229 ALLOCATE( y(0:ny) ) 233 230 ALLOCATE( yv(0:ny) ) 234 231 235 232 DO j = 0, ny 236 233 yv(j) = j * dy … … 247 244 248 245 ! 249 !-- For constructing an appropriate grid, the vertical grid spacing dz has to 250 !-- be specified with a non-negative value in the parameter file246 !-- For constructing an appropriate grid, the vertical grid spacing dz has to be specified with a 247 !-- non-negative value in the parameter file. 251 248 IF ( dz(1) == -1.0_wp ) THEN 252 249 message_string = 'missing dz' 253 CALL message( 'init_grid', 'PA0200', 1, 2, 0, 6, 0 ) 250 CALL message( 'init_grid', 'PA0200', 1, 2, 0, 6, 0 ) 254 251 ELSEIF ( dz(1) <= 0.0_wp ) THEN 255 252 WRITE( message_string, * ) 'dz=',dz(1),' <= 0.0' … … 258 255 259 256 ! 260 !-- Initialize dz_stretch_level_start with the value of dz_stretch_level 261 !-- if it was set by the user 257 !-- Initialize dz_stretch_level_start with the value of dz_stretch_level if it was set by the user. 262 258 IF ( dz_stretch_level /= -9999999.9_wp ) THEN 263 259 dz_stretch_level_start(1) = dz_stretch_level 264 260 ENDIF 265 266 ! 267 !-- Determine number of dz values and stretching levels specified by the 268 !-- user to allow right controlling of the stretching mechanism and to 269 !-- perform error checks. The additional requirement that dz /= dz_max 270 !-- for counting number of user-specified dz values is necessary. Otherwise 271 !-- restarts would abort if the old stretching mechanism with dz_stretch_level 272 !-- is used (Attention: The user is not allowed to specify a dz value equal 273 !-- to the default of dz_max = 999.0). 274 number_dz = COUNT( dz /= -1.0_wp .AND. dz /= dz_max) 275 number_stretch_level_start = COUNT( dz_stretch_level_start /= & 276 -9999999.9_wp ) 277 number_stretch_level_end = COUNT( dz_stretch_level_end /= & 278 9999999.9_wp ) 279 280 ! 281 !-- The number of specified end levels +1 has to be the same as the number 261 262 ! 263 !-- Determine number of dz values and stretching levels specified by the user to allow right 264 !-- controlling of the stretching mechanism and to perform error checks. The additional requirement 265 !-- that dz /= dz_max for counting number of user-specified dz values is necessary. Otherwise 266 !-- restarts would abort if the old stretching mechanism with dz_stretch_level is used (Attention: 267 !-- The user is not allowed to specify a dz value equal to the default of dz_max = 999.0). 268 number_dz = COUNT( dz /= -1.0_wp .AND. dz /= dz_max) 269 number_stretch_level_start = COUNT( dz_stretch_level_start /= -9999999.9_wp ) 270 number_stretch_level_end = COUNT( dz_stretch_level_end /= 9999999.9_wp ) 271 272 ! 273 !-- The number of specified end levels +1 has to be the same as the number 282 274 !-- of specified dz values 283 275 IF ( number_dz /= number_stretch_level_end + 1 ) THEN 284 WRITE( message_string, * ) 'The number of values for dz = ', & 285 number_dz, 'has to be the same as& ', & 286 'the number of values for ', & 287 'dz_stretch_level_end + 1 = ', & 288 number_stretch_level_end+1 276 WRITE( message_string, * ) 'The number of values for dz = ', number_dz, & 277 'has to be the same as& ', 'the number of values for ', & 278 'dz_stretch_level_end + 1 = ', number_stretch_level_end+1 289 279 CALL message( 'init_grid', 'PA0156', 1, 2, 0, 6, 0 ) 290 280 ENDIF 291 292 ! 293 !-- The number of specified start levels has to be the same or one less than 294 !-- the number of specified dz values 295 IF ( number_dz /= number_stretch_level_start + 1 .AND. & 296 number_dz /= number_stretch_level_start ) THEN 297 WRITE( message_string, * ) 'The number of values for dz = ', & 298 number_dz, 'has to be the same as or one ', & 299 'more than& the number of values for ', & 300 'dz_stretch_level_start = ', & 301 number_stretch_level_start 281 282 ! 283 !-- The number of specified start levels has to be the same or one less than the number of specified 284 !-- dz values 285 IF ( number_dz /= number_stretch_level_start + 1 .AND. & 286 number_dz /= number_stretch_level_start ) THEN 287 WRITE( message_string, * ) 'The number of values for dz = ', number_dz, & 288 'has to be the same as or one ', & 289 'more than& the number of values for ', & 290 'dz_stretch_level_start = ', number_stretch_level_start 302 291 CALL message( 'init_grid', 'PA0211', 1, 2, 0, 6, 0 ) 303 292 ENDIF 304 305 !-- The number of specified start levels has to be the same or one more than 306 !-- the number of specifiedend levels307 IF ( number_stretch_level_start /= number_stretch_level_end + 1 .AND.&293 294 !-- The number of specified start levels has to be the same or one more than the number of specified 295 !-- end levels 296 IF ( number_stretch_level_start /= number_stretch_level_end + 1 .AND. & 308 297 number_stretch_level_start /= number_stretch_level_end ) THEN 309 WRITE( message_string, * ) 'The number of values for ', & 310 'dz_stretch_level_start = ', & 311 dz_stretch_level_start, 'has to be the ', & 312 'same or one more than& the number of ', & 313 'values for dz_stretch_level_end = ', & 314 number_stretch_level_end 298 WRITE( message_string, * ) 'The number of values for ', & 299 'dz_stretch_level_start = ', dz_stretch_level_start, & 300 'has to be the ', 'same or one more than& the number of ', & 301 'values for dz_stretch_level_end = ', number_stretch_level_end 315 302 CALL message( 'init_grid', 'PA0216', 1, 2, 0, 6, 0 ) 316 303 ENDIF … … 318 305 ! 319 306 !-- Initialize dz for the free atmosphere with the value of dz_max 320 IF ( dz(number_stretch_level_start+1) == -1.0_wp .AND. & 321 number_stretch_level_start /= 0 ) THEN 307 IF ( dz(number_stretch_level_start+1) == -1.0_wp .AND. number_stretch_level_start /= 0 ) THEN 322 308 dz(number_stretch_level_start+1) = dz_max 323 309 ENDIF 324 325 ! 326 !-- Initialize the stretching factor if (infinitely) stretching in the free 327 !-- atmosphere is desired (dz_stretch_level_end was not specified for the 328 !-- free atmosphere) 329 IF ( number_stretch_level_start == number_stretch_level_end + 1 ) THEN 330 dz_stretch_factor_array(number_stretch_level_start) = & 331 dz_stretch_factor 310 311 ! 312 !-- Initialize the stretching factor if (infinitely) stretching in the free atmosphere is desired 313 !-- (dz_stretch_level_end was not specified for the free atmosphere) 314 IF ( number_stretch_level_start == number_stretch_level_end + 1 ) THEN 315 dz_stretch_factor_array(number_stretch_level_start) = dz_stretch_factor 332 316 ENDIF 333 317 334 318 ! 335 319 !-- Allocation of arrays for stretching … … 339 323 !-- Define the vertical grid levels. Start with atmosphere branch 340 324 IF ( .NOT. ocean_mode ) THEN 341 342 ! 343 !-- The stretching region has to be large enough to allow for a smooth 344 !-- transition between two different grid spacings. The number 4 is an 345 !-- empirical value 325 326 ! 327 !-- The stretching region has to be large enough to allow for a smooth transition between two 328 !-- different grid spacings. The number 4 is an empirical value. 346 329 DO n = 1, number_stretch_level_start 347 min_dz_stretch_level_end(n) = dz_stretch_level_start(n) + & 348 4 * MAX( dz(n),dz(n+1) ) 330 min_dz_stretch_level_end(n) = dz_stretch_level_start(n) + 4 * MAX( dz(n),dz(n+1) ) 349 331 ENDDO 350 332 351 IF ( ANY( min_dz_stretch_level_end(1:number_stretch_level_start) > &352 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN353 message_string= 'Each dz_stretch_level_end has to be larger ' // &354 'than its corresponding value for &' // &355 'dz_stretch_level_start + 4*MAX(dz(n),dz(n+1)) '// &333 IF ( ANY( min_dz_stretch_level_end(1:number_stretch_level_start) > & 334 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN 335 message_string= 'Each dz_stretch_level_end has to be larger ' // & 336 'than its corresponding value for &' // & 337 'dz_stretch_level_start + 4*MAX(dz(n),dz(n+1)) '// & 356 338 'to allow for smooth grid stretching' 357 339 CALL message( 'init_grid', 'PA0224', 1, 2, 0, 6, 0 ) 358 340 ENDIF 359 360 ! 361 !-- Stretching must not be applied within the surface layer 362 !-- (first two grid points). For the default case dz_stretch_level_start 363 !-- is negative. Therefore the absolut value is checked here. 341 342 ! 343 !-- Stretching must not be applied within the surface layer (first two grid points). For the 344 !-- default case dz_stretch_level_start is negative. Therefore the absolut value is checked here. 364 345 IF ( ANY( ABS( dz_stretch_level_start ) <= dz(1) * 1.5_wp ) ) THEN 365 WRITE( message_string, * ) 'Each dz_stretch_level_start has to be ',&366 'larger than ', dz(1) * 1.5346 WRITE( message_string, * ) 'Each dz_stretch_level_start has to be ', & 347 'larger than ', dz(1) * 1.5 367 348 CALL message( 'init_grid', 'PA0226', 1, 2, 0, 6, 0 ) 368 349 ENDIF 369 350 370 351 ! 371 !-- The stretching has to start and end on a grid level. Therefore 372 !-- user-specified values are mapped to the next lowest level. The 373 !-- calculation of the first level is realized differently just because of 374 !-- historical reasons (the advanced/new stretching mechanism was realized 375 !-- in a way that results don't change if the old parameters 376 !-- dz_stretch_level, dz_stretch_factor and dz_max are used) 377 IF ( number_stretch_level_start /= 0 ) THEN 378 dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) - & 379 dz(1)/2.0) / dz(1) ) & 352 !-- The stretching has to start and end on a grid level. Therefore user-specified values are 353 !-- mapped to the next lowest level. The calculation of the first level is realized differently 354 !-- just because of historical reasons (the advanced/new stretching mechanism was realized in a 355 !-- way that results don't change if the old parameters dz_stretch_level, dz_stretch_factor and 356 !-- dz_max are used). 357 IF ( number_stretch_level_start /= 0 ) THEN 358 dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) - dz(1)/2.0) / dz(1) ) & 380 359 * dz(1) + dz(1)/2.0 381 360 ENDIF 382 361 383 362 IF ( number_stretch_level_start > 1 ) THEN 384 363 DO n = 2, number_stretch_level_start 385 dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) / & 386 dz(n) ) * dz(n) 387 ENDDO 388 ENDIF 389 364 dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) / dz(n) ) * dz(n) 365 ENDDO 366 ENDIF 367 390 368 IF ( number_stretch_level_end /= 0 ) THEN 391 369 DO n = 1, number_stretch_level_end 392 dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) / & 393 dz(n+1) ) * dz(n+1) 370 dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) / dz(n+1) ) * dz(n+1) 394 371 ENDDO 395 372 ENDIF … … 397 374 ! 398 375 !-- Determine stretching factor if necessary 399 IF ( number_stretch_level_end >= 1 ) THEN 376 IF ( number_stretch_level_end >= 1 ) THEN 400 377 CALL calculate_stretching_factor( number_stretch_level_end ) 401 378 ENDIF … … 403 380 ! 404 381 !-- Grid for atmosphere with surface at z=0 (k=0, w-grid). 405 !-- First compute the u- and v-levels. In case of dirichlet bc for u and v 406 !-- the first u/v- and w-level (k=0) are defined at same height (z=0). 407 !-- The second u-level (k=1) corresponds to the top of the 408 !-- surface layer. In case of symmetric boundaries (closed channel flow), 409 !-- the first grid point is always at z=0. 410 IF ( ibc_uv_b == 0 .OR. ibc_uv_b == 2 .OR. & 411 topography == 'closed_channel' ) THEN 382 !-- First compute the u- and v-levels. In case of dirichlet bc for u and v the first u/v- and 383 !-- w-level (k=0) are defined at same height (z=0). 384 !-- The second u-level (k=1) corresponds to the top of the surface layer. In case of symmetric 385 !-- boundaries (closed channel flow), the first grid point is always at z=0. 386 IF ( ibc_uv_b == 0 .OR. ibc_uv_b == 2 .OR. topography == 'closed_channel' ) THEN 412 387 zu(0) = 0.0_wp 413 388 ELSE 414 389 zu(0) = - dz(1) * 0.5_wp 415 390 ENDIF 416 391 417 392 zu(1) = dz(1) * 0.5_wp 418 419 ! 420 !-- Determine u and v height levels considering the possibility of grid 421 !-- stretching in severalheights.393 394 ! 395 !-- Determine u and v height levels considering the possibility of grid stretching in several 396 !-- heights. 422 397 n = 1 423 398 dz_stretch_level_start_index = nzt+1 … … 425 400 dz_stretched = dz(1) 426 401 427 !-- The default value of dz_stretch_level_start is negative, thus the first 428 !-- condition is true even if no stretching shall be applied. Hence, the 429 !-- second condition is also necessary. 402 !-- The default value of dz_stretch_level_start is negative, thus the first condition is true 403 !-- even if no stretching shall be applied. Hence, the second condition is also necessary. 430 404 DO k = 2, nzt+1-symmetry_flag 431 IF ( dz_stretch_level_start(n) <= zu(k-1) .AND.&432 dz_stretch_level_start(n) /= -9999999.9_wp ) THEN405 IF ( dz_stretch_level_start(n) <= zu(k-1) .AND. & 406 dz_stretch_level_start(n) /= -9999999.9_wp ) THEN 433 407 dz_stretched = dz_stretched * dz_stretch_factor_array(n) 434 435 IF ( dz(n) > dz(n+1) ) THEN408 409 IF ( dz(n) > dz(n+1) ) THEN 436 410 dz_stretched = MAX( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (higher) dz 437 411 ELSE 438 412 dz_stretched = MIN( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (lower) dz 439 413 ENDIF 440 441 IF ( dz_stretch_level_start_index(n) == nzt+1 ) & 442 dz_stretch_level_start_index(n) = k-1 443 444 ENDIF 445 414 415 IF ( dz_stretch_level_start_index(n) == nzt+1 ) dz_stretch_level_start_index(n) = k-1 416 417 ENDIF 418 446 419 zu(k) = zu(k-1) + dz_stretched 447 448 ! 449 !-- Make sure that the stretching ends exactly at dz_stretch_level_end 450 dz_level_end = ABS( zu(k) - dz_stretch_level_end(n) ) 451 452 IF ( dz_level_end < dz(n+1)/3.0 ) THEN420 421 ! 422 !-- Make sure that the stretching ends exactly at dz_stretch_level_end 423 dz_level_end = ABS( zu(k) - dz_stretch_level_end(n) ) 424 425 IF ( dz_level_end < dz(n+1)/3.0 ) THEN 453 426 zu(k) = dz_stretch_level_end(n) 454 427 dz_stretched = dz(n+1) 455 428 dz_stretch_level_end_index(n) = k 456 n = n + 1 429 n = n + 1 457 430 ENDIF 458 431 ENDDO 459 460 ! 461 !-- If a closed channel flow is simulated, make sure that grid structure is 462 !-- the same for both bottom and top boundary. (Hint: Using a different dz 463 !-- at the bottom and at the top makes no sense due to symmetric boundaries 464 !-- where dz should be equal. Therefore, different dz at the bottom and top 465 !-- causes an abort (see check_parameters).) 466 IF ( topography == 'closed_channel' ) THEN 432 433 ! 434 !-- If a closed channel flow is simulated, make sure that grid structure is the same for both 435 !-- bottom and top boundary. (Hint: Using a different dz at the bottom and at the top makes no 436 !-- sense due to symmetric boundaries where dz should be equal. Therefore, different dz at the 437 !-- bottom and top causes an abort (see check_parameters).) 438 IF ( topography == 'closed_channel' ) THEN 467 439 zu(nzt+1) = zu(nzt) + dz(1) * 0.5_wp 468 440 ENDIF 469 441 470 442 ! 471 !-- Compute the w-levels. They are always staggered half-way between the 472 !-- corresponding u-levels. In case of dirichlet bc for u and v at the 473 !-- ground the first u- and w-level (k=0) are defined at same height (z=0). 474 !-- Per default, the top w-level is extrapolated linearly. In case of 475 !-- a closed channel flow, zu(nzt+1) and zw(nzt) must be set explicitely. 476 !-- (Hint: Using a different dz at the bottom and at the top makes no sense 477 !-- due to symmetric boundaries where dz should be equal. Therefore, 478 !-- different dz at the bottom and top causes an abort (see 479 !-- check_parameters).) 443 !-- Compute the w-levels. They are always staggered half-way between the corresponding u-levels. 444 !-- In case of dirichlet bc for u and v at the ground the first u- and w-level (k=0) are defined 445 !-- at same height (z=0). 446 !-- Per default, the top w-level is extrapolated linearly. In case of a closed channel flow, 447 !-- zu(nzt+1) and zw(nzt) must be set explicitely. 448 !-- (Hint: Using a different dz at the bottom and at the top makes no sense due to symmetric 449 !-- boundaries where dz should be equal. Therefore, different dz at the bottom and top causes an 450 !-- abort (see check_parameters).) 480 451 zw(0) = 0.0_wp 481 452 DO k = 1, nzt-symmetry_flag 482 453 zw(k) = ( zu(k) + zu(k+1) ) * 0.5_wp 483 454 ENDDO 484 IF ( topography == 'closed_channel' ) THEN455 IF ( topography == 'closed_channel' ) THEN 485 456 zw(nzt) = zw(nzt-1) + dz(1) 486 457 zw(nzt+1) = zw(nzt) + dz(1) … … 492 463 493 464 ! 494 !-- The stretching region has to be large enough to allow for a smooth 495 !-- transition between two different grid spacings. The number 4 is an 496 !-- empirical value 465 !-- The stretching region has to be large enough to allow for a smooth transition between two 466 !-- different grid spacings. The number 4 is an empirical value 497 467 DO n = 1, number_stretch_level_start 498 min_dz_stretch_level_end(n) = dz_stretch_level_start(n) - & 499 4 * MAX( dz(n),dz(n+1) ) 468 min_dz_stretch_level_end(n) = dz_stretch_level_start(n) - 4 * MAX( dz(n),dz(n+1) ) 500 469 ENDDO 501 502 IF ( ANY( min_dz_stretch_level_end (1:number_stretch_level_start) < &503 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN504 message_string= 'Each dz_stretch_level_end has to be less ' // &505 'than its corresponding value for &' // &506 'dz_stretch_level_start - 4*MAX(dz(n),dz(n+1)) '// &470 471 IF ( ANY( min_dz_stretch_level_end (1:number_stretch_level_start) < & 472 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN 473 message_string= 'Each dz_stretch_level_end has to be less ' // & 474 'than its corresponding value for &' // & 475 'dz_stretch_level_start - 4*MAX(dz(n),dz(n+1)) '// & 507 476 'to allow for smooth grid stretching' 508 477 CALL message( 'init_grid', 'PA0224', 1, 2, 0, 6, 0 ) 509 478 ENDIF 510 511 ! 512 !-- Stretching must not be applied close to the surface (last two grid 513 !-- points). For the default case dz_stretch_level_start is negative.514 IF ( ANY( dz_stretch_level_start >= - dz(1) * 1.5_wp ) ) THEN515 WRITE( message_string, * ) 'Each dz_stretch_level_start has to be ',&516 'less than ', -dz(1) * 1.5479 480 ! 481 !-- Stretching must not be applied close to the surface (last two grid points). For the default 482 !-- case dz_stretch_level_start is negative. 483 IF ( ANY( dz_stretch_level_start >= - dz(1) * 1.5_wp ) ) THEN 484 WRITE( message_string, * ) 'Each dz_stretch_level_start has to be ', & 485 'less than ', -dz(1) * 1.5 517 486 CALL message( 'init_grid', 'PA0226', 1, 2, 0, 6, 0 ) 518 487 ENDIF 519 488 520 489 ! 521 !-- The stretching has to start and end on a grid level. Therefore 522 !-- user-specified values are mapped to the next highest level. The 523 !-- calculation of the first level is realized differently just because of 524 !-- historical reasons (the advanced/new stretching mechanism was realized 525 !-- in a way that results don't change if the old parameters 526 !-- dz_stretch_level, dz_stretch_factor and dz_max are used) 527 IF ( number_stretch_level_start /= 0 ) THEN 528 dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) + & 529 dz(1)/2.0) / dz(1) ) & 490 !-- The stretching has to start and end on a grid level. Therefore user-specified values are 491 !-- mapped to the next highest level. The calculation of the first level is realized differently 492 !-- just because of historical reasons (the advanced/new stretching mechanism was realized in a 493 !-- way that results don't change if the old parameters dz_stretch_level, dz_stretch_factor and 494 !-- dz_max are used) 495 IF ( number_stretch_level_start /= 0 ) THEN 496 dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) + dz(1)/2.0) / dz(1) ) & 530 497 * dz(1) - dz(1)/2.0 531 498 ENDIF 532 533 IF ( number_stretch_level_start > 1 ) THEN499 500 IF ( number_stretch_level_start > 1 ) THEN 534 501 DO n = 2, number_stretch_level_start 535 dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) / & 536 dz(n) ) * dz(n) 537 ENDDO 538 ENDIF 539 540 IF ( number_stretch_level_end /= 0 ) THEN 502 dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) / dz(n) ) * dz(n) 503 ENDDO 504 ENDIF 505 506 IF ( number_stretch_level_end /= 0 ) THEN 541 507 DO n = 1, number_stretch_level_end 542 dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) / & 543 dz(n+1) ) * dz(n+1) 544 ENDDO 545 ENDIF 546 508 dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) / dz(n+1) ) * dz(n+1) 509 ENDDO 510 ENDIF 511 547 512 ! 548 513 !-- Determine stretching factor if necessary 549 IF ( number_stretch_level_end >= 1 ) THEN 514 IF ( number_stretch_level_end >= 1 ) THEN 550 515 CALL calculate_stretching_factor( number_stretch_level_end ) 551 516 ENDIF … … 553 518 ! 554 519 !-- Grid for ocean with free water surface is at k=nzt (w-grid). 555 !-- In case of neumann bc at the ground the first first u-level (k=0) lies 556 !-- below the first w-level (k=0). In case of dirichlet bc the first u- and557 !-- w-level are defined at same height,but staggered from the second level.520 !-- In case of neumann bc at the ground the first first u-level (k=0) lies below the first 521 !-- w-level (k=0). In case of dirichlet bc the first u- and w-level are defined at same height, 522 !-- but staggered from the second level. 558 523 !-- The second u-level (k=1) corresponds to the top of the surface layer. 559 524 !-- z values are negative starting from z=0 (surface) … … 562 527 563 528 ! 564 !-- Determine u and v height levels considering the possibility of grid 565 !-- stretching in severalheights.529 !-- Determine u and v height levels considering the possibility of grid stretching in several 530 !-- heights. 566 531 n = 1 567 532 dz_stretch_level_start_index = 0 … … 570 535 571 536 DO k = nzt-1, 0, -1 572 573 IF ( dz_stretch_level_start(n) >= zu(k+1) ) THEN537 538 IF ( dz_stretch_level_start(n) >= zu(k+1) ) THEN 574 539 dz_stretched = dz_stretched * dz_stretch_factor_array(n) 575 540 576 IF ( dz(n) > dz(n+1) ) THEN541 IF ( dz(n) > dz(n+1) ) THEN 577 542 dz_stretched = MAX( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (higher) dz 578 543 ELSE 579 544 dz_stretched = MIN( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (lower) dz 580 545 ENDIF 581 582 IF ( dz_stretch_level_start_index(n) == 0 ) & 583 dz_stretch_level_start_index(n) = k+1 584 585 ENDIF 586 546 547 IF ( dz_stretch_level_start_index(n) == 0 ) dz_stretch_level_start_index(n) = k+1 548 549 ENDIF 550 587 551 zu(k) = zu(k+1) - dz_stretched 588 589 ! 590 !-- Make sure that the stretching ends exactly at dz_stretch_level_end 591 dz_level_end = ABS( zu(k) - dz_stretch_level_end(n) ) 592 593 IF ( dz_level_end < dz(n+1)/3.0 ) THEN552 553 ! 554 !-- Make sure that the stretching ends exactly at dz_stretch_level_end 555 dz_level_end = ABS( zu(k) - dz_stretch_level_end(n) ) 556 557 IF ( dz_level_end < dz(n+1)/3.0 ) THEN 594 558 zu(k) = dz_stretch_level_end(n) 595 559 dz_stretched = dz(n+1) 596 560 dz_stretch_level_end_index(n) = k 597 n = n + 1 561 n = n + 1 598 562 ENDIF 599 563 ENDDO 600 601 ! 602 !-- Compute the w-levels. They are always staggered half-way between the 603 !-- corresponding u-levels, except in case of dirichlet bc for u and v 604 !-- at the ground. In this case the first u- and w-level are defined at 605 !-- same height. The top w-level (nzt+1) is not used but set for 564 565 ! 566 !-- Compute the w-levels. They are always staggered half-way between the corresponding u-levels, 567 !-- except in case of dirichlet bc for u and v at the ground. In this case the first u- and 568 !-- w-level are defined at same height. The top w-level (nzt+1) is not used but set for 606 569 !-- consistency, since w and all scalar variables are defined up tp nzt+1. 607 570 zw(nzt+1) = dz(1) … … 612 575 613 576 ! 614 !-- In case of dirichlet bc for u and v the first u- and w-level are defined 615 !-- at same height. 577 !-- In case of dirichlet bc for u and v the first u- and w-level are defined at same height. 616 578 IF ( ibc_uv_b == 0 ) THEN 617 579 zu(0) = zw(0) … … 632 594 dd2zu(k) = 1.0_wp / ( dzu(k) + dzu(k+1) ) 633 595 ENDDO 634 635 ! 636 !-- The FFT- SOR-pressure solvers assume grid spacings of a staggered grid 637 !-- everywhere. For the actual grid, the grid spacing at the lowest level 638 !-- is only dz/2, but should be dz. Therefore, an additional array 639 !-- containing with appropriate grid information is created for these 640 !-- solvers. 596 597 ! 598 !-- The FFT- SOR-pressure solvers assume grid spacings of a staggered grid everywhere. For the 599 !-- actual grid, the grid spacing at the lowest level is only dz/2, but should be dz. Therefore, an 600 !-- additional array containing with appropriate grid information is created for these solvers. 641 601 IF ( psolver(1:9) /= 'multigrid' ) THEN 642 602 ALLOCATE( ddzu_pres(1:nzt+1) ) … … 659 619 topo = 0 660 620 ! 661 !-- Initialize topography by generic topography or read topography from file. 621 !-- Initialize topography by generic topography or read topography from file. 662 622 CALL init_topo( topo ) 663 623 ! 664 !-- Set flags to mask topography on the grid. 624 !-- Set flags to mask topography on the grid. 665 625 CALL set_topo_flags( topo ) 666 626 667 627 ! 668 !-- Determine the maximum level of topography. It is used for 669 !-- steering the degradation of order of the applied advection scheme, 670 !-- as well in the lpm. 628 !-- Determine the maximum level of topography. It is used for steering the degradation of order of 629 !-- the applied advection scheme, as well in the lpm. 671 630 k_top = 0 672 631 DO i = nxl, nxr … … 678 637 ENDDO 679 638 #if defined( __parallel ) 680 CALL MPI_ALLREDUCE( k_top, nzb_max, 1, MPI_INTEGER, & 681 MPI_MAX, comm2d, ierr ) 639 CALL MPI_ALLREDUCE( k_top, nzb_max, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr ) 682 640 #else 683 641 nzb_max = k_top … … 686 644 !-- Increment nzb_max by 1 in order to allow for proper diverengence correction. 687 645 !-- Further, in case topography extents up to the model top, limit to nzt. 688 nzb_max = MIN( nzb_max+1, nzt ) 689 ! 690 !-- Determine minimum index of topography. Usually, this will be nzb. In case 691 !-- t here is elevated topography, however, the lowest topography will be higher.692 !-- This index is e.g. used to calculate mean first-grid point atmosphere 693 !-- temperature, surfacepressure and density, etc. .646 nzb_max = MIN( nzb_max+1, nzt ) 647 ! 648 !-- Determine minimum index of topography. Usually, this will be nzb. In case there is elevated 649 !-- topography, however, the lowest topography will be higher. 650 !-- This index is e.g. used to calculate mean first-grid point atmosphere temperature, surface 651 !-- pressure and density, etc. . 694 652 topo_min_level = 0 695 653 #if defined( __parallel ) 696 CALL MPI_ALLREDUCE( MINVAL( topo_top_ind(nys:nyn,nxl:nxr,0) ), 697 topo_min_level, 1, MPI_INTEGER,MPI_MIN, comm2d, ierr )654 CALL MPI_ALLREDUCE( MINVAL( topo_top_ind(nys:nyn,nxl:nxr,0) ), topo_min_level, 1, MPI_INTEGER, & 655 MPI_MIN, comm2d, ierr ) 698 656 #else 699 657 topo_min_level = MINVAL( topo_top_ind(nys:nyn,nxl:nxr,0) ) … … 701 659 702 660 ! 703 !-- Check topography for consistency with model domain. Therefore, use 704 !-- maximum and minium topography-top indices. Note, minimum topography top 705 !-- index is already calculated. 661 !-- Check topography for consistency with model domain. Therefore, use maximum and minium 662 !-- topography-top indices. Note, minimum topography top index is already calculated. 706 663 IF ( TRIM( topography ) /= 'flat' ) THEN 707 664 #if defined( __parallel ) 708 CALL MPI_ALLREDUCE( MAXVAL( topo_top_ind(nys:nyn,nxl:nxr,0) ), &709 nzb_local_max, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )665 CALL MPI_ALLREDUCE( MAXVAL( topo_top_ind(nys:nyn,nxl:nxr,0) ), nzb_local_max, 1, & 666 MPI_INTEGER, MPI_MAX, comm2d, ierr ) 710 667 #else 711 668 nzb_local_max = MAXVAL( topo_top_ind(nys:nyn,nxl:nxr,0) ) … … 715 672 !-- Consistency checks 716 673 IF ( nzb_local_min < 0 .OR. nzb_local_max > nz + 1 ) THEN 717 WRITE( message_string, * ) 'nzb_local values are outside the', & 718 ' model domain', & 719 '&MINVAL( nzb_local ) = ', nzb_local_min, & 720 '&MAXVAL( nzb_local ) = ', nzb_local_max 674 WRITE( message_string, * ) 'nzb_local values are outside the model domain', & 675 '&MINVAL( nzb_local ) = ', nzb_local_min, & 676 '&MAXVAL( nzb_local ) = ', nzb_local_max 721 677 CALL message( 'init_grid', 'PA0210', 1, 2, 0, 6, 0 ) 722 678 ENDIF 723 679 ENDIF 724 680 ! 725 !-- Define vertical gridpoint from (or to) which on the usual finite difference 726 !-- form (which does not use surface fluxes) is applied681 !-- Define vertical gridpoint from (or to) which on the usual finite difference form (which does not 682 !-- use surface fluxes) is applied. 727 683 IF ( constant_flux_layer .OR. use_surface_fluxes ) THEN 728 684 nzb_diff = nzb + 2 … … 733 689 IF ( TRIM( topography ) /= 'flat' ) THEN 734 690 ! 735 !-- Allocate and set the arrays containing the topography height (for output 736 !-- reasons only). 691 !-- Allocate and set the arrays containing the topography height (for output reasons only). 737 692 IF ( nxr == nx .AND. nyn /= ny ) THEN 738 ALLOCATE( zu_s_inner(nxl:nxr+1,nys:nyn), & 739 zw_w_inner(nxl:nxr+1,nys:nyn) ) 693 ALLOCATE( zu_s_inner(nxl:nxr+1,nys:nyn), zw_w_inner(nxl:nxr+1,nys:nyn) ) 740 694 ELSEIF ( nxr /= nx .AND. nyn == ny ) THEN 741 ALLOCATE( zu_s_inner(nxl:nxr,nys:nyn+1), & 742 zw_w_inner(nxl:nxr,nys:nyn+1) ) 695 ALLOCATE( zu_s_inner(nxl:nxr,nys:nyn+1), zw_w_inner(nxl:nxr,nys:nyn+1) ) 743 696 ELSEIF ( nxr == nx .AND. nyn == ny ) THEN 744 ALLOCATE( zu_s_inner(nxl:nxr+1,nys:nyn+1), & 745 zw_w_inner(nxl:nxr+1,nys:nyn+1) ) 697 ALLOCATE( zu_s_inner(nxl:nxr+1,nys:nyn+1), zw_w_inner(nxl:nxr+1,nys:nyn+1) ) 746 698 ELSE 747 ALLOCATE( zu_s_inner(nxl:nxr,nys:nyn), & 748 zw_w_inner(nxl:nxr,nys:nyn) ) 699 ALLOCATE( zu_s_inner(nxl:nxr,nys:nyn), zw_w_inner(nxl:nxr,nys:nyn) ) 749 700 ENDIF 750 701 … … 752 703 zw_w_inner = 0.0_wp 753 704 ! 754 !-- Determine local topography height on scalar and w-grid. Note, setting 755 !-- lateral boundary values is not necessary, realized via wall_flags_static_0 756 !-- array. Further, please note that loop bounds are different from 757 !-- nxl to nxr and nys to nyn on south and right model boundary, hence, 705 !-- Determine local topography height on scalar and w-grid. Note, setting lateral boundary values 706 !-- is not necessary, realized via wall_flags_static_0 array. Further, please note that loop 707 !-- bounds are different from nxl to nxr and nys to nyn on south and right model boundary, hence, 758 708 !-- use intrinsic lbound and ubound functions to infer array bounds. 759 709 DO i = LBOUND(zu_s_inner, 1), UBOUND(zu_s_inner, 1) 760 710 DO j = LBOUND(zu_s_inner, 2), UBOUND(zu_s_inner, 2) 761 711 ! 762 !-- Topography height on scalar grid. Therefore, determine index of 763 !-- upward-facing surfaceelement on scalar grid.712 !-- Topography height on scalar grid. Therefore, determine index of upward-facing surface 713 !-- element on scalar grid. 764 714 zu_s_inner(i,j) = zu(topo_top_ind(j,i,0)) 765 715 ! 766 !-- Topography height on w grid. Therefore, determine index of 767 !-- upward-facing surfaceelement on w grid.716 !-- Topography height on w grid. Therefore, determine index of upward-facing surface 717 !-- element on w grid. 768 718 zw_w_inner(i,j) = zw(topo_top_ind(j,i,3)) 769 719 ENDDO … … 775 725 776 726 ! Description: 777 ! -----------------------------------------------------------------------------! 778 !> Calculation of the stretching factor through an iterative method. Ideas were 779 !> taken from the paper "Regional stretched grid generation and its application 780 !> to the NCAR RegCM (1999)". Normally, no analytic solution exists because the 781 !> system of equations has two variables (r,l) but four requirements 782 !> (l=integer, r=[0,88;1,2], Eq(6), Eq(5) starting from index j=1) which 783 !> results into an overdetermined system. 784 !------------------------------------------------------------------------------! 727 ! -------------------------------------------------------------------------------------------------! 728 !> Calculation of the stretching factor through an iterative method. Ideas were taken from the paper 729 !> "Regional stretched grid generation and its application to the NCAR RegCM (1999)". Normally, no 730 !> analytic solution exists because the system of equations has two variables (r,l) but four 731 !> requirements (l=integer, r=[0,88;1,2], Eq(6), Eq(5) starting from index j=1) which results into 732 !> an overdetermined system. 733 !--------------------------------------------------------------------------------------------------! 785 734 SUBROUTINE calculate_stretching_factor( number_end ) 786 787 USE control_parameters, &788 ONLY: dz, dz_stretch_factor_array, 789 dz_stretch_level_end, dz_stretch_level_start,message_string790 735 736 USE control_parameters, & 737 ONLY: dz, dz_stretch_factor_array, dz_stretch_level_end, dz_stretch_level_start, & 738 message_string 739 791 740 USE kinds 792 741 793 742 IMPLICIT NONE 794 795 INTEGER(iwp) :: iterations !< number of iterations until stretch_factor_lower/upper_limit is reached 796 INTEGER(iwp) :: l_rounded !< after l_rounded grid levels dz(n) is strechted to dz(n+1) with stretch_factor_2 743 744 REAL(wp), PARAMETER :: stretch_factor_interval = 1.0E-06_wp !< interval for sampling possible stretching factors 745 REAL(wp), PARAMETER :: stretch_factor_lower_limit = 0.88_wp !< lowest possible stretching factor 746 REAL(wp), PARAMETER :: stretch_factor_upper_limit = 1.12_wp !< highest possible stretching factor 747 748 INTEGER(iwp) :: iterations !< number of iterations until stretch_factor_lower/upper_limit is reached 749 INTEGER(iwp) :: l_rounded !< after l_rounded grid levels dz(n) is strechted to dz(n+1) with stretch_factor_2 797 750 INTEGER(iwp) :: n !< loop variable for stretching 798 751 799 752 INTEGER(iwp), INTENT(IN) :: number_end !< number of user-specified end levels for stretching 800 753 801 754 REAL(wp) :: delta_l !< absolute difference between l and l_rounded 802 755 REAL(wp) :: delta_stretch_factor !< absolute difference between stretch_factor_1 and stretch_factor_2 803 REAL(wp) :: delta_total_new !< sum of delta_l and delta_stretch_factor for the next iteration (should be as small as possible) 804 REAL(wp) :: delta_total_old !< sum of delta_l and delta_stretch_factor for the last iteration 756 REAL(wp) :: delta_total_new !< sum of delta_l and delta_stretch_factor for the next iteration (should be as small as 757 !< possible) 758 REAL(wp) :: delta_total_old !< sum of delta_l and delta_stretch_factor for the last iteration 805 759 REAL(wp) :: distance !< distance between dz_stretch_level_start and dz_stretch_level_end (stretching region) 806 REAL(wp) :: l !< value that fulfil Eq. (5) in the paper mentioned above together with stretch_factor_1 exactly 760 REAL(wp) :: l !< value that fulfil Eq. (5) in the paper mentioned above together with stretch_factor_1 761 !< exactly 807 762 REAL(wp) :: numerator !< numerator of the quotient 808 763 REAL(wp) :: stretch_factor_1 !< stretching factor that fulfil Eq. (5) togehter with l exactly 809 764 REAL(wp) :: stretch_factor_2 !< stretching factor that fulfil Eq. (6) togehter with l_rounded exactly 810 811 REAL(wp) :: dz_stretch_factor_array_2(9) = 1.08_wp !< Array that contains all stretch_factor_2 that belongs to stretch_factor_1 812 813 REAL(wp), PARAMETER :: stretch_factor_interval = 1.0E-06_wp !< interval for sampling possible stretching factors 814 REAL(wp), PARAMETER :: stretch_factor_lower_limit = 0.88_wp !< lowest possible stretching factor 815 REAL(wp), PARAMETER :: stretch_factor_upper_limit = 1.12_wp !< highest possible stretching factor 816 817 765 766 REAL(wp) :: dz_stretch_factor_array_2(9) = 1.08_wp !< Array that contains all stretch_factor_2 that belongs to 767 !< stretch_factor_1 768 769 818 770 l = 0 819 771 DO n = 1, number_end 820 772 821 773 iterations = 1 822 stretch_factor_1 = 1.0_wp 774 stretch_factor_1 = 1.0_wp 823 775 stretch_factor_2 = 1.0_wp 824 776 delta_total_old = 1.0_wp 825 777 826 778 ! 827 779 !-- First branch for stretching from rough to fine 828 IF ( dz(n) > dz(n+1) ) THEN829 DO WHILE ( stretch_factor_1 >= stretch_factor_lower_limit ) 830 780 IF ( dz(n) > dz(n+1) ) THEN 781 DO WHILE ( stretch_factor_1 >= stretch_factor_lower_limit ) 782 831 783 stretch_factor_1 = 1.0_wp - iterations * stretch_factor_interval 832 distance = ABS( dz_stretch_level_end(n) - & 833 dz_stretch_level_start(n) ) 834 numerator = distance*stretch_factor_1/dz(n) + & 835 stretch_factor_1 - distance/dz(n) 836 837 IF ( numerator > 0.0_wp ) THEN 784 distance = ABS( dz_stretch_level_end(n) - dz_stretch_level_start(n) ) 785 numerator = distance * stretch_factor_1 / dz(n) + stretch_factor_1 - distance / dz(n) 786 787 IF ( numerator > 0.0_wp ) THEN 838 788 l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0_wp 839 789 l_rounded = NINT( l ) 840 790 delta_l = ABS( l_rounded - l ) / l 841 791 ENDIF 842 792 843 793 stretch_factor_2 = EXP( LOG( dz(n+1)/dz(n) ) / (l_rounded) ) 844 845 delta_stretch_factor = ABS( stretch_factor_1 - & 846 stretch_factor_2 ) / & 847 stretch_factor_2 848 794 795 delta_stretch_factor = ABS( stretch_factor_1 - stretch_factor_2 ) / stretch_factor_2 796 849 797 delta_total_new = delta_l + delta_stretch_factor 850 798 851 799 ! 852 !-- stretch_factor_1 is taken to guarantee that the stretching 853 !-- p rocedure ends as close as possible to dz_stretch_level_end.854 !-- stretch_factor_2 would guarantee that the stretched dz(n) is 855 !-- equal to dz(n+1) afterl_rounded grid levels.856 IF (delta_total_new < delta_total_old) THEN800 !-- stretch_factor_1 is taken to guarantee that the stretching procedure ends as close as 801 !-- possible to dz_stretch_level_end. 802 !-- stretch_factor_2 would guarantee that the stretched dz(n) is equal to dz(n+1) after 803 !-- l_rounded grid levels. 804 IF (delta_total_new < delta_total_old) THEN 857 805 dz_stretch_factor_array(n) = stretch_factor_1 858 806 dz_stretch_factor_array_2(n) = stretch_factor_2 859 807 delta_total_old = delta_total_new 860 808 ENDIF 861 809 862 810 iterations = iterations + 1 863 811 864 812 ENDDO 865 813 866 814 ! 867 815 !-- Second branch for stretching from fine to rough 868 ELSEIF ( dz(n) < dz(n+1) ) THEN816 ELSEIF ( dz(n) < dz(n+1) ) THEN 869 817 DO WHILE ( stretch_factor_1 <= stretch_factor_upper_limit ) 870 818 871 819 stretch_factor_1 = 1.0_wp + iterations * stretch_factor_interval 872 distance = ABS( dz_stretch_level_end(n) - & 873 dz_stretch_level_start(n) ) 874 numerator = distance*stretch_factor_1/dz(n) + & 875 stretch_factor_1 - distance/dz(n) 876 820 distance = ABS( dz_stretch_level_end(n) - dz_stretch_level_start(n) ) 821 numerator = distance * stretch_factor_1 / dz(n) + stretch_factor_1 - distance / dz(n) 822 877 823 l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0_wp 878 824 l_rounded = NINT( l ) 879 825 delta_l = ABS( l_rounded - l ) / l 880 826 881 827 stretch_factor_2 = EXP( LOG( dz(n+1)/dz(n) ) / (l_rounded) ) 882 828 883 delta_stretch_factor = ABS( stretch_factor_1 - & 884 stretch_factor_2 ) / & 885 stretch_factor_2 886 829 delta_stretch_factor = ABS( stretch_factor_1 - stretch_factor_2 ) / stretch_factor_2 830 887 831 delta_total_new = delta_l + delta_stretch_factor 888 889 ! 890 !-- stretch_factor_1 is taken to guarantee that the stretching 891 !-- p rocedure ends as close as possible to dz_stretch_level_end.892 !-- stretch_factor_2 would guarantee that the stretched dz(n) is 893 !-- equal to dz(n+1) afterl_rounded grid levels.894 IF (delta_total_new < delta_total_old) THEN832 833 ! 834 !-- stretch_factor_1 is taken to guarantee that the stretching procedure ends as close as 835 !-- possible to dz_stretch_level_end. 836 !-- stretch_factor_2 would guarantee that the stretched dz(n) is equal to dz(n+1) after 837 !-- l_rounded grid levels. 838 IF (delta_total_new < delta_total_old) THEN 895 839 dz_stretch_factor_array(n) = stretch_factor_1 896 840 dz_stretch_factor_array_2(n) = stretch_factor_2 897 841 delta_total_old = delta_total_new 898 842 ENDIF 899 843 900 844 iterations = iterations + 1 901 845 ENDDO 902 846 903 847 ELSE 904 848 message_string= 'Two adjacent values of dz must be different' 905 849 CALL message( 'init_grid', 'PA0228', 1, 2, 0, 6, 0 ) 906 907 ENDIF 908 909 ! 910 !-- Check if also the second stretching factor fits into the allowed 911 !-- interval. If not, print a warning for the user. 912 IF ( dz_stretch_factor_array_2(n) < stretch_factor_lower_limit .OR. & 913 dz_stretch_factor_array_2(n) > stretch_factor_upper_limit ) THEN 914 WRITE( message_string, * ) 'stretch_factor_2 = ', & 915 dz_stretch_factor_array_2(n), ' which is',& 916 ' responsible for exactly reaching& dz =',& 917 dz(n+1), 'after a specific amount of', & 918 ' grid levels& exceeds the upper', & 919 ' limit =', stretch_factor_upper_limit, & 920 ' &or lower limit = ', & 921 stretch_factor_lower_limit 850 851 ENDIF 852 853 ! 854 !-- Check if also the second stretching factor fits into the allowed interval. If not, print a 855 !-- warning for the user. 856 IF ( dz_stretch_factor_array_2(n) < stretch_factor_lower_limit .OR. & 857 dz_stretch_factor_array_2(n) > stretch_factor_upper_limit ) THEN 858 WRITE( message_string, * ) 'stretch_factor_2 = ', dz_stretch_factor_array_2(n), & 859 ' which is', ' responsible for exactly reaching& dz =', & 860 dz(n+1), 'after a specific amount of', & 861 ' grid levels& exceeds the upper', & 862 ' limit =', stretch_factor_upper_limit, & 863 ' &or lower limit = ', stretch_factor_lower_limit 922 864 CALL message( 'init_grid', 'PA0499', 0, 1, 0, 6, 0 ) 923 865 924 866 ENDIF 925 867 ENDDO 926 868 927 869 END SUBROUTINE calculate_stretching_factor 928 929 870 871 930 872 ! Description: 931 ! -----------------------------------------------------------------------------! 932 !> Set temporary topography flags and reference buildings on top of underlying 933 !> orography. 934 !------------------------------------------------------------------------------! 873 ! -------------------------------------------------------------------------------------------------! 874 !> Set temporary topography flags and reference buildings on top of underlying orography. 875 !--------------------------------------------------------------------------------------------------! 935 876 SUBROUTINE process_topography( topo_3d ) 936 877 937 USE arrays_3d, &878 USE arrays_3d, & 938 879 ONLY: zu, zw 939 880 940 USE control_parameters, &881 USE control_parameters, & 941 882 ONLY: bc_lr_cyc, bc_ns_cyc, ocean_mode 942 883 943 USE exchange_horiz_mod, & 944 ONLY: exchange_horiz_int, exchange_horiz_2d 945 946 USE indices, & 947 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nzb, & 948 nzt 949 950 USE netcdf_data_input_mod, & 951 ONLY: buildings_f, building_id_f, building_type_f, & 952 init_model, & 953 input_pids_static, & 884 USE exchange_horiz_mod, & 885 ONLY: exchange_horiz_2d, exchange_horiz_int 886 887 USE indices, & 888 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nzb, nzt 889 890 USE netcdf_data_input_mod, & 891 ONLY: buildings_f, building_id_f, building_type_f, & 892 init_model, & 893 input_pids_static, & 954 894 terrain_height_f 955 895 … … 972 912 #endif 973 913 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: build_ids !< building IDs on entire model domain 974 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: build_ids_final !< building IDs on entire model domain, multiple occurences are sorted out 914 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: build_ids_final !< building IDs on entire model domain, multiple occurences are 915 !< sorted out 975 916 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: build_ids_final_tmp !< temporary array used for resizing 976 917 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: build_ids_l !< building IDs on local subdomain … … 980 921 INTEGER(iwp), DIMENSION(0:numprocs-1) :: num_buildings_l !< number of buildings with different ID on local subdomain 981 922 982 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo_3d !< input array for 3D topography and dummy array for setting "outer"-flags 983 984 REAL(wp) :: ocean_offset !< offset to consider inverse vertical coordinate at topography definition 985 REAL(wp) :: oro_min = 0.0_wp !< minimum terrain height in entire model domain, used to reference terrain to zero 923 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo_3d !< input array for 3D topography and dummy array for setting 924 !< "outer"-flags 925 926 REAL(wp) :: ocean_offset !< offset to consider inverse vertical coordinate at topography 927 !< definition 928 REAL(wp) :: oro_min = 0.0_wp !< minimum terrain height in entire model domain, used to reference 929 !< terrain to zero 986 930 REAL(wp), DIMENSION(:), ALLOCATABLE :: oro_max !< maximum terrain height occupied by an building with certain id 987 REAL(wp), DIMENSION(:), ALLOCATABLE :: oro_max_l !< maximum terrain height occupied by an building with certain id, on local subdomain988 989 ! 990 ! -- Reference lowest terrain height to zero. This ensures that first,991 !-- non-required gird levels (those which lie entirely below the minimum992 !-- orography) are avoided, and second, that also negative orography can be used993 !-- within the input file.994 !-- Please note, in case of a nested run, the global minimum from all parent and 995 !-- childs need to be removeto avoid steep edges at the child-domain boundaries.931 REAL(wp), DIMENSION(:), ALLOCATABLE :: oro_max_l !< maximum terrain height occupied by an building with certain id, 932 !< on local subdomain 933 934 ! 935 !-- Reference lowest terrain height to zero. This ensures that first, non-required gird levels 936 !-- (those which lie entirely below the minimum orography) are avoided, and second, that also 937 !-- negative orography can be used within the input file. 938 !-- Please note, in case of a nested run, the global minimum from all parent and childs needs to be 939 !-- removed to avoid steep edges at the child-domain boundaries. 996 940 IF ( input_pids_static ) THEN 997 998 #if defined( __parallel ) 999 CALL MPI_ALLREDUCE( MINVAL( terrain_height_f%var ), oro_min, 1, &1000 MPI_ REAL, MPI_MIN, MPI_COMM_WORLD, ierr )941 942 #if defined( __parallel ) 943 CALL MPI_ALLREDUCE( MINVAL( terrain_height_f%var ), oro_min, 1, MPI_REAL, MPI_MIN, & 944 MPI_COMM_WORLD, ierr ) 1001 945 #else 1002 946 oro_min = MINVAL( terrain_height_f%var ) … … 1007 951 init_model%origin_z = init_model%origin_z + oro_min 1008 952 1009 ENDIF 1010 1011 ! 1012 !-- In the following, buildings and orography are further preprocessed 1013 !-- before they are mapped on the LES grid. 1014 !-- Buildings are mapped on top of the orography by maintaining the roof 1015 !-- shape of the building. This can be achieved by referencing building on 1016 !-- top of the maximum terrain height within the area occupied by the 1017 !-- respective building. As buildings and terrain height are defined PE-wise, 1018 !-- parallelization of this referencing is required (a building can be 1019 !-- distributed between different PEs). 1020 !-- In a first step, determine the number of buildings with different 1021 !-- building id on each PE. In a next step, all building ids are gathered 1022 !-- into one array which is present to all PEs. For each building ID, 1023 !-- the maximum terrain height occupied by the respective building is 1024 !-- computed and distributed to each PE. 1025 !-- Finally, for each building id and its respective reference orography, 1026 !-- builidings are mapped on top. 1027 !-- 1028 !-- First, pre-set topography flags, bit 1 indicates orography, bit 2 1029 !-- buildings 1030 !-- classify the respective surfaces. 953 ENDIF 954 955 ! 956 !-- In the following, buildings and orography are further preprocessed before they are mapped on the 957 !-- LES grid. 958 !-- Buildings are mapped on top of the orography by maintaining the roof shape of the building. This 959 !-- can be achieved by referencing building on top of the maximum terrain height within the area 960 !-- occupied by the respective building. As buildings and terrain height are defined PE-wise, 961 !-- parallelization of this referencing is required (a building can be distributed between different 962 !-- PEs). 963 !-- In a first step, determine the number of buildings with different building id on each PE. In a 964 !-- next step, all building ids are gathered into one array which is present to all PEs. For each 965 !-- building ID, the maximum terrain height occupied by the respective building is computed and 966 !-- distributed to each PE. 967 !-- Finally, for each building id and its respective reference orography, builidings are mapped on 968 !-- top. 969 !-- 970 !-- First, pre-set topography flags, bit 1 indicates orography, bit 2 buildings classify the 971 !-- respective surfaces. 1031 972 topo_3d = IBSET( topo_3d, 0 ) 1032 973 topo_3d(nzb,:,:) = IBCLR( topo_3d(nzb,:,:), 0 ) 1033 974 ! 1034 !-- In order to map topography on PALM grid also in case of ocean simulations, 1035 !-- pre-calculate anoffset value.975 !-- In order to map topography on PALM grid also in case of ocean simulations, pre-calculate an 976 !-- offset value. 1036 977 ocean_offset = MERGE( zw(0), 0.0_wp, ocean_mode ) 1037 978 ! 1038 !-- Reference buildings on top of orography. This is not necessary 1039 !-- if topography is read from ASCII file as no distinction between buildings 1040 !-- and terrain height can be made. Moreover, this is also not necessary if 1041 !-- urban-surface and land-surface model are used at the same time. 979 !-- Reference buildings on top of orography. This is not necessary if topography is read from ASCII 980 !-- file as no distinction between buildings and terrain height can be made. Moreover, this is also 981 !-- not necessary if urban-surface and land-surface model are used at the same time. 1042 982 IF ( input_pids_static ) THEN 1043 983 1044 IF ( buildings_f%from_file ) THEN 984 IF ( buildings_f%from_file ) THEN 1045 985 num_buildings_l = 0 1046 986 num_buildings = 0 1047 987 ! 1048 !-- Allocate at least one element for building ids and give it an inital 1049 !-- negative value that will be overwritten later. This, however, is1050 !-- necessary in case there all IDs in the model domain are fill values.988 !-- Allocate at least one element for building ids and give it an inital negative value that 989 !-- will be overwritten later. This, however, is necessary in case there all IDs in the model 990 !-- domain are fill values. 1051 991 ALLOCATE( build_ids_l(1) ) 1052 build_ids_l = -1 992 build_ids_l = -1 1053 993 DO i = nxl, nxr 1054 994 DO j = nys, nyn 1055 995 IF ( building_id_f%var(j,i) /= building_id_f%fill ) THEN 1056 996 IF ( num_buildings_l(myid) > 0 ) THEN 1057 IF ( ANY( building_id_f%var(j,i) == build_ids_l ) ) & 1058 THEN 997 IF ( ANY( building_id_f%var(j,i) == build_ids_l ) ) THEN 1059 998 CYCLE 1060 999 ELSE … … 1066 1005 DEALLOCATE( build_ids_l ) 1067 1006 ALLOCATE( build_ids_l(1:num_buildings_l(myid)) ) 1068 build_ids_l(1:num_buildings_l(myid)-1) = &1069 build_ids_l_tmp(1:num_buildings_l(myid)-1)1007 build_ids_l(1:num_buildings_l(myid)-1) = & 1008 build_ids_l_tmp(1:num_buildings_l(myid)-1) 1070 1009 build_ids_l(num_buildings_l(myid)) = building_id_f%var(j,i) 1071 1010 DEALLOCATE( build_ids_l_tmp ) 1072 1011 ENDIF 1073 1012 ! 1074 !-- First occuring building id on PE 1075 ELSE 1013 !-- First occuring building id on PE 1014 ELSE 1076 1015 num_buildings_l(myid) = num_buildings_l(myid) + 1 1077 1016 build_ids_l(1) = building_id_f%var(j,i) … … 1081 1020 ENDDO 1082 1021 ! 1083 !-- Determine number of different building ids for the entire domain 1084 #if defined( __parallel ) 1085 CALL MPI_ALLREDUCE( num_buildings_l, num_buildings, numprocs, 1086 MPI_INTEGER, MPI_SUM, comm2d, ierr )1022 !-- Determine number of different building ids for the entire domain 1023 #if defined( __parallel ) 1024 CALL MPI_ALLREDUCE( num_buildings_l, num_buildings, numprocs, MPI_INTEGER, MPI_SUM, & 1025 comm2d, ierr ) 1087 1026 #else 1088 1027 num_buildings = num_buildings_l 1089 1028 #endif 1090 1029 ! 1091 !-- Gather all buildings ids on each PEs. 1092 !-- First, allocate array encompassing all building ids in model domain. 1030 !-- Gather all buildings ids on each PEs. 1031 !-- First, allocate array encompassing all building ids in model domain. 1093 1032 ALLOCATE( build_ids(1:SUM(num_buildings)) ) 1094 #if defined( __parallel ) 1095 ! 1096 !-- Allocate array for displacements. 1097 !-- As each PE may has a different number of buildings, so that 1098 !-- the block sizes send by each PE may not be equal. Hence, 1099 !-- information about the respective displacement is required, indicating 1100 !-- the respective adress where each MPI-task writes into the receive 1101 !-- buffer array 1033 #if defined( __parallel ) 1034 ! 1035 !-- Allocate array for displacements. 1036 !-- As each PE may has a different number of buildings, so that the block sizes send by each 1037 !-- PE may not be equal. Hence, information about the respective displacement is required, 1038 !-- indicating the respective adress where each MPI-task writes into the receive buffer array. 1102 1039 ALLOCATE( displace_dum(0:numprocs-1) ) 1103 1040 displace_dum(0) = 0 … … 1106 1043 ENDDO 1107 1044 1108 CALL MPI_ALLGATHERV( build_ids_l(1:num_buildings_l(myid)), & 1109 num_buildings(myid), & 1110 MPI_INTEGER, & 1111 build_ids, & 1112 num_buildings, & 1113 displace_dum, & 1114 MPI_INTEGER, & 1115 comm2d, ierr ) 1045 CALL MPI_ALLGATHERV( build_ids_l(1:num_buildings_l(myid)), num_buildings(myid), & 1046 MPI_INTEGER, build_ids, num_buildings, displace_dum, MPI_INTEGER, & 1047 comm2d, ierr ) 1116 1048 1117 1049 DEALLOCATE( displace_dum ) … … 1122 1054 1123 1055 ! 1124 !-- Note, in parallel mode building ids can occure mutliple times, as 1125 !-- each PE has send its own ids. Therefore, sort out building ids which 1126 !-- appear more than one time. 1056 !-- Note, in parallel mode building ids can occure mutliple times, as each PE has send its own 1057 !-- ids. Therefore, sort out building ids which appear more than one time. 1127 1058 num_build = 0 1128 1059 DO nr = 1, SIZE(build_ids) … … 1142 1073 build_ids_final(num_build) = build_ids(nr) 1143 1074 DEALLOCATE( build_ids_final_tmp ) 1144 ENDIF 1075 ENDIF 1145 1076 ELSE 1146 1077 num_build = num_build + 1 … … 1151 1082 1152 1083 ! 1153 !-- Determine maximumum terrain height occupied by the respective 1154 !-- building and temporalily store on oro_max1084 !-- Determine maximumum terrain height occupied by the respective building and temporalily 1085 !-- store on oro_max. 1155 1086 ALLOCATE( oro_max_l(1:SIZE(build_ids_final)) ) 1156 1087 ALLOCATE( oro_max(1:SIZE(build_ids_final)) ) … … 1158 1089 1159 1090 DO nr = 1, SIZE(build_ids_final) 1160 oro_max_l(nr) = MAXVAL( & 1161 MERGE( terrain_height_f%var(nys:nyn,nxl:nxr), & 1162 0.0_wp, & 1163 building_id_f%var(nys:nyn,nxl:nxr) == & 1164 build_ids_final(nr) ) ) 1165 ENDDO 1166 1167 #if defined( __parallel ) 1168 IF ( SIZE(build_ids_final) >= 1 ) THEN 1169 CALL MPI_ALLREDUCE( oro_max_l, oro_max, SIZE( oro_max ), MPI_REAL,& 1170 MPI_MAX, comm2d, ierr ) 1091 oro_max_l(nr) = MAXVAL( MERGE( terrain_height_f%var(nys:nyn,nxl:nxr), & 1092 0.0_wp, & 1093 building_id_f%var(nys:nyn,nxl:nxr) == & 1094 build_ids_final(nr) ) ) 1095 ENDDO 1096 1097 #if defined( __parallel ) 1098 IF ( SIZE(build_ids_final) >= 1 ) THEN 1099 CALL MPI_ALLREDUCE( oro_max_l, oro_max, SIZE( oro_max ), MPI_REAL, MPI_MAX, comm2d, & 1100 ierr ) 1171 1101 ENDIF 1172 1102 #else … … 1174 1104 #endif 1175 1105 ! 1176 !-- Finally, determine discrete grid height of maximum orography occupied 1177 !-- by a building. Use all-or-nothing approach, i.e. if terrain 1178 !-- exceeds the scalar level the grid box is fully terrain and the 1179 !-- maximum terrain is set to the zw level. 1180 !-- terrain or 1106 !-- Finally, determine discrete grid height of maximum orography occupied by a building. Use 1107 !-- all-or-nothing approach, i.e. if terrain exceeds the scalar level the grid box is fully 1108 !-- terrain and the maximum terrain is set to the zw level. 1109 !-- terrain or 1181 1110 oro_max_l = 0.0 1182 1111 DO nr = 1, SIZE(build_ids_final) 1183 1112 DO k = nzb, nzt 1184 IF ( zu(k) - ocean_offset <= oro_max(nr) ) & 1185 oro_max_l(nr) = zw(k) - ocean_offset 1113 IF ( zu(k) - ocean_offset <= oro_max(nr) ) oro_max_l(nr) = zw(k) - ocean_offset 1186 1114 ENDDO 1187 1115 oro_max(nr) = oro_max_l(nr) … … 1195 1123 END IF 1196 1124 ! 1197 !-- Map orography as well as buildings onto grid. 1125 !-- Map orography as well as buildings onto grid. 1198 1126 DO i = nxl, nxr 1199 1127 DO j = nys, nyn … … 1204 1132 IF ( building_id_f%var(j,i) /= building_id_f%fill ) THEN 1205 1133 ! 1206 !-- Determine index where maximum terrain height occupied by 1207 !-- the respective building height is stored. 1208 nr = MINLOC( ABS( build_ids_final - & 1209 building_id_f%var(j,i) ), DIM = 1 ) 1134 !-- Determine index where maximum terrain height occupied by the respective building 1135 !-- height is stored. 1136 nr = MINLOC( ABS( build_ids_final - building_id_f%var(j,i) ), DIM=1 ) 1210 1137 ! 1211 1138 !-- Save grid-indexed oro_max … … 1215 1142 DO k = nzb, nzt 1216 1143 ! 1217 !-- In a first step, if grid point is below or equal the given 1218 !-- terrain height, grid point is flagged to be of type natural. 1219 !-- Please note, in case there is also a building which is lower 1220 !-- than the vertical grid spacing, initialization of surface 1221 !-- attributes will not be correct as given surface information 1222 !-- will not be in accordance to the classified grid points. 1144 !-- In a first step, if grid point is below or equal the given terrain height, grid 1145 !-- point is flagged to be of type natural. 1146 !-- Please note, in case there is also a building which is lower than the vertical grid 1147 !-- spacing, initialization of surface attributes will not be correct as given surface 1148 !-- information will not be in accordance to the classified grid points. 1223 1149 !-- Hence, in this case, also a building flag. 1224 1150 IF ( zu(k) - ocean_offset <= terrain_height_f%var(j,i) ) THEN … … 1228 1154 ENDIF 1229 1155 ! 1230 !-- Set building grid points. Here, only consider 2D buildings. 1231 !-- 3D buildings require separate treatment. 1156 !-- Set building grid points. Here, only consider 2D buildings. 1157 !-- 3D buildings require separate treatment. 1232 1158 IF ( buildings_f%from_file .AND. buildings_f%lod == 1 ) THEN 1233 1159 ! 1234 !-- Fill-up the terrain to the level of maximum orography 1235 !-- within the building-coveredarea.1160 !-- Fill-up the terrain to the level of maximum orography within the building-covered 1161 !-- area. 1236 1162 IF ( building_id_f%var(j,i) /= building_id_f%fill ) THEN 1237 1163 ! 1238 !-- Note, oro_max is always on zw level 1164 !-- Note, oro_max is always on zw level 1239 1165 IF ( zu(k) - ocean_offset < oro_max(nr) ) THEN 1240 1166 topo_3d(k,j,i) = IBCLR( topo_3d(k,j,i), 0 ) 1241 1167 topo_3d(k,j,i) = IBSET( topo_3d(k,j,i), 1 ) 1242 ELSEIF ( zu(k) - ocean_offset <= & 1243 oro_max(nr) + buildings_f%var_2d(j,i) ) THEN 1168 ELSEIF ( zu(k) - ocean_offset <= oro_max(nr) + buildings_f%var_2d(j,i) ) THEN 1244 1169 topo_3d(k,j,i) = IBCLR( topo_3d(k,j,i), 0 ) 1245 1170 topo_3d(k,j,i) = IBSET( topo_3d(k,j,i), 2 ) … … 1249 1174 ENDDO 1250 1175 ! 1251 !-- Special treatment for non grid-resolved buildings. This case, 1252 !-- the uppermost terrain grid point is flagged as building as well 1253 !-- well, even though no building exists at all. However, the 1254 !-- surface element will be identified as urban-surface and the 1255 !-- input data provided by the drivers is consistent to the surface 1256 !-- classification. Else, all non grid-resolved buildings would vanish 1257 !-- and identified as terrain grid points, which, however, won't be 1258 !-- consistent with the input data. 1176 !-- Special treatment for non grid-resolved buildings. This case, the uppermost terrain 1177 !-- grid point is flagged as building as well, even though no building exists at all. 1178 !-- However, the surface element will be identified as urban-surface and the input data 1179 !-- provided by the drivers is consistent to the surface classification. Else, all non 1180 !-- grid-resolved buildings would vanish and identified as terrain grid points, which, 1181 !-- however, won't be consistent with the input data. 1259 1182 IF ( buildings_f%from_file .AND. buildings_f%lod == 1 ) THEN 1260 1183 IF ( building_id_f%var(j,i) /= building_id_f%fill ) THEN … … 1269 1192 ENDIF 1270 1193 ! 1271 !-- Map 3D buildings onto terrain height. 1272 !-- In case of any slopes, map building on top of maximum terrain 1273 !-- height covered by the building. In other words, extend1274 !-- building down to the respective local terrain-surface height.1194 !-- Map 3D buildings onto terrain height. 1195 !-- In case of any slopes, map building on top of maximum terrain height covered by the 1196 !-- building. In other words, extend building down to the respective local terrain-surface 1197 !-- height. 1275 1198 IF ( buildings_f%from_file .AND. buildings_f%lod == 2 ) THEN 1276 1199 IF ( building_id_f%var(j,i) /= building_id_f%fill ) THEN 1277 1200 ! 1278 !-- Extend building down to the terrain surface, i.e. fill-up 1279 !-- surface irregularities below a building. Note, oro_max 1280 !-- is already a discrete height according to the all-or-nothing 1281 !-- approach, i.e. grid box is either topography or atmosphere, 1201 !-- Extend building down to the terrain surface, i.e. fill-up surface irregularities 1202 !-- below a building. Note, oro_max is already a discrete height according to the 1203 !-- all-or-nothing approach, i.e. grid box is either topography or atmosphere, 1282 1204 !-- terrain top is defined at upper bound of the grid box. 1283 !-- Hence, check for zw in this case. 1284 !-- Note, do this only for buildings which are surface mounted, 1285 !-- i.e. building types 1-6. Below bridges, which are represented 1286 !-- exclusively by building type 7, terrain shape should be 1287 !-- maintained. 1205 !-- Hence, check for zw in this case. 1206 !-- Note, do this only for buildings which are surface mounted, i.e. building types 1207 !-- 1-6. Below bridges, which are represented exclusively by building type 7, terrain 1208 !-- shape should be maintained. 1288 1209 IF ( building_type_f%from_file ) THEN 1289 1210 IF ( building_type_f%var(j,i) /= 7 ) THEN 1290 DO k = topo_top_index + 1, nzt + 1 1211 DO k = topo_top_index + 1, nzt + 1 1291 1212 IF ( zu(k) - ocean_offset <= oro_max(nr) ) THEN 1292 1213 topo_3d(k,j,i) = IBCLR( topo_3d(k,j,i), 0 ) 1293 1214 topo_3d(k,j,i) = IBSET( topo_3d(k,j,i), 1 ) 1294 1215 ENDIF 1295 ENDDO 1296 ! 1297 !-- After surface irregularities are smoothen, determine 1298 !-- lower start index where building starts.1216 ENDDO 1217 ! 1218 !-- After surface irregularities are smoothen, determine lower start index 1219 !-- where building starts. 1299 1220 DO k = nzb, nzt 1300 IF ( zu(k) - ocean_offset <= oro_max(nr) ) & 1301 topo_top_index = k 1221 IF ( zu(k) - ocean_offset <= oro_max(nr) ) topo_top_index = k 1302 1222 ENDDO 1303 1223 ENDIF … … 1320 1240 ENDDO 1321 1241 ! 1322 !-- Horizontal exchange the oro_max array, which is required to for 1323 !-- initialization ofbuilding-surface properties.1242 !-- Horizontal exchange the oro_max array, which is required to for initialization of 1243 !-- building-surface properties. 1324 1244 IF ( ALLOCATED( buildings_f%oro_max ) ) THEN 1325 1245 CALL exchange_horiz_2d( buildings_f%oro_max(:,:) ) … … 1331 1251 IF ( ALLOCATED( build_ids_final ) ) DEALLOCATE( build_ids_final ) 1332 1252 ! 1333 !-- Topography input via ASCII format. 1253 !-- Topography input via ASCII format. 1334 1254 ELSE 1335 1255 ocean_offset = MERGE( zw(0), 0.0_wp, ocean_mode ) 1336 1256 ! 1337 !-- Initialize topography bit 0 (indicates obstacle) everywhere to zero 1338 !-- and clear all grid points at nzb, where alway a surface is defined. 1339 !-- Further, set also bit 1 (indicates terrain) at nzb, which is further 1340 !-- used for masked data output and further processing. Note, in the 1341 !-- ASCII case no distinction is made between buildings and terrain, 1342 !-- so that setting of bit 1 and 2 at the same time has no effect. 1257 !-- Initialize topography bit 0 (indicates obstacle) everywhere to zero and clear all grid points 1258 !-- at nzb, where alway a surface is defined. 1259 !-- Further, set also bit 1 (indicates terrain) at nzb, which is further used for masked data 1260 !-- output and further processing. Note, in the ASCII case no distinction is made between 1261 !-- buildings and terrain, so that setting of bit 1 and 2 at the same time has no effect. 1343 1262 topo_3d = IBSET( topo_3d, 0 ) 1344 1263 topo_3d(nzb,:,:) = IBCLR( topo_3d(nzb,:,:), 0 ) … … 1348 1267 DO k = nzb, nzt 1349 1268 ! 1350 !-- Flag topography for all grid points which are below 1351 !-- the local topography height. 1352 !-- Note, each topography is flagged as building (bit 2) as well as 1353 !-- terrain (bit 1) in order to employ urban-surface as well as 1354 !-- land-surface model. 1269 !-- Flag topography for all grid points which are below the local topography height. 1270 !-- Note, each topography is flagged as building (bit 2) as well as terrain (bit 1) in 1271 !-- order to employ urban-surface as well as land-surface model. 1355 1272 IF ( zu(k) - ocean_offset <= buildings_f%var_2d(j,i) ) THEN 1356 1273 topo_3d(k,j,i) = IBCLR( topo_3d(k,j,i), 0 ) … … 1372 1289 IF ( .NOT. bc_lr_cyc ) THEN 1373 1290 IF ( nxl == 0 ) topo_3d(:,:,-1) = topo_3d(:,:,0) 1374 IF ( nxr == nx ) topo_3d(:,:,nx+1) = topo_3d(:,:,nx) 1291 IF ( nxr == nx ) topo_3d(:,:,nx+1) = topo_3d(:,:,nx) 1375 1292 ENDIF 1376 1293 … … 1379 1296 1380 1297 ! Description: 1381 ! ----------------------------------------------------------------------------- !1382 !> Filter topography, i.e. fill holes resolved by only one grid point. 1383 !> Such holes are suspected to lead to velocity blow-ups as continuity 1384 !> equation on discrete gridcannot be fulfilled in such case.1385 !------------------------------------------------------------------------------ !1298 ! -------------------------------------------------------------------------------------------------! 1299 !> Filter topography, i.e. fill holes resolved by only one grid point. 1300 !> Such holes are suspected to lead to velocity blow-ups as continuity equation on discrete grid 1301 !> cannot be fulfilled in such case. 1302 !--------------------------------------------------------------------------------------------------! 1386 1303 SUBROUTINE filter_topography( topo_3d ) 1387 1304 1388 USE control_parameters, &1305 USE control_parameters, & 1389 1306 ONLY: bc_lr_cyc, bc_ns_cyc, message_string 1390 1307 1391 USE exchange_horiz_mod, &1308 USE exchange_horiz_mod, & 1392 1309 ONLY: exchange_horiz_int, exchange_horiz_2d_byte, exchange_horiz_2d_int 1393 1310 1394 USE indices, &1311 USE indices, & 1395 1312 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nzb, nzt 1396 1313 1397 USE netcdf_data_input_mod, &1398 ONLY: building_id_f, building_type_f 1314 USE netcdf_data_input_mod, & 1315 ONLY: building_id_f, building_type_f 1399 1316 1400 1317 USE pegrid 1401 1318 1402 1319 IMPLICIT NONE 1403 1404 LOGICAL :: filled = .FALSE. !< flag indicating if holes were filled1405 1320 1406 1321 INTEGER(iwp) :: i !< running index along x-direction 1407 1322 INTEGER(iwp) :: j !< running index along y-direction 1408 1323 INTEGER(iwp) :: k !< running index along z-direction 1409 INTEGER(iwp) :: num_hole !< number of holes (in topography) resolved by only one grid point 1410 INTEGER(iwp) :: num_hole_l !< number of holes (in topography) resolved by only one grid point on local PE 1324 INTEGER(iwp) :: num_hole !< number of holes (in topography) resolved by only one grid point 1325 INTEGER(iwp) :: num_hole_l !< number of holes (in topography) resolved by only one grid point on local PE 1411 1326 INTEGER(iwp) :: num_wall !< number of surrounding vertical walls for a single grid point 1412 1327 1413 1328 INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE :: topo_tmp !< temporary 3D-topography used to fill holes 1414 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo_3d !< 3D-topography array merging buildings and orography 1415 ! 1416 !-- Before checking for holes, set lateral boundary conditions for 1329 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo_3d !< 3D-topography array merging buildings and 1330 !< orography 1331 1332 LOGICAL :: filled = .FALSE. !< flag indicating if holes were filled 1333 1334 ! 1335 !-- Before checking for holes, set lateral boundary conditions for 1417 1336 !-- topography. After hole-filling, boundary conditions must be set again. 1418 !-- Several iterations are performed, in order to fill holes which might 1337 !-- Several iterations are performed, in order to fill holes which might 1419 1338 !-- emerge by the filling-algorithm itself. 1420 1339 ALLOCATE( topo_tmp(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) … … 1422 1341 1423 1342 num_hole = 99999 1424 DO WHILE ( num_hole > 0 ) 1425 1426 num_hole = 0 1343 DO WHILE ( num_hole > 0 ) 1344 1345 num_hole = 0 1427 1346 CALL exchange_horiz_int( topo_3d, nys, nyn, nxl, nxr, nzt, nbgp ) 1428 1347 ! 1429 !-- Exchange also building ID and type. Note, building_type is an one-byte 1430 !-- variable. 1431 IF ( building_id_f%from_file ) & 1348 !-- Exchange also building ID and type. Note, building_type is an one-byte variable. 1349 IF ( building_id_f%from_file ) & 1432 1350 CALL exchange_horiz_2d_int( building_id_f%var, nys, nyn, nxl, nxr, nbgp ) 1433 IF ( building_type_f%from_file ) &1351 IF ( building_type_f%from_file ) & 1434 1352 CALL exchange_horiz_2d_byte( building_type_f%var, nys, nyn, nxl, nxr, nbgp ) 1435 1353 1436 1354 topo_tmp = topo_3d 1437 1355 ! 1438 !-- In case of non-cyclic lateral boundaries, assume lateral boundary to be 1439 !-- a solid wall. Thus, intermediate spaces of one grid point between1440 !-- boundary and some topographic structure will be filled.1356 !-- In case of non-cyclic lateral boundaries, assume lateral boundary to be a solid wall. Thus, 1357 !-- intermediate spaces of one grid point between boundary and some topographic structure will be 1358 !-- filled. 1441 1359 IF ( .NOT. bc_ns_cyc ) THEN 1442 1360 IF ( nys == 0 ) topo_tmp(:,-1,:) = IBCLR( topo_tmp(:,0,:), 0 ) … … 1446 1364 IF ( .NOT. bc_lr_cyc ) THEN 1447 1365 IF ( nxl == 0 ) topo_tmp(:,:,-1) = IBCLR( topo_tmp(:,:,0), 0 ) 1448 IF ( nxr == nx ) topo_tmp(:,:,nx+1) = IBCLR( topo_tmp(:,:,nx), 0 ) 1366 IF ( nxr == nx ) topo_tmp(:,:,nx+1) = IBCLR( topo_tmp(:,:,nx), 0 ) 1449 1367 ENDIF 1450 1368 … … 1455 1373 IF ( BTEST( topo_tmp(k,j,i), 0 ) ) THEN 1456 1374 num_wall = 0 1457 IF ( .NOT. BTEST( topo_tmp(k,j-1,i), 0 ) ) & 1458 num_wall = num_wall + 1 1459 IF ( .NOT. BTEST( topo_tmp(k,j+1,i), 0 ) ) & 1460 num_wall = num_wall + 1 1461 IF ( .NOT. BTEST( topo_tmp(k,j,i-1), 0 ) ) & 1462 num_wall = num_wall + 1 1463 IF ( .NOT. BTEST( topo_tmp(k,j,i+1), 0 ) ) & 1464 num_wall = num_wall + 1 1465 IF ( .NOT. BTEST( topo_tmp(k-1,j,i), 0 ) ) & 1466 num_wall = num_wall + 1 1467 IF ( .NOT. BTEST( topo_tmp(k+1,j,i), 0 ) ) & 1468 num_wall = num_wall + 1 1375 IF ( .NOT. BTEST( topo_tmp(k,j-1,i), 0 ) ) num_wall = num_wall + 1 1376 IF ( .NOT. BTEST( topo_tmp(k,j+1,i), 0 ) ) num_wall = num_wall + 1 1377 IF ( .NOT. BTEST( topo_tmp(k,j,i-1), 0 ) ) num_wall = num_wall + 1 1378 IF ( .NOT. BTEST( topo_tmp(k,j,i+1), 0 ) ) num_wall = num_wall + 1 1379 IF ( .NOT. BTEST( topo_tmp(k-1,j,i), 0 ) ) num_wall = num_wall + 1 1380 IF ( .NOT. BTEST( topo_tmp(k+1,j,i), 0 ) ) num_wall = num_wall + 1 1469 1381 1470 1382 IF ( num_wall >= 4 ) THEN 1471 1383 num_hole_l = num_hole_l + 1 1472 1384 ! 1473 !-- Clear flag 0 and set special flag ( bit 4) to indicate 1474 !-- that new topographypoint is a result of filtering process.1385 !-- Clear flag 0 and set special flag ( bit 4) to indicate that new topography 1386 !-- point is a result of filtering process. 1475 1387 topo_3d(k,j,i) = IBCLR( topo_3d(k,j,i), 0 ) 1476 1388 topo_3d(k,j,i) = IBSET( topo_3d(k,j,i), 4 ) 1477 1389 ! 1478 !-- If filled grid point is occupied by a building, classify 1479 !-- it as building gridpoint.1390 !-- If filled grid point is occupied by a building, classify it as building grid 1391 !-- point. 1480 1392 IF ( building_type_f%from_file ) THEN 1481 IF ( building_type_f%var(j,i) /= & 1482 building_type_f%fill .OR. & 1483 building_type_f%var(j+1,i) /= & 1484 building_type_f%fill .OR. & 1485 building_type_f%var(j-1,i) /= & 1486 building_type_f%fill .OR. & 1487 building_type_f%var(j,i+1) /= & 1488 building_type_f%fill .OR. & 1489 building_type_f%var(j,i-1) /= & 1490 building_type_f%fill ) THEN 1393 IF ( building_type_f%var(j,i) /= building_type_f%fill .OR. & 1394 building_type_f%var(j+1,i) /= building_type_f%fill .OR. & 1395 building_type_f%var(j-1,i) /= building_type_f%fill .OR. & 1396 building_type_f%var(j,i+1) /= building_type_f%fill .OR. & 1397 building_type_f%var(j,i-1) /= building_type_f%fill ) THEN 1491 1398 ! 1492 1399 !-- Set flag indicating building surfaces 1493 1400 topo_3d(k,j,i) = IBSET( topo_3d(k,j,i), 2 ) 1494 1401 ! 1495 !-- Set building_type and ID at this position if not 1496 !-- already set. This is required for proper 1497 !-- initialization of urban-surface energy balance 1402 !-- Set building_type and ID at this position if not already set. This is 1403 !-- required for proper initialization of urban-surface energy balance 1498 1404 !-- solver. 1499 IF ( building_type_f%var(j,i) == & 1500 building_type_f%fill ) THEN 1501 1502 IF ( building_type_f%var(j+1,i) /= & 1503 building_type_f%fill ) THEN 1504 building_type_f%var(j,i) = & 1505 building_type_f%var(j+1,i) 1506 building_id_f%var(j,i) = & 1507 building_id_f%var(j+1,i) 1508 ELSEIF ( building_type_f%var(j-1,i) /= & 1509 building_type_f%fill ) THEN 1510 building_type_f%var(j,i) = & 1511 building_type_f%var(j-1,i) 1512 building_id_f%var(j,i) = & 1513 building_id_f%var(j-1,i) 1514 ELSEIF ( building_type_f%var(j,i+1) /= & 1515 building_type_f%fill ) THEN 1516 building_type_f%var(j,i) = & 1517 building_type_f%var(j,i+1) 1518 building_id_f%var(j,i) = & 1519 building_id_f%var(j,i+1) 1520 ELSEIF ( building_type_f%var(j,i-1) /= & 1521 building_type_f%fill ) THEN 1522 building_type_f%var(j,i) = & 1523 building_type_f%var(j,i-1) 1524 building_id_f%var(j,i) = & 1525 building_id_f%var(j,i-1) 1405 IF ( building_type_f%var(j,i) == building_type_f%fill ) THEN 1406 1407 IF ( building_type_f%var(j+1,i) /= building_type_f%fill ) THEN 1408 building_type_f%var(j,i) = building_type_f%var(j+1,i) 1409 building_id_f%var(j,i) = building_id_f%var(j+1,i) 1410 ELSEIF ( building_type_f%var(j-1,i) /= building_type_f%fill ) THEN 1411 building_type_f%var(j,i) = building_type_f%var(j-1,i) 1412 building_id_f%var(j,i) = building_id_f%var(j-1,i) 1413 ELSEIF ( building_type_f%var(j,i+1) /= building_type_f%fill ) THEN 1414 building_type_f%var(j,i) = building_type_f%var(j,i+1) 1415 building_id_f%var(j,i) = building_id_f%var(j,i+1) 1416 ELSEIF ( building_type_f%var(j,i-1) /= building_type_f%fill ) THEN 1417 building_type_f%var(j,i) = building_type_f%var(j,i-1) 1418 building_id_f%var(j,i) = building_id_f%var(j,i-1) 1526 1419 ENDIF 1527 1420 ENDIF … … 1529 1422 ENDIF 1530 1423 ! 1531 !-- If filled grid point is already classified as building 1532 !-- everything is fine, else classify this grid point as 1533 !-- natural type grid point. This case, values for the 1534 !-- surface type are already set. 1424 !-- If filled grid point is already classified as building everything is fine, 1425 !-- else classify this grid point as natural type grid point. This case, values 1426 !-- for the surface type are already set. 1535 1427 IF ( .NOT. BTEST( topo_3d(k,j,i), 2 ) ) THEN 1536 1428 topo_3d(k,j,i) = IBSET( topo_3d(k,j,i), 1 ) … … 1544 1436 !-- Count the total number of holes, required for informative message. 1545 1437 #if defined( __parallel ) 1546 CALL MPI_ALLREDUCE( num_hole_l, num_hole, 1, MPI_INTEGER, MPI_SUM, & 1547 comm2d, ierr ) 1438 CALL MPI_ALLREDUCE( num_hole_l, num_hole, 1, MPI_INTEGER, MPI_SUM, comm2d, ierr ) 1548 1439 #else 1549 1440 num_hole = num_hole_l 1550 #endif 1441 #endif 1551 1442 IF ( num_hole > 0 .AND. .NOT. filled ) filled = .TRUE. 1552 1443 … … 1555 1446 !-- Create an informative message if any holes were filled. 1556 1447 IF ( filled ) THEN 1557 WRITE( message_string, * ) 'Topography was filtered, i.e. holes ' // &1558 'resolved by only one grid point ' // &1448 WRITE( message_string, * ) 'Topography was filtered, i.e. holes ' // & 1449 'resolved by only one grid point ' // & 1559 1450 'were filled during initialization.' 1560 1451 CALL message( 'init_grid', 'PA0430', 0, 0, 0, 6, 0 ) … … 1563 1454 DEALLOCATE( topo_tmp ) 1564 1455 ! 1565 !-- Finally, exchange topo_3d array again and if necessary set Neumann boundary 1566 !-- condition in case of non-cyclic lateral boundaries.1456 !-- Finally, exchange topo_3d array again and if necessary set Neumann boundary condition in case of 1457 !-- non-cyclic lateral boundaries. 1567 1458 CALL exchange_horiz_int( topo_3d, nys, nyn, nxl, nxr, nzt, nbgp ) 1568 1459 … … 1574 1465 IF ( .NOT. bc_lr_cyc ) THEN 1575 1466 IF ( nxl == 0 ) topo_3d(:,:,-1) = topo_3d(:,:,0) 1576 IF ( nxr == nx ) topo_3d(:,:,nx+1) = topo_3d(:,:,nx) 1467 IF ( nxr == nx ) topo_3d(:,:,nx+1) = topo_3d(:,:,nx) 1577 1468 ENDIF 1578 1469 ! 1579 1470 !-- Exchange building ID and type. Note, building_type is an one-byte variable. 1580 IF ( building_id_f%from_file ) &1471 IF ( building_id_f%from_file ) & 1581 1472 CALL exchange_horiz_2d_int( building_id_f%var, nys, nyn, nxl, nxr, nbgp ) 1582 IF ( building_type_f%from_file ) &1473 IF ( building_type_f%from_file ) & 1583 1474 CALL exchange_horiz_2d_byte( building_type_f%var, nys, nyn, nxl, nxr, nbgp ) 1584 1475 … … 1587 1478 1588 1479 ! Description: 1589 ! -----------------------------------------------------------------------------! 1590 !> Reads topography information from file or sets generic topography. Moreover, 1591 !> all topography-relevant topography arrays are initialized, and grid flags 1592 !> are set. 1593 !------------------------------------------------------------------------------! 1480 ! -------------------------------------------------------------------------------------------------! 1481 !> Reads topography information from file or sets generic topography. Moreover, all 1482 !> topography-relevant topography arrays are initialized, and grid flags are set. 1483 !--------------------------------------------------------------------------------------------------! 1594 1484 SUBROUTINE init_topo( topo ) 1595 1485 1596 USE arrays_3d, &1486 USE arrays_3d, & 1597 1487 ONLY: zw 1598 1599 USE control_parameters, & 1600 ONLY: bc_lr_cyc, bc_ns_cyc, building_height, building_length_x, & 1601 building_length_y, building_wall_left, building_wall_south, & 1602 canyon_height, canyon_wall_left, canyon_wall_south, & 1603 canyon_width_x, canyon_width_y, dp_level_ind_b, dz, & 1604 message_string, topography, topography_grid_convention, & 1605 tunnel_height, tunnel_length, tunnel_width_x, tunnel_width_y, & 1606 tunnel_wall_depth 1607 1608 USE exchange_horiz_mod, & 1488 1489 USE control_parameters, & 1490 ONLY: bc_lr_cyc, bc_ns_cyc, building_height, building_length_x, building_length_y, & 1491 building_wall_left, building_wall_south, canyon_height, canyon_wall_left, & 1492 canyon_wall_south, canyon_width_x, canyon_width_y, dp_level_ind_b, dz, & 1493 message_string, topography, topography_grid_convention, tunnel_height, & 1494 tunnel_length, tunnel_width_x, tunnel_width_y, tunnel_wall_depth 1495 1496 USE exchange_horiz_mod, & 1609 1497 ONLY: exchange_horiz_int 1610 1498 1611 USE grid_variables, &1499 USE grid_variables, & 1612 1500 ONLY: dx, dy 1613 1614 USE indices, & 1615 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nz, & 1616 nzb, nzt 1617 1501 1502 USE indices, & 1503 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nz, nzb, nzt 1504 1618 1505 USE kinds 1619 1620 USE netcdf_data_input_mod, &1621 ONLY: buildings_f, terrain_height_f 1506 1507 USE netcdf_data_input_mod, & 1508 ONLY: buildings_f, terrain_height_f 1622 1509 1623 1510 USE pegrid … … 1626 1513 1627 1514 INTEGER(iwp) :: bh !< temporary vertical index of building height 1515 INTEGER(iwp) :: ch !< temporary vertical index for canyon height 1516 INTEGER(iwp) :: hv_in !< heavyside function to model inner tunnel surface 1517 INTEGER(iwp) :: i !< index variable along x 1518 INTEGER(iwp) :: index_left_bwall !< index for left building wall 1519 INTEGER(iwp) :: index_north_bwall !< index for north building wall 1520 INTEGER(iwp) :: index_right_bwall !< index for right building wall 1521 INTEGER(iwp) :: index_south_bwall !< index for south building wall 1522 INTEGER(iwp) :: index_left_cwall !< index for left canyon wall 1523 INTEGER(iwp) :: index_north_cwall !< index for north canyon wall 1524 INTEGER(iwp) :: index_right_cwall !< index for right canyon wall 1525 INTEGER(iwp) :: index_south_cwall !< index for south canyon wall 1526 INTEGER(iwp) :: j !< index variable along y 1527 INTEGER(iwp) :: k !< index variable along z 1628 1528 INTEGER(iwp) :: ngp_bx !< grid point number of building size along x 1629 1529 INTEGER(iwp) :: ngp_by !< grid point number of building size along y 1630 INTEGER(iwp) :: index_left_bwall !< index for left building wall1631 INTEGER(iwp) :: index_right_bwall !< index for right building wall1632 INTEGER(iwp) :: index_north_bwall !< index for north building wall1633 INTEGER(iwp) :: index_south_bwall !< index for south building wall1634 INTEGER(iwp) :: ch !< temporary vertical index for canyon height1635 1530 INTEGER(iwp) :: ngp_cx !< grid point number of canyon size along x 1636 1531 INTEGER(iwp) :: ngp_cy !< grid point number of canyon size along y 1637 INTEGER(iwp) :: index_left_cwall !< index for left canyon wall 1638 INTEGER(iwp) :: index_right_cwall !< index for right canyon wall 1639 INTEGER(iwp) :: index_north_cwall !< index for north canyon wall 1640 INTEGER(iwp) :: index_south_cwall !< index for south canyon wall 1641 INTEGER(iwp) :: i !< index variable along x 1642 INTEGER(iwp) :: j !< index variable along y 1643 INTEGER(iwp) :: k !< index variable along z 1644 INTEGER(iwp) :: hv_in !< heavyside function to model inner tunnel surface 1645 INTEGER(iwp) :: hv_out !< heavyside function to model outer tunnel surface 1646 INTEGER(iwp) :: txe_out !< end position of outer tunnel wall in x 1647 INTEGER(iwp) :: txs_out !< start position of outer tunnel wall in x 1648 INTEGER(iwp) :: tye_out !< end position of outer tunnel wall in y 1649 INTEGER(iwp) :: tys_out !< start position of outer tunnel wall in y 1650 INTEGER(iwp) :: txe_in !< end position of inner tunnel wall in x 1651 INTEGER(iwp) :: txs_in !< start position of inner tunnel wall in x 1652 INTEGER(iwp) :: tye_in !< end position of inner tunnel wall in y 1653 INTEGER(iwp) :: tys_in !< start position of inner tunnel wall in y 1532 INTEGER(iwp) :: hv_out !< heavyside function to model outer tunnel surface 1654 1533 INTEGER(iwp) :: td !< tunnel wall depth 1655 1534 INTEGER(iwp) :: th !< height of outer tunnel wall 1535 INTEGER(iwp) :: txe_in !< end position of inner tunnel wall in x 1536 INTEGER(iwp) :: txe_out !< end position of outer tunnel wall in x 1537 INTEGER(iwp) :: txs_in !< start position of inner tunnel wall in x 1538 INTEGER(iwp) :: txs_out !< start position of outer tunnel wall in x 1539 INTEGER(iwp) :: tye_in !< end position of inner tunnel wall in y 1540 INTEGER(iwp) :: tye_out !< end position of outer tunnel wall in y 1541 INTEGER(iwp) :: tys_in !< start position of inner tunnel wall in y 1542 INTEGER(iwp) :: tys_out !< start position of outer tunnel wall in y 1656 1543 1657 1544 INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE :: nzb_local !< index for topography top at cell-center 1658 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo !< input array for 3D topography and dummy array for setting "outer"-flags1659 ! 1660 ! -- Check for correct setting of the namelist parameter topography. If1661 !-- topography information is read from file but topography = 'flat',1662 !-- initialization does not work properly.1663 IF ( ( buildings_f%from_file .OR. terrain_height_f%from_file ) .AND. &1545 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo !< input array for 3D topography and dummy array for setting 1546 !< "outer"-flags 1547 ! 1548 !-- Check for correct setting of the namelist parameter topography. If topography information is 1549 !-- read from file but topography = 'flat', initialization does not work properly. 1550 IF ( ( buildings_f%from_file .OR. terrain_height_f%from_file ) .AND. & 1664 1551 TRIM( topography ) /= 'read_from_file' ) THEN 1665 message_string = 'If topography information is provided (via ' // &1666 'Netcdf or ASCII input) topography = ' // &1552 message_string = 'If topography information is provided (via ' // & 1553 'Netcdf or ASCII input) topography = ' // & 1667 1554 '"read_from_file" is required.' 1668 CALL message( 'init_grid', 'PA0437', 1, 2, 0, 6, 0 ) 1555 CALL message( 'init_grid', 'PA0437', 1, 2, 0, 6, 0 ) 1669 1556 ENDIF 1670 1557 ! 1671 1558 !-- Set outer and inner index arrays for non-flat topography. 1672 !-- Here consistency checks concerning domain size and periodicity are 1673 !-- necessary. 1674 !-- Within this SELECT CASE structure only nzb_local is initialized 1675 !-- individually depending on the chosen topography type, all other index 1676 !-- arrays are initialized further below. 1559 !-- Here consistency checks concerning domain size and periodicity are necessary. 1560 !-- Within this SELECT CASE structure only nzb_local is initialized individually depending on the 1561 !-- chosen topography type, all other index arrays are initialized further below. 1677 1562 SELECT CASE ( TRIM( topography ) ) 1678 1563 1679 1564 CASE ( 'flat' ) 1680 ! 1565 ! 1681 1566 !-- Initialilize 3D topography array, used later for initializing flags 1682 1567 topo(nzb+1:nzt+1,:,:) = IBSET( topo(nzb+1:nzt+1,:,:), 0 ) 1683 1568 1684 1569 CASE ( 'closed_channel' ) 1685 ! 1570 ! 1686 1571 !-- Initialilize 3D topography array, used later for initializing flags 1687 topo(nzb+1:nzt,:,:) = IBSET( topo(nzb+1:nzt,:,:), 0 ) 1572 topo(nzb+1:nzt,:,:) = IBSET( topo(nzb+1:nzt,:,:), 0 ) 1688 1573 1689 1574 CASE ( 'single_building' ) … … 1694 1579 ngp_by = NINT( building_length_y / dy ) 1695 1580 bh = MINLOC( ABS( zw - building_height ), 1 ) - 1 1696 IF ( ABS( zw(bh) - building_height ) == & 1697 ABS( zw(bh+1) - building_height ) ) bh = bh + 1 1581 IF ( ABS( zw(bh) - building_height ) == ABS( zw(bh+1) - building_height ) ) bh = bh + 1 1698 1582 IF ( building_wall_left == 9999999.9_wp ) THEN 1699 1583 building_wall_left = ( nx + 1 - ngp_bx ) / 2 * dx … … 1710 1594 ! 1711 1595 !-- Building size has to meet some requirements 1712 IF ( ( index_left_bwall < 1 ) .OR. ( index_right_bwall > nx-1 ) .OR.&1713 ( index_right_bwall < index_left_bwall+3 ) .OR.&1714 ( index_south_bwall < 1 ) .OR. ( index_north_bwall > ny-1 ) .OR.&1596 IF ( ( index_left_bwall < 1 ) .OR. ( index_right_bwall > nx-1 ) .OR. & 1597 ( index_right_bwall < index_left_bwall+3 ) .OR. & 1598 ( index_south_bwall < 1 ) .OR. ( index_north_bwall > ny-1 ) .OR. & 1715 1599 ( index_north_bwall < index_south_bwall+3 ) ) THEN 1716 WRITE( message_string, * ) 'inconsistent building parameters:', &1717 '&index_left_bwall=', index_left_bwall, &1718 'index_right_bwall=', index_right_bwall, &1719 'index_south_bwall=', index_south_bwall, &1720 'index_north_bwall=', index_north_bwall, &1600 WRITE( message_string, * ) 'inconsistent building parameters:', & 1601 '&index_left_bwall=', index_left_bwall, & 1602 'index_right_bwall=', index_right_bwall, & 1603 'index_south_bwall=', index_south_bwall, & 1604 'index_north_bwall=', index_north_bwall, & 1721 1605 'nx=', nx, 'ny=', ny 1722 1606 CALL message( 'init_grid', 'PA0203', 1, 2, 0, 6, 0 ) … … 1726 1610 nzb_local = 0 1727 1611 ! 1728 !-- Define the building. 1729 IF ( index_left_bwall <= nxr .AND. index_right_bwall >= nxl .AND. &1730 index_south_bwall <= nyn .AND. index_north_bwall >= nys ) &1731 nzb_local(MAX(nys,index_south_bwall):MIN(nyn,index_north_bwall), &1612 !-- Define the building. 1613 IF ( index_left_bwall <= nxr .AND. index_right_bwall >= nxl .AND. & 1614 index_south_bwall <= nyn .AND. index_north_bwall >= nys ) & 1615 nzb_local(MAX(nys,index_south_bwall):MIN(nyn,index_north_bwall), & 1732 1616 MAX(nxl,index_left_bwall):MIN(nxr,index_right_bwall)) = bh 1733 1617 ! … … 1735 1619 DO i = nxl, nxr 1736 1620 DO j = nys, nyn 1737 topo(nzb_local(j,i)+1:nzt+1,j,i) = & 1738 IBSET( topo(nzb_local(j,i)+1:nzt+1,j,i), 0 ) 1621 topo(nzb_local(j,i)+1:nzt+1,j,i) = IBSET( topo(nzb_local(j,i)+1:nzt+1,j,i), 0 ) 1739 1622 ENDDO 1740 1623 ENDDO 1741 1624 1742 1625 DEALLOCATE( nzb_local ) 1743 1626 1744 1627 CALL exchange_horiz_int( topo, nys, nyn, nxl, nxr, nzt, nbgp ) 1745 1628 ! 1746 !-- Set boundary conditions also for flags. Can be interpreted as Neumann 1747 !-- boundary conditions for topography.1629 !-- Set boundary conditions also for flags. Can be interpreted as Neumannb oundary conditions 1630 !-- for topography. 1748 1631 IF ( .NOT. bc_ns_cyc ) THEN 1749 1632 IF ( nys == 0 ) THEN 1750 DO i = 1, nbgp 1633 DO i = 1, nbgp 1751 1634 topo(:,nys-i,:) = topo(:,nys,:) 1752 1635 ENDDO 1753 1636 ENDIF 1754 1637 IF ( nyn == ny ) THEN 1755 DO i = 1, nbgp 1638 DO i = 1, nbgp 1756 1639 topo(:,nyn+i,:) = topo(:,nyn,:) 1757 1640 ENDDO … … 1760 1643 IF ( .NOT. bc_lr_cyc ) THEN 1761 1644 IF ( nxl == 0 ) THEN 1762 DO i = 1, nbgp 1645 DO i = 1, nbgp 1763 1646 topo(:,:,nxl-i) = topo(:,:,nxl) 1764 1647 ENDDO 1765 1648 ENDIF 1766 IF ( nxr == nx ) THEN 1767 DO i = 1, nbgp 1768 topo(:,:,nxr+i) = topo(:,:,nxr) 1649 IF ( nxr == nx ) THEN 1650 DO i = 1, nbgp 1651 topo(:,:,nxr+i) = topo(:,:,nxr) 1769 1652 ENDDO 1770 ENDIF 1653 ENDIF 1771 1654 ENDIF 1772 1655 … … 1793 1676 index_south_cwall = NINT( canyon_wall_south / dy ) 1794 1677 index_north_cwall = index_south_cwall + ngp_cy 1795 1678 1796 1679 ELSE 1797 1680 1798 1681 message_string = 'no street canyon width given' 1799 1682 CALL message( 'init_grid', 'PA0204', 1, 2, 0, 6, 0 ) 1800 1683 1801 1684 ENDIF 1802 1685 1803 1686 ch = MINLOC( ABS( zw - canyon_height ), 1 ) - 1 1804 IF ( ABS( zw(ch) - canyon_height ) == & 1805 ABS( zw(ch+1) - canyon_height ) ) ch = ch + 1 1687 IF ( ABS( zw(ch) - canyon_height ) == ABS( zw(ch+1) - canyon_height ) ) ch = ch + 1 1806 1688 dp_level_ind_b = ch 1807 1689 ! 1808 1690 !-- Street canyon size has to meet some requirements 1809 1691 IF ( canyon_width_x /= 9999999.9_wp ) THEN 1810 IF ( ( index_left_cwall< 1 ) .OR. ( index_right_cwall> nx-1 ) .OR.&1692 IF ( ( index_left_cwall< 1 ) .OR. ( index_right_cwall> nx-1 ) .OR. & 1811 1693 ( ngp_cx < 3 ) ) THEN 1812 WRITE( message_string, * ) 'inconsistent canyon parameters:', & 1813 '&index_left_cwall=', index_left_cwall, & 1814 ' index_right_cwall=', index_right_cwall, & 1815 ' ngp_cx=', ngp_cx, & 1816 ' ch=', ch, ' nx=', nx, ' ny=', ny 1817 CALL message( 'init_grid', 'PA0205', 1, 2, 0, 6, 0 ) 1694 WRITE( message_string, * ) 'inconsistent canyon parameters:', & 1695 '&index_left_cwall=', index_left_cwall, & 1696 ' index_right_cwall=', index_right_cwall, & 1697 ' ngp_cx=', ngp_cx, ' ch=', ch, ' nx=', nx, ' ny=', ny 1698 CALL message( 'init_grid', 'PA0205', 1, 2, 0, 6, 0 ) 1818 1699 ENDIF 1819 1700 ELSEIF ( canyon_width_y /= 9999999.9_wp ) THEN 1820 IF ( ( index_south_cwall < 1 ) .OR. & 1821 ( index_north_cwall > ny-1 ) .OR. ( ngp_cy < 3 ) ) THEN 1822 WRITE( message_string, * ) 'inconsistent canyon parameters:', & 1823 '&index_south_cwall=', index_south_cwall, & 1824 ' index_north_cwall=', index_north_cwall, & 1825 ' ngp_cy=', ngp_cy, & 1826 ' ch=', ch, ' nx=', nx, ' ny=', ny 1827 CALL message( 'init_grid', 'PA0206', 1, 2, 0, 6, 0 ) 1828 ENDIF 1829 ENDIF 1830 IF ( canyon_width_x /= 9999999.9_wp .AND. & 1831 canyon_width_y /= 9999999.9_wp ) THEN 1832 message_string = 'inconsistent canyon parameters:' // & 1833 '&street canyon can only be oriented' // & 1701 IF ( ( index_south_cwall < 1 ) .OR. & 1702 ( index_north_cwall > ny-1 ) .OR. ( ngp_cy < 3 ) ) THEN 1703 WRITE( message_string, * ) 'inconsistent canyon parameters:', & 1704 '&index_south_cwall=', index_south_cwall, & 1705 ' index_north_cwall=', index_north_cwall, & 1706 ' ngp_cy=', ngp_cy, ' ch=', ch, ' nx=', nx, ' ny=', ny 1707 CALL message( 'init_grid', 'PA0206', 1, 2, 0, 6, 0 ) 1708 ENDIF 1709 ENDIF 1710 IF ( canyon_width_x /= 9999999.9_wp .AND. canyon_width_y /= 9999999.9_wp ) THEN 1711 message_string = 'inconsistent canyon parameters:' // & 1712 '&street canyon can only be oriented' // & 1834 1713 ' either in x- or in y-direction' 1835 1714 CALL message( 'init_grid', 'PA0207', 1, 2, 0, 6, 0 ) … … 1839 1718 nzb_local = ch 1840 1719 IF ( canyon_width_x /= 9999999.9_wp ) THEN 1841 IF ( index_left_cwall<= nxr .AND. index_right_cwall>= nxl ) &1720 IF ( index_left_cwall<= nxr .AND. index_right_cwall>= nxl ) & 1842 1721 nzb_local(:,MAX(nxl,index_left_cwall+1):MIN(nxr,index_right_cwall-1)) = 0 1843 1722 ELSEIF ( canyon_width_y /= 9999999.9_wp ) THEN 1844 IF ( index_south_cwall <= nyn .AND. index_north_cwall >= nys ) &1723 IF ( index_south_cwall <= nyn .AND. index_north_cwall >= nys ) & 1845 1724 nzb_local(MAX(nys,index_south_cwall+1):MIN(nyn,index_north_cwall-1),:) = 0 1846 1725 ENDIF … … 1849 1728 DO i = nxl, nxr 1850 1729 DO j = nys, nyn 1851 topo(nzb_local(j,i)+1:nzt+1,j,i) = & 1852 IBSET( topo(nzb_local(j,i)+1:nzt+1,j,i), 0 ) 1730 topo(nzb_local(j,i)+1:nzt+1,j,i) = IBSET( topo(nzb_local(j,i)+1:nzt+1,j,i), 0 ) 1853 1731 ENDDO 1854 1732 ENDDO … … 1857 1735 CALL exchange_horiz_int( topo, nys, nyn, nxl, nxr, nzt, nbgp ) 1858 1736 ! 1859 !-- Set boundary conditions also for flags. Can be interpreted as Neumann 1860 !-- boundary conditions for topography.1737 !-- Set boundary conditions also for flags. Can be interpreted as Neumann boundary conditions 1738 !-- for topography. 1861 1739 IF ( .NOT. bc_ns_cyc ) THEN 1862 1740 IF ( nys == 0 ) THEN 1863 DO i = 1, nbgp 1864 topo(:,nys-i,:) 1741 DO i = 1, nbgp 1742 topo(:,nys-i,:) = topo(:,nys,:) 1865 1743 ENDDO 1866 1744 ENDIF 1867 1745 IF ( nyn == ny ) THEN 1868 DO i = 1, nbgp 1746 DO i = 1, nbgp 1869 1747 topo(:,nyn+i,:) = topo(:,nyn,:) 1870 1748 ENDDO … … 1873 1751 IF ( .NOT. bc_lr_cyc ) THEN 1874 1752 IF ( nxl == 0 ) THEN 1875 DO i = 1, nbgp 1876 topo(:,:,nxl-i) 1753 DO i = 1, nbgp 1754 topo(:,:,nxl-i) = topo(:,:,nxl) 1877 1755 ENDDO 1878 1756 ENDIF 1879 IF ( nxr == nx ) THEN 1880 DO i = 1, nbgp 1881 topo(:,:,nxr+i) = topo(:,:,nxr) 1757 IF ( nxr == nx ) THEN 1758 DO i = 1, nbgp 1759 topo(:,:,nxr+i) = topo(:,:,nxr) 1882 1760 ENDDO 1883 ENDIF 1761 ENDIF 1884 1762 ENDIF 1885 1763 … … 1895 1773 ! 1896 1774 !-- Tunnel-wall depth 1897 IF ( tunnel_wall_depth == 9999999.9_wp ) THEN 1775 IF ( tunnel_wall_depth == 9999999.9_wp ) THEN 1898 1776 td = MAX ( dx, dy, dz(1) ) 1899 1777 ELSE … … 1902 1780 ! 1903 1781 !-- Check for tunnel width 1904 IF ( tunnel_width_x == 9999999.9_wp .AND. & 1905 tunnel_width_y == 9999999.9_wp ) THEN 1782 IF ( tunnel_width_x == 9999999.9_wp .AND. tunnel_width_y == 9999999.9_wp ) THEN 1906 1783 message_string = 'No tunnel width is given. ' 1907 1784 CALL message( 'init_grid', 'PA0280', 1, 2, 0, 6, 0 ) 1908 1785 ENDIF 1909 IF ( tunnel_width_x /= 9999999.9_wp .AND. & 1910 tunnel_width_y /= 9999999.9_wp ) THEN 1911 message_string = 'Inconsistent tunnel parameters:' // & 1912 'tunnel can only be oriented' // & 1786 IF ( tunnel_width_x /= 9999999.9_wp .AND. tunnel_width_y /= 9999999.9_wp ) THEN 1787 message_string = 'Inconsistent tunnel parameters:' // & 1788 'tunnel can only be oriented' // & 1913 1789 'either in x- or in y-direction.' 1914 1790 CALL message( 'init_grid', 'PA0281', 1, 2, 0, 6, 0 ) … … 1916 1792 ! 1917 1793 !-- Check for too small tunnel width in x- and y-direction 1918 IF ( tunnel_width_x /= 9999999.9_wp .AND. &1794 IF ( tunnel_width_x /= 9999999.9_wp .AND. & 1919 1795 tunnel_width_x - 2.0_wp * td <= 2.0_wp * dx ) THEN 1920 1796 message_string = 'tunnel_width_x too small' 1921 1797 CALL message( 'init_grid', 'PA0175', 1, 2, 0, 6, 0 ) 1922 1798 ENDIF 1923 IF ( tunnel_width_y /= 9999999.9_wp .AND. &1799 IF ( tunnel_width_y /= 9999999.9_wp .AND. & 1924 1800 tunnel_width_y - 2.0_wp * td <= 2.0_wp * dy ) THEN 1925 1801 message_string = 'tunnel_width_y too small' … … 1927 1803 ENDIF 1928 1804 ! 1929 !-- Check for too large tunnel width. 1805 !-- Check for too large tunnel width. 1930 1806 !-- Tunnel axis along y. 1931 1807 IF ( tunnel_width_x /= 9999999.9_wp ) THEN … … 1937 1813 txs_out = INT( ( nx + 1 ) * 0.5_wp * dx - tunnel_width_x * 0.5_wp ) 1938 1814 txe_out = INT( ( nx + 1 ) * 0.5_wp * dx + tunnel_width_x * 0.5_wp ) 1939 txs_in = INT( ( nx + 1 ) * 0.5_wp * dx - & 1940 ( tunnel_width_x * 0.5_wp - td ) ) 1941 txe_in = INT( ( nx + 1 ) * 0.5_wp * dx + & 1942 ( tunnel_width_x * 0.5_wp - td ) ) 1815 txs_in = INT( ( nx + 1 ) * 0.5_wp * dx - ( tunnel_width_x * 0.5_wp - td ) ) 1816 txe_in = INT( ( nx + 1 ) * 0.5_wp * dx + ( tunnel_width_x * 0.5_wp - td ) ) 1943 1817 1944 1818 tys_out = INT( ( ny + 1 ) * 0.5_wp * dy - tunnel_length * 0.5_wp ) … … 1962 1836 tys_out = INT( ( ny + 1 ) * 0.5_wp * dy - tunnel_width_y * 0.5_wp ) 1963 1837 tye_out = INT( ( ny + 1 ) * 0.5_wp * dy + tunnel_width_y * 0.5_wp ) 1964 tys_in = INT( ( ny + 1 ) * 0.5_wp * dy - & 1965 ( tunnel_width_y * 0.5_wp - td ) ) 1966 tye_in = INT( ( ny + 1 ) * 0.5_wp * dy + & 1967 ( tunnel_width_y * 0.5_wp - td ) ) 1838 tys_in = INT( ( ny + 1 ) * 0.5_wp * dy - ( tunnel_width_y * 0.5_wp - td ) ) 1839 tye_in = INT( ( ny + 1 ) * 0.5_wp * dy + ( tunnel_width_y * 0.5_wp - td ) ) 1968 1840 ENDIF 1969 1841 … … 1973 1845 ! 1974 1846 !-- Use heaviside function to model outer tunnel surface 1975 hv_out = th * 0.5_wp * & 1976 ( ( SIGN( 1.0_wp, i * dx - txs_out ) + 1.0_wp ) & 1977 - ( SIGN( 1.0_wp, i * dx - txe_out ) + 1.0_wp ) ) 1978 1979 hv_out = hv_out * 0.5_wp * & 1980 ( ( SIGN( 1.0_wp, j * dy - tys_out ) + 1.0_wp ) & 1981 - ( SIGN( 1.0_wp, j * dy - tye_out ) + 1.0_wp ) ) 1982 ! 1847 hv_out = th * 0.5_wp * ( ( SIGN( 1.0_wp, i * dx - txs_out ) + 1.0_wp ) & 1848 - ( SIGN( 1.0_wp, i * dx - txe_out ) + 1.0_wp ) ) 1849 1850 hv_out = hv_out * 0.5_wp * ( ( SIGN( 1.0_wp, j * dy - tys_out ) + 1.0_wp ) & 1851 - ( SIGN( 1.0_wp, j * dy - tye_out ) + 1.0_wp ) ) 1852 ! 1983 1853 !-- Use heaviside function to model inner tunnel surface 1984 hv_in = ( th - td ) * 0.5_wp * & 1985 ( ( SIGN( 1.0_wp, i * dx - txs_in ) + 1.0_wp ) & 1986 - ( SIGN( 1.0_wp, i * dx - txe_in ) + 1.0_wp ) ) 1987 1988 hv_in = hv_in * 0.5_wp * & 1989 ( ( SIGN( 1.0_wp, j * dy - tys_in ) + 1.0_wp ) & 1990 - ( SIGN( 1.0_wp, j * dy - tye_in ) + 1.0_wp ) ) 1854 hv_in = ( th - td ) * 0.5_wp * ( ( SIGN( 1.0_wp, i * dx - txs_in ) + 1.0_wp ) & 1855 - ( SIGN( 1.0_wp, i * dx - txe_in ) + 1.0_wp ) ) 1856 1857 hv_in = hv_in * 0.5_wp * ( ( SIGN( 1.0_wp, j * dy - tys_in ) + 1.0_wp ) & 1858 - ( SIGN( 1.0_wp, j * dy - tye_in ) + 1.0_wp ) ) 1991 1859 ! 1992 1860 !-- Set flags at x-y-positions without any tunnel surface … … 2009 1877 !-- Lateral tunnel walls 2010 1878 IF ( hv_out - hv_in == td ) THEN 2011 IF ( zw(k) <= hv_in ) THEN 1879 IF ( zw(k) <= hv_in ) THEN 2012 1880 topo(k,j,i) = IBSET( topo(k,j,i), 0 ) 2013 ELSEIF ( zw(k) > hv_in .AND. zw(k) <= hv_out ) THEN 1881 ELSEIF ( zw(k) > hv_in .AND. zw(k) <= hv_out ) THEN 2014 1882 topo(k,j,i) = IBCLR( topo(k,j,i), 0 ) 2015 ELSEIF ( zw(k) > hv_out ) THEN 1883 ELSEIF ( zw(k) > hv_out ) THEN 2016 1884 topo(k,j,i) = IBSET( topo(k,j,i), 0 ) 2017 1885 ENDIF … … 2024 1892 CALL exchange_horiz_int( topo, nys, nyn, nxl, nxr, nzt, nbgp ) 2025 1893 ! 2026 !-- Set boundary conditions also for flags. Can be interpreted as Neumann 2027 !-- boundary conditions for topography.1894 !-- Set boundary conditions also for flags. Can be interpreted as Neumann boundary conditions 1895 !-- for topography. 2028 1896 IF ( .NOT. bc_ns_cyc ) THEN 2029 1897 IF ( nys == 0 ) THEN 2030 DO i = 1, nbgp 2031 topo(:,nys-i,:) 1898 DO i = 1, nbgp 1899 topo(:,nys-i,:) = topo(:,nys,:) 2032 1900 ENDDO 2033 1901 ENDIF 2034 1902 IF ( nyn == ny ) THEN 2035 DO i = 1, nbgp 1903 DO i = 1, nbgp 2036 1904 topo(:,nyn+i,:) = topo(:,nyn,:) 2037 1905 ENDDO … … 2040 1908 IF ( .NOT. bc_lr_cyc ) THEN 2041 1909 IF ( nxl == 0 ) THEN 2042 DO i = 1, nbgp 2043 topo(:,:,nxl-i) 1910 DO i = 1, nbgp 1911 topo(:,:,nxl-i) = topo(:,:,nxl) 2044 1912 ENDDO 2045 1913 ENDIF 2046 IF ( nxr == nx ) THEN 2047 DO i = 1, nbgp 2048 topo(:,:,nxr+i) = topo(:,:,nxr) 1914 IF ( nxr == nx ) THEN 1915 DO i = 1, nbgp 1916 topo(:,:,nxr+i) = topo(:,:,nxr) 2049 1917 ENDDO 2050 ENDIF 1918 ENDIF 2051 1919 ENDIF 2052 1920 2053 1921 CASE ( 'read_from_file' ) 2054 1922 ! 2055 !-- Note, topography information have been already read. 2056 !-- If required, further process topography, i.e. reference buildings on 2057 !-- top of orography and set temporary 3D topography array, which is 2058 !-- used later to set grid flags. Calling of this rouinte is also 2059 !-- required in case of ASCII input, even though no distinction between 2060 !-- terrain- and building height is made in this case. 1923 !-- Note, topography information have been already read. 1924 !-- If required, further process topography, i.e. reference buildings on top of orography and 1925 !-- set temporary 3D topography array, which is used later to set grid flags. Calling of this 1926 !-- rouinte is also required in case of ASCII input, even though no distinction between 1927 !-- terrain- and building height is made in this case. 2061 1928 CALL process_topography( topo ) 2062 1929 ! … … 2064 1931 CALL filter_topography( topo ) 2065 1932 ! 2066 !-- Exchange ghost-points, as well as add cyclic or Neumann boundary 2067 !-- conditions. 1933 !-- Exchange ghost-points, as well as add cyclic or Neumann boundary conditions. 2068 1934 CALL exchange_horiz_int( topo, nys, nyn, nxl, nxr, nzt, nbgp ) 2069 1935 ! … … 2071 1937 IF ( .NOT. bc_ns_cyc ) THEN 2072 1938 IF ( nys == 0 ) THEN 2073 DO i = 1, nbgp 1939 DO i = 1, nbgp 2074 1940 topo(:,nys-i,:) = topo(:,nys,:) 2075 1941 ENDDO 2076 1942 ENDIF 2077 1943 IF ( nyn == ny ) THEN 2078 DO i = 1, nbgp 1944 DO i = 1, nbgp 2079 1945 topo(:,nyn+i,:) = topo(:,nyn,:) 2080 1946 ENDDO … … 2084 1950 IF ( .NOT. bc_lr_cyc ) THEN 2085 1951 IF ( nxl == 0 ) THEN 2086 DO i = 1, nbgp 1952 DO i = 1, nbgp 2087 1953 topo(:,:,nxl-i) = topo(:,:,nxl) 2088 1954 ENDDO 2089 1955 ENDIF 2090 1956 IF ( nxr == nx ) THEN 2091 DO i = 1, nbgp 1957 DO i = 1, nbgp 2092 1958 topo(:,:,nxr+i) = topo(:,:,nxr) 2093 1959 ENDDO … … 2097 1963 2098 1964 CASE DEFAULT 2099 ! 2100 !-- The DEFAULT case is reached either if the parameter topography 2101 !-- contains a wrong character string or if the user has defined a special 2102 !-- case in the user interface. There, the subroutine user_init_grid 2103 !-- checks which of these two conditions applies. 1965 ! 1966 !-- The DEFAULT case is reached either if the parameter topography contains a wrong character 1967 !-- string or if the user has defined a special case in the user interface. There, the 1968 !-- subroutine user_init_grid checks which of these two conditions applies. 2104 1969 CALL user_init_grid( topo ) 2105 1970 CALL filter_topography( topo ) … … 2107 1972 END SELECT 2108 1973 ! 2109 !-- Consistency checks and index array initialization are only required for 2110 !-- non-flat topography. 1974 !-- Consistency checks and index array initialization are only required for non-flat topography. 2111 1975 IF ( TRIM( topography ) /= 'flat' ) THEN 2112 1976 ! 2113 !-- In case of non-flat topography, check whether the convention how to 2114 !-- define the topography grid has been set correctly, or whether the default2115 !-- is applicable. If this is not possible,abort.1977 !-- In case of non-flat topography, check whether the convention how to define the topography 1978 !-- grid has been set correctly, or whether the default is applicable. If this is not possible, 1979 !-- abort. 2116 1980 IF ( TRIM( topography_grid_convention ) == ' ' ) THEN 2117 IF ( TRIM( topography ) /= 'closed_channel' .AND.&2118 TRIM( topography ) /= 'single_building' .AND.&2119 TRIM( topography ) /= 'single_street_canyon' .AND.&2120 TRIM( topography ) /= 'tunnel' .AND.&1981 IF ( TRIM( topography ) /= 'closed_channel' .AND. & 1982 TRIM( topography ) /= 'single_building' .AND. & 1983 TRIM( topography ) /= 'single_street_canyon' .AND. & 1984 TRIM( topography ) /= 'tunnel' .AND. & 2121 1985 TRIM( topography ) /= 'read_from_file') THEN 2122 !-- The default value is not applicable here, because it is only valid 2123 !-- for the four standard cases 'single_building', 2124 !-- 'single_street_canyon', 'tunnel' and 'read_from_file' 1986 !-- The default value is not applicable here, because it is only valid for the four 1987 !-- standard cases 'single_building', 'single_street_canyon', 'tunnel' and 'read_from_file' 2125 1988 !-- defined in init_grid. 2126 WRITE( message_string, * ) & 2127 'The value for "topography_grid_convention" ', & 2128 'is not set. Its default value is & only valid for ', & 2129 '"topography" = ''single_building'', ''tunnel'' ', & 2130 '''single_street_canyon'', ''closed_channel'' & or ', & 2131 '''read_from_file''.', & 2132 '& Choose ''cell_edge'' or ''cell_center''.' 1989 WRITE( message_string, * ) 'The value for "topography_grid_convention" ', & 1990 'is not set. Its default value is & only valid for ', & 1991 '"topography" = ''single_building'', ''tunnel'' ', & 1992 '''single_street_canyon'', ''closed_channel'' & or ', & 1993 '''read_from_file''.', & 1994 '& Choose ''cell_edge'' or ''cell_center''.' 2133 1995 CALL message( 'init_grid', 'PA0239', 1, 2, 0, 6, 0 ) 2134 1996 ELSE 2135 1997 !-- The default value is applicable here. 2136 1998 !-- Set convention according to topography. 2137 IF ( TRIM( topography ) == 'single_building' .OR.&1999 IF ( TRIM( topography ) == 'single_building' .OR. & 2138 2000 TRIM( topography ) == 'single_street_canyon' ) THEN 2139 2001 topography_grid_convention = 'cell_edge' 2140 ELSEIF ( TRIM( topography ) == 'read_from_file' .OR. &2002 ELSEIF ( TRIM( topography ) == 'read_from_file' .OR. & 2141 2003 TRIM( topography ) == 'tunnel') THEN 2142 2004 topography_grid_convention = 'cell_center' 2143 2005 ENDIF 2144 2006 ENDIF 2145 ELSEIF ( TRIM( topography_grid_convention ) /= 'cell_edge' .AND.&2007 ELSEIF ( TRIM( topography_grid_convention ) /= 'cell_edge' .AND. & 2146 2008 TRIM( topography_grid_convention ) /= 'cell_center' ) THEN 2147 WRITE( message_string, * ) & 2148 'The value for "topography_grid_convention" is ', & 2149 'not recognized.& Choose ''cell_edge'' or ''cell_center''.' 2009 WRITE( message_string, * ) 'The value for "topography_grid_convention" is ', & 2010 'not recognized.& Choose ''cell_edge'' or ''cell_center''.' 2150 2011 CALL message( 'init_grid', 'PA0240', 1, 2, 0, 6, 0 ) 2151 2012 ENDIF … … 2153 2014 2154 2015 IF ( topography_grid_convention == 'cell_edge' ) THEN 2155 ! 2156 !-- The array nzb_local as defined using the 'cell_edge' convention 2157 !-- describes the actual total size of topography which is defined at the 2158 !-- cell edges where u=0 on the topography walls in x-direction and v=0 2016 ! 2017 !-- The array nzb_local as defined using the 'cell_edge' convention 2018 !-- describes the actual total size of topography which is defined at the 2019 !-- cell edges where u=0 on the topography walls in x-direction and v=0 2159 2020 !-- on the topography walls in y-direction. However, PALM uses individual 2160 2021 !-- arrays nzb_u|v|w|s_inner|outer that are based on nzb_s_inner. 2161 !-- Therefore, the extent of topography in nzb_local is now reduced by 2162 !-- 1dx at the E topography walls and by 1dy at the N topography walls 2163 !-- to form the basis for nzb_s_inner. 2022 !-- Therefore, the extent of topography in nzb_local is now reduced by 2023 !-- 1dx at the E topography walls and by 1dy at the N topography walls 2024 !-- to form the basis for nzb_s_inner. 2164 2025 !-- Note, the reverse memory access (i-j instead of j-i) is absolutely 2165 2026 !-- required at this point. … … 2167 2028 DO i = nxl-1, nxr 2168 2029 DO k = nzb, nzt+1 2169 IF ( BTEST( topo(k,j,i), 0 ) .OR. & 2170 BTEST( topo(k,j,i+1), 0 ) ) & 2030 IF ( BTEST( topo(k,j,i), 0 ) .OR. BTEST( topo(k,j,i+1), 0 ) ) & 2171 2031 topo(k,j,i) = IBSET( topo(k,j,i), 0 ) 2172 2032 ENDDO 2173 2033 ENDDO 2174 ENDDO 2034 ENDDO 2175 2035 CALL exchange_horiz_int( topo, nys, nyn, nxl, nxr, nzt, nbgp ) 2176 2036 … … 2178 2038 DO j = nys-1, nyn 2179 2039 DO k = nzb, nzt+1 2180 IF ( BTEST( topo(k,j,i), 0 ) .OR. & 2181 BTEST( topo(k,j+1,i), 0 ) ) & 2040 IF ( BTEST( topo(k,j,i), 0 ) .OR. BTEST( topo(k,j+1,i), 0 ) ) & 2182 2041 topo(k,j,i) = IBSET( topo(k,j,i), 0 ) 2183 2042 ENDDO 2184 2043 ENDDO 2185 ENDDO 2044 ENDDO 2186 2045 CALL exchange_horiz_int( topo, nys, nyn, nxl, nxr, nzt, nbgp ) 2187 2046 2188 2047 ENDIF 2189 2048 ENDIF … … 2194 2053 SUBROUTINE set_topo_flags(topo) 2195 2054 2196 USE control_parameters, &2197 ONLY: bc_lr_cyc, bc_ns_cyc, constant_flux_layer, 2198 scalar_advec, topography,use_surface_fluxes, use_top_fluxes2199 2200 USE exchange_horiz_mod, &2055 USE control_parameters, & 2056 ONLY: bc_lr_cyc, bc_ns_cyc, constant_flux_layer, scalar_advec, topography, & 2057 use_surface_fluxes, use_top_fluxes 2058 2059 USE exchange_horiz_mod, & 2201 2060 ONLY: exchange_horiz_int 2202 2061 2203 USE indices, &2204 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nzb, &2205 nzt, topo_top_ind,wall_flags_static_0, wall_flags_total_02062 USE indices, & 2063 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg, nzb, nzt, topo_top_ind, & 2064 wall_flags_static_0, wall_flags_total_0 2206 2065 2207 2066 USE kinds … … 2214 2073 INTEGER(iwp) :: k !< index variable along z 2215 2074 2216 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo !< input array for 3D topography and dummy array for setting "outer"-flags 2075 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: topo !< input array for 3D topography and dummy array for setting 2076 !< "outer"-flags 2217 2077 2218 2078 ALLOCATE( wall_flags_static_0(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) … … 2220 2080 ! 2221 2081 !-- Set-up topography flags. First, set flags only for s, u, v and w-grid. 2222 !-- Further special flags will be set in following loops. 2082 !-- Further special flags will be set in following loops. 2223 2083 DO i = nxl, nxr 2224 2084 DO j = nys, nyn … … 2226 2086 ! 2227 2087 !-- scalar grid 2228 IF ( BTEST( topo(k,j,i), 0 ) ) &2088 IF ( BTEST( topo(k,j,i), 0 ) ) & 2229 2089 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 0 ) 2230 2090 ! 2231 2091 !-- u grid 2232 IF ( BTEST( topo(k,j,i), 0 ) .AND. & 2233 BTEST( topo(k,j,i-1), 0 ) ) & 2092 IF ( BTEST( topo(k,j,i), 0 ) .AND. BTEST( topo(k,j,i-1), 0 ) ) & 2234 2093 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 1 ) 2235 2094 ! 2236 2095 !-- v grid 2237 IF ( BTEST( topo(k,j,i), 0 ) .AND. & 2238 BTEST( topo(k,j-1,i), 0 ) ) & 2096 IF ( BTEST( topo(k,j,i), 0 ) .AND. BTEST( topo(k,j-1,i), 0 ) ) & 2239 2097 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 2 ) 2240 2098 … … 2244 2102 ! 2245 2103 !-- w grid 2246 IF ( BTEST( topo(k,j,i), 0 ) .AND. & 2247 BTEST( topo(k+1,j,i), 0 ) ) & 2104 IF ( BTEST( topo(k,j,i), 0 ) .AND. BTEST( topo(k+1,j,i), 0 ) ) & 2248 2105 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 3 ) 2249 2106 ENDDO 2250 2251 IF ( topography /= 'closed_channel' ) THEN2107 2108 IF ( topography /= 'closed_channel' ) THEN 2252 2109 wall_flags_static_0(nzt+1,j,i) = IBSET( wall_flags_static_0(nzt+1,j,i), 3 ) 2253 2110 ENDIF … … 2259 2116 2260 2117 ! 2261 !-- Set outer array for scalars to mask near-surface grid points. Note, on 2262 !-- basis of flag 24 futher flags will be derived which are used to control 2263 !-- production of subgrid TKE production near walls. 2264 2118 !-- Set outer array for scalars to mask near-surface grid points. Note, on basis of flag 24 futher 2119 !-- flags will be derived which are used to control production of subgrid TKE production near walls. 2120 2265 2121 ALLOCATE( wall_flags_total_0(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 2266 2122 wall_flags_total_0 = 0 2267 2123 2268 2124 DO i = nxl, nxr 2269 2125 DO j = nys, nyn … … 2273 2129 ENDDO 2274 2130 ENDDO 2275 2131 2276 2132 CALL exchange_horiz_int( wall_flags_total_0, nys, nyn, nxl, nxr, nzt, nbgp ) 2277 2133 2278 2134 DO i = nxl, nxr 2279 2135 DO j = nys, nyn 2280 2136 DO k = nzb, nzt+1 2281 IF ( BTEST( wall_flags_total_0(k,j-1,i), 0 ) .AND. &2282 BTEST( wall_flags_total_0(k,j+1,i), 0 ) .AND. &2283 BTEST( wall_flags_total_0(k,j,i-1), 0 ) .AND. &2284 BTEST( wall_flags_total_0(k,j,i+1), 0 ) .AND. &2285 BTEST( wall_flags_total_0(k,j-1,i-1), 0 ) .AND. &2286 BTEST( wall_flags_total_0(k,j+1,i-1), 0 ) .AND. &2287 BTEST( wall_flags_total_0(k,j-1,i+1), 0 ) .AND. &2288 BTEST( wall_flags_total_0(k,j+1,i+1), 0 ) ) &2137 IF ( BTEST( wall_flags_total_0(k,j-1,i), 0 ) .AND. & 2138 BTEST( wall_flags_total_0(k,j+1,i), 0 ) .AND. & 2139 BTEST( wall_flags_total_0(k,j,i-1), 0 ) .AND. & 2140 BTEST( wall_flags_total_0(k,j,i+1), 0 ) .AND. & 2141 BTEST( wall_flags_total_0(k,j-1,i-1), 0 ) .AND. & 2142 BTEST( wall_flags_total_0(k,j+1,i-1), 0 ) .AND. & 2143 BTEST( wall_flags_total_0(k,j-1,i+1), 0 ) .AND. & 2144 BTEST( wall_flags_total_0(k,j+1,i+1), 0 ) ) & 2289 2145 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 24 ) 2290 2146 ENDDO … … 2298 2154 ! 2299 2155 !-- scalar grid, former nzb_diff_s_inner. 2300 !-- Note, use this flag also to mask topography in diffusion_u and 2301 !-- diffusion_v along the vertical direction. In case of 2302 !-- use_surface_fluxes, fluxes are calculated via MOST, else, simple 2303 !-- gradient approach is applied. Please note, in case of u- and v- 2304 !-- diffuison, a small error is made at edges (on the east side for u, 2305 !-- at the north side for v), since topography on scalar grid point 2306 !-- is used instead of topography on u/v-grid. As number of topography grid 2307 !-- points on uv-grid is different than s-grid, different number of 2308 !-- surface elements would be required. In order to avoid this, 2309 !-- treat edges (u(k,j,i+1)) simply by a gradient approach, i.e. these 2310 !-- points are not masked within diffusion_u. Tests had shown that the 2311 !-- effect on the flow is negligible. 2156 !-- Note, use this flag also to mask topography in diffusion_u and diffusion_v along the 2157 !-- vertical direction. In case of use_surface_fluxes, fluxes are calculated via MOST, 2158 !-- else, simple gradient approach is applied. Please note, in case of u- and v-diffuison, 2159 !-- a small error is made at edges (on the east side for u, at the north side for v), since 2160 !-- topography on scalar grid point is used instead of topography on u/v-grid. As number of 2161 !-- topography grid points on uv-grid is different than s-grid, different number of surface 2162 !-- elements would be required. In order to avoid this, treat edges (u(k,j,i+1)) simply by 2163 !-- a gradient approach, i.e. these points are not masked within diffusion_u. Tests had 2164 !-- shown that the effect on the flow is negligible. 2312 2165 IF ( constant_flux_layer .OR. use_surface_fluxes ) THEN 2313 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) ) &2166 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) ) & 2314 2167 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 8 ) 2315 2168 ELSE … … 2319 2172 ENDDO 2320 2173 ! 2321 !-- Special flag to control vertical diffusion at model top - former 2322 !-- nzt_diff 2174 !-- Special flag to control vertical diffusion at model top - former nzt_diff 2323 2175 wall_flags_total_0(:,j,i) = IBSET( wall_flags_total_0(:,j,i), 9 ) 2324 2176 IF ( use_top_fluxes ) & … … 2328 2180 DO k = nzb+1, nzt 2329 2181 ! 2330 !-- Special flag on u grid, former nzb_u_inner + 1, required 2331 !-- for disturb_field and initialization. Do not disturb directly at 2332 !-- topography, as well as initialize u with zero one grid point outside 2333 !-- of topography. 2334 IF ( BTEST( wall_flags_total_0(k-1,j,i), 1 ) .AND. & 2335 BTEST( wall_flags_total_0(k,j,i), 1 ) .AND. & 2336 BTEST( wall_flags_total_0(k+1,j,i), 1 ) ) & 2182 !-- Special flag on u grid, former nzb_u_inner + 1, required for disturb_field and 2183 !-- initialization. Do not disturb directly at topography, as well as initialize u with 2184 !-- zero one grid point outside of topography. 2185 IF ( BTEST( wall_flags_total_0(k-1,j,i), 1 ) .AND. & 2186 BTEST( wall_flags_total_0(k,j,i), 1 ) .AND. & 2187 BTEST( wall_flags_total_0(k+1,j,i), 1 ) ) & 2337 2188 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 20 ) 2338 2189 ! 2339 !-- Special flag on v grid, former nzb_v_inner + 1, required 2340 !-- for disturb_field and initialization. Do not disturb directly at 2341 !-- topography, as well as initialize v with zero one grid point outside 2342 !-- of topography. 2343 IF ( BTEST( wall_flags_total_0(k-1,j,i), 2 ) .AND. & 2344 BTEST( wall_flags_total_0(k,j,i), 2 ) .AND. & 2345 BTEST( wall_flags_total_0(k+1,j,i), 2 ) ) & 2190 !-- Special flag on v grid, former nzb_v_inner + 1, required for disturb_field and 2191 !-- initialization. Do not disturb directly at topography, as well as initialize v with 2192 !-- zero one grid point outside of topography. 2193 IF ( BTEST( wall_flags_total_0(k-1,j,i), 2 ) .AND. & 2194 BTEST( wall_flags_total_0(k,j,i), 2 ) .AND. & 2195 BTEST( wall_flags_total_0(k+1,j,i), 2 ) ) & 2346 2196 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 21 ) 2347 2197 ! 2348 !-- Special flag on scalar grid, former nzb_s_inner+1. Used for 2349 !-- lpm_sgs_tke 2350 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 2351 BTEST( wall_flags_total_0(k-1,j,i), 0 ) .AND. & 2352 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2198 !-- Special flag on scalar grid, former nzb_s_inner+1. Used for lpm_sgs_tke 2199 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 2200 BTEST( wall_flags_total_0(k-1,j,i), 0 ) .AND. & 2201 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2353 2202 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 25 ) 2354 2203 ! 2355 !-- Special flag on scalar grid, nzb_diff_s_outer - 1, required in 2204 !-- Special flag on scalar grid, nzb_diff_s_outer - 1, required in in production_e 2205 IF ( constant_flux_layer .OR. use_surface_fluxes ) THEN 2206 IF ( BTEST( wall_flags_total_0(k,j,i), 24 ) .AND. & 2207 BTEST( wall_flags_total_0(k-1,j,i), 24 ) .AND. & 2208 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2209 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 29 ) 2210 ELSE 2211 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) ) & 2212 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 29 ) 2213 ENDIF 2214 ! 2215 !-- Special flag on scalar grid, nzb_diff_s_outer - 1, required in 2356 2216 !-- in production_e 2357 2217 IF ( constant_flux_layer .OR. use_surface_fluxes ) THEN 2358 IF ( BTEST( wall_flags_total_0(k,j,i), 24 ) .AND. & 2359 BTEST( wall_flags_total_0(k-1,j,i), 24 ) .AND. & 2360 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2361 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 29 ) 2362 ELSE 2363 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) ) & 2364 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 29 ) 2365 ENDIF 2366 ! 2367 !-- Special flag on scalar grid, nzb_diff_s_outer - 1, required in 2368 !-- in production_e 2369 IF ( constant_flux_layer .OR. use_surface_fluxes ) THEN 2370 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 2371 BTEST( wall_flags_total_0(k-1,j,i), 0 ) .AND. & 2372 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2218 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 2219 BTEST( wall_flags_total_0(k-1,j,i), 0 ) .AND. & 2220 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2373 2221 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 30 ) 2374 2222 ELSE 2375 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) ) &2223 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) ) & 2376 2224 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 30 ) 2377 2225 ENDIF … … 2382 2230 ! 2383 2231 !-- Scalar grid 2384 IF ( BTEST( wall_flags_total_0(k-1,j,i), 0 ) .AND.&2385 .NOT. BTEST( wall_flags_total_0(k,j,i), 0 ) ) &2386 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 13 ) 2232 IF ( BTEST( wall_flags_total_0(k-1,j,i), 0 ) .AND. & 2233 .NOT. BTEST( wall_flags_total_0(k,j,i), 0 ) ) & 2234 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 13 ) 2387 2235 ! 2388 2236 !-- Downward facing wall on u grid 2389 IF ( BTEST( wall_flags_total_0(k-1,j,i), 1 ) .AND.&2390 .NOT. BTEST( wall_flags_total_0(k,j,i), 1 ) ) &2237 IF ( BTEST( wall_flags_total_0(k-1,j,i), 1 ) .AND. & 2238 .NOT. BTEST( wall_flags_total_0(k,j,i), 1 ) ) & 2391 2239 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 15 ) 2392 2240 ! 2393 2241 !-- Downward facing wall on v grid 2394 IF ( BTEST( wall_flags_total_0(k-1,j,i), 2 ) .AND.&2395 .NOT. BTEST( wall_flags_total_0(k,j,i), 2 ) ) &2242 IF ( BTEST( wall_flags_total_0(k-1,j,i), 2 ) .AND. & 2243 .NOT. BTEST( wall_flags_total_0(k,j,i), 2 ) ) & 2396 2244 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 17 ) 2397 2245 ! 2398 2246 !-- Downward facing wall on w grid 2399 IF ( BTEST( wall_flags_total_0(k-1,j,i), 3 ) .AND.&2400 .NOT. BTEST( wall_flags_total_0(k,j,i), 3 ) ) &2247 IF ( BTEST( wall_flags_total_0(k-1,j,i), 3 ) .AND. & 2248 .NOT. BTEST( wall_flags_total_0(k,j,i), 3 ) ) & 2401 2249 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 19 ) 2402 2250 ENDDO … … 2406 2254 ! 2407 2255 !-- Upward facing wall on scalar grid 2408 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. &2409 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) &2256 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 2257 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2410 2258 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 12 ) 2411 2259 ! 2412 2260 !-- Upward facing wall on u grid 2413 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 1 ) .AND. &2414 BTEST( wall_flags_total_0(k+1,j,i), 1 ) ) &2261 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 1 ) .AND. & 2262 BTEST( wall_flags_total_0(k+1,j,i), 1 ) ) & 2415 2263 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 14 ) 2416 2264 2417 ! 2265 ! 2418 2266 !-- Upward facing wall on v grid 2419 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 2 ) .AND. &2420 BTEST( wall_flags_total_0(k+1,j,i), 2 ) ) &2267 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 2 ) .AND. & 2268 BTEST( wall_flags_total_0(k+1,j,i), 2 ) ) & 2421 2269 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 16 ) 2422 2270 2423 2271 ! 2424 2272 !-- Upward facing wall on w grid 2425 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 3 ) .AND. &2426 BTEST( wall_flags_total_0(k+1,j,i), 3 ) ) &2273 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 3 ) .AND. & 2274 BTEST( wall_flags_total_0(k+1,j,i), 3 ) ) & 2427 2275 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 18 ) 2428 2276 ! 2429 2277 !-- Special flag on scalar grid, former nzb_s_inner 2430 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .OR. &2431 BTEST( wall_flags_total_0(k,j,i), 12 ) .OR. &2432 BTEST( wall_flags_total_0(k,j,i), 13 ) ) &2278 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .OR. & 2279 BTEST( wall_flags_total_0(k,j,i), 12 ) .OR. & 2280 BTEST( wall_flags_total_0(k,j,i), 13 ) ) & 2433 2281 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 22 ) 2434 2282 ! 2435 !-- Special flag on scalar grid, nzb_diff_s_inner - 1, required for 2283 !-- Special flag on scalar grid, nzb_diff_s_inner - 1, required for 2436 2284 !-- flow_statistics 2437 2285 IF ( constant_flux_layer .OR. use_surface_fluxes ) THEN 2438 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. &2439 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) &2286 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 2287 BTEST( wall_flags_total_0(k+1,j,i), 0 ) ) & 2440 2288 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 23 ) 2441 2289 ELSE 2442 IF ( BTEST( wall_flags_total_0(k,j,i), 22 ) ) &2290 IF ( BTEST( wall_flags_total_0(k,j,i), 22 ) ) & 2443 2291 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 23 ) 2444 2292 ENDIF 2445 2293 2446 2294 2447 2295 ENDDO … … 2449 2297 wall_flags_total_0(nzt+1,j,i) = IBSET( wall_flags_total_0(nzt+1,j,i), 23 ) 2450 2298 ! 2451 !-- Set flags indicating that topography is close by in horizontal 2452 !-- direction, i.e. flags that infold the topography. These will be used 2453 !-- to set advection flags for passive scalars, where due to large 2454 !-- gradients near buildings stationary numerical oscillations can produce 2455 !-- unrealistically high concentrations. This is only necessary if 2456 !-- WS-scheme is applied for scalar advection. Note, these flags will be 2457 !-- only used for passive scalars such as chemical species or aerosols. 2299 !-- Set flags indicating that topography is close by in horizontal direction, i.e. flags that 2300 !-- infold the topography. These will be used to set advection flags for passive scalars, 2301 !-- where due to large gradients near buildings stationary numerical oscillations can produce 2302 !-- unrealistically high concentrations. This is only necessary if WS-scheme is applied for 2303 !-- scalar advection. Note, these flags will be only used for passive scalars such as chemical 2304 !-- species or aerosols. 2458 2305 IF ( scalar_advec == 'ws-scheme' ) THEN 2459 2306 DO k = nzb, nzt 2460 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. ( & 2461 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i-1), 0 ) ) .OR.& 2462 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i-2), 0 ) ) .OR.& 2463 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i-3), 0 ) ) .OR.& 2464 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i+1), 0 ) ) .OR.& 2465 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i+2), 0 ) ) .OR.& 2466 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i+3), 0 ) ) .OR.& 2467 ANY( .NOT. BTEST( wall_flags_total_0(k,j-1,i-3:i+3), 0 ) ) .OR.& 2468 ANY( .NOT. BTEST( wall_flags_total_0(k,j-2,i-3:i+3), 0 ) ) .OR.& 2469 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3,i-3:i+3), 0 ) ) .OR.& 2470 ANY( .NOT. BTEST( wall_flags_total_0(k,j+1,i-3:i+3), 0 ) ) .OR.& 2471 ANY( .NOT. BTEST( wall_flags_total_0(k,j+2,i-3:i+3), 0 ) ) .OR.& 2472 ANY( .NOT. BTEST( wall_flags_total_0(k,j+3,i-3:i+3), 0 ) ) & 2473 ) ) & 2307 IF ( BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. ( & 2308 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i-1), 0 ) ) .OR. & 2309 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i-2), 0 ) ) .OR. & 2310 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i-3), 0 ) ) .OR. & 2311 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i+1), 0 ) ) .OR. & 2312 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i+2), 0 ) ) .OR. & 2313 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3:j+3,i+3), 0 ) ) .OR. & 2314 ANY( .NOT. BTEST( wall_flags_total_0(k,j-1,i-3:i+3), 0 ) ) .OR. & 2315 ANY( .NOT. BTEST( wall_flags_total_0(k,j-2,i-3:i+3), 0 ) ) .OR. & 2316 ANY( .NOT. BTEST( wall_flags_total_0(k,j-3,i-3:i+3), 0 ) ) .OR. & 2317 ANY( .NOT. BTEST( wall_flags_total_0(k,j+1,i-3:i+3), 0 ) ) .OR. & 2318 ANY( .NOT. BTEST( wall_flags_total_0(k,j+2,i-3:i+3), 0 ) ) .OR. & 2319 ANY( .NOT. BTEST( wall_flags_total_0(k,j+3,i-3:i+3), 0 ) ) & 2320 ) & 2321 ) & 2474 2322 wall_flags_total_0(k,j,i) = IBSET( wall_flags_total_0(k,j,i), 31 ) 2475 2476 2323 ENDDO 2477 2324 ENDIF … … 2480 2327 ! 2481 2328 !-- Finally, set identification flags indicating natural terrain or buildings. 2482 !-- Natural terrain grid points. Information on the type of the surface is 2483 !-- stored in bit 1 of 3D Integer array topo. However, this bit is only set2484 !-- when topography is read from file. In order to run the land-surface model2485 !-- also without topography information, set bit 1 explicitely in thiscase.2486 !-- 2329 !-- Natural terrain grid points. Information on the type of the surface is stored in bit 1 of 2330 !-- 3D Integer array topo. However, this bit is only set when topography is read from file. In order 2331 !-- to run the land-surface model also without topography information, set bit 1 explicitely in this 2332 !-- case. 2333 !-- 2487 2334 !-- Natural terrain grid points 2488 2335 !-- If no topography is initialized, the land-surface is at k = nzb. … … 2493 2340 DO j = nys, nyn 2494 2341 DO k = nzb, nzt+1 2495 ! 2342 ! 2496 2343 !-- Natural terrain grid point 2497 IF ( BTEST( topo(k,j,i), 1 ) ) &2344 IF ( BTEST( topo(k,j,i), 1 ) ) & 2498 2345 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 5 ) 2499 2346 ENDDO … … 2506 2353 DO j = nys, nyn 2507 2354 DO k = nzb, nzt+1 2508 IF ( BTEST( topo(k,j,i), 2 ) ) &2355 IF ( BTEST( topo(k,j,i), 2 ) ) & 2509 2356 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 6 ) 2510 2357 ENDDO … … 2516 2363 DO j = nys, nyn 2517 2364 DO k = nzb, nzt+1 2518 IF ( BTEST( topo(k,j,i), 4 ) ) &2365 IF ( BTEST( topo(k,j,i), 4 ) ) & 2519 2366 wall_flags_static_0(k,j,i) = IBSET( wall_flags_static_0(k,j,i), 4 ) 2520 2367 ENDDO 2521 2368 ENDDO 2522 2369 ENDDO 2523 2370 2524 2371 CALL exchange_horiz_int( wall_flags_static_0, nys, nyn, nxl, nxr, nzt, nbgp ) 2525 2372 2526 2373 DO i = nxl, nxr 2527 2374 DO j = nys, nyn … … 2535 2382 CALL exchange_horiz_int( wall_flags_total_0, nys, nyn, nxl, nxr, nzt, nbgp ) 2536 2383 ! 2537 !-- Set boundary conditions also for flags. Can be interpreted as Neumann 2538 !-- boundary conditions for topography.2384 !-- Set boundary conditions also for flags. Can be interpreted as Neumann boundary conditions for 2385 !-- topography. 2539 2386 IF ( .NOT. bc_ns_cyc ) THEN 2540 2387 IF ( nys == 0 ) THEN 2541 DO i = 1, nbgp 2388 DO i = 1, nbgp 2542 2389 wall_flags_total_0(:,nys-i,:) = wall_flags_total_0(:,nys,:) 2543 2390 ENDDO 2544 2391 ENDIF 2545 2392 IF ( nyn == ny ) THEN 2546 DO i = 1, nbgp 2393 DO i = 1, nbgp 2547 2394 wall_flags_total_0(:,nyn+i,:) = wall_flags_total_0(:,nyn,:) 2548 2395 ENDDO … … 2551 2398 IF ( .NOT. bc_lr_cyc ) THEN 2552 2399 IF ( nxl == 0 ) THEN 2553 DO i = 1, nbgp 2400 DO i = 1, nbgp 2554 2401 wall_flags_total_0(:,:,nxl-i) = wall_flags_total_0(:,:,nxl) 2555 2402 ENDDO 2556 2403 ENDIF 2557 IF ( nxr == nx ) THEN 2558 DO i = 1, nbgp 2559 wall_flags_total_0(:,:,nxr+i) = wall_flags_total_0(:,:,nxr) 2560 ENDDO 2561 ENDIF 2404 IF ( nxr == nx ) THEN 2405 DO i = 1, nbgp 2406 wall_flags_total_0(:,:,nxr+i) = wall_flags_total_0(:,:,nxr) 2407 ENDDO 2408 ENDIF 2562 2409 ENDIF 2563 2410 ! 2564 !-- Pre-calculate topography top indices (former get_topography_top_index 2411 !-- Pre-calculate topography top indices (former get_topography_top_index 2565 2412 !-- function) 2566 2413 ALLOCATE( topo_top_ind(nysg:nyng,nxlg:nxrg,0:4) ) … … 2568 2415 !-- Uppermost topography index on scalar grid 2569 2416 ibit = 12 2570 topo_top_ind(:,:,0) = MAXLOC( & 2571 MERGE( 1, 0, & 2572 BTEST( wall_flags_total_0(:,:,:), ibit ) & 2573 ), DIM = 1 & 2574 ) - 1 2575 ! 2576 !-- Uppermost topography index on u grid 2417 topo_top_ind(:,:,0) = MAXLOC( MERGE( 1, 0, BTEST( wall_flags_total_0(:,:,:), ibit ) ), DIM=1 ) & 2418 - 1 2419 ! 2420 !-- Uppermost topography index on u grid 2577 2421 ibit = 14 2578 topo_top_ind(:,:,1) = MAXLOC( & 2579 MERGE( 1, 0, & 2580 BTEST( wall_flags_total_0(:,:,:), ibit ) & 2581 ), DIM = 1 & 2582 ) - 1 2583 ! 2584 !-- Uppermost topography index on v grid 2422 topo_top_ind(:,:,1) = MAXLOC( MERGE( 1, 0, BTEST( wall_flags_total_0(:,:,:), ibit ) ), DIM=1 ) & 2423 - 1 2424 ! 2425 !-- Uppermost topography index on v grid 2585 2426 ibit = 16 2586 topo_top_ind(:,:,2) = MAXLOC( & 2587 MERGE( 1, 0, & 2588 BTEST( wall_flags_total_0(:,:,:), ibit ) & 2589 ), DIM = 1 & 2590 ) - 1 2427 topo_top_ind(:,:,2) = MAXLOC( MERGE( 1, 0, BTEST( wall_flags_total_0(:,:,:), ibit ) ), DIM=1 ) & 2428 - 1 2591 2429 ! 2592 2430 !-- Uppermost topography index on w grid 2593 2431 ibit = 18 2594 topo_top_ind(:,:,3) = MAXLOC( & 2595 MERGE( 1, 0, & 2596 BTEST( wall_flags_total_0(:,:,:), ibit ) & 2597 ), DIM = 1 & 2598 ) - 1 2432 topo_top_ind(:,:,3) = MAXLOC( MERGE( 1, 0, BTEST( wall_flags_total_0(:,:,:), ibit ) ), DIM=1 ) & 2433 - 1 2599 2434 ! 2600 2435 !-- Uppermost topography index on scalar outer grid 2601 2436 ibit = 24 2602 topo_top_ind(:,:,4) = MAXLOC( & 2603 MERGE( 1, 0, & 2604 BTEST( wall_flags_total_0(:,:,:), ibit ) & 2605 ), DIM = 1 & 2606 ) - 1 2437 topo_top_ind(:,:,4) = MAXLOC( MERGE( 1, 0, BTEST( wall_flags_total_0(:,:,:), ibit ) ), DIM=1 ) & 2438 - 1 2607 2439 2608 2440 END SUBROUTINE set_topo_flags -
TabularUnified palm/trunk/SOURCE/init_masks.f90 ¶
r4521 r4648 1 1 !> @file init_masks.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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/>. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 8 ! 9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 12 ! 13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4521 2020-05-06 11:39:49Z schwenkel 27 29 ! Rename variable 28 ! 30 ! 29 31 ! 4502 2020-04-17 16:14:16Z schwenkel 30 32 ! Implementation of ice microphysics 31 ! 33 ! 32 34 ! 4444 2020-03-05 15:59:50Z raasch 33 35 ! bugfix: cpp-directives for serial mode added 34 ! 36 ! 35 37 ! 4360 2020-01-07 11:25:50Z suehring 36 38 ! Corrected "Former revisions" section 37 ! 39 ! 38 40 ! 4069 2019-07-01 14:05:51Z Giersch 39 ! Masked output running index mid has been introduced as a local variable to 40 ! avoid runtime error (Loop variable has been modified) in time_integration41 ! 41 ! Masked output running index mid has been introduced as a local variable to avoid runtime error 42 ! (Loop variable has been modified) in time_integration 43 ! 42 44 ! 3766 2019-02-26 16:23:41Z raasch 43 45 ! unused variables removed 44 ! 46 ! 45 47 ! 3687 2019-01-22 10:42:06Z knoop 46 48 ! unused variables removed 47 ! 49 ! 48 50 ! 3655 2019-01-07 16:51:22Z knoop 49 ! Move the control parameter "salsa" from salsa_mod to control_parameters 50 ! (M. Kurppa) 51 ! Move the control parameter "salsa" from salsa_mod to control_parameters (M. Kurppa) 51 52 ! 52 53 ! 410 2009-12-04 17:05:40Z letzel … … 57 58 ! ------------ 58 59 !> Initialize masked data output 59 !------------------------------------------------------------------------------ !60 !--------------------------------------------------------------------------------------------------! 60 61 SUBROUTINE init_masks 61 62 62 USE arrays_3d, &63 USE arrays_3d, & 63 64 ONLY: zu, zw 64 65 65 USE bulk_cloud_model_mod, & 66 ONLY: bulk_cloud_model, microphysics_morrison, microphysics_seifert, & 67 microphysics_ice_phase 68 69 USE control_parameters, & 70 ONLY: constant_diffusion, cloud_droplets, & 71 data_output_masks, data_output_masks_user, & 72 doav, doav_n, domask, domask_no, dz, dz_stretch_level_start, & 73 humidity, mask, masks, mask_scale, mask_i, & 74 mask_i_global, mask_j, mask_j_global, mask_k, mask_k_global, & 75 mask_k_over_surface, & 76 mask_loop, mask_size, mask_size_l, mask_start_l, & 77 mask_surface, mask_x, & 78 mask_x_loop, mask_xyz_dimension, mask_y, mask_y_loop, mask_z, & 79 mask_z_loop, max_masks, message_string, & 80 passive_scalar, ocean_mode, varnamelength 81 82 USE grid_variables, & 66 USE bulk_cloud_model_mod, & 67 ONLY: bulk_cloud_model, microphysics_ice_phase, microphysics_morrison, & 68 microphysics_seifert 69 70 71 USE control_parameters, & 72 ONLY: constant_diffusion, cloud_droplets, data_output_masks, data_output_masks_user, doav,& 73 doav_n, domask, domask_no, dz, dz_stretch_level_start, humidity, mask, masks, & 74 mask_scale, mask_i, mask_i_global, mask_j, mask_j_global, mask_k, mask_k_global, & 75 mask_k_over_surface, mask_loop, mask_size, mask_size_l, mask_start_l, mask_surface, & 76 mask_x, mask_x_loop, mask_xyz_dimension, mask_y, mask_y_loop, mask_z, mask_z_loop, & 77 max_masks, message_string, passive_scalar, ocean_mode, varnamelength 78 79 USE grid_variables, & 83 80 ONLY: dx, dy 84 81 85 USE indices, &82 USE indices, & 86 83 ONLY: nx, nxl, nxr, ny, nyn, nys, nz, nzb, nzt 87 84 88 85 USE kinds 89 86 90 USE module_interface, &87 USE module_interface, & 91 88 ONLY: module_interface_init_masks 92 89 93 USE netcdf_interface, &90 USE netcdf_interface, & 94 91 ONLY: domask_unit, netcdf_data_format 95 92 96 USE particle_attributes, &93 USE particle_attributes, & 97 94 ONLY: particle_advection 98 95 … … 103 100 CHARACTER (LEN=varnamelength) :: var !< contains variable name 104 101 CHARACTER (LEN=7) :: unit !< contains unit of variable 105 102 106 103 CHARACTER (LEN=varnamelength), DIMENSION(max_masks,100) :: do_mask !< list of output variables 107 104 CHARACTER (LEN=varnamelength), DIMENSION(max_masks,100) :: do_mask_user !< list of user-specified output variables … … 120 117 INTEGER(iwp) :: sender !< PE id of sending PE 121 118 #endif 122 119 123 120 INTEGER(iwp), DIMENSION(:), ALLOCATABLE :: tmp_array !< temporary 1D array 124 121 … … 126 123 127 124 ! 128 !-- Initial values are explicitly set here due to a bug in the Cray compiler 129 !-- in case of assignments of initial values in declaration statements for130 !-- arrays with more than 9999 elements(appears with -eD only)125 !-- Initial values are explicitly set here due to a bug in the Cray compiler in case of assignments 126 !-- of initial values in declaration statements for arrays with more than 9999 elements 127 !-- (appears with -eD only) 131 128 domask = ' ' 132 129 … … 135 132 ALLOCATE( tmp_array( MAX(nx,ny,nz)+2 ) ) 136 133 137 ALLOCATE( mask_i(max_masks,nxr-nxl+2), &138 mask_j(max_masks,nyn-nys+2), &134 ALLOCATE( mask_i(max_masks,nxr-nxl+2), & 135 mask_j(max_masks,nyn-nys+2), & 139 136 mask_k(max_masks,nzt-nzb+2) ) 140 137 ! 141 138 !-- internal mask arrays ("mask,dimension,selection") 142 ALLOCATE( mask(max_masks,3,mask_xyz_dimension), & 143 mask_loop(max_masks,3,3) ) 144 145 ! 146 !-- Parallel mask output not yet supported. In check_parameters data format 147 !-- is restricted and is switched back to non-parallel output. Therefore the 148 !-- following error can not occur at the moment. 139 ALLOCATE( mask(max_masks,3,mask_xyz_dimension), mask_loop(max_masks,3,3) ) 140 141 ! 142 !-- Parallel mask output not yet supported. In check_parameters data format is restricted and is 143 !-- switched back to non-parallel output. Therefore the following error can not occur at the moment. 149 144 IF ( netcdf_data_format > 4 ) THEN 150 message_string = 'netCDF file formats '// &151 '5 and 6 (with parallel I/O support)'// &145 message_string = 'netCDF file formats '// & 146 '5 and 6 (with parallel I/O support)'// & 152 147 ' are currently not supported.' 153 148 CALL message( 'init_masks', 'PA0328', 1, 2, 0, 6, 0 ) … … 157 152 !-- Store data output parameters for masked data output in few shared arrays 158 153 DO mid = 1, masks 159 154 160 155 do_mask (mid,:) = data_output_masks(mid,:) 161 156 do_mask_user(mid,:) = data_output_masks_user(mid,:) 162 mask (mid,1,:) = mask_x(mid,:) 157 mask (mid,1,:) = mask_x(mid,:) 163 158 mask (mid,2,:) = mask_y(mid,:) 164 mask (mid,3,:) = mask_z(mid,:) 159 mask (mid,3,:) = mask_z(mid,:) 165 160 ! 166 161 !-- Flag a mask as terrain following … … 169 164 ENDIF 170 165 171 IF ( mask_x_loop(mid,1) == -1.0_wp .AND. mask_x_loop(mid,2) == -1.0_wp &172 .AND.mask_x_loop(mid,3) == -1.0_wp ) THEN166 IF ( mask_x_loop(mid,1) == -1.0_wp .AND. mask_x_loop(mid,2) == -1.0_wp .AND. & 167 mask_x_loop(mid,3) == -1.0_wp ) THEN 173 168 mask_loop(mid,1,1:2) = -1.0_wp 174 169 mask_loop(mid,1,3) = 0.0_wp … … 176 171 mask_loop(mid,1,:) = mask_x_loop(mid,:) 177 172 ENDIF 178 IF ( mask_y_loop(mid,1) == -1.0_wp .AND. mask_y_loop(mid,2) == -1.0_wp &179 .AND.mask_y_loop(mid,3) == -1.0_wp ) THEN173 IF ( mask_y_loop(mid,1) == -1.0_wp .AND. mask_y_loop(mid,2) == -1.0_wp .AND. & 174 mask_y_loop(mid,3) == -1.0_wp ) THEN 180 175 mask_loop(mid,2,1:2) = -1.0_wp 181 176 mask_loop(mid,2,3) = 0.0_wp … … 183 178 mask_loop(mid,2,:) = mask_y_loop(mid,:) 184 179 ENDIF 185 IF ( mask_z_loop(mid,1) == -1.0_wp .AND. mask_z_loop(mid,2) == -1.0_wp &186 .AND.mask_z_loop(mid,3) == -1.0_wp ) THEN180 IF ( mask_z_loop(mid,1) == -1.0_wp .AND. mask_z_loop(mid,2) == -1.0_wp .AND. & 181 mask_z_loop(mid,3) == -1.0_wp ) THEN 187 182 mask_loop(mid,3,1:2) = -1.0_wp 188 183 mask_loop(mid,3,3) = 0.0_wp … … 190 185 mask_loop(mid,3,:) = mask_z_loop(mid,:) 191 186 ENDIF 192 187 193 188 ENDDO 194 189 195 190 mask_i = -1; mask_j = -1; mask_k = -1 196 191 197 192 ! 198 193 !-- Global arrays are required by define_netcdf_header. 199 194 IF ( myid == 0 .OR. netcdf_data_format > 4 ) THEN 200 ALLOCATE( mask_i_global(max_masks,nx+2), &201 mask_j_global(max_masks,ny+2), &195 ALLOCATE( mask_i_global(max_masks,nx+2), & 196 mask_j_global(max_masks,ny+2), & 202 197 mask_k_global(max_masks,nz+2) ) 203 198 mask_i_global = -1; mask_j_global = -1; mask_k_global = -1 … … 217 212 DO WHILE ( do_mask_user(mid,j) /= ' ' .AND. j <= 100 ) 218 213 IF ( i > 100 ) THEN 219 WRITE ( message_string, * ) 'number of output quantitities ', &220 'given by data_output_mask and data_output_mask_user ',&221 'exceeds the limit of 100'214 WRITE ( message_string, * ) 'number of output quantitities ', & 215 'given by data_output_mask and data_output_mask_user ',& 216 'exceeds the limit of 100' 222 217 CALL message( 'init_masks', 'PA0329', 1, 2, 0, 6, 0 ) 223 218 ENDIF … … 249 244 CASE ( 'e' ) 250 245 IF ( constant_diffusion ) THEN 251 WRITE ( message_string, * ) 'output of "', TRIM( var ), &252 '" requires constant_diffusion = .FALSE.'246 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 247 '" requires constant_diffusion = .FALSE.' 253 248 CALL message( 'init_masks', 'PA0103', 1, 2, 0, 6, 0 ) 254 249 ENDIF … … 257 252 CASE ( 'thetal' ) 258 253 IF ( .NOT. bulk_cloud_model ) THEN 259 WRITE ( message_string, * ) 'output of "', TRIM( var ), &260 '" requires bulk_cloud_model = .TRUE.'254 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 255 '" requires bulk_cloud_model = .TRUE.' 261 256 CALL message( 'init_masks', 'PA0108', 1, 2, 0, 6, 0 ) 262 257 ENDIF … … 265 260 CASE ( 'nc' ) 266 261 IF ( .NOT. bulk_cloud_model ) THEN 267 WRITE ( message_string, * ) 'output of "', TRIM( var ), &268 '" requires bulk_cloud_model = .TRUE.'262 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 263 '" requires bulk_cloud_model = .TRUE.' 269 264 CALL message( 'init_masks', 'PA0108', 1, 2, 0, 6, 0 ) 270 ELSEIF ( .NOT. microphysics_morrison ) THEN 271 message_string = 'output of "' // TRIM( var ) // '" ' // & 272 'requires = morrison' 265 ELSEIF ( .NOT. microphysics_morrison ) THEN 266 message_string = 'output of "' // TRIM( var ) // '" ' // 'requires = morrison' 273 267 CALL message( 'check_parameters', 'PA0359', 1, 2, 0, 6, 0 ) 274 268 ENDIF … … 277 271 CASE ( 'ni' ) 278 272 IF ( .NOT. bulk_cloud_model ) THEN 279 WRITE ( message_string, * ) 'output of "', TRIM( var ), &280 '" requires bulk_cloud_model = .TRUE.'273 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 274 '" requires bulk_cloud_model = .TRUE.' 281 275 CALL message( 'init_masks', 'PA0108', 1, 2, 0, 6, 0 ) 282 ELSEIF ( .NOT. microphysics_ice_phase ) THEN283 message_string = 'output of "' // TRIM( var ) // '" ' // &284 'requires microphysics_ice_phase = .TRUE.'276 ELSEIF ( .NOT. microphysics_ice_phase ) THEN 277 message_string = 'output of "' // TRIM( var ) // '" ' // & 278 'requires microphysics_ice_phase = .TRUE.' 285 279 CALL message( 'check_parameters', 'PA0359', 1, 2, 0, 6, 0 ) 286 280 ENDIF … … 289 283 CASE ( 'nr' ) 290 284 IF ( .NOT. bulk_cloud_model ) THEN 291 WRITE ( message_string, * ) 'output of "', TRIM( var ), &292 '" requires bulk_cloud_model = .TRUE.'285 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 286 '" requires bulk_cloud_model = .TRUE.' 293 287 CALL message( 'init_masks', 'PA0108', 1, 2, 0, 6, 0 ) 294 ELSEIF ( .NOT. microphysics_seifert )THEN295 message_string = 'output of "' // TRIM( var ) // '"' // &296 'requires cloud_scheme = seifert_beheng'288 ELSEIF ( .NOT. microphysics_seifert ) THEN 289 message_string = 'output of "' // TRIM( var ) // '"' // & 290 'requires cloud_scheme = seifert_beheng' 297 291 CALL message( 'check_parameters', 'PA0359', 1, 2, 0, 6, 0 ) 298 292 ENDIF … … 301 295 CASE ( 'pc', 'pr' ) 302 296 IF ( .NOT. particle_advection ) THEN 303 WRITE ( message_string, * ) 'output of "', TRIM( var ), &304 '" requires a "particles_par"-NAMELIST in the ',&305 'parameter file (PARIN)'297 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 298 '" requires a "particles_par"-NAMELIST in the ', & 299 'parameter file (PARIN)' 306 300 CALL message( 'init_masks', 'PA0104', 1, 2, 0, 6, 0 ) 307 301 ENDIF … … 311 305 CASE ( 'q', 'thetav' ) 312 306 IF ( .NOT. humidity ) THEN 313 WRITE ( message_string, * ) 'output of "', TRIM( var ), &314 '" requires humidity = .TRUE.'307 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 308 '" requires humidity = .TRUE.' 315 309 CALL message( 'init_masks', 'PA0105', 1, 2, 0, 6, 0 ) 316 310 ENDIF … … 320 314 CASE ( 'qc' ) 321 315 IF ( .NOT. bulk_cloud_model ) THEN 322 message_string = 'output of "' // TRIM( var ) // '"' // &323 'requires bulk_cloud_model = .TRUE.'316 message_string = 'output of "' // TRIM( var ) // '"' // & 317 'requires bulk_cloud_model = .TRUE.' 324 318 CALL message( 'check_parameters', 'PA0108', 1, 2, 0, 6, 0 ) 325 319 ENDIF … … 328 322 CASE ( 'ql' ) 329 323 IF ( .NOT. ( bulk_cloud_model .OR. cloud_droplets ) ) THEN 330 WRITE ( message_string, * ) 'output of "', TRIM( var ), &331 '" requires bulk_cloud_model = .TRUE. or ',&332 'cloud_droplets = .TRUE.'324 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 325 '" requires bulk_cloud_model = .TRUE. or ', & 326 'cloud_droplets = .TRUE.' 333 327 CALL message( 'init_masks', 'PA0106', 1, 2, 0, 6, 0 ) 334 328 ENDIF … … 337 331 CASE ( 'ql_c', 'ql_v', 'ql_vp' ) 338 332 IF ( .NOT. cloud_droplets ) THEN 339 WRITE ( message_string, * ) 'output of "', TRIM( var ), &340 '" requires cloud_droplets = .TRUE.'333 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 334 '" requires cloud_droplets = .TRUE.' 341 335 CALL message( 'init_masks', 'PA0107', 1, 2, 0, 6, 0 ) 342 336 ENDIF … … 347 341 CASE ( 'qv' ) 348 342 IF ( .NOT. bulk_cloud_model ) THEN 349 WRITE ( message_string, * ) 'output of "', TRIM( var ), &350 ' " requires bulk_cloud_model = .TRUE.'343 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 344 ' " requires bulk_cloud_model = .TRUE.' 351 345 CALL message( 'init_masks', 'PA0108', 1, 2, 0, 6, 0 ) 352 346 ENDIF … … 355 349 CASE ( 'qi' ) 356 350 IF ( .NOT. bulk_cloud_model ) THEN 357 message_string = 'output of "' // TRIM( var ) // '" ' // &358 'requires bulk_cloud_model = .TRUE.'351 message_string = 'output of "' // TRIM( var ) // '" ' // & 352 'requires bulk_cloud_model = .TRUE.' 359 353 CALL message( 'check_parameters', 'PA0108', 1, 2, 0, 6, 0 ) 360 354 ELSEIF ( .NOT. microphysics_ice_phase ) THEN 361 message_string = 'output of "' // TRIM( var ) // '" ' // &362 'requires microphysics_ice_phase = .TRUE.'355 message_string = 'output of "' // TRIM( var ) // '" ' // & 356 'requires microphysics_ice_phase = .TRUE.' 363 357 CALL message( 'check_parameters', 'PA0359', 1, 2, 0, 6, 0 ) 364 358 ENDIF … … 367 361 CASE ( 'qr' ) 368 362 IF ( .NOT. bulk_cloud_model ) THEN 369 message_string = 'output of "' // TRIM( var ) // '" ' // &370 'requires bulk_cloud_model = .TRUE.'363 message_string = 'output of "' // TRIM( var ) // '" ' // & 364 'requires bulk_cloud_model = .TRUE.' 371 365 CALL message( 'check_parameters', 'PA0108', 1, 2, 0, 6, 0 ) 372 366 ELSEIF ( .NOT. microphysics_seifert ) THEN 373 message_string = 'output of "' // TRIM( var ) // '" ' // &374 'requires cloud_scheme = seifert_beheng'367 message_string = 'output of "' // TRIM( var ) // '" ' // & 368 'requires cloud_scheme = seifert_beheng' 375 369 CALL message( 'check_parameters', 'PA0359', 1, 2, 0, 6, 0 ) 376 370 ENDIF … … 379 373 CASE ( 'rho_sea_water' ) 380 374 IF ( .NOT. ocean_mode ) THEN 381 WRITE ( message_string, * ) 'output of "', TRIM( var ), &382 '" requires ocean mode'375 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 376 '" requires ocean mode' 383 377 CALL message( 'init_masks', 'PA0109', 1, 2, 0, 6, 0 ) 384 378 ENDIF … … 387 381 CASE ( 's' ) 388 382 IF ( .NOT. passive_scalar ) THEN 389 WRITE ( message_string, * ) 'output of "', TRIM( var ), &390 '" requires passive_scalar = .TRUE.'383 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 384 '" requires passive_scalar = .TRUE.' 391 385 CALL message( 'init_masks', 'PA0110', 1, 2, 0, 6, 0 ) 392 386 ENDIF … … 395 389 CASE ( 'sa' ) 396 390 IF ( .NOT. ocean_mode ) THEN 397 WRITE ( message_string, * ) 'output of "', TRIM( var ), & 398 '" requires ocean mode' 391 WRITE ( message_string, * ) 'output of "', TRIM( var ), '" requires ocean mode' 399 392 CALL message( 'init_masks', 'PA0109', 1, 2, 0, 6, 0 ) 400 393 ENDIF … … 402 395 403 396 CASE ( 'us*', 't*', 'lwp*', 'pra*', 'prr*', 'z0*', 'z0h*' ) 404 WRITE ( message_string, * ) 'illegal value for data_', & 405 'output: "', TRIM( var ), '" is only allowed', & 406 'for horizontal cross section' 397 WRITE ( message_string, * ) 'illegal value for data_', 'output: "', TRIM( var ), & 398 '" is only allowed', 'for horizontal cross section' 407 399 CALL message( 'init_masks', 'PA0111', 1, 2, 0, 6, 0 ) 408 400 … … 422 414 IF ( unit == 'illegal' ) THEN 423 415 IF ( do_mask_user(mid,1) /= ' ' ) THEN 424 WRITE ( message_string, * ) 'illegal value for data_', &425 'output_masks or data_output_masks_user: "',&426 TRIM( do_mask(mid,i) ), '"'416 WRITE ( message_string, * ) 'illegal value for data_', & 417 'output_masks or data_output_masks_user: "', & 418 TRIM( do_mask(mid,i) ), '"' 427 419 CALL message( 'init_masks', 'PA0018', 1, 2, 0, 6, 0 ) 428 420 ELSE 429 WRITE ( message_string, * ) 'illegal value for data_', &430 ' output_masks : "', TRIM( do_mask(mid,i) ), '"'421 WRITE ( message_string, * ) 'illegal value for data_', & 422 ' output_masks : "', TRIM( do_mask(mid,i) ), '"' 431 423 CALL message( 'init_masks', 'PA0330', 1, 2, 0, 6, 0 ) 432 424 ENDIF … … 471 463 ELSE 472 464 ! 473 !-- Set vertical mask locations and size in case of terrain-following 474 !-- output 465 !-- Set vertical mask locations and size in case of terrain-following output 475 466 count = 0 476 467 DO WHILE ( mask_k_over_surface(mid, count+1) >= 0 ) 477 468 m = mask_k_over_surface(mid, count+1) 478 469 IF ( m > nz+1 ) THEN 479 WRITE ( message_string, '(I3,A,I3,A,I1,3A,I3)' ) &480 m,' in mask ',mid,' along dimension ', 3,&481 ' exceeds (nz+1) = ',nz+1470 WRITE ( message_string, '(I3,A,I3,A,I1,3A,I3)' ) m, ' in mask ', mid, & 471 ' along dimension ', 3, & 472 ' exceeds (nz+1) = ', nz+1 482 473 CALL message( 'init_masks', 'PA0331', 1, 2, 0, 6, 0 ) 483 474 ENDIF … … 491 482 ENDIF 492 483 ! 493 !-- Set global masks along all three dimensions (required by 494 !-- define_netcdf_header). 484 !-- Set global masks along all three dimensions (required by define_netcdf_header). 495 485 #if defined( __parallel ) 496 486 ! 497 !-- PE0 receives partial arrays from all processors of the respective mask 498 !-- a nd outputs them. Here a barrier has to be set, because otherwise499 !-- "-MPI- FATAL: Remote protocol queue full" mayoccur.487 !-- PE0 receives partial arrays from all processors of the respective mask and outputs them. Here 488 !-- a barrier has to be set, because otherwise "-MPI- FATAL: Remote protocol queue full" may 489 !-- occur. 500 490 501 491 CALL MPI_BARRIER( comm2d, ierr ) … … 519 509 !-- Receive index limits first, then arrays. 520 510 !-- Index limits are received in arbitrary order from the PEs. 521 CALL MPI_RECV( ind(1), 6, MPI_INTEGER, MPI_ANY_SOURCE, 0, & 522 comm2d, status, ierr ) 511 CALL MPI_RECV( ind(1), 6, MPI_INTEGER, MPI_ANY_SOURCE, 0, comm2d, status, ierr ) 523 512 ! 524 513 !-- Not all PEs have data for the mask. 525 514 IF ( ind(1) /= -9999 ) THEN 526 515 sender = status(MPI_SOURCE) 527 CALL MPI_RECV( tmp_array(ind(1)), ind(2)-ind(1)+1, &528 MPI_INTEGER, sender, 1, comm2d,status, ierr )516 CALL MPI_RECV( tmp_array(ind(1)), ind(2)-ind(1)+1, MPI_INTEGER, sender, 1, comm2d, & 517 status, ierr ) 529 518 mask_i_global(mid,ind(1):ind(2)) = tmp_array(ind(1):ind(2)) 530 CALL MPI_RECV( tmp_array(ind(3)), ind(4)-ind(3)+1, &531 MPI_INTEGER, sender, 2, comm2d,status, ierr )519 CALL MPI_RECV( tmp_array(ind(3)), ind(4)-ind(3)+1, MPI_INTEGER, sender, 2, comm2d, & 520 status, ierr ) 532 521 mask_j_global(mid,ind(3):ind(4)) = tmp_array(ind(3):ind(4)) 533 CALL MPI_RECV( tmp_array(ind(5)), ind(6)-ind(5)+1, &534 MPI_INTEGER, sender, 3, comm2d,status, ierr )522 CALL MPI_RECV( tmp_array(ind(5)), ind(6)-ind(5)+1, MPI_INTEGER, sender, 3, comm2d, & 523 status, ierr ) 535 524 mask_k_global(mid,ind(5):ind(6)) = tmp_array(ind(5):ind(6)) 536 525 ENDIF … … 539 528 ELSE 540 529 ! 541 !-- If at least part of the mask resides on the PE, send the index limits 542 !-- for the targetarray, otherwise send -9999 to PE0.543 IF ( mask_size_l(mid,1) > 0 .AND. mask_size_l(mid,2) > 0 .AND. &530 !-- If at least part of the mask resides on the PE, send the index limits for the target 531 !-- array, otherwise send -9999 to PE0. 532 IF ( mask_size_l(mid,1) > 0 .AND. mask_size_l(mid,2) > 0 .AND. & 544 533 mask_size_l(mid,3) > 0 ) THEN 545 534 ind(1) = mask_start_l(mid,1) … … 559 548 IF ( ind(1) /= -9999 ) THEN 560 549 tmp_array(:mask_size_l(mid,1)) = mask_i(mid,:mask_size_l(mid,1)) 561 CALL MPI_SEND( tmp_array(1), mask_size_l(mid,1), & 562 MPI_INTEGER, 0, 1, comm2d, ierr ) 550 CALL MPI_SEND( tmp_array(1), mask_size_l(mid,1), MPI_INTEGER, 0, 1, comm2d, ierr ) 563 551 tmp_array(:mask_size_l(mid,2)) = mask_j(mid,:mask_size_l(mid,2)) 564 CALL MPI_SEND( tmp_array(1), mask_size_l(mid,2), & 565 MPI_INTEGER, 0, 2, comm2d, ierr ) 552 CALL MPI_SEND( tmp_array(1), mask_size_l(mid,2), MPI_INTEGER, 0, 2, comm2d, ierr ) 566 553 tmp_array(:mask_size_l(mid,3)) = mask_k(mid,:mask_size_l(mid,3)) 567 CALL MPI_SEND( tmp_array(1), mask_size_l(mid,3), & 568 MPI_INTEGER, 0, 3, comm2d, ierr ) 554 CALL MPI_SEND( tmp_array(1), mask_size_l(mid,3), MPI_INTEGER, 0, 3, comm2d, ierr ) 569 555 ENDIF 570 556 ENDIF 571 557 ! 572 !-- A barrier has to be set, because otherwise some PEs may proceed too fast 573 !-- so that PE0 mayreceive wrong data on tag 0.558 !-- A barrier has to be set, because otherwise some PEs may proceed too fast so that PE0 may 559 !-- receive wrong data on tag 0. 574 560 CALL MPI_BARRIER( comm2d, ierr ) 575 561 576 562 IF ( netcdf_data_format > 4 ) THEN 577 578 CALL MPI_BCAST( mask_i_global(mid,:), nx+2, MPI_INTEGER, 0, comm2d, & 579 ierr ) 580 CALL MPI_BCAST( mask_j_global(mid,:), ny+2, MPI_INTEGER, 0, comm2d, & 581 ierr ) 582 CALL MPI_BCAST( mask_k_global(mid,:), nz+2, MPI_INTEGER, 0, comm2d, & 583 ierr ) 584 563 564 CALL MPI_BCAST( mask_i_global(mid,:), nx+2, MPI_INTEGER, 0, comm2d, ierr ) 565 CALL MPI_BCAST( mask_j_global(mid,:), ny+2, MPI_INTEGER, 0, comm2d, ierr ) 566 CALL MPI_BCAST( mask_k_global(mid,:), nz+2, MPI_INTEGER, 0, comm2d, ierr ) 567 585 568 ENDIF 586 569 … … 596 579 DEALLOCATE( tmp_array ) 597 580 ! 598 !-- Internal mask arrays cannot be deallocated on PE 0 because they are 599 !-- required for header outputon PE 0.581 !-- Internal mask arrays cannot be deallocated on PE 0 because they are required for header output 582 !-- on PE 0. 600 583 IF ( myid /= 0 ) DEALLOCATE( mask, mask_loop ) 601 584 602 585 CONTAINS 603 586 604 !------------------------------------------------------------------------------ !587 !--------------------------------------------------------------------------------------------------! 605 588 ! Description: 606 589 ! ------------ 607 590 !> Set local mask for each subdomain along 'dim' direction. 608 !------------------------------------------------------------------------------! 609 SUBROUTINE set_mask_locations( dim, dxyz, dxyz_string, nxyz, nxyz_string, & 610 lb, ub ) 591 !--------------------------------------------------------------------------------------------------! 592 SUBROUTINE set_mask_locations( dim, dxyz, dxyz_string, nxyz, nxyz_string, lb, ub ) 611 593 612 594 IMPLICIT NONE … … 614 596 CHARACTER (LEN=2) :: dxyz_string !< 615 597 CHARACTER (LEN=2) :: nxyz_string !< 616 598 617 599 INTEGER(iwp) :: count !< 618 600 INTEGER(iwp) :: count_l !< … … 625 607 INTEGER(iwp) :: nxyz !< 626 608 INTEGER(iwp) :: ub !< 627 609 628 610 REAL(wp) :: dxyz !< 629 611 REAL(wp) :: ddxyz !< … … 631 613 REAL(wp) :: tmp2 !< 632 614 633 count = 0; count_l = 0 634 ddxyz = 1.0_wp / dxyz 615 count = 0; count_l = 0 616 ddxyz = 1.0_wp / dxyz 635 617 tmp1 = 0.0_wp 636 618 tmp2 = 0.0_wp … … 638 620 IF ( mask(mid,dim,1) >= 0.0_wp ) THEN 639 621 ! 640 !-- use predefined mask_* array622 !-- Use predefined mask_* array 641 623 DO WHILE ( mask(mid,dim,count+1) >= 0.0_wp ) 642 624 count = count + 1 643 IF ( dim == 1 .OR.dim == 2 ) THEN625 IF ( dim == 1 .OR. dim == 2 ) THEN 644 626 m = NINT( mask(mid,dim,count) * mask_scale(dim) * ddxyz - 0.5_wp ) 645 627 IF ( m < 0 ) m = 0 ! avoid negative values … … 650 632 ENDIF 651 633 IF ( m > (nxyz+1) ) THEN 652 WRITE ( message_string, '(I3,A,I3,A,I1,3A,I3)' ) & 653 m,' in mask ',mid,' along dimension ',dim, & 654 ' exceeds (',nxyz_string,'+1) = ',nxyz+1 634 WRITE ( message_string, '(I3,A,I3,A,I1,3A,I3)' ) m, ' in mask ', mid, & 635 ' along dimension ' ,dim, & 636 ' exceeds (' ,nxyz_string, & 637 '+1) = ', nxyz+1 655 638 CALL message( 'init_masks', 'PA0331', 1, 2, 0, 6, 0 ) 656 639 ENDIF 657 IF ( ( m >= lb .AND. m <= ub ) .OR. & 658 ( m == (nxyz+1) .AND. ub == nxyz ) ) THEN 640 IF ( ( m >= lb .AND. m <= ub ) .OR. ( m == (nxyz+1) .AND. ub == nxyz ) ) THEN 659 641 IF ( count_l == 0 ) mask_start_l(mid,dim) = count 660 642 count_l = count_l + 1 … … 674 656 ELSE 675 657 ! 676 !-- use predefined mask_loop_* array, or use the default (all grid points677 !-- along thisdirection)658 !-- Use predefined mask_loop_* array, or use the default (all grid points along this 659 !-- direction) 678 660 IF ( mask_loop(mid,dim,1) < 0.0_wp ) THEN 679 661 tmp1 = mask_loop(mid,dim,1) … … 687 669 IF ( MAXVAL( mask_loop(mid,dim,1:2) ) & 688 670 > (nxyz+1) * dxyz / mask_scale(dim) ) THEN 689 WRITE ( message_string, '(2(A,I3,A,I1,A,F9.3),5A,I1,A,F9.3)' ) & 690 'mask_loop(',mid,',',dim,',1)=',mask_loop(mid,dim,1), & 691 ' and/or mask_loop(',mid,',',dim,',2)=', & 692 mask_loop(mid,dim,2),' exceed (', & 693 nxyz_string,'+1)*',dxyz_string,'/mask_scale(',dim,')=', & 671 WRITE ( message_string, '(2(A,I3,A,I1,A,F9.3),5A,I1,A,F9.3)' ) & 672 'mask_loop(', mid, ',', dim, ',1)=', mask_loop(mid,dim,1), & 673 ' and/or mask_loop(', mid, ',', dim, ',2)=', mask_loop(mid,dim,2), & 674 ' exceed (', nxyz_string,'+1)*',dxyz_string,'/mask_scale(',dim,')=', & 694 675 (nxyz+1)*dxyz/mask_scale(dim) 695 676 CALL message( 'init_masks', 'PA0332', 1, 2, 0, 6, 0 ) 696 677 ENDIF 697 loop_begin = NINT( mask_loop(mid,dim,1) * mask_scale(dim) & 698 * ddxyz - 0.5_wp ) 699 loop_end = NINT( mask_loop(mid,dim,2) * mask_scale(dim) & 700 * ddxyz - 0.5_wp ) 701 loop_stride = NINT( mask_loop(mid,dim,3) * mask_scale(dim) & 702 * ddxyz ) 678 loop_begin = NINT( mask_loop(mid,dim,1) * mask_scale(dim) * ddxyz - 0.5_wp ) 679 loop_end = NINT( mask_loop(mid,dim,2) * mask_scale(dim) * ddxyz - 0.5_wp ) 680 loop_stride = NINT( mask_loop(mid,dim,3) * mask_scale(dim) * ddxyz ) 703 681 IF ( loop_begin == -1 ) loop_begin = 0 ! avoid negative values 704 682 ELSEIF ( dim == 3 ) THEN … … 707 685 mask_loop(mid,dim,2) = zu(nz+1) / mask_scale(dim) ! (default) 708 686 ENDIF 709 IF ( MAXVAL( mask_loop(mid,dim,1:2) ) & 710 > zu(nz+1) / mask_scale(dim) ) THEN 711 WRITE ( message_string, '(2(A,I3,A,I1,A,F9.3),A,I1,A,F9.3)' ) & 712 'mask_loop(',mid,',',dim,',1)=',mask_loop(mid,dim,1), & 713 ' and/or mask_loop(',mid,',',dim,',2)=', & 714 mask_loop(mid,dim,2),' exceed zu(nz+1)/mask_scale(',dim, & 715 ')=',zu(nz+1)/mask_scale(dim) 687 IF ( MAXVAL( mask_loop(mid,dim,1:2) ) > zu(nz+1) / mask_scale(dim) ) THEN 688 WRITE ( message_string, '(2(A,I3,A,I1,A,F9.3),A,I1,A,F9.3)' ) & 689 'mask_loop(', mid, ',', dim, ',1)=', mask_loop(mid,dim,1), & 690 ' and/or mask_loop(', mid, ',', dim, ',2)=', mask_loop(mid,dim,2), & 691 ' exceed zu(nz+1)/mask_scale(', dim, ')=',zu(nz+1)/mask_scale(dim) 716 692 CALL message( 'init_masks', 'PA0333', 1, 2, 0, 6, 0 ) 717 693 ENDIF 718 ind_array = & 719 MINLOC( ABS( mask_loop(mid,dim,1) * mask_scale(dim) - zu ) ) 720 loop_begin = & 721 ind_array(1) - 1 + nzb ! MINLOC uses lower array bound 1 722 ind_array = & 723 MINLOC( ABS( mask_loop(mid,dim,2) * mask_scale(dim) - zu ) ) 724 loop_end = ind_array(1) - 1 + nzb ! MINLOC uses lower array bound 1 725 ! 726 !-- The following line assumes a constant vertical grid spacing within 727 !-- the vertical mask range; it fails for vertical grid stretching. 728 !-- Maybe revise later. Issue warning but continue execution. ABS(...) 729 !-- within the IF statement is necessary because the default value of 730 !-- dz_stretch_level_start is -9999999.9_wp. 694 ind_array = MINLOC( ABS( mask_loop(mid,dim,1) * mask_scale(dim) - zu ) ) 695 loop_begin = ind_array(1) - 1 + nzb ! MINLOC uses lower array bound 1 696 ind_array = MINLOC( ABS( mask_loop(mid,dim,2) * mask_scale(dim) - zu ) ) 697 loop_end = ind_array(1) - 1 + nzb ! MINLOC uses lower array bound 1 698 ! 699 !-- The following line assumes a constant vertical grid spacing within the vertical mask 700 !-- range; it fails for vertical grid stretching. 701 !-- Maybe revise later. Issue warning but continue execution. ABS(...) within the IF 702 !-- statement is necessary because the default value of dz_stretch_level_start is 703 !-- -9999999.9_wp. 731 704 loop_stride = NINT( mask_loop(mid,dim,3) * mask_scale(dim) * ddxyz ) 732 705 733 IF ( mask_loop(mid,dim,2) * mask_scale(dim) > & 734 ABS( dz_stretch_level_start(1) ) ) THEN 735 WRITE ( message_string, '(A,I3,A,I1,A,F9.3,A,F8.2,3A)' ) & 736 'mask_loop(',mid,',',dim,',2)=', mask_loop(mid,dim,2), & 737 ' exceeds dz_stretch_level=',dz_stretch_level_start(1), & 738 '.&Vertical mask locations will not ', & 739 'match the desired heights within the stretching ', & 740 'region.' 706 IF ( mask_loop(mid,dim,2) * mask_scale(dim) > ABS( dz_stretch_level_start(1) ) ) THEN 707 WRITE ( message_string, '(A,I3,A,I1,A,F9.3,A,F8.2,3A)' ) & 708 'mask_loop(', mid, ',', dim, ',2)=', mask_loop(mid,dim,2), & 709 ' exceeds dz_stretch_level=', dz_stretch_level_start(1), & 710 '.&Vertical mask locations will not ', & 711 'match the desired heights within the stretching ', 'region.' 741 712 CALL message( 'init_masks', 'PA0334', 0, 1, 0, 6, 0 ) 742 713 ENDIF … … 748 719 IF ( tmp2 < 0.0_wp ) mask_loop(mid,dim,2) = tmp2 749 720 ! 750 !-- The default stride +/-1 (every grid point) applies if 751 !-- mask_loop(mid,dim,3) is notspecified (its default is zero).721 !-- The default stride +/-1 (every grid point) applies if mask_loop(mid,dim,3) is not 722 !-- specified (its default is zero). 752 723 IF ( loop_stride == 0 ) THEN 753 724 IF ( loop_end >= loop_begin ) THEN … … 759 730 DO m = loop_begin, loop_end, loop_stride 760 731 count = count + 1 761 IF ( ( m >= lb .AND. m <= ub ) .OR. & 762 ( m == (nxyz+1) .AND. ub == nxyz ) ) THEN 732 IF ( ( m >= lb .AND. m <= ub ) .OR. ( m == (nxyz+1) .AND. ub == nxyz ) ) THEN 763 733 IF ( count_l == 0 ) mask_start_l(mid,dim) = count 764 734 count_l = count_l + 1 -
TabularUnified palm/trunk/SOURCE/init_pegrid.f90 ¶
r4564 r4648 1 1 !> @file init_pegrid.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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 !------------------------------------------------------------------------------! 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 8 ! 9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 12 ! 13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 19 15 ! 20 16 ! Current revisions: 21 17 ! ------------------ 22 ! 23 ! 18 ! 19 ! 24 20 ! Former revisions: 25 21 ! ----------------- 26 22 ! $Id$ 23 ! file re-formatted to follow the PALM coding standard 24 ! 25 ! 4564 2020-06-12 14:03:36Z raasch 27 26 ! Vertical nesting method of Huq et al. (2019) removed 28 ! 27 ! 29 28 ! 4461 2020-03-12 16:51:59Z raasch 30 29 ! communicator configurations for four virtual pe grids defined 31 ! 30 ! 32 31 ! 4444 2020-03-05 15:59:50Z raasch 33 32 ! bugfix: cpp-directives for serial mode added 34 ! 33 ! 35 34 ! 4360 2020-01-07 11:25:50Z suehring 36 35 ! changed message PA0467 37 ! 36 ! 38 37 ! 4264 2019-10-15 16:00:23Z scharf 39 38 ! corrected error message string 40 ! 39 ! 41 40 ! 4241 2019-09-27 06:32:47Z raasch 42 ! Check added to ensure that subdomain grid has at least the size as given by the number 43 ! of ghostpoints44 ! 41 ! Check added to ensure that subdomain grid has at least the size as given by the number of ghost 42 ! points 43 ! 45 44 ! 4182 2019-08-22 15:20:23Z scharf 46 45 ! Corrected "Former revisions" section 47 ! 46 ! 48 47 ! 4045 2019-06-21 10:58:47Z raasch 49 ! bugfix: kind attribute added to nint function to allow for large integers which may appear in 50 ! caseof default recycling width and small grid spacings51 ! 48 ! bugfix: kind attribute added to nint function to allow for large integers which may appear in case 49 ! of default recycling width and small grid spacings 50 ! 52 51 ! 3999 2019-05-23 16:09:37Z suehring 53 52 ! Spend 3 ghost points also in case of pw-scheme when nesting is applied 54 ! 53 ! 55 54 ! 3897 2019-04-15 11:51:14Z suehring 56 55 ! Minor revision of multigrid check; give warning instead of an abort. 57 ! 56 ! 58 57 ! 3890 2019-04-12 15:59:20Z suehring 59 ! Check if grid coarsening is possible on subdomain, in order to avoid that 60 ! multigrid approacheffectively reduces to a Gauss-Seidel scheme.61 ! 58 ! Check if grid coarsening is possible on subdomain, in order to avoid that multigrid approach 59 ! effectively reduces to a Gauss-Seidel scheme. 60 ! 62 61 ! 3885 2019-04-11 11:29:34Z kanani 63 ! Changes related to global restructuring of location messages and introduction 64 ! of additional debugmessages65 ! 62 ! Changes related to global restructuring of location messages and introduction of additional debug 63 ! messages 64 ! 66 65 ! 3884 2019-04-10 13:31:55Z Giersch 67 66 ! id_recycling is only calculated in case of tubulent inflow 68 ! 67 ! 69 68 ! 3761 2019-02-25 15:31:42Z raasch 70 69 ! unused variable removed 71 ! 70 ! 72 71 ! 3655 2019-01-07 16:51:22Z knoop 73 72 ! variables documented … … 79 78 ! Description: 80 79 ! ------------ 81 !> Determination of the virtual processor topology (if not prescribed by the 82 !> user)and computation of the grid point number and array bounds of the local 83 !> domains. 84 !> @todo: remove MPI-data types for 2D exchange on coarse multigrid level (not 85 !> used any more) 86 !------------------------------------------------------------------------------! 80 !> Determination of the virtual processor topology (if not prescribed by the user) and computation 81 !> of the grid point number and array bounds of the local domains. 82 !> @todo: remove MPI-data types for 2D exchange on coarse multigrid level (not used any more) 83 !--------------------------------------------------------------------------------------------------! 87 84 SUBROUTINE init_pegrid 88 89 90 USE control_parameters, & 91 ONLY: bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r, bc_dirichlet_s, & 92 bc_lr, bc_ns, bc_radiation_l, bc_radiation_n, bc_radiation_r, & 93 bc_radiation_s, & 94 grid_level, grid_level_count, maximum_grid_level, & 95 message_string, mg_switch_to_pe0_level, & 96 psolver 85 86 87 USE control_parameters, & 88 ONLY: bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r, bc_dirichlet_s, bc_lr, bc_ns, & 89 bc_radiation_l, bc_radiation_n, bc_radiation_r, bc_radiation_s, grid_level, & 90 grid_level_count, maximum_grid_level, message_string, mg_switch_to_pe0_level, psolver 97 91 98 92 99 93 #if defined( __parallel ) 100 USE control_parameters, &101 ONLY: coupling_mode, coupling_topology, gathered_size, momentum_advec, &102 outflow_source_plane, recycling_width, scalar_advec, subdomain_size, &94 USE control_parameters, & 95 ONLY: coupling_mode, coupling_topology, gathered_size, momentum_advec, & 96 outflow_source_plane, recycling_width, scalar_advec, subdomain_size, & 103 97 turbulent_inflow, turbulent_outflow, y_shift 104 98 105 USE grid_variables, &99 USE grid_variables, & 106 100 ONLY: dx 107 101 #endif 108 109 USE indices, & 110 ONLY: nnx, nny, nnz, nx, nxl, nxl_mg, & 111 nxlu, nxr, nxr_mg, ny, nyn, nyn_mg, nys, nys_mg, & 112 nysv, nz, nzb, nzt, nzt_mg, wall_flags_1, wall_flags_2, & 113 wall_flags_3, wall_flags_4, wall_flags_5, wall_flags_6, & 114 wall_flags_7, wall_flags_8, wall_flags_9, wall_flags_10 102 103 USE indices, & 104 ONLY: nnx, nny, nnz, nx, nxl, nxl_mg, nxlu, nxr, nxr_mg, ny, nyn, nyn_mg, nys, nys_mg, & 105 nysv, nz, nzb, nzt, nzt_mg, wall_flags_1, wall_flags_2, wall_flags_3, wall_flags_4, & 106 wall_flags_5, wall_flags_6, wall_flags_7, wall_flags_8, wall_flags_9, wall_flags_10 115 107 116 108 #if defined( __parallel ) 117 USE indices, &109 USE indices, & 118 110 ONLY: mg_loc_ind, nbgp, nx_a, nx_o, ny_a, ny_o 119 111 #endif 120 112 121 113 USE kinds 122 114 123 115 USE pegrid 124 116 125 117 #if defined( __parallel ) 126 USE pmc_interface, &118 USE pmc_interface, & 127 119 ONLY: nested_run 128 120 129 USE spectra_mod, &121 USE spectra_mod, & 130 122 ONLY: calculate_spectra 131 123 132 USE synthetic_turbulence_generator_mod, & 133 ONLY: id_stg_left, id_stg_north, id_stg_right, id_stg_south, & 134 use_syn_turb_gen 124 USE synthetic_turbulence_generator_mod, & 125 ONLY: id_stg_left, id_stg_north, id_stg_right, id_stg_south, use_syn_turb_gen 135 126 #endif 136 127 137 USE transpose_indices, & 138 ONLY: nxl_y, nxl_z, nxr_y, nxr_z, nyn_x, nyn_z, nys_x,& 139 nys_z, nzb_x, nzb_y, nzt_x, nzt_y 128 USE transpose_indices, & 129 ONLY: nxl_y, nxl_z, nxr_y, nxr_z, nyn_x, nyn_z, nys_x, nys_z, nzb_x, nzb_y, nzt_x, nzt_y 140 130 141 131 #if defined( __parallel ) 142 USE transpose_indices, &132 USE transpose_indices, & 143 133 ONLY: nxl_yd, nxr_yd, nzb_yd, nzt_yd 144 134 #endif … … 152 142 INTEGER(iwp) :: id_outflow_source_l !< local value of id_outflow_source 153 143 INTEGER(iwp) :: id_recycling_l !< ID indicating processors located at the recycling plane 154 INTEGER(iwp) :: id_stg_left_l !< left lateral boundary local core id in case of turbulence generator 155 INTEGER(iwp) :: id_stg_north_l !< north lateral boundary local core id in case of turbulence generator 156 INTEGER(iwp) :: id_stg_right_l !< right lateral boundary local core id in case of turbulence generator 157 INTEGER(iwp) :: id_stg_south_l !< south lateral boundary local core id in case of turbulence generator 144 INTEGER(iwp) :: id_stg_left_l !< left lateral boundary local core id in case of turbulence generator 145 INTEGER(iwp) :: id_stg_north_l !< north lateral boundary local core id in case of turbulence generator 146 INTEGER(iwp) :: id_stg_right_l !< right lateral boundary local core id in case of turbulence generator 147 INTEGER(iwp) :: id_stg_south_l !< south lateral boundary local core id in case of turbulence generator 158 148 INTEGER(iwp) :: ind(5) !< array containing the subdomain bounds 159 149 #endif … … 222 212 223 213 ! 224 !-- Prescribed by user. Number of processors on the prescribed topology 225 !-- must be equal to thenumber of PEs available to the job214 !-- Prescribed by user. Number of processors on the prescribed topology must be equal to the 215 !-- number of PEs available to the job 226 216 IF ( ( npex * npey ) /= numprocs ) THEN 227 WRITE( message_string, * ) 'number of PEs of the prescribed ', 228 'topology (', npex*npey,') does not match & the number of ',&229 'PEs available to the job (', numprocs, ')'217 WRITE( message_string, * ) 'number of PEs of the prescribed ', 'topology (', npex*npey, & 218 ') does not match & the number of ', & 219 'PEs available to the job (', numprocs, ')' 230 220 CALL message( 'init_pegrid', 'PA0221', 1, 2, 0, 6, 0 ) 231 221 ENDIF … … 237 227 !-- If the processor topology is prescribed by the user, the number of 238 228 !-- PEs must be given in both directions 239 message_string = 'if the processor topology is prescribed by th' // &240 'e user & both values of "npex" and "npey" must be given' //&241 ' in the &NAMELIST-parameter file'229 message_string = 'if the processor topology is prescribed by th' // & 230 'e user & both values of "npex" and "npey" must be given' // & 231 ' in the &NAMELIST-parameter file' 242 232 CALL message( 'init_pegrid', 'PA0222', 1, 2, 0, 6, 0 ) 243 233 … … 245 235 246 236 ! 247 !-- Create four default MPI communicators for the 2d virtual PE grid. One of them will be used 248 !-- asthe main communicator for this run, while others might be used for specific quantities like237 !-- Create four default MPI communicators for the 2d virtual PE grid. One of them will be used as 238 !-- the main communicator for this run, while others might be used for specific quantities like 249 239 !-- aerosol, chemical species, or passive scalars), if their horizontal boundary conditions shall 250 240 !-- be different from those of the other quantities (e.g. non-cyclic conditions for aerosols, and … … 297 287 298 288 ! 299 !-- In case of cyclic boundary conditions, a y-shift at the boundaries in 300 !-- x-direction can be introduced via parameter y_shift. The shift is done 301 !-- by modifying the processor grid in such a way that processors located 302 !-- at the x-boundary communicate across it to processors with y-coordinate 303 !-- shifted by y_shift relative to their own. This feature can not be used 304 !-- in combination with an fft pressure solver. It has been implemented to 305 !-- counter the effect of streak structures in case of cyclic boundary 306 !-- conditions. For a description of these see Munters 289 !-- In case of cyclic boundary conditions, a y-shift at the boundaries in x-direction can be 290 !-- introduced via parameter y_shift. The shift is done by modifying the processor grid in such a 291 !-- way that processors located at the x-boundary communicate across it to processors with 292 !-- y-coordinate shifted by y_shift relative to their own. This feature can not be used in 293 !-- combination with an fft pressure solver. It has been implemented to counter the effect of streak 294 !-- structures in case of cyclic boundary conditions. For a description of these see Munters 307 295 !-- (2016; dx.doi.org/10.1063/1.4941912) 308 296 !-- … … 310 298 IF ( y_shift /= 0 ) THEN 311 299 IF ( bc_lr == 'cyclic' ) THEN 312 IF ( TRIM( psolver ) /= 'multigrid' .AND. & 313 TRIM( psolver ) /= 'multigrid_noopt') & 314 THEN 300 IF ( TRIM( psolver ) /= 'multigrid' .AND. TRIM( psolver ) /= 'multigrid_noopt') THEN 315 301 message_string = 'y_shift /= 0 requires a multigrid pressure solver ' 316 302 CALL message( 'check_parameters', 'PA0468', 1, 2, 0, 6, 0 ) … … 320 306 CALL MPI_CART_COORDS( comm2d, pleft, ndim, lcoord, ierr ) 321 307 322 ! 323 !-- If the x(y)-coordinate of the right (left) neighbor is smaller (greater) 324 !-- than that of the calling process, then the calling process is located on 325 !-- the right (left) boundary of the processor grid. In that case, 326 !-- the y-coordinate of that neighbor is increased (decreased) by y_shift. 327 !-- The rank of the process with that coordinate is then inquired and the 328 !-- neighbor rank for MPI_SENDRECV, pright (pleft) is set to it. 329 !-- In this way, the calling process receives a new right (left) neighbor 330 !-- for all future MPI_SENDRECV calls. That neighbor has a y-coordinate 331 !-- of y+(-)y_shift, where y is the original right (left) neighbor's 332 !-- y-coordinate. The modulo-operation ensures that if the neighbor's 333 !-- y-coordinate exceeds the grid-boundary, it will be relocated to 334 !-- the opposite part of the grid cyclicly. 335 IF ( rcoord(1) < pcoord(1) ) THEN 308 ! 309 !-- If the x(y)-coordinate of the right (left) neighbor is smaller (greater) than that of the 310 !-- calling process, then the calling process is located on the right (left) boundary of the 311 !-- processor grid. In that case, the y-coordinate of that neighbor is increased (decreased) 312 !-- by y_shift. 313 !-- The rank of the process with that coordinate is then inquired and the neighbor rank for 314 !-- MPI_SENDRECV, pright (pleft) is set to it. 315 !-- In this way, the calling process receives a new right (left) neighbor for all future 316 !-- MPI_SENDRECV calls. That neighbor has a y-coordinate of y+(-)y_shift, where y is the 317 !-- original right (left) neighbor's y-coordinate. The modulo-operation ensures that if the 318 !-- neighbor's y-coordinate exceeds the grid-boundary, it will be relocated to the opposite 319 !-- part of the grid cyclicly. 320 IF ( rcoord(1) < pcoord(1) ) THEN 336 321 rcoord(2) = MODULO( rcoord(2) + y_shift, pdims(2) ) 337 322 CALL MPI_CART_RANK( comm2d, rcoord, pright, ierr ) 338 323 ENDIF 339 324 340 IF ( lcoord(1) > pcoord(1) ) THEN325 IF ( lcoord(1) > pcoord(1) ) THEN 341 326 lcoord(2) = MODULO( lcoord(2) - y_shift, pdims(2) ) 342 327 CALL MPI_CART_RANK( comm2d, lcoord, pleft, ierr ) 343 328 ENDIF 344 329 345 330 ELSE 346 331 ! 347 !-- y-shift for non-cyclic boundary conditions is only implemented 332 !-- y-shift for non-cyclic boundary conditions is only implemented 348 333 !-- for the turbulence recycling method in inflow_turbulence.f90 349 334 IF ( .NOT. turbulent_inflow ) THEN 350 message_string = 'y_shift /= 0 is only allowed for cyclic ' // &351 'boundary conditions in both directions ' // &335 message_string = 'y_shift /= 0 is only allowed for cyclic ' // & 336 'boundary conditions in both directions ' // & 352 337 'or with turbulent_inflow == .TRUE.' 353 338 CALL message( 'check_parameters', 'PA0467', 1, 2, 0, 6, 0 ) … … 373 358 ! 374 359 !-- Calculate array bounds along x-direction for every PE. 375 ALLOCATE( nxlf(0:pdims(1)-1), nxrf(0:pdims(1)-1), nynf(0:pdims(2)-1), & 376 nysf(0:pdims(2)-1) ) 360 ALLOCATE( nxlf(0:pdims(1)-1), nxrf(0:pdims(1)-1), nynf(0:pdims(2)-1), nysf(0:pdims(2)-1) ) 377 361 378 362 IF ( MOD( nx+1 , pdims(1) ) /= 0 ) THEN 379 WRITE( message_string, * ) 'x-direction: gridpoint number (' ,nx+1,') ',&380 'is not an& integral multiple of the number', &381 ' of processors (', pdims(1),')'363 WRITE( message_string, * ) 'x-direction: gridpoint number (' ,nx+1, ') ', & 364 'is not an& integral multiple of the number', & 365 ' of processors (', pdims(1), ')' 382 366 CALL message( 'init_pegrid', 'PA0225', 1, 2, 0, 6, 0 ) 383 367 ELSE … … 395 379 !-- Calculate array bounds in y-direction for every PE. 396 380 IF ( MOD( ny+1 , pdims(2) ) /= 0 ) THEN 397 WRITE( message_string, * ) 'y-direction: gridpoint number (', ny+1,') ',&398 'is not an& integral multiple of the number', &399 ' of processors (', pdims(2),')'381 WRITE( message_string, * ) 'y-direction: gridpoint number (', ny+1, ') ', & 382 'is not an& integral multiple of the number', & 383 ' of processors (', pdims(2), ')' 400 384 CALL message( 'init_pegrid', 'PA0227', 1, 2, 0, 6, 0 ) 401 385 ELSE … … 421 405 422 406 ! 423 !-- Set switches to define if the PE is situated at the border of the virtual 424 !-- processor grid 407 !-- Set switches to define if the PE is situated at the border of the virtual processor grid 425 408 IF ( nxl == 0 ) left_border_pe = .TRUE. 426 409 IF ( nxr == nx ) right_border_pe = .TRUE. … … 429 412 430 413 ! 431 !-- Calculate array bounds and gridpoint numbers for the transposed arrays 432 !-- (needed in the pressuresolver)433 !-- For the transposed arrays, cyclic boundaries as well as top and bottom 434 !-- b oundaries are omitted, because they are obstructive to the transposition414 !-- Calculate array bounds and gridpoint numbers for the transposed arrays (needed in the pressure 415 !-- solver) 416 !-- For the transposed arrays, cyclic boundaries as well as top and bottom boundaries are omitted, 417 !-- because they are obstructive to the transposition 435 418 436 419 ! … … 441 424 IF ( pdims(2) /= 1 ) THEN 442 425 IF ( MOD( nz , pdims(1) ) /= 0 ) THEN 443 WRITE( message_string, * ) 'transposition z --> x:& ', &444 'nz=', nz,' is not an integral multiple ',&445 'of pdims(1)=', pdims(1)426 WRITE( message_string, * ) 'transposition z --> x:& ', & 427 'nz=', nz, ' is not an integral multiple ', & 428 'of pdims(1)=', pdims(1) 446 429 CALL message( 'init_pegrid', 'PA0230', 1, 2, 0, 6, 0 ) 447 430 ENDIF … … 463 446 !-- 2. transposition x --> y 464 447 IF ( MOD( nx+1 , pdims(2) ) /= 0 ) THEN 465 WRITE( message_string, * ) 'transposition x --> y:& ', &466 'nx+1=', nx+1,' is not an integral ',&467 'multiple of pdims(2)=', pdims(2)448 WRITE( message_string, * ) 'transposition x --> y:& ', & 449 'nx+1=', nx+1, ' is not an integral ', & 450 'multiple of pdims(2)=', pdims(2) 468 451 CALL message( 'init_pegrid', 'PA0231', 1, 2, 0, 6, 0 ) 469 452 ENDIF … … 492 475 !-- along x, except that the uptream-spline method is switched on 493 476 IF ( MOD( ny+1 , pdims(1) ) /= 0 ) THEN 494 WRITE( message_string, * ) 'transposition y --> z:& ', &495 'ny+1=', ny+1,' is not an integral ',&496 'multiple of pdims(1)=', pdims(1)477 WRITE( message_string, * ) 'transposition y --> z:& ', & 478 'ny+1=', ny+1, ' is not an integral ', & 479 'multiple of pdims(1)=', pdims(1) 497 480 CALL message( 'init_pegrid', 'PA0232', 1, 2, 0, 6, 0 ) 498 481 ENDIF … … 503 486 !-- This condition must be fulfilled for a 1D-decomposition along x 504 487 IF ( MOD( ny+1 , pdims(1) ) /= 0 ) THEN 505 WRITE( message_string, * ) 'transposition x --> y:& ', &506 'ny+1=', ny+1,' is not an integral ',&507 'multiple of pdims(1)=', pdims(1)488 WRITE( message_string, * ) 'transposition x --> y:& ', & 489 'ny+1=', ny+1, ' is not an integral ', & 490 'multiple of pdims(1)=', pdims(1) 508 491 CALL message( 'init_pegrid', 'PA0233', 1, 2, 0, 6, 0 ) 509 492 ENDIF … … 517 500 IF ( calculate_spectra ) THEN 518 501 IF ( MOD( nz, pdims(2) ) /= 0 ) THEN 519 WRITE( message_string, * ) 'direct transposition z --> y (needed ', &520 'for spectra):& nz=', nz,' is not an ',&521 'integral multiple of pdims(2)=', pdims(2)502 WRITE( message_string, * ) 'direct transposition z --> y (needed ', & 503 'for spectra):& nz=', nz, ' is not an ', & 504 'integral multiple of pdims(2)=', pdims(2) 522 505 CALL message( 'init_pegrid', 'PA0234', 1, 2, 0, 6, 0 ) 523 506 ELSE … … 532 515 IF ( psolver == 'poisfft' .OR. calculate_spectra ) THEN 533 516 ! 534 !-- Indices for direct transpositions y --> x 517 !-- Indices for direct transpositions y --> x 535 518 !-- (they are only possible in case of a 1d-decomposition along x) 536 519 IF ( pdims(2) == 1 ) THEN … … 547 530 IF ( psolver == 'poisfft' ) THEN 548 531 ! 549 !-- Indices for direct transpositions x --> y 532 !-- Indices for direct transpositions x --> y 550 533 !-- (they are only possible in case of a 1d-decomposition along y) 551 534 IF ( pdims(1) == 1 ) THEN … … 579 562 !-- Receive data from all other PEs 580 563 DO i = 1, numprocs-1 581 CALL MPI_RECV( ibuf, 4, MPI_INTEGER, i, MPI_ANY_TAG, comm2d, status, & 582 ierr ) 564 CALL MPI_RECV( ibuf, 4, MPI_INTEGER, i, MPI_ANY_TAG, comm2d, status, ierr ) 583 565 hor_index_bounds(:,i) = ibuf(1:4) 584 566 ENDDO … … 602 584 PRINT*, '*** processor topology ***' 603 585 PRINT*, ' ' 604 PRINT*, 'myid pcoord left right south north idx idy nxl: nxr',& 605 &' nys: nyn' 606 PRINT*, '------------------------------------------------------------',& 607 &'-----------' 608 WRITE (*,1000) 0, pcoord(1), pcoord(2), pleft, pright, psouth, pnorth, & 609 myidx, myidy, nxl, nxr, nys, nyn 610 1000 FORMAT (I4,2X,'(',I3,',',I3,')',3X,I4,2X,I4,3X,I4,2X,I4,2X,I3,1X,I3, & 611 2(2X,I4,':',I4)) 586 PRINT*, 'myid pcoord left right south north idx idy nxl: nxr',' nys: nyn' 587 PRINT*, '------------------------------------------------------------','-----------' 588 WRITE (*,1000) 0, pcoord(1), pcoord(2), pleft, pright, psouth, pnorth, myidx, myidy, nxl, & 589 nxr, nys, nyn 590 1000 FORMAT (I4,2X,'(',I3,',',I3,')',3X,I4,2X,I4,3X,I4,2X,I4,2X,I3,1X,I3,2(2X,I4,':',I4)) 612 591 613 592 ! 614 593 !-- Receive data from the other PEs 615 594 DO i = 1,numprocs-1 616 CALL MPI_RECV( ibuf, 12, MPI_INTEGER, i, MPI_ANY_TAG, comm2d, status, & 617 ierr ) 595 CALL MPI_RECV( ibuf, 12, MPI_INTEGER, i, MPI_ANY_TAG, comm2d, status, ierr ) 618 596 WRITE (*,1000) i, ( ibuf(j) , j = 1,12 ) 619 597 ENDDO … … 626 604 ibuf(8) = myidy; ibuf(9) = nxl; ibuf(10) = nxr; ibuf(11) = nys 627 605 ibuf(12) = nyn 628 CALL MPI_SEND( ibuf, 12, MPI_INTEGER, 0, myid, comm2d, ierr ) 606 CALL MPI_SEND( ibuf, 12, MPI_INTEGER, 0, myid, comm2d, ierr ) 629 607 ENDIF 630 608 #endif 631 609 632 ! 610 ! 633 611 !-- Determine the number of ghost point layers 634 IF ( scalar_advec == 'ws-scheme' .OR. &612 IF ( scalar_advec == 'ws-scheme' .OR. & 635 613 momentum_advec == 'ws-scheme' .OR. nested_run ) THEN 636 614 nbgp = 3 637 615 ELSE 638 616 nbgp = 1 639 ENDIF 640 641 ! 642 !-- Check that the number of computational grid points is not smaller than the number of 643 !-- ghostpoints.617 ENDIF 618 619 ! 620 !-- Check that the number of computational grid points is not smaller than the number of ghost 621 !-- points. 644 622 IF ( nnx < nbgp ) THEN 645 623 WRITE( message_string, * ) 'number of subdomain grid points along x (', nnx, ') is smaller',& … … 654 632 655 633 ! 656 !-- Create a new MPI derived datatype for the exchange of surface (xy) data, 657 !-- which is needed forcoupled atmosphere-ocean runs.634 !-- Create a new MPI derived datatype for the exchange of surface (xy) data, which is needed for 635 !-- coupled atmosphere-ocean runs. 658 636 !-- First, calculate number of grid points of an xy-plane. 659 637 ngp_xy = ( nxr - nxl + 1 + 2 * nbgp ) * ( nyn - nys + 1 + 2 * nbgp ) … … 662 640 663 641 IF ( TRIM( coupling_mode ) /= 'uncoupled' ) THEN 664 642 665 643 ! 666 644 !-- Pass the number of grid points of the atmosphere model to … … 673 651 IF ( myid == 0 ) THEN 674 652 675 CALL MPI_SEND( nx_a, 1, MPI_INTEGER, numprocs, 1, comm_inter, & 676 ierr ) 677 CALL MPI_SEND( ny_a, 1, MPI_INTEGER, numprocs, 2, comm_inter, & 678 ierr ) 679 CALL MPI_SEND( pdims, 2, MPI_INTEGER, numprocs, 3, comm_inter, & 680 ierr ) 681 CALL MPI_RECV( nx_o, 1, MPI_INTEGER, numprocs, 4, comm_inter, & 682 status, ierr ) 683 CALL MPI_RECV( ny_o, 1, MPI_INTEGER, numprocs, 5, comm_inter, & 684 status, ierr ) 685 CALL MPI_RECV( pdims_remote, 2, MPI_INTEGER, numprocs, 6, & 686 comm_inter, status, ierr ) 653 CALL MPI_SEND( nx_a, 1, MPI_INTEGER, numprocs, 1, comm_inter, ierr ) 654 CALL MPI_SEND( ny_a, 1, MPI_INTEGER, numprocs, 2, comm_inter, ierr ) 655 CALL MPI_SEND( pdims, 2, MPI_INTEGER, numprocs, 3, comm_inter, ierr ) 656 CALL MPI_RECV( nx_o, 1, MPI_INTEGER, numprocs, 4, comm_inter, status, ierr ) 657 CALL MPI_RECV( ny_o, 1, MPI_INTEGER, numprocs, 5, comm_inter, status, ierr ) 658 CALL MPI_RECV( pdims_remote, 2, MPI_INTEGER, numprocs, 6, comm_inter, status, ierr ) 687 659 ENDIF 688 660 689 661 CALL MPI_BCAST( nx_o, 1, MPI_INTEGER, 0, comm2d, ierr ) 690 CALL MPI_BCAST( ny_o, 1, MPI_INTEGER, 0, comm2d, ierr ) 662 CALL MPI_BCAST( ny_o, 1, MPI_INTEGER, 0, comm2d, ierr ) 691 663 CALL MPI_BCAST( pdims_remote, 2, MPI_INTEGER, 0, comm2d, ierr ) 692 664 693 665 ELSEIF ( coupling_mode == 'ocean_to_atmosphere' ) THEN 694 666 695 667 nx_o = nx 696 ny_o = ny 697 698 IF ( myid == 0 ) THEN 699 700 CALL MPI_RECV( nx_a, 1, MPI_INTEGER, 0, 1, comm_inter, status, & 701 ierr ) 702 CALL MPI_RECV( ny_a, 1, MPI_INTEGER, 0, 2, comm_inter, status, & 703 ierr ) 704 CALL MPI_RECV( pdims_remote, 2, MPI_INTEGER, 0, 3, comm_inter, & 705 status, ierr ) 668 ny_o = ny 669 670 IF ( myid == 0 ) THEN 671 672 CALL MPI_RECV( nx_a, 1, MPI_INTEGER, 0, 1, comm_inter, status, ierr ) 673 CALL MPI_RECV( ny_a, 1, MPI_INTEGER, 0, 2, comm_inter, status, ierr ) 674 CALL MPI_RECV( pdims_remote, 2, MPI_INTEGER, 0, 3, comm_inter, status, ierr ) 706 675 CALL MPI_SEND( nx_o, 1, MPI_INTEGER, 0, 4, comm_inter, ierr ) 707 676 CALL MPI_SEND( ny_o, 1, MPI_INTEGER, 0, 5, comm_inter, ierr ) … … 710 679 711 680 CALL MPI_BCAST( nx_a, 1, MPI_INTEGER, 0, comm2d, ierr) 712 CALL MPI_BCAST( ny_a, 1, MPI_INTEGER, 0, comm2d, ierr) 713 CALL MPI_BCAST( pdims_remote, 2, MPI_INTEGER, 0, comm2d, ierr) 714 715 ENDIF 716 681 CALL MPI_BCAST( ny_a, 1, MPI_INTEGER, 0, comm2d, ierr) 682 CALL MPI_BCAST( pdims_remote, 2, MPI_INTEGER, 0, comm2d, ierr) 683 684 ENDIF 685 717 686 ngp_a = ( nx_a+1 + 2 * nbgp ) * ( ny_a+1 + 2 * nbgp ) 718 687 ngp_o = ( nx_o+1 + 2 * nbgp ) * ( ny_o+1 + 2 * nbgp ) 719 688 720 689 ! 721 !-- Determine if the horizontal grid and the number of PEs in ocean and 722 !-- atmosphere is same or not 723 IF ( nx_o == nx_a .AND. ny_o == ny_a .AND. & 724 pdims(1) == pdims_remote(1) .AND. pdims(2) == pdims_remote(2) ) & 725 THEN 690 !-- Determine if the horizontal grid and the number of PEs in ocean and atmosphere is same or not. 691 IF ( nx_o == nx_a .AND. ny_o == ny_a .AND. & 692 pdims(1) == pdims_remote(1) .AND. pdims(2) == pdims_remote(2) ) THEN 726 693 coupling_topology = 0 727 694 ELSE 728 695 coupling_topology = 1 729 ENDIF 730 731 ! 732 !-- Determine the target PEs for the exchange between ocean and 733 !-- atmosphere (comm2d) 696 ENDIF 697 698 ! 699 !-- Determine the target PEs for the exchange between ocean and atmosphere (comm2d) 734 700 IF ( coupling_topology == 0 ) THEN 735 701 ! 736 !-- In case of identical topologies, every atmosphere PE has exactly one 737 !-- ocean PE counterpartand vice versa738 IF ( TRIM( coupling_mode ) == 'atmosphere_to_ocean' ) THEN702 !-- In case of identical topologies, every atmosphere PE has exactly one ocean PE counterpart 703 !-- and vice versa 704 IF ( TRIM( coupling_mode ) == 'atmosphere_to_ocean' ) THEN 739 705 target_id = myid + numprocs 740 706 ELSE 741 target_id = myid 707 target_id = myid 742 708 ENDIF 743 709 744 710 ELSE 745 711 ! 746 !-- In case of nonequivalent topology in ocean and atmosphere only for 747 !-- PE0 in ocean and PE0 in atmosphere a target_id is needed, since 748 !-- data echxchange between ocean and atmosphere will be done only 749 !-- between these PEs. 712 !-- In case of nonequivalent topology in ocean and atmosphere only for PE0 in ocean and PE0 in 713 !-- atmosphere a target_id is needed, since data echxchange between ocean and atmosphere will 714 !-- be done only between these PEs. 750 715 IF ( myid == 0 ) THEN 751 716 752 717 IF ( TRIM( coupling_mode ) == 'atmosphere_to_ocean' ) THEN 753 target_id = numprocs 718 target_id = numprocs 754 719 ELSE 755 720 target_id = 0 … … 765 730 766 731 ! 767 !-- Array bounds when running on a single PE (respectively a non-parallel 768 !-- machine) 732 !-- Array bounds when running on a single PE (respectively a non-parallel machine) 769 733 nxl = 0 770 734 nxr = nx … … 784 748 785 749 ! 786 !-- Array bounds for the pressure solver (in the parallel code, these bounds 787 !-- are the ones for thetransposed arrays)750 !-- Array bounds for the pressure solver (in the parallel code, these bounds are the ones for the 751 !-- transposed arrays) 788 752 nys_x = nys 789 753 nyn_x = nyn … … 804 768 805 769 ! 806 !-- Calculate number of grid levels necessary for the multigrid poisson solver 807 !-- as well as thegridpoint indices on each level770 !-- Calculate number of grid levels necessary for the multigrid poisson solver as well as the 771 !-- gridpoint indices on each level 808 772 IF ( psolver(1:9) == 'multigrid' ) THEN 809 773 … … 833 797 ENDDO 834 798 ! 835 !-- The optimized MG-solver does not allow odd values for nz at the coarsest 836 !-- grid level 799 !-- The optimized MG-solver does not allow odd values for nz at the coarsest grid level 837 800 IF ( TRIM( psolver ) /= 'multigrid_noopt' ) THEN 838 801 IF ( MOD( k, 2 ) /= 0 ) mg_levels_z = mg_levels_z - 1 839 802 ! 840 !-- An odd value of nz does not work. The finest level must have an even 841 !-- value. 803 !-- An odd value of nz does not work. The finest level must have an even value. 842 804 IF ( mg_levels_z == 0 ) THEN 843 805 message_string = 'optimized multigrid method requires nz to be even' … … 847 809 848 810 maximum_grid_level = MIN( mg_levels_x, mg_levels_y, mg_levels_z ) 849 ! 850 !-- Check if subdomain sizes prevents any coarsening. 851 !-- This case, the maximum number of grid levels is 1, i.e. effectively 852 !-- a Gauss-Seidel scheme is applied rather than a multigrid approach.811 ! 812 !-- Check if subdomain sizes prevents any coarsening. 813 !-- This case, the maximum number of grid levels is 1, i.e. effectively a Gauss-Seidel scheme is 814 !-- applied rather than a multigrid approach. 853 815 !-- Give a warning in this case. 854 816 IF ( maximum_grid_level == 1 .AND. mg_switch_to_pe0_level == -1 ) THEN 855 message_string = 'No grid coarsening possible, multigrid ' // &856 'approach effectively reduces to a Gauss-Seidel ' // &817 message_string = 'No grid coarsening possible, multigrid ' // & 818 'approach effectively reduces to a Gauss-Seidel ' // & 857 819 'scheme.' 858 820 859 821 CALL message( 'poismg', 'PA0648', 0, 1, 0, 6, 0 ) 860 822 ENDIF 861 823 862 824 ! 863 !-- Find out, if the total domain allows more levels. These additional 864 !-- levels are identicallyprocessed on all PEs.825 !-- Find out, if the total domain allows more levels. These additional levels are identically 826 !-- processed on all PEs. 865 827 IF ( numprocs > 1 .AND. mg_switch_to_pe0_level /= -1 ) THEN 866 828 … … 887 849 888 850 IF ( maximum_grid_level_l > mg_switch_to_pe0_level_l ) THEN 889 mg_switch_to_pe0_level_l = maximum_grid_level_l - & 890 mg_switch_to_pe0_level_l + 1 851 mg_switch_to_pe0_level_l = maximum_grid_level_l - mg_switch_to_pe0_level_l + 1 891 852 ELSE 892 853 mg_switch_to_pe0_level_l = 0 … … 901 862 902 863 ! 903 !-- Use switch level calculated above only if it is not pre-defined 904 !-- by user 864 !-- Use switch level calculated above only if it is not pre-defined by user 905 865 IF ( mg_switch_to_pe0_level == 0 ) THEN 906 866 IF ( mg_switch_to_pe0_level_l /= 0 ) THEN … … 912 872 ! 913 873 !-- Check pre-defined value and reset to default, if neccessary 914 IF ( mg_switch_to_pe0_level < mg_switch_to_pe0_level_l .OR. &874 IF ( mg_switch_to_pe0_level < mg_switch_to_pe0_level_l .OR. & 915 875 mg_switch_to_pe0_level >= maximum_grid_level_l ) THEN 916 message_string = 'mg_switch_to_pe0_level ' // &876 message_string = 'mg_switch_to_pe0_level ' // & 917 877 'out of range and reset to 0' 918 878 CALL message( 'init_pegrid', 'PA0235', 0, 1, 0, 6, 0 ) … … 920 880 ELSE 921 881 ! 922 !-- Use the largest number of possible levels anyway and recalculate 923 !-- th e switch level to this largest number of possible values882 !-- Use the largest number of possible levels anyway and recalculate the switch level to 883 !-- this largest number of possible values 924 884 maximum_grid_level = maximum_grid_level_l 925 885 … … 930 890 ENDIF 931 891 932 ALLOCATE( grid_level_count(maximum_grid_level), &933 nxl_mg(0:maximum_grid_level), nxr_mg(0:maximum_grid_level), &934 nyn_mg(0:maximum_grid_level), nys_mg(0:maximum_grid_level), &892 ALLOCATE( grid_level_count(maximum_grid_level), & 893 nxl_mg(0:maximum_grid_level), nxr_mg(0:maximum_grid_level), & 894 nyn_mg(0:maximum_grid_level), nys_mg(0:maximum_grid_level), & 935 895 nzt_mg(0:maximum_grid_level) ) 936 896 937 897 grid_level_count = 0 938 898 ! 939 !-- Index zero required as dummy due to definition of arrays f2 and p2 in 940 !-- recursive subroutinenext_mg_level899 !-- Index zero required as dummy due to definition of arrays f2 and p2 in recursive subroutine 900 !-- next_mg_level 941 901 nxl_mg(0) = 0; nxr_mg(0) = 0; nyn_mg(0) = 0; nys_mg(0) = 0; nzt_mg(0) = 0 942 902 … … 948 908 #if defined( __parallel ) 949 909 ! 950 !-- Save the grid size of the subdomain at the switch level, because 951 !-- it is needed in poismg. 910 !-- Save the grid size of the subdomain at the switch level, because it is needed in poismg. 952 911 ind(1) = nxl_l; ind(2) = nxr_l 953 912 ind(3) = nys_l; ind(4) = nyn_l … … 969 928 nys_l = 0 970 929 ! 971 !-- The size of this gathered array must not be larger than the 972 !-- array tend, which is used in the multigrid scheme as a temporary 973 !-- array. Therefore the subdomain size of an PE is calculated and 974 !-- the size of the gathered grid. These values are used in 975 !-- routines pres and poismg 976 subdomain_size = ( nxr - nxl + 2 * nbgp + 1 ) * & 930 !-- The size of this gathered array must not be larger than the array tend, which is used 931 !-- in the multigrid scheme as a temporary array. Therefore the subdomain size of an PE is 932 !-- calculated and the size of the gathered grid. These values are used in routines pres 933 !-- and poismg. 934 subdomain_size = ( nxr - nxl + 2 * nbgp + 1 ) * & 977 935 ( nyn - nys + 2 * nbgp + 1 ) * ( nzt - nzb + 2 ) 978 gathered_size = ( nxr_l - nxl_l + 3 ) * ( nyn_l - nys_l + 3 ) * & 979 ( nzt_l - nzb + 2 ) 936 gathered_size = ( nxr_l - nxl_l + 3 ) * ( nyn_l - nys_l + 3 ) * ( nzt_l - nzb + 2 ) 980 937 981 938 #else 982 message_string = 'multigrid gather/scatter impossible ' // &939 message_string = 'multigrid gather/scatter impossible ' // & 983 940 'in non parallel mode' 984 941 CALL message( 'init_pegrid', 'PA0237', 1, 2, 0, 6, 0 ) … … 992 949 nzt_mg(i) = nzt_l 993 950 994 nxl_l = nxl_l / 2995 nxr_l = nxr_l / 2996 nys_l = nys_l / 2997 nyn_l = nyn_l / 2998 nzt_l = nzt_l / 2999 1000 ENDDO1001 1002 !1003 !-- Temporary problem: Currently calculation of maxerror in routine poismg crashes1004 !-- if grid data are collected on PE0 already on the finest grid level.1005 !-- To be solved later.1006 IF ( maximum_grid_level == mg_switch_to_pe0_level ) THEN1007 message_string = 'grid coarsening on subdomain level cannot be performed'1008 CALL message( 'poismg', 'PA0236', 1, 2, 0, 6, 0 )1009 ENDIF1010 1011 ELSE1012 1013 maximum_grid_level = 01014 1015 ENDIF1016 1017 !1018 !-- Default level 0 tells exchange_horiz that all ghost planes have to be1019 !-- exchanged. grid_level is adjusted in poismg, where only one ghost plane1020 !-- is required.1021 grid_level = 01022 1023 #if defined( __parallel )1024 !1025 !-- Gridpoint number for the exchange of ghost points (y-line for 2D-arrays)1026 ngp_y = nyn - nys + 1 + 2 * nbgp1027 1028 !1029 !-- Define new MPI derived datatypes for the exchange of ghost points in1030 !-- x- and y-direction for 2D-arrays (line)1031 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp, ngp_y, MPI_REAL, type_x, &1032 ierr )1033 CALL MPI_TYPE_COMMIT( type_x, ierr )1034 1035 CALL MPI_TYPE_VECTOR( nbgp, ngp_y, ngp_y, MPI_REAL, type_y, ierr )1036 CALL MPI_TYPE_COMMIT( type_y, ierr )1037 !1038 !-- Define new MPI derived datatypes for the exchange of ghost points in1039 !-- x- and y-direction for 2D-INTEGER arrays (line) - on normal grid.1040 !-- Define types for 32-bit and 8-bit Integer. The 8-bit Integer are only1041 !-- required on normal grid, while 32-bit Integer may be also required on1042 !-- coarser grid level in case of multigrid solver.1043 !1044 !-- 8-bit Integer1045 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp, ngp_y, MPI_BYTE, &1046 type_x_byte, ierr )1047 CALL MPI_TYPE_COMMIT( type_x_byte, ierr )1048 1049 CALL MPI_TYPE_VECTOR( nbgp, ngp_y, ngp_y, MPI_BYTE, &1050 type_y_byte, ierr )1051 CALL MPI_TYPE_COMMIT( type_y_byte, ierr )1052 !1053 !-- 32-bit Integer1054 ALLOCATE( type_x_int(0:maximum_grid_level), &1055 type_y_int(0:maximum_grid_level) )1056 1057 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp, ngp_y, MPI_INTEGER, &1058 type_x_int(0), ierr )1059 CALL MPI_TYPE_COMMIT( type_x_int(0), ierr )1060 1061 CALL MPI_TYPE_VECTOR( nbgp, ngp_y, ngp_y, MPI_INTEGER, type_y_int(0), ierr )1062 CALL MPI_TYPE_COMMIT( type_y_int(0), ierr )1063 !1064 !-- Calculate gridpoint numbers for the exchange of ghost points along x1065 !-- (yz-plane for 3D-arrays) and define MPI derived data type(s) for the1066 !-- exchange of ghost points in y-direction (xz-plane).1067 !-- Do these calculations for the model grid and (if necessary) also1068 !-- for the coarser grid levels used in the multigrid method1069 ALLOCATE ( ngp_xz(0:maximum_grid_level), &1070 ngp_xz_int(0:maximum_grid_level), &1071 ngp_yz(0:maximum_grid_level), &1072 ngp_yz_int(0:maximum_grid_level), &1073 type_xz(0:maximum_grid_level), &1074 type_xz_int(0:maximum_grid_level), &1075 type_yz(0:maximum_grid_level), &1076 type_yz_int(0:maximum_grid_level) )1077 1078 nxl_l = nxl; nxr_l = nxr; nys_l = nys; nyn_l = nyn; nzb_l = nzb; nzt_l = nzt1079 1080 !1081 !-- Discern between the model grid, which needs nbgp ghost points and1082 !-- grid levels for the multigrid scheme. In the latter case only one1083 !-- ghost point is necessary.1084 !-- First definition of MPI-datatypes for exchange of ghost layers on normal1085 !-- grid. The following loop is needed for data exchange in poismg.f90.1086 !1087 !-- Determine number of grid points of yz-layer for exchange1088 ngp_yz(0) = (nzt - nzb + 2) * (nyn - nys + 1 + 2 * nbgp)1089 1090 !1091 !-- Define an MPI-datatype for the exchange of left/right boundaries.1092 !-- Although data are contiguous in physical memory (which does not1093 !-- necessarily require an MPI-derived datatype), the data exchange between1094 !-- left and right PE's using the MPI-derived type is 10% faster than without.1095 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp*(nzt-nzb+2), ngp_yz(0), &1096 MPI_REAL, type_xz(0), ierr )1097 CALL MPI_TYPE_COMMIT( type_xz(0), ierr )1098 1099 CALL MPI_TYPE_VECTOR( nbgp, ngp_yz(0), ngp_yz(0), MPI_REAL, type_yz(0), &1100 ierr )1101 CALL MPI_TYPE_COMMIT( type_yz(0), ierr )1102 1103 !1104 !-- Define data types for exchange of 3D Integer arrays.1105 ngp_yz_int(0) = (nzt - nzb + 2) * (nyn - nys + 1 + 2 * nbgp)1106 1107 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp*(nzt-nzb+2), ngp_yz_int(0), &1108 MPI_INTEGER, type_xz_int(0), ierr )1109 CALL MPI_TYPE_COMMIT( type_xz_int(0), ierr )1110 1111 CALL MPI_TYPE_VECTOR( nbgp, ngp_yz_int(0), ngp_yz_int(0), MPI_INTEGER, &1112 type_yz_int(0), ierr )1113 CALL MPI_TYPE_COMMIT( type_yz_int(0), ierr )1114 1115 !1116 !-- Definition of MPI-datatypes for multigrid method (coarser level grids)1117 IF ( psolver(1:9) == 'multigrid' ) THEN1118 !1119 !-- Definition of MPI-datatyoe as above, but only 1 ghost level is used1120 DO i = maximum_grid_level, 1 , -11121 !1122 !-- For 3D-exchange on different multigrid level, one ghost point for1123 !-- REAL arrays, two ghost points for INTEGER arrays1124 ngp_xz(i) = (nzt_l - nzb_l + 2) * (nxr_l - nxl_l + 3)1125 ngp_yz(i) = (nzt_l - nzb_l + 2) * (nyn_l - nys_l + 3)1126 1127 ngp_xz_int(i) = (nzt_l - nzb_l + 2) * (nxr_l - nxl_l + 3)1128 ngp_yz_int(i) = (nzt_l - nzb_l + 2) * (nyn_l - nys_l + 3)1129 !1130 !-- MPI data type for REAL arrays, for xz-layers1131 CALL MPI_TYPE_VECTOR( nxr_l-nxl_l+3, nzt_l-nzb_l+2, ngp_yz(i), &1132 MPI_REAL, type_xz(i), ierr )1133 CALL MPI_TYPE_COMMIT( type_xz(i), ierr )1134 1135 !1136 !-- MPI data type for INTEGER arrays, for xz-layers1137 CALL MPI_TYPE_VECTOR( nxr_l-nxl_l+3, nzt_l-nzb_l+2, ngp_yz_int(i), &1138 MPI_INTEGER, type_xz_int(i), ierr )1139 CALL MPI_TYPE_COMMIT( type_xz_int(i), ierr )1140 1141 !1142 !-- MPI data type for REAL arrays, for yz-layers1143 CALL MPI_TYPE_VECTOR( 1, ngp_yz(i), ngp_yz(i), MPI_REAL, type_yz(i), &1144 ierr )1145 CALL MPI_TYPE_COMMIT( type_yz(i), ierr )1146 !1147 !-- MPI data type for INTEGER arrays, for yz-layers1148 CALL MPI_TYPE_VECTOR( 1, ngp_yz_int(i), ngp_yz_int(i), MPI_INTEGER, &1149 type_yz_int(i), ierr )1150 CALL MPI_TYPE_COMMIT( type_yz_int(i), ierr )1151 1152 1153 !-- For 2D-exchange of INTEGER arrays on coarser grid level, where 2 ghost1154 !-- points need to be exchanged. Only required for 32-bit Integer arrays.1155 CALL MPI_TYPE_VECTOR( nxr_l-nxl_l+5, 2, nyn_l-nys_l+5, MPI_INTEGER, &1156 type_x_int(i), ierr )1157 CALL MPI_TYPE_COMMIT( type_x_int(i), ierr )1158 1159 1160 CALL MPI_TYPE_VECTOR( 2, nyn_l-nys_l+5, nyn_l-nys_l+5, MPI_INTEGER, &1161 type_y_int(i), ierr )1162 CALL MPI_TYPE_COMMIT( type_y_int(i), ierr )1163 1164 951 nxl_l = nxl_l / 2 1165 952 nxr_l = nxr_l / 2 … … 1170 957 ENDDO 1171 958 959 ! 960 !-- Temporary problem: Currently calculation of maxerror in routine poismg crashes if grid data 961 !-- are collected on PE0 already on the finest grid level. 962 !-- To be solved later. 963 IF ( maximum_grid_level == mg_switch_to_pe0_level ) THEN 964 message_string = 'grid coarsening on subdomain level cannot be performed' 965 CALL message( 'poismg', 'PA0236', 1, 2, 0, 6, 0 ) 966 ENDIF 967 968 ELSE 969 970 maximum_grid_level = 0 971 972 ENDIF 973 974 ! 975 !-- Default level 0 tells exchange_horiz that all ghost planes have to be exchanged. grid_level is 976 !-- adjusted in poismg, where only one ghost plane is required. 977 grid_level = 0 978 979 #if defined( __parallel ) 980 ! 981 !-- Gridpoint number for the exchange of ghost points (y-line for 2D-arrays) 982 ngp_y = nyn - nys + 1 + 2 * nbgp 983 984 ! 985 !-- Define new MPI derived datatypes for the exchange of ghost points in x- and y-direction for 986 !-- 2D-arrays (line) 987 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp, ngp_y, MPI_REAL, type_x, ierr ) 988 CALL MPI_TYPE_COMMIT( type_x, ierr ) 989 990 CALL MPI_TYPE_VECTOR( nbgp, ngp_y, ngp_y, MPI_REAL, type_y, ierr ) 991 CALL MPI_TYPE_COMMIT( type_y, ierr ) 992 ! 993 !-- Define new MPI derived datatypes for the exchange of ghost points in x- and y-direction for 994 !-- 2D-INTEGER arrays (line) - on normal grid. 995 !-- Define types for 32-bit and 8-bit Integer. The 8-bit Integer are only required on normal grid, 996 !-- while 32-bit Integer may be also required on coarser grid level in case of multigrid solver. 997 ! 998 !-- 8-bit Integer 999 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp, ngp_y, MPI_BYTE, type_x_byte, ierr ) 1000 CALL MPI_TYPE_COMMIT( type_x_byte, ierr ) 1001 1002 CALL MPI_TYPE_VECTOR( nbgp, ngp_y, ngp_y, MPI_BYTE, type_y_byte, ierr ) 1003 CALL MPI_TYPE_COMMIT( type_y_byte, ierr ) 1004 ! 1005 !-- 32-bit Integer 1006 ALLOCATE( type_x_int(0:maximum_grid_level), type_y_int(0:maximum_grid_level) ) 1007 1008 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp, ngp_y, MPI_INTEGER, type_x_int(0), ierr ) 1009 CALL MPI_TYPE_COMMIT( type_x_int(0), ierr ) 1010 1011 CALL MPI_TYPE_VECTOR( nbgp, ngp_y, ngp_y, MPI_INTEGER, type_y_int(0), ierr ) 1012 CALL MPI_TYPE_COMMIT( type_y_int(0), ierr ) 1013 ! 1014 !-- Calculate gridpoint numbers for the exchange of ghost points along x (yz-plane for 3D-arrays) 1015 !-- and define MPI derived data type(s) for the exchange of ghost points in y-direction (xz-plane). 1016 !-- Do these calculations for the model grid and (if necessary) also for the coarser grid levels 1017 !-- used in the multigrid method 1018 ALLOCATE ( ngp_xz(0:maximum_grid_level), & 1019 ngp_xz_int(0:maximum_grid_level), & 1020 ngp_yz(0:maximum_grid_level), & 1021 ngp_yz_int(0:maximum_grid_level), & 1022 type_xz(0:maximum_grid_level), & 1023 type_xz_int(0:maximum_grid_level), & 1024 type_yz(0:maximum_grid_level), & 1025 type_yz_int(0:maximum_grid_level) ) 1026 1027 nxl_l = nxl; nxr_l = nxr; nys_l = nys; nyn_l = nyn; nzb_l = nzb; nzt_l = nzt 1028 1029 ! 1030 !-- Discern between the model grid, which needs nbgp ghost points and grid levels for the multigrid 1031 !-- scheme. In the latter case only one ghost point is necessary. 1032 !-- First definition of MPI-datatypes for exchange of ghost layers on normal grid. The following 1033 !-- loop is needed for data exchange in poismg.f90. 1034 ! 1035 !-- Determine number of grid points of yz-layer for exchange 1036 ngp_yz(0) = (nzt - nzb + 2) * (nyn - nys + 1 + 2 * nbgp) 1037 1038 ! 1039 !-- Define an MPI-datatype for the exchange of left/right boundaries. 1040 !-- Although data are contiguous in physical memory (which does not necessarily require an 1041 !-- MPI-derived datatype), the data exchange between left and right PE's using the MPI-derived type 1042 !-- is 10% faster than without. 1043 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp*(nzt-nzb+2), ngp_yz(0), MPI_REAL, type_xz(0), & 1044 ierr ) 1045 CALL MPI_TYPE_COMMIT( type_xz(0), ierr ) 1046 1047 CALL MPI_TYPE_VECTOR( nbgp, ngp_yz(0), ngp_yz(0), MPI_REAL, type_yz(0), ierr ) 1048 CALL MPI_TYPE_COMMIT( type_yz(0), ierr ) 1049 1050 ! 1051 !-- Define data types for exchange of 3D Integer arrays. 1052 ngp_yz_int(0) = (nzt - nzb + 2) * (nyn - nys + 1 + 2 * nbgp) 1053 1054 CALL MPI_TYPE_VECTOR( nxr-nxl+1+2*nbgp, nbgp*(nzt-nzb+2), ngp_yz_int(0), MPI_INTEGER, & 1055 type_xz_int(0), ierr ) 1056 CALL MPI_TYPE_COMMIT( type_xz_int(0), ierr ) 1057 1058 CALL MPI_TYPE_VECTOR( nbgp, ngp_yz_int(0), ngp_yz_int(0), MPI_INTEGER, type_yz_int(0), ierr ) 1059 CALL MPI_TYPE_COMMIT( type_yz_int(0), ierr ) 1060 1061 ! 1062 !-- Definition of MPI-datatypes for multigrid method (coarser level grids) 1063 IF ( psolver(1:9) == 'multigrid' ) THEN 1064 ! 1065 !-- Definition of MPI-datatyoe as above, but only 1 ghost level is used 1066 DO i = maximum_grid_level, 1 , -1 1067 ! 1068 !-- For 3D-exchange on different multigrid level, one ghost point for REAL arrays, two ghost 1069 !-- points for INTEGER arrays 1070 ngp_xz(i) = (nzt_l - nzb_l + 2) * (nxr_l - nxl_l + 3) 1071 ngp_yz(i) = (nzt_l - nzb_l + 2) * (nyn_l - nys_l + 3) 1072 1073 ngp_xz_int(i) = (nzt_l - nzb_l + 2) * (nxr_l - nxl_l + 3) 1074 ngp_yz_int(i) = (nzt_l - nzb_l + 2) * (nyn_l - nys_l + 3) 1075 ! 1076 !-- MPI data type for REAL arrays, for xz-layers 1077 CALL MPI_TYPE_VECTOR( nxr_l-nxl_l+3, nzt_l-nzb_l+2, ngp_yz(i), MPI_REAL, type_xz(i), & 1078 ierr ) 1079 CALL MPI_TYPE_COMMIT( type_xz(i), ierr ) 1080 1081 ! 1082 !-- MPI data type for INTEGER arrays, for xz-layers 1083 CALL MPI_TYPE_VECTOR( nxr_l-nxl_l+3, nzt_l-nzb_l+2, ngp_yz_int(i), MPI_INTEGER, & 1084 type_xz_int(i), ierr ) 1085 CALL MPI_TYPE_COMMIT( type_xz_int(i), ierr ) 1086 1087 ! 1088 !-- MPI data type for REAL arrays, for yz-layers 1089 CALL MPI_TYPE_VECTOR( 1, ngp_yz(i), ngp_yz(i), MPI_REAL, type_yz(i), ierr ) 1090 CALL MPI_TYPE_COMMIT( type_yz(i), ierr ) 1091 ! 1092 !-- MPI data type for INTEGER arrays, for yz-layers 1093 CALL MPI_TYPE_VECTOR( 1, ngp_yz_int(i), ngp_yz_int(i), MPI_INTEGER, type_yz_int(i), ierr ) 1094 CALL MPI_TYPE_COMMIT( type_yz_int(i), ierr ) 1095 1096 1097 !-- For 2D-exchange of INTEGER arrays on coarser grid level, where 2 ghost points need to be 1098 !-- exchanged. Only required for 32-bit Integer arrays. 1099 CALL MPI_TYPE_VECTOR( nxr_l-nxl_l+5, 2, nyn_l-nys_l+5, MPI_INTEGER, type_x_int(i), ierr ) 1100 CALL MPI_TYPE_COMMIT( type_x_int(i), ierr ) 1101 1102 1103 CALL MPI_TYPE_VECTOR( 2, nyn_l-nys_l+5, nyn_l-nys_l+5, MPI_INTEGER, type_y_int(i), ierr ) 1104 CALL MPI_TYPE_COMMIT( type_y_int(i), ierr ) 1105 1106 nxl_l = nxl_l / 2 1107 nxr_l = nxr_l / 2 1108 nys_l = nys_l / 2 1109 nyn_l = nyn_l / 2 1110 nzt_l = nzt_l / 2 1111 1112 ENDDO 1113 1172 1114 ENDIF 1173 1115 … … 1178 1120 !-- Setting of flags for inflow/outflow/nesting conditions. 1179 1121 IF ( pleft == MPI_PROC_NULL ) THEN 1180 IF ( bc_lr == 'dirichlet/radiation' .OR. bc_lr == 'nested' .OR. &1122 IF ( bc_lr == 'dirichlet/radiation' .OR. bc_lr == 'nested' .OR. & 1181 1123 bc_lr == 'nesting_offline' ) THEN 1182 1124 bc_dirichlet_l = .TRUE. … … 1185 1127 ENDIF 1186 1128 ENDIF 1187 1129 1188 1130 IF ( pright == MPI_PROC_NULL ) THEN 1189 1131 IF ( bc_lr == 'dirichlet/radiation' ) THEN 1190 1132 bc_radiation_r = .TRUE. 1191 ELSEIF ( bc_lr == 'radiation/dirichlet' .OR. bc_lr == 'nested' .OR. &1133 ELSEIF ( bc_lr == 'radiation/dirichlet' .OR. bc_lr == 'nested' .OR. & 1192 1134 bc_lr == 'nesting_offline' ) THEN 1193 1135 bc_dirichlet_r = .TRUE. … … 1198 1140 IF ( bc_ns == 'dirichlet/radiation' ) THEN 1199 1141 bc_radiation_s = .TRUE. 1200 ELSEIF ( bc_ns == 'radiation/dirichlet' .OR. bc_ns == 'nested' .OR. &1142 ELSEIF ( bc_ns == 'radiation/dirichlet' .OR. bc_ns == 'nested' .OR. & 1201 1143 bc_ns == 'nesting_offline' ) THEN 1202 1144 bc_dirichlet_s = .TRUE. … … 1205 1147 1206 1148 IF ( pnorth == MPI_PROC_NULL ) THEN 1207 IF ( bc_ns == 'dirichlet/radiation' .OR. bc_ns == 'nested' .OR. &1149 IF ( bc_ns == 'dirichlet/radiation' .OR. bc_ns == 'nested' .OR. & 1208 1150 bc_ns == 'nesting_offline' ) THEN 1209 1151 bc_dirichlet_n = .TRUE. … … 1213 1155 ENDIF 1214 1156 ! 1215 !-- In case of synthetic turbulence geneartor determine ids. 1216 !-- Please note, if no forcing or nesting is applied, the generator is applied 1217 !-- only at the leftlateral boundary.1157 !-- In case of synthetic turbulence geneartor determine ids. 1158 !-- Please note, if no forcing or nesting is applied, the generator is applied only at the left 1159 !-- lateral boundary. 1218 1160 IF ( use_syn_turb_gen ) THEN 1219 1161 IF ( bc_dirichlet_l ) THEN … … 1239 1181 1240 1182 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1241 CALL MPI_ALLREDUCE( id_stg_left_l, id_stg_left, 1, MPI_INTEGER, & 1242 MPI_SUM, comm1dx, ierr ) 1183 CALL MPI_ALLREDUCE( id_stg_left_l, id_stg_left, 1, MPI_INTEGER, MPI_SUM, comm1dx, ierr ) 1243 1184 1244 1185 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1245 CALL MPI_ALLREDUCE( id_stg_right_l, id_stg_right, 1, MPI_INTEGER, & 1246 MPI_SUM, comm1dx, ierr ) 1186 CALL MPI_ALLREDUCE( id_stg_right_l, id_stg_right, 1, MPI_INTEGER, MPI_SUM, comm1dx, ierr ) 1247 1187 1248 1188 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1249 CALL MPI_ALLREDUCE( id_stg_south_l, id_stg_south, 1, MPI_INTEGER, & 1250 MPI_SUM, comm1dy, ierr ) 1189 CALL MPI_ALLREDUCE( id_stg_south_l, id_stg_south, 1, MPI_INTEGER, MPI_SUM, comm1dy, ierr ) 1251 1190 1252 1191 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1253 CALL MPI_ALLREDUCE( id_stg_north_l, id_stg_north, 1, MPI_INTEGER, & 1254 MPI_SUM, comm1dy, ierr ) 1255 1256 ENDIF 1257 1192 CALL MPI_ALLREDUCE( id_stg_north_l, id_stg_north, 1, MPI_INTEGER, MPI_SUM, comm1dy, ierr ) 1193 1194 ENDIF 1195 1258 1196 ! 1259 1197 !-- Broadcast the id of the inflow PE … … 1264 1202 ENDIF 1265 1203 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1266 CALL MPI_ALLREDUCE( id_inflow_l, id_inflow, 1, MPI_INTEGER, MPI_SUM, & 1267 comm1dx, ierr ) 1204 CALL MPI_ALLREDUCE( id_inflow_l, id_inflow, 1, MPI_INTEGER, MPI_SUM, comm1dx, ierr ) 1268 1205 1269 1206 ! … … 1271 1208 !-- WARNING: needs to be adjusted in case of inflows other than from left side! 1272 1209 IF ( turbulent_inflow ) THEN 1273 1210 1274 1211 IF ( NINT( recycling_width / dx, KIND=idp ) >= nxl .AND. & 1275 1212 NINT( recycling_width / dx, KIND=idp ) <= nxr ) THEN … … 1279 1216 ENDIF 1280 1217 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1281 CALL MPI_ALLREDUCE( id_recycling_l, id_recycling, 1, MPI_INTEGER, MPI_SUM, & 1282 comm1dx, ierr ) 1283 1218 CALL MPI_ALLREDUCE( id_recycling_l, id_recycling, 1, MPI_INTEGER, MPI_SUM, comm1dx, ierr ) 1219 1284 1220 ENDIF 1285 1221 … … 1297 1233 comm1dx, ierr ) 1298 1234 1299 IF ( NINT( outflow_source_plane / dx ) >= nxl .AND. &1235 IF ( NINT( outflow_source_plane / dx ) >= nxl .AND. & 1300 1236 NINT( outflow_source_plane / dx ) <= nxr ) THEN 1301 1237 id_outflow_source_l = myidx … … 1304 1240 ENDIF 1305 1241 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1306 CALL MPI_ALLREDUCE( id_outflow_source_l, id_outflow_source, 1, &1307 MPI_INTEGER, MPI_SUM,comm1dx, ierr )1242 CALL MPI_ALLREDUCE( id_outflow_source_l, id_outflow_source, 1, MPI_INTEGER, MPI_SUM, & 1243 comm1dx, ierr ) 1308 1244 1309 1245 ENDIF … … 1330 1266 1331 1267 ! 1332 !-- At the inflow or outflow, u or v, respectively, have to be calculated for 1333 !-- one more grid point. 1268 !-- At the inflow or outflow, u or v, respectively, have to be calculated for one more grid point. 1334 1269 IF ( bc_dirichlet_l .OR. bc_radiation_l ) THEN 1335 1270 nxlu = nxl + 1 … … 1352 1287 1353 1288 CASE ( 1 ) 1354 ALLOCATE( wall_flags_1(nzb:nzt_mg(i)+1, &1355 nys_mg(i)-1:nyn_mg(i)+1, &1289 ALLOCATE( wall_flags_1(nzb:nzt_mg(i)+1, & 1290 nys_mg(i)-1:nyn_mg(i)+1, & 1356 1291 nxl_mg(i)-1:nxr_mg(i)+1) ) 1357 1292 1358 1293 CASE ( 2 ) 1359 ALLOCATE( wall_flags_2(nzb:nzt_mg(i)+1, &1360 nys_mg(i)-1:nyn_mg(i)+1, &1294 ALLOCATE( wall_flags_2(nzb:nzt_mg(i)+1, & 1295 nys_mg(i)-1:nyn_mg(i)+1, & 1361 1296 nxl_mg(i)-1:nxr_mg(i)+1) ) 1362 1297 1363 1298 CASE ( 3 ) 1364 ALLOCATE( wall_flags_3(nzb:nzt_mg(i)+1, &1365 nys_mg(i)-1:nyn_mg(i)+1, &1299 ALLOCATE( wall_flags_3(nzb:nzt_mg(i)+1, & 1300 nys_mg(i)-1:nyn_mg(i)+1, & 1366 1301 nxl_mg(i)-1:nxr_mg(i)+1) ) 1367 1302 1368 1303 CASE ( 4 ) 1369 ALLOCATE( wall_flags_4(nzb:nzt_mg(i)+1, &1370 nys_mg(i)-1:nyn_mg(i)+1, &1304 ALLOCATE( wall_flags_4(nzb:nzt_mg(i)+1, & 1305 nys_mg(i)-1:nyn_mg(i)+1, & 1371 1306 nxl_mg(i)-1:nxr_mg(i)+1) ) 1372 1307 1373 1308 CASE ( 5 ) 1374 ALLOCATE( wall_flags_5(nzb:nzt_mg(i)+1, &1375 nys_mg(i)-1:nyn_mg(i)+1, &1309 ALLOCATE( wall_flags_5(nzb:nzt_mg(i)+1, & 1310 nys_mg(i)-1:nyn_mg(i)+1, & 1376 1311 nxl_mg(i)-1:nxr_mg(i)+1) ) 1377 1312 1378 1313 CASE ( 6 ) 1379 ALLOCATE( wall_flags_6(nzb:nzt_mg(i)+1, &1380 nys_mg(i)-1:nyn_mg(i)+1, &1314 ALLOCATE( wall_flags_6(nzb:nzt_mg(i)+1, & 1315 nys_mg(i)-1:nyn_mg(i)+1, & 1381 1316 nxl_mg(i)-1:nxr_mg(i)+1) ) 1382 1317 1383 1318 CASE ( 7 ) 1384 ALLOCATE( wall_flags_7(nzb:nzt_mg(i)+1, &1385 nys_mg(i)-1:nyn_mg(i)+1, &1319 ALLOCATE( wall_flags_7(nzb:nzt_mg(i)+1, & 1320 nys_mg(i)-1:nyn_mg(i)+1, & 1386 1321 nxl_mg(i)-1:nxr_mg(i)+1) ) 1387 1322 1388 1323 CASE ( 8 ) 1389 ALLOCATE( wall_flags_8(nzb:nzt_mg(i)+1, &1390 nys_mg(i)-1:nyn_mg(i)+1, &1324 ALLOCATE( wall_flags_8(nzb:nzt_mg(i)+1, & 1325 nys_mg(i)-1:nyn_mg(i)+1, & 1391 1326 nxl_mg(i)-1:nxr_mg(i)+1) ) 1392 1327 1393 1328 CASE ( 9 ) 1394 ALLOCATE( wall_flags_9(nzb:nzt_mg(i)+1, &1395 nys_mg(i)-1:nyn_mg(i)+1, &1329 ALLOCATE( wall_flags_9(nzb:nzt_mg(i)+1, & 1330 nys_mg(i)-1:nyn_mg(i)+1, & 1396 1331 nxl_mg(i)-1:nxr_mg(i)+1) ) 1397 1332 1398 1333 CASE ( 10 ) 1399 ALLOCATE( wall_flags_10(nzb:nzt_mg(i)+1, &1400 nys_mg(i)-1:nyn_mg(i)+1, &1334 ALLOCATE( wall_flags_10(nzb:nzt_mg(i)+1, & 1335 nys_mg(i)-1:nyn_mg(i)+1, & 1401 1336 nxl_mg(i)-1:nxr_mg(i)+1) ) 1402 1337 -
TabularUnified palm/trunk/SOURCE/init_pt_anomaly.f90 ¶
r4457 r4648 1 1 !> @file init_pt_anomaly.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 9 8 ! 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 FOR12 ! A PARTICULAR PURPOSE. See the GNU GeneralPublic License for more details.9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 13 12 ! 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/>.13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4457 2020-03-11 14:20:43Z raasch 27 29 ! use statement for exchange horiz added 28 ! 30 ! 29 31 ! 4360 2020-01-07 11:25:50Z suehring 30 ! Introduction of wall_flags_total_0, which currently sets bits based on static 31 ! topographyinformation used in wall_flags_static_032 ! 32 ! Introduction of wall_flags_total_0, which currently sets bits based on static topography 33 ! information used in wall_flags_static_0 34 ! 33 35 ! 4329 2019-12-10 15:46:36Z motisi 34 36 ! Renamed wall_flags_0 to wall_flags_static_0 35 ! 37 ! 36 38 ! 4182 2019-08-22 15:20:23Z scharf 37 39 ! Corrected "Former revisions" section 38 ! 40 ! 39 41 ! 3655 2019-01-07 16:51:22Z knoop 40 42 ! Added topography flags … … 47 49 ! ------------ 48 50 !> Impose a temperature perturbation for an advection test. 49 !------------------------------------------------------------------------------ !51 !--------------------------------------------------------------------------------------------------! 50 52 SUBROUTINE init_pt_anomaly 51 53 52 54 53 USE arrays_3d, &55 USE arrays_3d, & 54 56 ONLY: pt, zu 55 57 56 58 USE control_parameters 57 59 58 USE exchange_horiz_mod, &60 USE exchange_horiz_mod, & 59 61 ONLY: exchange_horiz 60 62 61 USE grid_variables, &63 USE grid_variables, & 62 64 ONLY: dx, dy 63 65 64 USE indices, &66 USE indices, & 65 67 ONLY: nbgp, nx, nxl, nxr, ny, nyn, nys, nzb, nzt, wall_flags_total_0 66 68 … … 70 72 71 73 INTEGER(iwp) :: i !< grid index along x 72 INTEGER(iwp) :: ic !< center index along x 74 INTEGER(iwp) :: ic !< center index along x 73 75 INTEGER(iwp) :: j !< grid index along y 74 76 INTEGER(iwp) :: jc !< center index along y … … 125 127 126 128 ! 127 !-- Initialize warm air bubble close to surface and homogenous elegonated 128 !-- along x-Axis 129 !-- Initialize warm air bubble close to surface and homogenous elegonated along x-Axis 129 130 ELSEIF ( INDEX( initializing_actions, 'initialize_bubble' ) /= 0 ) THEN 130 131 ! … … 141 142 flag = MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 0 ) ) 142 143 143 pt(k,j,i) = pt(k,j,i) + & 144 EXP( -0.5 * ( (j* dy - bubble_center_y) / & 145 bubble_sigma_y )**2) * & 146 EXP( -0.5 * ( (zu(k) - bubble_center_z) / & 147 bubble_sigma_z)**2) * & 144 pt(k,j,i) = pt(k,j,i) + & 145 EXP( -0.5 * ( (j* dy - bubble_center_y) / bubble_sigma_y )**2) * & 146 EXP( -0.5 * ( (zu(k) - bubble_center_z) / bubble_sigma_z)**2) * & 148 147 initial_temperature_difference * flag 149 148 ENDDO -
TabularUnified palm/trunk/SOURCE/init_rankine.f90 ¶
r4457 r4648 1 1 !> @file init_rankine.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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/>. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 8 ! 9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 12 ! 13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4457 2020-03-11 14:20:43Z raasch 27 29 ! use statement for exchange horiz added 28 ! 30 ! 29 31 ! 4360 2020-01-07 11:25:50Z suehring 30 32 ! Corrected "Former revisions" section 31 ! 33 ! 32 34 ! 3655 2019-01-07 16:51:22Z knoop 33 35 ! Modularization of all bulk cloud physics code components … … 39 41 ! Description: 40 42 ! ------------ 41 !> Initialize a (nondivergent) Rankine eddy with a vertical axis in order to test 42 !> t he advection terms and the pressure solver.43 !------------------------------------------------------------------------------ !43 !> Initialize a (nondivergent) Rankine eddy with a vertical axis in order to test the advection 44 !> terms and the pressure solver. 45 !--------------------------------------------------------------------------------------------------! 44 46 SUBROUTINE init_rankine 45 46 47 USE arrays_3d, &47 48 49 USE arrays_3d, & 48 50 ONLY: pt, pt_init, u, u_init, v, v_init 49 51 50 USE control_parameters, &51 ONLY: initializing_actions, n_sor, nsor, nsor_ini 52 53 USE basic_constants_and_equations_mod, &52 USE control_parameters, & 53 ONLY: initializing_actions, n_sor, nsor, nsor_ini 54 55 USE basic_constants_and_equations_mod, & 54 56 ONLY: pi 55 57 56 USE exchange_horiz_mod, &58 USE exchange_horiz_mod, & 57 59 ONLY: exchange_horiz 58 60 59 USE grid_variables, &60 ONLY: dx, dy 61 62 USE indices, &63 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, nyn, nyng, nys, nysg, nzb, nzt 64 61 USE grid_variables, & 62 ONLY: dx, dy 63 64 USE indices, & 65 ONLY: nbgp, nx, nxl, nxlg, nxr, nxrg, nyn, nyng, nys, nysg, nzb, nzt 66 65 67 USE kinds 66 68 … … 74 76 INTEGER(iwp) :: kc1 !< 75 77 INTEGER(iwp) :: kc2 !< 76 78 77 79 REAL(wp) :: alpha !< 78 80 REAL(wp) :: betrag !< -
TabularUnified palm/trunk/SOURCE/init_slope.f90 ¶
r4360 r4648 1 1 !> @file init_slope.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 9 8 ! 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 FOR12 ! A PARTICULAR PURPOSE. See the GNU GeneralPublic License for more details.9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 13 12 ! 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/>.13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4360 2020-01-07 11:25:50Z suehring 27 29 ! Corrected "Former revisions" section 28 ! 30 ! 29 31 ! 3655 2019-01-07 16:51:22Z knoop 30 32 ! Modularization of all bulk cloud physics code components … … 36 38 ! Description: 37 39 ! ------------ 38 !> Initialization of the temperature field and other variables used in case 39 !> of a sloping surface. 40 !> Initialization of the temperature field and other variables used in case of a sloping surface. 40 41 !> @note when a sloping surface is used, only one constant temperature 41 42 !> gradient is allowed! 42 !------------------------------------------------------------------------------ !43 !--------------------------------------------------------------------------------------------------! 43 44 SUBROUTINE init_slope 44 45 45 46 USE arrays_3d, & 46 47 USE arrays_3d, & 47 48 ONLY: pt, pt_init, pt_slope_ref, zu 48 49 USE basic_constants_and_equations_mod, &49 50 USE basic_constants_and_equations_mod, & 50 51 ONLY: pi 51 52 USE control_parameters, &53 ONLY: alpha_surface, initializing_actions, pt_slope_offset, &54 pt_ surface, pt_vertical_gradient, sin_alpha_surface55 56 USE grid_variables, &52 53 USE control_parameters, & 54 ONLY: alpha_surface, initializing_actions, pt_slope_offset, pt_surface, & 55 pt_vertical_gradient, sin_alpha_surface 56 57 USE grid_variables, & 57 58 ONLY: dx 58 59 USE indices, &59 60 USE indices, & 60 61 ONLY: ngp_2dh, nx, nxl, nxlg, nxr, nxrg, nyn, nyng, nys, nysg, nzb, nzt 61 62 62 63 USE kinds 63 64 … … 70 71 INTEGER(iwp) :: j !< 71 72 INTEGER(iwp) :: k !< 72 73 73 74 REAL(wp) :: alpha !< 74 75 REAL(wp) :: height !< 75 76 REAL(wp) :: pt_value !< 76 77 REAL(wp) :: radius !< 77 78 78 79 REAL(wp), DIMENSION(:), ALLOCATABLE :: pt_init_local !< 79 80 … … 86 87 87 88 ! 88 !-- Compute height of grid-point relative to lower left corner of 89 !-- the total domain. 90 !-- First compute the distance between the actual grid point and the 91 !-- lower left corner as well as the angle between the line connecting 92 !-- these points and the bottom of the model. 89 !-- Compute height of grid-point relative to lower left corner of the total domain. 90 !-- First compute the distance between the actual grid point and the lower left corner as well 91 !-- as the angle between the line connecting these points and the bottom of the model. 93 92 IF ( k /= nzb ) THEN 94 93 radius = SQRT( ( i * dx )**2 + zu(k)**2 ) … … 106 105 !-- Compute temperatures in the rotated coordinate system 107 106 alpha = alpha + alpha_surface / 180.0_wp * pi 108 pt_value = pt_surface + radius * SIN( alpha ) * & 109 pt_vertical_gradient(1) / 100.0_wp 107 pt_value = pt_surface + radius * SIN( alpha ) * pt_vertical_gradient(1) / 100.0_wp 110 108 pt_slope_ref(k,i) = pt_value 111 ENDDO 109 ENDDO 112 110 ENDDO 113 111 114 112 ! 115 !-- Temperature difference between left and right boundary of the total domain, 116 !-- used for the cyclic boundary in x-direction 117 pt_slope_offset = (nx+1) * dx * sin_alpha_surface * & 118 pt_vertical_gradient(1) / 100.0_wp 113 !-- Temperature difference between left and right boundary of the total domain, used for the cyclic 114 !-- boundary in x-direction 115 pt_slope_offset = (nx+1) * dx * sin_alpha_surface * pt_vertical_gradient(1) / 100.0_wp 119 116 120 117 … … 129 126 130 127 ! 131 !-- Recompute the mean initial temperature profile (mean along x-direction of 132 !-- the rotatedcoordinate system)128 !-- Recompute the mean initial temperature profile (mean along x-direction of the rotated 129 !-- coordinate system) 133 130 ALLOCATE( pt_init_local(nzb:nzt+1) ) 134 131 pt_init_local = 0.0_wp … … 143 140 #if defined( __parallel ) 144 141 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 145 CALL MPI_ALLREDUCE( pt_init_local, pt_init, nzt+2-nzb, MPI_REAL, & 146 MPI_SUM, comm2d, ierr ) 142 CALL MPI_ALLREDUCE( pt_init_local, pt_init, nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, ierr ) 147 143 #else 148 144 pt_init = pt_init_local -
TabularUnified palm/trunk/SOURCE/init_vertical_profiles.f90 ¶
r4481 r4648 1 1 !> @file ocean_mod.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 9 8 ! 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 FOR12 ! A PARTICULAR PURPOSE. See the GNU GeneralPublic License for more details.9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 13 12 ! 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/>.13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 2017-2020 Leibniz Universitaet Hannover 18 !-------------------------------------------------------------------------------- !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: 21 20 ! ----------------- 22 ! 23 ! 21 ! 22 ! 24 23 ! Former revisions: 25 24 ! ----------------- 26 25 ! $Id$ 27 ! split from check_parameters as separate file to avoid circular dependency 28 ! with ocean_mod 26 ! file re-formatted to follow the PALM coding standard 29 27 ! 30 ! 28 ! 4481 2020-03-31 18:55:54Z maronga 29 ! split from check_parameters as separate file to avoid circular dependency with ocean_mod 30 ! 31 ! 31 32 ! 32 33 ! … … 38 39 ! ------------ 39 40 !> Inititalizes the vertical profiles of scalar quantities. 40 !------------------------------------------------------------------------------ !41 SUBROUTINE init_vertical_profiles( vertical_gradient_level_ind, &42 vertical_gradient_level, &43 vertical_gradient, initial_profile, &41 !--------------------------------------------------------------------------------------------------! 42 SUBROUTINE init_vertical_profiles( vertical_gradient_level_ind, & 43 vertical_gradient_level, & 44 vertical_gradient, initial_profile, & 44 45 surface_value, bc_top_gradient ) 45 46 46 USE arrays_3d, &47 USE arrays_3d, & 47 48 ONLY: dzu, zu 48 49 49 USE control_parameters, &50 USE control_parameters, & 50 51 ONLY: ocean_mode 51 52 52 USE indices, &53 USE indices, & 53 54 ONLY: nz, nzt 54 55 … … 59 60 INTEGER(iwp) :: i !< loop counter 60 61 INTEGER(iwp) :: k !< loop counter 62 61 63 INTEGER(iwp), DIMENSION(1:10) :: vertical_gradient_level_ind !< vertical grid indices for gradient levels 62 64 … … 77 79 DO k = 1, nzt+1 78 80 IF ( i < 11 ) THEN 79 IF ( vertical_gradient_level(i) < zu(k) .AND. &81 IF ( vertical_gradient_level(i) < zu(k) .AND. & 80 82 vertical_gradient_level(i) >= 0.0_wp ) THEN 81 83 gradient = vertical_gradient(i) / 100.0_wp … … 103 105 104 106 ! 105 !-- In ocean mode, profiles are constructed starting from the ocean surface, 106 !-- which is at the topof the model domain107 !-- In ocean mode, profiles are constructed starting from the ocean surface, which is at the top 108 !-- of the model domain 107 109 vertical_gradient_level_ind(1) = nzt+1 108 110 DO k = nzt, 0, -1 109 111 IF ( i < 11 ) THEN 110 IF ( vertical_gradient_level(i) > zu(k) .AND. &112 IF ( vertical_gradient_level(i) > zu(k) .AND. & 111 113 vertical_gradient_level(i) <= 0.0_wp ) THEN 112 114 gradient = vertical_gradient(i) / 100.0_wp … … 119 121 initial_profile(k) = initial_profile(k+1) - dzu(k+1) * gradient 120 122 ELSE 121 initial_profile(k) = surface_value - 0.5_wp * dzu(k+1) * & 122 gradient 123 initial_profile(k+1) = surface_value + 0.5_wp * dzu(k+1) * & 124 gradient 123 initial_profile(k) = surface_value - 0.5_wp * dzu(k+1) * gradient 124 initial_profile(k+1) = surface_value + 0.5_wp * dzu(k+1) * gradient 125 125 ENDIF 126 126 ELSE … … 143 143 ! 144 144 !-- Store gradient at the top boundary for possible Neumann boundary condition 145 bc_top_gradient = ( initial_profile(nzt+1) - initial_profile(nzt) ) / & 146 dzu(nzt+1) 145 bc_top_gradient = ( initial_profile(nzt+1) - initial_profile(nzt) ) / dzu(nzt+1) 147 146 148 147 END SUBROUTINE init_vertical_profiles -
TabularUnified palm/trunk/SOURCE/lagrangian_particle_model_mod.f90 ¶
r4629 r4648 1 1 !> @file lagrangian_particle_model_mod.f90 2 !------------------------------------------------------------------------------ !2 !--------------------------------------------------------------------------------------------------! 3 3 ! This file is part of the PALM model system. 4 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/>. 5 ! PALM is free software: you can redistribute it and/or modify it under the terms of the GNU General 6 ! Public License as published by the Free Software Foundation, either version 3 of the License, or 7 ! (at your option) any later version. 8 ! 9 ! PALM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 10 ! implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 11 ! Public License for more details. 12 ! 13 ! You should have received a copy of the GNU General Public License along with PALM. If not, see 14 ! <http://www.gnu.org/licenses/>. 16 15 ! 17 16 ! Copyright 1997-2020 Leibniz Universitaet Hannover 18 !------------------------------------------------------------------------------ !17 !--------------------------------------------------------------------------------------------------! 19 18 ! 20 19 ! Current revisions: … … 25 24 ! ----------------- 26 25 ! $Id$ 26 ! file re-formatted to follow the PALM coding standard 27 ! 28 ! 4629 2020-07-29 09:37:56Z raasch 27 29 ! support for MPI Fortran77 interface (mpif.h) removed 28 30 ! … … 32 34 ! 4616 2020-07-21 10:09:46Z schwenkel 33 35 ! Bugfix in case of strechting: k-calculation limited lower bound of 1 34 ! 36 ! 35 37 ! 4589 2020-07-06 12:34:09Z suehring 36 38 ! remove unused variables 37 ! 39 ! 38 40 ! 4588 2020-07-06 11:06:02Z suehring 39 41 ! Simplify particle-speed interpolation in logarithmic layer 40 ! 42 ! 41 43 ! 4585 2020-06-30 15:05:20Z suehring 42 ! Limit logarithmically interpolated particle speed to the velocity component 43 ! at the first prognostic grid point (since no stability corrected interpolation44 ! is employed the particle speedcould be overestimated in unstable conditions).45 ! 44 ! Limit logarithmically interpolated particle speed to the velocity component at the first 45 ! prognostic grid point (since no stability corrected interpolation is employed the particle speed 46 ! could be overestimated in unstable conditions). 47 ! 46 48 ! 4546 2020-05-24 12:16:41Z raasch 47 49 ! Variables iran and iran_part completely removed, added I/O of parallel random numbers to restart 48 50 ! file 49 ! 51 ! 50 52 ! 4545 2020-05-22 13:17:57Z schwenkel 51 53 ! Using parallel random generator, thus preventing dependency of PE number 52 ! 54 ! 53 55 ! 4535 2020-05-15 12:07:23Z raasch 54 56 ! bugfix for restart data format query 55 ! 57 ! 56 58 ! 4520 2020-05-06 08:57:19Z schwenkel 57 59 ! Add error number 58 ! 60 ! 59 61 ! 4517 2020-05-03 14:29:30Z raasch 60 62 ! restart data handling with MPI-IO added 61 ! 63 ! 62 64 ! 4471 2020-03-24 12:08:06Z schwenkel 63 65 ! Bugfix in lpm_droplet_interactions_ptq 64 ! 66 ! 65 67 ! 4457 2020-03-11 14:20:43Z raasch 66 68 ! use statement for exchange horiz added 67 ! 69 ! 68 70 ! 4444 2020-03-05 15:59:50Z raasch 69 71 ! bugfix: cpp-directives for serial mode added 70 ! 72 ! 71 73 ! 4430 2020-02-27 18:02:20Z suehring 72 ! - Bugfix in logarithmic interpolation of near-ground particle speed (density 73 ! was not considered). 74 ! - Bugfix in logarithmic interpolation of near-ground particle speed (density was not considered). 74 75 ! - Revise CFL-check when SGS particle speeds are considered. 75 ! - In nested case with SGS particle speeds in the child domain, do not give 76 ! warning that particles are on domain boundaries. At the end of the particle77 ! t ime integration these will be transferred to the parent domain anyhow.78 ! 76 ! - In nested case with SGS particle speeds in the child domain, do not give warning that particles 77 ! are on domain boundaries. At the end of the particle time integration these will be transferred 78 ! to the parent domain anyhow. 79 ! 79 80 ! 4360 2020-01-07 11:25:50Z suehring 80 ! Introduction of wall_flags_total_0, which currently sets bits based on static 81 ! topographyinformation used in wall_flags_static_082 ! 81 ! Introduction of wall_flags_total_0, which currently sets bits based on static topography 82 ! information used in wall_flags_static_0 83 ! 83 84 ! 4336 2019-12-13 10:12:05Z raasch 84 ! bugfix: wrong header output of particle group features (density ratio) in case 85 ! of restartscorrected86 ! 85 ! bugfix: wrong header output of particle group features (density ratio) in case of restarts 86 ! corrected 87 ! 87 88 ! 4329 2019-12-10 15:46:36Z motisi 88 89 ! Renamed wall_flags_0 to wall_flags_static_0 89 ! 90 ! 90 91 ! 4282 2019-10-29 16:18:46Z schwenkel 91 92 ! Bugfix of particle timeseries in case of more than one particle group 92 ! 93 ! 93 94 ! 4277 2019-10-28 16:53:23Z schwenkel 94 95 ! Bugfix: Added first_call_lpm in use statement 95 ! 96 ! 96 97 ! 4276 2019-10-28 16:03:29Z schwenkel 97 98 ! Modularize lpm: Move conditions in time intergration to module 98 ! 99 ! 99 100 ! 4275 2019-10-28 15:34:55Z schwenkel 100 ! Change call of simple predictor corrector method, i.e. two divergence free 101 ! velocitiy fields arenow used.101 ! Change call of simple predictor corrector method, i.e. two divergence free velocitiy fields are 102 ! now used. 102 103 ! 103 104 ! 4232 2019-09-20 09:34:22Z knoop 104 105 ! Removed INCLUDE "mpif.h", as it is not needed because of USE pegrid 105 ! 106 ! 106 107 ! 4195 2019-08-28 13:44:27Z schwenkel 107 ! Bugfix for simple_corrector interpolation method in case of ocean runs and 108 ! output particleadvection interpolation method into header109 ! 108 ! Bugfix for simple_corrector interpolation method in case of ocean runs and output particle 109 ! advection interpolation method into header 110 ! 110 111 ! 4182 2019-08-22 15:20:23Z scharf 111 112 ! Corrected "Former revisions" section 112 ! 113 ! 113 114 ! 4168 2019-08-16 13:50:17Z suehring 114 115 ! Replace function get_topography_top_index by topo_top_ind 115 ! 116 ! 116 117 ! 4145 2019-08-06 09:55:22Z schwenkel 117 118 ! Some reformatting 118 ! 119 ! 119 120 ! 4144 2019-08-06 09:11:47Z raasch 120 121 ! relational operators .EQ., .NE., etc. replaced by ==, /=, etc. 121 ! 122 ! 122 123 ! 4143 2019-08-05 15:14:53Z schwenkel 123 124 ! Rename variable and change select case to if statement 124 ! 125 ! 125 126 ! 4122 2019-07-26 13:11:56Z schwenkel 126 127 ! Implement reset method as bottom boundary condition 127 ! 128 ! 128 129 ! 4121 2019-07-26 10:01:22Z schwenkel 129 ! Implementation of an simple method for interpolating the velocities to 130 ! particle position 131 ! 130 ! Implementation of an simple method for interpolating the velocities to particle position 131 ! 132 132 ! 4114 2019-07-23 14:09:27Z schwenkel 133 133 ! Bugfix: Added working precision for if statement 134 ! 134 ! 135 135 ! 4054 2019-06-27 07:42:18Z raasch 136 136 ! bugfix for calculating the minimum particle time step 137 ! 137 ! 138 138 ! 4044 2019-06-19 12:28:27Z schwenkel 139 139 ! Bugfix in case of grid strecting: corrected calculation of k-Index … … 141 141 ! 4043 2019-06-18 16:59:00Z schwenkel 142 142 ! Remove min_nr_particle, Add lpm_droplet_interactions_ptq into module 143 ! 143 ! 144 144 ! 4028 2019-06-13 12:21:37Z schwenkel 145 145 ! Further modularization of particle code components 146 ! 146 ! 147 147 ! 4020 2019-06-06 14:57:48Z schwenkel 148 ! Removing submodules 149 ! 148 ! Removing submodules 149 ! 150 150 ! 4018 2019-06-06 13:41:50Z eckhard 151 151 ! Bugfix for former revision 152 ! 152 ! 153 153 ! 4017 2019-06-06 12:16:46Z schwenkel 154 154 ! Modularization of all lagrangian particle model code components 155 ! 156 ! 3655 2019-01-07 16:51:22Z knoop 157 ! bugfix to guarantee correct particle releases in case that the release 158 ! interval is smaller thanthe model timestep155 ! 156 ! 3655 2019-01-07 16:51:22Z knoop 157 ! bugfix to guarantee correct particle releases in case that the release interval is smaller than 158 ! the model timestep 159 159 ! 160 160 ! Revision 1.1 1999/11/25 16:16:06 raasch … … 164 164 ! Description: 165 165 ! ------------ 166 !> The embedded LPM allows for studying transport and dispersion processes within 167 !> turbulent flows. This model including passive particles that do not show any 168 !> feedback on the turbulent flow. Further also particles with inertia and 169 !> cloud droplets ca be simulated explicitly. 166 !> The embedded LPM allows for studying transport and dispersion processes within turbulent flows. 167 !> This model is including passive particles that do not show any feedback on the turbulent flow. 168 !> Further also particles with inertia and cloud droplets can be simulated explicitly. 170 169 !> 171 170 !> @todo test lcm … … 173 172 !> @note <Enter notes on the module> 174 173 !> @bug <Enter bug on the module> 175 !------------------------------------------------------------------------------ !174 !--------------------------------------------------------------------------------------------------! 176 175 MODULE lagrangian_particle_model_mod 177 176 178 177 USE, INTRINSIC :: ISO_C_BINDING 179 178 180 USE arrays_3d, & 181 ONLY: de_dx, de_dy, de_dz, & 182 d_exner, & 183 dzw, zu, zw, ql_c, ql_v, ql_vp, hyp, & 184 pt, q, exner, ql, diss, e, u, v, w, km, ql_1, ql_2 185 186 USE averaging, & 187 ONLY: ql_c_av, pr_av, pc_av, ql_vp_av, ql_v_av 188 189 USE basic_constants_and_equations_mod, & 190 ONLY: molecular_weight_of_solute, molecular_weight_of_water, magnus, & 191 pi, rd_d_rv, rho_l, r_v, rho_s, vanthoff, l_v, kappa, g, lv_d_cp 192 193 USE control_parameters, & 194 ONLY: bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r, bc_dirichlet_s, & 195 child_domain, & 196 cloud_droplets, constant_flux_layer, current_timestep_number, & 197 dt_3d, dt_3d_reached, debug_output, first_call_lpm, humidity, & 198 dt_3d_reached_l, dt_dopts, dz, initializing_actions, & 199 intermediate_timestep_count, intermediate_timestep_count_max, & 200 message_string, molecular_viscosity, ocean_mode, & 201 particle_maximum_age, restart_data_format_input, & 202 restart_data_format_output, & 203 simulated_time, topography, dopts_time_count, & 204 time_since_reference_point, rho_surface, u_gtrans, v_gtrans, & 205 dz_stretch_level, dz_stretch_level_start 206 207 USE cpulog, & 179 USE arrays_3d, & 180 ONLY: d_exner, de_dx, de_dy, de_dz, diss, dzw, e, exner, hyp, km, pt, q, ql, ql_1, ql_2, & 181 ql_c, ql_v, ql_vp, u, v, w, zu, zw 182 183 USE averaging, & 184 ONLY: pc_av, pr_av, ql_c_av, ql_v_av, ql_vp_av 185 186 USE basic_constants_and_equations_mod, & 187 ONLY: g, kappa, l_v, lv_d_cp, magnus, molecular_weight_of_solute, & 188 molecular_weight_of_water, pi, r_v, rd_d_rv, rho_l, rho_s, vanthoff 189 190 USE control_parameters, & 191 ONLY: bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r, bc_dirichlet_s, & 192 child_domain, cloud_droplets, constant_flux_layer, current_timestep_number, & 193 debug_output, dopts_time_count, dt_3d, dt_3d_reached, dt_3d_reached_l, dt_dopts, dz,& 194 dz_stretch_level, dz_stretch_level_start, first_call_lpm, humidity, & 195 initializing_actions, intermediate_timestep_count, intermediate_timestep_count_max, & 196 message_string, molecular_viscosity, ocean_mode, particle_maximum_age, & 197 restart_data_format_input, restart_data_format_output, rho_surface, simulated_time, & 198 time_since_reference_point, topography, u_gtrans, v_gtrans 199 200 USE cpulog, & 208 201 ONLY: cpu_log, log_point, log_point_s 209 202 210 USE indices, & 211 ONLY: nx, nxl, nxlg, nxrg, nxr, ny, nyn, nys, nyng, nysg, nz, nzb, & 212 nzb_max, nzt,nbgp, ngp_2dh_outer, & 213 topo_top_ind, & 214 wall_flags_total_0 203 USE indices, & 204 ONLY: nbgp, ngp_2dh_outer, nx, nxl, nxlg, nxrg, nxr, ny, nyn, nys, nyng, nysg, nz, nzb, & 205 nzb_max, nzt, topo_top_ind, wall_flags_total_0 215 206 216 207 USE kinds … … 221 212 222 213 #if defined( __parallel ) 223 USE pmc_particle_interface, & 224 ONLY: pmcp_c_get_particle_from_parent, pmcp_p_fill_particle_win, & 225 pmcp_c_send_particle_to_parent, pmcp_p_empty_particle_win, & 226 pmcp_p_delete_particles_in_fine_grid_area, pmcp_g_init, & 227 pmcp_g_print_number_of_particles 214 USE pmc_particle_interface, & 215 ONLY: pmcp_c_get_particle_from_parent, pmcp_c_send_particle_to_parent, pmcp_g_init, & 216 pmcp_g_print_number_of_particles, pmcp_p_delete_particles_in_fine_grid_area, & 217 pmcp_p_empty_particle_win, pmcp_p_fill_particle_win 228 218 #endif 229 219 230 USE pmc_interface, &220 USE pmc_interface, & 231 221 ONLY: nested_run 232 222 233 USE grid_variables, &223 USE grid_variables, & 234 224 ONLY: ddx, dx, ddy, dy 235 225 236 USE netcdf_interface, & 237 ONLY: netcdf_data_format, netcdf_deflate, dopts_num, id_set_pts, & 238 id_var_dopts, id_var_time_pts, nc_stat, & 239 netcdf_handle_error 240 241 USE random_generator_parallel, & 242 ONLY: init_parallel_random_generator, & 243 random_dummy, & 244 random_number_parallel, & 245 random_number_parallel_gauss, & 246 random_seed_parallel, & 247 id_random_array 248 249 USE restart_data_mpi_io_mod, & 250 ONLY: rd_mpi_io_check_array, & 251 rd_mpi_io_check_open, & 252 rd_mpi_io_close, & 253 rd_mpi_io_open, & 254 rd_mpi_io_particle_filetypes, & 255 rrd_mpi_io, & 256 rrd_mpi_io_global_array, & 257 rrd_mpi_io_particles, & 258 wrd_mpi_io, & 259 wrd_mpi_io_global_array, & 226 USE netcdf_interface, & 227 ONLY: dopts_num, id_set_pts, id_var_dopts, id_var_time_pts, nc_stat, netcdf_data_format, & 228 netcdf_deflate, netcdf_handle_error 229 230 USE random_generator_parallel, & 231 ONLY: init_parallel_random_generator, & 232 id_random_array, & 233 random_dummy, & 234 random_number_parallel, & 235 random_number_parallel_gauss, & 236 random_seed_parallel 237 238 USE restart_data_mpi_io_mod, & 239 ONLY: rd_mpi_io_check_array, & 240 rd_mpi_io_check_open, & 241 rd_mpi_io_close, & 242 rd_mpi_io_open, & 243 rd_mpi_io_particle_filetypes, & 244 rrd_mpi_io, & 245 rrd_mpi_io_global_array, & 246 rrd_mpi_io_particles, & 247 wrd_mpi_io, & 248 wrd_mpi_io_global_array, & 260 249 wrd_mpi_io_particles 261 250 262 USE statistics, &251 USE statistics, & 263 252 ONLY: hom 264 253 265 USE surface_mod, &266 ONLY: bc_h, &267 surf_def_h, &268 surf_lsm_h, &254 USE surface_mod, & 255 ONLY: bc_h, & 256 surf_def_h, & 257 surf_lsm_h, & 269 258 surf_usm_h 270 259 … … 283 272 IMPLICIT NONE 284 273 274 INTEGER(iwp), PARAMETER :: nr_2_direction_move = 10000 !< 275 INTEGER(iwp), PARAMETER :: phase_init = 1 !< 276 INTEGER(iwp), PARAMETER, PUBLIC :: phase_release = 2 !< 277 278 REAL(wp), PARAMETER :: c_0 = 3.0_wp !< parameter for lagrangian timescale 279 285 280 CHARACTER(LEN=15) :: aero_species = 'nacl' !< aerosol species 286 281 CHARACTER(LEN=15) :: aero_type = 'maritime' !< aerosol type 282 CHARACTER(LEN=15) :: bc_par_b = 'reflect' !< bottom boundary condition 287 283 CHARACTER(LEN=15) :: bc_par_lr = 'cyclic' !< left/right boundary condition 288 284 CHARACTER(LEN=15) :: bc_par_ns = 'cyclic' !< north/south boundary condition 289 CHARACTER(LEN=15) :: bc_par_b = 'reflect' !< bottom boundary condition290 285 CHARACTER(LEN=15) :: bc_par_t = 'absorb' !< top boundary condition 291 286 CHARACTER(LEN=15) :: collision_kernel = 'none' !< collision kernel … … 296 291 CHARACTER(LEN=25) :: particle_advection_interpolation = 'trilinear' !< interpolation method for calculatin the particle 297 292 298 INTEGER(iwp) :: deleted_particles = 0 !< number of deleted particles per time step 293 INTEGER(iwp) :: deleted_particles = 0 !< number of deleted particles per time step 299 294 INTEGER(iwp) :: i_splitting_mode !< dummy for splitting mode 295 INTEGER(iwp) :: isf !< dummy for splitting function 300 296 INTEGER(iwp) :: max_number_particles_per_gridbox = 100 !< namelist parameter (see documentation) 301 INTEGER(iwp) :: isf !< dummy for splitting function302 297 INTEGER(iwp) :: number_particles_per_gridbox = -1 !< namelist parameter (see documentation) 303 INTEGER(iwp) :: number_of_sublayers = 20 !< number of sublayers for particle velocities betwenn surface and first grid level 304 INTEGER(iwp) :: offset_ocean_nzt = 0 !< in case of oceans runs, the vertical index calculations need an offset 305 INTEGER(iwp) :: offset_ocean_nzt_m1 = 0 !< in case of oceans runs, the vertical index calculations need an offset 298 INTEGER(iwp) :: number_of_sublayers = 20 !< number of sublayers for particle velocities betwenn surface 299 !< and first grid level 300 INTEGER(iwp) :: offset_ocean_nzt = 0 !< in case of oceans runs, the vertical index calculations need 301 !< an offset 302 INTEGER(iwp) :: offset_ocean_nzt_m1 = 0 !< in case of oceans runs, the vertical index calculations need 303 !< an offset 306 304 INTEGER(iwp) :: particles_per_point = 1 !< namelist parameter (see documentation) 307 305 INTEGER(iwp) :: radius_classes = 20 !< namelist parameter (see documentation) … … 310 308 INTEGER(iwp) :: step_dealloc = 100 !< namelist parameter (see documentation) 311 309 INTEGER(iwp) :: total_number_of_particles !< total number of particles in the whole model domain 310 INTEGER(iwp) :: trlp_count_recv_sum !< parameter for particle exchange of PEs 312 311 INTEGER(iwp) :: trlp_count_sum !< parameter for particle exchange of PEs 313 INTEGER(iwp) :: tr lp_count_recv_sum !< parameter for particle exchange of PEs312 INTEGER(iwp) :: trrp_count_recv_sum !< parameter for particle exchange of PEs 314 313 INTEGER(iwp) :: trrp_count_sum !< parameter for particle exchange of PEs 315 INTEGER(iwp) :: tr rp_count_recv_sum !< parameter for particle exchange of PEs314 INTEGER(iwp) :: trsp_count_recv_sum !< parameter for particle exchange of PEs 316 315 INTEGER(iwp) :: trsp_count_sum !< parameter for particle exchange of PEs 317 INTEGER(iwp) :: tr sp_count_recv_sum !< parameter for particle exchange of PEs316 INTEGER(iwp) :: trnp_count_recv_sum !< parameter for particle exchange of PEs 318 317 INTEGER(iwp) :: trnp_count_sum !< parameter for particle exchange of PEs 319 INTEGER(iwp) :: trnp_count_recv_sum !< parameter for particle exchange of PEs320 318 321 319 INTEGER(isp), DIMENSION(:,:,:), ALLOCATABLE :: seq_random_array_particles !< sequence of random array for particle 322 320 323 LOGICAL :: lagrangian_particle_model = .FALSE. !< namelist parameter (see documentation)324 321 LOGICAL :: curvature_solution_effects = .FALSE. !< namelist parameter (see documentation) 325 322 LOGICAL :: deallocate_memory = .TRUE. !< namelist parameter (see documentation) 326 323 LOGICAL :: hall_kernel = .FALSE. !< flag for collision kernel 324 LOGICAL :: interpolation_simple_corrector = .FALSE. !< flag for simple particle advection interpolation with corrector step 325 LOGICAL :: interpolation_simple_predictor = .FALSE. !< flag for simple particle advection interpolation with predictor step 326 LOGICAL :: interpolation_trilinear = .FALSE. !< flag for trilinear particle advection interpolation 327 LOGICAL :: lagrangian_particle_model = .FALSE. !< namelist parameter (see documentation) 327 328 LOGICAL :: merging = .FALSE. !< namelist parameter (see documentation) 328 329 LOGICAL :: random_start_position = .FALSE. !< namelist parameter (see documentation) … … 332 333 LOGICAL :: use_kernel_tables = .FALSE. !< parameter, which turns on the use of precalculated collision kernels 333 334 LOGICAL :: write_particle_statistics = .FALSE. !< namelist parameter (see documentation) 334 LOGICAL :: interpolation_simple_predictor = .FALSE. !< flag for simple particle advection interpolation with predictor step 335 LOGICAL :: interpolation_simple_corrector = .FALSE. !< flag for simple particle advection interpolation with corrector step 336 LOGICAL :: interpolation_trilinear = .FALSE. !< flag for trilinear particle advection interpolation 337 338 LOGICAL, DIMENSION(max_number_of_particle_groups) :: vertical_particle_advection = .TRUE. !< Switch for vertical particle transport 335 336 LOGICAL, DIMENSION(max_number_of_particle_groups) :: vertical_particle_advection = .TRUE. !< Switch for vertical particle 337 !< transport 339 338 340 339 REAL(wp) :: aero_weight = 1.0_wp !< namelist parameter (see documentation) … … 342 341 REAL(wp) :: dt_prel = 9999999.9_wp !< namelist parameter (see documentation) 343 342 REAL(wp) :: dt_write_particle_data = 9999999.9_wp !< namelist parameter (see documentation) 343 REAL(wp) :: epsilon_collision !< 344 344 REAL(wp) :: end_time_prel = 9999999.9_wp !< namelist parameter (see documentation) 345 345 REAL(wp) :: initial_weighting_factor = 1.0_wp !< namelist parameter (see documentation) … … 350 350 REAL(wp) :: radius_merge = 1.0E-7_wp !< namelist parameter (see documentation) 351 351 REAL(wp) :: radius_split = 40.0E-6_wp !< namelist parameter (see documentation) 352 REAL(wp) :: rclass_lbound !< 353 REAL(wp) :: rclass_ubound !< 352 354 REAL(wp) :: rm(3) = 1.0E-6_wp !< namelist parameter (see documentation) 353 355 REAL(wp) :: sgs_wf_part !< parameter for sgs 354 356 REAL(wp) :: time_write_particle_data = 0.0_wp !< write particle data at current time on file 357 REAL(wp) :: urms !< 355 358 REAL(wp) :: weight_factor_merge = -1.0_wp !< namelist parameter (see documentation) 356 359 REAL(wp) :: weight_factor_split = -1.0_wp !< namelist parameter (see documentation) 357 360 REAL(wp) :: z0_av_global !< horizontal mean value of z0 358 359 REAL(wp) :: rclass_lbound !<360 REAL(wp) :: rclass_ubound !<361 362 REAL(wp), PARAMETER :: c_0 = 3.0_wp !< parameter for lagrangian timescale363 361 364 362 REAL(wp), DIMENSION(max_number_of_particle_groups) :: density_ratio = 9999999.9_wp !< namelist parameter (see documentation) … … 376 374 REAL(wp), DIMENSION(:), ALLOCATABLE :: log_z_z0 !< Precalculate LOG(z/z0) 377 375 378 INTEGER(iwp), PARAMETER :: NR_2_direction_move = 10000 !<379 380 376 #if defined( __parallel ) 381 377 INTEGER(iwp) :: nr_move_north !< … … 385 381 TYPE(particle_type), DIMENSION(:), ALLOCATABLE :: move_also_south 386 382 #endif 387 388 REAL(wp) :: epsilon_collision !<389 REAL(wp) :: urms !<390 383 391 384 REAL(wp), DIMENSION(:), ALLOCATABLE :: epsclass !< dissipation rate class … … 404 397 REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: w_t !< w value of old timelevel t 405 398 406 407 INTEGER(iwp), PARAMETER :: PHASE_INIT = 1 !<408 INTEGER(iwp), PARAMETER, PUBLIC :: PHASE_RELEASE = 2 !<409 410 399 SAVE 411 400 412 401 PRIVATE 413 402 414 PUBLIC lpm_parin, &415 lpm_header, &416 lpm_init_arrays, &417 lpm_init, &418 lpm_actions, &419 lpm_data_output_ptseries, &420 lpm_interaction_droplets_ptq, &421 lpm_rrd_local_particles, &422 lpm_wrd_local, &423 lpm_rrd_global, &424 lpm_wrd_global, &425 lpm_rrd_local, &403 PUBLIC lpm_parin, & 404 lpm_header, & 405 lpm_init_arrays, & 406 lpm_init, & 407 lpm_actions, & 408 lpm_data_output_ptseries, & 409 lpm_interaction_droplets_ptq, & 410 lpm_rrd_local_particles, & 411 lpm_wrd_local, & 412 lpm_rrd_global, & 413 lpm_wrd_global, & 414 lpm_rrd_local, & 426 415 lpm_check_parameters 427 416 … … 443 432 MODULE PROCEDURE lpm_init_arrays 444 433 END INTERFACE lpm_init_arrays 445 434 446 435 INTERFACE lpm_init 447 436 MODULE PROCEDURE lpm_init … … 544 533 545 534 CONTAINS 546 547 548 !------------------------------------------------------------------------------ !535 536 537 !--------------------------------------------------------------------------------------------------! 549 538 ! Description: 550 539 ! ------------ 551 540 !> Parin for &particle_parameters for the Lagrangian particle model 552 !------------------------------------------------------------------------------ !541 !--------------------------------------------------------------------------------------------------! 553 542 SUBROUTINE lpm_parin 554 543 555 544 CHARACTER (LEN=80) :: line !< 556 545 557 NAMELIST /particles_par/ &558 aero_species, &559 aero_type, &560 aero_weight, &561 alloc_factor, &562 bc_par_b, &563 bc_par_lr, &564 bc_par_ns, &565 bc_par_t, &566 collision_kernel, &567 curvature_solution_effects, &568 deallocate_memory, &569 density_ratio, &570 dissipation_classes, &571 dt_dopts, &572 dt_min_part, &573 dt_prel, &574 dt_write_particle_data, &575 end_time_prel, &576 initial_weighting_factor, &577 log_sigma, &578 max_number_particles_per_gridbox, &579 merging, &580 na, &581 number_concentration, &582 number_of_particle_groups, &583 number_particles_per_gridbox, &584 particles_per_point, &585 particle_advection_start, &586 particle_advection_interpolation, &587 particle_maximum_age, &588 pdx, &589 pdy, &590 pdz, &591 psb, &592 psl, &593 psn, &594 psr, &595 pss, &596 pst, &597 radius, &598 radius_classes, &599 radius_merge, &600 radius_split, &601 random_start_position, &602 read_particles_from_restartfile, &603 rm, &604 seed_follows_topography, &605 splitting, &606 splitting_factor, &607 splitting_factor_max, &608 splitting_function, &609 splitting_mode, &610 step_dealloc, &611 use_sgs_for_particles, &612 vertical_particle_advection, &613 weight_factor_merge, &614 weight_factor_split, &546 NAMELIST /particles_par/ & 547 aero_species, & 548 aero_type, & 549 aero_weight, & 550 alloc_factor, & 551 bc_par_b, & 552 bc_par_lr, & 553 bc_par_ns, & 554 bc_par_t, & 555 collision_kernel, & 556 curvature_solution_effects, & 557 deallocate_memory, & 558 density_ratio, & 559 dissipation_classes, & 560 dt_dopts, & 561 dt_min_part, & 562 dt_prel, & 563 dt_write_particle_data, & 564 end_time_prel, & 565 initial_weighting_factor, & 566 log_sigma, & 567 max_number_particles_per_gridbox, & 568 merging, & 569 na, & 570 number_concentration, & 571 number_of_particle_groups, & 572 number_particles_per_gridbox, & 573 particles_per_point, & 574 particle_advection_start, & 575 particle_advection_interpolation, & 576 particle_maximum_age, & 577 pdx, & 578 pdy, & 579 pdz, & 580 psb, & 581 psl, & 582 psn, & 583 psr, & 584 pss, & 585 pst, & 586 radius, & 587 radius_classes, & 588 radius_merge, & 589 radius_split, & 590 random_start_position, & 591 read_particles_from_restartfile, & 592 rm, & 593 seed_follows_topography, & 594 splitting, & 595 splitting_factor, & 596 splitting_factor_max, & 597 splitting_function, & 598 splitting_mode, & 599 step_dealloc, & 600 use_sgs_for_particles, & 601 vertical_particle_advection, & 602 weight_factor_merge, & 603 weight_factor_split, & 615 604 write_particle_statistics 616 605 617 NAMELIST /particle_parameters/ &618 aero_species, &619 aero_type, &620 aero_weight, &621 alloc_factor, &622 bc_par_b, &623 bc_par_lr, &624 bc_par_ns, &625 bc_par_t, &626 collision_kernel, &627 curvature_solution_effects, &628 deallocate_memory, &629 density_ratio, &630 dissipation_classes, &631 dt_dopts, &632 dt_min_part, &633 dt_prel, &634 dt_write_particle_data, &635 end_time_prel, &636 initial_weighting_factor, &637 log_sigma, &638 max_number_particles_per_gridbox, &639 merging, &640 na, &641 number_concentration, &642 number_of_output_particles, &643 number_of_particle_groups, &644 number_particles_per_gridbox, &645 oversize, &646 particles_per_point, &647 particle_advection_start, &648 particle_advection_interpolation, &649 particle_maximum_age, &650 part_output, &651 part_inc, &652 part_percent, &653 pdx, &654 pdy, &655 pdz, &656 psb, &657 psl, &658 psn, &659 psr, &660 pss, &661 pst, &662 radius, &663 radius_classes, &664 radius_merge, &665 radius_split, &666 random_start_position, &667 read_particles_from_restartfile, &668 rm, &669 seed_follows_topography, &670 splitting, &671 splitting_factor, &672 splitting_factor_max, &673 splitting_function, &674 splitting_mode, &675 step_dealloc, &676 unlimited_dimension, &677 use_sgs_for_particles, &678 vertical_particle_advection, &679 weight_factor_merge, &680 weight_factor_split, &606 NAMELIST /particle_parameters/ & 607 aero_species, & 608 aero_type, & 609 aero_weight, & 610 alloc_factor, & 611 bc_par_b, & 612 bc_par_lr, & 613 bc_par_ns, & 614 bc_par_t, & 615 collision_kernel, & 616 curvature_solution_effects, & 617 deallocate_memory, & 618 density_ratio, & 619 dissipation_classes, & 620 dt_dopts, & 621 dt_min_part, & 622 dt_prel, & 623 dt_write_particle_data, & 624 end_time_prel, & 625 initial_weighting_factor, & 626 log_sigma, & 627 max_number_particles_per_gridbox, & 628 merging, & 629 na, & 630 number_concentration, & 631 number_of_output_particles, & 632 number_of_particle_groups, & 633 number_particles_per_gridbox, & 634 oversize, & 635 particles_per_point, & 636 particle_advection_start, & 637 particle_advection_interpolation, & 638 particle_maximum_age, & 639 part_output, & 640 part_inc, & 641 part_percent, & 642 pdx, & 643 pdy, & 644 pdz, & 645 psb, & 646 psl, & 647 psn, & 648 psr, & 649 pss, & 650 pst, & 651 radius, & 652 radius_classes, & 653 radius_merge, & 654 radius_split, & 655 random_start_position, & 656 read_particles_from_restartfile, & 657 rm, & 658 seed_follows_topography, & 659 splitting, & 660 splitting_factor, & 661 splitting_factor_max, & 662 splitting_function, & 663 splitting_mode, & 664 step_dealloc, & 665 unlimited_dimension, & 666 use_sgs_for_particles, & 667 vertical_particle_advection, & 668 weight_factor_merge, & 669 weight_factor_split, & 681 670 write_particle_statistics 682 671 683 672 ! 684 !-- Position the namelist-file at the beginning (it was already opened in 685 !-- parin), search for the namelist-group of the package and position the686 !-- file at this line. Do the same for eachoptionally used package.673 !-- Position the namelist-file at the beginning (it was already opened in parin), search for the 674 !-- namelist-group of the package and position the file at this line. Do the same for each 675 !-- optionally used package. 687 676 line = ' ' 688 677 689 678 ! 690 679 !-- Try to find particles package … … 701 690 !-- Set flag that indicates that particles are switched on 702 691 particle_advection = .TRUE. 703 692 704 693 GOTO 14 705 694 … … 719 708 READ ( 11, particles_par, ERR = 13, END = 14 ) 720 709 721 message_string = 'namelist particles_par is deprecated and will be ' // &722 'removed in near future. Please use namelist ' // &710 message_string = 'namelist particles_par is deprecated and will be ' // & 711 'removed in near future. Please use namelist ' // & 723 712 'particle_parameters instead' 724 713 CALL message( 'package_parin', 'PA0487', 0, 1, 0, 6, 0 ) … … 737 726 738 727 END SUBROUTINE lpm_parin 739 740 !------------------------------------------------------------------------------ !728 729 !--------------------------------------------------------------------------------------------------! 741 730 ! Description: 742 731 ! ------------ 743 732 !> Writes used particle attributes in header file. 744 !------------------------------------------------------------------------------ !733 !--------------------------------------------------------------------------------------------------! 745 734 SUBROUTINE lpm_header ( io ) 746 735 … … 763 752 ENDIF 764 753 ENDIF 765 754 766 755 IF ( particle_advection ) THEN 767 756 ! 768 757 !-- Particle attributes 769 WRITE ( io, 480 ) particle_advection_start, TRIM(particle_advection_interpolation), & 770 dt_prel, bc_par_lr, & 771 bc_par_ns, bc_par_b, bc_par_t, particle_maximum_age, & 758 WRITE ( io, 480 ) particle_advection_start, TRIM(particle_advection_interpolation), & 759 dt_prel, bc_par_lr, bc_par_ns, bc_par_b, bc_par_t, particle_maximum_age, & 772 760 end_time_prel 773 761 IF ( use_sgs_for_particles ) WRITE ( io, 488 ) dt_min_part … … 801 789 WRITE ( io, 492 ) 802 790 ENDIF 803 WRITE ( io, 493 ) psl(i), psr(i), pss(i), psn(i), psb(i), pst(i), & 804 pdx(i), pdy(i), pdz(i) 791 WRITE ( io, 493 ) psl(i), psr(i), pss(i), psn(i), psb(i), pst(i), pdx(i), pdy(i), pdz(i) 805 792 IF ( .NOT. vertical_particle_advection(i) ) WRITE ( io, 482 ) 806 793 ENDDO 807 794 808 795 ENDIF 809 796 810 797 344 FORMAT (' Output format: ',A/) 811 798 354 FORMAT (' Output format: ',A, ' compressed with level: ',I1/) 812 799 813 433 FORMAT (' Cloud droplets treated explicitly using the Lagrangian part', & 814 'icle model') 815 434 FORMAT (' Curvature and solution effecs are considered for growth of', & 800 433 FORMAT (' Cloud droplets treated explicitly using the Lagrangian part','icle model') 801 434 FORMAT (' Curvature and solution effecs are considered for growth of', & 816 802 ' droplets < 1.0E-6 m') 817 803 435 FORMAT (' Droplet collision is handled by ',A,'-kernel') 818 436 FORMAT (' Fast kernel with fixed radius- and dissipation classes ', & 819 'are used'/ & 820 ' number of radius classes: ',I3,' interval ', & 821 '[1.0E-6,2.0E-4] m'/ & 822 ' number of dissipation classes: ',I2,' interval ', & 823 '[0,1000] cm**2/s**3') 804 436 FORMAT (' Fast kernel with fixed radius- and dissipation classes ','are used'/ & 805 ' number of radius classes: ',I3,' interval ','[1.0E-6,2.0E-4] m'/ & 806 ' number of dissipation classes: ',I2,' interval ','[0,1000] cm**2/s**3') 824 807 437 FORMAT (' Droplet collision is switched off') 825 808 826 480 FORMAT (' Particles:'/ & 827 ' ---------'// & 828 ' Particle advection is active (switched on at t = ', F7.1, & 829 ' s)'/ & 830 ' Interpolation of particle velocities is done by using ', A, & 831 ' method'/ & 832 ' Start of new particle generations every ',F6.1,' s'/ & 833 ' Boundary conditions: left/right: ', A, ' north/south: ', A/& 834 ' bottom: ', A, ' top: ', A/& 835 ' Maximum particle age: ',F9.1,' s'/ & 809 480 FORMAT (' Particles:'/ & 810 ' ---------'// & 811 ' Particle advection is active (switched on at t = ', F7.1,' s)'/ & 812 ' Interpolation of particle velocities is done by using ', A,' method'/ & 813 ' Start of new particle generations every ',F6.1,' s'/ & 814 ' Boundary conditions: left/right: ', A, ' north/south: ', A/ & 815 ' bottom: ', A, ' top: ', A/ & 816 ' Maximum particle age: ',F9.1,' s'/ & 836 817 ' Advection stopped at t = ',F9.1,' s'/) 837 818 481 FORMAT (' Particles have random start positions'/) … … 840 821 486 FORMAT (' Particle statistics are written on file'/) 841 822 487 FORMAT (' Number of particle groups: ',I2/) 842 488 FORMAT (' SGS velocity components are used for particle advection'/ &823 488 FORMAT (' SGS velocity components are used for particle advection'/ & 843 824 ' minimum timestep for advection:', F8.5/) 844 489 FORMAT (' Number of particles simultaneously released at each ', & 845 'point: ', I5/) 846 490 FORMAT (' Particle group ',I2,':'/ & 825 489 FORMAT (' Number of particles simultaneously released at each ','point: ', I5/) 826 490 FORMAT (' Particle group ',I2,':'/ & 847 827 ' Particle radius: ',E10.3, 'm') 848 491 FORMAT (' Particle inertia is activated'/ &828 491 FORMAT (' Particle inertia is activated'/ & 849 829 ' density_ratio (rho_fluid/rho_particle) =',F6.3/) 850 830 492 FORMAT (' Particles are advected only passively (no inertia)'/) 851 493 FORMAT (' Boundaries of particle source: x:',F8.1,' - ',F8.1,' m'/& 852 ' y:',F8.1,' - ',F8.1,' m'/& 853 ' z:',F8.1,' - ',F8.1,' m'/& 854 ' Particle distances: dx = ',F8.1,' m dy = ',F8.1, & 855 ' m dz = ',F8.1,' m'/) 856 494 FORMAT (' Output of particle time series in NetCDF format every ', & 857 F8.2,' s'/) 831 493 FORMAT (' Boundaries of particle source: x:',F8.1,' - ',F8.1,' m'/ & 832 ' y:',F8.1,' - ',F8.1,' m'/ & 833 ' z:',F8.1,' - ',F8.1,' m'/ & 834 ' Particle distances: dx = ',F8.1,' m dy = ',F8.1,' m dz = ',F8.1,' m'/) 835 494 FORMAT (' Output of particle time series in NetCDF format every ',F8.2,' s'/) 858 836 495 FORMAT (' Number of particles in total domain: ',I10/) 859 496 FORMAT (' Initial vertical particle positions are interpreted ', &837 496 FORMAT (' Initial vertical particle positions are interpreted ', & 860 838 'as relative to the given topography') 861 839 862 840 END SUBROUTINE lpm_header 863 864 !------------------------------------------------------------------------------ !841 842 !--------------------------------------------------------------------------------------------------! 865 843 ! Description: 866 844 ! ------------ 867 845 !> Writes used particle attributes in header file. 868 !------------------------------------------------------------------------------ !846 !--------------------------------------------------------------------------------------------------! 869 847 SUBROUTINE lpm_check_parameters 870 848 871 849 ! 872 850 !-- Collision kernels: … … 883 861 884 862 CASE DEFAULT 885 message_string = 'unknown collision kernel: collision_kernel = "' // &863 message_string = 'unknown collision kernel: collision_kernel = "' // & 886 864 TRIM( collision_kernel ) // '"' 887 865 CALL message( 'lpm_check_parameters', 'PA0350', 1, 2, 0, 6, 0 ) … … 891 869 892 870 ! 893 !-- Subgrid scale velocites with the simple interpolation method for resolved 894 !-- velocites is not implemented for passive particles. However, for cloud 895 !-- it can be combined as the sgs-velocites for active particles are 896 !-- calculated differently, i.e. no subboxes are needed. 897 IF ( .NOT. TRIM( particle_advection_interpolation ) == 'trilinear' .AND. & 898 use_sgs_for_particles .AND. .NOT. cloud_droplets ) THEN 899 message_string = 'subrgrid scale velocities in combination with ' // & 900 'simple interpolation method is not ' // & 871 !-- Subgrid scale velocites with the simple interpolation method for resolved velocites is not 872 !-- implemented for passive particles. However, for cloud it can be combined as the sgs-velocites 873 !-- for active particles are calculated differently, i.e. no subboxes are needed. 874 IF ( .NOT. TRIM( particle_advection_interpolation ) == 'trilinear' .AND. & 875 use_sgs_for_particles .AND. .NOT. cloud_droplets ) THEN 876 message_string = 'subrgrid scale velocities in combination with ' // & 877 'simple interpolation method is not ' // & 901 878 'implemented' 902 879 CALL message( 'lpm_check_parameters', 'PA0659', 1, 2, 0, 6, 0 ) … … 904 881 905 882 IF ( nested_run .AND. cloud_droplets ) THEN 906 message_string = 'nested runs in combination with cloud droplets ' // &883 message_string = 'nested runs in combination with cloud droplets ' // & 907 884 'is not implemented' 908 885 CALL message( 'lpm_check_parameters', 'PA0687', 1, 2, 0, 6, 0 ) … … 911 888 912 889 END SUBROUTINE lpm_check_parameters 913 914 !------------------------------------------------------------------------------ !890 891 !--------------------------------------------------------------------------------------------------! 915 892 ! Description: 916 893 ! ------------ 917 894 !> Initialize arrays for lpm 918 !------------------------------------------------------------------------------ !895 !--------------------------------------------------------------------------------------------------! 919 896 SUBROUTINE lpm_init_arrays 920 897 921 898 IF ( cloud_droplets ) THEN 922 899 ! 923 900 !-- Liquid water content, change in liquid water content 924 ALLOCATE ( ql_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &901 ALLOCATE ( ql_1(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 925 902 ql_2(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 926 903 !-- Real volume of particles (with weighting), volume of particles 927 ALLOCATE ( ql_v(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &904 ALLOCATE ( ql_v(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 928 905 ql_vp(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 929 906 ENDIF 930 907 931 908 932 ALLOCATE( u_t(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &933 v_t(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &909 ALLOCATE( u_t(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 910 v_t(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 934 911 w_t(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 935 912 ! … … 946 923 947 924 END SUBROUTINE lpm_init_arrays 948 949 !------------------------------------------------------------------------------ !925 926 !--------------------------------------------------------------------------------------------------! 950 927 ! Description: 951 928 ! ------------ 952 929 !> Initialize Lagrangian particle model 953 !------------------------------------------------------------------------------ !930 !--------------------------------------------------------------------------------------------------! 954 931 SUBROUTINE lpm_init 955 932 … … 965 942 966 943 ! 967 !-- In case of oceans runs, the vertical index calculations need an offset, 968 !-- because otherwise the kindices will become negative944 !-- In case of oceans runs, the vertical index calculations need an offset, because otherwise the k 945 !-- indices will become negative 969 946 IF ( ocean_mode ) THEN 970 947 offset_ocean_nzt = nzt … … 973 950 974 951 ! 975 !-- Define block offsets for dividing a gridcell in 8 sub cells 976 !-- See documentation for List of subgrid boxes 977 !-- See pack_and_sort in lpm_pack_arrays.f90 for assignment of the subgrid boxes 952 !-- Define block offsets for dividing a gridcell in 8 sub cells. 953 !-- See documentation for List of subgrid boxes. 954 !-- See pack_and_sort in lpm_pack_arrays.f90 for assignment of the subgrid boxes. 978 955 block_offset(0) = block_offset_def ( 0, 0, 0) 979 956 block_offset(1) = block_offset_def ( 0, 0,-1) … … 987 964 !-- Check the number of particle groups. 988 965 IF ( number_of_particle_groups > max_number_of_particle_groups ) THEN 989 WRITE( message_string, * ) 'max_number_of_particle_groups =', &990 max_number_of_particle_groups , &991 '&number_of_particle_groups reset to ', &966 WRITE( message_string, * ) 'max_number_of_particle_groups =', & 967 max_number_of_particle_groups , & 968 '&number_of_particle_groups reset to ', & 992 969 max_number_of_particle_groups 993 970 CALL message( 'lpm_init', 'PA0213', 0, 1, 0, 6, 0 ) … … 995 972 ENDIF 996 973 ! 997 !-- Check if downward-facing walls exist. This case, reflection boundary 998 !-- conditions (as well as subgrid-scale velocities) may do not work 999 !-- propably (not realized so far). 974 !-- Check if downward-facing walls exist. This case, reflection boundary conditions (as well as 975 !-- subgrid-scale velocities) may do not work properly (not realized so far). 1000 976 IF ( surf_def_h(1)%ns >= 1 ) THEN 1001 WRITE( message_string, * ) 'Overhanging topography do not work '// &977 WRITE( message_string, * ) 'Overhanging topography do not work '// & 1002 978 'with particles' 1003 979 CALL message( 'lpm_init', 'PA0212', 0, 1, 0, 6, 0 ) … … 1019 995 1020 996 ! 1021 !-- If number_particles_per_gridbox is set, the parametres pdx, pdy and pdz are 1022 !-- calculateddiagnostically. Therfore an isotropic distribution is prescribed.997 !-- If number_particles_per_gridbox is set, the parametres pdx, pdy and pdz are calculated 998 !-- diagnostically. Therfore an isotropic distribution is prescribed. 1023 999 IF ( number_particles_per_gridbox /= -1 .AND. & 1024 1000 number_particles_per_gridbox >= 1 ) THEN … … 1026 1002 REAL(number_particles_per_gridbox))**0.3333333_wp 1027 1003 ! 1028 !-- Ensure a smooth value (two significant digits) of distance between 1029 !-- particles (pdx, pdy, pdz). 1004 !-- Ensure a smooth value (two significant digits) of distance between particles (pdx, pdy, pdz). 1030 1005 div = 1000.0_wp 1031 1006 DO WHILE ( pdx(1) < div ) … … 1066 1041 1067 1042 ! 1068 !-- Allocate array required for logarithmic vertical interpolation of 1069 !-- horizontal particle velocities between the surface and the first vertical 1070 !-- grid level. In order to avoid repeated CPU cost-intensive CALLS of 1071 !-- intrinsic FORTRAN procedure LOG(z/z0), LOG(z/z0) is precalculated for 1043 !-- Allocate array required for logarithmic vertical interpolation of horizontal particle velocities 1044 !-- between the surface and the first vertical grid level. In order to avoid repeated CPU 1045 !-- cost-intensive CALLS of intrinsic FORTRAN procedure LOG(z/z0), LOG(z/z0) is precalculated for 1072 1046 !-- several heights. Splitting into 20 sublayers turned out to be sufficient. 1073 !-- To obtain exact height levels of particles, linear interpolation is applied 1074 !-- (see lpm_advec.f90). 1047 !-- To obtain exact height levels of particles, linear interpolation is applied (see lpm_advec.f90). 1075 1048 IF ( constant_flux_layer ) THEN 1076 1049 … … 1079 1052 1080 1053 ! 1081 !-- Calculate horizontal mean value of z0 used for logartihmic 1082 !-- interpolation. Note: this is not exact for heterogeneous z0. 1083 !-- However, sensitivity studies showed that the effect is 1084 !-- negligible. 1085 z0_av_local = SUM( surf_def_h(0)%z0 ) + SUM( surf_lsm_h%z0 ) + & 1086 SUM( surf_usm_h%z0 ) 1054 !-- Calculate horizontal mean value of z0 used for logartihmic interpolation. Note: this is not 1055 !-- exact for heterogeneous z0. 1056 !-- However, sensitivity studies showed that the effect is negligible. 1057 z0_av_local = SUM( surf_def_h(0)%z0 ) + SUM( surf_lsm_h%z0 ) + SUM( surf_usm_h%z0 ) 1087 1058 z0_av_global = 0.0_wp 1088 1059 1089 1060 #if defined( __parallel ) 1090 CALL MPI_ALLREDUCE(z0_av_local, z0_av_global, 1, MPI_REAL, MPI_SUM, & 1091 comm2d, ierr ) 1061 CALL MPI_ALLREDUCE( z0_av_local, z0_av_global, 1, MPI_REAL, MPI_SUM, comm2d, ierr ) 1092 1062 #else 1093 1063 z0_av_global = z0_av_local … … 1143 1113 1144 1114 CASE DEFAULT 1145 WRITE( message_string, * ) 'unknown boundary condition ', &1115 WRITE( message_string, * ) 'unknown boundary condition ', & 1146 1116 'bc_par_b = "', TRIM( bc_par_b ), '"' 1147 1117 CALL message( 'lpm_init', 'PA0217', 1, 2, 0, 6, 0 ) … … 1160 1130 1161 1131 CASE DEFAULT 1162 WRITE( message_string, * ) 'unknown boundary condition ', &1132 WRITE( message_string, * ) 'unknown boundary condition ', & 1163 1133 'bc_par_t = "', TRIM( bc_par_t ), '"' 1164 1134 CALL message( 'lpm_init', 'PA0218', 1, 2, 0, 6, 0 ) … … 1180 1150 1181 1151 CASE DEFAULT 1182 WRITE( message_string, * ) 'unknown boundary condition ', &1152 WRITE( message_string, * ) 'unknown boundary condition ', & 1183 1153 'bc_par_lr = "', TRIM( bc_par_lr ), '"' 1184 1154 CALL message( 'lpm_init', 'PA0219', 1, 2, 0, 6, 0 ) … … 1200 1170 1201 1171 CASE DEFAULT 1202 WRITE( message_string, * ) 'unknown boundary condition ', &1172 WRITE( message_string, * ) 'unknown boundary condition ', & 1203 1173 'bc_par_ns = "', TRIM( bc_par_ns ), '"' 1204 1174 CALL message( 'lpm_init', 'PA0220', 1, 2, 0, 6, 0 ) … … 1217 1187 1218 1188 CASE DEFAULT 1219 WRITE( message_string, * ) 'unknown splitting_mode = "', & 1220 TRIM( splitting_mode ), '"' 1189 WRITE( message_string, * ) 'unknown splitting_mode = "', TRIM( splitting_mode ), '"' 1221 1190 CALL message( 'lpm_init', 'PA0146', 1, 2, 0, 6, 0 ) 1222 1191 … … 1234 1203 1235 1204 CASE DEFAULT 1236 WRITE( message_string, * ) 'unknown splitting function = "', &1205 WRITE( message_string, * ) 'unknown splitting function = "', & 1237 1206 TRIM( splitting_function ), '"' 1238 1207 CALL message( 'lpm_init', 'PA0147', 1, 2, 0, 6, 0 ) … … 1244 1213 1245 1214 ! 1246 !-- For the first model run of a possible job chain initialize the 1247 !-- particle s, otherwise read the particledata from restart file.1248 IF ( TRIM( initializing_actions ) == 'read_restart_data' &1215 !-- For the first model run of a possible job chain initialize the particles, otherwise read the 1216 !-- particle data from restart file. 1217 IF ( TRIM( initializing_actions ) == 'read_restart_data' & 1249 1218 .AND. read_particles_from_restartfile ) THEN 1250 1219 CALL lpm_rrd_local_particles 1251 1220 ELSE 1252 1221 ! 1253 !-- Allocate particle arrays and set attributes of the initial set of 1254 !-- particles, which can bealso periodically released at later times.1255 ALLOCATE( prt_count(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &1222 !-- Allocate particle arrays and set attributes of the initial set of particles, which can be 1223 !-- also periodically released at later times. 1224 ALLOCATE( prt_count(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 1256 1225 grid_particles(nzb+1:nzt,nys:nyn,nxl:nxr) ) 1257 1226 … … 1259 1228 prt_count = 0 1260 1229 ! 1261 !-- initialize counter for particle IDs1230 !-- Initialize counter for particle IDs 1262 1231 grid_particles%id_counter = 1 1263 1232 ! 1264 !-- Initialize all particles with dummy values (otherwise errors may 1265 !-- occur within restart runs). The reason for this is still not clear1266 !-- and may be presumably caused by errors in therespective user-interface.1267 zero_particle = particle_type( 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, &1268 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, &1269 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, &1270 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, &1233 !-- Initialize all particles with dummy values (otherwise errors may occur within restart runs). 1234 !-- The reason for this is still not clear and may be presumably caused by errors in the 1235 !-- respective user-interface. 1236 zero_particle = particle_type( 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 1237 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 1238 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 1239 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 1271 1240 0, 0, 0_idp, .FALSE., -1, -1 ) 1272 1241 1273 1242 particle_groups = particle_groups_type( 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp ) 1274 1243 ! 1275 !-- Set values for the density ratio and radius for all particle 1276 !-- groups, if necessary 1244 !-- Set values for the density ratio and radius for all particle groups, if necessary. 1277 1245 IF ( density_ratio(1) == 9999999.9_wp ) density_ratio(1) = 0.0_wp 1278 1246 IF ( radius(1) == 9999999.9_wp ) radius(1) = 0.0_wp … … 1286 1254 DO i = 1, number_of_particle_groups 1287 1255 IF ( density_ratio(i) /= 0.0_wp .AND. radius(i) == 0 ) THEN 1288 WRITE( message_string, * ) 'particle group #', i, ' has a', &1256 WRITE( message_string, * ) 'particle group #', i, ' has a', & 1289 1257 'density ratio /= 0 but radius = 0' 1290 1258 CALL message( 'lpm_init', 'PA0215', 1, 2, 0, 6, 0 ) … … 1295 1263 1296 1264 ! 1297 !-- Initialize parallel random number sequence seed for particles 1265 !-- Initialize parallel random number sequence seed for particles. 1298 1266 !-- This is done separately here, as thus particle random numbers do not affect the random 1299 1267 !-- numbers used for the flow field (e.g. for generating flow disturbances). … … 1301 1269 seq_random_array_particles = 0 1302 1270 1303 !-- Initializing with random_seed_parallel for every vertical 1304 !-- gridpoint column. 1271 !-- Initializing with random_seed_parallel for every vertical gridpoint column. 1305 1272 random_dummy = 0 1306 1273 DO i = nxl, nxr … … 1322 1289 IF ( write_particle_statistics ) THEN 1323 1290 CALL check_open( 80 ) 1324 WRITE ( 80, 8000 ) current_timestep_number, simulated_time, & 1325 number_of_particles 1291 WRITE ( 80, 8000 ) current_timestep_number, simulated_time, number_of_particles 1326 1292 CALL close_file( 80 ) 1327 1293 ENDIF … … 1333 1299 #endif 1334 1300 1301 ! 1335 1302 !-- next line is in preparation for particle data output 1336 1303 ! CALL dop_init … … 1346 1313 1347 1314 END SUBROUTINE lpm_init 1348 1349 !------------------------------------------------------------------------------ !1315 1316 !--------------------------------------------------------------------------------------------------! 1350 1317 ! Description: 1351 1318 ! ------------ 1352 1319 !> Create Lagrangian particles 1353 !------------------------------------------------------------------------------ !1320 !--------------------------------------------------------------------------------------------------! 1354 1321 SUBROUTINE lpm_create_particle (phase) 1355 1322 … … 1378 1345 REAL(wp) :: rand_contr !< dummy argument for random position 1379 1346 1380 TYPE(particle_type),TARGET :: tmp_particle !< temporary particle used for initialization 1381 1382 1383 ! 1384 !-- Calculate particle positions and store particle attributes, if 1385 !-- particle is situated on this PE 1347 TYPE(particle_type), TARGET :: tmp_particle !< temporary particle used for initialization 1348 1349 1350 ! 1351 !-- Calculate particle positions and store particle attributes, if particle is situated on this PE. 1386 1352 DO loop_stride = 1, 2 1387 1353 first_stride = (loop_stride == 1) … … 1395 1361 !-- Calculate initial_weighting_factor diagnostically 1396 1362 IF ( number_concentration /= -1.0_wp .AND. number_concentration > 0.0_wp ) THEN 1397 initial_weighting_factor = number_concentration * & 1398 pdx(1) * pdy(1) * pdz(1) 1363 initial_weighting_factor = number_concentration * pdx(1) * pdy(1) * pdz(1) 1399 1364 END IF 1400 1365 … … 1406 1371 pos_y = pss(i) 1407 1372 DO WHILE ( pos_y <= psn(i) ) 1408 IF ( pos_y >= nys * dy .AND. & 1409 pos_y < ( nyn + 1 ) * dy ) THEN 1373 IF ( pos_y >= nys * dy .AND. pos_y < ( nyn + 1 ) * dy ) THEN 1410 1374 pos_x = psl(i) 1411 1375 xloop: DO WHILE ( pos_x <= psr(i) ) 1412 IF ( pos_x >= nxl * dx .AND. & 1413 pos_x < ( nxr + 1) * dx ) THEN 1376 IF ( pos_x >= nxl * dx .AND. pos_x < ( nxr + 1) * dx ) THEN 1414 1377 DO j = 1, particles_per_point 1415 1378 n = n + 1 … … 1450 1413 ! 1451 1414 !-- In case of stretching the actual k index is found iteratively 1452 IF ( dz_stretch_level /= -9999999.9_wp .OR. &1415 IF ( dz_stretch_level /= -9999999.9_wp .OR. & 1453 1416 dz_stretch_level_start(1) /= -9999999.9_wp ) THEN 1454 1417 kp = MAX( MINLOC( ABS( tmp_particle%z - zu ), DIM = 1 ) - 1, 1 ) … … 1457 1420 ENDIF 1458 1421 ! 1459 !-- Determine surface level. Therefore, check for 1460 !-- upward-facing wall on w-grid.1422 !-- Determine surface level. Therefore, check for upward-facing wall on 1423 !-- w-grid. 1461 1424 k_surf = topo_top_ind(jp,ip,3) 1462 1425 IF ( seed_follows_topography ) THEN … … 1465 1428 kp = kp + k_surf 1466 1429 tmp_particle%z = tmp_particle%z + zw(k_surf) 1467 ! -- Skip particle release if particle position is1468 !-- above model top, or within topography in case1469 !-- of overhanging structures.1470 IF ( kp > nzt .OR. &1471 .NOT. BTEST( wall_flags_total_0(kp,jp,ip), 0 ) ) THEN1430 ! 1431 !-- Skip particle release if particle position is above model top, or 1432 !-- within topography in case of overhanging structures. 1433 IF ( kp > nzt .OR. & 1434 .NOT. BTEST( wall_flags_total_0(kp,jp,ip), 0 ) ) THEN 1472 1435 pos_x = pos_x + pdx(i) 1473 1436 CYCLE xloop 1474 1437 ENDIF 1475 1438 ! 1476 !-- Skip particle release if particle position is 1477 !-- below surface, or within topography in case 1478 !-- of overhanging structures. 1479 ELSEIF ( .NOT. seed_follows_topography .AND. & 1480 tmp_particle%z <= zw(k_surf) .OR. & 1481 .NOT. BTEST( wall_flags_total_0(kp,jp,ip), 0 ) )& 1482 THEN 1439 !-- Skip particle release if particle position is below surface, or 1440 !-- within topography in case of overhanging structures. 1441 ELSEIF ( .NOT. seed_follows_topography .AND. & 1442 tmp_particle%z <= zw(k_surf) .OR. & 1443 .NOT. BTEST( wall_flags_total_0(kp,jp,ip), 0 ) ) THEN 1483 1444 pos_x = pos_x + pdx(i) 1484 1445 CYCLE xloop … … 1494 1455 write(6,*) 'xu ',ip,jp,kp,nxr,nyn,nzt 1495 1456 ENDIF 1496 grid_particles(kp,jp,ip)%particles(local_count(kp,jp,ip)) = tmp_particle 1457 grid_particles(kp,jp,ip)%particles(local_count(kp,jp,ip)) = & 1458 tmp_particle 1497 1459 ENDIF 1498 1460 ENDDO … … 1513 1475 DO jp = nys, nyn 1514 1476 DO kp = nzb+1, nzt 1515 IF ( phase == PHASE_INIT) THEN1477 IF ( phase == phase_init ) THEN 1516 1478 IF ( local_count(kp,jp,ip) > 0 ) THEN 1517 alloc_size = MAX( INT( local_count(kp,jp,ip) * & 1518 ( 1.0_wp + alloc_factor / 100.0_wp ) ), & 1519 1 ) 1479 alloc_size = MAX( INT( local_count(kp,jp,ip) * & 1480 ( 1.0_wp + alloc_factor / 100.0_wp ) ), 1 ) 1520 1481 ELSE 1521 1482 alloc_size = 1 … … 1525 1486 grid_particles(kp,jp,ip)%particles(n) = zero_particle 1526 1487 ENDDO 1527 ELSEIF ( phase == PHASE_RELEASE) THEN1488 ELSEIF ( phase == phase_release ) THEN 1528 1489 IF ( local_count(kp,jp,ip) > 0 ) THEN 1529 1490 new_size = local_count(kp,jp,ip) + prt_count(kp,jp,ip) 1530 alloc_size = MAX( INT( new_size * ( 1.0_wp + &1531 alloc_factor / 100.0_wp ) ), 1 )1491 alloc_size = MAX( INT( new_size * ( 1.0_wp + & 1492 alloc_factor / 100.0_wp ) ), 1 ) 1532 1493 IF( alloc_size > SIZE( grid_particles(kp,jp,ip)%particles) ) THEN 1533 1494 CALL realloc_particles_array( ip, jp, kp, alloc_size ) … … 1555 1516 DO n = local_start(kp,jp,ip), number_of_particles !only new particles 1556 1517 1557 particles(n)%id = 10000_idp**3 * grid_particles(kp,jp,ip)%id_counter + &1518 particles(n)%id = 10000_idp**3 * grid_particles(kp,jp,ip)%id_counter + & 1558 1519 10000_idp**2 * kp + 10000_idp * jp + ip 1559 1520 ! 1560 1521 !-- Count the number of particles that have been released before 1561 grid_particles(kp,jp,ip)%id_counter = & 1562 grid_particles(kp,jp,ip)%id_counter + 1 1522 grid_particles(kp,jp,ip)%id_counter = grid_particles(kp,jp,ip)%id_counter + 1 1563 1523 1564 1524 ENDDO … … 1585 1545 particles => grid_particles(kp,jp,ip)%particles(1:number_of_particles) 1586 1546 ! 1587 !-- Move only new particles. Moreover, limit random fluctuation 1588 !-- in order to prevent that particles move more than one grid box, 1589 !-- which would lead to problems concerning particle exchange 1590 !-- between processors in case pdx/pdy are larger than dx/dy, 1547 !-- Move only new particles. Moreover, limit random fluctuation in order to prevent that 1548 !-- particles move more than one grid box, which would lead to problems concerning 1549 !-- particle exchange between processors in case pdx/pdy are larger than dx/dy, 1591 1550 !-- respectively. 1592 1551 DO n = local_start(kp,jp,ip), number_of_particles 1593 1552 IF ( psl(particles(n)%group) /= psr(particles(n)%group) ) THEN 1594 1553 CALL random_number_parallel( random_dummy ) 1595 rand_contr = ( random_dummy - 0.5_wp ) * & 1596 pdx(particles(n)%group) 1597 particles(n)%x = particles(n)%x + & 1598 MERGE( rand_contr, SIGN( dx, rand_contr ), & 1599 ABS( rand_contr ) < dx & 1600 ) 1554 rand_contr = ( random_dummy - 0.5_wp ) * pdx(particles(n)%group) 1555 particles(n)%x = particles(n)%x + & 1556 MERGE( rand_contr, SIGN( dx, rand_contr ), & 1557 ABS( rand_contr ) < dx & 1558 ) 1601 1559 ENDIF 1602 1560 IF ( pss(particles(n)%group) /= psn(particles(n)%group) ) THEN 1603 1561 CALL random_number_parallel( random_dummy ) 1604 rand_contr = ( random_dummy - 0.5_wp ) * & 1605 pdy(particles(n)%group) 1606 particles(n)%y = particles(n)%y + & 1607 MERGE( rand_contr, SIGN( dy, rand_contr ), & 1608 ABS( rand_contr ) < dy & 1609 ) 1562 rand_contr = ( random_dummy - 0.5_wp ) * pdy(particles(n)%group) 1563 particles(n)%y = particles(n)%y + & 1564 MERGE( rand_contr, SIGN( dy, rand_contr ), & 1565 ABS( rand_contr ) < dy & 1566 ) 1610 1567 ENDIF 1611 1568 IF ( psb(particles(n)%group) /= pst(particles(n)%group) ) THEN 1612 1569 CALL random_number_parallel( random_dummy ) 1613 rand_contr = ( random_dummy - 0.5_wp ) * & 1614 pdz(particles(n)%group) 1615 particles(n)%z = particles(n)%z + & 1616 MERGE( rand_contr, SIGN( dzw(kp), rand_contr ), & 1617 ABS( rand_contr ) < dzw(kp) & 1618 ) 1570 rand_contr = ( random_dummy - 0.5_wp ) * pdz(particles(n)%group) 1571 particles(n)%z = particles(n)%z + & 1572 MERGE( rand_contr, SIGN( dzw(kp), rand_contr ), & 1573 ABS( rand_contr ) < dzw(kp) & 1574 ) 1619 1575 ENDIF 1620 1576 ENDDO 1621 1577 ! 1622 !-- Identify particles located outside the model domain and reflect 1623 !-- or absorb them ifnecessary.1578 !-- Identify particles located outside the model domain and reflect or absorb them if 1579 !-- necessary. 1624 1580 CALL lpm_boundary_conds( 'bottom/top', i, j, k ) 1625 1581 ! … … 1627 1583 !-- the particle speed is still zero at this point, wall 1628 1584 !-- reflection boundary conditions will not work in this case. 1629 particles => & 1630 grid_particles(kp,jp,ip)%particles(1:number_of_particles) 1585 particles => grid_particles(kp,jp,ip)%particles(1:number_of_particles) 1631 1586 DO n = local_start(kp,jp,ip), number_of_particles 1632 1587 i = particles(n)%x * ddx … … 1660 1615 ENDIF 1661 1616 ! 1662 !-- In case of random_start_position, delete particles identified by 1663 !-- lpm_exchange_horiz and lpm_boundary_conds. Then sort particles into blocks, 1664 !-- which is needed for a fast interpolation of the LES fields on the particle 1665 !-- position. 1617 !-- In case of random_start_position, delete particles identified by lpm_exchange_horiz and 1618 !-- lpm_boundary_conds. Then sort particles into blocks, which is needed for a fast interpolation of 1619 !-- the LES fields on the particle position. 1666 1620 CALL lpm_sort_and_delete 1667 1621 ! … … 1670 1624 DO jp = nys, nyn 1671 1625 DO kp = nzb+1, nzt 1672 number_of_particles = number_of_particles & 1673 + prt_count(kp,jp,ip) 1626 number_of_particles = number_of_particles + prt_count(kp,jp,ip) 1674 1627 ENDDO 1675 1628 ENDDO … … 1679 1632 #if defined( __parallel ) 1680 1633 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 1681 CALL MPI_ALLREDUCE( number_of_particles, total_number_of_particles, 1, &1682 MPI_INTEGER, MPI_SUM,comm2d, ierr )1634 CALL MPI_ALLREDUCE( number_of_particles, total_number_of_particles, 1, MPI_INTEGER, MPI_SUM, & 1635 comm2d, ierr ) 1683 1636 #else 1684 1637 total_number_of_particles = number_of_particles … … 1688 1641 1689 1642 END SUBROUTINE lpm_create_particle 1690 1691 1692 !------------------------------------------------------------------------------ !1643 1644 1645 !--------------------------------------------------------------------------------------------------! 1693 1646 ! Description: 1694 1647 ! ------------ 1695 !> This routine initialize the particles as aerosols with physio-chemical 1696 !> properties. 1697 !------------------------------------------------------------------------------! 1648 !> This routine initializes the particles as aerosols with physio-chemical properties. 1649 !--------------------------------------------------------------------------------------------------! 1698 1650 SUBROUTINE lpm_init_aerosols(local_start) 1651 1652 INTEGER(iwp) :: ip !< 1653 INTEGER(iwp) :: jp !< 1654 INTEGER(iwp) :: kp !< 1655 INTEGER(iwp) :: n !< 1656 1657 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg), INTENT(IN) :: local_start !< 1699 1658 1700 1659 REAL(wp) :: afactor !< curvature effects … … 1703 1662 REAL(wp) :: e_a !< vapor pressure 1704 1663 REAL(wp) :: e_s !< saturation vapor pressure 1664 REAL(wp) :: rmax = 10.0e-6_wp !< maximum aerosol radius 1705 1665 REAL(wp) :: rmin = 0.005e-6_wp !< minimum aerosol radius 1706 REAL(wp) :: r max = 10.0e-6_wp !< maximum aerosol radius1666 REAL(wp) :: r_l !< left radius of bin 1707 1667 REAL(wp) :: r_mid !< mean radius of bin 1708 REAL(wp) :: r_l !< left radius of bin1709 1668 REAL(wp) :: r_r !< right radius of bin 1710 1669 REAL(wp) :: sigma !< surface tension 1711 1670 REAL(wp) :: t_int !< temperature 1712 1671 1713 INTEGER(iwp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg), INTENT(IN) :: local_start !<1714 1715 INTEGER(iwp) :: n !<1716 INTEGER(iwp) :: ip !<1717 INTEGER(iwp) :: jp !<1718 INTEGER(iwp) :: kp !<1719 1672 1720 1673 ! 1721 1674 !-- Set constants for different aerosol species 1722 1675 IF ( TRIM( aero_species ) == 'nacl' ) THEN 1723 molecular_weight_of_solute = 0.05844_wp 1676 molecular_weight_of_solute = 0.05844_wp 1724 1677 rho_s = 2165.0_wp 1725 1678 vanthoff = 2.0_wp 1726 1679 ELSEIF ( TRIM( aero_species ) == 'c3h4o4' ) THEN 1727 molecular_weight_of_solute = 0.10406_wp 1680 molecular_weight_of_solute = 0.10406_wp 1728 1681 rho_s = 1600.0_wp 1729 1682 vanthoff = 1.37_wp 1730 1683 ELSEIF ( TRIM( aero_species ) == 'nh4o3' ) THEN 1731 molecular_weight_of_solute = 0.08004_wp 1684 molecular_weight_of_solute = 0.08004_wp 1732 1685 rho_s = 1720.0_wp 1733 1686 vanthoff = 2.31_wp 1734 1687 ELSE 1735 WRITE( message_string, * ) 'unknown aerosol species ', &1736 'aero_species = "', TRIM( aero_species ), '"'1688 WRITE( message_string, * ) 'unknown aerosol species ', & 1689 'aero_species = "', TRIM( aero_species ), '"' 1737 1690 CALL message( 'lpm_init', 'PA0470', 1, 2, 0, 6, 0 ) 1738 1691 ENDIF … … 1771 1724 CONTINUE 1772 1725 ELSE 1773 WRITE( message_string, * ) 'unknown aerosol type ', &1774 'aero_type = "', TRIM( aero_type ), '"'1726 WRITE( message_string, * ) 'unknown aerosol type ', & 1727 'aero_type = "', TRIM( aero_type ), '"' 1775 1728 CALL message( 'lpm_init', 'PA0459', 1, 2, 0, 6, 0 ) 1776 1729 ENDIF … … 1787 1740 particles => grid_particles(kp,jp,ip)%particles(1:number_of_particles) 1788 1741 1789 dlogr = ( LOG10( rmax) - LOG10(rmin) ) / ( number_of_particles - local_start(kp,jp,ip) + 1 )1790 ! 1791 ! -- Initialize the aerosols with a predefined spectral distribution1792 !-- of the dry radius (logarithmically increasing bins) and a varying1793 !-- weighting factor1742 dlogr = ( LOG10( rmax ) - LOG10( rmin ) ) / & 1743 ( number_of_particles - local_start(kp,jp,ip) + 1 ) 1744 ! 1745 !-- Initialize the aerosols with a predefined spectral distribution of the dry radius 1746 !-- (logarithmically increasing bins) and a varying weighting factor. 1794 1747 DO n = local_start(kp,jp,ip), number_of_particles !only new particles 1795 1748 … … 1799 1752 1800 1753 particles(n)%aux1 = r_mid 1801 particles(n)%weight_factor = &1802 ( na(1) / ( SQRT( 2.0_wp * pi ) * log_sigma(1) ) * &1803 EXP( - LOG10( r_mid / rm(1) )**2 / ( 2.0_wp * log_sigma(1)**2 ) ) + &1804 na(2) / ( SQRT( 2.0_wp * pi ) * log_sigma(2) ) * &1805 EXP( - LOG10( r_mid / rm(2) )**2 / ( 2.0_wp * log_sigma(2)**2 ) ) + &1806 na(3) / ( SQRT( 2.0_wp * pi ) * log_sigma(3) ) * &1807 EXP( - LOG10( r_mid / rm(3) )**2 / ( 2.0_wp * log_sigma(3)**2 ) ) &1808 ) * ( LOG10( r_r) - LOG10(r_l) ) * ( dx * dy * dzw(kp) )1809 1810 ! 1811 !-- Multiply weight_factor with the namelist parameter aero_weight 1812 !-- to increase ordecrease the number of simulated aerosols1754 particles(n)%weight_factor = & 1755 ( na(1) / ( SQRT( 2.0_wp * pi ) * log_sigma(1) ) * & 1756 EXP( - LOG10( r_mid / rm(1) )**2 / ( 2.0_wp * log_sigma(1)**2 ) ) + & 1757 na(2) / ( SQRT( 2.0_wp * pi ) * log_sigma(2) ) * & 1758 EXP( - LOG10( r_mid / rm(2) )**2 / ( 2.0_wp * log_sigma(2)**2 ) ) + & 1759 na(3) / ( SQRT( 2.0_wp * pi ) * log_sigma(3) ) * & 1760 EXP( - LOG10( r_mid / rm(3) )**2 / ( 2.0_wp * log_sigma(3)**2 ) ) & 1761 ) * ( LOG10( r_r ) - LOG10( r_l ) ) * ( dx * dy * dzw(kp) ) 1762 1763 ! 1764 !-- Multiply weight_factor with the namelist parameter aero_weight to increase or 1765 !-- decrease the number of simulated aerosols 1813 1766 particles(n)%weight_factor = particles(n)%weight_factor * aero_weight 1814 1767 ! 1815 1768 !-- Create random numver with parallel number generator 1816 1769 CALL random_number_parallel( random_dummy ) 1817 IF ( particles(n)%weight_factor - FLOOR( particles(n)%weight_factor,KIND=wp)&1770 IF ( particles(n)%weight_factor - FLOOR( particles(n)%weight_factor, KIND=wp ) & 1818 1771 > random_dummy ) THEN 1819 particles(n)%weight_factor = FLOOR(particles(n)%weight_factor,KIND=wp) + 1.0_wp 1772 particles(n)%weight_factor = FLOOR( particles(n)%weight_factor, KIND=wp ) & 1773 + 1.0_wp 1820 1774 ELSE 1821 particles(n)%weight_factor = FLOOR( particles(n)%weight_factor,KIND=wp)1775 particles(n)%weight_factor = FLOOR( particles(n)%weight_factor, KIND=wp ) 1822 1776 ENDIF 1823 1777 ! … … 1827 1781 ENDDO 1828 1782 ! 1829 !-- Set particle radius to equilibrium radius based on the environmental 1830 !-- supersaturation (Khvorostyanov and Curry, 2007, JGR). This avoids 1831 !-- the sometimes lengthy growth toward their equilibrium radius within 1832 !-- the simulation. 1783 !-- Set particle radius to equilibrium radius based on the environmental supersaturation 1784 !-- (Khvorostyanov and Curry, 2007, JGR). This avoids the sometimes lengthy growth toward 1785 !-- their equilibrium radius within the simulation. 1833 1786 t_int = pt(kp,jp,ip) * exner(kp) 1834 1787 … … 1839 1792 afactor = 2.0_wp * sigma / ( rho_l * r_v * t_int ) 1840 1793 1841 bfactor = vanthoff * molecular_weight_of_water * &1794 bfactor = vanthoff * molecular_weight_of_water * & 1842 1795 rho_s / ( molecular_weight_of_solute * rho_l ) 1843 1796 ! 1844 !-- The formula is only valid for subsaturated environments. For 1845 !-- supersaturations higherthan -5 %, the supersaturation is set to -5%.1797 !-- The formula is only valid for subsaturated environments. For supersaturations higher 1798 !-- than -5 %, the supersaturation is set to -5%. 1846 1799 IF ( e_a / e_s >= 0.95_wp ) e_a = 0.95_wp * e_s 1847 1800 … … 1850 1803 !-- For details on this equation, see Eq. (14) of Khvorostyanov and 1851 1804 !-- Curry (2007, JGR) 1852 particles(n)%radius = bfactor**0.3333333_wp * &1853 particles(n)%aux1 / ( 1.0_wp - e_a / e_s )**0.3333333_wp /&1854 ( 1.0_wp + ( afactor / ( 3.0_wp * bfactor**0.3333333_wp *&1855 particles(n)%aux1 ) ) /&1856 ( 1.0_wp - e_a / e_s )**0.6666666_wp&1857 )1805 particles(n)%radius = bfactor**0.3333333_wp * & 1806 particles(n)%aux1 / ( 1.0_wp - e_a / e_s )**0.3333333_wp / & 1807 ( 1.0_wp + ( afactor / ( 3.0_wp * bfactor**0.3333333_wp * & 1808 particles(n)%aux1 ) ) / & 1809 ( 1.0_wp - e_a / e_s )**0.6666666_wp & 1810 ) 1858 1811 1859 1812 ENDDO … … 1869 1822 1870 1823 1871 !------------------------------------------------------------------------------ !1824 !--------------------------------------------------------------------------------------------------! 1872 1825 ! Description: 1873 1826 ! ------------ 1874 !> Calculates quantities required for considering the SGS velocity fluctuations 1875 !> in the particle transport by a stochastic approach. The respective 1876 !> quantities are: SGS-TKE gradients and horizontally averaged profiles of the 1877 !> SGS TKE and the resolved-scale velocity variances. 1878 !------------------------------------------------------------------------------! 1827 !> Calculates quantities required for considering the SGS velocity fluctuations in the particle 1828 !> transport by a stochastic approach. The respective quantities are: SGS-TKE gradients and 1829 !> horizontally averaged profiles of the SGS TKE and the resolved-scale velocity variances. 1830 !--------------------------------------------------------------------------------------------------! 1879 1831 SUBROUTINE lpm_init_sgs_tke 1880 1832 1881 USE exchange_horiz_mod, &1833 USE exchange_horiz_mod, & 1882 1834 ONLY: exchange_horiz 1883 1835 1884 USE statistics, &1836 USE statistics, & 1885 1837 ONLY: flow_statistics_called, hom, sums, sums_l 1886 1838 … … 1888 1840 INTEGER(iwp) :: j !< index variable along y 1889 1841 INTEGER(iwp) :: k !< index variable along z 1890 INTEGER(iwp) :: m !< running index for the surface elements 1842 INTEGER(iwp) :: m !< running index for the surface elements 1891 1843 1892 1844 REAL(wp) :: flag1 !< flag to mask topography … … 1898 1850 DO k = nzb, nzt+1 1899 1851 1900 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i-1), 0 ) .AND. &1901 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. &1902 BTEST( wall_flags_total_0(k,j,i+1), 0 ) ) &1852 IF ( .NOT. BTEST( wall_flags_total_0(k,j,i-1), 0 ) .AND. & 1853 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 1854 BTEST( wall_flags_total_0(k,j,i+1), 0 ) ) & 1903 1855 THEN 1904 de_dx(k,j,i) = 2.0_wp * sgs_wf_part * & 1905 ( e(k,j,i+1) - e(k,j,i) ) * ddx 1906 ELSEIF ( BTEST( wall_flags_total_0(k,j,i-1), 0 ) .AND. & 1907 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 1908 .NOT. BTEST( wall_flags_total_0(k,j,i+1), 0 ) ) & 1856 de_dx(k,j,i) = 2.0_wp * sgs_wf_part * ( e(k,j,i+1) - e(k,j,i) ) * ddx 1857 ELSEIF ( BTEST( wall_flags_total_0(k,j,i-1), 0 ) .AND. & 1858 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 1859 .NOT. BTEST( wall_flags_total_0(k,j,i+1), 0 ) ) & 1909 1860 THEN 1910 de_dx(k,j,i) = 2.0_wp * sgs_wf_part * & 1911 ( e(k,j,i) - e(k,j,i-1) ) * ddx 1912 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) .AND. & 1913 .NOT. BTEST( wall_flags_total_0(k,j,i+1), 22 ) ) & 1861 de_dx(k,j,i) = 2.0_wp * sgs_wf_part * ( e(k,j,i) - e(k,j,i-1) ) * ddx 1862 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) .AND. & 1863 .NOT. BTEST( wall_flags_total_0(k,j,i+1), 22 ) ) & 1914 1864 THEN 1915 1865 de_dx(k,j,i) = 0.0_wp 1916 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j,i-1), 22 ) .AND. &1917 .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) ) &1866 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j,i-1), 22 ) .AND. & 1867 .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) ) & 1918 1868 THEN 1919 1869 de_dx(k,j,i) = 0.0_wp … … 1922 1872 ENDIF 1923 1873 1924 IF ( .NOT. BTEST( wall_flags_total_0(k,j-1,i), 0 ) .AND. &1925 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. &1926 BTEST( wall_flags_total_0(k,j+1,i), 0 ) ) &1874 IF ( .NOT. BTEST( wall_flags_total_0(k,j-1,i), 0 ) .AND. & 1875 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 1876 BTEST( wall_flags_total_0(k,j+1,i), 0 ) ) & 1927 1877 THEN 1928 de_dy(k,j,i) = 2.0_wp * sgs_wf_part * & 1929 ( e(k,j+1,i) - e(k,j,i) ) * ddy 1930 ELSEIF ( BTEST( wall_flags_total_0(k,j-1,i), 0 ) .AND. & 1931 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 1932 .NOT. BTEST( wall_flags_total_0(k,j+1,i), 0 ) ) & 1878 de_dy(k,j,i) = 2.0_wp * sgs_wf_part * ( e(k,j+1,i) - e(k,j,i) ) * ddy 1879 ELSEIF ( BTEST( wall_flags_total_0(k,j-1,i), 0 ) .AND. & 1880 BTEST( wall_flags_total_0(k,j,i), 0 ) .AND. & 1881 .NOT. BTEST( wall_flags_total_0(k,j+1,i), 0 ) ) & 1933 1882 THEN 1934 de_dy(k,j,i) = 2.0_wp * sgs_wf_part * & 1935 ( e(k,j,i) - e(k,j-1,i) ) * ddy 1936 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) .AND. & 1937 .NOT. BTEST( wall_flags_total_0(k,j+1,i), 22 ) ) & 1883 de_dy(k,j,i) = 2.0_wp * sgs_wf_part * ( e(k,j,i) - e(k,j-1,i) ) * ddy 1884 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) .AND. & 1885 .NOT. BTEST( wall_flags_total_0(k,j+1,i), 22 ) ) & 1938 1886 THEN 1939 1887 de_dy(k,j,i) = 0.0_wp 1940 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j-1,i), 22 ) .AND. &1941 .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) ) &1888 ELSEIF ( .NOT. BTEST( wall_flags_total_0(k,j-1,i), 22 ) .AND. & 1889 .NOT. BTEST( wall_flags_total_0(k,j,i), 22 ) ) & 1942 1890 THEN 1943 1891 de_dy(k,j,i) = 0.0_wp … … 1959 1907 flag1 = MERGE( 1.0_wp, 0.0_wp, BTEST( wall_flags_total_0(k,j,i), 0 ) ) 1960 1908 1961 de_dz(k,j,i) = 2.0_wp * sgs_wf_part * & 1962 ( e(k+1,j,i) - e(k-1,j,i) ) / ( zu(k+1) - zu(k-1) ) & 1963 * flag1 1909 de_dz(k,j,i) = 2.0_wp * sgs_wf_part * & 1910 ( e(k+1,j,i) - e(k-1,j,i) ) / ( zu(k+1) - zu(k-1) ) * flag1 1964 1911 ENDDO 1965 1912 ! … … 1967 1914 DO m = bc_h(0)%start_index(j,i), bc_h(0)%end_index(j,i) 1968 1915 k = bc_h(0)%k(m) 1969 de_dz(k,j,i) = 2.0_wp * sgs_wf_part * & 1970 ( e(k+1,j,i) - e(k,j,i) ) / ( zu(k+1) - zu(k) ) 1916 de_dz(k,j,i) = 2.0_wp * sgs_wf_part * ( e(k+1,j,i) - e(k,j,i) ) / ( zu(k+1) - zu(k) ) 1971 1917 ENDDO 1972 1918 ! … … 1974 1920 DO m = bc_h(1)%start_index(j,i), bc_h(1)%end_index(j,i) 1975 1921 k = bc_h(1)%k(m) 1976 de_dz(k,j,i) = 2.0_wp * sgs_wf_part * & 1977 ( e(k,j,i) - e(k-1,j,i) ) / ( zu(k) - zu(k-1) ) 1922 de_dz(k,j,i) = 2.0_wp * sgs_wf_part * ( e(k,j,i) - e(k-1,j,i) ) / ( zu(k) - zu(k-1) ) 1978 1923 ENDDO 1979 1924 … … 1990 1935 CALL exchange_horiz( diss, nbgp ) 1991 1936 ! 1992 !-- Set boundary conditions at non-periodic boundaries. Note, at non-period 1993 !-- boundaries zero-gradient boundary conditions are set for the subgrid TKE. 1994 !-- Thus, TKE gradients normal to the respective lateral boundaries are zero, 1995 !-- while tangetial TKE gradients then must be the same as within the prognostic 1996 !-- domain. 1937 !-- Set boundary conditions at non-periodic boundaries. Note, at non-period boundaries zero-gradient 1938 !-- boundary conditions are set for the subgrid TKE. 1939 !-- Thus, TKE gradients normal to the respective lateral boundaries are zero, 1940 !-- while tangetial TKE gradients then must be the same as within the prognostic domain. 1997 1941 IF ( bc_dirichlet_l ) THEN 1998 1942 de_dx(:,:,-1) = 0.0_wp 1999 de_dy(:,:,-1) = de_dy(:,:,0) 1943 de_dy(:,:,-1) = de_dy(:,:,0) 2000 1944 de_dz(:,:,-1) = de_dz(:,:,0) 2001 1945 ENDIF 2002 1946 IF ( bc_dirichlet_r ) THEN 2003 1947 de_dx(:,:,nxr+1) = 0.0_wp 2004 de_dy(:,:,nxr+1) = de_dy(:,:,nxr) 1948 de_dy(:,:,nxr+1) = de_dy(:,:,nxr) 2005 1949 de_dz(:,:,nxr+1) = de_dz(:,:,nxr) 2006 1950 ENDIF 2007 1951 IF ( bc_dirichlet_n ) THEN 2008 1952 de_dx(:,nyn+1,:) = de_dx(:,nyn,:) 2009 de_dy(:,nyn+1,:) = 0.0_wp 1953 de_dy(:,nyn+1,:) = 0.0_wp 2010 1954 de_dz(:,nyn+1,:) = de_dz(:,nyn,:) 2011 1955 ENDIF 2012 1956 IF ( bc_dirichlet_s ) THEN 2013 1957 de_dx(:,nys-1,:) = de_dx(:,nys,:) 2014 de_dy(:,nys-1,:) = 0.0_wp 1958 de_dy(:,nys-1,:) = 0.0_wp 2015 1959 de_dz(:,nys-1,:) = de_dz(:,nys,:) 2016 ENDIF 2017 ! 2018 !-- Calculate the horizontally averaged profiles of SGS TKE and resolved 2019 !-- velocity variances (they may have been already calculated in routine 2020 !-- flow_statistics). 1960 ENDIF 1961 ! 1962 !-- Calculate the horizontally averaged profiles of SGS TKE and resolved velocity variances (they 1963 !-- may have been already calculated in routine flow_statistics). 2021 1964 IF ( .NOT. flow_statistics_called ) THEN 2022 1965 2023 1966 ! 2024 !-- First calculate horizontally averaged profiles of the horizontal 2025 !-- velocities. 1967 !-- First calculate horizontally averaged profiles of the horizontal velocities. 2026 1968 sums_l(:,1,0) = 0.0_wp 2027 1969 sums_l(:,2,0) = 0.0_wp … … 2044 1986 !-- Compute total sum from local sums 2045 1987 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2046 CALL MPI_ALLREDUCE( sums_l(nzb,1,0), sums(nzb,1), nzt+2-nzb, &2047 MPI_REAL, MPI_SUM, comm2d,ierr )1988 CALL MPI_ALLREDUCE( sums_l(nzb,1,0), sums(nzb,1), nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, & 1989 ierr ) 2048 1990 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2049 CALL MPI_ALLREDUCE( sums_l(nzb,2,0), sums(nzb,2), nzt+2-nzb, &2050 MPI_REAL, MPI_SUM, comm2d,ierr )1991 CALL MPI_ALLREDUCE( sums_l(nzb,2,0), sums(nzb,2), nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, & 1992 ierr ) 2051 1993 #else 2052 1994 sums(:,1) = sums_l(:,1,0) … … 2055 1997 2056 1998 ! 2057 !-- Final values are obtained by division by the total number of grid 2058 !-- points used for thesummation.1999 !-- Final values are obtained by division by the total number of grid points used for the 2000 !-- summation. 2059 2001 hom(:,1,1,0) = sums(:,1) / ngp_2dh_outer(:,0) ! u 2060 2002 hom(:,1,2,0) = sums(:,2) / ngp_2dh_outer(:,0) ! v 2061 2003 2062 2004 ! 2063 !-- Now calculate the profiles of SGS TKE and the resolved-scale 2064 !-- velocity variances 2005 !-- Now calculate the profiles of SGS TKE and the resolved-scale velocity variances 2065 2006 sums_l(:,8,0) = 0.0_wp 2066 2007 sums_l(:,30,0) = 0.0_wp … … 2086 2027 !-- Compute total sum from local sums 2087 2028 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2088 CALL MPI_ALLREDUCE( sums_l(nzb,8,0), sums(nzb,8), nzt+2-nzb, &2089 MPI_REAL, MPI_SUM, comm2d,ierr )2029 CALL MPI_ALLREDUCE( sums_l(nzb,8,0), sums(nzb,8), nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, & 2030 ierr ) 2090 2031 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2091 CALL MPI_ALLREDUCE( sums_l(nzb,30,0), sums(nzb,30), nzt+2-nzb, &2092 MPI_REAL, MPI_SUM, comm2d,ierr )2032 CALL MPI_ALLREDUCE( sums_l(nzb,30,0), sums(nzb,30), nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, & 2033 ierr ) 2093 2034 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2094 CALL MPI_ALLREDUCE( sums_l(nzb,31,0), sums(nzb,31), nzt+2-nzb, &2095 MPI_REAL, MPI_SUM, comm2d,ierr )2035 CALL MPI_ALLREDUCE( sums_l(nzb,31,0), sums(nzb,31), nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, & 2036 ierr ) 2096 2037 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2097 CALL MPI_ALLREDUCE( sums_l(nzb,32,0), sums(nzb,32), nzt+2-nzb, &2098 MPI_REAL, MPI_SUM, comm2d,ierr )2038 CALL MPI_ALLREDUCE( sums_l(nzb,32,0), sums(nzb,32), nzt+2-nzb, MPI_REAL, MPI_SUM, comm2d, & 2039 ierr ) 2099 2040 2100 2041 #else … … 2106 2047 2107 2048 ! 2108 !-- Final values are obtained by division by the total number of grid 2109 !-- points used for thesummation.2049 !-- Final values are obtained by division by the total number of grid points used for the 2050 !-- summation. 2110 2051 hom(:,1,8,0) = sums(:,8) / ngp_2dh_outer(:,0) ! e 2111 2052 hom(:,1,30,0) = sums(:,30) / ngp_2dh_outer(:,0) ! u*2 2112 hom(:,1,31,0) = sums(:,31) / ngp_2dh_outer(:,0) ! v*2 2053 hom(:,1,31,0) = sums(:,31) / ngp_2dh_outer(:,0) ! v*2 2113 2054 hom(:,1,32,0) = sums(:,32) / ngp_2dh_outer(:,0) ! w*2 2114 2055 … … 2116 2057 2117 2058 END SUBROUTINE lpm_init_sgs_tke 2118 2119 2120 !------------------------------------------------------------------------------ !2059 2060 2061 !--------------------------------------------------------------------------------------------------! 2121 2062 ! Description: 2122 2063 ! ------------ 2123 !> Sobroutine control lpm actions, i.e. all actions during one time step. 2124 !------------------------------------------------------------------------------ !2064 !> Sobroutine control lpm actions, i.e. all actions during one time step. 2065 !--------------------------------------------------------------------------------------------------! 2125 2066 SUBROUTINE lpm_actions( location ) 2126 2067 2127 USE exchange_horiz_mod, &2068 USE exchange_horiz_mod, & 2128 2069 ONLY: exchange_horiz 2129 2070 … … 2152 2093 !-- The particle model is executed if particle advection start is reached and only at the end 2153 2094 !-- of the intermediate time step loop. 2154 IF ( time_since_reference_point >= particle_advection_start &2095 IF ( time_since_reference_point >= particle_advection_start & 2155 2096 .AND. intermediate_timestep_count == intermediate_timestep_count_max ) & 2156 2097 THEN … … 2158 2099 ! 2159 2100 !-- Write particle data at current time on file. 2160 !-- This has to be done here, before particles are further processed, 2161 !-- because they may be deleted within this timestep (in case that2162 !-- dt_write_particle_data = dt_prel =particle_maximum_age).2101 !-- This has to be done here, before particles are further processed, because they may be 2102 !-- deleted within this timestep (in case that dt_write_particle_data = dt_prel = 2103 !-- particle_maximum_age). 2163 2104 time_write_particle_data = time_write_particle_data + dt_3d 2164 2105 IF ( time_write_particle_data >= dt_write_particle_data ) THEN … … 2166 2107 CALL lpm_data_output_particles 2167 2108 ! 2168 !-- The MOD function allows for changes in the output interval with restart 2169 !-- runs. 2170 time_write_particle_data = MOD( time_write_particle_data, & 2109 !-- The MOD function allows for changes in the output interval with restart runs. 2110 time_write_particle_data = MOD( time_write_particle_data, & 2171 2111 MAX( dt_write_particle_data, dt_3d ) ) 2172 2112 ENDIF 2173 2113 2174 2114 ! 2175 !-- Initialize arrays for marking those particles to be deleted after the 2176 !-- (sub-) timestep 2115 !-- Initialize arrays for marking those particles to be deleted after the (sub-) timestep. 2177 2116 deleted_particles = 0 2178 2117 2179 2118 ! 2180 !-- Initialize variables used for accumulating the number of particles 2181 !-- xchanged between the subdomains during all sub-timesteps (if sgs 2182 !-- velocities are included). These data are output further below on the 2183 !-- particle statistics file. 2119 !-- Initialize variables used for accumulating the number of particles exchanged between 2120 !-- the subdomains during all sub-timesteps (if sgs velocities are included). These data 2121 !-- are output further below on the particle statistics file. 2184 2122 trlp_count_sum = 0 2185 2123 trlp_count_recv_sum = 0 … … 2195 2133 DO m = 1, number_of_particle_groups 2196 2134 IF ( particle_groups(m)%density_ratio /= 0.0_wp ) THEN 2197 particle_groups(m)%exp_arg = & 2198 4.5_wp * particle_groups(m)%density_ratio * & 2199 molecular_viscosity / ( particle_groups(m)%radius )**2 2200 2201 particle_groups(m)%exp_term = EXP( -particle_groups(m)%exp_arg * & 2202 dt_3d ) 2135 particle_groups(m)%exp_arg = 4.5_wp * particle_groups(m)%density_ratio * & 2136 molecular_viscosity / & 2137 ( particle_groups(m)%radius )**2 2138 2139 particle_groups(m)%exp_term = EXP( -particle_groups(m)%exp_arg * dt_3d ) 2203 2140 ENDIF 2204 2141 ENDDO 2205 2142 ! 2206 2143 !-- If necessary, release new set of particles 2207 IF ( ( simulated_time - last_particle_release_time ) >= dt_prel .AND. &2144 IF ( ( simulated_time - last_particle_release_time ) >= dt_prel .AND. & 2208 2145 end_time_prel > simulated_time ) THEN 2209 2146 DO WHILE ( ( simulated_time - last_particle_release_time ) >= dt_prel ) 2210 CALL lpm_create_particle( PHASE_RELEASE)2147 CALL lpm_create_particle( phase_release ) 2211 2148 last_particle_release_time = last_particle_release_time + dt_prel 2212 2149 ENDDO … … 2224 2161 ! 2225 2162 !-- Timestep loop for particle advection. 2226 !-- This loop has to be repeated until the advection time of every particle 2227 !-- (within the total domain!) has reached the LES timestep (dt_3d). 2228 !-- In case of including the SGS velocities, the particle timestep may be 2229 !-- smaller than the LES timestep (because of the Lagrangian timescale 2230 !-- restriction) and particles may require to undergo several particle 2231 !-- timesteps, before the LES timestep is reached. Because the number of these 2232 !-- particle timesteps to be carried out is unknown at first, these steps are 2233 !-- carried out in the following infinite loop with exit condition. 2163 !-- This loop has to be repeated until the advection time of every particle (within the 2164 !-- total domain!) has reached the LES timestep (dt_3d). 2165 !-- In case of including the SGS velocities, the particle timestep may be smaller than the 2166 !-- LES timestep (because of the Lagrangian timescale restriction) and particles may 2167 !-- require to undergo several particle timesteps, before the LES timestep is reached. 2168 !-- Because the number of these particle timesteps to be carried out is unknown at first, 2169 !-- these steps are carried out in the following infinite loop with exit condition. 2234 2170 DO 2235 2171 CALL cpu_log( log_point_s(44), 'lpm_advec', 'start' ) … … 2237 2173 2238 2174 ! 2239 !-- If particle advection includes SGS velocity components, calculate the 2240 !-- required SGS quantities (i.e. gradients of the TKE, as well as 2241 !-- horizontally averaged profiles of the SGS TKE and the resolved-scale 2242 !-- velocity variances) 2175 !-- If particle advection includes SGS velocity components, calculate the required SGS 2176 !-- quantities (i.e. gradients of the TKE, as well as horizontally averaged profiles of 2177 !-- the SGS TKE and the resolved-scale velocity variances) 2243 2178 IF ( use_sgs_for_particles .AND. .NOT. cloud_droplets ) THEN 2244 2179 CALL lpm_init_sgs_tke 2245 2180 ENDIF 2246 2181 ! 2247 !-- In case SGS-particle speed is considered, particles may carry out 2248 !-- several particle timesteps. In order to prevent unnecessary 2249 !-- treatment of particles that already reached the final time level, 2250 !-- particles are sorted into contiguous blocks of finished and 2251 !-- not-finished particles, in addition to their already sorting 2182 !-- In case SGS-particle speed is considered, particles may carry out several particle 2183 !-- timesteps. In order to prevent unnecessary treatment of particles that already 2184 !-- reached the final time level, particles are sorted into contiguous blocks of 2185 !-- finished and not-finished particles, in addition to their already sorting 2252 2186 !-- according to their sub-boxes. 2253 IF ( .NOT. first_loop_stride .AND. use_sgs_for_particles ) &2187 IF ( .NOT. first_loop_stride .AND. use_sgs_for_particles ) & 2254 2188 CALL lpm_sort_timeloop_done 2255 2189 DO i = nxl, nxr … … 2276 2210 particles(1:number_of_particles)%particle_mask = .TRUE. 2277 2211 ! 2278 !-- Initialize the variable storing the total time that a particle 2279 !-- has advanced within the timestep procedure2212 !-- Initialize the variable storing the total time that a particle has advanced 2213 !-- within the timestep procedure. 2280 2214 IF ( first_loop_stride ) THEN 2281 2215 particles(1:number_of_particles)%dt_sum = 0.0_wp 2282 2216 ENDIF 2283 2217 ! 2284 !-- Particle (droplet) growth by condensation/evaporation and 2285 !-- collision 2218 !-- Particle (droplet) growth by condensation/evaporation and collision 2286 2219 IF ( cloud_droplets .AND. first_loop_stride) THEN 2287 2220 ! … … 2296 2229 ENDIF 2297 2230 ! 2298 !-- Initialize the switch used for the loop exit condition checked 2299 !-- at the end of this loop. If at least one particle has failed to 2300 !-- reach the LES timestep, this switch will be set false in 2301 !-- lpm_advec. 2231 !-- Initialize the switch used for the loop exit condition checked at the end 2232 !-- of this loop. If at least one particle has failed to reach the LES 2233 !-- timestep, this switch will be set false in lpm_advec. 2302 2234 dt_3d_reached_l = .TRUE. 2303 2235 … … 2306 2238 CALL lpm_advec( i, j, k ) 2307 2239 ! 2308 !-- Particle reflection from walls. Only applied if the particles 2309 !-- are in the vertical range of the topography. (Here, some2310 !-- optimization is stillpossible.)2240 !-- Particle reflection from walls. Only applied if the particles are in the 2241 !-- vertical range of the topography. (Here, some optimization is still 2242 !-- possible.) 2311 2243 IF ( topography /= 'flat' .AND. k < nzb_max + 2 ) THEN 2312 2244 CALL lpm_boundary_conds( 'walls', i, j, k ) 2313 2245 ENDIF 2314 2246 ! 2315 !-- User-defined actions after the calculation of the new particle 2316 !-- position 2247 !-- User-defined actions after the calculation of the new particle position 2317 2248 CALL user_lpm_advec( i, j, k ) 2318 2249 ! 2319 !-- Apply boundary conditions to those particles that have crossed 2320 !-- the top or bottom boundary and delete those particles, which are 2321 !-- older than allowed 2250 !-- Apply boundary conditions to those particles that have crossed the top or 2251 !-- bottom boundary and delete those particles, which are older than allowed 2322 2252 CALL lpm_boundary_conds( 'bottom/top', i, j, k ) 2323 2253 ! 2324 !--- If not all particles of the actual grid cell have reached the 2325 !-- LES timestep, this cell has to do another loop iteration. Due to2326 !-- the fact that particles can move into neighboring grid cells,2327 !-- these neighbor cells also have toperform another loop iteration.2328 !-- Please note, this realization does not work properly if 2329 !-- particles move intoanother subdomain.2254 !--- If not all particles of the actual grid cell have reached the LES timestep, 2255 !-- this cell has to do another loop iteration. Due to the fact that particles 2256 !-- can move into neighboring grid cells, these neighbor cells also have to 2257 !-- perform another loop iteration. 2258 !-- Please note, this realization does not work properly if particles move into 2259 !-- another subdomain. 2330 2260 IF ( .NOT. dt_3d_reached_l ) THEN 2331 2261 ks = MAX(nzb+1,k-1) … … 2350 2280 dt_3d_reached_l = ALL(grid_particles(:,:,:)%time_loop_done) 2351 2281 ! 2352 !-- Find out, if all particles on every PE have completed the LES timestep 2353 !-- and set theswitch corespondingly2282 !-- Find out, if all particles on every PE have completed the LES timestep and set the 2283 !-- switch corespondingly 2354 2284 #if defined( __parallel ) 2355 2285 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2356 CALL MPI_ALLREDUCE( dt_3d_reached_l, dt_3d_reached, 1, MPI_LOGICAL, &2357 MPI_LAND,comm2d, ierr )2286 CALL MPI_ALLREDUCE( dt_3d_reached_l, dt_3d_reached, 1, MPI_LOGICAL, MPI_LAND, & 2287 comm2d, ierr ) 2358 2288 #else 2359 2289 dt_3d_reached = dt_3d_reached_l … … 2382 2312 IF ( .NOT. dt_3d_reached .OR. .NOT. nested_run ) THEN 2383 2313 ! 2384 !-- Pack particles (eliminate those marked for deletion), 2385 !-- determine new number ofparticles2314 !-- Pack particles (eliminate those marked for deletion), determine new number of 2315 !-- particles 2386 2316 CALL lpm_sort_and_delete 2387 2317 2388 !-- Initialize variables for the next (sub-) timestep, i.e., for marking 2389 !-- thoseparticles to be deleted after the timestep2318 !-- Initialize variables for the next (sub-) timestep, i.e., for marking those 2319 !-- particles to be deleted after the timestep 2390 2320 deleted_particles = 0 2391 2321 ENDIF … … 2398 2328 #if defined( __parallel ) 2399 2329 ! 2400 !-- in case of nested runs do the transfer of particles after every full model time step2330 !-- In case of nested runs do the transfer of particles after every full model time step 2401 2331 IF ( nested_run ) THEN 2402 2332 CALL particles_from_parent_to_child … … 2433 2363 2434 2364 ! 2435 !-- Write particle statistics (in particular the number of particles 2436 !-- exchanged between thesubdomains) on file2365 !-- Write particle statistics (in particular the number of particles exchanged between the 2366 !-- subdomains) on file 2437 2367 IF ( write_particle_statistics ) CALL lpm_write_exchange_statistics 2438 2368 ! 2439 !-- Execute Interactions of condnesation and evaporation to humidity and 2440 !-- temperature field 2369 !-- Execute Interactions of condnesation and evaporation to humidity and temperature field 2441 2370 IF ( cloud_droplets ) THEN 2442 2371 CALL lpm_interaction_droplets_ptq … … 2465 2394 CASE ( 'after_integration' ) 2466 2395 ! 2467 !-- Call at the end of timestep routine to save particle velocities fields 2468 !-- for the nexttimestep2396 !-- Call at the end of timestep routine to save particle velocities fields for the next 2397 !-- timestep 2469 2398 CALL lpm_swap_timelevel_for_particle_advection 2470 2399 … … 2475 2404 2476 2405 END SUBROUTINE lpm_actions 2477 2406 2478 2407 2479 2408 #if defined( __parallel ) 2480 !------------------------------------------------------------------------------ !2409 !--------------------------------------------------------------------------------------------------! 2481 2410 ! Description: 2482 2411 ! ------------ 2483 2412 ! 2484 !------------------------------------------------------------------------------ !2413 !--------------------------------------------------------------------------------------------------! 2485 2414 SUBROUTINE particles_from_parent_to_child 2486 2415 … … 2492 2421 END SUBROUTINE particles_from_parent_to_child 2493 2422 2494 2495 !------------------------------------------------------------------------------ !2423 2424 !--------------------------------------------------------------------------------------------------! 2496 2425 ! Description: 2497 2426 ! ------------ 2498 2427 ! 2499 !------------------------------------------------------------------------------ !2428 !--------------------------------------------------------------------------------------------------! 2500 2429 SUBROUTINE particles_from_child_to_parent 2501 2430 … … 2507 2436 END SUBROUTINE particles_from_child_to_parent 2508 2437 #endif 2509 2510 !------------------------------------------------------------------------------ !2438 2439 !--------------------------------------------------------------------------------------------------! 2511 2440 ! Description: 2512 2441 ! ------------ 2513 !> This routine write exchange statistics of the lpm in a ascii file. 2514 !------------------------------------------------------------------------------ !2442 !> This routine write exchange statistics of the lpm in a ascii file. 2443 !--------------------------------------------------------------------------------------------------! 2515 2444 SUBROUTINE lpm_write_exchange_statistics 2516 2445 … … 2526 2455 DO jp = nys, nyn 2527 2456 DO kp = nzb+1, nzt 2528 number_of_particles = number_of_particles & 2529 + prt_count(kp,jp,ip) 2457 number_of_particles = number_of_particles + prt_count(kp,jp,ip) 2530 2458 ENDDO 2531 2459 ENDDO … … 2534 2462 CALL check_open( 80 ) 2535 2463 #if defined( __parallel ) 2536 WRITE ( 80, 8000 ) current_timestep_number+1, simulated_time+dt_3d, & 2537 number_of_particles, pleft, trlp_count_sum, & 2538 trlp_count_recv_sum, pright, trrp_count_sum, & 2539 trrp_count_recv_sum, psouth, trsp_count_sum, & 2540 trsp_count_recv_sum, pnorth, trnp_count_sum, & 2541 trnp_count_recv_sum 2464 WRITE ( 80, 8000 ) current_timestep_number+1, simulated_time+dt_3d, number_of_particles, & 2465 pleft, trlp_count_sum, trlp_count_recv_sum, pright, trrp_count_sum, & 2466 trrp_count_recv_sum, psouth, trsp_count_sum, trsp_count_recv_sum, pnorth, & 2467 trnp_count_sum, trnp_count_recv_sum 2542 2468 #else 2543 WRITE ( 80, 8000 ) current_timestep_number+1, simulated_time+dt_3d, & 2544 number_of_particles 2469 WRITE ( 80, 8000 ) current_timestep_number+1, simulated_time+dt_3d, number_of_particles 2545 2470 #endif 2546 2471 CALL close_file( 80 ) 2547 2472 2548 2473 IF ( number_of_particles > 0 ) THEN 2549 WRITE(9,*) 'number_of_particles ', number_of_particles, 2550 current_timestep_number + 1,simulated_time + dt_3d2474 WRITE(9,*) 'number_of_particles ', number_of_particles, current_timestep_number + 1, & 2475 simulated_time + dt_3d 2551 2476 ENDIF 2552 2477 2553 2478 #if defined( __parallel ) 2554 CALL MPI_ALLREDUCE( number_of_particles, tot_number_of_particles, 1, 2555 MPI_INTEGER, MPI_SUM,comm2d, ierr )2479 CALL MPI_ALLREDUCE( number_of_particles, tot_number_of_particles, 1, MPI_INTEGER, MPI_SUM, & 2480 comm2d, ierr ) 2556 2481 #else 2557 2482 tot_number_of_particles = number_of_particles … … 2560 2485 #if defined( __parallel ) 2561 2486 IF ( nested_run ) THEN 2562 CALL pmcp_g_print_number_of_particles( simulated_time+dt_3d, & 2563 tot_number_of_particles) 2487 CALL pmcp_g_print_number_of_particles( simulated_time + dt_3d, tot_number_of_particles) 2564 2488 ENDIF 2565 2489 #endif … … 2571 2495 2572 2496 END SUBROUTINE lpm_write_exchange_statistics 2573 2574 2575 !------------------------------------------------------------------------------ !2497 2498 2499 !--------------------------------------------------------------------------------------------------! 2576 2500 ! Description: 2577 2501 ! ------------ 2578 !> Write particle data in FORTRAN binary and/or netCDF format 2579 !------------------------------------------------------------------------------ !2502 !> Write particle data in FORTRAN binary and/or netCDF format 2503 !--------------------------------------------------------------------------------------------------! 2580 2504 SUBROUTINE lpm_data_output_particles 2581 2505 2582 2506 INTEGER(iwp) :: ip !< 2583 2507 INTEGER(iwp) :: jp !< … … 2587 2511 2588 2512 ! 2589 !-- Attention: change version number for unit 85 (in routine check_open) 2590 !-- whenever the output formatfor this unit is changed!2513 !-- Attention: change version number for unit 85 (in routine check_open) whenever the output format 2514 !-- for this unit is changed! 2591 2515 CALL check_open( 85 ) 2592 2516 … … 2612 2536 ! !-- Output in netCDF format 2613 2537 ! CALL check_open( 108 ) 2614 ! 2538 ! 2615 2539 ! ! 2616 2540 ! !-- Update the NetCDF time axis 2617 2541 ! prt_time_count = prt_time_count + 1 2618 ! 2542 ! 2619 2543 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_time_prt, & 2620 2544 ! (/ simulated_time /), & 2621 2545 ! start = (/ prt_time_count /), count = (/ 1 /) ) 2622 2546 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 1 ) 2623 ! 2547 ! 2624 2548 ! ! 2625 2549 ! !-- Output the real number of particles used … … 2628 2552 ! start = (/ prt_time_count /), count = (/ 1 /) ) 2629 2553 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 2 ) 2630 ! 2554 ! 2631 2555 ! ! 2632 2556 ! !-- Output all particle attributes … … 2635 2559 ! count = (/ maximum_number_of_particles /) ) 2636 2560 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 3 ) 2637 ! 2561 ! 2638 2562 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(2), particles%user, & 2639 2563 ! start = (/ 1, prt_time_count /), & 2640 2564 ! count = (/ maximum_number_of_particles /) ) 2641 2565 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 4 ) 2642 ! 2566 ! 2643 2567 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(3), particles%origin_x, & 2644 2568 ! start = (/ 1, prt_time_count /), & 2645 2569 ! count = (/ maximum_number_of_particles /) ) 2646 2570 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 5 ) 2647 ! 2571 ! 2648 2572 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(4), particles%origin_y, & 2649 2573 ! start = (/ 1, prt_time_count /), & 2650 2574 ! count = (/ maximum_number_of_particles /) ) 2651 2575 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 6 ) 2652 ! 2576 ! 2653 2577 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(5), particles%origin_z, & 2654 2578 ! start = (/ 1, prt_time_count /), & 2655 2579 ! count = (/ maximum_number_of_particles /) ) 2656 2580 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 7 ) 2657 ! 2581 ! 2658 2582 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(6), particles%radius, & 2659 2583 ! start = (/ 1, prt_time_count /), & 2660 2584 ! count = (/ maximum_number_of_particles /) ) 2661 2585 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 8 ) 2662 ! 2586 ! 2663 2587 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(7), particles%speed_x, & 2664 2588 ! start = (/ 1, prt_time_count /), & 2665 2589 ! count = (/ maximum_number_of_particles /) ) 2666 2590 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 9 ) 2667 ! 2591 ! 2668 2592 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(8), particles%speed_y, & 2669 2593 ! start = (/ 1, prt_time_count /), & 2670 2594 ! count = (/ maximum_number_of_particles /) ) 2671 2595 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 10 ) 2672 ! 2596 ! 2673 2597 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(9), particles%speed_z, & 2674 2598 ! start = (/ 1, prt_time_count /), & 2675 2599 ! count = (/ maximum_number_of_particles /) ) 2676 2600 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 11 ) 2677 ! 2601 ! 2678 2602 ! nc_stat = NF90_PUT_VAR( id_set_prt,id_var_prt(10), & 2679 2603 ! particles%weight_factor, & … … 2681 2605 ! count = (/ maximum_number_of_particles /) ) 2682 2606 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 12 ) 2683 ! 2607 ! 2684 2608 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(11), particles%x, & 2685 2609 ! start = (/ 1, prt_time_count /), & 2686 2610 ! count = (/ maximum_number_of_particles /) ) 2687 2611 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 13 ) 2688 ! 2612 ! 2689 2613 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(12), particles%y, & 2690 2614 ! start = (/ 1, prt_time_count /), & 2691 2615 ! count = (/ maximum_number_of_particles /) ) 2692 2616 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 14 ) 2693 ! 2617 ! 2694 2618 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(13), particles%z, & 2695 2619 ! start = (/ 1, prt_time_count /), & 2696 2620 ! count = (/ maximum_number_of_particles /) ) 2697 2621 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 15 ) 2698 ! 2622 ! 2699 2623 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(14), particles%class, & 2700 2624 ! start = (/ 1, prt_time_count /), & 2701 2625 ! count = (/ maximum_number_of_particles /) ) 2702 2626 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 16 ) 2703 ! 2627 ! 2704 2628 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(15), particles%group, & 2705 2629 ! start = (/ 1, prt_time_count /), & 2706 2630 ! count = (/ maximum_number_of_particles /) ) 2707 2631 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 17 ) 2708 ! 2632 ! 2709 2633 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(16), & 2710 2634 ! particles%id2, & … … 2712 2636 ! count = (/ maximum_number_of_particles /) ) 2713 2637 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 18 ) 2714 ! 2638 ! 2715 2639 ! nc_stat = NF90_PUT_VAR( id_set_prt, id_var_prt(17), particles%id1, & 2716 2640 ! start = (/ 1, prt_time_count /), & 2717 2641 ! count = (/ maximum_number_of_particles /) ) 2718 2642 ! CALL netcdf_handle_error( 'lpm_data_output_particles', 19 ) 2719 ! 2643 ! 2720 2644 #endif 2721 2645 … … 2723 2647 2724 2648 END SUBROUTINE lpm_data_output_particles 2725 2726 !------------------------------------------------------------------------------ !2649 2650 !--------------------------------------------------------------------------------------------------! 2727 2651 ! Description: 2728 2652 ! ------------ 2729 2653 !> This routine calculates and provide particle timeseries output. 2730 !------------------------------------------------------------------------------ !2654 !--------------------------------------------------------------------------------------------------! 2731 2655 SUBROUTINE lpm_data_output_ptseries 2732 2656 2733 2657 INTEGER(iwp) :: i !< 2734 2658 INTEGER(iwp) :: inum !< … … 2752 2676 ! 2753 2677 !-- Update the particle time series time axis 2754 nc_stat = NF90_PUT_VAR( id_set_pts, id_var_time_pts, & 2755 (/ time_since_reference_point /), & 2678 nc_stat = NF90_PUT_VAR( id_set_pts, id_var_time_pts, (/ time_since_reference_point /), & 2756 2679 start = (/ dopts_time_count /), count = (/ 1 /) ) 2757 2680 CALL netcdf_handle_error( 'data_output_ptseries', 391 ) … … 2760 2683 ENDIF 2761 2684 2762 ALLOCATE( pts_value(0:number_of_particle_groups,dopts_num), &2685 ALLOCATE( pts_value(0:number_of_particle_groups,dopts_num), & 2763 2686 pts_value_l(0:number_of_particle_groups,dopts_num) ) 2764 2687 … … 2767 2690 2768 2691 ! 2769 !-- Calculate or collect the particle time series quantities for all particles 2770 !-- and seperately foreach particle group (if there is more than one group)2692 !-- Calculate or collect the particle time series quantities for all particles and seperately for 2693 !-- each particle group (if there is more than one group) 2771 2694 DO i = nxl, nxr 2772 2695 DO j = nys, nyn … … 2779 2702 IF ( particles(n)%particle_mask ) THEN ! Restrict analysis to active particles 2780 2703 2781 pts_value_l(0,1) = pts_value_l(0,1) + 1.0_wp ! total # of particles2782 pts_value_l(0,2) = pts_value_l(0,2) + &2783 ( particles(n)%x - particles(n)%origin_x ) ! mean x2784 pts_value_l(0,3) = pts_value_l(0,3) + &2785 ( particles(n)%y - particles(n)%origin_y ) ! mean y2786 pts_value_l(0,4) = pts_value_l(0,4) + &2787 ( particles(n)%z - particles(n)%origin_z ) ! mean z2788 pts_value_l(0,5) = pts_value_l(0,5) + particles(n)%z ! mean z (absolute)2789 pts_value_l(0,6) = pts_value_l(0,6) + particles(n)%speed_x ! mean u2790 pts_value_l(0,7) = pts_value_l(0,7) + particles(n)%speed_y ! mean v2791 pts_value_l(0,8) = pts_value_l(0,8) + particles(n)%speed_z ! mean w2792 pts_value_l(0,9) = pts_value_l(0,9) + particles(n)%rvar1 ! mean sgsu2793 pts_value_l(0,10) = pts_value_l(0,10) + particles(n)%rvar2 ! mean sgsv2794 pts_value_l(0,11) = pts_value_l(0,11) + particles(n)%rvar3 ! mean sgsw2704 pts_value_l(0,1) = pts_value_l(0,1) + 1.0_wp ! total # of particles 2705 pts_value_l(0,2) = pts_value_l(0,2) + & 2706 ( particles(n)%x - particles(n)%origin_x ) ! mean x 2707 pts_value_l(0,3) = pts_value_l(0,3) + & 2708 ( particles(n)%y - particles(n)%origin_y ) ! mean y 2709 pts_value_l(0,4) = pts_value_l(0,4) + & 2710 ( particles(n)%z - particles(n)%origin_z ) ! mean z 2711 pts_value_l(0,5) = pts_value_l(0,5) + particles(n)%z ! mean z (absolute) 2712 pts_value_l(0,6) = pts_value_l(0,6) + particles(n)%speed_x ! mean u 2713 pts_value_l(0,7) = pts_value_l(0,7) + particles(n)%speed_y ! mean v 2714 pts_value_l(0,8) = pts_value_l(0,8) + particles(n)%speed_z ! mean w 2715 pts_value_l(0,9) = pts_value_l(0,9) + particles(n)%rvar1 ! mean sgsu 2716 pts_value_l(0,10) = pts_value_l(0,10) + particles(n)%rvar2 ! mean sgsv 2717 pts_value_l(0,11) = pts_value_l(0,11) + particles(n)%rvar3 ! mean sgsw 2795 2718 IF ( particles(n)%speed_z > 0.0_wp ) THEN 2796 pts_value_l(0,12) = pts_value_l(0,12) + 1.0_wp ! # of upward moving prts 2797 pts_value_l(0,13) = pts_value_l(0,13) + & 2798 particles(n)%speed_z ! mean w upw. 2719 pts_value_l(0,12) = pts_value_l(0,12) + 1.0_wp ! # of upward moving prts 2720 pts_value_l(0,13) = pts_value_l(0,13) + particles(n)%speed_z ! mean w upw. 2799 2721 ELSE 2800 pts_value_l(0,14) = pts_value_l(0,14) + & 2801 particles(n)%speed_z ! mean w down 2722 pts_value_l(0,14) = pts_value_l(0,14) + particles(n)%speed_z ! mean w down 2802 2723 ENDIF 2803 pts_value_l(0,15) = pts_value_l(0,15) + particles(n)%radius ! mean rad2724 pts_value_l(0,15) = pts_value_l(0,15) + particles(n)%radius ! mean rad 2804 2725 pts_value_l(0,16) = MIN( pts_value_l(0,16), particles(n)%radius ) ! minrad 2805 2726 pts_value_l(0,17) = MAX( pts_value_l(0,17), particles(n)%radius ) ! maxrad … … 2812 2733 2813 2734 pts_value_l(jg,1) = pts_value_l(jg,1) + 1.0_wp 2814 pts_value_l(jg,2) = pts_value_l(jg,2) + &2815 ( particles(n)%x- particles(n)%origin_x )2816 pts_value_l(jg,3) = pts_value_l(jg,3) + &2817 ( particles(n)%y- particles(n)%origin_y )2818 pts_value_l(jg,4) = pts_value_l(jg,4) + &2819 ( particles(n)%z- particles(n)%origin_z )2735 pts_value_l(jg,2) = pts_value_l(jg,2) + & 2736 ( particles(n)%x - particles(n)%origin_x ) 2737 pts_value_l(jg,3) = pts_value_l(jg,3) + & 2738 ( particles(n)%y - particles(n)%origin_y ) 2739 pts_value_l(jg,4) = pts_value_l(jg,4) + & 2740 ( particles(n)%z - particles(n)%origin_z ) 2820 2741 pts_value_l(jg,5) = pts_value_l(jg,5) + particles(n)%z 2821 2742 pts_value_l(jg,6) = pts_value_l(jg,6) + particles(n)%speed_x … … 2853 2774 2854 2775 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2855 CALL MPI_ALLREDUCE( pts_value_l(0,1), pts_value(0,1), 15*inum, MPI_REAL, & 2856 MPI_SUM, comm2d, ierr ) 2776 CALL MPI_ALLREDUCE( pts_value_l(0,1), pts_value(0,1), 15*inum, MPI_REAL, MPI_SUM, comm2d, ierr ) 2857 2777 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2858 CALL MPI_ALLREDUCE( pts_value_l(0,16), pts_value(0,16), inum, MPI_REAL, & 2859 MPI_MIN, comm2d, ierr ) 2778 CALL MPI_ALLREDUCE( pts_value_l(0,16), pts_value(0,16), inum, MPI_REAL, MPI_MIN, comm2d, ierr ) 2860 2779 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2861 CALL MPI_ALLREDUCE( pts_value_l(0,17), pts_value(0,17), inum, MPI_REAL, & 2862 MPI_MAX, comm2d, ierr ) 2780 CALL MPI_ALLREDUCE( pts_value_l(0,17), pts_value(0,17), inum, MPI_REAL, MPI_MAX, comm2d, ierr ) 2863 2781 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2864 CALL MPI_ALLREDUCE( pts_value_l(0,18), pts_value(0,18), inum, MPI_REAL, & 2865 MPI_MAX, comm2d, ierr ) 2782 CALL MPI_ALLREDUCE( pts_value_l(0,18), pts_value(0,18), inum, MPI_REAL, MPI_MAX, comm2d, ierr ) 2866 2783 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2867 CALL MPI_ALLREDUCE( pts_value_l(0,19), pts_value(0,19), inum, MPI_REAL, & 2868 MPI_MIN, comm2d, ierr ) 2784 CALL MPI_ALLREDUCE( pts_value_l(0,19), pts_value(0,19), inum, MPI_REAL, MPI_MIN, comm2d, ierr ) 2869 2785 #else 2870 2786 pts_value(:,1:19) = pts_value_l(:,1:19) … … 2872 2788 2873 2789 ! 2874 !-- Normalize the above calculated quantities (except min/max values) with the 2875 !-- total number ofparticles2790 !-- Normalize the above calculated quantities (except min/max values) with the total number of 2791 !-- particles 2876 2792 IF ( number_of_particle_groups > 1 ) THEN 2877 2793 inum = number_of_particle_groups … … 2899 2815 2900 2816 ! 2901 !-- Calculate higher order moments of particle time series quantities, 2902 !-- seperately for each particlegroup (if there is more than one group)2817 !-- Calculate higher order moments of particle time series quantities, seperately for each particle 2818 !-- group (if there is more than one group) 2903 2819 DO i = nxl, nxr 2904 2820 DO j = nys, nyn … … 2909 2825 DO n = 1, number_of_particles 2910 2826 2911 pts_value_l(0,20) = pts_value_l(0,20) + ( particles(n)%x - &2912 particles(n)%origin_x - pts_value(0,2) )**2 ! x*22913 pts_value_l(0,21) = pts_value_l(0,21) + ( particles(n)%y - &2914 particles(n)%origin_y - pts_value(0,3) )**2 ! y*22915 pts_value_l(0,22) = pts_value_l(0,22) + ( particles(n)%z - &2916 particles(n)%origin_z - pts_value(0,4) )**2 ! z*22917 pts_value_l(0,23) = pts_value_l(0,23) + ( particles(n)%speed_x - &2918 pts_value(0,6) )**2! u*22919 pts_value_l(0,24) = pts_value_l(0,24) + ( particles(n)%speed_y - &2920 pts_value(0,7) )**2 ! v*22921 pts_value_l(0,25) = pts_value_l(0,25) + ( particles(n)%speed_z - &2922 pts_value(0,8) )**2 ! w*22923 pts_value_l(0,26) = pts_value_l(0,26) + ( particles(n)%rvar1 - &2924 pts_value(0,9) )**2 ! u"22925 pts_value_l(0,27) = pts_value_l(0,27) + ( particles(n)%rvar2 - &2926 pts_value(0,10) )**2 ! v"22927 pts_value_l(0,28) = pts_value_l(0,28) + ( particles(n)%rvar3 - &2827 pts_value_l(0,20) = pts_value_l(0,20) + ( particles(n)%x - & 2828 particles(n)%origin_x - pts_value(0,2) )**2 ! x*2 2829 pts_value_l(0,21) = pts_value_l(0,21) + ( particles(n)%y - & 2830 particles(n)%origin_y - pts_value(0,3) )**2 ! y*2 2831 pts_value_l(0,22) = pts_value_l(0,22) + ( particles(n)%z - & 2832 particles(n)%origin_z - pts_value(0,4) )**2 ! z*2 2833 pts_value_l(0,23) = pts_value_l(0,23) + ( particles(n)%speed_x - & 2834 pts_value(0,6) )**2 ! u*2 2835 pts_value_l(0,24) = pts_value_l(0,24) + ( particles(n)%speed_y - & 2836 pts_value(0,7) )**2 ! v*2 2837 pts_value_l(0,25) = pts_value_l(0,25) + ( particles(n)%speed_z - & 2838 pts_value(0,8) )**2 ! w*2 2839 pts_value_l(0,26) = pts_value_l(0,26) + ( particles(n)%rvar1 - & 2840 pts_value(0,9) )**2 ! u"2 2841 pts_value_l(0,27) = pts_value_l(0,27) + ( particles(n)%rvar2 - & 2842 pts_value(0,10) )**2 ! v"2 2843 pts_value_l(0,28) = pts_value_l(0,28) + ( particles(n)%rvar3 - & 2928 2844 pts_value(0,11) )**2 ! w"2 2929 2845 ! … … 2932 2848 jg = particles(n)%group 2933 2849 2934 pts_value_l(jg,20) = pts_value_l(jg,20) + ( particles(n)%x - &2935 particles(n)%origin_x - pts_value(jg,2) )**22936 pts_value_l(jg,21) = pts_value_l(jg,21) + ( particles(n)%y - &2937 particles(n)%origin_y - pts_value(jg,3) )**22938 pts_value_l(jg,22) = pts_value_l(jg,22) + ( particles(n)%z - &2939 particles(n)%origin_z - pts_value(jg,4) )**22940 pts_value_l(jg,23) = pts_value_l(jg,23) + ( particles(n)%speed_x - &2941 pts_value(jg,6) )**22942 pts_value_l(jg,24) = pts_value_l(jg,24) + ( particles(n)%speed_y - &2943 pts_value(jg,7) )**22944 pts_value_l(jg,25) = pts_value_l(jg,25) + ( particles(n)%speed_z - &2945 pts_value(jg,8) )**22946 pts_value_l(jg,26) = pts_value_l(jg,26) + ( particles(n)%rvar1 - &2947 pts_value(jg,9) )**22948 pts_value_l(jg,27) = pts_value_l(jg,27) + ( particles(n)%rvar2 - &2949 pts_value(jg,10) )**22950 pts_value_l(jg,28) = pts_value_l(jg,28) + ( particles(n)%rvar3 - &2951 pts_value(jg,11) )**22850 pts_value_l(jg,20) = pts_value_l(jg,20) + ( particles(n)%x - & 2851 particles(n)%origin_x - pts_value(jg,2) )**2 2852 pts_value_l(jg,21) = pts_value_l(jg,21) + ( particles(n)%y - & 2853 particles(n)%origin_y - pts_value(jg,3) )**2 2854 pts_value_l(jg,22) = pts_value_l(jg,22) + ( particles(n)%z - & 2855 particles(n)%origin_z - pts_value(jg,4) )**2 2856 pts_value_l(jg,23) = pts_value_l(jg,23) + ( particles(n)%speed_x - & 2857 pts_value(jg,6) )**2 2858 pts_value_l(jg,24) = pts_value_l(jg,24) + ( particles(n)%speed_y - & 2859 pts_value(jg,7) )**2 2860 pts_value_l(jg,25) = pts_value_l(jg,25) + ( particles(n)%speed_z - & 2861 pts_value(jg,8) )**2 2862 pts_value_l(jg,26) = pts_value_l(jg,26) + ( particles(n)%rvar1 - & 2863 pts_value(jg,9) )**2 2864 pts_value_l(jg,27) = pts_value_l(jg,27) + ( particles(n)%rvar2 - & 2865 pts_value(jg,10) )**2 2866 pts_value_l(jg,28) = pts_value_l(jg,28) + ( particles(n)%rvar3 - & 2867 pts_value(jg,11) )**2 2952 2868 ENDIF 2953 2869 … … 2961 2877 IF ( number_of_particle_groups > 1 ) THEN 2962 2878 DO j = 1, number_of_particle_groups 2963 pts_value_l(j,29) = ( pts_value_l(j,1) - & 2964 pts_value(j,1) / numprocs )**2 2879 pts_value_l(j,29) = ( pts_value_l(j,1) - pts_value(j,1) / numprocs )**2 2965 2880 ENDDO 2966 2881 ENDIF … … 2972 2887 2973 2888 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 2974 CALL MPI_ALLREDUCE( pts_value_l(0,20), pts_value(0,20), inum*10, MPI_REAL, &2975 MPI_SUM, comm2d,ierr )2889 CALL MPI_ALLREDUCE( pts_value_l(0,20), pts_value(0,20), inum*10, MPI_REAL, MPI_SUM, comm2d, & 2890 ierr ) 2976 2891 #else 2977 2892 pts_value(:,20:29) = pts_value_l(:,20:29) … … 2979 2894 2980 2895 ! 2981 !-- Normalize the above calculated quantities with the total number of 2982 !-- particles 2896 !-- Normalize the above calculated quantities with the total number of particles 2983 2897 IF ( number_of_particle_groups > 1 ) THEN 2984 2898 inum = number_of_particle_groups … … 3002 2916 DO j = 0, inum 3003 2917 DO i = 1, dopts_num 3004 nc_stat = NF90_PUT_VAR( id_set_pts, id_var_dopts(i,j), &3005 (/ pts_value(j,i) /), &3006 start = (/ dopts_time_count /), &2918 nc_stat = NF90_PUT_VAR( id_set_pts, id_var_dopts(i,j), & 2919 (/ pts_value(j,i) /), & 2920 start = (/ dopts_time_count /), & 3007 2921 count = (/ 1 /) ) 3008 2922 CALL netcdf_handle_error( 'data_output_ptseries', 392 ) … … 3018 2932 END SUBROUTINE lpm_data_output_ptseries 3019 2933 3020 3021 !------------------------------------------------------------------------------ !2934 2935 !--------------------------------------------------------------------------------------------------! 3022 2936 ! Description: 3023 2937 ! ------------ 3024 2938 !> This routine reads the respective restart data for the lpm. 3025 !------------------------------------------------------------------------------ !2939 !--------------------------------------------------------------------------------------------------! 3026 2940 SUBROUTINE lpm_rrd_local_particles 3027 2941 … … 3048 2962 !-- First open the input unit. 3049 2963 IF ( myid_char == '' ) THEN 3050 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_IN'//myid_char, & 3051 FORM='UNFORMATTED' ) 2964 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_IN'//myid_char, FORM='UNFORMATTED' ) 3052 2965 ELSE 3053 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_IN/'//myid_char, & 3054 FORM='UNFORMATTED' ) 2966 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_IN/'//myid_char, FORM='UNFORMATTED' ) 3055 2967 ENDIF 3056 2968 … … 3060 2972 particle_binary_version = '4.0' 3061 2973 IF ( TRIM( version_on_file ) /= TRIM( particle_binary_version ) ) THEN 3062 message_string = 'version mismatch concerning data from prior ' // &3063 'run &version on file = "' // &3064 TRIM( version_on_file ) // &3065 '&version in program = "' // &2974 message_string = 'version mismatch concerning data from prior ' // & 2975 'run &version on file = "' // & 2976 TRIM( version_on_file ) // & 2977 '&version in program = "' // & 3066 2978 TRIM( particle_binary_version ) // '"' 3067 2979 CALL message( 'lpm_read_restart_file', 'PA0214', 1, 2, 0, 6, 0 ) … … 3069 2981 3070 2982 ! 3071 !-- If less particles are stored on the restart file than prescribed by 3072 !-- 1, the remainder is initialized by zero_particle to avoid 3073 !-- errors. 3074 zero_particle = particle_type( 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 3075 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 3076 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 3077 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 2983 !-- If less particles are stored on the restart file than prescribed by 1, the remainder is 2984 !-- initialized by zero_particle to avoid errors. 2985 zero_particle = particle_type( 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 2986 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 2987 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 2988 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, 0.0_wp, & 3078 2989 0, 0, 0_idp, .FALSE., -1, -1 ) 3079 2990 ! 3080 !-- Read some particle parameters and the size of the particle arrays, 3081 !-- allocate them and read their contents. 3082 READ ( 90 ) bc_par_b, bc_par_lr, bc_par_ns, bc_par_t, & 3083 last_particle_release_time, number_of_particle_groups, & 3084 particle_groups, time_write_particle_data 3085 3086 ALLOCATE( prt_count(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 2991 !-- Read some particle parameters and the size of the particle arrays, allocate them and read 2992 !-- their contents. 2993 READ ( 90 ) bc_par_b, bc_par_lr, bc_par_ns, bc_par_t, last_particle_release_time, & 2994 number_of_particle_groups, particle_groups, time_write_particle_data 2995 2996 ALLOCATE( prt_count(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 3087 2997 grid_particles(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 3088 2998 … … 3095 3005 number_of_particles = prt_count(kp,jp,ip) 3096 3006 IF ( number_of_particles > 0 ) THEN 3097 alloc_size = MAX( INT( number_of_particles * &3098 ( 1.0_wp + alloc_factor / 100.0_wp ) ),&3099 1 )3007 alloc_size = MAX( INT( number_of_particles * & 3008 ( 1.0_wp + alloc_factor / 100.0_wp ) ), & 3009 1 ) 3100 3010 ELSE 3101 3011 alloc_size = 1 … … 3110 3020 DEALLOCATE( tmp_particles ) 3111 3021 IF ( number_of_particles < alloc_size ) THEN 3112 grid_particles(kp,jp,ip)%particles(number_of_particles+1:alloc_size) &3022 grid_particles(kp,jp,ip)%particles(number_of_particles+1:alloc_size) & 3113 3023 = zero_particle 3114 3024 ENDIF … … 3128 3038 FLUSH(9) 3129 3039 3130 ALLOCATE( prt_count(nzb:nzt+1,nysg:nyng,nxlg:nxrg), &3040 ALLOCATE( prt_count(nzb:nzt+1,nysg:nyng,nxlg:nxrg), & 3131 3041 grid_particles(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 3132 3042 3133 3043 ALLOCATE( prt_global_index(nzb:nzt+1,nysg:nyng,nxlg:nxrg) ) 3134 3044 ! 3135 !-- Open restart file for read, if not already open, and do not allow usage of 3136 !-- shared-memory I/O 3045 !-- Open restart file for read, if not already open, and do not allow usage of shared-memory I/O 3137 3046 IF ( .NOT. rd_mpi_io_check_open() ) THEN 3138 3047 save_restart_data_format_input = restart_data_format_input … … 3156 3065 number_of_particles = prt_count(kp,jp,ip) 3157 3066 IF ( number_of_particles > 0 ) THEN 3158 alloc_size = MAX( INT( number_of_particles * &3159 ( 1.0_wp + alloc_factor / 100.0_wp ) ),&3160 1 )3067 alloc_size = MAX( INT( number_of_particles * & 3068 ( 1.0_wp + alloc_factor / 100.0_wp ) ), & 3069 1 ) 3161 3070 ELSE 3162 3071 alloc_size = 1 … … 3186 3095 ENDIF 3187 3096 ! 3188 !-- Must be called to sort particles into blocks, which is needed for a fast 3189 !-- interpolation of theLES fields on the particle position.3097 !-- Must be called to sort particles into blocks, which is needed for a fast interpolation of the 3098 !-- LES fields on the particle position. 3190 3099 CALL lpm_sort_and_delete 3191 3100 3192 3101 END SUBROUTINE lpm_rrd_local_particles 3193 3194 3195 !------------------------------------------------------------------------------ !3102 3103 3104 !--------------------------------------------------------------------------------------------------! 3196 3105 ! Description: 3197 3106 ! ------------ 3198 3107 !> Read module-specific local restart data arrays (Fortran binary format). 3199 !------------------------------------------------------------------------------! 3200 SUBROUTINE lpm_rrd_local_ftn( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc, & 3201 nxr_on_file, nynf, nync, nyn_on_file, nysf, & 3202 nysc, nys_on_file, tmp_3d, found ) 3203 3204 3205 USE control_parameters, & 3108 !--------------------------------------------------------------------------------------------------! 3109 SUBROUTINE lpm_rrd_local_ftn( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc, nxr_on_file, nynf, nync, & 3110 nyn_on_file, nysf, nysc, nys_on_file, tmp_3d, found ) 3111 3112 3113 USE control_parameters, & 3206 3114 ONLY: length, restart_string 3207 3115 … … 3220 3128 INTEGER(iwp) :: nys_on_file !< 3221 3129 3130 INTEGER(isp), DIMENSION(:,:,:), ALLOCATABLE :: tmp_2d_seq_random_particles !< temporary array for storing random generator 3131 !< data for the lpm 3132 3222 3133 LOGICAL, INTENT(OUT) :: found 3223 3224 INTEGER(isp), DIMENSION(:,:,:), ALLOCATABLE :: tmp_2d_seq_random_particles !< temporary array for storing random generator data for the lpm3225 3134 3226 3135 REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d !< … … 3236 3145 ENDIF 3237 3146 IF ( k == 1 ) READ ( 13 ) tmp_3d 3238 pc_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &3147 pc_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = & 3239 3148 tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp) 3240 3149 … … 3244 3153 ENDIF 3245 3154 IF ( k == 1 ) READ ( 13 ) tmp_3d 3246 pr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &3155 pr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = & 3247 3156 tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp) 3248 3157 3249 3158 CASE ( 'ql_c_av' ) 3250 3159 IF ( .NOT. ALLOCATED( ql_c_av ) ) THEN … … 3252 3161 ENDIF 3253 3162 IF ( k == 1 ) READ ( 13 ) tmp_3d 3254 ql_c_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &3163 ql_c_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = & 3255 3164 tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp) 3256 3165 … … 3260 3169 ENDIF 3261 3170 IF ( k == 1 ) READ ( 13 ) tmp_3d 3262 ql_v_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &3171 ql_v_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = & 3263 3172 tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp) 3264 3173 … … 3268 3177 ENDIF 3269 3178 IF ( k == 1 ) READ ( 13 ) tmp_3d 3270 ql_vp_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &3179 ql_vp_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = & 3271 3180 tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp) 3272 3181 3273 3182 CASE ( 'seq_random_array_particles' ) 3274 3275 3276 3277 3278 3279 seq_random_array_particles(:,nysc:nync,nxlc:nxrc) =&3280 3281 3183 ALLOCATE( tmp_2d_seq_random_particles(5,nys_on_file:nyn_on_file,nxl_on_file:nxr_on_file) ) 3184 IF ( .NOT. ALLOCATED( seq_random_array_particles ) ) THEN 3185 ALLOCATE( seq_random_array_particles(5,nys:nyn,nxl:nxr) ) 3186 ENDIF 3187 IF ( k == 1 ) READ ( 13 ) tmp_2d_seq_random_particles 3188 seq_random_array_particles(:,nysc:nync,nxlc:nxrc) = & 3189 tmp_2d_seq_random_particles(:,nysf:nynf,nxlf:nxrf) 3190 DEALLOCATE( tmp_2d_seq_random_particles ) 3282 3191 3283 3192 CASE DEFAULT … … 3289 3198 END SUBROUTINE lpm_rrd_local_ftn 3290 3199 3291 3292 !------------------------------------------------------------------------------ !3200 3201 !--------------------------------------------------------------------------------------------------! 3293 3202 ! Description: 3294 3203 ! ------------ 3295 3204 !> Read module-specific local restart data arrays (MPI-IO). 3296 !------------------------------------------------------------------------------ !3205 !--------------------------------------------------------------------------------------------------! 3297 3206 SUBROUTINE lpm_rrd_local_mpi 3298 3207 … … 3349 3258 3350 3259 3351 !------------------------------------------------------------------------------ !3260 !--------------------------------------------------------------------------------------------------! 3352 3261 ! Description: 3353 3262 ! ------------ 3354 3263 !> This routine writes the respective restart data for the lpm. 3355 !------------------------------------------------------------------------------ !3264 !--------------------------------------------------------------------------------------------------! 3356 3265 SUBROUTINE lpm_wrd_local 3357 3266 3358 3267 CHARACTER (LEN=10) :: particle_binary_version !< 3359 3268 CHARACTER (LEN=32) :: tmp_name !< temporary variable … … 3364 3273 INTEGER(iwp) :: jp !< 3365 3274 INTEGER(iwp) :: k !< loop index 3366 INTEGER(iwp) :: kp !< 3275 INTEGER(iwp) :: kp !< 3367 3276 3368 3277 #if defined( __parallel ) … … 3382 3291 !-- First open the output unit. 3383 3292 IF ( myid_char == '' ) THEN 3384 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_OUT'//myid_char, & 3385 FORM='UNFORMATTED') 3293 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_OUT'//myid_char, FORM='UNFORMATTED') 3386 3294 ELSE 3387 3295 IF ( myid == 0 ) CALL local_system( 'mkdir PARTICLE_RESTART_DATA_OUT' ) 3388 3296 #if defined( __parallel ) 3389 3297 ! 3390 !-- Set a barrier in order to allow that thereafter all other processors 3391 !-- in the directorycreated by PE0 can open their file3298 !-- Set a barrier in order to allow that thereafter all other processors in the directory 3299 !-- created by PE0 can open their file 3392 3300 CALL MPI_BARRIER( comm2d, ierr ) 3393 3301 #endif 3394 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_OUT/'//myid_char, & 3395 FORM='UNFORMATTED' ) 3302 OPEN ( 90, FILE='PARTICLE_RESTART_DATA_OUT/'//myid_char, FORM='UNFORMATTED' ) 3396 3303 ENDIF 3397 3304 3398 3305 ! 3399 3306 !-- Write the version number of the binary format. 3400 !-- Attention: After changes to the following output commands the version 3401 !-- --------- number of the variable particle_binary_version must be 3402 !-- changed! Also, the version number and the list of arrays 3403 !-- to be read in lpm_read_restart_file must be adjusted 3404 !-- accordingly. 3307 !-- Attention: After changes to the following output commands the version number of the variable 3308 !-- --------- particle_binary_version must be changed! Also, the version number and the list of 3309 !-- arrays to be read in lpm_read_restart_file must be adjusted accordingly. 3405 3310 particle_binary_version = '4.0' 3406 3311 WRITE ( 90 ) particle_binary_version … … 3408 3313 ! 3409 3314 !-- Write some particle parameters, the size of the particle arrays 3410 WRITE ( 90 ) bc_par_b, bc_par_lr, bc_par_ns, bc_par_t, & 3411 last_particle_release_time, number_of_particle_groups, & 3412 particle_groups, time_write_particle_data 3315 WRITE ( 90 ) bc_par_b, bc_par_lr, bc_par_ns, bc_par_t, last_particle_release_time, & 3316 number_of_particle_groups, particle_groups, time_write_particle_data 3413 3317 3414 3318 WRITE ( 90 ) prt_count 3415 3319 3416 3320 DO ip = nxl, nxr 3417 3321 DO jp = nys, nyn … … 3465 3369 3466 3370 #if defined( __parallel ) 3467 CALL MPI_ALLREDUCE( nr_particles_local, nr_particles_global, numprocs, MPI_INTEGER, 3468 MPI_SUM,comm2d, ierr )3371 CALL MPI_ALLREDUCE( nr_particles_local, nr_particles_global, numprocs, MPI_INTEGER, MPI_SUM,& 3372 comm2d, ierr ) 3469 3373 #else 3470 3374 nr_particles_global = nr_particles_local … … 3500 3404 3501 3405 3502 !------------------------------------------------------------------------------ !3406 !--------------------------------------------------------------------------------------------------! 3503 3407 ! Description: 3504 3408 ! ------------ 3505 3409 !> This routine writes the respective restart data for the lpm. 3506 !------------------------------------------------------------------------------ !3410 !--------------------------------------------------------------------------------------------------! 3507 3411 SUBROUTINE lpm_wrd_global 3508 3412 … … 3513 3417 REAL(wp), DIMENSION(4,max_number_of_particle_groups) :: particle_groups_array !< 3514 3418 3515 3419 3516 3420 IF ( TRIM( restart_data_format_output ) == 'fortran_binary' ) THEN 3517 3421 … … 3569 3473 3570 3474 END SUBROUTINE lpm_wrd_global 3571 3572 3573 !------------------------------------------------------------------------------ !3475 3476 3477 !--------------------------------------------------------------------------------------------------! 3574 3478 ! Description: 3575 3479 ! ------------ 3576 3480 !> Read module-specific global restart data (Fortran binary format). 3577 !------------------------------------------------------------------------------ !3481 !--------------------------------------------------------------------------------------------------! 3578 3482 SUBROUTINE lpm_rrd_global_ftn( found ) 3579 3580 USE control_parameters, &3483 3484 USE control_parameters, & 3581 3485 ONLY: length, restart_string 3582 3486 … … 3603 3507 found = .FALSE. 3604 3508 3605 END SELECT 3606 3509 END SELECT 3510 3607 3511 END SUBROUTINE lpm_rrd_global_ftn 3608 3512 3609 3513 3610 !------------------------------------------------------------------------------ !3514 !--------------------------------------------------------------------------------------------------! 3611 3515 ! Description: 3612 3516 ! ------------ 3613 3517 !> Read module-specific global restart data (MPI-IO). 3614 !------------------------------------------------------------------------------ !3518 !--------------------------------------------------------------------------------------------------! 3615 3519 SUBROUTINE lpm_rrd_global_mpi 3616 3520 … … 3661 3565 3662 3566 3663 !------------------------------------------------------------------------------ !3567 !--------------------------------------------------------------------------------------------------! 3664 3568 ! Description: 3665 3569 ! ------------ 3666 !> This is a submodule of the lagrangian particle model. It contains all 3667 !> dynamic processes of the lpm. This includes the advection (resolved and sub- 3668 !> grid scale) as well as the boundary conditions of particles. As a next step 3669 !> this submodule should be excluded as an own file. 3670 !------------------------------------------------------------------------------! 3570 !> This is a submodule of the lagrangian particle model. It contains all dynamic processes of the 3571 !> lpm. This includes the advection (resolved and sub-grid scale) as well as the boundary conditions 3572 !> of particles. As a next step this submodule should be excluded as an own file. 3573 !--------------------------------------------------------------------------------------------------! 3671 3574 SUBROUTINE lpm_advec (ip,jp,kp) 3672 3575 3673 LOGICAL :: subbox_at_wall !< flag to see if the current subgridbox is adjacent to a wall 3576 REAL(wp), PARAMETER :: a_rog = 9.65_wp !< parameter for fall velocity 3577 REAL(wp), PARAMETER :: b_rog = 10.43_wp !< parameter for fall velocity 3578 REAL(wp), PARAMETER :: c_rog = 0.6_wp !< parameter for fall velocity 3579 REAL(wp), PARAMETER :: k_cap_rog = 4.0_wp !< parameter for fall velocity 3580 REAL(wp), PARAMETER :: k_low_rog = 12.0_wp !< parameter for fall velocity 3581 REAL(wp), PARAMETER :: d0_rog = 0.745_wp !< separation diameter 3674 3582 3675 3583 INTEGER(iwp) :: i !< index variable along x … … 3681 3589 INTEGER(iwp) :: jp !< index variable along y 3682 3590 INTEGER(iwp) :: k !< index variable along z 3683 INTEGER(iwp) :: k_wall !< vertical index of topography top 3591 INTEGER(iwp) :: k_wall !< vertical index of topography top 3684 3592 INTEGER(iwp) :: kp !< index variable along z 3685 3593 INTEGER(iwp) :: k_next !< index variable along z … … 3687 3595 INTEGER(iwp) :: kkw !< index variable along z 3688 3596 INTEGER(iwp) :: n !< loop variable over all particles in a grid box 3597 INTEGER(iwp) :: nn !< loop variable over iterations steps 3689 3598 INTEGER(iwp) :: nb !< block number particles are sorted in 3690 3599 INTEGER(iwp) :: particle_end !< end index for partilce loop … … 3692 3601 INTEGER(iwp) :: subbox_end !< end index for loop over subboxes in particle advection 3693 3602 INTEGER(iwp) :: subbox_start !< start index for loop over subboxes in particle advection 3694 INTEGER(iwp) :: nn !< loop variable over iterations steps 3695 3603 3604 INTEGER(iwp), DIMENSION(0:7) :: end_index !< start particle index for current block 3696 3605 INTEGER(iwp), DIMENSION(0:7) :: start_index !< start particle index for current block 3697 INTEGER(iwp), DIMENSION(0:7) :: end_index !< start particle index for current block 3606 3607 LOGICAL :: subbox_at_wall !< flag to see if the current subgridbox is adjacent to a wall 3698 3608 3699 3609 REAL(wp) :: aa !< dummy argument for horizontal particle interpolation 3700 3610 REAL(wp) :: alpha !< interpolation facor for x-direction 3701 3702 3611 REAL(wp) :: bb !< dummy argument for horizontal particle interpolation 3703 3612 REAL(wp) :: beta !< interpolation facor for y-direction 3704 3613 REAL(wp) :: cc !< dummy argument for horizontal particle interpolation 3705 REAL(wp) :: d_z_p_z0 !< inverse of interpolation length for logarithmic interpolation 3706 REAL(wp) :: dd !< dummy argument for horizontal particle interpolation 3614 REAL(wp) :: d_z_p_z0 !< inverse of interpolation length for logarithmic interpolation 3615 REAL(wp) :: dd !< dummy argument for horizontal particle interpolation 3707 3616 REAL(wp) :: de_dx_int_l !< x/y-interpolated TKE gradient (x) at particle position at lower vertical level 3708 3617 REAL(wp) :: de_dx_int_u !< x/y-interpolated TKE gradient (x) at particle position at upper vertical level … … 3724 3633 REAL(wp) :: exp_term !< exponent term 3725 3634 REAL(wp) :: gamma !< interpolation facor for z-direction 3726 REAL(wp) :: gg !< dummy argument for horizontal particle interpolation 3635 REAL(wp) :: gg !< dummy argument for horizontal particle interpolation 3727 3636 REAL(wp) :: height_p !< dummy argument for logarithmic interpolation 3728 3637 REAL(wp) :: log_z_z0_int !< logarithmus used for surface_layer interpolation 3729 REAL(wp) :: RL!< Lagrangian autocorrelation coefficient3638 REAL(wp) :: rl !< Lagrangian autocorrelation coefficient 3730 3639 REAL(wp) :: rg1 !< Gaussian distributed random number 3731 3640 REAL(wp) :: rg2 !< Gaussian distributed random number … … 3739 3648 REAL(wp) :: v_int_u !< x/y-interpolated v-component at particle position at upper vertical level 3740 3649 REAL(wp) :: vnext !< calculated particle v-velocity of corrector step 3741 REAL(wp) :: vv_int !< dummy to compute interpolated mean SGS TKE, used to scale SGS advection 3650 REAL(wp) :: vv_int !< dummy to compute interpolated mean SGS TKE, used to scale SGS advection 3742 3651 REAL(wp) :: w_int_l !< x/y-interpolated w-component at particle position at lower vertical level 3743 3652 REAL(wp) :: w_int_u !< x/y-interpolated w-component at particle position at upper vertical level 3744 3653 REAL(wp) :: wnext !< calculated particle w-velocity of corrector step 3745 3654 REAL(wp) :: w_s !< terminal velocity of droplets 3746 REAL(wp) :: x !< dummy argument for horizontal particle interpolation 3655 REAL(wp) :: x !< dummy argument for horizontal particle interpolation 3747 3656 REAL(wp) :: xp !< calculated particle position in x of predictor step 3748 3657 REAL(wp) :: y !< dummy argument for horizontal particle interpolation … … 3751 3660 REAL(wp) :: zp !< calculated particle position in z of predictor step 3752 3661 3753 REAL(wp), PARAMETER :: a_rog = 9.65_wp !< parameter for fall velocity3754 REAL(wp), PARAMETER :: b_rog = 10.43_wp !< parameter for fall velocity3755 REAL(wp), PARAMETER :: c_rog = 0.6_wp !< parameter for fall velocity3756 REAL(wp), PARAMETER :: k_cap_rog = 4.0_wp !< parameter for fall velocity3757 REAL(wp), PARAMETER :: k_low_rog = 12.0_wp !< parameter for fall velocity3758 REAL(wp), PARAMETER :: d0_rog = 0.745_wp !< separation diameter3759 3760 REAL(wp), DIMENSION(number_of_particles) :: term_1_2 !< flag to communicate whether a particle is near topography or not3761 REAL(wp), DIMENSION(number_of_particles) :: dens_ratio !< ratio between the density of the fluid and the density of the particles3762 3662 REAL(wp), DIMENSION(number_of_particles) :: de_dx_int !< horizontal TKE gradient along x at particle position 3763 3663 REAL(wp), DIMENSION(number_of_particles) :: de_dy_int !< horizontal TKE gradient along y at particle position 3764 3664 REAL(wp), DIMENSION(number_of_particles) :: de_dz_int !< horizontal TKE gradient along z at particle position 3665 REAL(wp), DIMENSION(number_of_particles) :: dens_ratio !< ratio between the density of the fluid and the density of the 3666 !< particles 3765 3667 REAL(wp), DIMENSION(number_of_particles) :: diss_int !< dissipation at particle position 3766 3668 REAL(wp), DIMENSION(number_of_particles) :: dt_gap !< remaining time until particle time integration reaches LES time … … 3772 3674 REAL(wp), DIMENSION(number_of_particles) :: rvar2_temp !< SGS particle velocity - v-component 3773 3675 REAL(wp), DIMENSION(number_of_particles) :: rvar3_temp !< SGS particle velocity - w-component 3676 REAL(wp), DIMENSION(number_of_particles) :: term_1_2 !< flag to communicate whether a particle is near topography or not 3774 3677 REAL(wp), DIMENSION(number_of_particles) :: u_int !< u-component of particle speed 3775 REAL(wp), DIMENSION(number_of_particles) :: v_int !< v-component of particle speed 3678 REAL(wp), DIMENSION(number_of_particles) :: v_int !< v-component of particle speed 3776 3679 REAL(wp), DIMENSION(number_of_particles) :: w_int !< w-component of particle speed 3777 3680 REAL(wp), DIMENSION(number_of_particles) :: xv !< x-position … … 3783 3686 CALL cpu_log( log_point_s(44), 'lpm_advec', 'continue' ) 3784 3687 ! 3785 !-- Determine height of Prandtl layer and distance between Prandtl-layer 3786 !-- height and horizontal mean roughness height, which are required for 3787 !-- vertical logarithmic interpolation of horizontal particle speeds 3788 !-- (for particles below first vertical grid level). 3688 !-- Determine height of Prandtl layer and distance between Prandtl-layer height and horizontal mean 3689 !-- roughness height, which are required for vertical logarithmic interpolation of horizontal 3690 !-- particle speeds (for particles below first vertical grid level). 3789 3691 z_p = zu(nzb+1) - zw(nzb) 3790 3692 d_z_p_z0 = 1.0_wp / ( z_p - z0_av_global ) … … 3796 3698 3797 3699 ! 3798 !-- This case uses a simple interpolation method for the particle velocites, 3799 !-- and applying a predictor-corrector method. @note the current time divergence3800 !-- free time step is denoted with u_t etc.; the velocities of the time level of3801 !-- t+1 wit u,v, and w, as the model is called afterswap timelevel3700 !-- This case uses a simple interpolation method for the particle velocites, and applying a 3701 !-- predictor-corrector method. @note the current time divergence free time step is denoted with 3702 !-- u_t etc.; the velocities of the time level of t+1 wit u,v, and w, as the model is called after 3703 !-- swap timelevel 3802 3704 !-- @attention: for the corrector step the velocities of t(n+1) are required. 3803 !-- Therefore the particle code is executed at the end of the time intermediate 3804 !-- timestep routine. This interpolation method is described in more detail 3805 !-- in Grabowski et al., 2018 (GMD). 3705 !-- Therefore the particle code is executed at the end of the time intermediate timestep routine. 3706 !-- This interpolation method is described in more detail in Grabowski et al., 2018 (GMD). 3806 3707 IF ( interpolation_simple_corrector ) THEN 3807 3708 ! … … 3816 3717 v_int(n) = v_t(kp,jp,ip) * ( 1.0_wp - beta ) + v_t(kp,jp+1,ip) * beta 3817 3718 3818 gamma = MAX( MIN( ( particles(n)%z - zw(kkw) ) / 3819 ( zw(kkw+1) - zw(kkw) ), 1.0_wp ),0.0_wp )3719 gamma = MAX( MIN( ( particles(n)%z - zw(kkw) ) / ( zw(kkw+1) - zw(kkw) ), 1.0_wp ), & 3720 0.0_wp ) 3820 3721 w_int(n) = w_t(kkw,jp,ip) * ( 1.0_wp - gamma ) + w_t(kkw+1,jp,ip) * gamma 3821 3722 … … 3845 3746 !-- z_direction 3846 3747 k_next = MAX( MIN( FLOOR( zp / (zw(kkw+1)-zw(kkw)) + offset_ocean_nzt ), nzt ), 0) 3847 gamma = MAX( MIN( ( zp - zw(k_next) ) / &3748 gamma = MAX( MIN( ( zp - zw(k_next) ) / & 3848 3749 ( zw(k_next+1) - zw(k_next) ), 1.0_wp ), 0.0_wp ) 3849 3750 ! 3850 3751 !-- Calculate part of the corrector step 3851 unext = u(k_next+1, j_next, i_next) * ( 1.0_wp - alpha ) + &3752 unext = u(k_next+1, j_next, i_next) * ( 1.0_wp - alpha ) + & 3852 3753 u(k_next+1, j_next, i_next+1) * alpha 3853 3754 3854 vnext = v(k_next+1, j_next, i_next) * ( 1.0_wp - beta ) + &3755 vnext = v(k_next+1, j_next, i_next) * ( 1.0_wp - beta ) + & 3855 3756 v(k_next+1, j_next+1, i_next ) * beta 3856 3757 3857 wnext = w(k_next, j_next, i_next) * ( 1.0_wp - gamma ) + &3758 wnext = w(k_next, j_next, i_next) * ( 1.0_wp - gamma ) + & 3858 3759 w(k_next+1, j_next, i_next ) * gamma 3859 3760 3860 3761 ! 3861 !-- Calculate interpolated particle velocity with predictor 3862 !-- corrector step. u_int, v_int and w_int describes the part of 3863 !-- the predictor step. unext, vnext and wnext is the part of the 3864 !-- corrector step. The resulting new position is set below. The 3865 !-- implementation is based on Grabowski et al., 2018 (GMD). 3762 !-- Calculate interpolated particle velocity with predictor corrector step. u_int, v_int 3763 !-- and w_int describes the part of the predictor step. unext, vnext and wnext is the part 3764 !-- of the corrector step. The resulting new position is set below. The implementation is 3765 !-- based on Grabowski et al., 2018 (GMD). 3866 3766 u_int(n) = 0.5_wp * ( u_int(n) + unext ) 3867 3767 v_int(n) = 0.5_wp * ( v_int(n) + vnext ) … … 3871 3771 ENDDO 3872 3772 ! 3873 !-- This case uses a simple interpolation method for the particle velocites, 3874 !-- and applying apredictor.3773 !-- This case uses a simple interpolation method for the particle velocites, and applying a 3774 !-- predictor. 3875 3775 ELSEIF ( interpolation_simple_predictor ) THEN 3876 3776 ! … … 3886 3786 v_int(n) = v(kp,jp,ip) * ( 1.0_wp - beta ) + v(kp,jp+1,ip) * beta 3887 3787 3888 gamma = MAX( MIN( ( particles(n)%z - zw(kkw) ) / 3889 ( zw(kkw+1) - zw(kkw) ), 1.0_wp ),0.0_wp )3788 gamma = MAX( MIN( ( particles(n)%z - zw(kkw) ) / ( zw(kkw+1) - zw(kkw) ), 1.0_wp ), & 3789 0.0_wp ) 3890 3790 w_int(n) = w(kkw,jp,ip) * ( 1.0_wp - gamma ) + w(kkw+1,jp,ip) * gamma 3891 3791 ENDDO … … 3907 3807 ! 3908 3808 !-- Interpolation of the u velocity component onto particle position. 3909 !-- Particles are interpolation bi-linearly in the horizontal and a 3910 !-- linearly in the vertical. An exception is made for particles below 3911 !-- the first vertical grid level in case of a prandtl layer. In this 3912 !-- case the horizontal particle velocity components are determined using 3913 !-- Monin-Obukhov relations (if branch). 3914 !-- First, check if particle is located below first vertical grid level 3915 !-- above topography (Prandtl-layer height) 3809 !-- Particles are interpolation bi-linearly in the horizontal and a linearly in the 3810 !-- vertical. An exception is made for particles below the first vertical grid level in 3811 !-- case of a prandtl layer. In this case the horizontal particle velocity components are 3812 !-- determined using Monin-Obukhov relations (if branch). 3813 !-- First, check if particle is located below first vertical grid level above topography 3814 !-- (Prandtl-layer height). 3916 3815 !-- Determine vertical index of topography top 3917 3816 k_wall = topo_top_ind(jp,ip,0) … … 3925 3824 ! 3926 3825 !-- Determine the sublayer. Further used as index. 3927 height_p = ( zv(n) - zw(k_wall) - z0_av_global ) &3928 * REAL( number_of_sublayers, KIND=wp ) &3826 height_p = ( zv(n) - zw(k_wall) - z0_av_global ) & 3827 * REAL( number_of_sublayers, KIND=wp ) & 3929 3828 * d_z_p_z0 3930 3829 ! 3931 3830 !-- Calculate LOG(z/z0) for exact particle height. Therefore, 3932 3831 !-- interpolate linearly between precalculated logarithm. 3933 log_z_z0_int = log_z_z0(INT(height_p)) & 3934 + ( height_p - INT(height_p) ) & 3935 * ( log_z_z0(INT(height_p)+1) & 3936 - log_z_z0(INT(height_p)) & 3937 ) 3832 log_z_z0_int = log_z_z0( INT( height_p ) ) + ( height_p - INT( height_p ) ) * & 3833 ( log_z_z0( INT( height_p ) + 1 ) - log_z_z0( INT( height_p ) ) ) 3938 3834 ! 3939 3835 !-- Compute u*-portion for u-component based on mean roughness. 3940 !-- Note, neutral solution is applied for all situations, e.g. also for 3941 !-- unstable and stable situations. Even though this is not exact 3942 !-- this saves a lot of CPU time since several calls of intrinsic 3943 !-- FORTRAN procedures (LOG, ATAN) are avoided, This is justified 3944 !-- as sensitivity studies revealed no significant effect of 3945 !-- using the neutral solution also for un/stable situations. Based on the u* 3946 !-- recalculate the velocity at height z_particle. Since the analytical solution 3947 !-- only yields absolute values, include the sign using the intrinsic SIGN function. 3836 !-- Note, neutral solution is applied for all situations, e.g. also for unstable and 3837 !-- stable situations. Even though this is not exact this saves a lot of CPU time 3838 !-- since several calls of intrinsic FORTRAN procedures (LOG, ATAN) are avoided. This 3839 !-- is justified as sensitivity studies revealed no significant effect of using the 3840 !-- neutral solution also for un/stable situations. Based on the u* recalculate the 3841 !-- velocity at height z_particle. Since the analytical solution only yields absolute 3842 !-- values, include the sign using the intrinsic SIGN function. 3948 3843 us_int = kappa * 0.5_wp * ABS( u(k_wall+1,jp,ip) + u(k_wall+1,jp,ip+1) ) / & 3949 3844 log_z_z0(number_of_sublayers) … … 3953 3848 ENDIF 3954 3849 ! 3955 !-- Particle above the first grid level. Bi-linear interpolation in the 3956 !-- horizontal andlinear interpolation in the vertical direction.3850 !-- Particle above the first grid level. Bi-linear interpolation in the horizontal and 3851 !-- linear interpolation in the vertical direction. 3957 3852 ELSE 3958 3853 x = xv(n) - i * dx … … 3964 3859 gg = aa + bb + cc + dd 3965 3860 3966 u_int_l = ( ( gg - aa ) * u(k,j,i) + ( gg - bb ) * u(k,j,i+1) &3967 + ( gg - cc ) * u(k,j+1,i) + ( gg - dd ) * &3968 u(k,j+1,i+1) )/ ( 3.0_wp * gg ) - u_gtrans3861 u_int_l = ( ( gg - aa ) * u(k,j,i) + ( gg - bb ) * u(k,j,i+1) & 3862 + ( gg - cc ) * u(k,j+1,i) + ( gg - dd ) * u(k,j+1,i+1) ) & 3863 / ( 3.0_wp * gg ) - u_gtrans 3969 3864 3970 3865 IF ( k == nzt ) THEN 3971 3866 u_int(n) = u_int_l 3972 3867 ELSE 3973 u_int_u = ( ( gg-aa ) * u(k+1,j,i) + ( gg-bb ) * u(k+1,j,i+1) & 3974 + ( gg-cc ) * u(k+1,j+1,i) + ( gg-dd ) * & 3975 u(k+1,j+1,i+1) ) / ( 3.0_wp * gg ) - u_gtrans 3976 u_int(n) = u_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 3977 ( u_int_u - u_int_l ) 3868 u_int_u = ( ( gg-aa ) * u(k+1,j,i) + ( gg-bb ) * u(k+1,j,i+1) & 3869 + ( gg-cc ) * u(k+1,j+1,i) + ( gg-dd ) * u(k+1,j+1,i+1) ) & 3870 / ( 3.0_wp * gg ) - u_gtrans 3871 u_int(n) = u_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * ( u_int_u - u_int_l ) 3978 3872 ENDIF 3979 3873 ENDIF … … 3998 3892 ! 3999 3893 !-- Determine the sublayer. Further used as index. 4000 height_p = ( zv(n) - zw(k_wall) - z0_av_global ) &4001 * REAL( number_of_sublayers, KIND=wp ) &3894 height_p = ( zv(n) - zw(k_wall) - z0_av_global ) & 3895 * REAL( number_of_sublayers, KIND=wp ) & 4002 3896 * d_z_p_z0 4003 3897 ! 4004 !-- Calculate LOG(z/z0) for exact particle height. Therefore, 4005 !-- interpolate linearly between precalculated logarithm. 4006 log_z_z0_int = log_z_z0(INT(height_p)) & 4007 + ( height_p - INT(height_p) ) & 4008 * ( log_z_z0(INT(height_p)+1) & 4009 - log_z_z0(INT(height_p)) & 3898 !-- Calculate LOG(z/z0) for exact particle height. Therefore, interpolate linearly 3899 !-- between precalculated logarithm. 3900 log_z_z0_int = log_z_z0(INT(height_p)) & 3901 + ( height_p - INT(height_p) ) & 3902 * ( log_z_z0(INT(height_p)+1) - log_z_z0(INT(height_p)) & 4010 3903 ) 4011 3904 ! 4012 3905 !-- Compute u*-portion for v-component based on mean roughness. 4013 !-- Note, neutral solution is applied for all situations, e.g. also for 4014 !-- unstable and stable situations. Even though this is not exact 4015 !-- this saves a lot of CPU time since several calls of intrinsic 4016 !-- FORTRAN procedures (LOG, ATAN) are avoided, This is justified 4017 !-- as sensitivity studies revealed no significant effect of 4018 !-- using the neutral solution also for un/stable situations. Based on the u* 4019 !-- recalculate the velocity at height z_particle. Since the analytical solution 4020 !-- only yields absolute values, include the sign using the intrinsic SIGN function. 3906 !-- Note, neutral solution is applied for all situations, e.g. also for unstable and 3907 !-- stable situations. Even though this is not exact this saves a lot of CPU time 3908 !-- since several calls of intrinsic FORTRAN procedures (LOG, ATAN) are avoided, This 3909 !-- is justified as sensitivity studies revealed no significant effect of using the 3910 !-- neutral solution also for un/stable situations. Based on the u* recalculate the 3911 !-- velocity at height z_particle. Since the analytical solution only yields absolute 3912 !-- values, include the sign using the intrinsic SIGN function. 4021 3913 us_int = kappa * 0.5_wp * ABS( v(k_wall+1,jp,ip) + v(k_wall+1,jp+1,ip) ) / & 4022 3914 log_z_z0(number_of_sublayers) … … 4034 3926 gg = aa + bb + cc + dd 4035 3927 4036 v_int_l = ( ( gg - aa ) * v(k,j,i) + ( gg - bb ) * v(k,j,i+1) &4037 + ( gg - cc ) * v(k,j+1,i) + ( gg - dd ) * v(k,j+1,i+1) &3928 v_int_l = ( ( gg - aa ) * v(k,j,i) + ( gg - bb ) * v(k,j,i+1) & 3929 + ( gg - cc ) * v(k,j+1,i) + ( gg - dd ) * v(k,j+1,i+1) & 4038 3930 ) / ( 3.0_wp * gg ) - v_gtrans 4039 3931 … … 4041 3933 v_int(n) = v_int_l 4042 3934 ELSE 4043 v_int_u = ( ( gg-aa ) * v(k+1,j,i) + ( gg-bb ) * v(k+1,j,i+1) &4044 + ( gg-cc ) * v(k+1,j+1,i) + ( gg-dd ) * v(k+1,j+1,i+1) &3935 v_int_u = ( ( gg-aa ) * v(k+1,j,i) + ( gg-bb ) * v(k+1,j,i+1) & 3936 + ( gg-cc ) * v(k+1,j+1,i) + ( gg-dd ) * v(k+1,j+1,i+1) & 4045 3937 ) / ( 3.0_wp * gg ) - v_gtrans 4046 v_int(n) = v_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 4047 ( v_int_u - v_int_l ) 3938 v_int(n) = v_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * ( v_int_u - v_int_l ) 4048 3939 ENDIF 4049 3940 ENDIF … … 4065 3956 gg = aa + bb + cc + dd 4066 3957 4067 w_int_l = ( ( gg - aa ) * w(k,j,i) + ( gg - bb ) * w(k,j,i+1) &4068 + ( gg - cc ) * w(k,j+1,i) + ( gg - dd ) * w(k,j+1,i+1) &3958 w_int_l = ( ( gg - aa ) * w(k,j,i) + ( gg - bb ) * w(k,j,i+1) & 3959 + ( gg - cc ) * w(k,j+1,i) + ( gg - dd ) * w(k,j+1,i+1) & 4069 3960 ) / ( 3.0_wp * gg ) 4070 3961 … … 4072 3963 w_int(n) = w_int_l 4073 3964 ELSE 4074 w_int_u = ( ( gg-aa ) * w(k+1,j,i) + &4075 ( gg-bb ) * w(k+1,j,i+1) + &4076 ( gg-cc ) * w(k+1,j+1,i) + &4077 ( gg-dd ) * w(k+1,j+1,i+1) &3965 w_int_u = ( ( gg-aa ) * w(k+1,j,i) + & 3966 ( gg-bb ) * w(k+1,j,i+1) + & 3967 ( gg-cc ) * w(k+1,j+1,i) + & 3968 ( gg-dd ) * w(k+1,j+1,i+1) & 4078 3969 ) / ( 3.0_wp * gg ) 4079 w_int(n) = w_int_l + ( zv(n) - zw(k) ) / dzw(k+1) * & 4080 ( w_int_u - w_int_l ) 3970 w_int(n) = w_int_l + ( zv(n) - zw(k) ) / dzw(k+1) * ( w_int_u - w_int_l ) 4081 3971 ENDIF 4082 3972 ELSE … … 4087 3977 ENDIF 4088 3978 4089 !-- Interpolate and calculate quantities needed for calculating the SGS 4090 !-- velocities 3979 !-- Interpolate and calculate quantities needed for calculating the SGS velocities 4091 3980 IF ( use_sgs_for_particles .AND. .NOT. cloud_droplets ) THEN 4092 3981 … … 4100 3989 j = jp + MERGE( -1_iwp , 1_iwp, BTEST( nb, 1 ) ) 4101 3990 k = kp + MERGE( -1_iwp , 1_iwp, BTEST( nb, 0 ) ) 4102 IF ( .NOT. BTEST(wall_flags_total_0(k, jp, ip), 0) .OR. &4103 .NOT. BTEST(wall_flags_total_0(kp, j, ip), 0) .OR. &4104 .NOT. BTEST(wall_flags_total_0(kp, jp, i ), 0) ) &3991 IF ( .NOT. BTEST(wall_flags_total_0(k, jp, ip), 0) .OR. & 3992 .NOT. BTEST(wall_flags_total_0(kp, j, ip), 0) .OR. & 3993 .NOT. BTEST(wall_flags_total_0(kp, jp, i ), 0) ) & 4105 3994 THEN 4106 3995 subbox_at_wall = .TRUE. … … 4108 3997 ENDIF 4109 3998 IF ( subbox_at_wall ) THEN 4110 e_int(start_index(nb):end_index(nb)) = e(kp,jp,ip) 3999 e_int(start_index(nb):end_index(nb)) = e(kp,jp,ip) 4111 4000 diss_int(start_index(nb):end_index(nb)) = diss(kp,jp,ip) 4112 4001 de_dx_int(start_index(nb):end_index(nb)) = de_dx(kp,jp,ip) … … 4132 4021 gg = aa + bb + cc + dd 4133 4022 4134 e_int_l = ( ( gg-aa ) * e(k,j,i) + ( gg-bb ) * e(k,j,i+1) &4135 + ( gg-cc ) * e(k,j+1,i) + ( gg-dd ) * e(k,j+1,i+1) &4023 e_int_l = ( ( gg-aa ) * e(k,j,i) + ( gg-bb ) * e(k,j,i+1) & 4024 + ( gg-cc ) * e(k,j+1,i) + ( gg-dd ) * e(k,j+1,i+1) & 4136 4025 ) / ( 3.0_wp * gg ) 4137 4026 … … 4144 4033 ( gg - dd ) * e(k+1,j+1,i+1) & 4145 4034 ) / ( 3.0_wp * gg ) 4146 e_int(n) = e_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 4147 ( e_int_u - e_int_l ) 4035 e_int(n) = e_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * ( e_int_u - e_int_l ) 4148 4036 ENDIF 4149 4037 ! 4150 !-- Needed to avoid NaN particle velocities (this might not be 4151 !-- required any more) 4038 !-- Needed to avoid NaN particle velocities (this might not be required any more) 4152 4039 IF ( e_int(n) <= 0.0_wp ) THEN 4153 4040 e_int(n) = 1.0E-20_wp 4154 4041 ENDIF 4155 4042 ! 4156 !-- Interpolate the TKE gradient along x (adopt incides i,j,k and 4157 !-- all position variablesfrom above (TKE))4158 de_dx_int_l = ( ( gg - aa ) * de_dx(k,j,i) + &4159 ( gg - bb ) * de_dx(k,j,i+1) + &4160 ( gg - cc ) * de_dx(k,j+1,i) + &4161 ( gg - dd ) * de_dx(k,j+1,i+1) &4043 !-- Interpolate the TKE gradient along x (adopt incides i,j,k and all position variables 4044 !-- from above (TKE)) 4045 de_dx_int_l = ( ( gg - aa ) * de_dx(k,j,i) + & 4046 ( gg - bb ) * de_dx(k,j,i+1) + & 4047 ( gg - cc ) * de_dx(k,j+1,i) + & 4048 ( gg - dd ) * de_dx(k,j+1,i+1) & 4162 4049 ) / ( 3.0_wp * gg ) 4163 4050 … … 4165 4052 de_dx_int(n) = de_dx_int_l 4166 4053 ELSE 4167 de_dx_int_u = ( ( gg - aa ) * de_dx(k+1,j,i) + &4168 ( gg - bb ) * de_dx(k+1,j,i+1) + &4169 ( gg - cc ) * de_dx(k+1,j+1,i) + &4170 ( gg - dd ) * de_dx(k+1,j+1,i+1) &4054 de_dx_int_u = ( ( gg - aa ) * de_dx(k+1,j,i) + & 4055 ( gg - bb ) * de_dx(k+1,j,i+1) + & 4056 ( gg - cc ) * de_dx(k+1,j+1,i) + & 4057 ( gg - dd ) * de_dx(k+1,j+1,i+1) & 4171 4058 ) / ( 3.0_wp * gg ) 4172 de_dx_int(n) = de_dx_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * &4059 de_dx_int(n) = de_dx_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 4173 4060 ( de_dx_int_u - de_dx_int_l ) 4174 4061 ENDIF 4175 4062 ! 4176 4063 !-- Interpolate the TKE gradient along y 4177 de_dy_int_l = ( ( gg - aa ) * de_dy(k,j,i) + &4178 ( gg - bb ) * de_dy(k,j,i+1) + &4179 ( gg - cc ) * de_dy(k,j+1,i) + &4180 ( gg - dd ) * de_dy(k,j+1,i+1) &4064 de_dy_int_l = ( ( gg - aa ) * de_dy(k,j,i) + & 4065 ( gg - bb ) * de_dy(k,j,i+1) + & 4066 ( gg - cc ) * de_dy(k,j+1,i) + & 4067 ( gg - dd ) * de_dy(k,j+1,i+1) & 4181 4068 ) / ( 3.0_wp * gg ) 4182 4069 IF ( ( k+1 == nzt+1 ) .OR. ( k == nzb ) ) THEN 4183 4070 de_dy_int(n) = de_dy_int_l 4184 4071 ELSE 4185 de_dy_int_u = ( ( gg - aa ) * de_dy(k+1,j,i) + &4186 ( gg - bb ) * de_dy(k+1,j,i+1) + &4187 ( gg - cc ) * de_dy(k+1,j+1,i) + &4188 ( gg - dd ) * de_dy(k+1,j+1,i+1) &4072 de_dy_int_u = ( ( gg - aa ) * de_dy(k+1,j,i) + & 4073 ( gg - bb ) * de_dy(k+1,j,i+1) + & 4074 ( gg - cc ) * de_dy(k+1,j+1,i) + & 4075 ( gg - dd ) * de_dy(k+1,j+1,i+1) & 4189 4076 ) / ( 3.0_wp * gg ) 4190 de_dy_int(n) = de_dy_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * &4077 de_dy_int(n) = de_dy_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 4191 4078 ( de_dy_int_u - de_dy_int_l ) 4192 4079 ENDIF … … 4197 4084 de_dz_int(n) = 0.0_wp 4198 4085 ELSE 4199 de_dz_int_l = ( ( gg - aa ) * de_dz(k,j,i) + &4200 ( gg - bb ) * de_dz(k,j,i+1) + &4201 ( gg - cc ) * de_dz(k,j+1,i) + &4202 ( gg - dd ) * de_dz(k,j+1,i+1) &4086 de_dz_int_l = ( ( gg - aa ) * de_dz(k,j,i) + & 4087 ( gg - bb ) * de_dz(k,j,i+1) + & 4088 ( gg - cc ) * de_dz(k,j+1,i) + & 4089 ( gg - dd ) * de_dz(k,j+1,i+1) & 4203 4090 ) / ( 3.0_wp * gg ) 4204 4091 … … 4206 4093 de_dz_int(n) = de_dz_int_l 4207 4094 ELSE 4208 de_dz_int_u = ( ( gg - aa ) * de_dz(k+1,j,i) + &4209 ( gg - bb ) * de_dz(k+1,j,i+1) + &4210 ( gg - cc ) * de_dz(k+1,j+1,i) + &4211 ( gg - dd ) * de_dz(k+1,j+1,i+1) &4095 de_dz_int_u = ( ( gg - aa ) * de_dz(k+1,j,i) + & 4096 ( gg - bb ) * de_dz(k+1,j,i+1) + & 4097 ( gg - cc ) * de_dz(k+1,j+1,i) + & 4098 ( gg - dd ) * de_dz(k+1,j+1,i+1) & 4212 4099 ) / ( 3.0_wp * gg ) 4213 de_dz_int(n) = de_dz_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * &4100 de_dz_int(n) = de_dz_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 4214 4101 ( de_dz_int_u - de_dz_int_l ) 4215 4102 ENDIF … … 4218 4105 ! 4219 4106 !-- Interpolate the dissipation of TKE 4220 diss_int_l = ( ( gg - aa ) * diss(k,j,i) + &4221 ( gg - bb ) * diss(k,j,i+1) + &4222 ( gg - cc ) * diss(k,j+1,i) + &4223 ( gg - dd ) * diss(k,j+1,i+1) &4107 diss_int_l = ( ( gg - aa ) * diss(k,j,i) + & 4108 ( gg - bb ) * diss(k,j,i+1) + & 4109 ( gg - cc ) * diss(k,j+1,i) + & 4110 ( gg - dd ) * diss(k,j+1,i+1) & 4224 4111 ) / ( 3.0_wp * gg ) 4225 4112 … … 4227 4114 diss_int(n) = diss_int_l 4228 4115 ELSE 4229 diss_int_u = ( ( gg - aa ) * diss(k+1,j,i) + &4230 ( gg - bb ) * diss(k+1,j,i+1) + &4231 ( gg - cc ) * diss(k+1,j+1,i) + &4232 ( gg - dd ) * diss(k+1,j+1,i+1) &4116 diss_int_u = ( ( gg - aa ) * diss(k+1,j,i) + & 4117 ( gg - bb ) * diss(k+1,j,i+1) + & 4118 ( gg - cc ) * diss(k+1,j+1,i) + & 4119 ( gg - dd ) * diss(k+1,j+1,i+1) & 4233 4120 ) / ( 3.0_wp * gg ) 4234 diss_int(n) = diss_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * &4121 diss_int(n) = diss_int_l + ( zv(n) - zu(k) ) / dzw(k+1) * & 4235 4122 ( diss_int_u - diss_int_l ) 4236 4123 ENDIF … … 4250 4137 DO n = start_index(nb), end_index(nb) 4251 4138 ! 4252 !-- Vertical interpolation of the horizontally averaged SGS TKE and 4253 !-- resolved-scale velocity variances and use the interpolated values 4254 !-- to calculate the coefficient fs, which is a measure of the ratio 4255 !-- of the subgrid-scale turbulent kinetic energy to the total amount 4139 !-- Vertical interpolation of the horizontally averaged SGS TKE and resolved-scale velocity 4140 !-- variances and use the interpolated values to calculate the coefficient fs, which is a 4141 !-- measure of the ratio of the subgrid-scale turbulent kinetic energy to the total amount 4256 4142 !-- of turbulent kinetic energy. 4257 4143 IF ( k == 0 ) THEN 4258 4144 e_mean_int = hom(0,1,8,0) 4259 4145 ELSE 4260 e_mean_int = hom(k,1,8,0) + & 4261 ( hom(k+1,1,8,0) - hom(k,1,8,0) ) / & 4262 ( zu(k+1) - zu(k) ) * & 4263 ( zv(n) - zu(k) ) 4146 e_mean_int = hom(k,1,8,0) + ( hom(k+1,1,8,0) - hom(k,1,8,0) ) / & 4147 ( zu(k+1) - zu(k) ) * & 4148 ( zv(n) - zu(k) ) 4264 4149 ENDIF 4265 4150 … … 4274 4159 ( 1.0_wp * ( zw(kw+1) - zw(kw) ) ) ) 4275 4160 ELSE 4276 aa = hom(k,1,30,0) + ( hom(k+1,1,30,0) - hom(k,1,30,0) ) * &4161 aa = hom(k,1,30,0) + ( hom(k+1,1,30,0) - hom(k,1,30,0) ) * & 4277 4162 ( ( zv(n) - zu(k) ) / ( zu(k+1) - zu(k) ) ) 4278 bb = hom(k,1,31,0) + ( hom(k+1,1,31,0) - hom(k,1,31,0) ) * &4163 bb = hom(k,1,31,0) + ( hom(k+1,1,31,0) - hom(k,1,31,0) ) * & 4279 4164 ( ( zv(n) - zu(k) ) / ( zu(k+1) - zu(k) ) ) 4280 cc = hom(kw,1,32,0) + ( hom(kw+1,1,32,0)-hom(kw,1,32,0) ) * &4165 cc = hom(kw,1,32,0) + ( hom(kw+1,1,32,0)-hom(kw,1,32,0) ) * & 4281 4166 ( ( zv(n) - zw(kw) ) / ( zw(kw+1)-zw(kw) ) ) 4282 4167 ENDIF … … 4284 4169 vv_int = ( 1.0_wp / 3.0_wp ) * ( aa + bb + cc ) 4285 4170 ! 4286 !-- Needed to avoid NaN particle velocities. The value of 1.0 is just 4287 !-- an educated guess forthe given case.4171 !-- Needed to avoid NaN particle velocities. The value of 1.0 is just an educated guess for 4172 !-- the given case. 4288 4173 IF ( vv_int + ( 2.0_wp / 3.0_wp ) * e_mean_int == 0.0_wp ) THEN 4289 4174 fs_int(n) = 1.0_wp 4290 4175 ELSE 4291 fs_int(n) = ( 2.0_wp / 3.0_wp ) * e_mean_int / &4176 fs_int(n) = ( 2.0_wp / 3.0_wp ) * e_mean_int / & 4292 4177 ( vv_int + ( 2.0_wp / 3.0_wp ) * e_mean_int ) 4293 4178 ENDIF … … 4312 4197 ! 4313 4198 !-- Calculate the Lagrangian timescale according to Weil et al. (2004). 4314 lagr_timescale(n) = ( 4.0_wp * e_int(n) + 1E-20_wp ) / &4315 ( 3.0_wp * fs_int(n) * c_0 * diss_int(n) + 1E-20_wp )4316 4317 ! 4318 !-- Calculate the next particle timestep. dt_gap is the time needed to 4319 !-- complete the currentLES timestep.4199 lagr_timescale(n) = ( 4.0_wp * e_int(n) + 1E-20_wp ) / & 4200 ( 3.0_wp * fs_int(n) * c_0 * diss_int(n) + 1E-20_wp ) 4201 4202 ! 4203 !-- Calculate the next particle timestep. dt_gap is the time needed to complete the current 4204 !-- LES timestep. 4320 4205 dt_gap(n) = dt_3d - particles(n)%dt_sum 4321 4206 dt_particle(n) = MIN( dt_3d, 0.025_wp * lagr_timescale(n), dt_gap(n) ) … … 4323 4208 particles(n)%aux2 = dt_gap(n) 4324 4209 ! 4325 !-- The particle timestep should not be too small in order to prevent 4326 !-- the number ofparticle timesteps of getting too large4210 !-- The particle timestep should not be too small in order to prevent the number of 4211 !-- particle timesteps of getting too large 4327 4212 IF ( dt_particle(n) < dt_min_part ) THEN 4328 4213 IF ( dt_min_part < dt_gap(n) ) THEN … … 4340 4225 IF ( particles(n)%age == 0.0_wp ) THEN 4341 4226 ! 4342 !-- For new particles the SGS components are derived from the SGS 4343 !-- TKE. Limit the Gaussian random number to the interval 4344 !-- [-5.0*sigma, 5.0*sigma] in order to prevent the SGS velocities 4345 !-- from becoming unrealistically large. 4346 rvar1_temp(n) = SQRT( 2.0_wp * sgs_wf_part * e_int(n) & 4347 + 1E-20_wp ) * rg(n,1) 4348 rvar2_temp(n) = SQRT( 2.0_wp * sgs_wf_part * e_int(n) & 4349 + 1E-20_wp ) * rg(n,2) 4350 rvar3_temp(n) = SQRT( 2.0_wp * sgs_wf_part * e_int(n) & 4351 + 1E-20_wp ) * rg(n,3) 4227 !-- For new particles the SGS components are derived from the SGS TKE. Limit the 4228 !-- Gaussian random number to the interval [-5.0*sigma, 5.0*sigma] in order to prevent 4229 !-- the SGS velocities from becoming unrealistically large. 4230 rvar1_temp(n) = SQRT( 2.0_wp * sgs_wf_part * e_int(n) + 1E-20_wp ) * rg(n,1) 4231 rvar2_temp(n) = SQRT( 2.0_wp * sgs_wf_part * e_int(n) + 1E-20_wp ) * rg(n,2) 4232 rvar3_temp(n) = SQRT( 2.0_wp * sgs_wf_part * e_int(n) + 1E-20_wp ) * rg(n,3) 4352 4233 ELSE 4353 4234 ! 4354 !-- Restriction of the size of the new timestep: compared to the 4235 !-- Restriction of the size of the new timestep: compared to the 4355 4236 !-- previous timestep the increase must not exceed 200%. First, 4356 4237 !-- check if age > age_m, in order to prevent that particles get zero 4357 4238 !-- timestep. 4358 dt_particle_m = MERGE( dt_particle(n), & 4359 particles(n)%age - particles(n)%age_m, & 4360 particles(n)%age - particles(n)%age_m < & 4361 1E-8_wp ) 4239 dt_particle_m = MERGE( dt_particle(n), & 4240 particles(n)%age - particles(n)%age_m, & 4241 particles(n)%age - particles(n)%age_m < 1E-8_wp ) 4362 4242 IF ( dt_particle(n) > 2.0_wp * dt_particle_m ) THEN 4363 4243 dt_particle(n) = 2.0_wp * dt_particle_m 4364 4244 ENDIF 4365 4245 4366 !-- For old particles the SGS components are correlated with the 4367 !-- values from the previous timestep. Random numbers have also to 4368 !-- be limited (see above). 4369 !-- As negative values for the subgrid TKE are not allowed, the 4370 !-- change of the subgrid TKE with time cannot be smaller than 4371 !-- -e_int(n)/dt_particle. This value is used as a lower boundary 4372 !-- value for the change of TKE 4246 !-- For old particles the SGS components are correlated with the values from the 4247 !-- previous timestep. Random numbers have also to be limited (see above). 4248 !-- As negative values for the subgrid TKE are not allowed, the change of the subgrid 4249 !-- TKE with time cannot be smaller than -e_int(n)/dt_particle. This value is used as a 4250 !-- lower boundary value for the change of TKE 4373 4251 de_dt_min = - e_int(n) / dt_particle(n) 4374 4252 … … 4379 4257 ENDIF 4380 4258 4381 CALL weil_stochastic_eq( rvar1_temp(n), fs_int(n), e_int(n), & 4382 de_dx_int(n), de_dt, diss_int(n), & 4383 dt_particle(n), rg(n,1), term_1_2(n) ) 4384 4385 CALL weil_stochastic_eq( rvar2_temp(n), fs_int(n), e_int(n), & 4386 de_dy_int(n), de_dt, diss_int(n), & 4387 dt_particle(n), rg(n,2), term_1_2(n) ) 4388 4389 CALL weil_stochastic_eq( rvar3_temp(n), fs_int(n), e_int(n), & 4390 de_dz_int(n), de_dt, diss_int(n), & 4391 dt_particle(n), rg(n,3), term_1_2(n) ) 4259 CALL weil_stochastic_eq( rvar1_temp(n), fs_int(n), e_int(n), de_dx_int(n), de_dt, & 4260 diss_int(n), dt_particle(n), rg(n,1), term_1_2(n) ) 4261 4262 CALL weil_stochastic_eq( rvar2_temp(n), fs_int(n), e_int(n), de_dy_int(n), de_dt, & 4263 diss_int(n), dt_particle(n), rg(n,2), term_1_2(n) ) 4264 4265 CALL weil_stochastic_eq( rvar3_temp(n), fs_int(n), e_int(n), de_dz_int(n), de_dt, & 4266 diss_int(n), dt_particle(n), rg(n,3), term_1_2(n) ) 4392 4267 4393 4268 ENDIF … … 4396 4271 ENDDO 4397 4272 ! 4398 !-- Check if the added SGS velocities result in a violation of the CFL- 4399 !-- criterion. If yes, limt the SGS particle speed to match the 4400 !-- CFL criterion. Note, a re-calculation of the SGS particle speed with 4401 !-- smaller timestep does not necessarily fulfill the CFL criterion as the 4402 !-- new SGS speed can be even larger (due to the random term with scales with 4403 !-- the square-root of dt_particle, for small dt the random contribution increases). 4404 !-- Thus, we would need to re-calculate the SGS speeds as long as they would 4405 !-- fulfill the requirements, which could become computationally expensive, 4273 !-- Check if the added SGS velocities result in a violation of the CFL-criterion. If yes, limt 4274 !-- the SGS particle speed to match the CFL criterion. Note, a re-calculation of the SGS particle 4275 !-- speed with smaller timestep does not necessarily fulfill the CFL criterion as the new SGS 4276 !-- speed can be even larger (due to the random term with scales with the square-root of 4277 !-- dt_particle, for small dt the random contribution increases). 4278 !-- Thus, we would need to re-calculate the SGS speeds as long as they would fulfill the 4279 !-- requirements, which could become computationally expensive, 4406 4280 !-- Hence, we just limit them. 4407 4281 dz_temp = zw(kp)-zw(kp-1) … … 4409 4283 DO nb = 0, 7 4410 4284 DO n = start_index(nb), end_index(nb) 4411 IF ( ABS( u_int(n) + rvar1_temp(n) ) > ( dx / dt_particle(n) ) .OR. &4412 ABS( v_int(n) + rvar2_temp(n) ) > ( dy / dt_particle(n) ) .OR. &4285 IF ( ABS( u_int(n) + rvar1_temp(n) ) > ( dx / dt_particle(n) ) .OR. & 4286 ABS( v_int(n) + rvar2_temp(n) ) > ( dy / dt_particle(n) ) .OR. & 4413 4287 ABS( w_int(n) + rvar3_temp(n) ) > ( dz_temp / dt_particle(n) ) ) THEN 4414 4288 ! 4415 !-- If total speed exceeds the allowed speed according to CFL 4289 !-- If total speed exceeds the allowed speed according to CFL 4416 4290 !-- criterion, limit the SGS speed to 4417 4291 !-- dx_i / dt_particle - u_resolved_i, considering a safty factor. 4418 rvar1_temp(n) = MERGE( rvar1_temp(n), &4419 0.9_wp * &4420 SIGN( dx / dt_particle(n) &4421 - ABS( u_int(n) ), rvar1_temp(n) ),&4422 ABS( u_int(n) + rvar1_temp(n) ) < &4292 rvar1_temp(n) = MERGE( rvar1_temp(n), & 4293 0.9_wp * & 4294 SIGN( dx / dt_particle(n) & 4295 - ABS( u_int(n) ), rvar1_temp(n) ), & 4296 ABS( u_int(n) + rvar1_temp(n) ) < & 4423 4297 ( dx / dt_particle(n) ) ) 4424 rvar2_temp(n) = MERGE( rvar2_temp(n), &4425 0.9_wp * &4426 SIGN( dy / dt_particle(n) &4427 - ABS( v_int(n) ), rvar2_temp(n) ),&4428 ABS( v_int(n) + rvar2_temp(n) ) < &4298 rvar2_temp(n) = MERGE( rvar2_temp(n), & 4299 0.9_wp * & 4300 SIGN( dy / dt_particle(n) & 4301 - ABS( v_int(n) ), rvar2_temp(n) ), & 4302 ABS( v_int(n) + rvar2_temp(n) ) < & 4429 4303 ( dy / dt_particle(n) ) ) 4430 rvar3_temp(n) = MERGE( rvar3_temp(n), &4431 0.9_wp * &4432 SIGN( zw(kp)-zw(kp-1) / dt_particle(n) &4433 - ABS( w_int(n) ), rvar3_temp(n) ),&4434 ABS( w_int(n) + rvar3_temp(n) ) < &4304 rvar3_temp(n) = MERGE( rvar3_temp(n), & 4305 0.9_wp * & 4306 SIGN( zw(kp)-zw(kp-1) / dt_particle(n) & 4307 - ABS( w_int(n) ), rvar3_temp(n) ), & 4308 ABS( w_int(n) + rvar3_temp(n) ) < & 4435 4309 ( zw(kp)-zw(kp-1) / dt_particle(n) ) ) 4436 4310 ENDIF 4437 4311 ! 4438 !-- Update particle velocites 4312 !-- Update particle velocites 4439 4313 particles(n)%rvar1 = rvar1_temp(n) 4440 4314 particles(n)%rvar2 = rvar2_temp(n) … … 4444 4318 w_int(n) = w_int(n) + particles(n)%rvar3 4445 4319 ! 4446 !-- Store the SGS TKE of the current timelevel which is needed for 4447 !-- for calculating the SGSparticle velocities at the next timestep4320 !-- Store the SGS TKE of the current timelevel which is needed for for calculating the SGS 4321 !-- particle velocities at the next timestep 4448 4322 particles(n)%e_m = e_int(n) 4449 4323 ENDDO … … 4452 4326 ELSE 4453 4327 ! 4454 !-- If no SGS velocities are used, only the particle timestep has to 4455 !-- be set 4328 !-- If no SGS velocities are used, only the particle timestep has to be set 4456 4329 dt_particle = dt_3d 4457 4330 … … 4461 4334 IF ( ANY( dens_ratio == 0.0_wp ) ) THEN 4462 4335 ! 4463 !-- Decide whether the particle loop runs over the subboxes or only over 1, 4464 !-- number_of_particles. This depends on the selected interpolation method. 4465 !-- If particle interpolation method is not trilinear, then the sorting within 4466 !-- subboxes is not required. However, therefore the index start_index(nb) and 4467 !-- end_index(nb) are not defined and the loops are still over 4468 !-- number_of_particles. @todo find a more generic way to write this loop or 4469 !-- delete trilinear interpolation 4336 !-- Decide whether the particle loop runs over the subboxes or only over 1, number_of_particles. 4337 !-- This depends on the selected interpolation method. 4338 !-- If particle interpolation method is not trilinear, then the sorting within subboxes is not 4339 !-- required. However, therefore the index start_index(nb) and end_index(nb) are not defined and 4340 !-- the loops are still over number_of_particles. @todo find a more generic way to write this 4341 !-- loop or delete trilinear interpolation 4470 4342 IF ( interpolation_trilinear ) THEN 4471 4343 subbox_start = 0 … … 4476 4348 ENDIF 4477 4349 ! 4478 !-- loop over subboxes. In case of simple interpolation scheme no subboxes 4479 !-- are introduced, as they are not required. Accordingly, this loops goes 4480 !-- from 1 to 1. 4350 !-- loop over subboxes. In case of simple interpolation scheme no subboxes are introduced, as 4351 !-- they are not required. Accordingly, this loop goes from 1 to 1. 4481 4352 DO nb = subbox_start, subbox_end 4482 4353 IF ( interpolation_trilinear ) THEN … … 4507 4378 ! 4508 4379 !-- Transport of particles with inertia 4509 particles(n)%x = particles(n)%x + particles(n)%speed_x * & 4510 dt_particle(n) 4511 particles(n)%y = particles(n)%y + particles(n)%speed_y * & 4512 dt_particle(n) 4513 particles(n)%z = particles(n)%z + particles(n)%speed_z * & 4514 dt_particle(n) 4380 particles(n)%x = particles(n)%x + particles(n)%speed_x * dt_particle(n) 4381 particles(n)%y = particles(n)%y + particles(n)%speed_y * dt_particle(n) 4382 particles(n)%z = particles(n)%z + particles(n)%speed_z * dt_particle(n) 4515 4383 4516 4384 ! … … 4532 4400 IF ( use_sgs_for_particles ) THEN 4533 4401 lagr_timescale(n) = km(kp,jp,ip) / MAX( e(kp,jp,ip), 1.0E-20_wp ) 4534 RL = EXP( -1.0_wp * dt_3d / MAX( lagr_timescale(n), & 4535 1.0E-20_wp ) ) 4536 sigma = SQRT( e(kp,jp,ip) ) 4402 rl = EXP( -1.0_wp * dt_3d / MAX( lagr_timescale(n), 1.0E-20_wp ) ) 4403 sigma = SQRT( e(kp,jp,ip) ) 4537 4404 ! 4538 4405 !-- Calculate random component of particle sgs velocity using parallel … … 4545 4412 rg3 = random_dummy 4546 4413 4547 particles(n)%rvar1 = RL * particles(n)%rvar1 +&4548 SQRT( 1.0_wp - RL**2 ) * sigma * rg14549 particles(n)%rvar2 = RL * particles(n)%rvar2 +&4550 SQRT( 1.0_wp - RL**2 ) * sigma * rg24551 particles(n)%rvar3 = RL * particles(n)%rvar3 +&4552 SQRT( 1.0_wp - RL**2 ) * sigma * rg34414 particles(n)%rvar1 = rl * particles(n)%rvar1 + & 4415 SQRT( 1.0_wp - rl**2 ) * sigma * rg1 4416 particles(n)%rvar2 = rl * particles(n)%rvar2 + & 4417 SQRT( 1.0_wp - rl**2 ) * sigma * rg2 4418 particles(n)%rvar3 = rl * particles(n)%rvar3 + & 4419 SQRT( 1.0_wp - rl**2 ) * sigma * rg3 4553 4420 4554 4421 particles(n)%speed_x = u_int(n) + particles(n)%rvar1 … … 4570 4437 exp_term = particle_groups(particles(n)%group)%exp_term 4571 4438 ENDIF 4572 particles(n)%speed_x = particles(n)%speed_x * exp_term + &4439 particles(n)%speed_x = particles(n)%speed_x * exp_term + & 4573 4440 u_int(n) * ( 1.0_wp - exp_term ) 4574 particles(n)%speed_y = particles(n)%speed_y * exp_term + &4441 particles(n)%speed_y = particles(n)%speed_y * exp_term + & 4575 4442 v_int(n) * ( 1.0_wp - exp_term ) 4576 particles(n)%speed_z = particles(n)%speed_z * exp_term + &4577 ( w_int(n) - ( 1.0_wp - dens_ratio(n) ) * &4443 particles(n)%speed_z = particles(n)%speed_z * exp_term + & 4444 ( w_int(n) - ( 1.0_wp - dens_ratio(n) ) * & 4578 4445 g / exp_arg ) * ( 1.0_wp - exp_term ) 4579 4446 ENDIF … … 4585 4452 ELSE 4586 4453 ! 4587 !-- Decide whether the particle loop runs over the subboxes or only over 1, 4588 !-- number_of_particles.This depends on the selected interpolation method.4454 !-- Decide whether the particle loop runs over the subboxes or only over 1, number_of_particles. 4455 !-- This depends on the selected interpolation method. 4589 4456 IF ( interpolation_trilinear ) THEN 4590 4457 subbox_start = 0 … … 4594 4461 subbox_end = 1 4595 4462 ENDIF 4596 !-- loop over subboxes. In case of simple interpolation scheme no subboxes 4597 !-- are introduced, as they are not required. Accordingly, this loops goes 4598 !-- from 1 to 1. 4463 !-- loop over subboxes. In case of simple interpolation scheme no subboxes are introduced, as 4464 !-- they are not required. Accordingly, this loop goes from 1 to 1. 4599 4465 DO nb = subbox_start, subbox_end 4600 4466 IF ( interpolation_trilinear ) THEN … … 4618 4484 IF ( cloud_droplets ) THEN 4619 4485 ! 4620 !-- Terminal velocity is computed for vertical direction (Rogers et al., 4621 !-- 1993,J. Appl. Meteorol.)4486 !-- Terminal velocity is computed for vertical direction (Rogers et al., 1993, 4487 !-- J. Appl. Meteorol.) 4622 4488 diameter = particles(n)%radius * 2000.0_wp !diameter in mm 4623 4489 IF ( diameter <= d0_rog ) THEN … … 4632 4498 IF ( use_sgs_for_particles ) THEN 4633 4499 lagr_timescale(n) = km(kp,jp,ip) / MAX( e(kp,jp,ip), 1.0E-20_wp ) 4634 RL = EXP( -1.0_wp * dt_3d / MAX( lagr_timescale(n), & 4635 1.0E-20_wp ) ) 4636 sigma = SQRT( e(kp,jp,ip) ) 4637 4638 ! 4639 !-- Calculate random component of particle sgs velocity using parallel 4640 !-- random generator 4500 rl = EXP( -1.0_wp * dt_3d / MAX( lagr_timescale(n), 1.0E-20_wp ) ) 4501 sigma = SQRT( e(kp,jp,ip) ) 4502 4503 ! 4504 !-- Calculate random component of particle sgs velocity using parallel random 4505 !-- generator 4641 4506 CALL random_number_parallel_gauss( random_dummy ) 4642 4507 rg1 = random_dummy … … 4646 4511 rg3 = random_dummy 4647 4512 4648 particles(n)%rvar1 = RL * particles(n)%rvar1 +&4649 SQRT( 1.0_wp - RL**2 ) * sigma * rg14650 particles(n)%rvar2 = RL * particles(n)%rvar2 +&4651 SQRT( 1.0_wp - RL**2 ) * sigma * rg24652 particles(n)%rvar3 = RL * particles(n)%rvar3 +&4653 SQRT( 1.0_wp - RL**2 ) * sigma * rg34513 particles(n)%rvar1 = rl * particles(n)%rvar1 + & 4514 SQRT( 1.0_wp - rl**2 ) * sigma * rg1 4515 particles(n)%rvar2 = rl * particles(n)%rvar2 + & 4516 SQRT( 1.0_wp - rl**2 ) * sigma * rg2 4517 particles(n)%rvar3 = rl * particles(n)%rvar3 + & 4518 SQRT( 1.0_wp - rl**2 ) * sigma * rg3 4654 4519 4655 4520 particles(n)%speed_x = u_int(n) + particles(n)%rvar1 … … 4671 4536 exp_term = particle_groups(particles(n)%group)%exp_term 4672 4537 ENDIF 4673 particles(n)%speed_x = particles(n)%speed_x * exp_term + &4538 particles(n)%speed_x = particles(n)%speed_x * exp_term + & 4674 4539 u_int(n) * ( 1.0_wp - exp_term ) 4675 particles(n)%speed_y = particles(n)%speed_y * exp_term + &4540 particles(n)%speed_y = particles(n)%speed_y * exp_term + & 4676 4541 v_int(n) * ( 1.0_wp - exp_term ) 4677 particles(n)%speed_z = particles(n)%speed_z * exp_term + &4678 ( w_int(n) - ( 1.0_wp - dens_ratio(n) ) * g / &4542 particles(n)%speed_z = particles(n)%speed_z * exp_term + & 4543 ( w_int(n) - ( 1.0_wp - dens_ratio(n) ) * g / & 4679 4544 exp_arg ) * ( 1.0_wp - exp_term ) 4680 4545 ENDIF … … 4685 4550 4686 4551 ! 4687 !-- Store the old age of the particle ( needed to prevent that a 4688 !-- particle crosses several PEs during one timestep, and for the 4689 !-- evaluation of the subgrid particle velocity fluctuations ) 4552 !-- Store the old age of the particle ( needed to prevent that a particle crosses several PEs during 4553 !-- one timestep, and for the evaluation of the subgrid particle velocity fluctuations ) 4690 4554 particles(1:number_of_particles)%age_m = particles(1:number_of_particles)%age 4691 4555 4692 4556 ! 4693 !-- loop over subboxes. In case of simple interpolation scheme no subboxes 4694 !-- are introduced, as they are not required. Accordingly, this loops goes 4695 !-- from 1 to 1. 4696 ! 4697 !-- Decide whether the particle loop runs over the subboxes or only over 1, 4698 !-- number_of_particles. This depends on the selected interpolation method. 4557 !-- loop over subboxes. In case of simple interpolation scheme no subboxes are introduced, as 4558 !-- they are not required. Accordingly, this loop goes from 1 to 1. 4559 ! 4560 !-- Decide whether the particle loop runs over the subboxes or only over 1, number_of_particles. 4561 !-- This depends on the selected interpolation method. 4699 4562 IF ( interpolation_trilinear ) THEN 4700 4563 subbox_start = 0 … … 4713 4576 ENDIF 4714 4577 ! 4715 !-- Loop from particle start to particle end and increment the particle 4716 !-- age and the total time that the particle has advanced within the 4717 !-- particle timestep procedure. 4578 !-- Loop from particle start to particle end and increment the particle age and the total time 4579 !-- that the particle has advanced within the particle timestep procedure. 4718 4580 DO n = particle_start, particle_end 4719 4581 particles(n)%age = particles(n)%age + dt_particle(n) … … 4722 4584 ! 4723 4585 !-- Particles that leave the child domain during the SGS-timestep loop 4724 !-- must not continue timestepping until they are transferred to the 4586 !-- must not continue timestepping until they are transferred to the 4725 4587 !-- parent. Hence, set their dt_sum to dt. 4726 4588 IF ( child_domain .AND. use_sgs_for_particles ) THEN 4727 4589 DO n = particle_start, particle_end 4728 IF ( particles(n)%x < 0.0_wp .OR. &4729 particles(n)%y < 0.0_wp .OR. &4730 particles(n)%x > ( nx+1 ) * dx .OR. &4590 IF ( particles(n)%x < 0.0_wp .OR. & 4591 particles(n)%y < 0.0_wp .OR. & 4592 particles(n)%x > ( nx+1 ) * dx .OR. & 4731 4593 particles(n)%y < ( ny+1 ) * dy ) THEN 4732 4594 particles(n)%dt_sum = dt_3d … … 4735 4597 ENDIF 4736 4598 ! 4737 !-- Check whether there is still a particle that has not yet completed 4738 !-- the total LES timestep 4599 !-- Check whether there is still a particle that has not yet completed the total LES timestep 4739 4600 DO n = particle_start, particle_end 4740 IF ( ( dt_3d - particles(n)%dt_sum ) > 1E-8_wp ) & 4741 dt_3d_reached_l = .FALSE. 4601 IF ( ( dt_3d - particles(n)%dt_sum ) > 1E-8_wp ) dt_3d_reached_l = .FALSE. 4742 4602 ENDDO 4743 4603 ENDDO … … 4748 4608 END SUBROUTINE lpm_advec 4749 4609 4750 4751 !------------------------------------------------------------------------------ !4610 4611 !--------------------------------------------------------------------------------------------------! 4752 4612 ! Description: 4753 4613 ! ------------ 4754 !> Calculation of subgrid-scale particle speed using the stochastic model 4614 !> Calculation of subgrid-scale particle speed using the stochastic model 4755 4615 !> of Weil et al. (2004, JAS, 61, 2877-2887). 4756 !------------------------------------------------------------------------------! 4757 SUBROUTINE weil_stochastic_eq( v_sgs, fs_n, e_n, dedxi_n, dedt_n, diss_n, & 4758 dt_n, rg_n, fac ) 4616 !--------------------------------------------------------------------------------------------------! 4617 SUBROUTINE weil_stochastic_eq( v_sgs, fs_n, e_n, dedxi_n, dedt_n, diss_n, dt_n, rg_n, fac ) 4759 4618 4760 4619 REAL(wp) :: a1 !< dummy argument 4761 REAL(wp) :: dedt_n !< time derivative of TKE at particle position 4620 REAL(wp) :: dedt_n !< time derivative of TKE at particle position 4762 4621 REAL(wp) :: dedxi_n !< horizontal derivative of TKE at particle position 4763 REAL(wp) :: diss_n !< dissipation at particle position 4622 REAL(wp) :: diss_n !< dissipation at particle position 4764 4623 REAL(wp) :: dt_n !< particle timestep 4765 4624 REAL(wp) :: e_n !< TKE at particle position … … 4770 4629 REAL(wp) :: term2 !< drift correction term 4771 4630 REAL(wp) :: term3 !< random term 4772 REAL(wp) :: v_sgs !< subgrid-scale velocity component 4773 4774 !-- At first, limit TKE to a small non-zero number, in order to prevent 4775 !-- the occurrence of extremely large SGS-velocities in case TKE is zero, 4776 !-- (could occur at the simulation begin). 4631 REAL(wp) :: v_sgs !< subgrid-scale velocity component 4632 4633 !-- At first, limit TKE to a small non-zero number, in order to prevent the occurrence of extremely 4634 !-- large SGS-velocities in case TKE is zero, (could occur at the simulation begin). 4777 4635 e_n = MAX( e_n, 1E-20_wp ) 4778 4636 ! 4779 !-- Please note, terms 1 and 2 (drift and memory term, respectively) are 4780 !-- multiplied by a flag to switch of both terms near topography. 4781 !-- This is necessary, as both terms may cause a subgrid-scale velocity build up 4782 !-- if particles are trapped in regions with very small TKE, e.g. in narrow street 4783 !-- canyons resolved by only a few grid points. Hence, term 1 and term 2 are 4784 !-- disabled if one of the adjacent grid points belongs to topography. 4785 !-- Moreover, in this case, the previous subgrid-scale component is also set 4786 !-- to zero. 4637 !-- Please note, terms 1 and 2 (drift and memory term, respectively) are multiplied by a flag to 4638 !-- switch of both terms near topography. 4639 !-- This is necessary, as both terms may cause a subgrid-scale velocity build up if particles are 4640 !-- trapped in regions with very small TKE, e.g. in narrow street canyons resolved by only a few 4641 !-- grid points. Hence, term 1 and term 2 are disabled if one of the adjacent grid points belongs to 4642 !-- topography. 4643 !-- Moreover, in this case, the previous subgrid-scale component is also set to zero. 4787 4644 4788 4645 a1 = fs_n * c_0 * diss_n 4789 4646 ! 4790 4647 !-- Memory term 4791 term1 = - a1 * v_sgs * dt_n / ( 4.0_wp * sgs_wf_part * e_n + 1E-20_wp ) & 4792 * fac 4648 term1 = - a1 * v_sgs * dt_n / ( 4.0_wp * sgs_wf_part * e_n + 1E-20_wp ) * fac 4793 4649 ! 4794 4650 !-- Drift correction term 4795 term2 = ( ( dedt_n * v_sgs / e_n ) + dedxi_n ) * 0.5_wp * dt_n & 4796 * fac 4651 term2 = ( ( dedt_n * v_sgs / e_n ) + dedxi_n ) * 0.5_wp * dt_n * fac 4797 4652 ! 4798 4653 !-- Random term 4799 4654 term3 = SQRT( MAX( a1, 1E-20_wp ) ) * ( rg_n - 1.0_wp ) * SQRT( dt_n ) 4800 4655 ! 4801 !-- In cese one of the adjacent grid-boxes belongs to topograhy, the previous 4802 !-- subgrid-scale velocity component is set to zero, in order to prevent a 4803 !-- velocity build-up. 4804 !-- This case, set also previous subgrid-scale component to zero. 4656 !-- In case one of the adjacent grid-boxes belongs to topograhy, the previous subgrid-scale velocity 4657 !-- component is set to zero, in order to prevent a velocity build-up. 4658 !-- This case, set also previous subgrid-scale component to zero. 4805 4659 v_sgs = v_sgs * fac + term1 + term2 + term3 4806 4660 … … 4808 4662 4809 4663 4810 !------------------------------------------------------------------------------ !4664 !--------------------------------------------------------------------------------------------------! 4811 4665 ! Description: 4812 4666 ! ------------ 4813 4667 !> swap timelevel in case of particle advection interpolation 'simple-corrector' 4814 !> This routine is called at the end of one timestep, the velocities are then 4815 !> used for the nexttimestep4816 !------------------------------------------------------------------------------ !4668 !> This routine is called at the end of one timestep, the velocities are then used for the next 4669 !> timestep 4670 !--------------------------------------------------------------------------------------------------! 4817 4671 SUBROUTINE lpm_swap_timelevel_for_particle_advection 4818 4672 4819 4673 ! 4820 !-- save the divergence free velocites of t+1 to use them at the end of the 4821 !-- next time step 4674 !-- Save the divergence free velocites of t+1 to use them at the end of the next time step 4822 4675 u_t = u 4823 4676 v_t = v … … 4827 4680 4828 4681 4829 !------------------------------------------------------------------------------ !4682 !--------------------------------------------------------------------------------------------------! 4830 4683 ! Description: 4831 4684 ! ------------ 4832 4685 !> Boundary conditions for the Lagrangian particles. 4833 !> The routine consists of two different parts. One handles the bottom (flat) 4834 !> and top boundary. In this part, also particles which exceeded their lifetime 4835 !> are deleted. 4686 !> The routine consists of two different parts. One handles the bottom (flat) and top boundary. In 4687 !> this part, also particles which exceeded their lifetime are deleted. 4836 4688 !> The other part handles the reflection of particles from vertical walls. 4837 4689 !> This part was developed by Jin Zhang during 2006-2007. 4838 4690 !> 4839 !> To do: Code structure for finding the t_index values and for checking the 4840 !> ----- reflection conditions is basically the same for all four cases, so it4841 !> s hould be possible to further simplify/shorten it.4691 !> To do: Code structure for finding the t_index values and for checking the reflection conditions 4692 !> ------ is basically the same for all four cases, so it should be possible to further 4693 !> simplify/shorten it. 4842 4694 !> 4843 4695 !> THE WALLS PART OF THIS ROUTINE HAS NOT BEEN TESTED FOR OCEAN RUNS SO FAR!!!! 4844 4696 !> (see offset_ocean_*) 4845 !------------------------------------------------------------------------------ !4697 !--------------------------------------------------------------------------------------------------! 4846 4698 SUBROUTINE lpm_boundary_conds( location_bc , i, j, k ) 4847 4699 4848 4700 CHARACTER (LEN=*), INTENT(IN) :: location_bc !< general mode: boundary conditions at bottom/top of the model domain 4849 !< or at vertical surfaces (buildings, terrain steps) 4701 !< or at vertical surfaces (buildings, terrain steps) 4850 4702 INTEGER(iwp), INTENT(IN) :: i !< grid index of particle box along x 4851 4703 INTEGER(iwp), INTENT(IN) :: j !< grid index of particle box along y … … 4919 4771 4920 4772 ! 4921 !-- Apply boundary conditions to those particles that have crossed the top or 4922 !-- bottom boundary anddelete those particles, which are older than allowed4773 !-- Apply boundary conditions to those particles that have crossed the top or bottom boundary and 4774 !-- delete those particles, which are older than allowed 4923 4775 DO n = 1, number_of_particles 4924 4776 4925 4777 ! 4926 !-- Stop if particles have moved further than the length of one 4927 !-- PE subdomain (newly releasedparticles have age = age_m!)4778 !-- Stop if particles have moved further than the length of one PE subdomain (newly released 4779 !-- particles have age = age_m!) 4928 4780 IF ( particles(n)%age /= particles(n)%age_m ) THEN 4929 IF ( ABS(particles(n)%speed_x) > &4930 ((nxr-nxl+2)*dx)/(particles(n)%age-particles(n)%age_m) .OR. &4931 ABS(particles(n)%speed_y) > &4781 IF ( ABS(particles(n)%speed_x) > & 4782 ((nxr-nxl+2)*dx)/(particles(n)%age-particles(n)%age_m) .OR. & 4783 ABS(particles(n)%speed_y) > & 4932 4784 ((nyn-nys+2)*dy)/(particles(n)%age-particles(n)%age_m) ) THEN 4933 4785 4934 WRITE( message_string, * ) 'particle too fast. n = ', n 4786 WRITE( message_string, * ) 'particle too fast. n = ', n 4935 4787 CALL message( 'lpm_boundary_conds', 'PA0148', 2, 2, -1, 6, 1 ) 4936 4788 ENDIF 4937 4789 ENDIF 4938 4790 4939 IF ( particles(n)%age > particle_maximum_age .AND. & 4940 particles(n)%particle_mask ) & 4941 THEN 4791 IF ( particles(n)%age > particle_maximum_age .AND. particles(n)%particle_mask ) THEN 4942 4792 particles(n)%particle_mask = .FALSE. 4943 4793 deleted_particles = deleted_particles + 1 … … 5026 4876 k1 = k 5027 4877 ! 5028 !-- Determine horizontal as well as vertical walls at which particle can 5029 !-- be potentially reflected.4878 !-- Determine horizontal as well as vertical walls at which particle can be potentially 4879 !-- reflected. 5030 4880 !-- Start with walls aligned in yz layer. 5031 !-- Wall to the right 4881 !-- Wall to the right 5032 4882 IF ( prt_x > pos_x_old ) THEN 5033 4883 xwall = ( i1 + 1 ) * dx … … 5074 4924 z_wall_reached = .FALSE. 5075 4925 ! 5076 !-- Initialize time array 4926 !-- Initialize time array 5077 4927 t = 0.0_wp 5078 4928 ! 5079 !-- Check if particle can reach any wall. This case, calculate the 5080 !-- fractional time needed to reach this wall. Store this fractional 5081 !-- timestep in array t. Moreover, store indices for these grid 5082 !-- boxes where the respective wall belongs to. 4929 !-- Check if particle can reach any wall. This case, calculate the fractional time needed to 4930 !-- reach this wall. Store this fractional timestep in array t. Moreover, store indices for 4931 !-- these grid boxes where the respective wall belongs to. 5083 4932 !-- Start with x-direction. 5084 4933 t_index = 1 5085 t(t_index) = ( xwall - pos_x_old ) &5086 / MERGE( MAX( prt_x - pos_x_old, 1E-30_wp ),&5087 MIN( prt_x - pos_x_old, -1E-30_wp ),&5088 prt_x > pos_x_old )4934 t(t_index) = ( xwall - pos_x_old ) & 4935 / MERGE( MAX( prt_x - pos_x_old, 1E-30_wp ), & 4936 MIN( prt_x - pos_x_old, -1E-30_wp ), & 4937 prt_x > pos_x_old ) 5089 4938 x_ind(t_index) = i2 5090 4939 y_ind(t_index) = j1 … … 5094 4943 reach_z(t_index) = .FALSE. 5095 4944 ! 5096 !-- Store these values only if particle really reaches any wall. t must 5097 !-- be in a interval between [0:1].4945 !-- Store these values only if particle really reaches any wall. t must be in an interval 4946 !-- between [0:1]. 5098 4947 IF ( t(t_index) <= 1.0_wp .AND. t(t_index) >= 0.0_wp ) THEN 5099 4948 t_index = t_index + 1 … … 5102 4951 ! 5103 4952 !-- y-direction 5104 t(t_index) = ( ywall - pos_y_old ) &5105 / MERGE( MAX( prt_y - pos_y_old, 1E-30_wp ),&5106 MIN( prt_y - pos_y_old, -1E-30_wp ),&5107 prt_y > pos_y_old )4953 t(t_index) = ( ywall - pos_y_old ) & 4954 / MERGE( MAX( prt_y - pos_y_old, 1E-30_wp ), & 4955 MIN( prt_y - pos_y_old, -1E-30_wp ), & 4956 prt_y > pos_y_old ) 5108 4957 x_ind(t_index) = i1 5109 4958 y_ind(t_index) = j2 … … 5118 4967 ! 5119 4968 !-- z-direction 5120 t(t_index) = (zwall - pos_z_old ) &5121 / MERGE( MAX( prt_z - pos_z_old, 1E-30_wp ),&5122 MIN( prt_z - pos_z_old, -1E-30_wp ),&5123 prt_z > pos_z_old )4969 t(t_index) = (zwall - pos_z_old ) & 4970 / MERGE( MAX( prt_z - pos_z_old, 1E-30_wp ), & 4971 MIN( prt_z - pos_z_old, -1E-30_wp ), & 4972 prt_z > pos_z_old ) 5124 4973 5125 4974 x_ind(t_index) = i1 … … 5139 4988 IF ( cross_wall_x .OR. cross_wall_y .OR. cross_wall_z ) THEN 5140 4989 ! 5141 !-- Sort fractional timesteps in ascending order. Also sort the 5142 !-- corresponding indices and flag according to the time interval a 5143 !-- particle reaches the respective wall. 4990 !-- Sort fractional timesteps in ascending order. Also sort the corresponding indices and 4991 !-- flag according to the time interval a particle reaches the respective wall. 5144 4992 inc = 1 5145 4993 jr = 1 … … 5187 5035 !-- Loop over all times a particle possibly moves into a new grid box 5188 5036 t_old = 0.0_wp 5189 DO t_index = 1, t_index_number 5190 ! 5191 !-- Calculate intermediate particle position according to the 5192 !-- timesteps a particle reaches any wall. 5193 pos_x = pos_x + ( t(t_index) - t_old ) * dt_particle & 5194 * particles(n)%speed_x 5195 pos_y = pos_y + ( t(t_index) - t_old ) * dt_particle & 5196 * particles(n)%speed_y 5197 pos_z = pos_z + ( t(t_index) - t_old ) * dt_particle & 5198 * particles(n)%speed_z 5199 ! 5200 !-- Obtain x/y grid indices for intermediate particle position from 5201 !-- sorted index array 5037 DO t_index = 1, t_index_number 5038 ! 5039 !-- Calculate intermediate particle position according to the timesteps a particle 5040 !-- reaches any wall. 5041 pos_x = pos_x + ( t(t_index) - t_old ) * dt_particle * particles(n)%speed_x 5042 pos_y = pos_y + ( t(t_index) - t_old ) * dt_particle * particles(n)%speed_y 5043 pos_z = pos_z + ( t(t_index) - t_old ) * dt_particle * particles(n)%speed_z 5044 ! 5045 !-- Obtain x/y grid indices for intermediate particle position from sorted index array 5202 5046 i3 = x_ind(t_index) 5203 5047 j3 = y_ind(t_index) … … 5205 5049 ! 5206 5050 !-- Check which wall is already reached 5207 IF ( .NOT. x_wall_reached ) x_wall_reached = reach_x(t_index) 5051 IF ( .NOT. x_wall_reached ) x_wall_reached = reach_x(t_index) 5208 5052 IF ( .NOT. y_wall_reached ) y_wall_reached = reach_y(t_index) 5209 5053 IF ( .NOT. z_wall_reached ) z_wall_reached = reach_z(t_index) 5210 5054 ! 5211 !-- Check if a particle needs to be reflected at any yz-wall. If 5212 !-- necessary, carry out reflection. Please note, a security 5213 !-- constant is required, as the particle position does not 5214 !-- necessarily exactly match the wall location due to rounding 5215 !-- errors. 5216 IF ( reach_x(t_index) .AND. & 5217 ABS( pos_x - xwall ) < eps .AND. & 5218 .NOT. BTEST(wall_flags_total_0(k3,j3,i3),0) .AND. & 5055 !-- Check if a particle needs to be reflected at any yz-wall. If necessary, carry out 5056 !-- reflection. Please note, a security constant is required, as the particle position 5057 !-- does not necessarily exactly match the wall location due to rounding errors. 5058 IF ( reach_x(t_index) .AND. & 5059 ABS( pos_x - xwall ) < eps .AND. & 5060 .NOT. BTEST(wall_flags_total_0(k3,j3,i3),0) .AND. & 5219 5061 .NOT. reflect_x ) THEN 5220 ! 5221 ! 5222 !-- Reflection in x-direction. 5223 !-- Ensure correct reflection by MIN/MAX functions, depending on 5224 !-- direction of particle transport.5225 !-- Due to rounding errors pos_x does not exactly match the wall 5226 !-- location, leading to erroneous reflection.5227 pos_x = MERGE( MIN( 2.0_wp * xwall - pos_x, xwall ), &5228 MAX( 2.0_wp * xwall - pos_x, xwall ), &5062 ! 5063 ! 5064 !-- Reflection in x-direction. 5065 !-- Ensure correct reflection by MIN/MAX functions, depending on direction of 5066 !-- particle transport. 5067 !-- Due to rounding errors pos_x does not exactly match the wall location, leading to 5068 !-- erroneous reflection. 5069 pos_x = MERGE( MIN( 2.0_wp * xwall - pos_x, xwall ), & 5070 MAX( 2.0_wp * xwall - pos_x, xwall ), & 5229 5071 particles(n)%x > xwall ) 5230 5072 ! 5231 !-- Change sign of particle speed 5073 !-- Change sign of particle speed 5232 5074 particles(n)%speed_x = - particles(n)%speed_x 5233 5075 ! … … 5238 5080 reflect_x = .TRUE. 5239 5081 ! 5240 !-- As the particle does not cross any further yz-wall during 5241 !-- this timestep, setfurther x-indices to the current one.5082 !-- As the particle does not cross any further yz-wall during this timestep, set 5083 !-- further x-indices to the current one. 5242 5084 x_ind(t_index:t_index_number) = i1 5243 5085 ! 5244 !-- If particle already reached the wall but was not reflected, 5245 !-- set further x-indices tothe new one.5246 ELSEIF ( x_wall_reached .AND..NOT. reflect_x ) THEN5086 !-- If particle already reached the wall but was not reflected, set further x-indices to 5087 !-- the new one. 5088 ELSEIF ( x_wall_reached .AND. .NOT. reflect_x ) THEN 5247 5089 x_ind(t_index:t_index_number) = i2 5248 ENDIF !particle reflection in x direction done 5249 5250 ! 5251 !-- Check if a particle needs to be reflected at any xz-wall. If 5252 !-- necessary, carry out reflection. Please note, a security 5253 !-- constant is required, as the particle position does not 5254 !-- necessarily exactly match the wall location due to rounding 5255 !-- errors. 5256 IF ( reach_y(t_index) .AND. & 5257 ABS( pos_y - ywall ) < eps .AND. & 5258 .NOT. BTEST(wall_flags_total_0(k3,j3,i3),0) .AND. & 5090 ENDIF !particle reflection in x direction done 5091 5092 ! 5093 !-- Check if a particle needs to be reflected at any xz-wall. If necessary, carry out 5094 !-- reflection. Please note, a security constant is required, as the particle position 5095 !-- does not necessarily exactly match the wall location due to rounding errors. 5096 IF ( reach_y(t_index) .AND. & 5097 ABS( pos_y - ywall ) < eps .AND. & 5098 .NOT. BTEST(wall_flags_total_0(k3,j3,i3),0) .AND. & 5259 5099 .NOT. reflect_y ) THEN 5260 ! 5261 ! 5262 !-- Reflection in y-direction. 5263 !-- Ensure correct reflection by MIN/MAX functions, depending on 5264 !-- direction of particle transport.5265 !-- Due to rounding errors pos_y does not exactly match the wall 5266 !-- location, leading to erroneous reflection.5267 pos_y = MERGE( MIN( 2.0_wp * ywall - pos_y, ywall ), &5268 MAX( 2.0_wp * ywall - pos_y, ywall ), &5100 ! 5101 ! 5102 !-- Reflection in y-direction. 5103 !-- Ensure correct reflection by MIN/MAX functions, depending on direction of 5104 !-- particle transport. 5105 !-- Due to rounding errors pos_y does not exactly match the wall location, leading to 5106 !-- erroneous reflection. 5107 pos_y = MERGE( MIN( 2.0_wp * ywall - pos_y, ywall ), & 5108 MAX( 2.0_wp * ywall - pos_y, ywall ), & 5269 5109 particles(n)%y > ywall ) 5270 5110 ! 5271 !-- Change sign of particle speed 5111 !-- Change sign of particle speed 5272 5112 particles(n)%speed_y = - particles(n)%speed_y 5273 5113 ! … … 5278 5118 reflect_y = .TRUE. 5279 5119 ! 5280 !-- As the particle does not cross any further xz-wall during 5281 !-- this timestep, setfurther y-indices to the current one.5120 !-- As the particle does not cross any further xz-wall during this timestep, set 5121 !-- further y-indices to the current one. 5282 5122 y_ind(t_index:t_index_number) = j1 5283 5123 ! 5284 !-- If particle already reached the wall but was not reflected, 5285 !-- set further y-indices tothe new one.5286 ELSEIF ( y_wall_reached .AND..NOT. reflect_y ) THEN5124 !-- If particle already reached the wall but was not reflected, set further y-indices to 5125 !-- the new one. 5126 ELSEIF ( y_wall_reached .AND. .NOT. reflect_y ) THEN 5287 5127 y_ind(t_index:t_index_number) = j2 5288 ENDIF !particle reflection in y direction done 5289 5290 ! 5291 !-- Check if a particle needs to be reflected at any xy-wall. If 5292 !-- necessary, carry out reflection. Please note, a security 5293 !-- constant is required, as the particle position does not 5294 !-- necessarily exactly match the wall location due to rounding 5295 !-- errors. 5296 IF ( reach_z(t_index) .AND. & 5297 ABS( pos_z - zwall ) < eps .AND. & 5298 .NOT. BTEST(wall_flags_total_0(k3,j3,i3),0) .AND. & 5128 ENDIF !particle reflection in y direction done 5129 5130 ! 5131 !-- Check if a particle needs to be reflected at any xy-wall. If necessary, carry out 5132 !-- reflection. Please note, a security constant is required, as the particle position 5133 !-- does not necessarily exactly match the wall location due to rounding errors. 5134 IF ( reach_z(t_index) .AND. & 5135 ABS( pos_z - zwall ) < eps .AND. & 5136 .NOT. BTEST(wall_flags_total_0(k3,j3,i3),0) .AND. & 5299 5137 .NOT. reflect_z ) THEN 5300 ! 5301 ! 5302 !-- Reflection in z-direction. 5303 !-- Ensure correct reflection by MIN/MAX functions, depending on 5304 !-- direction of particle transport.5305 !-- Due to rounding errors pos_z does not exactly match the wall 5306 !-- location, leading to erroneous reflection.5307 pos_z = MERGE( MIN( 2.0_wp * zwall - pos_z, zwall ), &5308 MAX( 2.0_wp * zwall - pos_z, zwall ), &5138 ! 5139 ! 5140 !-- Reflection in z-direction. 5141 !-- Ensure correct reflection by MIN/MAX functions, depending on direction of 5142 !-- particle transport. 5143 !-- Due to rounding errors pos_z does not exactly match the wall location, leading to 5144 !-- erroneous reflection. 5145 pos_z = MERGE( MIN( 2.0_wp * zwall - pos_z, zwall ), & 5146 MAX( 2.0_wp * zwall - pos_z, zwall ), & 5309 5147 particles(n)%z > zwall ) 5310 5148 ! 5311 !-- Change sign of particle speed 5149 !-- Change sign of particle speed 5312 5150 particles(n)%speed_z = - particles(n)%speed_z 5313 5151 ! … … 5318 5156 reflect_z = .TRUE. 5319 5157 ! 5320 !-- As the particle does not cross any further xy-wall during 5321 !-- this timestep, setfurther z-indices to the current one.5158 !-- As the particle does not cross any further xy-wall during this timestep, set 5159 !-- further z-indices to the current one. 5322 5160 z_ind(t_index:t_index_number) = k1 5323 5161 ! 5324 !-- If particle already reached the wall but was not reflected, 5325 !-- set further z-indices tothe new one.5326 ELSEIF ( z_wall_reached .AND..NOT. reflect_z ) THEN5162 !-- If particle already reached the wall but was not reflected, set further z-indices to 5163 !-- the new one. 5164 ELSEIF ( z_wall_reached .AND. .NOT. reflect_z ) THEN 5327 5165 z_ind(t_index:t_index_number) = k2 5328 ENDIF !particle reflection in z direction done5166 ENDIF !particle reflection in z direction done 5329 5167 5330 5168 ! … … 5334 5172 ENDDO 5335 5173 ! 5336 !-- If a particle was reflected, calculate final position from last 5337 !-- intermediate position. 5174 !-- If a particle was reflected, calculate final position from last intermediate position. 5338 5175 IF ( reflect_x .OR. reflect_y .OR. reflect_z ) THEN 5339 5176 5340 particles(n)%x = pos_x + ( 1.0_wp - t_old ) * dt_particle & 5341 * particles(n)%speed_x 5342 particles(n)%y = pos_y + ( 1.0_wp - t_old ) * dt_particle & 5343 * particles(n)%speed_y 5344 particles(n)%z = pos_z + ( 1.0_wp - t_old ) * dt_particle & 5345 * particles(n)%speed_z 5177 particles(n)%x = pos_x + ( 1.0_wp - t_old ) * dt_particle * particles(n)%speed_x 5178 particles(n)%y = pos_y + ( 1.0_wp - t_old ) * dt_particle * particles(n)%speed_y 5179 particles(n)%z = pos_z + ( 1.0_wp - t_old ) * dt_particle * particles(n)%speed_z 5346 5180 5347 5181 ENDIF … … 5358 5192 END SELECT 5359 5193 5360 END SUBROUTINE lpm_boundary_conds 5361 5362 5363 !------------------------------------------------------------------------------ !5194 END SUBROUTINE lpm_boundary_conds 5195 5196 5197 !--------------------------------------------------------------------------------------------------! 5364 5198 ! Description: 5365 5199 ! ------------ 5366 !> Calculates change in droplet radius by condensation/evaporation, using 5367 !> either an analytic formula or by numerically integrating the radius growth 5368 !> equation including curvature and solution effects using Rosenbrocks method 5369 !> (see Numerical recipes in FORTRAN, 2nd edition, p. 731). 5200 !> Calculates change in droplet radius by condensation/evaporation, using either an analytic formula 5201 !> or by numerically integrating the radius growth equation including curvature and solution effects 5202 !> using Rosenbrocks method (see Numerical recipes in FORTRAN, 2nd edition, p. 731). 5370 5203 !> The analytical formula and growth equation follow those given in 5371 5204 !> Rogers and Yau (A short course in cloud physics, 3rd edition, p. 102/103). 5372 !------------------------------------------------------------------------------ !5205 !--------------------------------------------------------------------------------------------------! 5373 5206 SUBROUTINE lpm_droplet_condensation (i,j,k) 5207 5208 ! 5209 !-- Parameters for Rosenbrock method (see Verwer et al., 1999) 5210 REAL(wp), PARAMETER :: prec = 1.0E-3_wp !< precision of Rosenbrock solution 5211 REAL(wp), PARAMETER :: q_increase = 1.5_wp !< increase factor in timestep 5212 REAL(wp), PARAMETER :: q_decrease = 0.9_wp !< decrease factor in timestep 5213 REAL(wp), PARAMETER :: gamma = 0.292893218814_wp !< = 1.0 - 1.0 / SQRT(2.0) 5214 ! 5215 !-- Parameters for terminal velocity 5216 REAL(wp), PARAMETER :: a_rog = 9.65_wp !< parameter for fall velocity 5217 REAL(wp), PARAMETER :: b_rog = 10.43_wp !< parameter for fall velocity 5218 REAL(wp), PARAMETER :: c_rog = 0.6_wp !< parameter for fall velocity 5219 REAL(wp), PARAMETER :: k_cap_rog = 4.0_wp !< parameter for fall velocity 5220 REAL(wp), PARAMETER :: k_low_rog = 12.0_wp !< parameter for fall velocity 5221 REAL(wp), PARAMETER :: d0_rog = 0.745_wp !< separation diameter 5374 5222 5375 5223 INTEGER(iwp), INTENT(IN) :: i !< 5376 5224 INTEGER(iwp), INTENT(IN) :: j !< 5377 5225 INTEGER(iwp), INTENT(IN) :: k !< 5378 INTEGER(iwp) :: n!<5226 INTEGER(iwp) :: n !< 5379 5227 5380 5228 REAL(wp) :: afactor !< curvature effects … … 5398 5246 REAL(wp) :: r_ros_ini !< initial Rosenbrock radius 5399 5247 REAL(wp) :: r0 !< gas-kinetic lengthscale 5248 REAL(wp) :: re_p !< particle Reynolds number 5400 5249 REAL(wp) :: sigma !< surface tension of water 5401 5250 REAL(wp) :: thermal_conductivity !< thermal conductivity for water 5402 5251 REAL(wp) :: t_int !< temperature 5403 5252 REAL(wp) :: w_s !< terminal velocity of droplets 5404 REAL(wp) :: re_p !< particle Reynolds number 5405 ! 5406 !-- Parameters for Rosenbrock method (see Verwer et al., 1999) 5407 REAL(wp), PARAMETER :: prec = 1.0E-3_wp !< precision of Rosenbrock solution 5408 REAL(wp), PARAMETER :: q_increase = 1.5_wp !< increase factor in timestep 5409 REAL(wp), PARAMETER :: q_decrease = 0.9_wp !< decrease factor in timestep 5410 REAL(wp), PARAMETER :: gamma = 0.292893218814_wp !< = 1.0 - 1.0 / SQRT(2.0) 5411 ! 5412 !-- Parameters for terminal velocity 5413 REAL(wp), PARAMETER :: a_rog = 9.65_wp !< parameter for fall velocity 5414 REAL(wp), PARAMETER :: b_rog = 10.43_wp !< parameter for fall velocity 5415 REAL(wp), PARAMETER :: c_rog = 0.6_wp !< parameter for fall velocity 5416 REAL(wp), PARAMETER :: k_cap_rog = 4.0_wp !< parameter for fall velocity 5417 REAL(wp), PARAMETER :: k_low_rog = 12.0_wp !< parameter for fall velocity 5418 REAL(wp), PARAMETER :: d0_rog = 0.745_wp !< separation diameter 5419 5253 5254 REAL(wp), DIMENSION(number_of_particles) :: new_r !< 5420 5255 REAL(wp), DIMENSION(number_of_particles) :: ventilation_effect !< 5421 REAL(wp), DIMENSION(number_of_particles) :: new_r !<5422 5256 5423 5257 CALL cpu_log( log_point_s(42), 'lpm_droplet_condens', 'start' ) … … 5437 5271 ! 5438 5272 !-- Moldecular diffusivity of water vapor in air (Hall und Pruppacher, 1976) 5439 diff_coeff = 0.211E-4_wp * ( t_int / 273.15_wp )**1.94_wp * & 5440 ( 101325.0_wp / hyp(k) ) 5273 diff_coeff = 0.211E-4_wp * ( t_int / 273.15_wp )**1.94_wp * ( 101325.0_wp / hyp(k) ) 5441 5274 ! 5442 5275 !-- Lengthscale for gas-kinetic effects (from Mordy, 1959, p. 23): … … 5445 5278 !-- Calculate effects of heat conductivity and diffusion of water vapor on the 5446 5279 !-- diffusional growth process (usually known as 1.0 / (F_k + F_d) ) 5447 ddenom = 1.0_wp / ( rho_l * r_v * t_int / ( e_s * diff_coeff ) + &5448 ( l_v / ( r_v * t_int ) - 1.0_wp ) * rho_l * &5449 l_v / ( thermal_conductivity * t_int ) &5280 ddenom = 1.0_wp / ( rho_l * r_v * t_int / ( e_s * diff_coeff ) + & 5281 ( l_v / ( r_v * t_int ) - 1.0_wp ) * rho_l * & 5282 l_v / ( thermal_conductivity * t_int ) & 5450 5283 ) 5451 5284 new_r = 0.0_wp … … 5458 5291 !-- Terminal velocity is computed for vertical direction (Rogers et al., 5459 5292 !-- 1993, J. Appl. Meteorol.) 5460 diameter = particles(n)%radius * 2000.0_wp !diameter in mm5293 diameter = particles(n)%radius * 2000.0_wp !diameter in mm 5461 5294 IF ( diameter <= d0_rog ) THEN 5462 5295 w_s = k_cap_rog * diameter * ( 1.0_wp - EXP( -k_low_rog * diameter ) ) … … 5476 5309 ELSE 5477 5310 ! 5478 !-- For small droplets or in supersaturated environments, the ventilation 5479 !-- effect does not play a role5311 !-- For small droplets or in supersaturated environments, the ventilation effect does not play 5312 !-- a role. 5480 5313 ventilation_effect(n) = 1.0_wp 5481 5314 ENDIF … … 5484 5317 IF( .NOT. curvature_solution_effects ) THEN 5485 5318 ! 5486 !-- Use analytic model for diffusional growth including gas-kinetic 5487 !-- effects (Mordy, 1959) butwithout the impact of aerosols.5319 !-- Use analytic model for diffusional growth including gas-kinetic effects (Mordy, 1959) but 5320 !-- without the impact of aerosols. 5488 5321 DO n = 1, number_of_particles 5489 arg = ( particles(n)%radius + r0 )**2 + 2.0_wp * dt_3d * ddenom * &5490 ventilation_effect(n) *&5322 arg = ( particles(n)%radius + r0 )**2 + 2.0_wp * dt_3d * ddenom * & 5323 ventilation_effect(n) * & 5491 5324 ( e_a / e_s - 1.0_wp ) 5492 5325 arg = MAX( arg, ( 0.01E-6 + r0 )**2 ) … … 5508 5341 ! 5509 5342 !-- Solute effect (bfactor) 5510 bfactor = vanthoff * rho_s * particles(n)%aux1**3 * &5343 bfactor = vanthoff * rho_s * particles(n)%aux1**3 * & 5511 5344 molecular_weight_of_water / ( rho_l * molecular_weight_of_solute ) 5512 5345 … … 5518 5351 ! 5519 5352 !-- Integrate growth equation using a 2nd-order Rosenbrock method 5520 !-- (see Verwer et al., 1999, Eq. (3.2)). The Rosenbrock method adjusts 5521 !-- its with internaltimestep to minimize the local truncation error.5353 !-- (see Verwer et al., 1999, Eq. (3.2)). The Rosenbrock method adjusts its with internal 5354 !-- timestep to minimize the local truncation error. 5522 5355 DO WHILE ( dt_ros_sum < dt_3d ) 5523 5356 … … 5526 5359 DO 5527 5360 5528 drdt = ddenom * ventilation_effect(n) * ( e_a / e_s - 1.0_wp - &5529 afactor / r_ros + &5530 bfactor / r_ros**3 &5361 drdt = ddenom * ventilation_effect(n) * ( e_a / e_s - 1.0_wp - & 5362 afactor / r_ros + & 5363 bfactor / r_ros**3 & 5531 5364 ) / ( r_ros + r0 ) 5532 5365 5533 d2rdtdr = -ddenom * ventilation_effect(n) * (&5534 ( e_a / e_s - 1.0_wp ) * r_ros**4 -&5535 afactor * r0 * r_ros**2 - &5536 2.0_wp * afactor * r_ros**3 + &5537 3.0_wp * bfactor * r0 + &5538 4.0_wp * bfactor * r_ros &5539 )&5366 d2rdtdr = -ddenom * ventilation_effect(n) * ( & 5367 ( e_a / e_s - 1.0_wp ) * r_ros**4 - & 5368 afactor * r0 * r_ros**2 - & 5369 2.0_wp * afactor * r_ros**3 + & 5370 3.0_wp * bfactor * r0 + & 5371 4.0_wp * bfactor * r_ros & 5372 ) & 5540 5373 / ( r_ros**4 * ( r_ros + r0 )**2 ) 5541 5374 … … 5545 5378 r_err = r_ros 5546 5379 5547 drdt = ddenom * ventilation_effect(n) * ( e_a / e_s - 1.0_wp - &5548 afactor / r_ros + &5549 bfactor / r_ros**3 &5380 drdt = ddenom * ventilation_effect(n) * ( e_a / e_s - 1.0_wp - & 5381 afactor / r_ros + & 5382 bfactor / r_ros**3 & 5550 5383 ) / ( r_ros + r0 ) 5551 5384 5552 k2 = ( drdt - dt_ros * 2.0 * gamma * d2rdtdr * k1 ) / &5385 k2 = ( drdt - dt_ros * 2.0 * gamma * d2rdtdr * k1 ) / & 5553 5386 ( 1.0_wp - dt_ros * gamma * d2rdtdr ) 5554 5387 5555 5388 r_ros = MAX(r_ros_ini + dt_ros * ( 1.5_wp * k1 + 0.5_wp * k2), particles(n)%aux1) 5556 5557 !--Check error of the solution, and reduce dt_ros if necessary.5389 ! 5390 !-- Check error of the solution, and reduce dt_ros if necessary. 5558 5391 error = ABS(r_err - r_ros) / r_ros 5559 5392 IF ( error > prec ) THEN … … 5569 5402 END DO 5570 5403 5571 END DO !Rosenbrock loop5404 END DO !Rosenbrock loop 5572 5405 ! 5573 5406 !-- Store new particle radius … … 5583 5416 DO n = 1, number_of_particles 5584 5417 ! 5585 !-- Sum up the change in liquid water for the respective grid 5586 !-- box for the computation of the release/depletion of water vapor 5587 !-- and heat. 5588 ql_c(k,j,i) = ql_c(k,j,i) + particles(n)%weight_factor * & 5589 rho_l * 1.33333333_wp * pi * & 5590 ( new_r(n)**3 - particles(n)%radius**3 ) / & 5418 !-- Sum up the change in liquid water for the respective grid box for the computation of the 5419 !-- release/depletion of water vapor and heat. 5420 ql_c(k,j,i) = ql_c(k,j,i) + particles(n)%weight_factor * & 5421 rho_l * 1.33333333_wp * pi * & 5422 ( new_r(n)**3 - particles(n)%radius**3 ) / & 5591 5423 ( rho_surface * dx * dy * dzw(k) ) 5592 5424 ! 5593 !-- Check if the increase in liqid water is not too big. If this is the case, 5594 !-- the model timestepmight be too long.5425 !-- Check if the increase in liqid water is not too big. If this is the case, the model timestep 5426 !-- might be too long. 5595 5427 IF ( ql_c(k,j,i) > 100.0_wp ) THEN 5596 WRITE( message_string, * ) 'k=',k,' j=',j,' i=',i, &5597 ' ql_c=',ql_c(k,j,i), '&part(',n,')%wf=',&5598 particles(n)%weight_factor,' delta_r=',delta_r5428 WRITE( message_string, * ) 'k=',k,' j=',j,' i=',i, & 5429 ' ql_c=',ql_c(k,j,i), '&part(',n,')%wf=', & 5430 particles(n)%weight_factor,' delta_r=',delta_r 5599 5431 CALL message( 'lpm_droplet_condensation', 'PA0143', 2, 2, -1, 6, 1 ) 5600 5432 ENDIF 5601 5433 ! 5602 !-- Check if the change in the droplet radius is not too big. If this is the 5603 !-- case, the modeltimestep might be too long.5434 !-- Check if the change in the droplet radius is not too big. If this is the case, the model 5435 !-- timestep might be too long. 5604 5436 delta_r = new_r(n) - particles(n)%radius 5605 5437 IF ( delta_r < 0.0_wp .AND. new_r(n) < 0.0_wp ) THEN 5606 WRITE( message_string, * ) '#1 k=',k,' j=',j,' i=',i, &5607 ' e_s=',e_s, ' e_a=',e_a,' t_int=',t_int,&5608 '&delta_r=',delta_r,&5609 ' particle_radius=',particles(n)%radius5438 WRITE( message_string, * ) '#1 k=',k,' j=',j,' i=',i, & 5439 ' e_s=',e_s, ' e_a=',e_a,' t_int=',t_int, & 5440 '&delta_r=',delta_r, & 5441 ' particle_radius=',particles(n)%radius 5610 5442 CALL message( 'lpm_droplet_condensation', 'PA0144', 2, 2, -1, 6, 1 ) 5611 5443 ENDIF 5612 5444 ! 5613 !-- Sum up the total volume of liquid water (needed below for 5614 !-- re-calculating the weightingfactors)5445 !-- Sum up the total volume of liquid water (needed below for re-calculating the weighting 5446 !-- factors) 5615 5447 ql_v(k,j,i) = ql_v(k,j,i) + particles(n)%weight_factor * new_r(n)**3 5616 5448 ! 5617 5449 !-- Determine radius class of the particle needed for collision 5618 5450 IF ( use_kernel_tables ) THEN 5619 particles(n)%class = ( LOG( new_r(n) ) - rclass_lbound ) / & 5620 ( rclass_ubound - rclass_lbound ) * & 5621 radius_classes 5451 particles(n)%class = ( LOG( new_r(n) ) - rclass_lbound ) / & 5452 ( rclass_ubound - rclass_lbound ) * radius_classes 5622 5453 particles(n)%class = MIN( particles(n)%class, radius_classes ) 5623 5454 particles(n)%class = MAX( particles(n)%class, 1 ) … … 5635 5466 5636 5467 5637 !------------------------------------------------------------------------------ !5468 !--------------------------------------------------------------------------------------------------! 5638 5469 ! Description: 5639 5470 ! ------------ 5640 !> Release of latent heat and change of mixing ratio due to condensation / 5641 !> evaporation of droplets. 5642 !------------------------------------------------------------------------------! 5471 !> Release of latent heat and change of mixing ratio due to condensation / evaporation of droplets. 5472 !--------------------------------------------------------------------------------------------------! 5643 5473 SUBROUTINE lpm_interaction_droplets_ptq 5644 5474 … … 5657 5487 5658 5488 q(k,j,i) = q(k,j,i) - ql_c(k,j,i) * flag 5659 pt(k,j,i) = pt(k,j,i) + lv_d_cp * ql_c(k,j,i) * d_exner(k) & 5660 * flag 5489 pt(k,j,i) = pt(k,j,i) + lv_d_cp * ql_c(k,j,i) * d_exner(k) * flag 5661 5490 ENDDO 5662 5491 ENDDO … … 5666 5495 5667 5496 5668 !------------------------------------------------------------------------------ !5497 !--------------------------------------------------------------------------------------------------! 5669 5498 ! Description: 5670 5499 ! ------------ 5671 !> Release of latent heat and change of mixing ratio due to condensation / 5672 !> evaporation of droplets.Call for grid point i,j5673 !------------------------------------------------------------------------------ !5500 !> Release of latent heat and change of mixing ratio due to condensation / evaporation of droplets. 5501 !> Call for grid point i,j 5502 !--------------------------------------------------------------------------------------------------! 5674 5503 SUBROUTINE lpm_interaction_droplets_ptq_ij( i, j ) 5675 5504 … … 5693 5522 5694 5523 5695 !------------------------------------------------------------------------------ !5524 !--------------------------------------------------------------------------------------------------! 5696 5525 ! Description: 5697 5526 ! ------------ 5698 5527 !> Calculate the liquid water content for each grid box. 5699 !------------------------------------------------------------------------------ !5528 !--------------------------------------------------------------------------------------------------! 5700 5529 SUBROUTINE lpm_calc_liquid_water_content 5701 5530 … … 5721 5550 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 5722 5551 ! 5723 !-- Calculate the total volume in the boxes (ql_v, weighting factor 5724 !-- has to beincluded) 5552 !-- Calculate the total volume in the boxes (ql_v, weighting factor has to beincluded) 5725 5553 DO n = 1, prt_count(k,j,i) 5726 ql_v(k,j,i) = ql_v(k,j,i) + particles(n)%weight_factor * & 5727 particles(n)%radius**3 5554 ql_v(k,j,i) = ql_v(k,j,i) + particles(n)%weight_factor * particles(n)%radius**3 5728 5555 ENDDO 5729 5556 ! 5730 5557 !-- Calculate the liquid water content 5731 5558 IF ( ql_v(k,j,i) /= 0.0_wp ) THEN 5732 ql(k,j,i) = ql(k,j,i) + rho_l * 1.33333333_wp * pi * & 5733 ql_v(k,j,i) / & 5734 ( rho_surface * dx * dy * dzw(k) ) 5559 ql(k,j,i) = ql(k,j,i) + rho_l * 1.33333333_wp * pi * & 5560 ql_v(k,j,i) / ( rho_surface * dx * dy * dzw(k) ) 5735 5561 IF ( ql(k,j,i) < 0.0_wp ) THEN 5736 WRITE( message_string, * ) 'LWC out of range: ' , & 5737 ql(k,j,i),i,j,k 5738 CALL message( 'lpm_calc_liquid_water_content', 'PA0719', & 5739 2, 2, -1, 6, 1 ) 5562 WRITE( message_string, * ) 'LWC out of range: ' , ql(k,j,i),i,j,k 5563 CALL message( 'lpm_calc_liquid_water_content', 'PA0719', 2, 2, -1, 6, 1 ) 5740 5564 ENDIF 5741 5565 ELSE … … 5751 5575 5752 5576 5753 !------------------------------------------------------------------------------ !5577 !--------------------------------------------------------------------------------------------------! 5754 5578 ! Description: 5755 5579 ! ------------ 5756 !> Calculates change in droplet radius by collision. Droplet collision is 5757 !> calculated for each grid box seperately. Collision is parameterized by 5758 !> using collision kernels. Two different kernels are available: 5759 !> Hall kernel: Kernel from Hall (1980, J. Atmos. Sci., 2486-2507), which 5760 !> considers collision due to pure gravitational effects. 5761 !> Wang kernel: Beside gravitational effects (treated with the Hall-kernel) also 5762 !> the effects of turbulence on the collision are considered using 5763 !> parameterizations of Ayala et al. (2008, New J. Phys., 10, 5764 !> 075015) and Wang and Grabowski (2009, Atmos. Sci. Lett., 10, 5765 !> 1-8). This kernel includes three possible effects of turbulence: 5580 !> Calculates change in droplet radius by collision. Droplet collision is calculated for each grid 5581 !> box seperately. Collision is parameterized by using collision kernels. Two different kernels are 5582 !> available: 5583 !> Hall kernel: Kernel from Hall (1980, J. Atmos. Sci., 2486-2507), which considers collision due to 5584 !> pure gravitational effects. 5585 !> Wang kernel: Beside gravitational effects (treated with the Hall-kernel) also the effects of 5586 !> turbulence on the collision are considered using parameterizations of Ayala et al. 5587 !> (2008, New J. Phys., 10, 075015) and Wang and Grabowski (2009, Atmos. Sci. Lett., 5588 !> 10, 1-8). This kernel includes three possible effects of turbulence: 5766 5589 !> the modification of the relative velocity between the droplets, 5767 !> the effect of preferential concentration, and the enhancement of5768 !> collision efficiencies.5769 !------------------------------------------------------------------------------ !5590 !> the effect of preferential concentration, 5591 !> and the enhancement of collision efficiencies. 5592 !--------------------------------------------------------------------------------------------------! 5770 5593 SUBROUTINE lpm_droplet_collision (i,j,k) 5771 5594 … … 5789 5612 REAL(wp) :: xsn !< aerosol mass of super-droplet n 5790 5613 5614 REAL(wp), DIMENSION(:), ALLOCATABLE :: aero_mass !< total aerosol mass of super droplet 5615 REAL(wp), DIMENSION(:), ALLOCATABLE :: mass !< total mass of super droplet 5791 5616 REAL(wp), DIMENSION(:), ALLOCATABLE :: weight !< weighting factor 5792 REAL(wp), DIMENSION(:), ALLOCATABLE :: mass !< total mass of super droplet5793 REAL(wp), DIMENSION(:), ALLOCATABLE :: aero_mass !< total aerosol mass of super droplet5794 5617 5795 5618 CALL cpu_log( log_point_s(43), 'lpm_droplet_coll', 'start' ) … … 5804 5627 IF ( use_kernel_tables ) THEN 5805 5628 ! 5806 !-- Fast method with pre-calculated collection kernels for 5807 !-- dis crete radius- and dissipation-classes.5629 !-- Fast method with pre-calculated collection kernels for discrete radius- and 5630 !-- dissipation-classes. 5808 5631 IF ( wang_kernel ) THEN 5809 eclass = INT( diss(k,j,i) * 1.0E4_wp / 600.0_wp * & 5810 dissipation_classes ) + 1 5632 eclass = INT( diss(k,j,i) * 1.0E4_wp / 600.0_wp * dissipation_classes ) + 1 5811 5633 epsilon_collision = diss(k,j,i) 5812 5634 ELSE … … 5822 5644 ELSE 5823 5645 ! 5824 !-- Collection kernels are re-calculated for every new 5825 !-- grid box. First, allocate memory for kernel table. 5826 !-- Third dimension is 1, because table is re-calculated for 5827 !-- every new dissipation value. 5646 !-- Collection kernels are re-calculated for every new grid box. First, allocate memory for 5647 !-- kernel table. 5648 !-- Third dimension is 1, because table is re-calculated for every new dissipation value. 5828 5649 ALLOCATE( ckernel(1:number_of_particles,1:number_of_particles,1:1) ) 5829 5650 ! 5830 !-- Now calculate collection kernel for this box. Note that 5831 !-- the kernel is based on theprevious time step5651 !-- Now calculate collection kernel for this box. Note that the kernel is based on the 5652 !-- previous time step 5832 5653 CALL recalculate_kernel( i, j, k ) 5833 5654 5834 5655 ENDIF 5835 5656 ! 5836 !-- Temporary fields for total mass of super-droplet, aerosol mass, and 5837 !-- weighting factor areallocated.5657 !-- Temporary fields for total mass of super-droplet, aerosol mass, and weighting factor are 5658 !-- allocated. 5838 5659 ALLOCATE(mass(1:number_of_particles), weight(1:number_of_particles)) 5839 5660 IF ( curvature_solution_effects ) ALLOCATE(aero_mass(1:number_of_particles)) 5840 5661 5841 mass(1:number_of_particles) = particles(1:number_of_particles)%weight_factor * &5842 particles(1:number_of_particles)%radius**3 * &5662 mass(1:number_of_particles) = particles(1:number_of_particles)%weight_factor * & 5663 particles(1:number_of_particles)%radius**3 * & 5843 5664 factor_volume_to_mass 5844 5665 … … 5846 5667 5847 5668 IF ( curvature_solution_effects ) THEN 5848 aero_mass(1:number_of_particles) = particles(1:number_of_particles)%weight_factor * &5849 particles(1:number_of_particles)%aux1**3 * &5669 aero_mass(1:number_of_particles) = particles(1:number_of_particles)%weight_factor * & 5670 particles(1:number_of_particles)%aux1**3 * & 5850 5671 4.0_wp / 3.0_wp * pi * rho_s 5851 5672 ENDIF … … 5856 5677 DO m = n, number_of_particles 5857 5678 ! 5858 !-- For collisions, the weighting factor of at least one super-droplet 5859 !-- needs to be largeror equal to one.5679 !-- For collisions, the weighting factor of at least one super-droplet needs to be larger 5680 !-- or equal to one. 5860 5681 IF ( MIN( weight(n), weight(m) ) < 1.0_wp ) CYCLE 5861 5682 ! … … 5873 5694 rclass_s = particles(m)%class 5874 5695 5875 collection_probability = MAX( weight(n), weight(m) ) * &5696 collection_probability = MAX( weight(n), weight(m) ) * & 5876 5697 ckernel(rclass_l,rclass_s,eclass) * ddV * dt_3d 5877 5698 ELSE 5878 collection_probability = MAX( weight(n), weight(m) ) * &5699 collection_probability = MAX( weight(n), weight(m) ) * & 5879 5700 ckernel(n,m,1) * ddV * dt_3d 5880 5701 ENDIF … … 5883 5704 !-- (Accordingly, p_crit will be 0.0, 1.0, 2.0, ...) 5884 5705 CALL random_number_parallel( random_dummy ) 5885 IF ( collection_probability - FLOOR(collection_probability) & 5886 > random_dummy ) THEN 5706 IF ( collection_probability - FLOOR(collection_probability) > random_dummy ) THEN 5887 5707 collection_probability = FLOOR(collection_probability) + 1.0_wp 5888 5708 ELSE … … 5919 5739 !-- particle m collects 1/2 weight(m) droplets of particle n. 5920 5740 !-- The total mass mass changes accordingly. 5921 !-- If n = m, the first half of the droplets coalesces with the 5922 !-- second half of the droplets; mass is unchanged because 5923 !-- xm = xn for n = m. 5741 !-- If n = m, the first half of the droplets coalesces with the second half of the 5742 !-- droplets; mass is unchanged because xm = xn for n = m. 5924 5743 !-- 5925 !-- Note: For m = n this equation is an approximation only 5926 !-- valid for weight >> 1 (which is usually the case). The 5927 !-- approximation is weight(n)-1 = weight(n). 5744 !-- Note: For m = n this equation is an approximation only valid for weight >> 1 5745 !-- (which is usually the case). The approximation is weight(n)-1 = weight(n). 5928 5746 mass(n) = mass(n) + 0.5_wp * weight(n) * ( xm - xn ) 5929 5747 mass(m) = mass(m) + 0.5_wp * weight(m) * ( xn - xm ) … … 5947 5765 IF ( ANY(weight < 0.0_wp) ) THEN 5948 5766 WRITE( message_string, * ) 'negative weighting factor' 5949 CALL message( 'lpm_droplet_collision', 'PA0028', & 5950 2, 2, -1, 6, 1 ) 5767 CALL message( 'lpm_droplet_collision', 'PA0028', 2, 2, -1, 6, 1 ) 5951 5768 ENDIF 5952 5769 5953 particles(1:number_of_particles)%radius = ( mass(1:number_of_particles) / &5954 ( weight(1:number_of_particles)&5955 * factor_volume_to_mass&5956 )&5770 particles(1:number_of_particles)%radius = ( mass(1:number_of_particles) / & 5771 ( weight(1:number_of_particles) & 5772 * factor_volume_to_mass & 5773 ) & 5957 5774 )**0.33333333333333_wp 5958 5775 5959 5776 IF ( curvature_solution_effects ) THEN 5960 particles(1:number_of_particles)%aux1 = ( aero_mass(1:number_of_particles) / &5961 ( weight(1:number_of_particles)&5962 * 4.0_wp / 3.0_wp * pi * rho_s&5963 )&5777 particles(1:number_of_particles)%aux1 = ( aero_mass(1:number_of_particles) / & 5778 ( weight(1:number_of_particles) & 5779 * 4.0_wp / 3.0_wp * pi * rho_s & 5780 ) & 5964 5781 )**0.33333333333333_wp 5965 5782 ENDIF … … 5974 5791 !-- Check if LWC is conserved during collision process 5975 5792 IF ( ql_v(k,j,i) /= 0.0_wp ) THEN 5976 IF ( ql_vp(k,j,i) / ql_v(k,j,i) >= 1.0001_wp .OR. &5793 IF ( ql_vp(k,j,i) / ql_v(k,j,i) >= 1.0001_wp .OR. & 5977 5794 ql_vp(k,j,i) / ql_v(k,j,i) <= 0.9999_wp ) THEN 5978 WRITE( message_string, * ) ' LWC is not conserved during', & 5979 ' collision! ', & 5980 ' LWC after condensation: ', ql_v(k,j,i), & 5795 WRITE( message_string, * ) ' LWC is not conserved during',' collision! ', & 5796 ' LWC after condensation: ', ql_v(k,j,i), & 5981 5797 ' LWC after collision: ', ql_vp(k,j,i) 5982 5798 CALL message( 'lpm_droplet_collision', 'PA0040', 2, 2, -1, 6, 1 ) … … 5989 5805 5990 5806 END SUBROUTINE lpm_droplet_collision 5991 5992 !------------------------------------------------------------------------------ !5807 5808 !--------------------------------------------------------------------------------------------------! 5993 5809 ! Description: 5994 5810 ! ------------ 5995 !> Initialization of the collision efficiency matrix with fixed radius and 5996 !> dissipation classes,calculated at simulation start only.5997 !------------------------------------------------------------------------------ !5811 !> Initialization of the collision efficiency matrix with fixed radius and dissipation classes, 5812 !> calculated at simulation start only. 5813 !--------------------------------------------------------------------------------------------------! 5998 5814 SUBROUTINE lpm_init_kernels 5999 5815 … … 6001 5817 INTEGER(iwp) :: j !< 6002 5818 INTEGER(iwp) :: k !< 6003 6004 ! 6005 !-- Calculate collision efficiencies for fixed radius- and dissipation 6006 !-- classes 5819 5820 ! 5821 !-- Calculate collision efficiencies for fixed radius- and dissipation classes 6007 5822 IF ( collision_kernel(6:9) == 'fast' ) THEN 6008 5823 6009 ALLOCATE( ckernel(1:radius_classes,1:radius_classes, &6010 0:dissipation_classes), epsclass(1:dissipation_classes),&5824 ALLOCATE( ckernel(1:radius_classes,1:radius_classes,0:dissipation_classes), & 5825 epsclass(1:dissipation_classes), & 6011 5826 radclass(1:radius_classes) ) 6012 5827 6013 5828 ! 6014 !-- Calculate the radius class bounds with logarithmic distances 6015 !-- in the interval[1.0E-6, 1000.0E-6] m5829 !-- Calculate the radius class bounds with logarithmic distances in the interval 5830 !-- [1.0E-6, 1000.0E-6] m 6016 5831 rclass_lbound = LOG( 1.0E-6_wp ) 6017 5832 rclass_ubound = LOG( 1000.0E-6_wp ) 6018 5833 radclass(1) = EXP( rclass_lbound ) 6019 5834 DO i = 2, radius_classes 6020 radclass(i) = EXP( rclass_lbound + &6021 ( rclass_ubound - rclass_lbound ) * &5835 radclass(i) = EXP( rclass_lbound + & 5836 ( rclass_ubound - rclass_lbound ) * & 6022 5837 ( i - 1.0_wp ) / ( radius_classes - 1.0_wp ) ) 6023 5838 ENDDO … … 6030 5845 ! 6031 5846 !-- Calculate collision efficiencies of the Wang/ayala kernel 6032 ALLOCATE( ec(1:radius_classes,1:radius_classes), &6033 ecf(1:radius_classes,1:radius_classes), &6034 gck(1:radius_classes,1:radius_classes), &5847 ALLOCATE( ec(1:radius_classes,1:radius_classes), & 5848 ecf(1:radius_classes,1:radius_classes), & 5849 gck(1:radius_classes,1:radius_classes), & 6035 5850 winf(1:radius_classes) ) 6036 5851 … … 6054 5869 ! 6055 5870 !-- Calculate collision efficiencies of the Hall kernel 6056 ALLOCATE( hkernel(1:radius_classes,1:radius_classes), &5871 ALLOCATE( hkernel(1:radius_classes,1:radius_classes), & 6057 5872 hwratio(1:radius_classes,1:radius_classes) ) 6058 5873 … … 6062 5877 DO j = 1, radius_classes 6063 5878 DO i = 1, radius_classes 6064 hkernel(i,j) = pi * ( radclass(j) + radclass(i) )**2 &5879 hkernel(i,j) = pi * ( radclass(j) + radclass(i) )**2 & 6065 5880 * ec(i,j) * ABS( winf(j) - winf(i) ) 6066 5881 ckernel(i,j,0) = hkernel(i,j) ! hall kernel stored on index 0 … … 6072 5887 IF ( j == -1 ) THEN 6073 5888 PRINT*, '*** Hall kernel' 6074 WRITE ( *,'(5X,20(F4.0,1X))' ) ( radclass(i)*1.0E6_wp, & 6075 i = 1,radius_classes ) 5889 WRITE ( *,'(5X,20(F4.0,1X))' ) ( radclass(i)*1.0E6_wp, i = 1,radius_classes ) 6076 5890 DO j = 1, radius_classes 6077 WRITE ( *,'(F4.0,1X,20(F8.4,1X))' ) radclass(j), & 6078 ( hkernel(i,j), i = 1,radius_classes ) 5891 WRITE ( *,'(F4.0,1X,20(F8.4,1X))' ) radclass(j), ( hkernel(i,j), i = 1,radius_classes ) 6079 5892 ENDDO 6080 5893 … … 6091 5904 6092 5905 PRINT*, '*** epsilon = ', epsclass(k) 6093 WRITE ( *,'(5X,20(F4.0,1X))' ) ( radclass(i) * 1.0E6_wp, & 6094 i = 1,radius_classes ) 5906 WRITE ( *,'(5X,20(F4.0,1X))' ) ( radclass(i) * 1.0E6_wp, i = 1,radius_classes ) 6095 5907 DO j = 1, radius_classes 6096 WRITE ( *,'(F4.0,1X,20(F8.4,1X))' ) radclass(j) * 1.0E6_wp, &6097 ( hwratio(i,j), i = 1,radius_classes )5908 WRITE ( *,'(F4.0,1X,20(F8.4,1X))' ) radclass(j) * 1.0E6_wp, & 5909 ( hwratio(i,j), i = 1,radius_classes ) 6098 5910 ENDDO 6099 5911 ENDDO … … 6105 5917 6106 5918 END SUBROUTINE lpm_init_kernels 6107 6108 !------------------------------------------------------------------------------ !5919 5920 !--------------------------------------------------------------------------------------------------! 6109 5921 ! Description: 6110 5922 ! ------------ 6111 5923 !> Calculation of collision kernels during each timestep and for each grid box 6112 !------------------------------------------------------------------------------ !5924 !--------------------------------------------------------------------------------------------------! 6113 5925 SUBROUTINE recalculate_kernel( i1, j1, k1 ) 6114 5926 … … 6123 5935 number_of_particles = prt_count(k1,j1,i1) 6124 5936 radius_classes = number_of_particles ! necessary to use the same 6125 ! subroutines as for 5937 ! subroutines as for 6126 5938 ! precalculated kernels 6127 5939 6128 ALLOCATE( ec(1:number_of_particles,1:number_of_particles), &5940 ALLOCATE( ec(1:number_of_particles,1:number_of_particles), & 6129 5941 radclass(1:number_of_particles), winf(1:number_of_particles) ) 6130 5942 … … 6143 5955 ! 6144 5956 !-- Call routines to calculate efficiencies for the Wang kernel 6145 ALLOCATE( gck(1:number_of_particles,1:number_of_particles), &5957 ALLOCATE( gck(1:number_of_particles,1:number_of_particles), & 6146 5958 ecf(1:number_of_particles,1:number_of_particles) ) 6147 5959 … … 6165 5977 DO j = 1, number_of_particles 6166 5978 DO i = 1, number_of_particles 6167 ckernel(i,j,1) = pi * ( radclass(j) + radclass(i) )**2 &5979 ckernel(i,j,1) = pi * ( radclass(j) + radclass(i) )**2 & 6168 5980 * ec(i,j) * ABS( winf(j) - winf(i) ) 6169 5981 ENDDO … … 6175 5987 END SUBROUTINE recalculate_kernel 6176 5988 6177 !------------------------------------------------------------------------------ !5989 !--------------------------------------------------------------------------------------------------! 6178 5990 ! Description: 6179 5991 ! ------------ 6180 !> Calculation of effects of turbulence on the geometric collision kernel 6181 !> (by including the droplets' average radial relative velocities and their 6182 !> radial distribution function) following the analytic model by Aayala et al. 6183 !> (2008, New J. Phys.). For details check the second part 2 of the publication, 6184 !> page 37ff. 5992 !> Calculation of effects of turbulence on the geometric collision kernel (by including the 5993 !> droplets' average radial relative velocities and their radial distribution function) following 5994 !> the analytic model by Aayala et al. (2008, New J. Phys.). For details check the second part 2 of 5995 !> the publication, page 37ff. 6185 5996 !> 6186 !> Input parameters, which need to be replaced by PALM parameters: 6187 !> water density, air density 6188 !------------------------------------------------------------------------------! 5997 !> Input parameters, which need to be replaced by PALM parameters: water density, air density 5998 !--------------------------------------------------------------------------------------------------! 6189 5999 SUBROUTINE turbsd 6190 6000 … … 6284 6094 t2 = tau(j) 6285 6095 6286 v1xysq = b1 * d1 * phi_w(c1,e1,v1,t1) - b1 * d2 * phi_w(c1,e2,v1,t1)&6287 - b2 * d1 * phi_w(c2,e1,v1,t1) + b2 * d2 * phi_w(c2,e2,v1,t1)6096 v1xysq = b1 * d1 * phi_w(c1,e1,v1,t1) - b1 * d2 * phi_w(c1,e2,v1,t1) & 6097 - b2 * d1 * phi_w(c2,e1,v1,t1) + b2 * d2 * phi_w(c2,e2,v1,t1) 6288 6098 v1xysq = v1xysq * urms**2 / t1 6289 6099 vrms1xy = SQRT( v1xysq ) 6290 6100 6291 v2xysq = b1 * d1 * phi_w(c1,e1,v2,t2) - b1 * d2 * phi_w(c1,e2,v2,t2)&6292 - b2 * d1 * phi_w(c2,e1,v2,t2) + b2 * d2 * phi_w(c2,e2,v2,t2)6101 v2xysq = b1 * d1 * phi_w(c1,e1,v2,t2) - b1 * d2 * phi_w(c1,e2,v2,t2) & 6102 - b2 * d1 * phi_w(c2,e1,v2,t2) + b2 * d2 * phi_w(c2,e2,v2,t2) 6293 6103 v2xysq = v2xysq * urms**2 / t2 6294 6104 vrms2xy = SQRT( v2xysq ) … … 6306 6116 ENDIF 6307 6117 6308 v1v2xy = b1 * d1 * zhi(c1,e1,v1,t1,v2,t2) - &6309 b1 * d2 * zhi(c1,e2,v1,t1,v2,t2) - &6310 b2 * d1 * zhi(c2,e1,v1,t1,v2,t2) + &6118 v1v2xy = b1 * d1 * zhi(c1,e1,v1,t1,v2,t2) - & 6119 b1 * d2 * zhi(c1,e2,v1,t1,v2,t2) - & 6120 b2 * d1 * zhi(c2,e1,v1,t1,v2,t2) + & 6311 6121 b2 * d2* zhi(c2,e2,v1,t1,v2,t2) 6312 6122 fr = d1 * EXP( -rrp / e1 ) - d2 * EXP( -rrp / e2 ) … … 6325 6135 ENDIF 6326 6136 6327 xx = -0.1988_wp * sst**4 + 1.5275_wp * sst**3 - 4.2942_wp * & 6328 sst**2 + 5.3406_wp * sst 6137 xx = -0.1988_wp * sst**4 + 1.5275_wp * sst**3 - 4.2942_wp * sst**2 + 5.3406_wp * sst 6329 6138 IF ( xx < 0.0_wp ) xx = 0.0_wp 6330 6139 yy = 0.1886_wp * EXP( 20.306_wp / lambda_re ) … … 6340 6149 6341 6150 ! 6342 !-- Calculate general collection kernel (without the consideration of 6343 !-- collection efficiencies) 6151 !-- Calculate general collection kernel (without the consideration of collection efficiencies) 6344 6152 gck(i,j) = 2.0_wp * pi * rrp**2 * wrfin * grfin 6345 6153 gck(j,i) = gck(i,j) … … 6352 6160 REAL(wp) FUNCTION phi_w( a, b, vsett, tau0 ) 6353 6161 ! 6354 !-- Function used in the Ayala et al. (2008) analytical model for turbulent 6355 !-- effects on thecollision kernel6356 6162 !-- Function used in the Ayala et al. (2008) analytical model for turbulent effects on the 6163 !-- collision kernel 6164 6357 6165 6358 6166 REAL(wp) :: a !< … … 6369 6177 REAL(wp) FUNCTION zhi( a, b, vsett1, tau1, vsett2, tau2 ) 6370 6178 ! 6371 !-- Function used in the Ayala et al. (2008) analytical model for turbulent 6372 !-- effects on the collisionkernel6179 !-- Function used in the Ayala et al. (2008) analytical model for turbulent effects on the collision 6180 !-- kernel 6373 6181 6374 6182 REAL(wp) :: a !< … … 6390 6198 aa4 = ( vsett2 / b )**2 - ( 1.0_wp / tau2 + 1.0_wp / a )**2 6391 6199 aa5 = vsett2 / b + 1.0_wp / tau2 + 1.0_wp / a 6392 aa6 = 1.0_wp / tau1 - 1.0_wp / a + ( 1.0_wp / tau2 + 1.0_wp / a) * & 6393 vsett1 / vsett2 6394 zhi = (1.0_wp / aa1 - 1.0_wp / aa2 ) * ( vsett1 - vsett2 ) * 0.5_wp / & 6395 b / aa3**2 + ( 4.0_wp / aa4 - 1.0_wp / aa5**2 - 1.0_wp / aa1**2 ) & 6396 * vsett2 * 0.5_wp / b /aa6 + ( 2.0_wp * ( b / aa2 - b / aa1 ) - & 6200 aa6 = 1.0_wp / tau1 - 1.0_wp / a + ( 1.0_wp / tau2 + 1.0_wp / a) * vsett1 / vsett2 6201 zhi = ( 1.0_wp / aa1 - 1.0_wp / aa2 ) * ( vsett1 - vsett2 ) * 0.5_wp / & 6202 b / aa3**2 + ( 4.0_wp / aa4 - 1.0_wp / aa5**2 - 1.0_wp / aa1**2 ) & 6203 * vsett2 * 0.5_wp / b /aa6 + ( 2.0_wp * ( b / aa2 - b / aa1 ) - & 6397 6204 vsett1 / aa2**2 + vsett2 / aa1**2 ) * 0.5_wp / b / aa3 6398 6205 … … 6400 6207 6401 6208 6402 !------------------------------------------------------------------------------ !6209 !--------------------------------------------------------------------------------------------------! 6403 6210 ! Description: 6404 6211 ! ------------ 6405 !> Parameterization of terminal velocity following Rogers et al. (1993, J. Appl. 6406 !> Meteorol.) 6407 !------------------------------------------------------------------------------! 6212 !> Parameterization of terminal velocity following Rogers et al. (1993, J. Appl.Meteorol.) 6213 !--------------------------------------------------------------------------------------------------! 6408 6214 SUBROUTINE fallg 6409 6215 6410 6216 INTEGER(iwp) :: j !< 6411 6217 6412 REAL(wp), PARAMETER :: k_cap_rog = 4.0_wp !< parameter6413 REAL(wp), PARAMETER :: k_low_rog = 12.0_wp !< parameter6414 6218 REAL(wp), PARAMETER :: a_rog = 9.65_wp !< parameter 6415 6219 REAL(wp), PARAMETER :: b_rog = 10.43_wp !< parameter 6416 6220 REAL(wp), PARAMETER :: c_rog = 0.6_wp !< parameter 6417 6221 REAL(wp), PARAMETER :: d0_rog = 0.745_wp !< seperation diameter 6222 REAL(wp), PARAMETER :: k_cap_rog = 4.0_wp !< parameter 6223 REAL(wp), PARAMETER :: k_low_rog = 12.0_wp !< parameter 6418 6224 6419 6225 REAL(wp) :: diameter !< droplet diameter in mm … … 6425 6231 6426 6232 IF ( diameter <= d0_rog ) THEN 6427 winf(j) = k_cap_rog * diameter * ( 1.0_wp - & 6428 EXP( -k_low_rog * diameter ) ) 6233 winf(j) = k_cap_rog * diameter * ( 1.0_wp - EXP( -k_low_rog * diameter ) ) 6429 6234 ELSE 6430 6235 winf(j) = a_rog - b_rog * EXP( -c_rog * diameter ) … … 6436 6241 6437 6242 6438 !------------------------------------------------------------------------------ !6243 !--------------------------------------------------------------------------------------------------! 6439 6244 ! Description: 6440 6245 ! ------------ 6441 6246 !> Interpolation of collision efficiencies (Hall, 1980, J. Atmos. Sci.) 6442 !------------------------------------------------------------------------------ !6247 !--------------------------------------------------------------------------------------------------! 6443 6248 SUBROUTINE effic 6444 6249 6445 6250 INTEGER(iwp) :: i !< 6446 6251 INTEGER(iwp) :: iq !< … … 6460 6265 6461 6266 REAL(wp), DIMENSION(1:21), SAVE :: rat !< 6462 6267 6463 6268 REAL(wp), DIMENSION(1:15), SAVE :: r0 !< 6464 6269 6465 6270 REAL(wp), DIMENSION(1:15,1:21), SAVE :: ecoll !< 6466 6271 … … 6470 6275 6471 6276 first = .FALSE. 6472 r0 = (/ 6.0_wp, 8.0_wp, 10.0_wp, 15.0_wp, 20.0_wp, 25.0_wp, &6473 30.0_wp, 40.0_wp, 50.0_wp, 60.0_wp, 70.0_wp, 100.0_wp, &6277 r0 = (/ 6.0_wp, 8.0_wp, 10.0_wp, 15.0_wp, 20.0_wp, 25.0_wp, & 6278 30.0_wp, 40.0_wp, 50.0_wp, 60.0_wp, 70.0_wp, 100.0_wp, & 6474 6279 150.0_wp, 200.0_wp, 300.0_wp /) 6475 6280 6476 rat = (/ 0.00_wp, 0.05_wp, 0.10_wp, 0.15_wp, 0.20_wp, 0.25_wp, &6477 0.30_wp, 0.35_wp, 0.40_wp, 0.45_wp, 0.50_wp, 0.55_wp, &6478 0.60_wp, 0.65_wp, 0.70_wp, 0.75_wp, 0.80_wp, 0.85_wp, &6281 rat = (/ 0.00_wp, 0.05_wp, 0.10_wp, 0.15_wp, 0.20_wp, 0.25_wp, & 6282 0.30_wp, 0.35_wp, 0.40_wp, 0.45_wp, 0.50_wp, 0.55_wp, & 6283 0.60_wp, 0.65_wp, 0.70_wp, 0.75_wp, 0.80_wp, 0.85_wp, & 6479 6284 0.90_wp, 0.95_wp, 1.00_wp /) 6480 6285 6481 ecoll(:,1) = (/ 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, &6482 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, &6286 ecoll(:,1) = (/ 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, & 6287 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, & 6483 6288 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp, 0.001_wp /) 6484 ecoll(:,2) = (/ 0.003_wp, 0.003_wp, 0.003_wp, 0.004_wp, 0.005_wp, &6485 0.005_wp, 0.005_wp, 0.010_wp, 0.100_wp, 0.050_wp, &6289 ecoll(:,2) = (/ 0.003_wp, 0.003_wp, 0.003_wp, 0.004_wp, 0.005_wp, & 6290 0.005_wp, 0.005_wp, 0.010_wp, 0.100_wp, 0.050_wp, & 6486 6291 0.200_wp, 0.500_wp, 0.770_wp, 0.870_wp, 0.970_wp /) 6487 ecoll(:,3) = (/ 0.007_wp, 0.007_wp, 0.007_wp, 0.008_wp, 0.009_wp, &6488 0.010_wp, 0.010_wp, 0.070_wp, 0.400_wp, 0.430_wp, &6292 ecoll(:,3) = (/ 0.007_wp, 0.007_wp, 0.007_wp, 0.008_wp, 0.009_wp, & 6293 0.010_wp, 0.010_wp, 0.070_wp, 0.400_wp, 0.430_wp, & 6489 6294 0.580_wp, 0.790_wp, 0.930_wp, 0.960_wp, 1.000_wp /) 6490 ecoll(:,4) = (/ 0.009_wp, 0.009_wp, 0.009_wp, 0.012_wp, 0.015_wp, &6491 0.010_wp, 0.020_wp, 0.280_wp, 0.600_wp, 0.640_wp, &6295 ecoll(:,4) = (/ 0.009_wp, 0.009_wp, 0.009_wp, 0.012_wp, 0.015_wp, & 6296 0.010_wp, 0.020_wp, 0.280_wp, 0.600_wp, 0.640_wp, & 6492 6297 0.750_wp, 0.910_wp, 0.970_wp, 0.980_wp, 1.000_wp /) 6493 ecoll(:,5) = (/ 0.014_wp, 0.014_wp, 0.014_wp, 0.015_wp, 0.016_wp, &6494 0.030_wp, 0.060_wp, 0.500_wp, 0.700_wp, 0.770_wp, &6298 ecoll(:,5) = (/ 0.014_wp, 0.014_wp, 0.014_wp, 0.015_wp, 0.016_wp, & 6299 0.030_wp, 0.060_wp, 0.500_wp, 0.700_wp, 0.770_wp, & 6495 6300 0.840_wp, 0.950_wp, 0.970_wp, 1.000_wp, 1.000_wp /) 6496 ecoll(:,6) = (/ 0.017_wp, 0.017_wp, 0.017_wp, 0.020_wp, 0.022_wp, &6497 0.060_wp, 0.100_wp, 0.620_wp, 0.780_wp, 0.840_wp, &6301 ecoll(:,6) = (/ 0.017_wp, 0.017_wp, 0.017_wp, 0.020_wp, 0.022_wp, & 6302 0.060_wp, 0.100_wp, 0.620_wp, 0.780_wp, 0.840_wp, & 6498 6303 0.880_wp, 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6499 ecoll(:,7) = (/ 0.030_wp, 0.030_wp, 0.024_wp, 0.022_wp, 0.032_wp, &6500 0.062_wp, 0.200_wp, 0.680_wp, 0.830_wp, 0.870_wp, &6304 ecoll(:,7) = (/ 0.030_wp, 0.030_wp, 0.024_wp, 0.022_wp, 0.032_wp, & 6305 0.062_wp, 0.200_wp, 0.680_wp, 0.830_wp, 0.870_wp, & 6501 6306 0.900_wp, 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6502 ecoll(:,8) = (/ 0.025_wp, 0.025_wp, 0.025_wp, 0.036_wp, 0.043_wp, &6503 0.130_wp, 0.270_wp, 0.740_wp, 0.860_wp, 0.890_wp, &6307 ecoll(:,8) = (/ 0.025_wp, 0.025_wp, 0.025_wp, 0.036_wp, 0.043_wp, & 6308 0.130_wp, 0.270_wp, 0.740_wp, 0.860_wp, 0.890_wp, & 6504 6309 0.920_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6505 ecoll(:,9) = (/ 0.027_wp, 0.027_wp, 0.027_wp, 0.040_wp, 0.052_wp, &6506 0.200_wp, 0.400_wp, 0.780_wp, 0.880_wp, 0.900_wp, &6310 ecoll(:,9) = (/ 0.027_wp, 0.027_wp, 0.027_wp, 0.040_wp, 0.052_wp, & 6311 0.200_wp, 0.400_wp, 0.780_wp, 0.880_wp, 0.900_wp, & 6507 6312 0.940_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6508 ecoll(:,10) = (/ 0.030_wp, 0.030_wp, 0.030_wp, 0.047_wp, 0.064_wp, &6509 0.250_wp, 0.500_wp, 0.800_wp, 0.900_wp, 0.910_wp, &6313 ecoll(:,10) = (/ 0.030_wp, 0.030_wp, 0.030_wp, 0.047_wp, 0.064_wp, & 6314 0.250_wp, 0.500_wp, 0.800_wp, 0.900_wp, 0.910_wp, & 6510 6315 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6511 ecoll(:,11) = (/ 0.040_wp, 0.040_wp, 0.033_wp, 0.037_wp, 0.068_wp, &6512 0.240_wp, 0.550_wp, 0.800_wp, 0.900_wp, 0.910_wp, &6316 ecoll(:,11) = (/ 0.040_wp, 0.040_wp, 0.033_wp, 0.037_wp, 0.068_wp, & 6317 0.240_wp, 0.550_wp, 0.800_wp, 0.900_wp, 0.910_wp, & 6513 6318 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6514 ecoll(:,12) = (/ 0.035_wp, 0.035_wp, 0.035_wp, 0.055_wp, 0.079_wp, &6515 0.290_wp, 0.580_wp, 0.800_wp, 0.900_wp, 0.910_wp, &6319 ecoll(:,12) = (/ 0.035_wp, 0.035_wp, 0.035_wp, 0.055_wp, 0.079_wp, & 6320 0.290_wp, 0.580_wp, 0.800_wp, 0.900_wp, 0.910_wp, & 6516 6321 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6517 ecoll(:,13) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.062_wp, 0.082_wp, &6518 0.290_wp, 0.590_wp, 0.780_wp, 0.900_wp, 0.910_wp, &6322 ecoll(:,13) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.062_wp, 0.082_wp, & 6323 0.290_wp, 0.590_wp, 0.780_wp, 0.900_wp, 0.910_wp, & 6519 6324 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6520 ecoll(:,14) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.060_wp, 0.080_wp, &6521 0.290_wp, 0.580_wp, 0.770_wp, 0.890_wp, 0.910_wp, &6325 ecoll(:,14) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.060_wp, 0.080_wp, & 6326 0.290_wp, 0.580_wp, 0.770_wp, 0.890_wp, 0.910_wp, & 6522 6327 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6523 ecoll(:,15) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.041_wp, 0.075_wp, &6524 0.250_wp, 0.540_wp, 0.760_wp, 0.880_wp, 0.920_wp, &6328 ecoll(:,15) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.041_wp, 0.075_wp, & 6329 0.250_wp, 0.540_wp, 0.760_wp, 0.880_wp, 0.920_wp, & 6525 6330 0.950_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6526 ecoll(:,16) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.052_wp, 0.067_wp, &6527 0.250_wp, 0.510_wp, 0.770_wp, 0.880_wp, 0.930_wp, &6331 ecoll(:,16) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.052_wp, 0.067_wp, & 6332 0.250_wp, 0.510_wp, 0.770_wp, 0.880_wp, 0.930_wp, & 6528 6333 0.970_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6529 ecoll(:,17) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.047_wp, 0.057_wp, &6530 0.250_wp, 0.490_wp, 0.770_wp, 0.890_wp, 0.950_wp, &6334 ecoll(:,17) = (/ 0.037_wp, 0.037_wp, 0.037_wp, 0.047_wp, 0.057_wp, & 6335 0.250_wp, 0.490_wp, 0.770_wp, 0.890_wp, 0.950_wp, & 6531 6336 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp, 1.000_wp /) 6532 ecoll(:,18) = (/ 0.036_wp, 0.036_wp, 0.036_wp, 0.042_wp, 0.048_wp, &6533 0.230_wp, 0.470_wp, 0.780_wp, 0.920_wp, 1.000_wp, &6337 ecoll(:,18) = (/ 0.036_wp, 0.036_wp, 0.036_wp, 0.042_wp, 0.048_wp, & 6338 0.230_wp, 0.470_wp, 0.780_wp, 0.920_wp, 1.000_wp, & 6534 6339 1.020_wp, 1.020_wp, 1.020_wp, 1.020_wp, 1.020_wp /) 6535 ecoll(:,19) = (/ 0.040_wp, 0.040_wp, 0.035_wp, 0.033_wp, 0.040_wp, &6536 0.112_wp, 0.450_wp, 0.790_wp, 1.010_wp, 1.030_wp, &6340 ecoll(:,19) = (/ 0.040_wp, 0.040_wp, 0.035_wp, 0.033_wp, 0.040_wp, & 6341 0.112_wp, 0.450_wp, 0.790_wp, 1.010_wp, 1.030_wp, & 6537 6342 1.040_wp, 1.040_wp, 1.040_wp, 1.040_wp, 1.040_wp /) 6538 ecoll(:,20) = (/ 0.033_wp, 0.033_wp, 0.033_wp, 0.033_wp, 0.033_wp, &6539 0.119_wp, 0.470_wp, 0.950_wp, 1.300_wp, 1.700_wp, &6343 ecoll(:,20) = (/ 0.033_wp, 0.033_wp, 0.033_wp, 0.033_wp, 0.033_wp, & 6344 0.119_wp, 0.470_wp, 0.950_wp, 1.300_wp, 1.700_wp, & 6540 6345 2.300_wp, 2.300_wp, 2.300_wp, 2.300_wp, 2.300_wp /) 6541 ecoll(:,21) = (/ 0.027_wp, 0.027_wp, 0.027_wp, 0.027_wp, 0.027_wp, &6542 0.125_wp, 0.520_wp, 1.400_wp, 2.300_wp, 3.000_wp, &6346 ecoll(:,21) = (/ 0.027_wp, 0.027_wp, 0.027_wp, 0.027_wp, 0.027_wp, & 6347 0.125_wp, 0.520_wp, 1.400_wp, 2.300_wp, 3.000_wp, & 6543 6348 4.000_wp, 4.000_wp, 4.000_wp, 4.000_wp, 4.000_wp /) 6544 6349 ENDIF 6545 6350 6546 6351 ! 6547 !-- Calculate the radius class index of particles with respect to array r 6548 !-- Radius has to be in microns 6352 !-- Calculate the radius class index of particles with respect to array r. 6353 !-- Radius has to be in microns. 6549 6354 ALLOCATE( ira(1:radius_classes) ) 6550 6355 DO j = 1, radius_classes … … 6561 6366 ! 6562 6367 !-- Two-dimensional linear interpolation of the collision efficiency. 6563 !-- Radius has to be in microns 6368 !-- Radius has to be in microns. 6564 6369 DO j = 1, radius_classes 6565 6370 DO i = 1, j … … 6572 6377 IF ( ir < 16 ) THEN 6573 6378 IF ( ir >= 2 ) THEN 6574 pp = ( ( MAX( radclass(j), radclass(i) ) * 1.0E6_wp ) - &6575 r0(ir-1) )/ ( r0(ir) - r0(ir-1) )6379 pp = ( ( MAX( radclass(j), radclass(i) ) * 1.0E6_wp ) - r0(ir-1) ) & 6380 / ( r0(ir) - r0(ir-1) ) 6576 6381 qq = ( rq - rat(iq-1) ) / ( rat(iq) - rat(iq-1) ) 6577 ec(j,i) = ( 1.0_wp - pp ) * ( 1.0_wp - qq ) & 6578 * ecoll(ir-1,iq-1) & 6579 + pp * ( 1.0_wp - qq ) * ecoll(ir,iq-1) & 6580 + qq * ( 1.0_wp - pp ) * ecoll(ir-1,iq) & 6382 ec(j,i) = ( 1.0_wp - pp ) * ( 1.0_wp - qq ) * ecoll(ir-1,iq-1) & 6383 + pp * ( 1.0_wp - qq ) * ecoll(ir,iq-1) & 6384 + qq * ( 1.0_wp - pp ) * ecoll(ir-1,iq) & 6581 6385 + pp * qq * ecoll(ir,iq) 6582 6386 ELSE … … 6602 6406 6603 6407 6604 !------------------------------------------------------------------------------ !6408 !--------------------------------------------------------------------------------------------------! 6605 6409 ! Description: 6606 6410 ! ------------ 6607 !> Interpolation of turbulent enhancement factor for collision efficencies 6608 !> followingWang and Grabowski (2009, Atmos. Sci. Let.)6609 !------------------------------------------------------------------------------ !6411 !> Interpolation of turbulent enhancement factor for collision efficencies following 6412 !> Wang and Grabowski (2009, Atmos. Sci. Let.) 6413 !--------------------------------------------------------------------------------------------------! 6610 6414 SUBROUTINE turb_enhance_eff 6611 6415 … … 6641 6445 first = .FALSE. 6642 6446 6643 r0 = (/ 10.0_wp, 20.0_wp, 30.0_wp, 40.0_wp, 50.0_wp, 60.0_wp, & 6644 100.0_wp /) 6645 6646 rat = (/ 0.0_wp, 0.1_wp, 0.2_wp, 0.3_wp, 0.4_wp, 0.5_wp, 0.6_wp, & 6647 0.7_wp, 0.8_wp, 0.9_wp, 1.0_wp /) 6447 r0 = (/ 10.0_wp, 20.0_wp, 30.0_wp, 40.0_wp, 50.0_wp, 60.0_wp, 100.0_wp /) 6448 6449 rat = (/ 0.0_wp, 0.1_wp, 0.2_wp, 0.3_wp, 0.4_wp, 0.5_wp, 0.6_wp, 0.7_wp, 0.8_wp, 0.9_wp, & 6450 1.0_wp /) 6648 6451 ! 6649 6452 !-- Tabulated turbulent enhancement factor at 100 cm**2/s**3 6650 ecoll_100(:,1) = (/ 1.74_wp, 1.74_wp, 1.773_wp, 1.49_wp, &6453 ecoll_100(:,1) = (/ 1.74_wp, 1.74_wp, 1.773_wp, 1.49_wp, & 6651 6454 1.207_wp, 1.207_wp, 1.0_wp /) 6652 ecoll_100(:,2) = (/ 1.46_wp, 1.46_wp, 1.421_wp, 1.245_wp, &6455 ecoll_100(:,2) = (/ 1.46_wp, 1.46_wp, 1.421_wp, 1.245_wp, & 6653 6456 1.069_wp, 1.069_wp, 1.0_wp /) 6654 ecoll_100(:,3) = (/ 1.32_wp, 1.32_wp, 1.245_wp, 1.123_wp, &6457 ecoll_100(:,3) = (/ 1.32_wp, 1.32_wp, 1.245_wp, 1.123_wp, & 6655 6458 1.000_wp, 1.000_wp, 1.0_wp /) 6656 ecoll_100(:,4) = (/ 1.250_wp, 1.250_wp, 1.148_wp, 1.087_wp, &6459 ecoll_100(:,4) = (/ 1.250_wp, 1.250_wp, 1.148_wp, 1.087_wp, & 6657 6460 1.025_wp, 1.025_wp, 1.0_wp /) 6658 ecoll_100(:,5) = (/ 1.186_wp, 1.186_wp, 1.066_wp, 1.060_wp, &6461 ecoll_100(:,5) = (/ 1.186_wp, 1.186_wp, 1.066_wp, 1.060_wp, & 6659 6462 1.056_wp, 1.056_wp, 1.0_wp /) 6660 ecoll_100(:,6) = (/ 1.045_wp, 1.045_wp, 1.000_wp, 1.014_wp, &6463 ecoll_100(:,6) = (/ 1.045_wp, 1.045_wp, 1.000_wp, 1.014_wp, & 6661 6464 1.028_wp, 1.028_wp, 1.0_wp /) 6662 ecoll_100(:,7) = (/ 1.070_wp, 1.070_wp, 1.030_wp, 1.038_wp, &6465 ecoll_100(:,7) = (/ 1.070_wp, 1.070_wp, 1.030_wp, 1.038_wp, & 6663 6466 1.046_wp, 1.046_wp, 1.0_wp /) 6664 ecoll_100(:,8) = (/ 1.000_wp, 1.000_wp, 1.054_wp, 1.042_wp, &6467 ecoll_100(:,8) = (/ 1.000_wp, 1.000_wp, 1.054_wp, 1.042_wp, & 6665 6468 1.029_wp, 1.029_wp, 1.0_wp /) 6666 ecoll_100(:,9) = (/ 1.223_wp, 1.223_wp, 1.117_wp, 1.069_wp, &6469 ecoll_100(:,9) = (/ 1.223_wp, 1.223_wp, 1.117_wp, 1.069_wp, & 6667 6470 1.021_wp, 1.021_wp, 1.0_wp /) 6668 ecoll_100(:,10) = (/ 1.570_wp, 1.570_wp, 1.244_wp, 1.166_wp, &6471 ecoll_100(:,10) = (/ 1.570_wp, 1.570_wp, 1.244_wp, 1.166_wp, & 6669 6472 1.088_wp, 1.088_wp, 1.0_wp /) 6670 ecoll_100(:,11) = (/ 20.3_wp, 20.3_wp, 14.6_wp, 8.61_wp, &6473 ecoll_100(:,11) = (/ 20.3_wp, 20.3_wp, 14.6_wp, 8.61_wp, & 6671 6474 2.60_wp, 2.60_wp, 1.0_wp /) 6672 6475 ! 6673 6476 !-- Tabulated turbulent enhancement factor at 400 cm**2/s**3 6674 ecoll_400(:,1) = (/ 4.976_wp, 4.976_wp, 3.593_wp, 2.519_wp, &6477 ecoll_400(:,1) = (/ 4.976_wp, 4.976_wp, 3.593_wp, 2.519_wp, & 6675 6478 1.445_wp, 1.445_wp, 1.0_wp /) 6676 ecoll_400(:,2) = (/ 2.984_wp, 2.984_wp, 2.181_wp, 1.691_wp, &6479 ecoll_400(:,2) = (/ 2.984_wp, 2.984_wp, 2.181_wp, 1.691_wp, & 6677 6480 1.201_wp, 1.201_wp, 1.0_wp /) 6678 ecoll_400(:,3) = (/ 1.988_wp, 1.988_wp, 1.475_wp, 1.313_wp, &6481 ecoll_400(:,3) = (/ 1.988_wp, 1.988_wp, 1.475_wp, 1.313_wp, & 6679 6482 1.150_wp, 1.150_wp, 1.0_wp /) 6680 ecoll_400(:,4) = (/ 1.490_wp, 1.490_wp, 1.187_wp, 1.156_wp, &6483 ecoll_400(:,4) = (/ 1.490_wp, 1.490_wp, 1.187_wp, 1.156_wp, & 6681 6484 1.126_wp, 1.126_wp, 1.0_wp /) 6682 ecoll_400(:,5) = (/ 1.249_wp, 1.249_wp, 1.088_wp, 1.090_wp, &6485 ecoll_400(:,5) = (/ 1.249_wp, 1.249_wp, 1.088_wp, 1.090_wp, & 6683 6486 1.092_wp, 1.092_wp, 1.0_wp /) 6684 ecoll_400(:,6) = (/ 1.139_wp, 1.139_wp, 1.130_wp, 1.091_wp, &6487 ecoll_400(:,6) = (/ 1.139_wp, 1.139_wp, 1.130_wp, 1.091_wp, & 6685 6488 1.051_wp, 1.051_wp, 1.0_wp /) 6686 ecoll_400(:,7) = (/ 1.220_wp, 1.220_wp, 1.190_wp, 1.138_wp, &6489 ecoll_400(:,7) = (/ 1.220_wp, 1.220_wp, 1.190_wp, 1.138_wp, & 6687 6490 1.086_wp, 1.086_wp, 1.0_wp /) 6688 ecoll_400(:,8) = (/ 1.325_wp, 1.325_wp, 1.267_wp, 1.165_wp, &6491 ecoll_400(:,8) = (/ 1.325_wp, 1.325_wp, 1.267_wp, 1.165_wp, & 6689 6492 1.063_wp, 1.063_wp, 1.0_wp /) 6690 ecoll_400(:,9) = (/ 1.716_wp, 1.716_wp, 1.345_wp, 1.223_wp, &6493 ecoll_400(:,9) = (/ 1.716_wp, 1.716_wp, 1.345_wp, 1.223_wp, & 6691 6494 1.100_wp, 1.100_wp, 1.0_wp /) 6692 ecoll_400(:,10) = (/ 3.788_wp, 3.788_wp, 1.501_wp, 1.311_wp, &6495 ecoll_400(:,10) = (/ 3.788_wp, 3.788_wp, 1.501_wp, 1.311_wp, & 6693 6496 1.120_wp, 1.120_wp, 1.0_wp /) 6694 ecoll_400(:,11) = (/ 36.52_wp, 36.52_wp, 19.16_wp, 22.80_wp, &6497 ecoll_400(:,11) = (/ 36.52_wp, 36.52_wp, 19.16_wp, 22.80_wp, & 6695 6498 26.0_wp, 26.0_wp, 1.0_wp /) 6696 6499 … … 6698 6501 6699 6502 ! 6700 !-- Calculate the radius class index of particles with respect to array r0 6503 !-- Calculate the radius class index of particles with respect to array r0. 6701 6504 !-- The droplet radius has to be given in microns. 6702 6505 ALLOCATE( ira(1:radius_classes) ) … … 6733 6536 IF ( ir < 8 ) THEN 6734 6537 IF ( ir >= 2 ) THEN 6735 pp = ( MAX( radclass(j), radclass(i) ) * 1.0E6_wp - &6736 r0(ir-1) )/ ( r0(ir) - r0(ir-1) )6538 pp = ( MAX( radclass(j), radclass(i) ) * 1.0E6_wp - r0(ir-1) ) & 6539 / ( r0(ir) - r0(ir-1) ) 6737 6540 qq = ( rq - rat(iq-1) ) / ( rat(iq) - rat(iq-1) ) 6738 y2 = ( 1.0_wp - pp ) * ( 1.0_wp - qq ) * ecoll_100(ir-1,iq-1) + &6739 pp * ( 1.0_wp - qq ) * ecoll_100(ir,iq-1) + &6740 qq * ( 1.0_wp - pp ) * ecoll_100(ir-1,iq) + &6541 y2 = ( 1.0_wp - pp ) * ( 1.0_wp - qq ) * ecoll_100(ir-1,iq-1) + & 6542 pp * ( 1.0_wp - qq ) * ecoll_100(ir,iq-1) + & 6543 qq * ( 1.0_wp - pp ) * ecoll_100(ir-1,iq) + & 6741 6544 pp * qq * ecoll_100(ir,iq) 6742 y3 = ( 1.0-pp ) * ( 1.0_wp - qq ) * ecoll_400(ir-1,iq-1) + &6743 pp * ( 1.0_wp - qq ) * ecoll_400(ir,iq-1) + &6744 qq * ( 1.0_wp - pp ) * ecoll_400(ir-1,iq) + &6545 y3 = ( 1.0-pp ) * ( 1.0_wp - qq ) * ecoll_400(ir-1,iq-1) + & 6546 pp * ( 1.0_wp - qq ) * ecoll_400(ir,iq-1) + & 6547 qq * ( 1.0_wp - pp ) * ecoll_400(ir-1,iq) + & 6745 6548 pp * qq * ecoll_400(ir,iq) 6746 6549 ELSE … … 6757 6560 !-- Linear interpolation of turbulent enhancement factor 6758 6561 IF ( epsilon_collision <= 0.01_wp ) THEN 6759 ecf(j,i) = ( epsilon_collision - 0.01_wp ) / ( 0.0_wp - 0.01_wp ) * y1&6760 + ( epsilon_collision - 0.0_wp ) / ( 0.01_wp - 0.0_wp ) * y26562 ecf(j,i) = ( epsilon_collision - 0.01_wp ) / ( 0.0_wp - 0.01_wp ) * y1 & 6563 + ( epsilon_collision - 0.0_wp ) / ( 0.01_wp - 0.0_wp ) * y2 6761 6564 ELSEIF ( epsilon_collision <= 0.06_wp ) THEN 6762 ecf(j,i) = ( epsilon_collision - 0.04_wp ) / ( 0.01_wp - 0.04_wp ) * y2&6763 + ( epsilon_collision - 0.01_wp ) / ( 0.04_wp - 0.01_wp ) * y36565 ecf(j,i) = ( epsilon_collision - 0.04_wp ) / ( 0.01_wp - 0.04_wp ) * y2 & 6566 + ( epsilon_collision - 0.01_wp ) / ( 0.04_wp - 0.01_wp ) * y3 6764 6567 ELSE 6765 ecf(j,i) = ( 0.06_wp - 0.04_wp ) / ( 0.01_wp - 0.04_wp ) * y2&6766 + ( 0.06_wp - 0.01_wp ) / ( 0.04_wp - 0.01_wp ) * y36568 ecf(j,i) = ( 0.06_wp - 0.04_wp ) / ( 0.01_wp - 0.04_wp ) * y2 & 6569 + ( 0.06_wp - 0.01_wp ) / ( 0.04_wp - 0.01_wp ) * y3 6767 6570 ENDIF 6768 6571 … … 6775 6578 6776 6579 END SUBROUTINE turb_enhance_eff 6777 6778 6779 !------------------------------------------------------------------------------ !6580 6581 6582 !-------------------------------------------------------------------------------------------------! 6780 6583 ! Description: 6781 6584 ! ------------ 6782 ! This routine is a part of the Lagrangian particle model. Super droplets which 6783 ! fulfill certain criterion's (e.g. a big weighting factor and a large radius) 6784 ! can be split into several super droplets with a reduced number of 6785 ! represented particles of every super droplet. This mechanism ensures an 6786 ! improved representation of the right tail of the drop size distribution with 6787 ! a feasible amount of computational costs. The limits of particle creation 6788 ! should be chosen carefully! The idea of this algorithm is based on 6789 ! Unterstrasser and Soelch, 2014. 6790 !------------------------------------------------------------------------------! 6585 ! This routine is a part of the Lagrangian particle model. Super droplets which fulfill certain 6586 ! criterion's (e.g. a big weighting factor and a large radius) can be split into several super 6587 ! droplets with a reduced number of represented particles of every super droplet. This mechanism 6588 ! ensures an improved representation of the right tail of the drop size distribution with a feasible 6589 ! amount of computational costs. The limits of particle creation should be chosen carefully! The 6590 ! idea of this algorithm is based on Unterstrasser and Soelch, 2014. 6591 !--------------------------------------------------------------------------------------------------! 6791 6592 SUBROUTINE lpm_splitting 6792 6593 6793 INTEGER(iwp) :: i !< 6594 INTEGER(iwp), PARAMETER :: n_max = 100 !< number of radii bin for splitting functions 6595 6596 INTEGER(iwp) :: i !< 6794 6597 INTEGER(iwp) :: j !< 6795 6598 INTEGER(iwp) :: jpp !< … … 6798 6601 INTEGER(iwp) :: new_particles_gb !< counter of created particles within one grid box 6799 6602 INTEGER(iwp) :: new_size !< new particle array size 6800 INTEGER(iwp) :: np !< 6603 INTEGER(iwp) :: np !< 6801 6604 INTEGER(iwp) :: old_size !< old particle array size 6802 6803 INTEGER(iwp), PARAMETER :: n_max = 100 !< number of radii bin for splitting functions6804 6605 6805 6606 LOGICAL :: first_loop_stride_sp = .TRUE. !< flag to calculate constants only once … … 6818 6619 REAL(wp) :: m3_total !< average average over all PEs third moment of DSD 6819 6620 REAL(wp) :: mu !< spectral shape parameter of gamma distribution 6820 REAL(wp) :: nrclgb !< number of cloudy grid boxes (ql >= 1.0E-5 kg/kg) 6621 REAL(wp) :: nrclgb !< number of cloudy grid boxes (ql >= 1.0E-5 kg/kg) 6821 6622 REAL(wp) :: nrclgb_total !< average over all PEs of number of cloudy grid boxes 6822 6623 REAL(wp) :: nr !< number concentration of cloud droplets … … 6824 6625 REAL(wp) :: nr0 !< intercept parameter of gamma distribution 6825 6626 REAL(wp) :: pirho_l !< pi * rho_l / 6.0 6826 REAL(wp) :: ql_crit = 1.0E-5_wp !< threshold lwc for cloudy grid cells 6827 !< (Siebesma et al 2003, JAS, 60) 6627 REAL(wp) :: ql_crit = 1.0E-5_wp !< threshold lwc for cloudy grid cells (Siebesma et al 2003, JAS, 60) 6828 6628 REAL(wp) :: rm !< volume averaged mean radius 6829 6629 REAL(wp) :: rm_total !< average over all PEs of volume averaged mean radius 6830 REAL(wp) :: r_min = 1.0E-6_wp !< minimum radius of approximated spectra 6630 REAL(wp) :: r_min = 1.0E-6_wp !< minimum radius of approximated spectra 6831 6631 REAL(wp) :: r_max = 1.0E-3_wp !< maximum radius of approximated spectra 6832 6632 REAL(wp) :: sigma_log = 1.5_wp !< standard deviation of the LOG-distribution … … 6849 6649 ENDDO 6850 6650 r_bin(n_max) = 10.0_wp**( LOG10(r_min) + n_max * dlog - 0.5_wp * dlog ) 6851 ENDIF 6651 ENDIF 6852 6652 factor_volume_to_mass = 4.0_wp / 3.0_wp * pi * rho_l 6853 6653 pirho_l = pi * rho_l / 6.0_wp 6854 6654 IF ( weight_factor_split == -1.0_wp ) THEN 6855 weight_factor_split = 0.1_wp * initial_weighting_factor 6655 weight_factor_split = 0.1_wp * initial_weighting_factor 6856 6656 ENDIF 6857 6657 ENDIF … … 6866 6666 new_particles_gb = 0 6867 6667 number_of_particles = prt_count(k,j,i) 6868 IF ( number_of_particles <= 0 .OR. & 6869 ql(k,j,i) < ql_crit ) CYCLE 6668 IF ( number_of_particles <= 0 .OR. ql(k,j,i) < ql_crit ) CYCLE 6870 6669 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 6871 6670 ! 6872 !-- Start splitting operations. Each particle is checked if it 6873 !-- fulfilled the splitting criterion's. In splitting mode 'const' 6874 !-- a critical radius (radius_split) a critical weighting factor 6875 !-- (weight_factor_split) and a splitting factor (splitting_factor) 6876 !-- must be prescribed (see particle_parameters). Super droplets 6877 !-- which have a larger radius and larger weighting factor are split 6878 !-- into 'splitting_factor' super droplets. Therefore, the weighting 6879 !-- factor of the super droplet and all created clones is reduced 6880 !-- by the factor of 'splitting_factor'. 6671 !-- Start splitting operations. Each particle is checked if it fulfilled the splitting 6672 !-- criterion's. In splitting mode 'const' a critical radius (radius_split) a critical 6673 !-- weighting factor (weight_factor_split) and a splitting factor (splitting_factor) 6674 !-- must be prescribed (see particle_parameters). Super droplets which have a larger 6675 !-- radius and larger weighting factor are split into 'splitting_factor' super droplets. 6676 !-- Therefore, the weighting factor of the super droplet and all created clones is 6677 !-- reduced by the factor of 'splitting_factor'. 6881 6678 DO n = 1, number_of_particles 6882 IF ( particles(n)%particle_mask .AND.&6883 particles(n)%radius >= radius_split .AND. &6884 particles(n)%weight_factor >= weight_factor_split ) &6679 IF ( particles(n)%particle_mask .AND. & 6680 particles(n)%radius >= radius_split .AND. & 6681 particles(n)%weight_factor >= weight_factor_split ) & 6885 6682 THEN 6886 6683 ! … … 6888 6685 new_size = prt_count(k,j,i) + splitting_factor - 1 6889 6686 ! 6890 !-- Cycle if maximum number of particles per grid box 6891 !-- is greater than the allowedmaximum number.6687 !-- Cycle if maximum number of particles per grid box is greater than the allowed 6688 !-- maximum number. 6892 6689 IF ( new_size >= max_number_particles_per_gridbox ) CYCLE 6893 6690 ! 6894 !-- Reallocate particle array if necessary. 6895 IF ( new_size > SIZE( particles) ) THEN6691 !-- Reallocate particle array if necessary. 6692 IF ( new_size > SIZE( particles ) ) THEN 6896 6693 CALL realloc_particles_array( i, j, k, new_size ) 6897 6694 ENDIF … … 6899 6696 ! 6900 6697 !-- Calculate new weighting factor. 6901 particles(n)%weight_factor = & 6902 particles(n)%weight_factor / splitting_factor 6698 particles(n)%weight_factor = particles(n)%weight_factor / splitting_factor 6903 6699 tmp_particle = particles(n) 6904 6700 ! 6905 6701 !-- Create splitting_factor-1 new particles. 6906 6702 DO jpp = 1, splitting_factor-1 6907 grid_particles(k,j,i)%particles(jpp+old_size) = & 6908 tmp_particle 6909 ENDDO 6703 grid_particles(k,j,i)%particles(jpp+old_size) = tmp_particle 6704 ENDDO 6910 6705 new_particles_gb = new_particles_gb + splitting_factor - 1 6911 ! 6706 ! 6912 6707 !-- Save the new number of super droplets for every grid box. 6913 prt_count(k,j,i) = prt_count(k,j,i) + & 6914 splitting_factor - 1 6708 prt_count(k,j,i) = prt_count(k,j,i) + splitting_factor - 1 6915 6709 ENDIF 6916 6710 ENDDO … … 6920 6714 ENDDO 6921 6715 6922 ELSEIF ( i_splitting_mode == 2 ) THEN 6716 ELSEIF ( i_splitting_mode == 2 ) THEN 6923 6717 ! 6924 6718 !-- Initialize summing variables. 6925 6719 lwc = 0.0_wp 6926 lwc_total = 0.0_wp 6720 lwc_total = 0.0_wp 6927 6721 m1 = 0.0_wp 6928 6722 m1_total = 0.0_wp … … 6942 6736 DO k = nzb+1, nzt 6943 6737 number_of_particles = prt_count(k,j,i) 6944 IF ( number_of_particles <= 0 .OR. & 6945 ql(k,j,i) < ql_crit ) CYCLE 6738 IF ( number_of_particles <= 0 .OR. ql(k,j,i) < ql_crit ) CYCLE 6946 6739 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 6947 6740 nrclgb = nrclgb + 1.0_wp … … 6949 6742 !-- Calculate moments of DSD. 6950 6743 DO n = 1, number_of_particles 6951 IF ( particles(n)%particle_mask .AND. & 6952 particles(n)%radius >= r_min ) & 6744 IF ( particles(n)%particle_mask .AND. particles(n)%radius >= r_min ) & 6953 6745 THEN 6954 6746 nr = nr + particles(n)%weight_factor 6955 rm = rm + factor_volume_to_mass * &6956 particles(n)%radius**3 * &6747 rm = rm + factor_volume_to_mass * & 6748 particles(n)%radius**3 * & 6957 6749 particles(n)%weight_factor 6958 IF ( isf == 1 ) THEN 6750 IF ( isf == 1 ) THEN 6959 6751 diameter = particles(n)%radius * 2.0_wp 6960 lwc = lwc + factor_volume_to_mass * &6961 particles(n)%radius**3 * &6962 particles(n)%weight_factor 6752 lwc = lwc + factor_volume_to_mass * & 6753 particles(n)%radius**3 * & 6754 particles(n)%weight_factor 6963 6755 m1 = m1 + particles(n)%weight_factor * diameter 6964 6756 m2 = m2 + particles(n)%weight_factor * diameter**2 … … 6966 6758 ENDIF 6967 6759 ENDIF 6968 ENDDO 6760 ENDDO 6969 6761 ENDDO 6970 6762 ENDDO … … 6973 6765 #if defined( __parallel ) 6974 6766 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 6975 CALL MPI_ALLREDUCE( nr, nr_total, 1 , & 6976 MPI_REAL, MPI_SUM, comm2d, ierr ) 6977 CALL MPI_ALLREDUCE( rm, rm_total, 1 , & 6978 MPI_REAL, MPI_SUM, comm2d, ierr ) 6767 CALL MPI_ALLREDUCE( nr, nr_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6768 CALL MPI_ALLREDUCE( rm, rm_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6979 6769 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 6980 CALL MPI_ALLREDUCE( nrclgb, nrclgb_total, 1 , & 6981 MPI_REAL, MPI_SUM, comm2d, ierr ) 6770 CALL MPI_ALLREDUCE( nrclgb, nrclgb_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6982 6771 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 6983 CALL MPI_ALLREDUCE( lwc, lwc_total, 1 , & 6984 MPI_REAL, MPI_SUM, comm2d, ierr ) 6772 CALL MPI_ALLREDUCE( lwc, lwc_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6985 6773 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 6986 CALL MPI_ALLREDUCE( m1, m1_total, 1 , & 6987 MPI_REAL, MPI_SUM, comm2d, ierr ) 6774 CALL MPI_ALLREDUCE( m1, m1_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6988 6775 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 6989 CALL MPI_ALLREDUCE( m2, m2_total, 1 , & 6990 MPI_REAL, MPI_SUM, comm2d, ierr ) 6776 CALL MPI_ALLREDUCE( m2, m2_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6991 6777 IF ( collective_wait ) CALL MPI_BARRIER( comm2d, ierr ) 6992 CALL MPI_ALLREDUCE( m3, m3_total, 1 , & 6993 MPI_REAL, MPI_SUM, comm2d, ierr ) 6994 #endif 6778 CALL MPI_ALLREDUCE( m3, m3_total, 1 , MPI_REAL, MPI_SUM, comm2d, ierr ) 6779 #endif 6995 6780 6996 6781 ! 6997 6782 !-- Calculate number concentration and mean volume averaged radius. 6998 nr_total = MERGE( nr_total / nrclgb_total, & 6999 0.0_wp, nrclgb_total > 0.0_wp & 7000 ) 7001 rm_total = MERGE( ( rm_total / & 7002 ( nr_total * factor_volume_to_mass ) & 7003 )**0.3333333_wp, 0.0_wp, nrclgb_total > 0.0_wp & 6783 nr_total = MERGE( nr_total / nrclgb_total, 0.0_wp, nrclgb_total > 0.0_wp ) 6784 rm_total = MERGE( ( rm_total / ( nr_total * factor_volume_to_mass ) )**0.3333333_wp, 0.0_wp,& 6785 nrclgb_total > 0.0_wp & 7004 6786 ) 7005 6787 ! 7006 6788 !-- Check which function should be used to approximate the DSD. 7007 6789 IF ( isf == 1 ) THEN 7008 lwc_total = MERGE( lwc_total / nrclgb_total, & 7009 0.0_wp, nrclgb_total > 0.0_wp & 7010 ) 7011 m1_total = MERGE( m1_total / nrclgb_total, & 7012 0.0_wp, nrclgb_total > 0.0_wp & 7013 ) 7014 m2_total = MERGE( m2_total / nrclgb_total, & 7015 0.0_wp, nrclgb_total > 0.0_wp & 7016 ) 7017 m3_total = MERGE( m3_total / nrclgb_total, & 7018 0.0_wp, nrclgb_total > 0.0_wp & 7019 ) 6790 lwc_total = MERGE( lwc_total / nrclgb_total, 0.0_wp, nrclgb_total > 0.0_wp ) 6791 m1_total = MERGE( m1_total / nrclgb_total, 0.0_wp, nrclgb_total > 0.0_wp ) 6792 m2_total = MERGE( m2_total / nrclgb_total, 0.0_wp, nrclgb_total > 0.0_wp ) 6793 m3_total = MERGE( m3_total / nrclgb_total, 0.0_wp, nrclgb_total > 0.0_wp ) 7020 6794 zeta = m1_total * m3_total / m2_total**2 7021 mu = MAX( ( ( 1.0_wp - zeta ) * 2.0_wp + 1.0_wp ) / & 7022 ( zeta - 1.0_wp ), 0.0_wp & 7023 ) 7024 7025 lambda = ( pirho_l * nr_total / lwc_total * & 7026 ( mu + 3.0_wp ) * ( mu + 2.0_wp ) * ( mu + 1.0_wp ) & 6795 mu = MAX( ( ( 1.0_wp - zeta ) * 2.0_wp + 1.0_wp ) / ( zeta - 1.0_wp ), 0.0_wp ) 6796 6797 lambda = ( pirho_l * nr_total / lwc_total * & 6798 ( mu + 3.0_wp ) * ( mu + 2.0_wp ) * ( mu + 1.0_wp ) & 7027 6799 )**0.3333333_wp 7028 nr0 = nr_total / gamma( mu + 1.0_wp ) * lambda**( mu + 1.0_wp ) 6800 nr0 = nr_total / gamma( mu + 1.0_wp ) * lambda**( mu + 1.0_wp ) 7029 6801 7030 6802 DO n = 0, n_max-1 7031 6803 diameter = r_bin_mid(n) * 2.0_wp 7032 an_spl(n) = nr0 * diameter**mu * EXP( -lambda * diameter ) * &7033 ( r_bin(n+1) - r_bin(n) ) * 2.0_wp 6804 an_spl(n) = nr0 * diameter**mu * EXP( -lambda * diameter ) * & 6805 ( r_bin(n+1) - r_bin(n) ) * 2.0_wp 7034 6806 ENDDO 7035 6807 ELSEIF ( isf == 2 ) THEN 7036 6808 DO n = 0, n_max-1 7037 an_spl(n) = nr_total / ( SQRT( 2.0_wp * pi ) * & 7038 LOG(sigma_log) * r_bin_mid(n) & 7039 ) * & 7040 EXP( -( LOG( r_bin_mid(n) / rm_total )**2 ) / & 7041 ( 2.0_wp * LOG(sigma_log)**2 ) & 7042 ) * & 6809 an_spl(n) = nr_total / ( SQRT( 2.0_wp * pi ) * LOG(sigma_log) * r_bin_mid(n) ) * & 6810 EXP( -( LOG( r_bin_mid(n) / rm_total )**2 ) / & 6811 ( 2.0_wp * LOG(sigma_log)**2 ) & 6812 ) * & 7043 6813 ( r_bin(n+1) - r_bin(n) ) 7044 6814 ENDDO 7045 6815 ELSEIF( isf == 3 ) THEN 7046 DO n = 0, n_max-1 7047 an_spl(n) = 3.0_wp * nr_total * r_bin_mid(n)**2 / rm_total**3 * &7048 EXP( - ( r_bin_mid(n)**3 / rm_total**3 ) ) *&6816 DO n = 0, n_max-1 6817 an_spl(n) = 3.0_wp * nr_total * r_bin_mid(n)**2 / rm_total**3 * & 6818 EXP( -( r_bin_mid(n)**3 / rm_total**3 ) ) * & 7049 6819 ( r_bin(n+1) - r_bin(n) ) 7050 6820 ENDDO … … 7058 6828 DO k = nzb+1, nzt 7059 6829 number_of_particles = prt_count(k,j,i) 7060 IF ( number_of_particles <= 0 .OR. & 7061 ql(k,j,i) < ql_crit ) CYCLE 6830 IF ( number_of_particles <= 0 .OR. ql(k,j,i) < ql_crit ) CYCLE 7062 6831 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 7063 6832 new_particles_gb = 0 7064 6833 ! 7065 !-- Start splitting operations. Each particle is checked if it 7066 !-- fulfilled the splitting criterion's. In splitting mode 'cl_av' 7067 !-- a critical radius (radius_split) and a splitting function must 7068 !-- be prescribed (see particles_par). The critical weighting factor 7069 !-- is calculated while approximating a 'gamma', 'log' or 'exp'- 7070 !-- drop size distribution. In this mode the DSD is calculated as 7071 !-- an average over all cloudy grid boxes. Super droplets which 7072 !-- have a larger radius and larger weighting factor are split into 7073 !-- 'splitting_factor' super droplets. In this case the splitting 7074 !-- factor is calculated of weighting factor of the super droplet 7075 !-- and the approximated number concentration for droplet of such 7076 !-- a size. Due to the splitting, the weighting factor of the 7077 !-- super droplet and all created clones is reduced by the factor 7078 !-- of 'splitting_facor'. 6834 !-- Start splitting operations. Each particle is checked if it fulfilled the splitting 6835 !-- criterion's. In splitting mode 'cl_av' a critical radius (radius_split) and a 6836 !-- splitting function must be prescribed (see particles_par). The critical weighting 6837 !-- factor is calculated while approximating a 'gamma', 'log' or 'exp'- drop size 6838 !-- distribution. In this mode the DSD is calculated as an average over all cloudy grid 6839 !-- boxes. Super droplets which have a larger radius and larger weighting factor are 6840 !-- split into 'splitting_factor' super droplets. In this case the splitting factor is 6841 !-- calculated of weighting factor of the super droplet and the approximated number 6842 !-- concentration for droplet of such a size. Due to the splitting, the weighting factor 6843 !-- of the super droplet and all created clones is reduced by the factor of 6844 !-- 'splitting_facor'. 7079 6845 DO n = 1, number_of_particles 7080 6846 DO np = 0, n_max-1 7081 IF ( r_bin(np) >= radius_split .AND.&7082 particles(n)%particle_mask .AND.&7083 particles(n)%radius >= r_bin(np) .AND.&7084 particles(n)%radius < r_bin(np+1) .AND. &7085 particles(n)%weight_factor >= an_spl(np) ) &6847 IF ( r_bin(np) >= radius_split .AND. & 6848 particles(n)%particle_mask .AND. & 6849 particles(n)%radius >= r_bin(np) .AND. & 6850 particles(n)%radius < r_bin(np+1) .AND. & 6851 particles(n)%weight_factor >= an_spl(np) ) & 7086 6852 THEN 7087 6853 ! 7088 6854 !-- Calculate splitting factor 7089 splitting_factor = & 7090 MIN( INT( particles(n)%weight_factor / & 7091 an_spl(np) & 7092 ), splitting_factor_max & 7093 ) 6855 splitting_factor = MIN( INT( particles(n)%weight_factor / & 6856 an_spl(np) & 6857 ), splitting_factor_max & 6858 ) 7094 6859 IF ( splitting_factor < 2 ) CYCLE 7095 6860 ! … … 7097 6862 new_size = prt_count(k,j,i) + splitting_factor - 1 7098 6863 ! 7099 !-- Cycle if maximum number of particles per grid box 7100 !-- is greater than the allowed maximum number. 7101 IF ( new_size >= max_number_particles_per_gridbox ) & 7102 CYCLE 7103 ! 7104 !-- Reallocate particle array if necessary. 7105 IF ( new_size > SIZE(particles) ) THEN 6864 !-- Cycle if maximum number of particles per grid box is greater than the 6865 !-- allowed maximum number. 6866 IF ( new_size >= max_number_particles_per_gridbox ) CYCLE 6867 ! 6868 !-- Reallocate particle array if necessary. 6869 IF ( new_size > SIZE( particles ) ) THEN 7106 6870 CALL realloc_particles_array( i, j, k, new_size ) 7107 6871 ENDIF 7108 6872 old_size = prt_count(k,j,i) 7109 new_particles_gb = new_particles_gb + & 7110 splitting_factor - 1 6873 new_particles_gb = new_particles_gb + splitting_factor - 1 7111 6874 ! 7112 6875 !-- Calculate new weighting factor. 7113 particles(n)%weight_factor = & 7114 particles(n)%weight_factor / splitting_factor 6876 particles(n)%weight_factor = particles(n)%weight_factor / splitting_factor 7115 6877 tmp_particle = particles(n) 7116 6878 ! 7117 6879 !-- Create splitting_factor-1 new particles. 7118 6880 DO jpp = 1, splitting_factor-1 7119 grid_particles(k,j,i)%particles(jpp+old_size) = & 7120 tmp_particle 6881 grid_particles(k,j,i)%particles(jpp+old_size) = tmp_particle 7121 6882 ENDDO 7122 6883 ! 7123 !-- Save the new number of super droplets. 7124 prt_count(k,j,i) = prt_count(k,j,i) + & 7125 splitting_factor - 1 6884 !-- Save the new number of super droplets. 6885 prt_count(k,j,i) = prt_count(k,j,i) + splitting_factor - 1 7126 6886 ENDIF 7127 6887 ENDDO 7128 ENDDO 6888 ENDDO 7129 6889 7130 6890 ENDDO … … 7132 6892 ENDDO 7133 6893 7134 ELSEIF ( i_splitting_mode == 3 ) THEN 6894 ELSEIF ( i_splitting_mode == 3 ) THEN 7135 6895 7136 6896 DO i = nxl, nxr … … 7145 6905 m3 = 0.0_wp 7146 6906 nr = 0.0_wp 7147 rm = 0.0_wp 6907 rm = 0.0_wp 7148 6908 7149 6909 new_particles_gb = 0 7150 6910 number_of_particles = prt_count(k,j,i) 7151 IF ( number_of_particles <= 0 .OR. & 7152 ql(k,j,i) < ql_crit ) CYCLE 6911 IF ( number_of_particles <= 0 .OR. ql(k,j,i) < ql_crit ) CYCLE 7153 6912 particles => grid_particles(k,j,i)%particles 7154 6913 ! 7155 6914 !-- Calculate moments of DSD. 7156 6915 DO n = 1, number_of_particles 7157 IF ( particles(n)%particle_mask .AND. & 7158 particles(n)%radius >= r_min ) & 6916 IF ( particles(n)%particle_mask .AND. particles(n)%radius >= r_min ) & 7159 6917 THEN 7160 6918 nr = nr + particles(n)%weight_factor 7161 rm = rm + factor_volume_to_mass * &7162 particles(n)%radius**3 * &6919 rm = rm + factor_volume_to_mass * & 6920 particles(n)%radius**3 * & 7163 6921 particles(n)%weight_factor 7164 6922 IF ( isf == 1 ) THEN 7165 6923 diameter = particles(n)%radius * 2.0_wp 7166 lwc = lwc + factor_volume_to_mass * &7167 particles(n)%radius**3 * &7168 particles(n)%weight_factor 6924 lwc = lwc + factor_volume_to_mass * & 6925 particles(n)%radius**3 * & 6926 particles(n)%weight_factor 7169 6927 m1 = m1 + particles(n)%weight_factor * diameter 7170 6928 m2 = m2 + particles(n)%weight_factor * diameter**2 … … 7182 6940 IF ( isf == 1 ) THEN 7183 6941 ! 7184 !-- Gamma size distribution to calculate 6942 !-- Gamma size distribution to calculate 7185 6943 !-- critical weight_factor (e.g. Marshall + Palmer, 1948). 7186 6944 zeta = m1 * m3 / m2**2 7187 mu = MAX( ( ( 1.0_wp - zeta ) * 2.0_wp + 1.0_wp ) / & 7188 ( zeta - 1.0_wp ), 0.0_wp & 7189 ) 7190 lambda = ( pirho_l * nr / lwc * & 7191 ( mu + 3.0_wp ) * ( mu + 2.0_wp ) * & 7192 ( mu + 1.0_wp ) & 6945 mu = MAX( ( ( 1.0_wp - zeta ) * 2.0_wp + 1.0_wp ) / ( zeta - 1.0_wp ), 0.0_wp ) 6946 lambda = ( pirho_l * nr / lwc * & 6947 ( mu + 3.0_wp ) * ( mu + 2.0_wp ) * ( mu + 1.0_wp ) & 7193 6948 )**0.3333333_wp 7194 nr0 = ( nr / (gamma( mu + 1.0_wp ) ) ) * &7195 lambda**( mu + 1.0_wp ) 6949 nr0 = ( nr / (gamma( mu + 1.0_wp ) ) ) * & 6950 lambda**( mu + 1.0_wp ) 7196 6951 7197 6952 DO n = 0, n_max-1 7198 6953 diameter = r_bin_mid(n) * 2.0_wp 7199 an_spl(n) = nr0 * diameter**mu * &7200 EXP( -lambda * diameter ) * &7201 ( r_bin(n+1) - r_bin(n) ) * 2.0_wp 6954 an_spl(n) = nr0 * diameter**mu * & 6955 EXP( -lambda * diameter ) * & 6956 ( r_bin(n+1) - r_bin(n) ) * 2.0_wp 7202 6957 ENDDO 7203 6958 ELSEIF ( isf == 2 ) THEN 7204 6959 ! 7205 !-- Lognormal size distribution to calculate critical 6960 !-- Lognormal size distribution to calculate critical 7206 6961 !-- weight_factor (e.g. Levin, 1971, Bradley + Stow, 1974). 7207 6962 DO n = 0, n_max-1 7208 an_spl(n) = nr / ( SQRT( 2.0_wp * pi ) * &7209 LOG(sigma_log) * r_bin_mid(n) &7210 ) *&7211 EXP( -( LOG( r_bin_mid(n) / rm )**2 ) / &7212 ( 2.0_wp * LOG(sigma_log)**2 ) &7213 ) *&6963 an_spl(n) = nr / ( SQRT( 2.0_wp * pi ) * & 6964 LOG(sigma_log) * r_bin_mid(n) & 6965 ) * & 6966 EXP( -( LOG( r_bin_mid(n) / rm )**2 ) / & 6967 ( 2.0_wp * LOG(sigma_log)**2 ) & 6968 ) * & 7214 6969 ( r_bin(n+1) - r_bin(n) ) 7215 6970 ENDDO 7216 6971 ELSEIF ( isf == 3 ) THEN 7217 6972 ! 7218 !-- Exponential size distribution to calculate critical 7219 !-- weight_factor (e.g. Berry + Reinhardt, 1974).6973 !-- Exponential size distribution to calculate critical weight_factor 6974 !-- (e.g. Berry + Reinhardt, 1974). 7220 6975 DO n = 0, n_max-1 7221 an_spl(n) = 3.0_wp * nr * r_bin_mid(n)**2 / rm**3 * &7222 EXP( - ( r_bin_mid(n)**3 / rm**3 ) ) * &6976 an_spl(n) = 3.0_wp * nr * r_bin_mid(n)**2 / rm**3 * & 6977 EXP( - ( r_bin_mid(n)**3 / rm**3 ) ) * & 7223 6978 ( r_bin(n+1) - r_bin(n) ) 7224 6979 ENDDO … … 7229 6984 an_spl = MAX(an_spl, 1.0_wp) 7230 6985 ! 7231 !-- Start splitting operations. Each particle is checked if it 7232 !-- fulfilled the splitting criterion's. In splitting mode 'gb_av' 7233 !-- a critical radius (radius_split) and a splitting function must 7234 !-- be prescribed (see particles_par). The critical weighting factor 7235 !-- is calculated while appoximating a 'gamma', 'log' or 'exp'- 7236 !-- drop size distribution. In this mode a DSD is calculated for 7237 !-- every cloudy grid box. Super droplets which have a larger 7238 !-- radius and larger weighting factor are split into 7239 !-- 'splitting_factor' super droplets. In this case the splitting 7240 !-- factor is calculated of weighting factor of the super droplet 7241 !-- and theapproximated number concentration for droplet of such 7242 !-- a size. Due to the splitting, the weighting factor of the 7243 !-- super droplet and all created clones is reduced by the factor 7244 !-- of 'splitting_facor'. 6986 !-- Start splitting operations. Each particle is checked if it fulfilled the splitting 6987 !-- criterions. In splitting mode 'gb_av' a critical radius (radius_split) and a 6988 !-- splitting function must be prescribed (see particles_par). The critical weighting 6989 !-- factor is calculated while appoximating a 'gamma', 'log' or 'exp'-drop size 6990 !-- distribution. In this mode a DSD is calculated for every cloudy grid box. Super 6991 !-- droplets which have a larger radius and larger weighting factor are split into 6992 !-- 'splitting_factor' super droplets. In this case the splitting factor is calculated 6993 !-- by the weighting factor of the super droplet and the approximated number 6994 !-- concentration for droplets of such size. Due to the splitting, the weighting factor 6995 !-- of the super droplet and all created clones are reduced by the factor of 6996 !-- 'splitting_facor'. 7245 6997 DO n = 1, number_of_particles 7246 6998 DO np = 0, n_max-1 7247 IF ( r_bin(np) >= radius_split .AND.&7248 particles(n)%particle_mask .AND.&7249 particles(n)%radius >= r_bin(np) .AND. &7250 particles(n)%radius < r_bin(np+1) .AND. &7251 particles(n)%weight_factor >= an_spl(np) ) &6999 IF ( r_bin(np) >= radius_split .AND. & 7000 particles(n)%particle_mask .AND. & 7001 particles(n)%radius >= r_bin(np) .AND. & 7002 particles(n)%radius < r_bin(np+1) .AND. & 7003 particles(n)%weight_factor >= an_spl(np) ) & 7252 7004 THEN 7253 7005 ! 7254 7006 !-- Calculate splitting factor. 7255 splitting_factor = & 7256 MIN( INT( particles(n)%weight_factor / & 7257 an_spl(np) & 7258 ), splitting_factor_max & 7259 ) 7007 splitting_factor = MIN( INT( particles(n)%weight_factor / an_spl(np) ), & 7008 splitting_factor_max & 7009 ) 7260 7010 IF ( splitting_factor < 2 ) CYCLE 7261 7011 … … 7266 7016 !-- Cycle if maximum number of particles per grid box 7267 7017 !-- is greater than the allowed maximum number. 7268 IF ( new_size >= max_number_particles_per_gridbox ) & 7269 CYCLE 7018 IF ( new_size >= max_number_particles_per_gridbox ) CYCLE 7270 7019 ! 7271 7020 !-- Reallocate particle array if necessary. 7272 IF ( new_size > SIZE( particles) ) THEN7021 IF ( new_size > SIZE( particles ) ) THEN 7273 7022 CALL realloc_particles_array( i, j, k, new_size ) 7274 7023 ENDIF 7275 7024 ! 7276 7025 !-- Calculate new weighting factor. 7277 particles(n)%weight_factor = & 7278 particles(n)%weight_factor / splitting_factor 7026 particles(n)%weight_factor = particles(n)%weight_factor / splitting_factor 7279 7027 tmp_particle = particles(n) 7280 7028 old_size = prt_count(k,j,i) … … 7282 7030 !-- Create splitting_factor-1 new particles. 7283 7031 DO jpp = 1, splitting_factor-1 7284 grid_particles(k,j,i)%particles( jpp + old_size ) = & 7285 tmp_particle 7032 grid_particles(k,j,i)%particles( jpp + old_size ) = tmp_particle 7286 7033 ENDDO 7287 7034 ! 7288 7035 !-- Save the new number of droplets for every grid box. 7289 prt_count(k,j,i) = prt_count(k,j,i) + & 7290 splitting_factor - 1 7291 new_particles_gb = new_particles_gb + & 7292 splitting_factor - 1 7036 prt_count(k,j,i) = prt_count(k,j,i) + splitting_factor - 1 7037 new_particles_gb = new_particles_gb + splitting_factor - 1 7293 7038 ENDIF 7294 7039 ENDDO … … 7302 7047 7303 7048 END SUBROUTINE lpm_splitting 7304 7305 7306 !------------------------------------------------------------------------------ !7049 7050 7051 !--------------------------------------------------------------------------------------------------! 7307 7052 ! Description: 7308 7053 ! ------------ 7309 ! This routine is a part of the Lagrangian particle model. Two Super droplets 7310 ! which fulfill certain criterion's (e.g. a big weighting factor and a small 7311 ! radius) can be merged into one super droplet with a increased number of 7312 ! represented particles of the super droplet. This mechanism ensures an 7313 ! improved a feasible amount of computational costs. The limits of particle 7314 ! creation should be chosen carefully! The idea of this algorithm is based on 7315 ! Unterstrasser and Soelch, 2014. 7316 !------------------------------------------------------------------------------! 7054 ! This routine is a part of the Lagrangian particle model. Two Super droplets which fulfill certain 7055 ! criterions (e.g. a big weighting factor and a small radius) can be merged into one super droplet 7056 ! with a increased number of represented particles of the super droplet. This mechanism ensures an 7057 ! improved feasible amount of computational costs. The limits of particle creation should be chosen 7058 ! carefully! The idea of this algorithm is based on Unterstrasser and Soelch, 2014. 7059 !--------------------------------------------------------------------------------------------------! 7317 7060 SUBROUTINE lpm_merging 7318 7061 … … 7324 7067 7325 7068 7326 REAL(wp) :: ql_crit = 1.0E-5_wp !< threshold lwc for cloudy grid cells 7069 REAL(wp) :: ql_crit = 1.0E-5_wp !< threshold lwc for cloudy grid cells 7327 7070 !< (e.g. Siebesma et al 2003, JAS, 60) 7328 7071 … … 7332 7075 7333 7076 IF ( weight_factor_merge == -1.0_wp ) THEN 7334 weight_factor_merge = 0.5_wp * initial_weighting_factor 7077 weight_factor_merge = 0.5_wp * initial_weighting_factor 7335 7078 ENDIF 7336 7079 … … 7340 7083 7341 7084 number_of_particles = prt_count(k,j,i) 7342 IF ( number_of_particles <= 0 .OR. & 7343 ql(k,j,i) >= ql_crit ) CYCLE 7085 IF ( number_of_particles <= 0 .OR. ql(k,j,i) >= ql_crit ) CYCLE 7344 7086 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 7345 7087 ! 7346 !-- Start merging operations: This routine delete super droplets with 7347 !-- a small radius (radius <= radius_merge) and a low weighting 7348 !-- factor (weight_factor <= weight_factor_merge). The number of 7349 !-- represented particles will be added to the next particle of the 7350 !-- particle array. Tests showed that this simplified method can be 7351 !-- used because it will only take place outside of cloudy grid 7352 !-- boxes where ql <= 1.0E-5 kg/kg. Therefore, especially former cloned 7353 !-- and subsequent evaporated super droplets will be merged. 7088 !-- Start merging operations: This routine deletes super droplets with a small radius 7089 !-- (radius <= radius_merge) and a low weighting factor (weight_factor <= 7090 !-- weight_factor_merge). The number of represented particles will be added to the next 7091 !-- particle of the particle array. Tests showed that this simplified method can be used 7092 !-- because it will only take place outside of cloudy grid boxes where ql <= 1.0E-5 kg/kg. 7093 !-- Therefore, especially former cloned and subsequent evaporated super droplets will be 7094 !-- merged. 7354 7095 DO n = 1, number_of_particles-1 7355 IF ( particles(n)%particle_mask .AND. &7356 particles(n+1)%particle_mask .AND. &7357 particles(n)%radius <= radius_merge .AND. &7358 particles(n)%weight_factor <= weight_factor_merge ) &7096 IF ( particles(n)%particle_mask .AND. & 7097 particles(n+1)%particle_mask .AND. & 7098 particles(n)%radius <= radius_merge .AND. & 7099 particles(n)%weight_factor <= weight_factor_merge ) & 7359 7100 THEN 7360 particles(n+1)%weight_factor = & 7361 particles(n+1)%weight_factor + & 7362 ( particles(n)%radius**3 / & 7363 particles(n+1)%radius**3 * & 7364 particles(n)%weight_factor & 7365 ) 7101 particles(n+1)%weight_factor = particles(n+1)%weight_factor + & 7102 ( particles(n)%radius**3 / & 7103 particles(n+1)%radius**3 * & 7104 particles(n)%weight_factor & 7105 ) 7366 7106 particles(n)%particle_mask = .FALSE. 7367 deleted_particles = deleted_particles + 1 7107 deleted_particles = deleted_particles + 1 7368 7108 merge_drp = merge_drp + 1 7369 7109 … … 7379 7119 END SUBROUTINE lpm_merging 7380 7120 7381 7382 7383 7384 !------------------------------------------------------------------------------ !7121 7122 7123 7124 !--------------------------------------------------------------------------------------------------! 7385 7125 ! Description: 7386 7126 ! ------------ 7387 7127 !> Exchange between subdomains. 7388 !> As soon as one particle has moved beyond the boundary of the domain, it 7389 !> is included in the relevant transfer arrays and marked for subsequent 7390 !> deletion on this PE. 7391 !> First sweep for crossings in x direction. Find out first the number of 7392 !> particles to be transferred and allocate temporary arrays needed to store 7393 !> them. 7394 !> For a one-dimensional decomposition along y, no transfer is necessary, 7395 !> because the particle remains on the PE, but the particle coordinate has to 7396 !> be adjusted. 7397 !------------------------------------------------------------------------------! 7128 !> As soon as one particle has moved beyond the boundary of the domain, it is included in the 7129 !> relevant transfer arrays and marked for subsequent deletion on this PE. 7130 !> First sweep for crossings in x direction. Find out first the number of particles to be 7131 !> transferred and allocate temporary arrays needed to store them. 7132 !> For a one-dimensional decomposition along y, no transfer is necessary, because the particle 7133 !> remains on the PE, but the particle coordinate has to be adjusted. 7134 !--------------------------------------------------------------------------------------------------! 7398 7135 SUBROUTINE lpm_exchange_horiz 7399 7136 … … 7401 7138 INTEGER(iwp) :: jp !< index variable along y 7402 7139 INTEGER(iwp) :: kp !< index variable along z 7403 INTEGER(iwp) :: n !< particle index variable 7140 INTEGER(iwp) :: n !< particle index variable 7404 7141 7405 7142 #if defined( __parallel ) … … 7432 7169 ! 7433 7170 !-- Exchange between subdomains. 7434 !-- As soon as one particle has moved beyond the boundary of the domain, it 7435 !-- is included in the relevant transfer arrays and marked for subsequent 7436 !-- deletion on this PE. 7437 !-- First sweep for crossings in x direction. Find out first the number of 7438 !-- particles to be transferred and allocate temporary arrays needed to store 7439 !-- them. 7440 !-- For a one-dimensional decomposition along y, no transfer is necessary, 7441 !-- because the particle remains on the PE, but the particle coordinate has to 7442 !-- be adjusted. 7171 !-- As soon as one particle has moved beyond the boundary of the domain, it is included in the 7172 !-- relevant transfer arrays and marked for subsequent deletion on this PE. 7173 !-- First sweep for crossings in x direction. Find out first the number of particles to be 7174 !-- transferred and allocate temporary arrays needed to store them. 7175 !-- For a one-dimensional decomposition along y, no transfer is necessary, because the particle 7176 !-- remains on the PE, but the particle coordinate has to be adjusted. 7443 7177 trlp_count = 0 7444 7178 trrp_count = 0 … … 7449 7183 IF ( pdims(1) /= 1 ) THEN 7450 7184 ! 7451 !-- First calculate the storage necessary for sending and receiving the data. 7452 !-- Compute only first(nxl) and last (nxr) loop iterration.7185 !-- First calculate the storage necessary for sending and receiving the data. Compute only first 7186 !-- (nxl) and last (nxr) loop iterration. 7453 7187 DO ip = nxl, nxr, nxr - nxl 7454 7188 DO jp = nys, nyn … … 7499 7233 DO n = 1, number_of_particles 7500 7234 ! 7501 !-- Only those particles that have not been marked as 'deleted' may 7502 !-- be moved. 7235 !-- Only those particles that have not been marked as 'deleted' may be moved. 7503 7236 IF ( particles(n)%particle_mask ) THEN 7504 7237 … … 7551 7284 ELSE 7552 7285 ! 7553 !-- Store particle data in the transfer array, which will be 7554 !-- send to theneighbouring PE7286 !-- Store particle data in the transfer array, which will be send to the 7287 !-- neighbouring PE 7555 7288 trlp_count = trlp_count + 1 7556 7289 trlp(trlp_count) = particles(n) … … 7569 7302 IF ( pdims(1) == 1 ) THEN 7570 7303 particles(n)%x = particles(n)%x - ( nx + 1 ) * dx 7571 particles(n)%origin_x = particles(n)%origin_x - & 7572 ( nx + 1 ) * dx 7304 particles(n)%origin_x = particles(n)%origin_x - ( nx + 1 ) * dx 7573 7305 ELSE 7574 7306 trrp_count = trrp_count + 1 7575 7307 trrp(trrp_count) = particles(n) 7576 7308 trrp(trrp_count)%x = trrp(trrp_count)%x - ( nx + 1 ) * dx 7577 trrp(trrp_count)%origin_x = trrp(trrp_count)%origin_x - &7578 ( nx + 1 ) * dx7309 trrp(trrp_count)%origin_x = trrp(trrp_count)%origin_x - & 7310 ( nx + 1 ) * dx 7579 7311 particles(n)%particle_mask = .FALSE. 7580 7312 deleted_particles = deleted_particles + 1 … … 7597 7329 ELSE 7598 7330 ! 7599 !-- Store particle data in the transfer array, which will be send 7600 !-- to theneighbouring PE7331 !-- Store particle data in the transfer array, which will be send to the 7332 !-- neighbouring PE 7601 7333 trrp_count = trrp_count + 1 7602 7334 trrp(trrp_count) = particles(n) … … 7615 7347 7616 7348 ! 7617 !-- STORAGE_SIZE returns the storage size of argument A in bits. However , it 7349 !-- STORAGE_SIZE returns the storage size of argument A in bits. However , it 7618 7350 !-- is needed in bytes. The function C_SIZEOF which produces this value directly 7619 7351 !-- causes problems with gfortran. For this reason the use of C_SIZEOF is avoided 7620 par_size = STORAGE_SIZE( trlp(1))/87621 7622 7623 ! 7624 !-- Allocate arrays required for north-south exchange, as these 7625 !-- are used directly after particles areexchange along x-direction.7626 ALLOCATE( move_also_north(1: NR_2_direction_move) )7627 ALLOCATE( move_also_south(1: NR_2_direction_move) )7352 par_size = STORAGE_SIZE( trlp(1) ) / 8 7353 7354 7355 ! 7356 !-- Allocate arrays required for north-south exchange, as these are used directly after particles 7357 !-- are exchange along x-direction. 7358 ALLOCATE( move_also_north(1:nr_2_direction_move) ) 7359 ALLOCATE( move_also_south(1:nr_2_direction_move) ) 7628 7360 7629 7361 nr_move_north = 0 7630 7362 nr_move_south = 0 7631 7363 ! 7632 !-- Send left boundary, receive right boundary (but first exchange how many 7633 !-- and check, if particlestorage must be extended)7364 !-- Send left boundary, receive right boundary (but first exchange how many and check, if particle 7365 !-- storage must be extended) 7634 7366 IF ( pdims(1) /= 1 ) THEN 7635 7367 7636 CALL MPI_SENDRECV( trlp_count, 1, MPI_INTEGER, pleft, 0, &7637 trrp_count_recv, 1, MPI_INTEGER, pright, 0, &7368 CALL MPI_SENDRECV( trlp_count, 1, MPI_INTEGER, pleft, 0, & 7369 trrp_count_recv, 1, MPI_INTEGER, pright, 0, & 7638 7370 comm2d, status, ierr ) 7639 7371 7640 7372 ALLOCATE(rvrp(MAX(1,trrp_count_recv))) 7641 7373 7642 CALL MPI_SENDRECV( trlp, max(1,trlp_count)*par_size, MPI_BYTE,& 7643 pleft, 1, rvrp, & 7644 max(1,trrp_count_recv)*par_size, MPI_BYTE, pright, 1,& 7374 CALL MPI_SENDRECV( trlp, MAX(1,trlp_count)*par_size, MPI_BYTE, pleft, 1, & 7375 rvrp, MAX(1,trrp_count_recv)*par_size, MPI_BYTE, pright, 1, & 7645 7376 comm2d, status, ierr ) 7646 7377 … … 7651 7382 ! 7652 7383 !-- Send right boundary, receive left boundary 7653 CALL MPI_SENDRECV( trrp_count, 1, MPI_INTEGER, pright, 0, &7654 trlp_count_recv, 1, MPI_INTEGER, pleft, 0, &7384 CALL MPI_SENDRECV( trrp_count, 1, MPI_INTEGER, pright, 0, & 7385 trlp_count_recv, 1, MPI_INTEGER, pleft, 0, & 7655 7386 comm2d, status, ierr ) 7656 7387 7657 7388 ALLOCATE(rvlp(MAX(1,trlp_count_recv))) 7658 7389 ! 7659 !-- This MPI_SENDRECV should work even with odd mixture on 32 and 64 Bit 7660 !-- variables in structure particle_type (due to the calculation of par_size) 7661 CALL MPI_SENDRECV( trrp, max(1,trrp_count)*par_size, MPI_BYTE,& 7662 pright, 1, rvlp, & 7663 max(1,trlp_count_recv)*par_size, MPI_BYTE, pleft, 1, & 7390 !-- This MPI_SENDRECV should work even with odd mixture on 32 and 64 Bit variables in structure 7391 !-- particle_type (due to the calculation of par_size) 7392 CALL MPI_SENDRECV( trrp, MAX(1,trrp_count)*par_size, MPI_BYTE, pright, 1, & 7393 rvlp, MAX(1,trlp_count_recv)*par_size, MPI_BYTE, pleft, 1, & 7664 7394 comm2d, status, ierr ) 7665 7395 … … 7672 7402 7673 7403 ! 7674 !-- Check whether particles have crossed the boundaries in y direction. Note 7675 !-- that this case can also apply to particles that have just been received 7676 !-- from the adjacent right or left PE. 7677 !-- Find out first the number of particles to be transferred and allocate 7678 !-- temporary arrays needed to store them. 7679 !-- For a one-dimensional decomposition along y, no transfer is necessary, 7680 !-- because the particle remains on the PE. 7404 !-- Check whether particles have crossed the boundaries in y direction. Note that this case can also 7405 !-- apply to particles that have just been received from the adjacent right or left PE. 7406 !-- Find out first the number of particles to be transferred and allocate temporary arrays needed to 7407 !-- store them. 7408 !-- For a one-dimensional decomposition along y, no transfer is necessary, because the particle 7409 !-- remains on the PE. 7681 7410 trsp_count = nr_move_south 7682 7411 trnp_count = nr_move_north … … 7687 7416 IF ( pdims(2) /= 1 ) THEN 7688 7417 ! 7689 !-- First calculate the storage necessary for sending and receiving the 7690 !-- data 7418 !-- First calculate the storage necessary for sending and receiving the data 7691 7419 DO ip = nxl, nxr 7692 7420 DO jp = nys, nyn, nyn-nys !compute only first (nys) and last (nyn) loop iterration … … 7737 7465 DO n = 1, number_of_particles 7738 7466 ! 7739 !-- Only those particles that have not been marked as 'deleted' may 7740 !-- be moved. 7467 !-- Only those particles that have not been marked as 'deleted' may be moved. 7741 7468 IF ( particles(n)%particle_mask ) THEN 7742 7469 … … 7755 7482 IF ( pdims(2) == 1 ) THEN 7756 7483 particles(n)%y = ( ny + 1 ) * dy + particles(n)%y 7757 particles(n)%origin_y = ( ny + 1 ) * dy + & 7758 particles(n)%origin_y 7484 particles(n)%origin_y = ( ny + 1 ) * dy + particles(n)%origin_y 7759 7485 ELSE 7760 7486 trsp_count = trsp_count + 1 7761 7487 trsp(trsp_count) = particles(n) 7762 trsp(trsp_count)%y = ( ny + 1 ) * dy + & 7763 trsp(trsp_count)%y 7764 trsp(trsp_count)%origin_y = trsp(trsp_count)%origin_y & 7765 + ( ny + 1 ) * dy 7488 trsp(trsp_count)%y = ( ny + 1 ) * dy + trsp(trsp_count)%y 7489 trsp(trsp_count)%origin_y = trsp(trsp_count)%origin_y & 7490 + ( ny + 1 ) * dy 7766 7491 particles(n)%particle_mask = .FALSE. 7767 7492 deleted_particles = deleted_particles + 1 … … 7770 7495 trsp(trsp_count)%y = trsp(trsp_count)%y - 1.0E-10_wp 7771 7496 !++ why is 1 subtracted in next statement??? 7772 trsp(trsp_count)%origin_y = & 7773 trsp(trsp_count)%origin_y - 1 7497 trsp(trsp_count)%origin_y = trsp(trsp_count)%origin_y - 1 7774 7498 ENDIF 7775 7499 … … 7791 7515 ELSE 7792 7516 ! 7793 !-- Store particle data in the transfer array, which will 7794 !-- be send to theneighbouring PE7517 !-- Store particle data in the transfer array, which will be send to the 7518 !-- neighbouring PE 7795 7519 trsp_count = trsp_count + 1 7796 7520 trsp(trsp_count) = particles(n) … … 7809 7533 IF ( pdims(2) == 1 ) THEN 7810 7534 particles(n)%y = particles(n)%y - ( ny + 1 ) * dy 7811 particles(n)%origin_y = & 7812 particles(n)%origin_y - ( ny + 1 ) * dy 7535 particles(n)%origin_y = particles(n)%origin_y - ( ny + 1 ) * dy 7813 7536 ELSE 7814 7537 trnp_count = trnp_count + 1 7815 7538 trnp(trnp_count) = particles(n) 7816 trnp(trnp_count)%y = & 7817 trnp(trnp_count)%y - ( ny + 1 ) * dy 7818 trnp(trnp_count)%origin_y = & 7819 trnp(trnp_count)%origin_y - ( ny + 1 ) * dy 7539 trnp(trnp_count)%y = trnp(trnp_count)%y - ( ny + 1 ) * dy 7540 trnp(trnp_count)%origin_y = & 7541 trnp(trnp_count)%origin_y - ( ny + 1 ) * dy 7820 7542 particles(n)%particle_mask = .FALSE. 7821 7543 deleted_particles = deleted_particles + 1 … … 7837 7559 ELSE 7838 7560 ! 7839 !-- Store particle data in the transfer array, which will 7840 !-- be send to theneighbouring PE7561 !-- Store particle data in the transfer array, which will be send to the 7562 !-- neighbouring PE 7841 7563 trnp_count = trnp_count + 1 7842 7564 trnp(trnp_count) = particles(n) … … 7854 7576 7855 7577 ! 7856 !-- Send front boundary, receive back boundary (but first exchange how many 7857 !-- and check, if particlestorage must be extended)7578 !-- Send front boundary, receive back boundary (but first exchange how many and check, if particle 7579 !-- storage must be extended) 7858 7580 IF ( pdims(2) /= 1 ) THEN 7859 7581 … … 7864 7586 ALLOCATE(rvnp(MAX(1,trnp_count_recv))) 7865 7587 ! 7866 !-- This MPI_SENDRECV should work even with odd mixture on 32 and 64 Bit 7867 !-- variables in structure particle_type (due to the calculation of par_size) 7868 CALL MPI_SENDRECV( trsp, trsp_count*par_size, MPI_BYTE, & 7869 psouth, 1, rvnp, & 7870 trnp_count_recv*par_size, MPI_BYTE, pnorth, 1, & 7588 !-- This MPI_SENDRECV should work even with odd mixture on 32 and 64 Bit variables in structure 7589 !-- particle_type (due to the calculation of par_size) 7590 CALL MPI_SENDRECV( trsp, trsp_count*par_size, MPI_BYTE, psouth, 1, & 7591 rvnp, trnp_count_recv*par_size, MPI_BYTE, pnorth, 1, & 7871 7592 comm2d, status, ierr ) 7872 7593 … … 7877 7598 ! 7878 7599 !-- Send back boundary, receive front boundary 7879 CALL MPI_SENDRECV( trnp_count, 1, MPI_INTEGER, pnorth, 0, &7880 trsp_count_recv, 1, MPI_INTEGER, psouth, 0, &7600 CALL MPI_SENDRECV( trnp_count, 1, MPI_INTEGER, pnorth, 0, & 7601 trsp_count_recv, 1, MPI_INTEGER, psouth, 0, & 7881 7602 comm2d, status, ierr ) 7882 7603 7883 7604 ALLOCATE(rvsp(MAX(1,trsp_count_recv))) 7884 7605 ! 7885 !-- This MPI_SENDRECV should work even with odd mixture on 32 and 64 Bit 7886 !-- variables in structure particle_type (due to the calculation of par_size) 7887 CALL MPI_SENDRECV( trnp, trnp_count*par_size, MPI_BYTE, & 7888 pnorth, 1, rvsp, & 7889 trsp_count_recv*par_size, MPI_BYTE, psouth, 1, & 7606 !-- This MPI_SENDRECV should work even with odd mixture on 32 and 64 Bit variables in structure 7607 !-- particle_type (due to the calculation of par_size) 7608 CALL MPI_SENDRECV( trnp, trnp_count*par_size, MPI_BYTE, pnorth, 1, & 7609 rvsp, trsp_count_recv*par_size, MPI_BYTE, psouth, 1, & 7890 7610 comm2d, status, ierr ) 7891 7611 … … 7922 7642 !-- Cyclic boundary. Relevant coordinate has to be changed. 7923 7643 particles(n)%x = ( nx + 1 ) * dx + particles(n)%x 7924 particles(n)%origin_x = ( nx + 1 ) * dx + & 7925 particles(n)%origin_x 7644 particles(n)%origin_x = ( nx + 1 ) * dx + particles(n)%origin_x 7926 7645 ELSEIF ( ibc_par_lr == 1 ) THEN 7927 7646 ! … … 7943 7662 !-- Cyclic boundary. Relevant coordinate has to be changed. 7944 7663 particles(n)%x = particles(n)%x - ( nx + 1 ) * dx 7945 particles(n)%origin_x = particles(n)%origin_x - & 7946 ( nx + 1 ) * dx 7664 particles(n)%origin_x = particles(n)%origin_x - ( nx + 1 ) * dx 7947 7665 7948 7666 ELSEIF ( ibc_par_lr == 1 ) THEN … … 7979 7697 !-- Cyclic boundary. Relevant coordinate has to be changed. 7980 7698 particles(n)%y = ( ny + 1 ) * dy + particles(n)%y 7981 particles(n)%origin_y = ( ny + 1 ) * dy + & 7982 particles(n)%origin_y 7699 particles(n)%origin_y = ( ny + 1 ) * dy + particles(n)%origin_y 7983 7700 7984 7701 ELSEIF ( ibc_par_ns == 1 ) THEN … … 8001 7718 !-- Cyclic boundary. Relevant coordinate has to be changed. 8002 7719 particles(n)%y = particles(n)%y - ( ny + 1 ) * dy 8003 particles(n)%origin_y = particles(n)%origin_y - & 8004 ( ny + 1 ) * dy 7720 particles(n)%origin_y = particles(n)%origin_y - ( ny + 1 ) * dy 8005 7721 8006 7722 ELSEIF ( ibc_par_ns == 1 ) THEN … … 8043 7759 8044 7760 #if defined( __parallel ) 8045 !------------------------------------------------------------------------------ !7761 !--------------------------------------------------------------------------------------------------! 8046 7762 ! Description: 8047 7763 ! ------------ 8048 !> If a particle moves from one processor to another, this subroutine moves 8049 !> the corresponding elements from the particle arrays of the old grid cells8050 !> to the particle arrays of the new gridcells.8051 !------------------------------------------------------------------------------ !7764 !> If a particle moves from one processor to another, this subroutine moves the corresponding 7765 !> elements from the particle arrays of the old grid cells to the particle arrays of the new grid 7766 !> cells. 7767 !--------------------------------------------------------------------------------------------------! 8052 7768 SUBROUTINE lpm_add_particles_to_gridcell (particle_array) 8053 7769 … … 8065 7781 TYPE(particle_type), DIMENSION(:), ALLOCATABLE :: temp_ns !< temporary particle array for reallocation 8066 7782 7783 8067 7784 pack_done = .FALSE. 8068 7785 8069 DO n = 1, SIZE( particle_array)7786 DO n = 1, SIZE( particle_array ) 8070 7787 8071 7788 IF ( .NOT. particle_array(n)%particle_mask ) CYCLE … … 8075 7792 ! 8076 7793 !-- In case of stretching the actual k index must be found 8077 IF ( dz_stretch_level /= -9999999.9_wp .OR. 8078 dz_stretch_level_start(1) /= -9999999.9_wp )THEN7794 IF ( dz_stretch_level /= -9999999.9_wp .OR. dz_stretch_level_start(1) /= -9999999.9_wp ) & 7795 THEN 8079 7796 kp = MAX( MINLOC( ABS( particle_array(n)%z - zu ), DIM = 1 ) - 1, 1 ) 8080 7797 ELSE … … 8082 7799 ENDIF 8083 7800 8084 IF ( ip >= nxl .AND. ip <= nxr .AND. jp >= nys .AND. jp <= nyn & 8085 .AND. kp >= nzb+1 .AND. kp <= nzt) THEN ! particle stays on processor 7801 IF ( ip >= nxl .AND. ip <= nxr .AND. jp >= nys .AND. jp <= nyn .AND. & 7802 kp >= nzb+1 .AND. kp <= nzt) THEN ! particle stays on processor 7803 8086 7804 number_of_particles = prt_count(kp,jp,ip) 8087 7805 particles => grid_particles(kp,jp,ip)%particles(1:number_of_particles) 8088 7806 8089 7807 pindex = prt_count(kp,jp,ip)+1 8090 IF( pindex > SIZE( grid_particles(kp,jp,ip)%particles) ) THEN7808 IF( pindex > SIZE( grid_particles(kp,jp,ip)%particles ) ) THEN 8091 7809 IF ( pack_done ) THEN 8092 7810 CALL realloc_particles_array ( ip, jp, kp ) … … 8095 7813 prt_count(kp,jp,ip) = number_of_particles 8096 7814 pindex = prt_count(kp,jp,ip)+1 8097 IF ( pindex > SIZE( grid_particles(kp,jp,ip)%particles) ) THEN7815 IF ( pindex > SIZE( grid_particles(kp,jp,ip)%particles ) ) THEN 8098 7816 CALL realloc_particles_array ( ip, jp, kp ) 8099 7817 ENDIF … … 8103 7821 grid_particles(kp,jp,ip)%particles(pindex) = particle_array(n) 8104 7822 prt_count(kp,jp,ip) = pindex 7823 8105 7824 ELSE 7825 8106 7826 IF ( jp <= nys - 1 ) THEN 7827 8107 7828 nr_move_south = nr_move_south+1 8108 7829 ! 8109 !-- Before particle information is swapped to exchange-array, check 8110 !-- if enough memory is allocated. If required, reallocate exchange 8111 !-- array. 8112 IF ( nr_move_south > SIZE(move_also_south) ) THEN 8113 ! 8114 !-- At first, allocate further temporary array to swap particle 8115 !-- information. 8116 ALLOCATE( temp_ns(SIZE(move_also_south)+NR_2_direction_move) ) 7830 !-- Before particle information is swapped to exchange-array, check if enough memory is 7831 !-- allocated. If required, reallocate exchange array. 7832 IF ( nr_move_south > SIZE( move_also_south ) ) THEN 7833 ! 7834 !-- At first, allocate further temporary array to swap particle information. 7835 ALLOCATE( temp_ns(SIZE( move_also_south )+nr_2_direction_move) ) 8117 7836 temp_ns(1:nr_move_south-1) = move_also_south(1:nr_move_south-1) 8118 7837 DEALLOCATE( move_also_south ) 8119 ALLOCATE( move_also_south(SIZE( temp_ns)) )7838 ALLOCATE( move_also_south(SIZE( temp_ns )) ) 8120 7839 move_also_south(1:nr_move_south-1) = temp_ns(1:nr_move_south-1) 8121 7840 DEALLOCATE( temp_ns ) … … 8129 7848 !-- Apply boundary condition along y 8130 7849 IF ( ibc_par_ns == 0 ) THEN 8131 move_also_south(nr_move_south)%y = &8132 move_also_south(nr_move_south)%y + ( ny + 1 ) * dy8133 move_also_south(nr_move_south)%origin_y = &8134 move_also_south(nr_move_south)%origin_y + ( ny + 1 ) * dy7850 move_also_south(nr_move_south)%y = & 7851 move_also_south(nr_move_south)%y + ( ny + 1 ) * dy 7852 move_also_south(nr_move_south)%origin_y = & 7853 move_also_south(nr_move_south)%origin_y + ( ny + 1 ) * dy 8135 7854 ELSEIF ( ibc_par_ns == 1 ) THEN 8136 7855 ! … … 8142 7861 ! 8143 7862 !-- Particle reflection 8144 move_also_south(nr_move_south)%y = & 8145 -move_also_south(nr_move_south)%y 8146 move_also_south(nr_move_south)%speed_y = & 8147 -move_also_south(nr_move_south)%speed_y 7863 move_also_south(nr_move_south)%y = -move_also_south(nr_move_south)%y 7864 move_also_south(nr_move_south)%speed_y = -move_also_south(nr_move_south)%speed_y 8148 7865 8149 7866 ENDIF 7867 8150 7868 ENDIF 7869 8151 7870 ELSEIF ( jp >= nyn+1 ) THEN 7871 8152 7872 nr_move_north = nr_move_north+1 8153 7873 ! 8154 !-- Before particle information is swapped to exchange-array, check 8155 !-- if enough memory is allocated. If required, reallocate exchange 8156 !-- array. 8157 IF ( nr_move_north > SIZE(move_also_north) ) THEN 8158 ! 8159 !-- At first, allocate further temporary array to swap particle 8160 !-- information. 8161 ALLOCATE( temp_ns(SIZE(move_also_north)+NR_2_direction_move) ) 7874 !-- Before particle information is swapped to exchange-array, check if enough memory is 7875 !-- allocated. If required, reallocate exchange array. 7876 IF ( nr_move_north > SIZE( move_also_north ) ) THEN 7877 ! 7878 !-- At first, allocate further temporary array to swap particle information. 7879 ALLOCATE( temp_ns(SIZE( move_also_north )+nr_2_direction_move) ) 8162 7880 temp_ns(1:nr_move_north-1) = move_also_south(1:nr_move_north-1) 8163 7881 DEALLOCATE( move_also_north ) 8164 ALLOCATE( move_also_north(SIZE( temp_ns)) )7882 ALLOCATE( move_also_north(SIZE( temp_ns )) ) 8165 7883 move_also_north(1:nr_move_north-1) = temp_ns(1:nr_move_north-1) 8166 7884 DEALLOCATE( temp_ns ) … … 8174 7892 IF ( ibc_par_ns == 0 ) THEN 8175 7893 8176 move_also_north(nr_move_north)%y = &8177 move_also_north(nr_move_north)%y - ( ny + 1 ) * dy8178 move_also_north(nr_move_north)%origin_y = &8179 move_also_north(nr_move_north)%origin_y - ( ny + 1 ) * dy7894 move_also_north(nr_move_north)%y = & 7895 move_also_north(nr_move_north)%y - ( ny + 1 ) * dy 7896 move_also_north(nr_move_north)%origin_y = & 7897 move_also_north(nr_move_north)%origin_y - ( ny + 1 ) * dy 8180 7898 ELSEIF ( ibc_par_ns == 1 ) THEN 8181 7899 ! … … 8187 7905 ! 8188 7906 !-- Particle reflection 8189 move_also_north(nr_move_north)%y = & 8190 -move_also_north(nr_move_north)%y 8191 move_also_north(nr_move_north)%speed_y = & 8192 -move_also_north(nr_move_north)%speed_y 7907 move_also_north(nr_move_north)%y = -move_also_north(nr_move_north)%y 7908 move_also_north(nr_move_north)%speed_y = -move_also_north(nr_move_north)%speed_y 8193 7909 8194 7910 ENDIF 7911 8195 7912 ENDIF 7913 8196 7914 ELSE 7915 8197 7916 IF ( .NOT. child_domain ) THEN 8198 7917 WRITE(0,'(a,8i7)') 'particle out of range ',myid,ip,jp,kp,nxl,nxr,nys,nyn 7918 8199 7919 ENDIF 7920 8200 7921 ENDIF 7922 8201 7923 ENDIF 7924 8202 7925 ENDDO 8203 7926 8204 7927 END SUBROUTINE lpm_add_particles_to_gridcell 8205 7928 #endif 8206 8207 8208 !------------------------------------------------------------------------------ !7929 7930 7931 !--------------------------------------------------------------------------------------------------! 8209 7932 ! Description: 8210 7933 ! ------------ 8211 !> If a particle moves from one grid cell to another (on the current 8212 !> processor!), this subroutine moves the corresponding element from the 8213 !> particle array of the old grid cell to the particle array of the new grid 8214 !> cell. 8215 !------------------------------------------------------------------------------! 7934 !> If a particle moves from one grid cell to another (on the current processor!), this subroutine 7935 !> moves the corresponding element from the particle array of the old grid cell to the particle 7936 !> array of the new grid cell. 7937 !--------------------------------------------------------------------------------------------------! 8216 7938 SUBROUTINE lpm_move_particle 8217 7939 8218 7940 INTEGER(iwp) :: i !< grid index (x) of particle position 8219 7941 INTEGER(iwp) :: ip !< index variable along x … … 8243 7965 k = kp 8244 7966 ! 8245 !-- Find correct vertical particle grid box (necessary in case of grid stretching) 8246 !-- Due to the CFL limitations only the neighbouring grid boxes are considered. 7967 !-- Find correct vertical particle grid box (necessary in case of grid stretching). 7968 !-- Due to the CFL limitations only the neighbouring grid boxes are considered. 8247 7969 IF( zw(k) < particles_before_move(n)%z ) k = k + 1 8248 IF( zw(k-1) > particles_before_move(n)%z ) k = k - 1 8249 8250 !-- For lpm_exchange_horiz to work properly particles need to be moved to the outermost gridboxes8251 !-- of the respective processor. If the particle index is inside the processor the following lines8252 !-- will not change the index7970 IF( zw(k-1) > particles_before_move(n)%z ) k = k - 1 7971 7972 !-- For lpm_exchange_horiz to work properly particles need to be moved to the outermost 7973 !-- gridboxes of the respective processor. If the particle index is inside the processor 7974 !-- the following lines will not change the index. 8253 7975 i = MIN ( i , nxr ) 8254 7976 i = MAX ( i , nxl ) … … 8263 7985 IF ( i /= ip .OR. j /= jp .OR. k /= kp ) THEN 8264 7986 !! 8265 !-- If the particle stays on the same processor, the particle 8266 !-- will be added to theparticle array of the new processor.7987 !-- If the particle stays on the same processor, the particle will be added to the 7988 !-- particle array of the new processor. 8267 7989 number_of_particles = prt_count(k,j,i) 8268 7990 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 8269 7991 8270 7992 pindex = prt_count(k,j,i)+1 8271 IF ( pindex > SIZE(grid_particles(k,j,i)%particles) ) & 8272 THEN 7993 IF ( pindex > SIZE( grid_particles(k,j,i)%particles ) ) THEN 8273 7994 CALL realloc_particles_array( i, j, k ) 8274 7995 ENDIF … … 8290 8011 8291 8012 END SUBROUTINE lpm_move_particle 8292 8293 8294 !------------------------------------------------------------------------------ !8013 8014 8015 !--------------------------------------------------------------------------------------------------! 8295 8016 ! Description: 8296 8017 ! ------------ 8297 !> Check CFL-criterion for each particle. If one particle violated the 8298 !> criterion the particle willbe deleted and a warning message is given.8299 !------------------------------------------------------------------------------ !8300 SUBROUTINE lpm_check_cfl 8018 !> Check CFL-criterion for each particle. If one particle violated the criterion the particle will 8019 !> be deleted and a warning message is given. 8020 !--------------------------------------------------------------------------------------------------! 8021 SUBROUTINE lpm_check_cfl 8301 8022 8302 8023 IMPLICIT NONE … … 8312 8033 number_of_particles = prt_count(k,j,i) 8313 8034 IF ( number_of_particles <= 0 ) CYCLE 8314 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 8035 particles => grid_particles(k,j,i)%particles(1:number_of_particles) 8315 8036 DO n = 1, number_of_particles 8316 8037 ! 8317 !-- Note, check for CFL does not work at first particle timestep 8318 !-- when both, age and age_m are zero.8038 !-- Note, check for CFL does not work at first particle timestep when both, age and 8039 !-- age_m are zero. 8319 8040 IF ( particles(n)%age - particles(n)%age_m > 0.0_wp ) THEN 8320 IF( ABS( particles(n)%speed_x ) > &8321 ( dx / ( particles(n)%age - particles(n)%age_m) ) .OR.&8322 ABS( particles(n)%speed_y ) > &8323 ( dy / ( particles(n)%age - particles(n)%age_m) ) .OR.&8324 ABS( particles(n)%speed_z ) > &8325 ( ( zw(k)-zw(k-1) )&8326 / ( particles(n)%age - particles(n)%age_m) ) )THEN8327 WRITE( message_string, * ) &8328 'Particle violated CFL-criterion: &particle with id ', &8329 particles(n)%id, ' will be deleted!'8041 IF( ABS( particles(n)%speed_x ) > & 8042 ( dx / ( particles(n)%age - particles(n)%age_m) ) .OR. & 8043 ABS( particles(n)%speed_y ) > & 8044 ( dy / ( particles(n)%age - particles(n)%age_m) ) .OR. & 8045 ABS( particles(n)%speed_z ) > & 8046 ( ( zw(k)-zw(k-1) ) / ( particles(n)%age - particles(n)%age_m) ) ) & 8047 THEN 8048 WRITE( message_string, * ) & 8049 'Particle violated CFL-criterion: &particle with id ', particles(n)%id, & 8050 ' will be deleted!' 8330 8051 CALL message( 'lpm_check_cfl', 'PA0475', 0, 1, -1, 6, 0 ) 8331 8052 … … 8336 8057 ENDDO 8337 8058 ENDDO 8338 ENDDO 8059 ENDDO 8339 8060 8340 8061 END SUBROUTINE lpm_check_cfl 8341 8342 8343 !------------------------------------------------------------------------------ !8062 8063 8064 !--------------------------------------------------------------------------------------------------! 8344 8065 ! Description: 8345 8066 ! ------------ 8346 !> If the allocated memory for the particle array do not suffice to add arriving8347 !> particles from neighbour grid cells, this subrouting reallocates the8348 !> particle array to assure enough memory is available.8349 !------------------------------------------------------------------------------ !8067 !> If the allocated memory for the particle array does not suffice to add arriving particles from 8068 !> neighbour grid cells, this subrouting reallocates the particle array to assure enough memory is 8069 !> available. 8070 !--------------------------------------------------------------------------------------------------! 8350 8071 SUBROUTINE realloc_particles_array ( i, j, k, size_in ) 8351 8072 … … 8355 8076 INTEGER(iwp), INTENT(IN), OPTIONAL :: size_in !< 8356 8077 8078 INTEGER(iwp) :: new_size !< 8357 8079 INTEGER(iwp) :: old_size !< 8358 INTEGER(iwp) :: new_size !<8359 8080 TYPE(particle_type), DIMENSION(:), ALLOCATABLE :: tmp_particles_d !< 8360 8081 TYPE(particle_type), DIMENSION(500) :: tmp_particles_s !< 8361 8082 8362 old_size = SIZE( grid_particles(k,j,i)%particles)8363 8364 IF ( PRESENT( size_in) )THEN8083 old_size = SIZE( grid_particles(k,j,i)%particles ) 8084 8085 IF ( PRESENT( size_in) ) THEN 8365 8086 new_size = size_in 8366 8087 ELSE … … 8397 8118 8398 8119 RETURN 8399 8120 8400 8121 END SUBROUTINE realloc_particles_array 8401 8402 8403 !------------------------------------------------------------------------------ !8122 8123 8124 !--------------------------------------------------------------------------------------------------! 8404 8125 ! Description: 8405 8126 ! ------------ 8406 !> Not needed but allocated space for particles is dealloced. 8407 !------------------------------------------------------------------------------ !8127 !> Not needed but allocated space for particles is dealloced. 8128 !--------------------------------------------------------------------------------------------------! 8408 8129 SUBROUTINE dealloc_particles_array 8409 8130 8410 8131 8411 8132 INTEGER(iwp) :: i !< 8412 8133 INTEGER(iwp) :: j !< … … 8431 8152 ! 8432 8153 !-- Check for large unused memory 8433 dealloc = ( ( number_of_particles < 1 .AND. &8434 old_size > 1 ) .OR.&8435 ( number_of_particles > 1 .AND.&8436 old_size - number_of_particles *&8437 ( 1.0_wp + 0.01_wp * alloc_factor ) > 0.0_wp ))8154 dealloc = ( ( number_of_particles < 1 .AND. old_size > 1 ) .OR. & 8155 ( number_of_particles > 1 .AND. & 8156 old_size - number_of_particles * ( 1.0_wp + 0.01_wp * alloc_factor ) & 8157 > 0.0_wp ) & 8158 ) 8438 8159 8439 8160 IF ( dealloc ) THEN 8440 8161 IF ( number_of_particles < 1 ) THEN 8441 8162 new_size = 1 8442 ELSE 8163 ELSE 8443 8164 new_size = INT( number_of_particles * ( 1.0_wp + 0.01_wp * alloc_factor ) ) 8444 8165 ENDIF … … 8474 8195 ENDDO 8475 8196 8476 END SUBROUTINE dealloc_particles_array 8477 8478 8479 !------------------------------------------------------------------------------ !8197 END SUBROUTINE dealloc_particles_array 8198 8199 8200 !--------------------------------------------------------------------------------------------------! 8480 8201 ! Description: 8481 8202 ! ----------- 8482 !> Routine for the whole processor 8483 !> Sort all particles into the 8 respective subgrid boxes (in case of trilinear 8484 !> interpolation method) and free space of particles which has been marked for 8485 !> deletion. 8486 !------------------------------------------------------------------------------! 8203 !> Routine for the whole processor. 8204 !> Sort all particles into the 8 respective subgrid boxes (in case of trilinear interpolation 8205 !> method) and free space of particles which has been marked for deletion. 8206 !--------------------------------------------------------------------------------------------------! 8487 8207 SUBROUTINE lpm_sort_and_delete 8488 8208 … … 8520 8240 nn = nn + 1 8521 8241 ! 8522 !-- Sorting particles with a binary scheme 8242 !-- Sorting particles with a binary scheme. 8523 8243 !-- sort_index=111_2=7_10 -> particle at the left,south,bottom subgridbox 8524 8244 !-- sort_index=000_2=0_10 -> particle at the right,north,top subgridbox 8525 !-- For this the center of the gridbox is calculated 8245 !-- For this the center of the gridbox is calculated. 8526 8246 i = (particles(n)%x + 0.5_wp * dx) * ddx 8527 8247 j = (particles(n)%y + 0.5_wp * dy) * ddy … … 8538 8258 ENDDO 8539 8259 ! 8540 !-- Delete and resort particles by overwritting and set 8541 !-- the number_of_particles to theactual value.8260 !-- Delete and resort particles by overwritting and set the number_of_particles to 8261 !-- the actual value. 8542 8262 nn = 0 8543 8263 DO is = 0,7 … … 8557 8277 ENDDO 8558 8278 8559 !-- In case of the simple interpolation method the particles must not 8560 !-- be sorted in subboxes. Particles marked for deletion however, must be 8561 !-- deleted and number of particles must be recalculated as it is also 8562 !-- done for the trilinear particle advection interpolation method. 8279 !-- In case of the simple interpolation method the particles must not be sorted in subboxes. 8280 !-- Particles marked for deletion however, must be deleted and number of particles must be 8281 !-- recalculated as it is also done for the trilinear particle advection interpolation method. 8563 8282 ELSE 8564 8283 … … 8571 8290 particles => grid_particles(kp,jp,ip)%particles(1:number_of_particles) 8572 8291 ! 8573 !-- Repack particles array, i.e. delete particles and recalculate 8574 !-- number of particles 8292 !-- Repack particles array, i.e. delete particles and recalculate number of particles 8575 8293 CALL lpm_pack 8576 8294 prt_count(kp,jp,ip) = number_of_particles … … 8583 8301 END SUBROUTINE lpm_sort_and_delete 8584 8302 8585 8586 !------------------------------------------------------------------------------ !8303 8304 !--------------------------------------------------------------------------------------------------! 8587 8305 ! Description: 8588 8306 ! ------------ 8589 8307 !> Move all particles not marked for deletion to lowest indices (packing) 8590 !------------------------------------------------------------------------------ !8308 !--------------------------------------------------------------------------------------------------! 8591 8309 SUBROUTINE lpm_pack 8592 8310 … … 8594 8312 INTEGER(iwp) :: nn !< 8595 8313 ! 8596 !-- Find out elements marked for deletion and move data from highest index 8597 !-- values to these freeindices8314 !-- Find out elements marked for deletion and move data from highest index values to these free 8315 !-- indices 8598 8316 nn = number_of_particles 8599 8317 … … 8618 8336 8619 8337 ! 8620 !-- The number of deleted particles has been determined in routines 8621 !-- lpm_ boundary_conds, lpm_droplet_collision, and lpm_exchange_horiz8338 !-- The number of deleted particles has been determined in routines lpm_boundary_conds, 8339 !-- lpm_droplet_collision, and lpm_exchange_horiz 8622 8340 number_of_particles = nn 8623 8341 8624 END SUBROUTINE lpm_pack 8625 8626 8627 !------------------------------------------------------------------------------ !8342 END SUBROUTINE lpm_pack 8343 8344 8345 !--------------------------------------------------------------------------------------------------! 8628 8346 ! Description: 8629 8347 ! ------------ 8630 !> Sort particles in each sub-grid box into two groups: particles that already 8631 !> completed the LES timestep, and particles that need further timestepping to 8632 !> complete the LES timestep. 8633 !------------------------------------------------------------------------------! 8348 !> Sort particles in each sub-grid box into two groups: particles that already completed the LES 8349 !> timestep, and particles that need further timestepping to complete the LES timestep. 8350 !--------------------------------------------------------------------------------------------------! 8634 8351 SUBROUTINE lpm_sort_timeloop_done 8635 8352 … … 8661 8378 end_index = grid_particles(k,j,i)%end_index(nb) 8662 8379 ! 8663 !-- Allocate temporary array used for sorting. 8380 !-- Allocate temporary array used for sorting. 8664 8381 ALLOCATE( sort_particles(start_index:end_index) ) 8665 8382 ! 8666 !-- Determine number of particles already completed the LES 8667 !-- timestep, and write them into a temporary array.8383 !-- Determine number of particles already completed the LES timestep, and write them 8384 !-- into a temporary array. 8668 8385 nf = start_index 8669 8386 num_finalized = 0 … … 8676 8393 ENDDO 8677 8394 ! 8678 !-- Determine number of particles that not completed the LES 8679 !-- timestep, and write them into a temporary array.8395 !-- Determine number of particles that not completed the LES timestep, and write them 8396 !-- into a temporary array. 8680 8397 nnf = nf 8681 8398 DO n = start_index, end_index … … 8687 8404 ! 8688 8405 !-- Write back sorted particles 8689 particles(start_index:end_index) = & 8690 sort_particles(start_index:end_index) 8691 ! 8692 !-- Determine updated start_index, used to masked already 8693 !-- completed particles. 8694 grid_particles(k,j,i)%start_index(nb) = & 8695 grid_particles(k,j,i)%start_index(nb) & 8696 + num_finalized 8406 particles(start_index:end_index) = sort_particles(start_index:end_index) 8407 ! 8408 !-- Determine updated start_index, used to masked already 8409 !-- completed particles. 8410 grid_particles(k,j,i)%start_index(nb) = grid_particles(k,j,i)%start_index(nb) & 8411 + num_finalized 8697 8412 ! 8698 8413 !-- Deallocate dummy array 8699 8414 DEALLOCATE ( sort_particles ) 8700 8415 ! 8701 !-- Finally, if number of non-completed particles is non zero 8702 !-- in any of the sub-boxes, set control flag appropriately. 8703 IF ( nnf > nf ) & 8704 grid_particles(k,j,i)%time_loop_done = .FALSE. 8416 !-- Finally, if number of non-completed particles is non zero 8417 !-- in any of the sub-boxes, set control flag appropriately. 8418 IF ( nnf > nf ) grid_particles(k,j,i)%time_loop_done = .FALSE. 8705 8419 8706 8420 ENDDO … … 8709 8423 ENDDO 8710 8424 8711 END SUBROUTINE lpm_sort_timeloop_done 8425 END SUBROUTINE lpm_sort_timeloop_done 8712 8426 8713 8427 END MODULE lagrangian_particle_model_mod
Note: See TracChangeset
for help on using the changeset viewer.