Changeset 3866
- Timestamp:
- Apr 5, 2019 2:25:01 PM (6 years ago)
- Location:
- palm/trunk/UTIL
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified palm/trunk/UTIL/Makefile_utilities ¶
r3795 r3866 23 23 # ----------------- 24 24 # $Id$ 25 # Use PALM's kinds module in inifor 26 # 27 # 28 # 3795 2019-03-15 09:40:05Z eckhard 25 29 # Upated inifor build dependencies 26 30 # … … 141 145 inifor_defs.o \ 142 146 inifor_util.o 147 inifor_defs.o: \ 148 mod_kinds.o 143 149 inifor_grid.o: \ 144 150 inifor_control.o \ -
TabularUnified palm/trunk/UTIL/inifor/src/inifor.f90 ¶
r3785 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! Show error message if compiled without netCDF support 30 ! Renamed run_control -> log_runtime 31 ! Improved coding style added comments 32 ! 33 ! 34 ! 3785 2019-03-06 10:41:14Z eckhard 28 35 ! Average geostrophic wind components on coarse COSMO levels instead of fine PALM levels 29 36 ! Remove --debug netCDF output of internal pressure profiles … … 81 88 !------------------------------------------------------------------------------! 82 89 PROGRAM inifor 90 83 91 #if defined ( __netcdf ) 84 92 … … 86 94 USE inifor_defs 87 95 USE inifor_grid, & 88 ONLY: setup_parameters, setup_grids, setup_variable_tables, & 89 setup_io_groups, fini_grids, fini_variables, fini_io_groups, & 90 fini_file_lists, preprocess, origin_lon, origin_lat, & 91 output_file, io_group_list, output_var_table, & 92 cosmo_grid, palm_grid, nx, ny, nz, p0, cfg, f3, & 93 averaging_width_ns, averaging_width_ew, phi_n, lambda_n, & 94 lam_centre, phi_centre 96 ONLY: averaging_width_ns, & 97 averaging_width_ew, & 98 cfg, & 99 cosmo_grid, & 100 f3, & 101 fini_grids, & 102 fini_io_groups, & 103 fini_variables, & 104 fini_file_lists, & 105 io_group_list, & 106 lam_centre, & 107 lambda_n, & 108 nx, ny, nz, & 109 origin_lat, & 110 origin_lon, & 111 output_file, & 112 output_var_table, & 113 p0, & 114 phi_centre, & 115 phi_n, & 116 preprocess, & 117 palm_grid, & 118 setup_grids, & 119 setup_parameters, & 120 setup_variable_tables, & 121 setup_io_groups 95 122 USE inifor_io 96 123 USE inifor_transform, & 97 ONLY: average_pressure_perturbation, average_profile, interpolate_1d, & 98 interpolate_1d_arr, interpolate_2d, interpolate_3d, & 99 interp_average_profile, geostrophic_winds, extrapolate_density, & 100 extrapolate_pressure, get_surface_pressure 124 ONLY: average_pressure_perturbation, & 125 average_profile, & 126 extrapolate_density, & 127 extrapolate_pressure, & 128 geostrophic_winds, & 129 get_surface_pressure, & 130 interp_average_profile, & 131 interpolate_1d, & 132 interpolate_1d_arr, & 133 interpolate_2d, & 134 interpolate_3d 101 135 USE inifor_types 102 136 … … 107 141 INTEGER :: iter !< loop index for time steps 108 142 109 REAL( dp), ALLOCATABLE, DIMENSION(:,:,:) :: output_arr !< array buffer for interpolated quantities110 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_centre !< density profile of the centre averaging domain111 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: ug_cosmo !< profile of the geostrophic wind in x direction on COSMO levels112 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: vg_cosmo !< profile of the geostrophic wind in y direction on COSMO levels113 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: ug_palm !< profile of the geostrophic wind in x direction interpolated onto PALM levels114 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: vg_palm !< profile of the geostrophic wind in y direction interpolated onto PALM levels115 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_north !< density profile of the northern averaging domain116 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_south !< density profile of the southern averaging domain117 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_east !< density profile of the eastern averaging domain118 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_west !< density profile of the western averaging domain119 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: p_north !< pressure profile of the northern averaging domain120 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: p_south !< pressure profile of the southern averaging domain121 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: p_east !< pressure profile of the eastern averaging domain122 REAL( dp), ALLOCATABLE, DIMENSION(:), TARGET :: p_west !< pressure profile of the western averaging domain123 124 REAL( dp), POINTER, DIMENSION(:) :: internal_arr !< pointer to the currently processed internal array (density, pressure)125 REAL( dp), POINTER, DIMENSION(:) :: ug_vg_palm !< pointer to the currently processed geostrophic wind component143 REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) :: output_arr !< array buffer for interpolated quantities 144 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_centre !< density profile of the centre averaging domain 145 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: ug_cosmo !< profile of the geostrophic wind in x direction on COSMO levels 146 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: vg_cosmo !< profile of the geostrophic wind in y direction on COSMO levels 147 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: ug_palm !< profile of the geostrophic wind in x direction interpolated onto PALM levels 148 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: vg_palm !< profile of the geostrophic wind in y direction interpolated onto PALM levels 149 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_north !< density profile of the northern averaging domain 150 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_south !< density profile of the southern averaging domain 151 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_east !< density profile of the eastern averaging domain 152 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: rho_west !< density profile of the western averaging domain 153 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: p_north !< pressure profile of the northern averaging domain 154 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: p_south !< pressure profile of the southern averaging domain 155 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: p_east !< pressure profile of the eastern averaging domain 156 REAL(wp), ALLOCATABLE, DIMENSION(:), TARGET :: p_west !< pressure profile of the western averaging domain 157 158 REAL(wp), POINTER, DIMENSION(:) :: internal_arr !< pointer to the currently processed internal array (density, pressure) 159 REAL(wp), POINTER, DIMENSION(:) :: ug_vg_palm !< pointer to the currently processed geostrophic wind component 126 160 127 161 TYPE(nc_var), POINTER :: output_var !< pointer to the currently processed output variable … … 138 172 !- Section 1: Initialization 139 173 !------------------------------------------------------------------------------ 140 CALL run_control('init', 'void')174 CALL log_runtime( 'init', 'void' ) 141 175 142 176 ! 143 177 !-- Initialize INIFOR's parameters from command-line interface and namelists 144 CALL setup_parameters ()178 CALL setup_parameters 145 179 146 180 ! 147 181 !-- Initialize all grids, including interpolation neighbours and weights 148 CALL setup_grids ()149 CALL run_control('time', 'init')182 CALL setup_grids 183 CALL log_runtime( 'time', 'init' ) 150 184 151 185 ! 152 186 !-- Initialize the netCDF output file and define dimensions 153 CALL setup_netcdf_dimensions(output_file, palm_grid, cfg %start_date, &187 CALL setup_netcdf_dimensions(output_file, palm_grid, cfg%start_date, & 154 188 origin_lon, origin_lat) 155 CALL run_control('time', 'write')189 CALL log_runtime( 'time', 'write' ) 156 190 157 191 ! 158 192 !-- Set up the tables containing the input and output variables and set 159 193 !-- the corresponding netCDF dimensions for each output variable 160 CALL setup_variable_tables( cfg % ic_mode)161 CALL run_control('time', 'write')194 CALL setup_variable_tables( cfg%ic_mode ) 195 CALL log_runtime( 'time', 'write' ) 162 196 163 197 ! 164 198 !-- Add the output variables to the netCDF output file 165 CALL setup_netcdf_variables(output_file % name, output_var_table) 166 167 CALL setup_io_groups() 168 CALL run_control('time', 'init') 169 170 !------------------------------------------------------------------------------ 171 !- Section 2: Main loop 172 !------------------------------------------------------------------------------ 173 DO igroup = 1, SIZE(io_group_list) 199 CALL setup_netcdf_variables( output_file%name, output_var_table ) 200 201 CALL setup_io_groups 202 CALL log_runtime( 'time', 'init' ) 203 204 !------------------------------------------------------------------------------ 205 !-- Section 2: Main loop 206 !------------------------------------------------------------------------------ 207 ! 208 !-- Input and output variables are organized into IO groups. For instance, the 209 !-- 'thermodynamics' IO group bundles the input variaebls T, P, QV and the 210 !-- output variables p, theta, rho, and qv. 211 !-- An IO group bunldes variables that are physically dependent on each other. 212 !-- In case of the 'thermodynamics' group, theta = f(P,T), rho = f(P,T,QV). 213 DO igroup = 1, SIZE( io_group_list ) 174 214 175 215 group => io_group_list(igroup) 176 IF ( group %to_be_processed ) THEN216 IF ( group%to_be_processed ) THEN 177 217 178 DO iter = 1, group % nt 179 180 !------------------------------------------------------------------------------ 181 !- Section 2.1: Read and preprocess input data 182 !------------------------------------------------------------------------------ 183 CALL read_input_variables(group, iter, input_buffer) 184 CALL run_control('time', 'read') 185 186 CALL preprocess(group, input_buffer, cosmo_grid, iter) 187 CALL run_control('time', 'comp') 218 !-- Loop over all output time steps for the current group. 219 DO iter = 1, group%nt 220 221 !------------------------------------------------------------------------------ 222 !-- Section 2.1: Read and preprocess input data 223 !------------------------------------------------------------------------------ 224 CALL read_input_variables( group, iter, input_buffer ) 225 CALL log_runtime( 'time', 'read' ) 226 227 !-- Carry out all required physical conversion of the input variables 228 !-- of the current IO group on the input (COSMO) grid. For instance, 229 !-- horizontal velocities are rotated to the PALM coordinate system and 230 !-- potential temperature is computed from the absolute temperature and 231 !-- pressure. 232 CALL preprocess( group, input_buffer, cosmo_grid, iter ) 233 CALL log_runtime( 'time', 'comp' ) 188 234 189 235 !TODO: move this assertion into 'preprocess'. 190 IF ( .NOT. ALL(input_buffer(:) %is_preprocessed .AND. .TRUE.) ) THEN191 message = "Input buffers for group '" // TRIM( group % kind) // &192 "' could not be preprocessed sucessfully."193 CALL inifor_abort( 'main loop', message)236 IF ( .NOT. ALL(input_buffer(:)%is_preprocessed .AND. .TRUE.) ) THEN 237 message = "Input buffers for group '" // TRIM( group%kind ) // & 238 "' could not be preprocessed sucessfully." 239 CALL inifor_abort( 'main loop', message ) 194 240 ENDIF 195 241 196 242 !------------------------------------------------------------------------------ 197 !- Section 2.2: Interpolate each output variable of the group 198 !------------------------------------------------------------------------------ 199 DO ivar = 1, group % nv 200 201 output_var => group % out_vars( ivar ) 202 203 IF ( output_var % to_be_processed .AND. & 204 iter .LE. output_var % nt ) THEN 205 206 message = "Processing '" // TRIM(output_var % name) // & 207 "' (" // TRIM(output_var % kind) // & 208 "), iteration " // TRIM(str(iter)) //" of " // & 209 TRIM(str(output_var % nt)) 210 CALL report('main loop', message) 211 212 SELECT CASE( TRIM(output_var % task) ) 213 214 CASE( 'interpolate_2d' ) 215 216 SELECT CASE( TRIM(output_var % kind) ) 217 218 CASE( 'init soil' ) 219 220 ALLOCATE( output_arr( 0:output_var % grid % nx, & 221 0:output_var % grid % ny, & 222 SIZE(output_var % grid % depths) ) ) 223 224 CASE ( 'surface forcing' ) 225 226 ALLOCATE( output_arr( 0:output_var % grid % nx, & 227 0:output_var % grid % ny, 1 ) ) 228 229 CASE DEFAULT 230 231 message = "'" // TRIM(output_var % kind) // "' is not a soil variable" 232 CALL inifor_abort("main loop", message) 233 234 END SELECT 235 CALL run_control('time', 'alloc') 236 237 CALL interpolate_2d(input_buffer(output_var % input_id) % array(:,:,:), & 238 output_arr(:,:,:), output_var % intermediate_grid, output_var) 239 CALL run_control('time', 'comp') 240 241 242 CASE ( 'interpolate_3d' ) 243 244 ALLOCATE( output_arr( 0:output_var % grid % nx, & 245 0:output_var % grid % ny, & 246 1:output_var % grid % nz ) ) 247 248 CALL run_control('time', 'alloc') 249 CALL interpolate_3d( & 250 input_buffer(output_var % input_id) % array(:,:,:), & 251 output_arr(:,:,:), & 252 output_var % intermediate_grid, & 253 output_var % grid) 254 CALL run_control('time', 'comp') 255 256 CASE ( 'average profile' ) 257 258 ALLOCATE( output_arr( 0:output_var % grid % nx, & 259 0:output_var % grid % ny, & 260 1:output_var % grid % nz ) ) 261 CALL run_control('time', 'alloc') 243 !-- Section 2.2: Interpolate each output variable of the group 244 !------------------------------------------------------------------------------ 245 DO ivar = 1, group%nv 246 247 output_var => group%out_vars(ivar) 248 249 IF ( output_var%to_be_processed .AND. & 250 iter .LE. output_var%nt ) THEN 251 252 message = "Processing '" // TRIM( output_var%name ) // & 253 "' (" // TRIM( output_var%kind ) // & 254 "), iteration " // TRIM( str( iter ) ) //" of " //& 255 TRIM( str( output_var%nt ) ) 256 CALL report( 'main loop', message ) 257 258 SELECT CASE( TRIM( output_var%task ) ) 259 260 !-- 2D horizontal interpolation 261 CASE( 'interpolate_2d' ) 262 262 263 CALL interp_average_profile( & 264 input_buffer(output_var % input_id) % array(:,:,:), & 265 output_arr(0,0,:), & 266 output_var % averaging_grid) 267 268 IF ( TRIM(output_var % name) == & 269 'surface_forcing_surface_pressure' ) THEN 270 271 IF ( cfg % p0_is_set ) THEN 272 output_arr(0,0,1) = p0 273 ELSE 274 CALL get_surface_pressure( & 275 output_arr(0,0,:), rho_centre, & 276 output_var % averaging_grid) 263 SELECT CASE( TRIM( output_var%kind ) ) 264 265 CASE( 'init soil' ) 266 267 ALLOCATE( output_arr(0:output_var%grid%nx, & 268 0:output_var%grid%ny, & 269 SIZE( output_var%grid%depths )) ) 270 271 CASE ( 'surface forcing' ) 272 273 ALLOCATE( output_arr(0:output_var%grid%nx, & 274 0:output_var%grid%ny, 1) ) 275 276 CASE DEFAULT 277 278 message = "'" // TRIM( output_var%kind ) // "' is not a soil variable" 279 CALL inifor_abort( "main loop", message ) 280 281 END SELECT 282 CALL log_runtime( 'time', 'alloc' ) 283 284 CALL interpolate_2d( input_buffer(output_var%input_id)%array(:,:,:), & 285 output_arr(:,:,:), output_var%intermediate_grid, output_var ) 286 CALL log_runtime( 'time', 'comp' ) 287 288 289 !-- Interpolation in 3D, used for atmospheric initial and 290 !-- boundary conditions. 291 CASE ( 'interpolate_3d' ) 292 293 ALLOCATE( output_arr(0:output_var%grid % nx, & 294 0:output_var%grid % ny, & 295 1:output_var%grid % nz) ) 296 297 CALL log_runtime( 'time', 'alloc' ) 298 CALL interpolate_3d( & 299 input_buffer(output_var%input_id)%array(:,:,:), & 300 output_arr(:,:,:), & 301 output_var%intermediate_grid, & 302 output_var%grid) 303 CALL log_runtime( 'time', 'comp' ) 304 305 !-- Compute initial avaerage profiles (if --init-mode profile 306 !-- is used) 307 CASE ( 'average profile' ) 308 309 ALLOCATE( output_arr(0:output_var%grid%nx, & 310 0:output_var%grid%ny, & 311 1:output_var%grid%nz) ) 312 CALL log_runtime( 'time', 'alloc' ) 313 314 CALL interp_average_profile( & 315 input_buffer(output_var%input_id)%array(:,:,:), & 316 output_arr(0,0,:), & 317 output_var%averaging_grid ) 318 319 IF ( TRIM( output_var%name ) == & 320 'surface_forcing_surface_pressure' ) THEN 321 322 IF ( cfg%p0_is_set ) THEN 323 output_arr(0,0,1) = p0 324 ELSE 325 CALL get_surface_pressure( & 326 output_arr(0,0,:), rho_centre, & 327 output_var%averaging_grid ) 328 ENDIF 329 277 330 ENDIF 278 279 ENDIF280 CALL run_control('time', 'comp') 281 282 CASE ( 'internal profile' )283 284 message = "Averaging of internal profile for variable '" //&285 TRIM(output_var % name) // "' is not supported."286 287 SELECT CASE (TRIM(output_var % name))288 289 CASE('internal_density_centre')290 ALLOCATE( rho_centre( 1:cosmo_grid %nz) )291 internal_arr => rho_centre292 293 CASE('internal_density_north')294 ALLOCATE( rho_north( 1:cosmo_grid %nz) )295 internal_arr => rho_north296 297 CASE('internal_density_south')298 ALLOCATE( rho_south( 1:cosmo_grid %nz) )299 internal_arr => rho_south300 301 CASE('internal_density_east')302 ALLOCATE( rho_east( 1:cosmo_grid %nz) )303 internal_arr => rho_east304 305 CASE('internal_density_west')306 ALLOCATE( rho_west( 1:cosmo_grid %nz) )307 internal_arr => rho_west308 309 CASE('internal_pressure_north')310 ALLOCATE( p_north( 1:cosmo_grid %nz) )311 internal_arr => p_north312 313 CASE('internal_pressure_south')314 ALLOCATE( p_south( 1:cosmo_grid %nz) )315 internal_arr => p_south316 317 CASE('internal_pressure_east')318 ALLOCATE( p_east( 1:cosmo_grid %nz) )319 internal_arr => p_east320 321 CASE('internal_pressure_west')322 ALLOCATE( p_west( 1:cosmo_grid %nz) )323 internal_arr => p_west324 325 CASE DEFAULT326 CALL inifor_abort('main loop', message)327 328 END SELECT329 CALL run_control('time', 'alloc')330 331 332 SELECT CASE( TRIM( output_var %name ) )333 334 CASE( 'internal_pressure_north', &335 'internal_pressure_south', &336 'internal_pressure_east', &337 'internal_pressure_west' )338 339 CALL average_pressure_perturbation( &340 input_buffer(output_var %input_id) % array(:,:,:),&341 internal_arr(:), &342 cosmo_grid, output_var %averaging_grid &343 )344 345 CASE DEFAULT346 347 CALL average_profile( &348 input_buffer(output_var %input_id) % array(:,:,:),&349 internal_arr(:), &350 output_var %averaging_grid &351 )331 CALL log_runtime( 'time', 'comp' ) 332 333 !-- Compute internal profiles, required for differentiation of 334 !-- geostrophic wind 335 CASE ( 'internal profile' ) 336 337 message = "Averaging of internal profile for variable '" //& 338 TRIM( output_var%name ) // "' is not supported." 339 340 SELECT CASE ( TRIM( output_var%name ) ) 341 342 CASE( 'internal_density_centre' ) 343 ALLOCATE( rho_centre(1:cosmo_grid%nz) ) 344 internal_arr => rho_centre 345 346 CASE( 'internal_density_north' ) 347 ALLOCATE( rho_north(1:cosmo_grid%nz) ) 348 internal_arr => rho_north 349 350 CASE( 'internal_density_south' ) 351 ALLOCATE( rho_south(1:cosmo_grid%nz) ) 352 internal_arr => rho_south 353 354 CASE( 'internal_density_east' ) 355 ALLOCATE( rho_east(1:cosmo_grid%nz) ) 356 internal_arr => rho_east 357 358 CASE( 'internal_density_west' ) 359 ALLOCATE( rho_west(1:cosmo_grid%nz) ) 360 internal_arr => rho_west 361 362 CASE( 'internal_pressure_north' ) 363 ALLOCATE( p_north(1:cosmo_grid%nz) ) 364 internal_arr => p_north 365 366 CASE( 'internal_pressure_south' ) 367 ALLOCATE( p_south(1:cosmo_grid%nz) ) 368 internal_arr => p_south 369 370 CASE( 'internal_pressure_east' ) 371 ALLOCATE( p_east(1:cosmo_grid%nz) ) 372 internal_arr => p_east 373 374 CASE( 'internal_pressure_west' ) 375 ALLOCATE( p_west(1:cosmo_grid%nz) ) 376 internal_arr => p_west 377 378 CASE DEFAULT 379 CALL inifor_abort( 'main loop', message ) 380 381 END SELECT 382 CALL log_runtime( 'time', 'alloc' ) 383 384 385 SELECT CASE( TRIM( output_var%name ) ) 386 387 CASE( 'internal_pressure_north', & 388 'internal_pressure_south', & 389 'internal_pressure_east', & 390 'internal_pressure_west' ) 391 392 CALL average_pressure_perturbation( & 393 input_buffer(output_var%input_id) % array(:,:,:),& 394 internal_arr(:), & 395 cosmo_grid, output_var%averaging_grid & 396 ) 397 398 CASE DEFAULT 399 400 CALL average_profile( & 401 input_buffer(output_var%input_id) % array(:,:,:),& 402 internal_arr(:), & 403 output_var%averaging_grid & 404 ) 352 405 353 406 END SELECT … … 360 413 !-- (requires definiton of COSMO levels in netCDF output.) 361 414 !IF (.TRUE.) THEN 362 ! ALLOCATE( output_arr(1,1,1:output_var %grid % nz) )415 ! ALLOCATE( output_arr(1,1,1:output_var%grid % nz) ) 363 416 ! output_arr(1,1,:) = internal_arr(:) 364 417 !ENDIF 365 CALL run_control('time', 'comp')418 CALL log_runtime( 'time', 'comp' ) 366 419 367 420 ! … … 372 425 373 426 IF (.NOT. ug_vg_have_been_computed ) THEN 374 ALLOCATE( ug_palm(output_var % grid %nz) )375 ALLOCATE( vg_palm(output_var % grid %nz) )376 ALLOCATE( ug_cosmo(cosmo_grid %nz) )377 ALLOCATE( vg_cosmo(cosmo_grid %nz) )378 379 IF ( cfg %ug_defined_by_user ) THEN380 ug_palm = cfg %ug381 vg_palm = cfg %vg427 ALLOCATE( ug_palm(output_var%grid%nz) ) 428 ALLOCATE( vg_palm(output_var%grid%nz) ) 429 ALLOCATE( ug_cosmo(cosmo_grid%nz) ) 430 ALLOCATE( vg_cosmo(cosmo_grid%nz) ) 431 432 IF ( cfg%ug_defined_by_user ) THEN 433 ug_palm = cfg%ug 434 vg_palm = cfg%vg 382 435 ELSE 383 436 CALL geostrophic_winds( p_north, p_south, p_east, & … … 390 443 391 444 CALL interpolate_1d( ug_cosmo, ug_palm, & 392 output_var %grid )445 output_var%grid ) 393 446 394 447 CALL interpolate_1d( vg_cosmo, vg_palm, & 395 output_var %grid )448 output_var%grid ) 396 449 ENDIF 397 450 … … 402 455 ! 403 456 !-- Select output array of current geostrophic wind component 404 SELECT CASE( TRIM(output_var % name))405 CASE ( 'ls_forcing_ug')457 SELECT CASE( TRIM( output_var%name ) ) 458 CASE ( 'ls_forcing_ug' ) 406 459 ug_vg_palm => ug_palm 407 CASE ( 'ls_forcing_vg')460 CASE ( 'ls_forcing_vg' ) 408 461 ug_vg_palm => vg_palm 409 462 END SELECT 410 463 411 ALLOCATE( output_arr(1,1,output_var % grid %nz) )464 ALLOCATE( output_arr(1,1,output_var%grid%nz) ) 412 465 output_arr(1,1,:) = ug_vg_palm(:) 413 466 414 CASE ( 'average scalar' ) 415 416 ALLOCATE( output_arr(1,1,1) ) 417 CALL run_control('time', 'alloc') 418 output_arr(1,1,1) = p0 419 CALL run_control('time', 'comp') 420 467 !-- User defined constant profiles 421 468 CASE ( 'set profile' ) 422 469 423 ALLOCATE( output_arr( 1, 1, 1:nz) )424 CALL run_control('time', 'alloc')425 426 SELECT CASE ( TRIM(output_var % name))427 428 CASE ('nudging_tau')470 ALLOCATE( output_arr(1,1,1:nz) ) 471 CALL log_runtime( 'time', 'alloc' ) 472 473 SELECT CASE ( TRIM( output_var%name ) ) 474 475 CASE ( 'nudging_tau' ) 429 476 output_arr(1, 1, :) = NUDGING_TAU 430 477 431 478 CASE DEFAULT 432 message = "'" // TRIM( output_var % name) // &433 "' is not a valid '" // TRIM( output_var % kind) //&479 message = "'" // TRIM( output_var%name ) // & 480 "' is not a valid '" // TRIM( output_var%kind ) //& 434 481 "' variable kind." 435 CALL inifor_abort( 'main loop', message)482 CALL inifor_abort( 'main loop', message ) 436 483 END SELECT 437 CALL run_control('time', 'comp') 438 439 CASE('average large-scale profile') 440 message = "Averaging of large-scale forcing profiles " //& 441 "has not been implemented, yet." 442 CALL inifor_abort('main loop', message) 484 CALL log_runtime( 'time', 'comp' ) 443 485 444 486 CASE DEFAULT 445 message = "Processing task '" // TRIM( output_var % task) //&487 message = "Processing task '" // TRIM( output_var%task ) //& 446 488 "' not recognized." 447 CALL inifor_abort( '', message)489 CALL inifor_abort( '', message ) 448 490 449 491 END SELECT 450 CALL run_control('time', 'comp')492 CALL log_runtime( 'time', 'comp' ) 451 493 452 494 !------------------------------------------------------------------------------ … … 458 500 !-- defined on averaged COSMO levels instead of PALM levels 459 501 !-- (requires definiton of COSMO levels in netCDF output.) 460 !IF (.NOT. output_var %is_internal .OR. debugging_output) THEN461 462 IF ( .NOT. output_var % is_internal) THEN463 message = "Writing variable '" // TRIM( output_var%name) // "'."464 CALL report( 'main loop', message)465 CALL update_output( output_var, output_arr, iter,&466 output_file, cfg)467 CALL run_control('time', 'write')502 !IF (.NOT. output_var%is_internal .OR. debugging_output) THEN 503 504 IF ( .NOT. output_var%is_internal ) THEN 505 message = "Writing variable '" // TRIM( output_var%name ) // "'." 506 CALL report( 'main loop', message ) 507 CALL update_output( output_var, output_arr, iter, & 508 output_file, cfg ) 509 CALL log_runtime( 'time', 'write' ) 468 510 ENDIF 469 511 470 IF ( ALLOCATED(output_arr)) DEALLOCATE(output_arr)471 CALL run_control('time', 'alloc')512 IF ( ALLOCATED( output_arr ) ) DEALLOCATE( output_arr ) 513 CALL log_runtime( 'time', 'alloc' ) 472 514 473 515 ENDIF … … 478 520 479 521 ug_vg_have_been_computed = .FALSE. 480 IF ( group %kind == 'thermodynamics' ) THEN522 IF ( group%kind == 'thermodynamics' ) THEN 481 523 DEALLOCATE( rho_centre ) 482 524 DEALLOCATE( ug_palm ) … … 484 526 DEALLOCATE( ug_cosmo ) 485 527 DEALLOCATE( vg_cosmo ) 486 IF ( .NOT. cfg %ug_defined_by_user ) THEN528 IF ( .NOT. cfg%ug_defined_by_user ) THEN 487 529 DEALLOCATE( rho_north ) 488 530 DEALLOCATE( rho_south ) … … 499 541 !-- Keep input buffer around for averaged (radiation) and 500 542 !-- accumulated COSMO quantities (precipitation). 501 IF ( group %kind == 'running average' .OR. &502 group %kind == 'accumulated' ) THEN543 IF ( group%kind == 'running average' .OR. & 544 group%kind == 'accumulated' ) THEN 503 545 ELSE 504 CALL report( 'main loop', 'Deallocating input buffer', cfg % debug)505 DEALLOCATE( input_buffer)546 CALL report( 'main loop', 'Deallocating input buffer', cfg%debug ) 547 DEALLOCATE( input_buffer ) 506 548 ENDIF 507 CALL run_control('time', 'alloc')549 CALL log_runtime( 'time', 'alloc' ) 508 550 509 551 ! … … 511 553 ENDDO 512 554 513 IF ( ALLOCATED(input_buffer)) THEN514 CALL report( 'main loop', 'Deallocating input buffer', cfg % debug)515 DEALLOCATE( input_buffer)555 IF ( ALLOCATED( input_buffer ) ) THEN 556 CALL report( 'main loop', 'Deallocating input buffer', cfg%debug ) 557 DEALLOCATE( input_buffer ) 516 558 ENDIF 517 CALL run_control('time', 'alloc')559 CALL log_runtime( 'time', 'alloc' ) 518 560 519 561 ELSE 520 562 521 message = "Skipping IO group " // TRIM( str(igroup)) // " '" // TRIM(group % kind) // "'"522 IF ( ALLOCATED( group % in_var_list) ) THEN523 message = TRIM( message) // " with input variable '" //&524 TRIM( group % in_var_list(1) % name) // "'."563 message = "Skipping IO group " // TRIM( str( igroup ) ) // " '" // TRIM( group%kind ) // "'" 564 IF ( ALLOCATED( group%in_var_list ) ) THEN 565 message = TRIM( message ) // " with input variable '" // & 566 TRIM( group%in_var_list(1)%name ) // "'." 525 567 ENDIF 526 568 527 CALL report( 'main loop', message, cfg % debug)528 529 ! 530 !-- IO group %to_be_processed conditional569 CALL report( 'main loop', message, cfg%debug ) 570 571 ! 572 !-- IO group%to_be_processed conditional 531 573 ENDIF 532 574 … … 538 580 !- Section 3: Clean up. 539 581 !------------------------------------------------------------------------------ 540 CALL fini_file_lists ()541 CALL fini_io_groups ()542 CALL fini_variables ()543 !CALL fini_grids ()544 CALL run_control('time', 'alloc')545 CALL run_control('report', 'void')546 547 message = "Finished writing dynamic driver '" // TRIM( output_file % name) // &582 CALL fini_file_lists 583 CALL fini_io_groups 584 CALL fini_variables 585 !CALL fini_grids 586 CALL log_runtime( 'time', 'alloc' ) 587 CALL log_runtime( 'report', 'void' ) 588 589 message = "Finished writing dynamic driver '" // TRIM( output_file%name ) // & 548 590 "' successfully." 549 CALL report('main loop', message) 550 551 591 CALL report( 'main loop', message ) 592 CALL close_log 593 594 #else 595 596 USE inifor_control 597 IMPLICIT NONE 598 599 message = "INIFOR was compiled without netCDF support, which is required for it to run. " // & 600 "To use INIFOR, recompile PALM with netCDF support by adding the -D__netcdf " // & 601 "precompiler flag to your .palm.config file." 602 CALL inifor_abort( 'main loop', message ) 603 552 604 #endif 605 553 606 END PROGRAM inifor -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_control.f90 ¶
r3785 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! Renamed run_control -> log_runtime 30 ! Open log file only once 31 ! Improved coding style 32 ! 33 ! 34 ! 3785 2019-03-06 10:41:14Z eckhard 28 35 ! Added message buffer for displaying tips to rectify encountered errors 29 36 ! … … 66 73 !> feedback to the terminal and a log file. 67 74 !------------------------------------------------------------------------------! 68 #if defined ( __netcdf )69 75 MODULE inifor_control 70 76 71 77 USE inifor_defs, & 72 ONLY: LNAME, dp, VERSION, COPYRIGHT 73 78 ONLY: COPYRIGHT, LNAME, LOG_FILE_NAME, VERSION, wp 74 79 USE inifor_util, & 75 80 ONLY: real_to_str, real_to_str_f … … 79 84 CHARACTER (LEN=5000) :: message = '' !< log message buffer 80 85 CHARACTER (LEN=5000) :: tip = '' !< optional log message buffer for tips on how to rectify encountered errors 86 INTEGER, SAVE :: u !< Fortran file unit for the log file 81 87 82 88 CONTAINS … … 94 100 !> to it. 95 101 !------------------------------------------------------------------------------! 96 SUBROUTINE report(routine, message, debug) 97 98 CHARACTER(LEN=*), INTENT(IN) :: routine !< name of calling subroutine of function 99 CHARACTER(LEN=*), INTENT(IN) :: message !< log message 100 LOGICAL, OPTIONAL, INTENT(IN) :: debug !< flag the current message as debugging message 101 102 INTEGER :: u !< Fortran file unit for the log file 103 LOGICAL, SAVE :: is_first_run = .TRUE. !< control flag for file opening mode 104 LOGICAL :: suppress_message !< control falg for additional debugging log 105 106 107 IF ( is_first_run ) THEN 108 OPEN( NEWUNIT=u, FILE='inifor.log', STATUS='replace' ) 109 is_first_run = .FALSE. 110 ELSE 111 OPEN( NEWUNIT=u, FILE='inifor.log', POSITION='append', STATUS='old' ) 112 ENDIF 113 114 115 suppress_message = .FALSE. 116 IF ( PRESENT(debug) ) THEN 117 IF ( .NOT. debug ) suppress_message = .TRUE. 118 ENDIF 119 120 IF ( .NOT. suppress_message ) THEN 121 PRINT *, "inifor: " // TRIM(message) // " [ " // TRIM(routine) // " ]" 122 WRITE(u, *) TRIM(message) // " [ " // TRIM(routine) // " ]" 123 ENDIF 124 125 CLOSE(u) 126 127 END SUBROUTINE report 102 SUBROUTINE report(routine, message, debug) 103 104 CHARACTER(LEN=*), INTENT(IN) :: routine !< name of calling subroutine of function 105 CHARACTER(LEN=*), INTENT(IN) :: message !< log message 106 LOGICAL, OPTIONAL, INTENT(IN) :: debug !< flag the current message as debugging message 107 108 LOGICAL, SAVE :: is_first_run = .TRUE. !< control flag for file opening mode 109 LOGICAL :: suppress_message !< control falg for additional debugging log 110 111 IF ( is_first_run ) THEN 112 OPEN( NEWUNIT=u, FILE=LOG_FILE_NAME, STATUS='replace' ) 113 is_first_run = .FALSE. 114 ENDIF 115 116 117 suppress_message = .FALSE. 118 IF ( PRESENT(debug) ) THEN 119 IF ( .NOT. debug ) suppress_message = .TRUE. 120 ENDIF 121 122 IF ( .NOT. suppress_message ) THEN 123 PRINT *, "inifor: " // TRIM(message) // " [ " // TRIM(routine) // " ]" 124 WRITE(u, *) TRIM(message) // " [ " // TRIM(routine) // " ]" 125 ENDIF 126 127 END SUBROUTINE report 128 128 129 129 … … 138 138 !> continue. 139 139 !------------------------------------------------------------------------------! 140 141 142 143 144 145 146 147 140 SUBROUTINE warn(routine, message) 141 142 CHARACTER(LEN=*), INTENT(IN) :: routine !< name of calling subroutine or function 143 CHARACTER(LEN=*), INTENT(IN) :: message !< log message 144 145 CALL report(routine, "WARNING: " // TRIM(message)) 146 147 END SUBROUTINE warn 148 148 149 149 … … 158 158 !> INIFOR from continueing. 159 159 !------------------------------------------------------------------------------! 160 SUBROUTINE inifor_abort(routine, message) 161 162 CHARACTER(LEN=*), INTENT(IN) :: routine !< name of calling subroutine or function 163 CHARACTER(LEN=*), INTENT(IN) :: message !< log message 164 165 CALL report(routine, "ERROR: " // TRIM(message) // " Stopping.") 166 STOP 167 168 END SUBROUTINE inifor_abort 160 SUBROUTINE inifor_abort(routine, message) 161 162 CHARACTER(LEN=*), INTENT(IN) :: routine !< name of calling subroutine or function 163 CHARACTER(LEN=*), INTENT(IN) :: message !< log message 164 165 CALL report(routine, "ERROR: " // TRIM(message) // " Stopping.") 166 CALL close_log 167 STOP 168 169 END SUBROUTINE inifor_abort 170 171 172 SUBROUTINE close_log() 173 174 CLOSE(u) 175 176 END SUBROUTINE close_log 169 177 170 178 … … 175 183 !> print_version() prints the INIFOR version number and copyright notice. 176 184 !------------------------------------------------------------------------------! 177 178 179 180 181 182 183 !------------------------------------------------------------------------------! 184 ! Description: 185 ! ------------ 186 !> 187 !> run_control() measures the run times of various parts of INIFOR and185 SUBROUTINE print_version() 186 PRINT *, "INIFOR " // VERSION 187 PRINT *, COPYRIGHT 188 END SUBROUTINE print_version 189 190 191 !------------------------------------------------------------------------------! 192 ! Description: 193 ! ------------ 194 !> 195 !> log_runtime() measures the run times of various parts of INIFOR and 188 196 !> accumulates them in timing budgets. 189 197 !------------------------------------------------------------------------------! 190 SUBROUTINE run_control(mode, budget) 191 192 CHARACTER(LEN=*), INTENT(IN) :: mode !< name of the calling mode 193 CHARACTER(LEN=*), INTENT(IN) :: budget !< name of the timing budget 194 195 REAL(dp), SAVE :: t0 !< begin of timing interval 196 REAL(dp), SAVE :: t1 !< end of timing interval 197 REAL(dp), SAVE :: t_comp = 0.0_dp !< computation timing budget 198 REAL(dp), SAVE :: t_alloc = 0.0_dp !< allocation timing budget 199 REAL(dp), SAVE :: t_init = 0.0_dp !< initialization timing budget 200 REAL(dp), SAVE :: t_read = 0.0_dp !< reading timing budget 201 REAL(dp), SAVE :: t_total = 0.0_dp !< total time 202 REAL(dp), SAVE :: t_write = 0.0_dp !< writing timing budget 203 204 CHARACTER(LEN=*), PARAMETER :: fmt='(F6.2)' !< floating-point output format 205 206 207 SELECT CASE(TRIM(mode)) 208 209 CASE('init') 210 CALL CPU_TIME(t0) 211 212 CASE('time') 213 214 CALL CPU_TIME(t1) 215 216 SELECT CASE(TRIM(budget)) 217 218 CASE('alloc') 219 t_alloc = t_alloc + t1 - t0 220 221 CASE('init') 222 t_init = t_init + t1 - t0 223 224 CASE('read') 225 t_read = t_read + t1 - t0 226 227 CASE('write') 228 t_write = t_write + t1 - t0 229 230 CASE('comp') 231 t_comp = t_comp + t1 - t0 232 233 CASE DEFAULT 234 CALL inifor_abort('run_control', "Time Budget '" // TRIM(mode) // "' is not supported.") 235 236 END SELECT 237 238 t0 = t1 239 240 CASE('report') 241 t_total = t_init + t_read + t_write + t_comp 242 243 CALL report('run_control', " *** CPU time ***") 244 245 CALL report('run_control', "Initialization: " // real_to_str(t_init) // & 246 " s (" // TRIM(real_to_str(100*t_init/t_total, fmt)) // " %)") 247 248 CALL report('run_control', "(De-)Allocation:" // real_to_str(t_alloc) // & 249 " s (" // TRIM(real_to_str(100*t_alloc/t_total, fmt)) // " %)") 250 251 CALL report('run_control', "Reading data: " // real_to_str(t_read) // & 252 " s (" // TRIM(real_to_str(100*t_read/t_total, fmt)) // " %)") 253 254 CALL report('run_control', "Writing data: " // real_to_str(t_write) // & 255 " s (" // TRIM(real_to_str(100*t_write/t_total, fmt)) // " %)") 256 257 CALL report('run_control', "Computation: " // real_to_str(t_comp) // & 258 " s (" // TRIM(real_to_str(100*t_comp/t_total, fmt)) // " %)") 259 260 CALL report('run_control', "Total: " // real_to_str(t_total) // & 261 " s (" // TRIM(real_to_str(100*t_total/t_total, fmt)) // " %)") 262 263 CASE DEFAULT 264 CALL inifor_abort('run_control', "Mode '" // TRIM(mode) // "' is not supported.") 198 SUBROUTINE log_runtime(mode, budget) 199 200 CHARACTER(LEN=*), INTENT(IN) :: mode !< name of the calling mode 201 CHARACTER(LEN=*), INTENT(IN) :: budget !< name of the timing budget 202 203 REAL(wp), SAVE :: t0 !< begin of timing interval 204 REAL(wp), SAVE :: t1 !< end of timing interval 205 REAL(wp), SAVE :: t_comp = 0.0_wp !< computation timing budget 206 REAL(wp), SAVE :: t_alloc = 0.0_wp !< allocation timing budget 207 REAL(wp), SAVE :: t_init = 0.0_wp !< initialization timing budget 208 REAL(wp), SAVE :: t_read = 0.0_wp !< reading timing budget 209 REAL(wp), SAVE :: t_total = 0.0_wp !< total time 210 REAL(wp), SAVE :: t_write = 0.0_wp !< writing timing budget 211 212 CHARACTER(LEN=*), PARAMETER :: fmt='(F6.2)' !< floating-point output format 213 214 215 SELECT CASE(TRIM(mode)) 216 217 CASE('init') 218 CALL CPU_TIME(t0) 219 220 CASE('time') 221 222 CALL CPU_TIME(t1) 223 224 SELECT CASE(TRIM(budget)) 225 226 CASE('alloc') 227 t_alloc = t_alloc + t1 - t0 228 229 CASE('init') 230 t_init = t_init + t1 - t0 231 232 CASE('read') 233 t_read = t_read + t1 - t0 234 235 CASE('write') 236 t_write = t_write + t1 - t0 237 238 CASE('comp') 239 t_comp = t_comp + t1 - t0 240 241 CASE DEFAULT 242 CALL inifor_abort('log_runtime', "Time Budget '" // TRIM(mode) // "' is not supported.") 265 243 266 244 END SELECT 267 245 268 END SUBROUTINE run_control 246 t0 = t1 247 248 CASE('report') 249 t_total = t_init + t_read + t_write + t_comp 250 251 CALL report('log_runtime', " *** CPU time ***") 252 253 CALL report('log_runtime', "Initialization: " // TRIM( real_to_str( t_init ) ) // & 254 " s (" // TRIM( real_to_str( 100 * t_init / t_total, fmt ) ) // " %)" ) 255 256 CALL report('log_runtime', "(De-)Allocation: " // TRIM( real_to_str( t_alloc ) ) // & 257 " s (" // TRIM( real_to_str( 100 * t_alloc / t_total, fmt ) ) // " %)" ) 258 259 CALL report('log_runtime', "Reading data: " // TRIM( real_to_str( t_read ) ) // & 260 " s (" // TRIM( real_to_str( 100 * t_read / t_total, fmt ) ) // " %)" ) 261 262 CALL report('log_runtime', "Writing data: " // TRIM( real_to_str( t_write ) ) // & 263 " s (" // TRIM( real_to_str( 100 * t_write / t_total, fmt ) ) // " %)" ) 264 265 CALL report('log_runtime', "Computation: " // TRIM( real_to_str( t_comp ) ) // & 266 " s (" // TRIM( real_to_str( 100 * t_comp / t_total, fmt) ) // " %)" ) 267 268 CALL report('log_runtime', "Total: " // TRIM( real_to_str( t_total ) ) // & 269 " s (" // TRIM( real_to_str( 100 * t_total / t_total, fmt ) ) // " %)") 270 271 CASE DEFAULT 272 CALL inifor_abort('log_runtime', "Mode '" // TRIM(mode) // "' is not supported.") 273 274 END SELECT 275 276 END SUBROUTINE log_runtime 269 277 270 278 END MODULE inifor_control 271 #endif272 -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_defs.f90 ¶
r3801 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Added parameter for INIFOR's log file name 29 ! Use PALM's working precision 30 ! 31 ! 32 ! 3801 2019-03-15 17:14:25Z eckhard 28 33 ! Defined netCDF variable names for COSMO grid 29 34 ! Bumped version number … … 94 99 !> The defs module provides global constants used in INIFOR. 95 100 !------------------------------------------------------------------------------! 96 #if defined ( __netcdf )97 101 MODULE inifor_defs 98 102 103 USE kinds, & 104 ONLY : wp, iwp 105 99 106 IMPLICIT NONE 100 107 101 108 ! 102 109 !-- Parameters for type definitions 103 INTEGER, PARAMETER :: dp = 8 !< double precision (8 bytes = 64 bits)104 INTEGER, PARAMETER :: sp = 4 !< single precision (4 bytes = 32 bits)105 INTEGER, PARAMETER :: hp = 2 !< half precision (2 bytes = 16 bits)106 110 INTEGER, PARAMETER :: PATH = 140 !< length of file path strings 107 111 INTEGER, PARAMETER :: LNAME = 150 !< length of long name strings … … 111 115 ! 112 116 !-- Trigonomentry 113 REAL( dp), PARAMETER :: PI = 3.14159265358979323846264338_dp !< Ratio of a circle's circumference to its diamter [-]114 REAL( dp), PARAMETER :: TO_RADIANS = PI / 180.0_dp !< Conversion factor from degrees to radiant [-]115 REAL( dp), PARAMETER :: TO_DEGREES = 180.0_dp / PI !< Conversion factor from radians to degrees [-]117 REAL(wp), PARAMETER :: PI = 3.14159265358979323846264338_wp !< Ratio of a circle's circumference to its diamter [-] 118 REAL(wp), PARAMETER :: TO_RADIANS = PI / 180.0_wp !< Conversion factor from degrees to radiant [-] 119 REAL(wp), PARAMETER :: TO_DEGREES = 180.0_wp / PI !< Conversion factor from radians to degrees [-] 116 120 117 121 ! 118 122 !-- COSMO parameters 119 123 INTEGER, PARAMETER :: WATER_ID = 9 !< Integer corresponding to the water soil type in COSMO-DE [-] 120 REAL( dp), PARAMETER :: EARTH_RADIUS = 6371229.0_dp !< Earth radius used in COSMO-DE [m]121 REAL( dp), PARAMETER :: P_SL = 1e5_dp !< Reference pressure for computation of COSMO-DE's basic state pressure [Pa]122 REAL( dp), PARAMETER :: T_SL = 288.15_dp !< Reference temperature for computation of COSMO-DE's basic state pressure [K]123 REAL( dp), PARAMETER :: BETA = 42.0_dp !< logarithmic lapse rate, dT / d ln(p), for computation of COSMO-DE's basic124 REAL(wp), PARAMETER :: EARTH_RADIUS = 6371229.0_wp !< Earth radius used in COSMO-DE [m] 125 REAL(wp), PARAMETER :: P_SL = 1e5_wp !< Reference pressure for computation of COSMO-DE's basic state pressure [Pa] 126 REAL(wp), PARAMETER :: T_SL = 288.15_wp !< Reference temperature for computation of COSMO-DE's basic state pressure [K] 127 REAL(wp), PARAMETER :: BETA = 42.0_wp !< logarithmic lapse rate, dT / d ln(p), for computation of COSMO-DE's basic 124 128 !< state pressure [K] 125 REAL( dp), PARAMETER :: RD = 287.05_dp !< specific gas constant of dry air, used in computation of COSMO-DE's basic129 REAL(wp), PARAMETER :: RD = 287.05_wp !< specific gas constant of dry air, used in computation of COSMO-DE's basic 126 130 !< state [J/kg/K] 127 REAL( dp), PARAMETER :: RV = 461.51_dp !< specific gas constant of water vapor [J/kg/K]128 REAL( dp), PARAMETER :: G = 9.80665_dp !< acceleration of Earth's gravity, used in computation of COSMO-DE's basic131 REAL(wp), PARAMETER :: RV = 461.51_wp !< specific gas constant of water vapor [J/kg/K] 132 REAL(wp), PARAMETER :: G = 9.80665_wp !< acceleration of Earth's gravity, used in computation of COSMO-DE's basic 129 133 !< state [m/s/s] 130 REAL( dp), PARAMETER :: RHO_L = 1e3_dp !< density of liquid water, used to convert W_SO from [kg/m^2] to [m^3/m^3],134 REAL(wp), PARAMETER :: RHO_L = 1e3_wp !< density of liquid water, used to convert W_SO from [kg/m^2] to [m^3/m^3], 131 135 !< in [kg/m^3] 132 REAL( dp), PARAMETER :: HECTO = 100_dp !< unit conversion factor from hPa to Pa136 REAL(wp), PARAMETER :: HECTO = 100_wp !< unit conversion factor from hPa to Pa 133 137 134 138 ! 135 139 !-- PALM-4U parameters 136 REAL( dp), PARAMETER :: OMEGA = 7.29e-5_dp !< angular velocity of Earth's rotation [s^-1]137 REAL( dp), PARAMETER :: P_REF = 1e5_dp !< Reference pressure for potential temperature [Pa]138 REAL( dp), PARAMETER :: RD_PALM = 287.0_dp !< specific gas constant of dry air, used in computation of PALM-4U's potential temperature [J/kg/K]139 REAL( dp), PARAMETER :: CP_PALM = 1005.0_dp !< heat capacity of dry air at constant pressure, used in computation of PALM-4U's potential temperature [J/kg/K]140 REAL(wp), PARAMETER :: OMEGA = 7.29e-5_wp !< angular velocity of Earth's rotation [s^-1] 141 REAL(wp), PARAMETER :: P_REF = 1e5_wp !< Reference pressure for potential temperature [Pa] 142 REAL(wp), PARAMETER :: RD_PALM = 287.0_wp !< specific gas constant of dry air, used in computation of PALM-4U's potential temperature [J/kg/K] 143 REAL(wp), PARAMETER :: CP_PALM = 1005.0_wp !< heat capacity of dry air at constant pressure, used in computation of PALM-4U's potential temperature [J/kg/K] 140 144 141 145 ! … … 154 158 !< water cells [-] 155 159 INTEGER, PARAMETER :: FORCING_STEP = 1 !< Number of hours between forcing time steps [h] 156 REAL(dp), PARAMETER :: NUDGING_TAU = 21600.0_dp !< Nudging relaxation time scale [s] 157 CHARACTER(LEN=*), PARAMETER :: VERSION = '1.4.8' !< INIFOR version number 160 REAL(wp), PARAMETER :: NUDGING_TAU = 21600.0_wp !< Nudging relaxation time scale [s] 158 161 CHARACTER(LEN=*), PARAMETER :: COPYRIGHT = 'Copyright 2017-2019 Leibniz Universitaet Hannover' // & 159 ACHAR( 10 ) // ' Copyright 2017-2019 Deutscher Wetterdienst Offenbach' !< Copyright notice 160 162 ACHAR( 10 ) // ' Copyright 2017-2019 Deutscher Wetterdienst Offenbach' !< Copyright notice 163 CHARACTER(LEN=*), PARAMETER :: LOG_FILE_NAME = 'inifor.log' !< Name of INIFOR's log file 164 CHARACTER(LEN=*), PARAMETER :: VERSION = '1.4.9rc' !< INIFOR version number 165 161 166 END MODULE inifor_defs 162 #endif -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_grid.f90 ¶
r3802 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! Catch errors while reading namelists 30 ! Improved coding style 31 ! 32 ! 33 ! 3802 2019-03-17 13:33:42Z raasch 28 34 ! unused variable removed 29 35 ! … … 131 137 USE inifor_control 132 138 USE inifor_defs, & 133 ONLY: DATE, EARTH_RADIUS, TO_RADIANS, TO_DEGREES, PI, dp, hp, sp,&139 ONLY: DATE, EARTH_RADIUS, TO_RADIANS, TO_DEGREES, PI, & 134 140 SNAME, LNAME, PATH, FORCING_STEP, WATER_ID, FILL_ITERATIONS, & 135 141 BETA, P_SL, T_SL, BETA, RD, RV, G, P_REF, RD_PALM, CP_PALM, & 136 RHO_L, OMEGA, HECTO 142 RHO_L, OMEGA, HECTO, wp, iwp 137 143 USE inifor_io, & 138 144 ONLY: get_cosmo_grid, get_netcdf_attribute, get_netcdf_dim_vector, & … … 140 146 get_input_file_list, validate_config 141 147 USE inifor_transform, & 142 ONLY: average_2d, rotate_to_cosmo, find_horizontal_neighbours, &148 ONLY: average_2d, rotate_to_cosmo, find_horizontal_neighbours, & 143 149 compute_horizontal_interp_weights, & 144 150 find_vertical_neighbours_and_weights_interp, & … … 156 162 SAVE 157 163 158 REAL( dp) :: averaging_angle = 0.0_dp !< latitudal and longitudal width of averaging regions [rad]159 REAL( dp) :: averaging_width_ns = 0.0_dp !< longitudal width of averaging regions [m]160 REAL( dp) :: averaging_width_ew = 0.0_dp !< latitudal width of averaging regions [m]161 REAL( dp) :: phi_equat = 0.0_dp !< latitude of rotated equator of COSMO-DE grid [rad]162 REAL( dp) :: phi_n = 0.0_dp !< latitude of rotated pole of COSMO-DE grid [rad]163 REAL( dp) :: lambda_n = 0.0_dp !< longitude of rotaded pole of COSMO-DE grid [rad]164 REAL( dp) :: phi_c = 0.0_dp !< rotated-grid latitude of the center of the PALM domain [rad]165 REAL( dp) :: lambda_c = 0.0_dp !< rotated-grid longitude of the centre of the PALM domain [rad]166 REAL( dp) :: phi_cn = 0.0_dp !< latitude of the rotated pole relative to the COSMO-DE grid [rad]167 REAL( dp) :: lambda_cn = 0.0_dp !< longitude of the rotated pole relative to the COSMO-DE grid [rad]168 REAL( dp) :: lam_centre = 0.0_dp !< longitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad]169 REAL( dp) :: phi_centre = 0.0_dp !< latitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad]170 REAL( dp) :: lam_east = 0.0_dp !< longitude of the east central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]171 REAL( dp) :: lam_west = 0.0_dp !< longitude of the west central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]172 REAL( dp) :: phi_north = 0.0_dp !< latitude of the north central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]173 REAL( dp) :: phi_south = 0.0_dp !< latitude of the south central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]174 REAL( dp) :: gam = 0.0_dp !< angle for working around phirot2phi/rlarot2rla bug175 REAL( dp) :: dx = 0.0_dp !< PALM-4U grid spacing in x direction [m]176 REAL( dp) :: dy = 0.0_dp !< PALM-4U grid spacing in y direction [m]177 REAL( dp) :: dz(10) = -1.0_dp !< PALM-4U grid spacing in z direction [m]178 REAL( dp) :: dz_max = 1000.0_dp !< maximum vertical grid spacing [m]179 REAL( dp) :: dz_stretch_factor = 1.08_dp !< factor for vertical grid stretching [m]180 REAL( dp) :: dz_stretch_level = -9999999.9_dp!< height above which the vertical grid will be stretched [m]181 REAL( dp) :: dz_stretch_level_start(9) = -9999999.9_dp !< namelist parameter182 REAL( dp) :: dz_stretch_level_end(9) = 9999999.9_dp !< namelist parameter183 REAL( dp) :: dz_stretch_factor_array(9) = 1.08_dp !< namelist parameter184 REAL( dp) :: dxi = 0.0_dp !< inverse PALM-4U grid spacing in x direction [m^-1]185 REAL( dp) :: dyi = 0.0_dp !< inverse PALM-4U grid spacing in y direction [m^-1]186 REAL( dp) :: dzi = 0.0_dp !< inverse PALM-4U grid spacing in z direction [m^-1]187 REAL( dp) :: f3 = 0.0_dp !< Coriolis parameter188 REAL( dp) :: lx = 0.0_dp !< PALM-4U domain size in x direction [m]189 REAL( dp) :: ly = 0.0_dp !< PALM-4U domain size in y direction [m]190 REAL( dp) :: p0 = 0.0_dp !< PALM-4U surface pressure, at z0 [Pa]191 REAL( dp) :: x0 = 0.0_dp !< x coordinate of PALM-4U Earth tangent [m]192 REAL( dp) :: y0 = 0.0_dp !< y coordinate of PALM-4U Earth tangent [m]193 REAL( dp) :: z0 = 0.0_dp !< Elevation of the PALM-4U domain above sea level [m]194 REAL( dp) :: z_top = 0.0_dp !< height of the scalar top boundary [m]195 REAL( dp) :: zw_top = 0.0_dp !< height of the vertical velocity top boundary [m]196 REAL( dp) :: lonmin_cosmo = 0.0_dp !< Minimunm longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad]197 REAL( dp) :: lonmax_cosmo = 0.0_dp !< Maximum longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad]198 REAL( dp) :: latmin_cosmo = 0.0_dp !< Minimunm latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad]199 REAL( dp) :: latmax_cosmo = 0.0_dp !< Maximum latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad]200 REAL( dp) :: lonmin_palm = 0.0_dp !< Minimunm longitude of PALM grid [COSMO rotated-pole rad]201 REAL( dp) :: lonmax_palm = 0.0_dp !< Maximum longitude of PALM grid [COSMO rotated-pole rad]202 REAL( dp) :: latmin_palm = 0.0_dp !< Minimunm latitude of PALM grid [COSMO rotated-pole rad]203 REAL( dp) :: latmax_palm = 0.0_dp !< Maximum latitude of PALM grid [COSMO rotated-pole rad]204 REAL( dp) :: lonmin_tot = 0.0_dp !< Minimunm longitude of required COSMO data [COSMO rotated-pole rad]205 REAL( dp) :: lonmax_tot = 0.0_dp !< Maximum longitude of required COSMO data [COSMO rotated-pole rad]206 REAL( dp) :: latmin_tot = 0.0_dp !< Minimunm latitude of required COSMO data [COSMO rotated-pole rad]207 REAL( dp) :: latmax_tot = 0.0_dp !< Maximum latitude of required COSMO data [COSMO rotated-pole rad]208 REAL( dp) :: latitude = 0.0_dp !< geographical latitude of the PALM-4U origin, from inipar namelist [deg]209 REAL( dp) :: longitude = 0.0_dp !< geographical longitude of the PALM-4U origin, from inipar namelist [deg]210 REAL( dp) :: origin_lat = 0.0_dp !< geographical latitude of the PALM-4U origin, from static driver netCDF file [deg]211 REAL( dp) :: origin_lon = 0.0_dp !< geographical longitude of the PALM-4U origin, from static driver netCDF file [deg]212 REAL( dp) :: rotation_angle = 0.0_dp !< clockwise angle the PALM-4U north is rotated away from geographical north [deg]213 REAL( dp) :: end_time = 0.0_dp !< PALM-4U simulation time [s]214 215 REAL( dp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: hhl !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from external file216 REAL( dp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: hfl !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl217 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: depths !< COSMO-DE's TERRA-ML soil layer depths218 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: d_depth !< COSMO-DE's TERRA-ML soil layer thicknesses219 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: d_depth_rho_inv !< inverted soil water mass220 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: rlon !< longitudes of COSMO-DE's rotated-pole grid221 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: rlat !< latitudes of COSMO-DE's rotated-pole grid222 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: time !< output times223 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: x !< base palm grid x coordinate vector pointed to by grid_definitions224 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: xu !< base palm grid xu coordinate vector pointed to by grid_definitions225 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: y !< base palm grid y coordinate vector pointed to by grid_definitions226 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: yv !< base palm grid yv coordinate vector pointed to by grid_definitions227 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: z_column !< base palm grid z coordinate vector including the top boundary coordinate (entire column)228 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: zw_column !< base palm grid zw coordinate vector including the top boundary coordinate (entire column)229 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: z !< base palm grid z coordinate vector pointed to by grid_definitions230 REAL( dp), DIMENSION(:), ALLOCATABLE, TARGET :: zw !< base palm grid zw coordinate vector pointed to by grid_definitions231 232 INTEGER( hp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: soiltyp!< COSMO-DE soil type map164 REAL(wp) :: averaging_angle = 0.0_wp !< latitudal and longitudal width of averaging regions [rad] 165 REAL(wp) :: averaging_width_ns = 0.0_wp !< longitudal width of averaging regions [m] 166 REAL(wp) :: averaging_width_ew = 0.0_wp !< latitudal width of averaging regions [m] 167 REAL(wp) :: phi_equat = 0.0_wp !< latitude of rotated equator of COSMO-DE grid [rad] 168 REAL(wp) :: phi_n = 0.0_wp !< latitude of rotated pole of COSMO-DE grid [rad] 169 REAL(wp) :: lambda_n = 0.0_wp !< longitude of rotaded pole of COSMO-DE grid [rad] 170 REAL(wp) :: phi_c = 0.0_wp !< rotated-grid latitude of the center of the PALM domain [rad] 171 REAL(wp) :: lambda_c = 0.0_wp !< rotated-grid longitude of the centre of the PALM domain [rad] 172 REAL(wp) :: phi_cn = 0.0_wp !< latitude of the rotated pole relative to the COSMO-DE grid [rad] 173 REAL(wp) :: lambda_cn = 0.0_wp !< longitude of the rotated pole relative to the COSMO-DE grid [rad] 174 REAL(wp) :: lam_centre = 0.0_wp !< longitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad] 175 REAL(wp) :: phi_centre = 0.0_wp !< latitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad] 176 REAL(wp) :: lam_east = 0.0_wp !< longitude of the east central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad] 177 REAL(wp) :: lam_west = 0.0_wp !< longitude of the west central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad] 178 REAL(wp) :: phi_north = 0.0_wp !< latitude of the north central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad] 179 REAL(wp) :: phi_south = 0.0_wp !< latitude of the south central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad] 180 REAL(wp) :: gam = 0.0_wp !< angle for working around phirot2phi/rlarot2rla bug 181 REAL(wp) :: dx = 0.0_wp !< PALM-4U grid spacing in x direction [m] 182 REAL(wp) :: dy = 0.0_wp !< PALM-4U grid spacing in y direction [m] 183 REAL(wp) :: dz(10) = -1.0_wp !< PALM-4U grid spacing in z direction [m] 184 REAL(wp) :: dz_max = 1000.0_wp !< maximum vertical grid spacing [m] 185 REAL(wp) :: dz_stretch_factor = 1.08_wp !< factor for vertical grid stretching [m] 186 REAL(wp) :: dz_stretch_level = -9999999.9_wp!< height above which the vertical grid will be stretched [m] 187 REAL(wp) :: dz_stretch_level_start(9) = -9999999.9_wp !< namelist parameter 188 REAL(wp) :: dz_stretch_level_end(9) = 9999999.9_wp !< namelist parameter 189 REAL(wp) :: dz_stretch_factor_array(9) = 1.08_wp !< namelist parameter 190 REAL(wp) :: dxi = 0.0_wp !< inverse PALM-4U grid spacing in x direction [m^-1] 191 REAL(wp) :: dyi = 0.0_wp !< inverse PALM-4U grid spacing in y direction [m^-1] 192 REAL(wp) :: dzi = 0.0_wp !< inverse PALM-4U grid spacing in z direction [m^-1] 193 REAL(wp) :: f3 = 0.0_wp !< Coriolis parameter 194 REAL(wp) :: lx = 0.0_wp !< PALM-4U domain size in x direction [m] 195 REAL(wp) :: ly = 0.0_wp !< PALM-4U domain size in y direction [m] 196 REAL(wp) :: p0 = 0.0_wp !< PALM-4U surface pressure, at z0 [Pa] 197 REAL(wp) :: x0 = 0.0_wp !< x coordinate of PALM-4U Earth tangent [m] 198 REAL(wp) :: y0 = 0.0_wp !< y coordinate of PALM-4U Earth tangent [m] 199 REAL(wp) :: z0 = 0.0_wp !< Elevation of the PALM-4U domain above sea level [m] 200 REAL(wp) :: z_top = 0.0_wp !< height of the scalar top boundary [m] 201 REAL(wp) :: zw_top = 0.0_wp !< height of the vertical velocity top boundary [m] 202 REAL(wp) :: lonmin_cosmo = 0.0_wp !< Minimunm longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 203 REAL(wp) :: lonmax_cosmo = 0.0_wp !< Maximum longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 204 REAL(wp) :: latmin_cosmo = 0.0_wp !< Minimunm latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 205 REAL(wp) :: latmax_cosmo = 0.0_wp !< Maximum latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 206 REAL(wp) :: lonmin_palm = 0.0_wp !< Minimunm longitude of PALM grid [COSMO rotated-pole rad] 207 REAL(wp) :: lonmax_palm = 0.0_wp !< Maximum longitude of PALM grid [COSMO rotated-pole rad] 208 REAL(wp) :: latmin_palm = 0.0_wp !< Minimunm latitude of PALM grid [COSMO rotated-pole rad] 209 REAL(wp) :: latmax_palm = 0.0_wp !< Maximum latitude of PALM grid [COSMO rotated-pole rad] 210 REAL(wp) :: lonmin_tot = 0.0_wp !< Minimunm longitude of required COSMO data [COSMO rotated-pole rad] 211 REAL(wp) :: lonmax_tot = 0.0_wp !< Maximum longitude of required COSMO data [COSMO rotated-pole rad] 212 REAL(wp) :: latmin_tot = 0.0_wp !< Minimunm latitude of required COSMO data [COSMO rotated-pole rad] 213 REAL(wp) :: latmax_tot = 0.0_wp !< Maximum latitude of required COSMO data [COSMO rotated-pole rad] 214 REAL(wp) :: latitude = 0.0_wp !< geographical latitude of the PALM-4U origin, from inipar namelist [deg] 215 REAL(wp) :: longitude = 0.0_wp !< geographical longitude of the PALM-4U origin, from inipar namelist [deg] 216 REAL(wp) :: origin_lat = 0.0_wp !< geographical latitude of the PALM-4U origin, from static driver netCDF file [deg] 217 REAL(wp) :: origin_lon = 0.0_wp !< geographical longitude of the PALM-4U origin, from static driver netCDF file [deg] 218 REAL(wp) :: rotation_angle = 0.0_wp !< clockwise angle the PALM-4U north is rotated away from geographical north [deg] 219 REAL(wp) :: end_time = 0.0_wp !< PALM-4U simulation time [s] 220 221 REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: hhl !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from external file 222 REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: hfl !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl 223 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: depths !< COSMO-DE's TERRA-ML soil layer depths 224 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: d_depth !< COSMO-DE's TERRA-ML soil layer thicknesses 225 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: d_depth_rho_inv !< inverted soil water mass 226 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: rlon !< longitudes of COSMO-DE's rotated-pole grid 227 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: rlat !< latitudes of COSMO-DE's rotated-pole grid 228 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: time !< output times 229 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: x !< base palm grid x coordinate vector pointed to by grid_definitions 230 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: xu !< base palm grid xu coordinate vector pointed to by grid_definitions 231 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: y !< base palm grid y coordinate vector pointed to by grid_definitions 232 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: yv !< base palm grid yv coordinate vector pointed to by grid_definitions 233 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: z_column !< base palm grid z coordinate vector including the top boundary coordinate (entire column) 234 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: zw_column !< base palm grid zw coordinate vector including the top boundary coordinate (entire column) 235 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: z !< base palm grid z coordinate vector pointed to by grid_definitions 236 REAL(wp), DIMENSION(:), ALLOCATABLE, TARGET :: zw !< base palm grid zw coordinate vector pointed to by grid_definitions 237 238 INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: soiltyp !< COSMO-DE soil type map 233 239 INTEGER :: dz_stretch_level_end_index(9) !< vertical grid level index until which the vertical grid spacing is stretched 234 240 INTEGER :: dz_stretch_level_start_index(9) !< vertical grid level index above which the vertical grid spacing is stretched 241 INTEGER :: iostat !< return status of READ statement 235 242 INTEGER :: nt !< number of output time steps 236 243 INTEGER :: nx !< number of PALM-4U grid points in x direction … … 355 362 !> interplation grids later in setup_grids(). 356 363 !------------------------------------------------------------------------------! 357 364 SUBROUTINE setup_parameters() 358 365 359 366 ! … … 361 368 ! Section 1: Define default parameters 362 369 !------------------------------------------------------------------------------ 363 cfg %start_date = '2013072100'364 365 366 367 368 ! 369 !-- 370 origin_lat = 52.325079_dp * TO_RADIANS ! south-west of Berlin, origin used for the Dec 2017 showcase simulation371 origin_lon = 13.082744_dp * TO_RADIANS372 cfg % z0 = 35.0_dp373 374 ! 375 !-- 376 cfg % ug = 0.0_dp377 cfg % vg = 0.0_dp378 cfg %p0 = P_SL379 380 ! 381 !-- 382 383 384 385 386 387 388 389 390 cfg %flow_prefix = input_prefix391 cfg %input_prefix = input_prefix392 cfg %soil_prefix = input_prefix393 cfg %radiation_prefix = input_prefix394 cfg %soilmoisture_prefix = input_prefix395 396 397 398 399 400 401 cfg %debug = .FALSE.402 cfg % averaging_angle = 2.0_dp370 cfg%start_date = '2013072100' 371 end_hour = 2 372 start_hour_soil = -2 373 start_hour_soilmoisture = - (4 * 7 * 24) - 2 374 375 ! 376 !-- Defaultmain centre (_c) of the PALM-4U grid in the geographical system (_g) 377 origin_lat = 52.325079_wp * TO_RADIANS ! south-west of Berlin, origin used for the Dec 2017 showcase simulation 378 origin_lon = 13.082744_wp * TO_RADIANS 379 cfg%z0 = 35.0_wp 380 381 ! 382 !-- Default atmospheric parameters 383 cfg%ug = 0.0_wp 384 cfg%vg = 0.0_wp 385 cfg%p0 = P_SL 386 387 ! 388 !-- Parameters for file names 389 start_hour_flow = 0 390 start_hour_soil = 0 391 start_hour_radiation = 0 392 start_hour_soilmoisture = start_hour_flow - 2 393 end_hour_soilmoisture = start_hour_flow 394 step_hour = FORCING_STEP 395 396 input_prefix = 'laf' 397 cfg%flow_prefix = input_prefix 398 cfg%input_prefix = input_prefix 399 cfg%soil_prefix = input_prefix 400 cfg%radiation_prefix = input_prefix 401 cfg%soilmoisture_prefix = input_prefix 402 403 flow_suffix = '-flow' 404 soil_suffix = '-soil' 405 radiation_suffix = '-rad' 406 soilmoisture_suffix = '-soilmoisture' 407 408 cfg%debug = .FALSE. 409 cfg%averaging_angle = 2.0_wp 403 410 ! 404 411 !------------------------------------------------------------------------------ … … 407 414 408 415 ! 409 !-- Set default paths and modes 410 cfg % input_path = './' 411 cfg % hhl_file = '' 412 cfg % soiltyp_file = '' 413 cfg % namelist_file = './namelist' 414 cfg % static_driver_file = '' 415 cfg % output_file = './palm-4u-input.nc' 416 cfg % ic_mode = 'volume' 417 cfg % bc_mode = 'real' 418 cfg % averaging_mode = 'level' 419 420 ! 421 !-- Overwrite defaults with user configuration 422 CALL parse_command_line_arguments( cfg ) 423 CALL report('main_loop', 'Running INIFOR version ' // VERSION) 424 425 flow_prefix = TRIM(cfg % input_prefix) 426 radiation_prefix = TRIM(cfg % input_prefix) 427 soil_prefix = TRIM(cfg % input_prefix) 428 soilmoisture_prefix = TRIM(cfg % input_prefix) 429 IF (cfg % flow_prefix_is_set) flow_prefix = TRIM(cfg % flow_prefix) 430 IF (cfg % radiation_prefix_is_set) radiation_prefix = TRIM(cfg % radiation_prefix) 431 IF (cfg % soil_prefix_is_set) soil_prefix = TRIM(cfg % soil_prefix) 432 IF (cfg % soilmoisture_prefix_is_set) soilmoisture_prefix = TRIM(cfg % soilmoisture_prefix) 433 434 output_file % name = cfg % output_file 435 z0 = cfg % z0 436 p0 = cfg % p0 437 438 init_variables_required = .TRUE. 439 boundary_variables_required = TRIM( cfg % bc_mode ) == 'real' 440 ls_forcing_variables_required = TRIM( cfg % bc_mode ) == 'ideal' 441 surface_forcing_required = .FALSE. 442 443 IF ( ls_forcing_variables_required ) THEN 444 message = "Averaging of large-scale forcing profiles " // & 445 "has not been implemented, yet." 446 CALL inifor_abort('setup_parameters', message) 447 ENDIF 448 449 ! 450 !-- Set default file paths, if not specified by user. 451 CALL normalize_path(cfg % input_path) 452 IF (TRIM(cfg % hhl_file) == '') cfg % hhl_file = TRIM(cfg % input_path) // 'hhl.nc' 453 IF (TRIM(cfg % soiltyp_file) == '') cfg % soiltyp_file = TRIM(cfg % input_path) // 'soil.nc' 454 455 CALL validate_config( cfg ) 456 457 CALL report('setup_parameters', "initialization mode: " // TRIM(cfg % ic_mode)) 458 CALL report('setup_parameters', " forcing mode: " // TRIM(cfg % bc_mode)) 459 CALL report('setup_parameters', " averaging mode: " // TRIM(cfg % averaging_mode)) 460 CALL report('setup_parameters', " averaging angle: " // real_to_str(cfg % averaging_angle)) 461 CALL report('setup_parameters', " data path: " // TRIM(cfg % input_path)) 462 CALL report('setup_parameters', " hhl file: " // TRIM(cfg % hhl_file)) 463 CALL report('setup_parameters', " soiltyp file: " // TRIM(cfg % soiltyp_file)) 464 CALL report('setup_parameters', " namelist file: " // TRIM(cfg % namelist_file)) 465 CALL report('setup_parameters', " output data file: " // TRIM(output_file % name)) 466 IF (cfg % debug ) CALL report('setup_parameters', " debugging mode: enabled") 467 468 CALL run_control('time', 'init') 469 ! 470 !-- Read in namelist parameters 471 OPEN(10, FILE=cfg % namelist_file) 472 READ(10, NML=inipar) ! nx, ny, nz, dx, dy, dz 473 READ(10, NML=d3par) ! end_time 416 !-- Set default paths and modes 417 cfg%input_path = './' 418 cfg%hhl_file = '' 419 cfg%soiltyp_file = '' 420 cfg%namelist_file = './namelist' 421 cfg%static_driver_file = '' 422 cfg%output_file = './palm-4u-input.nc' 423 cfg%ic_mode = 'volume' 424 cfg%bc_mode = 'real' 425 cfg%averaging_mode = 'level' 426 427 ! 428 !-- Overwrite defaults with user configuration 429 CALL parse_command_line_arguments( cfg ) 430 CALL report('main_loop', 'Running INIFOR version ' // VERSION) 431 432 flow_prefix = TRIM(cfg%input_prefix) 433 radiation_prefix = TRIM(cfg%input_prefix) 434 soil_prefix = TRIM(cfg%input_prefix) 435 soilmoisture_prefix = TRIM(cfg%input_prefix) 436 IF (cfg%flow_prefix_is_set) flow_prefix = TRIM(cfg%flow_prefix) 437 IF (cfg%radiation_prefix_is_set) radiation_prefix = TRIM(cfg%radiation_prefix) 438 IF (cfg%soil_prefix_is_set) soil_prefix = TRIM(cfg%soil_prefix) 439 IF (cfg%soilmoisture_prefix_is_set) soilmoisture_prefix = TRIM(cfg%soilmoisture_prefix) 440 441 output_file%name = cfg%output_file 442 z0 = cfg%z0 443 p0 = cfg%p0 444 445 init_variables_required = .TRUE. 446 boundary_variables_required = TRIM( cfg%bc_mode ) == 'real' 447 ls_forcing_variables_required = TRIM( cfg%bc_mode ) == 'ideal' 448 surface_forcing_required = .FALSE. 449 450 IF ( ls_forcing_variables_required ) THEN 451 message = "Averaging of large-scale forcing profiles " // & 452 "has not been implemented, yet." 453 CALL inifor_abort('setup_parameters', message) 454 ENDIF 455 456 ! 457 !-- Set default file paths, if not specified by user. 458 CALL normalize_path(cfg%input_path) 459 IF (TRIM(cfg%hhl_file) == '') cfg%hhl_file = TRIM(cfg%input_path) // 'hhl.nc' 460 IF (TRIM(cfg%soiltyp_file) == '') cfg%soiltyp_file = TRIM(cfg%input_path) // 'soil.nc' 461 462 CALL validate_config( cfg ) 463 464 CALL report('setup_parameters', "initialization mode: " // TRIM(cfg%ic_mode)) 465 CALL report('setup_parameters', " forcing mode: " // TRIM(cfg%bc_mode)) 466 CALL report('setup_parameters', " averaging mode: " // TRIM(cfg%averaging_mode)) 467 CALL report('setup_parameters', " averaging angle: " // real_to_str(cfg%averaging_angle)) 468 CALL report('setup_parameters', " data path: " // TRIM(cfg%input_path)) 469 CALL report('setup_parameters', " hhl file: " // TRIM(cfg%hhl_file)) 470 CALL report('setup_parameters', " soiltyp file: " // TRIM(cfg%soiltyp_file)) 471 CALL report('setup_parameters', " namelist file: " // TRIM(cfg%namelist_file)) 472 CALL report('setup_parameters', " output data file: " // TRIM(output_file%name)) 473 IF (cfg%debug ) CALL report('setup_parameters', " debugging mode: enabled") 474 475 CALL log_runtime('time', 'init') 476 ! 477 !-- Read in namelist parameters 478 OPEN(10, FILE=cfg%namelist_file, STATUS='old') 479 READ(10, NML=inipar, IOSTAT=iostat) ! nx, ny, nz, dx, dy, dz 480 IF ( iostat > 0 ) THEN 481 message = "Failed to read namelist 'inipar' from file '" // & 482 TRIM( cfg%namelist_file ) // "'. " 483 CALL inifor_abort( 'setup_parameters', message ) 474 484 CLOSE(10) 475 CALL run_control('time', 'read') 476 477 end_hour = CEILING( end_time / 3600.0 * step_hour ) 478 479 ! 480 !-- Generate input file lists 481 CALL get_input_file_list( & 482 cfg % start_date, start_hour_flow, end_hour, step_hour, & 483 cfg % input_path, flow_prefix, flow_suffix, flow_files) 484 CALL get_input_file_list( & 485 cfg % start_date, start_hour_soil, end_hour, step_hour, & 486 cfg % input_path, soil_prefix, soil_suffix, soil_files) 487 CALL get_input_file_list( & 488 cfg % start_date, start_hour_radiation, end_hour, step_hour, & 489 cfg % input_path, radiation_prefix, radiation_suffix, radiation_files, nocheck=.TRUE.) 490 CALL get_input_file_list( & 491 cfg % start_date, start_hour_soilmoisture, end_hour_soilmoisture, step_hour, & 492 cfg % input_path, soilmoisture_prefix, soilmoisture_suffix, soil_moisture_files, nocheck=.TRUE.) 485 ENDIF 486 487 READ(10, NML=d3par, IOSTAT=iostat) ! end_time 488 IF ( iostat > 0 ) THEN 489 message = "Failed to read namelist 'd3par' from file '" // & 490 TRIM( cfg%namelist_file ) // "'. " 491 CALL inifor_abort( 'setup_parameters', message ) 492 CLOSE(10) 493 ENDIF 494 CLOSE(10) 495 496 CALL log_runtime('time', 'read') 497 498 end_hour = CEILING( end_time / 3600.0 * step_hour ) 499 500 ! 501 !-- Generate input file lists 502 CALL get_input_file_list( & 503 cfg%start_date, start_hour_flow, end_hour, step_hour, & 504 cfg%input_path, flow_prefix, flow_suffix, flow_files) 505 CALL get_input_file_list( & 506 cfg%start_date, start_hour_soil, end_hour, step_hour, & 507 cfg%input_path, soil_prefix, soil_suffix, soil_files) 508 CALL get_input_file_list( & 509 cfg%start_date, start_hour_radiation, end_hour, step_hour, & 510 cfg%input_path, radiation_prefix, radiation_suffix, radiation_files, nocheck=.TRUE.) 511 CALL get_input_file_list( & 512 cfg%start_date, start_hour_soilmoisture, end_hour_soilmoisture, step_hour, & 513 cfg%input_path, soilmoisture_prefix, soilmoisture_suffix, soil_moisture_files, nocheck=.TRUE.) 493 514 494 515 ! … … 506 527 507 528 508 CALL run_control('time', 'init')509 ! 510 !-- 511 cosmo_var %name = 'SOILTYP'512 CALL get_netcdf_variable(cfg %soiltyp_file, cosmo_var, soiltyp)513 514 515 IF (TRIM(cfg %static_driver_file) .NE. '') THEN516 517 origin_lon = get_netcdf_attribute(cfg %static_driver_file, 'origin_lon')518 origin_lat = get_netcdf_attribute(cfg %static_driver_file, 'origin_lat')519 520 521 // TRIM(cfg %static_driver_file) // "'"522 523 524 525 526 527 528 529 530 // TRIM(cfg %namelist_file) // "'"531 532 533 534 535 536 537 538 CALL run_control('time', 'read')539 540 541 542 543 544 545 529 CALL log_runtime('time', 'init') 530 ! 531 !-- Read COSMO soil type map 532 cosmo_var%name = 'SOILTYP' 533 CALL get_netcdf_variable(cfg%soiltyp_file, cosmo_var, soiltyp) 534 535 message = 'Reading PALM-4U origin from' 536 IF (TRIM(cfg%static_driver_file) .NE. '') THEN 537 538 origin_lon = get_netcdf_attribute(cfg%static_driver_file, 'origin_lon') 539 origin_lat = get_netcdf_attribute(cfg%static_driver_file, 'origin_lat') 540 541 message = TRIM(message) // " static driver file '" & 542 // TRIM(cfg%static_driver_file) // "'" 543 544 545 ELSE 546 547 origin_lon = longitude 548 origin_lat = latitude 549 550 message = TRIM(message) // " namlist file '" & 551 // TRIM(cfg%namelist_file) // "'" 552 553 ENDIF 554 origin_lon = origin_lon * TO_RADIANS 555 origin_lat = origin_lat * TO_RADIANS 556 557 CALL report('setup_parameters', message) 558 559 CALL log_runtime('time', 'read') 560 561 CALL get_cosmo_grid( cfg, soil_files(1), rlon, rlat, hhl, hfl, depths, & 562 d_depth, d_depth_rho_inv, phi_n, lambda_n, & 563 phi_equat, & 564 lonmin_cosmo, lonmax_cosmo, & 565 latmin_cosmo, latmax_cosmo, & 566 nlon, nlat, nlev, ndepths ) 546 567 547 568 … … 550 571 !------------------------------------------------------------------------------ 551 572 ! 552 !-- 553 554 555 556 ! 557 !-- 558 x0 = 0.0_dp559 y0 = 0.0_dp560 561 ! 562 !-- 563 nt = CEILING(end_time / (step_hour * 3600.0_dp)) + 1564 565 CALL linspace(0.0_dp, 3600.0_dp * (nt-1), time)566 output_file %time => time567 CALL run_control('time', 'init')568 569 ! 570 !-- 571 572 573 574 575 576 577 0.0_dp )578 579 ! 580 !-- 581 !-- 582 !-- 583 !-- 584 585 586 ! 587 !-- 588 !-- 589 !-- 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 CALL run_control('time', 'comp')573 !-- PALM-4U domain extents 574 lx = (nx+1) * dx 575 ly = (ny+1) * dy 576 577 ! 578 !-- PALM-4U point of Earth tangency 579 x0 = 0.0_wp 580 y0 = 0.0_wp 581 582 ! 583 !-- time vector 584 nt = CEILING(end_time / (step_hour * 3600.0_wp)) + 1 585 ALLOCATE( time(nt) ) 586 CALL linspace(0.0_wp, 3600.0_wp * (nt-1), time) 587 output_file%time => time 588 CALL log_runtime('time', 'init') 589 590 ! 591 !-- Convert the PALM-4U origin coordinates to COSMO's rotated-pole grid 592 phi_c = TO_RADIANS * & 593 phi2phirot( origin_lat * TO_DEGREES, origin_lon * TO_DEGREES,& 594 phi_n * TO_DEGREES, lambda_n * TO_DEGREES ) 595 lambda_c = TO_RADIANS * & 596 rla2rlarot( origin_lat * TO_DEGREES, origin_lon * TO_DEGREES,& 597 phi_n * TO_DEGREES, lambda_n * TO_DEGREES, & 598 0.0_wp ) 599 600 ! 601 !-- Set gamma according to whether PALM domain is in the northern or southern 602 !-- hemisphere of the COSMO rotated-pole system. Gamma assumes either the 603 !-- value 0 or PI and is needed to work around around a bug in the 604 !-- rotated-pole coordinate transformations. 605 gam = gamma_from_hemisphere(origin_lat, phi_equat) 606 607 ! 608 !-- Compute the north pole of the rotated-pole grid centred at the PALM-4U 609 !-- domain centre. The resulting (phi_cn, lambda_cn) are coordinates in 610 !-- COSMO-DE's rotated-pole grid. 611 phi_cn = phic_to_phin(phi_c) 612 lambda_cn = lamc_to_lamn(phi_c, lambda_c) 613 614 message = "PALM-4U origin:" // NEW_LINE('') // & 615 " lon (lambda) = " // & 616 TRIM(real_to_str_f(origin_lon * TO_DEGREES)) // " deg"// NEW_LINE(' ') //& 617 " lat (phi ) = " // & 618 TRIM(real_to_str_f(origin_lat * TO_DEGREES)) // " deg (geographical)" // NEW_LINE(' ') //& 619 " lon (lambda) = " // & 620 TRIM(real_to_str_f(lambda_c * TO_DEGREES)) // " deg" // NEW_LINE(' ') // & 621 " lat (phi ) = " // & 622 TRIM(real_to_str_f(phi_c * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)" 623 CALL report ('setup_parameters', message) 624 625 message = "North pole of the rotated COSMO-DE system:" // NEW_LINE(' ') // & 626 " lon (lambda) = " // & 627 TRIM(real_to_str_f(lambda_n * TO_DEGREES)) // " deg" // NEW_LINE(' ') //& 628 " lat (phi ) = " // & 629 TRIM(real_to_str_f(phi_n * TO_DEGREES)) // " deg (geographical)" 630 CALL report ('setup_parameters', message) 631 632 message = "North pole of the rotated palm system:" // NEW_LINE(' ') // & 633 " lon (lambda) = " // & 634 TRIM(real_to_str_f(lambda_cn * TO_DEGREES)) // " deg" // NEW_LINE(' ') // & 635 " lat (phi ) = " // & 636 TRIM(real_to_str_f(phi_cn * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)" 637 CALL report ('setup_parameters', message) 638 639 CALL log_runtime('time', 'comp') 619 640 620 641 !------------------------------------------------------------------------------ … … 625 646 !-- Compute coordiantes of the PALM centre in the source (COSMO) system 626 647 phi_centre = phirot2phi( & 627 phirot = project(0.5_ dp*ly, y0, EARTH_RADIUS) * TO_DEGREES, &628 rlarot = project(0.5_ dp*lx, x0, EARTH_RADIUS) * TO_DEGREES, &648 phirot = project(0.5_wp*ly, y0, EARTH_RADIUS) * TO_DEGREES, & 649 rlarot = project(0.5_wp*lx, x0, EARTH_RADIUS) * TO_DEGREES, & 629 650 polphi = phi_cn * TO_DEGREES, & 630 651 polgam = gam * TO_DEGREES & … … 632 653 633 654 lam_centre = rlarot2rla( & 634 phirot = project(0.5_ dp*ly, y0, EARTH_RADIUS) * TO_DEGREES, &635 rlarot = project(0.5_ dp*lx, x0, EARTH_RADIUS) * TO_DEGREES, &655 phirot = project(0.5_wp*ly, y0, EARTH_RADIUS) * TO_DEGREES, & 656 rlarot = project(0.5_wp*lx, x0, EARTH_RADIUS) * TO_DEGREES, & 636 657 polphi = phi_cn * TO_DEGREES, pollam = lambda_cn * TO_DEGREES, & 637 658 polgam = gam * TO_DEGREES & … … 647 668 ! 648 669 !-- Compute boundaries of the central averaging box 649 averaging_angle = cfg %averaging_angle * TO_RADIANS650 lam_east = lam_centre + 0.5_ dp * averaging_angle651 lam_west = lam_centre - 0.5_ dp * averaging_angle652 phi_north = phi_centre + 0.5_ dp * averaging_angle653 phi_south = phi_centre - 0.5_ dp * averaging_angle670 averaging_angle = cfg%averaging_angle * TO_RADIANS 671 lam_east = lam_centre + 0.5_wp * averaging_angle 672 lam_west = lam_centre - 0.5_wp * averaging_angle 673 phi_north = phi_centre + 0.5_wp * averaging_angle 674 phi_south = phi_centre - 0.5_wp * averaging_angle 654 675 averaging_width_ew = averaging_angle * COS(phi_centre) * EARTH_RADIUS 655 676 averaging_width_ns = averaging_angle * EARTH_RADIUS … … 674 695 ! 675 696 !-- Coriolis parameter 676 f3 = 2.0_ dp * OMEGA * SIN( &697 f3 = 2.0_wp * OMEGA * SIN( & 677 698 TO_RADIANS*phirot2phi( phi_centre * TO_DEGREES, lam_centre * TO_DEGREES,& 678 699 phi_n * TO_DEGREES, & … … 680 701 ) 681 702 682 703 END SUBROUTINE setup_parameters 683 704 684 705 … … 689 710 !> coordinates and interpolation weights 690 711 !------------------------------------------------------------------------------! 691 692 712 SUBROUTINE setup_grids() 713 CHARACTER :: interp_mode 693 714 694 715 !------------------------------------------------------------------------------ … … 696 717 !------------------------------------------------------------------------------ 697 718 ! 698 !-- 699 !-- 700 !-- 701 702 CALL linspace(0.5_dp * dx, lx - 0.5_dp * dx, x)703 CALL linspace(0.5_dp * dy, ly - 0.5_dp * dy, y)704 705 706 707 708 709 710 711 712 713 ! 714 !-- 715 !-- 716 717 718 719 720 721 719 !-- palm x y z, we allocate the column to nz+1 in order to include the top 720 !-- scalar boundary. The interpolation grids will be associated with 721 !-- a shorter column that omits the top element. 722 ALLOCATE( x(0:nx), y(0:ny), z(1:nz), z_column(1:nz+1) ) 723 CALL linspace(0.5_wp * dx, lx - 0.5_wp * dx, x) 724 CALL linspace(0.5_wp * dy, ly - 0.5_wp * dy, y) 725 CALL stretched_z(z_column, dz, dz_max=dz_max, & 726 dz_stretch_factor=dz_stretch_factor, & 727 dz_stretch_level=dz_stretch_level, & 728 dz_stretch_level_start=dz_stretch_level_start, & 729 dz_stretch_level_end=dz_stretch_level_end, & 730 dz_stretch_factor_array=dz_stretch_factor_array) 731 z(1:nz) = z_column(1:nz) 732 z_top = z_column(nz+1) 733 734 ! 735 !-- palm xu yv zw, compared to the scalar grid, velocity coordinates 736 !-- contain one element less. 737 ALLOCATE( xu(1:nx), yv(1:ny), zw(1:nz-1), zw_column(1:nz)) 738 CALL linspace(dx, lx - dx, xu) 739 CALL linspace(dy, ly - dy, yv) 740 CALL midpoints(z_column, zw_column) 741 zw(1:nz-1) = zw_column(1:nz-1) 742 zw_top = zw_column(nz) 722 743 723 744 … … 725 746 ! Section 1: Define initialization and boundary grids 726 747 !------------------------------------------------------------------------------ 727 CALL init_grid_definition('palm', grid=palm_grid, & 728 xmin=0.0_dp, xmax=lx, & 729 ymin=0.0_dp, ymax=ly, & 730 x0=x0, y0=y0, z0=z0, & 731 nx=nx, ny=ny, nz=nz, z=z, zw=zw, ic_mode=cfg % ic_mode) 732 733 ! 734 !-- Subtracting 1 because arrays will be allocated with nlon + 1 elements. 735 CALL init_grid_definition('cosmo-de', grid=cosmo_grid, & 736 xmin=lonmin_cosmo, xmax=lonmax_cosmo, & 737 ymin=latmin_cosmo, ymax=latmax_cosmo, & 738 x0=x0, y0=y0, z0=0.0_dp, & 739 nx=nlon-1, ny=nlat-1, nz=nlev-1) 740 741 ! 742 !-- Define intermediate grid. This is the same as palm_grid except with a 743 !-- much coarser vertical grid. The vertical levels are interpolated in each 744 !-- PALM column from COSMO's secondary levels. The main levels are then 745 !-- computed as the averages of the bounding secondary levels. 746 CALL init_grid_definition('palm intermediate', grid=palm_intermediate, & 747 xmin=0.0_dp, xmax=lx, & 748 ymin=0.0_dp, ymax=ly, & 749 x0=x0, y0=y0, z0=z0, & 750 nx=nx, ny=ny, nz=nlev-2) 751 752 CALL init_grid_definition('boundary', grid=u_initial_grid, & 748 CALL init_grid_definition('palm', grid=palm_grid, & 749 xmin=0.0_wp, xmax=lx, & 750 ymin=0.0_wp, ymax=ly, & 751 x0=x0, y0=y0, z0=z0, & 752 nx=nx, ny=ny, nz=nz, z=z, zw=zw, ic_mode=cfg%ic_mode) 753 754 ! 755 !-- Subtracting 1 because arrays will be allocated with nlon + 1 elements. 756 CALL init_grid_definition('cosmo-de', grid=cosmo_grid, & 757 xmin=lonmin_cosmo, xmax=lonmax_cosmo, & 758 ymin=latmin_cosmo, ymax=latmax_cosmo, & 759 x0=x0, y0=y0, z0=0.0_wp, & 760 nx=nlon-1, ny=nlat-1, nz=nlev-1) 761 762 ! 763 !-- Define intermediate grid. This is the same as palm_grid except with a 764 !-- much coarser vertical grid. The vertical levels are interpolated in each 765 !-- PALM column from COSMO's secondary levels. The main levels are then 766 !-- computed as the averages of the bounding secondary levels. 767 CALL init_grid_definition('palm intermediate', grid=palm_intermediate, & 768 xmin=0.0_wp, xmax=lx, & 769 ymin=0.0_wp, ymax=ly, & 770 x0=x0, y0=y0, z0=z0, & 771 nx=nx, ny=ny, nz=nlev-2) 772 773 CALL init_grid_definition('boundary', grid=u_initial_grid, & 774 xmin = dx, xmax = lx - dx, & 775 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 776 x0=x0, y0=y0, z0 = z0, & 777 nx = nx-1, ny = ny, nz = nz, & 778 z=z, ic_mode=cfg%ic_mode) 779 780 CALL init_grid_definition('boundary', grid=v_initial_grid, & 781 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 782 ymin = dy, ymax = ly - dy, & 783 x0=x0, y0=y0, z0 = z0, & 784 nx = nx, ny = ny-1, nz = nz, & 785 z=z, ic_mode=cfg%ic_mode) 786 787 CALL init_grid_definition('boundary', grid=w_initial_grid, & 788 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 789 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 790 x0=x0, y0=y0, z0 = z0, & 791 nx = nx, ny = ny, nz = nz-1, & 792 z=zw, ic_mode=cfg%ic_mode) 793 794 CALL init_grid_definition('boundary intermediate', grid=u_initial_intermediate, & 795 xmin = dx, xmax = lx - dx, & 796 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 797 x0=x0, y0=y0, z0 = z0, & 798 nx = nx-1, ny = ny, nz = nlev - 2) 799 800 CALL init_grid_definition('boundary intermediate', grid=v_initial_intermediate, & 801 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 802 ymin = dy, ymax = ly - dy, & 803 x0=x0, y0=y0, z0 = z0, & 804 nx = nx, ny = ny-1, nz = nlev - 2) 805 806 CALL init_grid_definition('boundary intermediate', grid=w_initial_intermediate, & 807 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 808 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 809 x0=x0, y0=y0, z0 = z0, & 810 nx = nx, ny = ny, nz = nlev - 1) 811 812 IF (boundary_variables_required) THEN 813 ! 814 !------------------------------------------------------------------------------ 815 ! Section 2: Define PALM-4U boundary grids 816 !------------------------------------------------------------------------------ 817 CALL init_grid_definition('boundary', grid=scalars_east_grid, & 818 xmin = lx + 0.5_wp * dx, xmax = lx + 0.5_wp * dx, & 819 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 820 x0=x0, y0=y0, z0 = z0, & 821 nx = 0, ny = ny, nz = nz, z=z) 822 823 CALL init_grid_definition('boundary', grid=scalars_west_grid, & 824 xmin = -0.5_wp * dx, xmax = -0.5_wp * dx, & 825 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 826 x0=x0, y0=y0, z0 = z0, & 827 nx = 0, ny = ny, nz = nz, z=z) 828 829 CALL init_grid_definition('boundary', grid=scalars_north_grid, & 830 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 831 ymin = ly + 0.5_wp * dy, ymax = ly + 0.5_wp * dy, & 832 x0=x0, y0=y0, z0 = z0, & 833 nx = nx, ny = 0, nz = nz, z=z) 834 835 CALL init_grid_definition('boundary', grid=scalars_south_grid, & 836 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 837 ymin = -0.5_wp * dy, ymax = -0.5_wp * dy, & 838 x0=x0, y0=y0, z0 = z0, & 839 nx = nx, ny = 0, nz = nz, z=z) 840 841 CALL init_grid_definition('boundary', grid=scalars_top_grid, & 842 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 843 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 844 x0=x0, y0=y0, z0 = z0, & 845 nx = nx, ny = ny, nz = 1, z=(/z_top/)) 846 847 CALL init_grid_definition('boundary', grid=u_east_grid, & 848 xmin = lx, xmax = lx, & 849 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 850 x0=x0, y0=y0, z0 = z0, & 851 nx = 0, ny = ny, nz = nz, z=z) 852 853 CALL init_grid_definition('boundary', grid=u_west_grid, & 854 xmin = 0.0_wp, xmax = 0.0_wp, & 855 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 856 x0=x0, y0=y0, z0 = z0, & 857 nx = 0, ny = ny, nz = nz, z=z) 858 859 CALL init_grid_definition('boundary', grid=u_north_grid, & 753 860 xmin = dx, xmax = lx - dx, & 754 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,&861 ymin = ly + 0.5_wp * dy, ymax = ly + 0.5_wp * dy, & 755 862 x0=x0, y0=y0, z0 = z0, & 756 nx = nx-1, ny = ny, nz = nz, & 757 z=z, ic_mode=cfg % ic_mode) 758 759 CALL init_grid_definition('boundary', grid=v_initial_grid, & 760 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 863 nx = nx-1, ny = 0, nz = nz, z=z) 864 865 CALL init_grid_definition('boundary', grid=u_south_grid, & 866 xmin = dx, xmax = lx - dx, & 867 ymin = -0.5_wp * dy, ymax = -0.5_wp * dy, & 868 x0=x0, y0=y0, z0 = z0, & 869 nx = nx-1, ny = 0, nz = nz, z=z) 870 871 CALL init_grid_definition('boundary', grid=u_top_grid, & 872 xmin = dx, xmax = lx - dx, & 873 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 874 x0=x0, y0=y0, z0 = z0, & 875 nx = nx-1, ny = ny, nz = 1, z=(/z_top/)) 876 877 CALL init_grid_definition('boundary', grid=v_east_grid, & 878 xmin = lx + 0.5_wp * dx, xmax = lx + 0.5_wp * dx, & 761 879 ymin = dy, ymax = ly - dy, & 762 880 x0=x0, y0=y0, z0 = z0, & 763 nx = nx, ny = ny-1, nz = nz, & 764 z=z, ic_mode=cfg % ic_mode) 765 766 CALL init_grid_definition('boundary', grid=w_initial_grid, & 767 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 768 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 881 nx = 0, ny = ny-1, nz = nz, z=z) 882 883 CALL init_grid_definition('boundary', grid=v_west_grid, & 884 xmin = -0.5_wp * dx, xmax = -0.5_wp * dx, & 885 ymin = dy, ymax = ly - dy, & 769 886 x0=x0, y0=y0, z0 = z0, & 770 nx = nx, ny = ny, nz = nz-1, & 771 z=zw, ic_mode=cfg % ic_mode) 772 773 CALL init_grid_definition('boundary intermediate', grid=u_initial_intermediate, & 887 nx = 0, ny = ny-1, nz = nz, z=z) 888 889 CALL init_grid_definition('boundary', grid=v_north_grid, & 890 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 891 ymin = ly, ymax = ly, & 892 x0=x0, y0=y0, z0 = z0, & 893 nx = nx, ny = 0, nz = nz, z=z) 894 895 CALL init_grid_definition('boundary', grid=v_south_grid, & 896 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 897 ymin = 0.0_wp, ymax = 0.0_wp, & 898 x0=x0, y0=y0, z0 = z0, & 899 nx = nx, ny = 0, nz = nz, z=z) 900 901 CALL init_grid_definition('boundary', grid=v_top_grid, & 902 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 903 ymin = dy, ymax = ly - dy, & 904 x0=x0, y0=y0, z0 = z0, & 905 nx = nx, ny = ny-1, nz = 1, z=(/z_top/)) 906 907 CALL init_grid_definition('boundary', grid=w_east_grid, & 908 xmin = lx + 0.5_wp * dx, xmax = lx + 0.5_wp * dx, & 909 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 910 x0=x0, y0=y0, z0 = z0, & 911 nx = 0, ny = ny, nz = nz - 1, z=zw) 912 913 CALL init_grid_definition('boundary', grid=w_west_grid, & 914 xmin = -0.5_wp * dx, xmax = -0.5_wp * dx, & 915 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 916 x0=x0, y0=y0, z0 = z0, & 917 nx = 0, ny = ny, nz = nz - 1, z=zw) 918 919 CALL init_grid_definition('boundary', grid=w_north_grid, & 920 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 921 ymin = ly + 0.5_wp * dy, ymax = ly + 0.5_wp * dy, & 922 x0=x0, y0=y0, z0 = z0, & 923 nx = nx, ny = 0, nz = nz - 1, z=zw) 924 925 CALL init_grid_definition('boundary', grid=w_south_grid, & 926 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 927 ymin = -0.5_wp * dy, ymax = -0.5_wp * dy, & 928 x0=x0, y0=y0, z0 = z0, & 929 nx = nx, ny = 0, nz = nz - 1, z=zw) 930 931 CALL init_grid_definition('boundary', grid=w_top_grid, & 932 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 933 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 934 x0=x0, y0=y0, z0 = z0, & 935 nx = nx, ny = ny, nz = 1, z=(/zw_top/)) 936 937 CALL init_grid_definition('boundary intermediate', grid=scalars_east_intermediate, & 938 xmin = lx + 0.5_wp * dx, xmax = lx + 0.5_wp * dx, & 939 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 940 x0=x0, y0=y0, z0 = z0, & 941 nx = 0, ny = ny, nz = nlev - 2) 942 943 CALL init_grid_definition('boundary intermediate', grid=scalars_west_intermediate, & 944 xmin = -0.5_wp * dx, xmax = -0.5_wp * dx, & 945 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 946 x0=x0, y0=y0, z0 = z0, & 947 nx = 0, ny = ny, nz = nlev - 2) 948 949 CALL init_grid_definition('boundary intermediate', grid=scalars_north_intermediate, & 950 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 951 ymin = ly + 0.5_wp * dy, ymax = ly + 0.5_wp * dy, & 952 x0=x0, y0=y0, z0 = z0, & 953 nx = nx, ny = 0, nz = nlev - 2) 954 955 CALL init_grid_definition('boundary intermediate', grid=scalars_south_intermediate, & 956 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 957 ymin = -0.5_wp * dy, ymax = -0.5_wp * dy, & 958 x0=x0, y0=y0, z0 = z0, & 959 nx = nx, ny = 0, nz = nlev - 2) 960 961 CALL init_grid_definition('boundary intermediate', grid=scalars_top_intermediate, & 962 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 963 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 964 x0=x0, y0=y0, z0 = z0, & 965 nx = nx, ny = ny, nz = nlev - 2) 966 967 CALL init_grid_definition('boundary intermediate', grid=u_east_intermediate, & 968 xmin = lx, xmax = lx, & 969 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 970 x0=x0, y0=y0, z0 = z0, & 971 nx = 0, ny = ny, nz = nlev - 2) 972 973 CALL init_grid_definition('boundary intermediate', grid=u_west_intermediate, & 974 xmin = 0.0_wp, xmax = 0.0_wp, & 975 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 976 x0=x0, y0=y0, z0 = z0, & 977 nx = 0, ny = ny, nz = nlev - 2) 978 979 CALL init_grid_definition('boundary intermediate', grid=u_north_intermediate, & 774 980 xmin = dx, xmax = lx - dx, & 775 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 981 ymin = ly + 0.5_wp * dy, ymax = ly + 0.5_wp * dy, & 982 x0=x0, y0=y0, z0 = z0, & 983 nx = nx-1, ny = 0, nz = nlev - 2) 984 985 CALL init_grid_definition('boundary intermediate', grid=u_south_intermediate, & 986 xmin = dx, xmax = lx - dx, & 987 ymin = -0.5_wp * dy, ymax = -0.5_wp * dy, & 988 x0=x0, y0=y0, z0 = z0, & 989 nx = nx-1, ny = 0, nz = nlev - 2) 990 991 CALL init_grid_definition('boundary intermediate', grid=u_top_intermediate, & 992 xmin = dx, xmax = lx - dx, & 993 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 776 994 x0=x0, y0=y0, z0 = z0, & 777 995 nx = nx-1, ny = ny, nz = nlev - 2) 778 996 779 CALL init_grid_definition('boundary intermediate', grid=v_initial_intermediate, & 780 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 997 CALL init_grid_definition('boundary intermediate', grid=v_east_intermediate, & 998 xmin = lx + 0.5_wp * dx, xmax = lx + 0.5_wp * dx, & 999 ymin = dy, ymax = ly - dy, & 1000 x0=x0, y0=y0, z0 = z0, & 1001 nx = 0, ny = ny-1, nz = nlev - 2) 1002 1003 CALL init_grid_definition('boundary intermediate', grid=v_west_intermediate, & 1004 xmin = -0.5_wp * dx, xmax = -0.5_wp * dx, & 1005 ymin = dy, ymax = ly - dy, & 1006 x0=x0, y0=y0, z0 = z0, & 1007 nx = 0, ny = ny-1, nz = nlev - 2) 1008 1009 CALL init_grid_definition('boundary intermediate', grid=v_north_intermediate, & 1010 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 1011 ymin = ly, ymax = ly, & 1012 x0=x0, y0=y0, z0 = z0, & 1013 nx = nx, ny = 0, nz = nlev - 2) 1014 1015 CALL init_grid_definition('boundary intermediate', grid=v_south_intermediate, & 1016 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 1017 ymin = 0.0_wp, ymax = 0.0_wp, & 1018 x0=x0, y0=y0, z0 = z0, & 1019 nx = nx, ny = 0, nz = nlev - 2) 1020 1021 CALL init_grid_definition('boundary intermediate', grid=v_top_intermediate, & 1022 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 781 1023 ymin = dy, ymax = ly - dy, & 782 1024 x0=x0, y0=y0, z0 = z0, & 783 1025 nx = nx, ny = ny-1, nz = nlev - 2) 784 1026 785 CALL init_grid_definition('boundary intermediate', grid=w_initial_intermediate, & 786 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 787 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 1027 CALL init_grid_definition('boundary intermediate', grid=w_east_intermediate, & 1028 xmin = lx + 0.5_wp * dx, xmax = lx + 0.5_wp * dx, & 1029 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 1030 x0=x0, y0=y0, z0 = z0, & 1031 nx = 0, ny = ny, nz = nlev - 1) 1032 1033 CALL init_grid_definition('boundary intermediate', grid=w_west_intermediate, & 1034 xmin = -0.5_wp * dx, xmax = -0.5_wp * dx, & 1035 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 1036 x0=x0, y0=y0, z0 = z0, & 1037 nx = 0, ny = ny, nz = nlev - 1) 1038 1039 CALL init_grid_definition('boundary intermediate', grid=w_north_intermediate, & 1040 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 1041 ymin = ly + 0.5_wp * dy, ymax = ly + 0.5_wp * dy, & 1042 x0=x0, y0=y0, z0 = z0, & 1043 nx = nx, ny = 0, nz = nlev - 1) 1044 1045 CALL init_grid_definition('boundary intermediate', grid=w_south_intermediate, & 1046 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 1047 ymin = -0.5_wp * dy, ymax = -0.5_wp * dy, & 1048 x0=x0, y0=y0, z0 = z0, & 1049 nx = nx, ny = 0, nz = nlev - 1) 1050 1051 CALL init_grid_definition('boundary intermediate', grid=w_top_intermediate, & 1052 xmin = 0.5_wp * dx, xmax = lx - 0.5_wp * dx, & 1053 ymin = 0.5_wp * dy, ymax = ly - 0.5_wp * dy, & 788 1054 x0=x0, y0=y0, z0 = z0, & 789 1055 nx = nx, ny = ny, nz = nlev - 1) 790 791 IF (boundary_variables_required) THEN 792 ! 793 !------------------------------------------------------------------------------ 794 ! Section 2: Define PALM-4U boundary grids 795 !------------------------------------------------------------------------------ 796 CALL init_grid_definition('boundary', grid=scalars_east_grid, & 797 xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx, & 798 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 799 x0=x0, y0=y0, z0 = z0, & 800 nx = 0, ny = ny, nz = nz, z=z) 801 802 CALL init_grid_definition('boundary', grid=scalars_west_grid, & 803 xmin = -0.5_dp * dx, xmax = -0.5_dp * dx, & 804 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 805 x0=x0, y0=y0, z0 = z0, & 806 nx = 0, ny = ny, nz = nz, z=z) 807 808 CALL init_grid_definition('boundary', grid=scalars_north_grid, & 809 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 810 ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy, & 811 x0=x0, y0=y0, z0 = z0, & 812 nx = nx, ny = 0, nz = nz, z=z) 813 814 CALL init_grid_definition('boundary', grid=scalars_south_grid, & 815 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 816 ymin = -0.5_dp * dy, ymax = -0.5_dp * dy, & 817 x0=x0, y0=y0, z0 = z0, & 818 nx = nx, ny = 0, nz = nz, z=z) 819 820 CALL init_grid_definition('boundary', grid=scalars_top_grid, & 821 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 822 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 823 x0=x0, y0=y0, z0 = z0, & 824 nx = nx, ny = ny, nz = 1, z=(/z_top/)) 825 826 CALL init_grid_definition('boundary', grid=u_east_grid, & 827 xmin = lx, xmax = lx, & 828 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 829 x0=x0, y0=y0, z0 = z0, & 830 nx = 0, ny = ny, nz = nz, z=z) 831 832 CALL init_grid_definition('boundary', grid=u_west_grid, & 833 xmin = 0.0_dp, xmax = 0.0_dp, & 834 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 835 x0=x0, y0=y0, z0 = z0, & 836 nx = 0, ny = ny, nz = nz, z=z) 837 838 CALL init_grid_definition('boundary', grid=u_north_grid, & 839 xmin = dx, xmax = lx - dx, & 840 ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy, & 841 x0=x0, y0=y0, z0 = z0, & 842 nx = nx-1, ny = 0, nz = nz, z=z) 843 844 CALL init_grid_definition('boundary', grid=u_south_grid, & 845 xmin = dx, xmax = lx - dx, & 846 ymin = -0.5_dp * dy, ymax = -0.5_dp * dy, & 847 x0=x0, y0=y0, z0 = z0, & 848 nx = nx-1, ny = 0, nz = nz, z=z) 849 850 CALL init_grid_definition('boundary', grid=u_top_grid, & 851 xmin = dx, xmax = lx - dx, & 852 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 853 x0=x0, y0=y0, z0 = z0, & 854 nx = nx-1, ny = ny, nz = 1, z=(/z_top/)) 855 856 CALL init_grid_definition('boundary', grid=v_east_grid, & 857 xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx, & 858 ymin = dy, ymax = ly - dy, & 859 x0=x0, y0=y0, z0 = z0, & 860 nx = 0, ny = ny-1, nz = nz, z=z) 861 862 CALL init_grid_definition('boundary', grid=v_west_grid, & 863 xmin = -0.5_dp * dx, xmax = -0.5_dp * dx, & 864 ymin = dy, ymax = ly - dy, & 865 x0=x0, y0=y0, z0 = z0, & 866 nx = 0, ny = ny-1, nz = nz, z=z) 867 868 CALL init_grid_definition('boundary', grid=v_north_grid, & 869 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 870 ymin = ly, ymax = ly, & 871 x0=x0, y0=y0, z0 = z0, & 872 nx = nx, ny = 0, nz = nz, z=z) 873 874 CALL init_grid_definition('boundary', grid=v_south_grid, & 875 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 876 ymin = 0.0_dp, ymax = 0.0_dp, & 877 x0=x0, y0=y0, z0 = z0, & 878 nx = nx, ny = 0, nz = nz, z=z) 879 880 CALL init_grid_definition('boundary', grid=v_top_grid, & 881 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 882 ymin = dy, ymax = ly - dy, & 883 x0=x0, y0=y0, z0 = z0, & 884 nx = nx, ny = ny-1, nz = 1, z=(/z_top/)) 885 886 CALL init_grid_definition('boundary', grid=w_east_grid, & 887 xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx, & 888 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 889 x0=x0, y0=y0, z0 = z0, & 890 nx = 0, ny = ny, nz = nz - 1, z=zw) 891 892 CALL init_grid_definition('boundary', grid=w_west_grid, & 893 xmin = -0.5_dp * dx, xmax = -0.5_dp * dx, & 894 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 895 x0=x0, y0=y0, z0 = z0, & 896 nx = 0, ny = ny, nz = nz - 1, z=zw) 897 898 CALL init_grid_definition('boundary', grid=w_north_grid, & 899 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 900 ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy, & 901 x0=x0, y0=y0, z0 = z0, & 902 nx = nx, ny = 0, nz = nz - 1, z=zw) 903 904 CALL init_grid_definition('boundary', grid=w_south_grid, & 905 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 906 ymin = -0.5_dp * dy, ymax = -0.5_dp * dy, & 907 x0=x0, y0=y0, z0 = z0, & 908 nx = nx, ny = 0, nz = nz - 1, z=zw) 909 910 CALL init_grid_definition('boundary', grid=w_top_grid, & 911 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 912 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 913 x0=x0, y0=y0, z0 = z0, & 914 nx = nx, ny = ny, nz = 1, z=(/zw_top/)) 915 916 CALL init_grid_definition('boundary intermediate', grid=scalars_east_intermediate, & 917 xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx, & 918 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 919 x0=x0, y0=y0, z0 = z0, & 920 nx = 0, ny = ny, nz = nlev - 2) 921 922 CALL init_grid_definition('boundary intermediate', grid=scalars_west_intermediate, & 923 xmin = -0.5_dp * dx, xmax = -0.5_dp * dx, & 924 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 925 x0=x0, y0=y0, z0 = z0, & 926 nx = 0, ny = ny, nz = nlev - 2) 927 928 CALL init_grid_definition('boundary intermediate', grid=scalars_north_intermediate, & 929 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 930 ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy, & 931 x0=x0, y0=y0, z0 = z0, & 932 nx = nx, ny = 0, nz = nlev - 2) 933 934 CALL init_grid_definition('boundary intermediate', grid=scalars_south_intermediate, & 935 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 936 ymin = -0.5_dp * dy, ymax = -0.5_dp * dy, & 937 x0=x0, y0=y0, z0 = z0, & 938 nx = nx, ny = 0, nz = nlev - 2) 939 940 CALL init_grid_definition('boundary intermediate', grid=scalars_top_intermediate, & 941 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 942 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 943 x0=x0, y0=y0, z0 = z0, & 944 nx = nx, ny = ny, nz = nlev - 2) 945 946 CALL init_grid_definition('boundary intermediate', grid=u_east_intermediate, & 947 xmin = lx, xmax = lx, & 948 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 949 x0=x0, y0=y0, z0 = z0, & 950 nx = 0, ny = ny, nz = nlev - 2) 951 952 CALL init_grid_definition('boundary intermediate', grid=u_west_intermediate, & 953 xmin = 0.0_dp, xmax = 0.0_dp, & 954 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 955 x0=x0, y0=y0, z0 = z0, & 956 nx = 0, ny = ny, nz = nlev - 2) 957 958 CALL init_grid_definition('boundary intermediate', grid=u_north_intermediate, & 959 xmin = dx, xmax = lx - dx, & 960 ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy, & 961 x0=x0, y0=y0, z0 = z0, & 962 nx = nx-1, ny = 0, nz = nlev - 2) 963 964 CALL init_grid_definition('boundary intermediate', grid=u_south_intermediate, & 965 xmin = dx, xmax = lx - dx, & 966 ymin = -0.5_dp * dy, ymax = -0.5_dp * dy, & 967 x0=x0, y0=y0, z0 = z0, & 968 nx = nx-1, ny = 0, nz = nlev - 2) 969 970 CALL init_grid_definition('boundary intermediate', grid=u_top_intermediate, & 971 xmin = dx, xmax = lx - dx, & 972 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 973 x0=x0, y0=y0, z0 = z0, & 974 nx = nx-1, ny = ny, nz = nlev - 2) 975 976 CALL init_grid_definition('boundary intermediate', grid=v_east_intermediate, & 977 xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx, & 978 ymin = dy, ymax = ly - dy, & 979 x0=x0, y0=y0, z0 = z0, & 980 nx = 0, ny = ny-1, nz = nlev - 2) 981 982 CALL init_grid_definition('boundary intermediate', grid=v_west_intermediate, & 983 xmin = -0.5_dp * dx, xmax = -0.5_dp * dx, & 984 ymin = dy, ymax = ly - dy, & 985 x0=x0, y0=y0, z0 = z0, & 986 nx = 0, ny = ny-1, nz = nlev - 2) 987 988 CALL init_grid_definition('boundary intermediate', grid=v_north_intermediate, & 989 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 990 ymin = ly, ymax = ly, & 991 x0=x0, y0=y0, z0 = z0, & 992 nx = nx, ny = 0, nz = nlev - 2) 993 994 CALL init_grid_definition('boundary intermediate', grid=v_south_intermediate, & 995 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 996 ymin = 0.0_dp, ymax = 0.0_dp, & 997 x0=x0, y0=y0, z0 = z0, & 998 nx = nx, ny = 0, nz = nlev - 2) 999 1000 CALL init_grid_definition('boundary intermediate', grid=v_top_intermediate, & 1001 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 1002 ymin = dy, ymax = ly - dy, & 1003 x0=x0, y0=y0, z0 = z0, & 1004 nx = nx, ny = ny-1, nz = nlev - 2) 1005 1006 CALL init_grid_definition('boundary intermediate', grid=w_east_intermediate, & 1007 xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx, & 1008 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 1009 x0=x0, y0=y0, z0 = z0, & 1010 nx = 0, ny = ny, nz = nlev - 1) 1011 1012 CALL init_grid_definition('boundary intermediate', grid=w_west_intermediate, & 1013 xmin = -0.5_dp * dx, xmax = -0.5_dp * dx, & 1014 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 1015 x0=x0, y0=y0, z0 = z0, & 1016 nx = 0, ny = ny, nz = nlev - 1) 1017 1018 CALL init_grid_definition('boundary intermediate', grid=w_north_intermediate, & 1019 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 1020 ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy, & 1021 x0=x0, y0=y0, z0 = z0, & 1022 nx = nx, ny = 0, nz = nlev - 1) 1023 1024 CALL init_grid_definition('boundary intermediate', grid=w_south_intermediate, & 1025 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 1026 ymin = -0.5_dp * dy, ymax = -0.5_dp * dy, & 1027 x0=x0, y0=y0, z0 = z0, & 1028 nx = nx, ny = 0, nz = nlev - 1) 1029 1030 CALL init_grid_definition('boundary intermediate', grid=w_top_intermediate, & 1031 xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx, & 1032 ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy, & 1033 x0=x0, y0=y0, z0 = z0, & 1034 nx = nx, ny = ny, nz = nlev - 1) 1035 ENDIF 1056 ENDIF 1036 1057 1037 1058 ! … … 1040 1061 !------------------------------------------------------------------------------ 1041 1062 1042 lonmin_palm = MINVAL(palm_intermediate %clon)1043 lonmax_palm = MAXVAL(palm_intermediate %clon)1044 latmin_palm = MINVAL(palm_intermediate %clat)1045 latmax_palm = MAXVAL(palm_intermediate %clat)1046 1047 1048 x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0, &1049 1050 1051 1052 1053 1054 x = 0.5_dp * lx, y = 0.5_dp * ly, z = zw, z0 = z0, &1055 1056 1057 1058 1059 1060 x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0, &1061 1062 1063 1064 1065 1066 x = 0.5_dp * lx, y = 0.5_dp * ly, z = zw, z0 = z0, &1067 1068 1069 1070 1071 1072 x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0, &1073 1074 1075 1076 1077 1078 1079 x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0, &1080 1081 1082 1083 1084 1085 1086 x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0, &1087 1088 1089 1090 1091 1092 1093 x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0, &1094 1095 1096 1097 1063 lonmin_palm = MINVAL(palm_intermediate%clon) 1064 lonmax_palm = MAXVAL(palm_intermediate%clon) 1065 latmin_palm = MINVAL(palm_intermediate%clat) 1066 latmax_palm = MAXVAL(palm_intermediate%clat) 1067 1068 CALL init_averaging_grid(averaged_initial_scalar_profile, cosmo_grid, & 1069 x = 0.5_wp * lx, y = 0.5_wp * ly, z = z, z0 = z0, & 1070 lonmin = lonmin_palm, lonmax = lonmax_palm, & 1071 latmin = latmin_palm, latmax = latmax_palm, & 1072 kind='scalar', name='averaged initial scalar') 1073 1074 CALL init_averaging_grid(averaged_initial_w_profile, cosmo_grid, & 1075 x = 0.5_wp * lx, y = 0.5_wp * ly, z = zw, z0 = z0, & 1076 lonmin = lonmin_palm, lonmax = lonmax_palm, & 1077 latmin = latmin_palm, latmax = latmax_palm, & 1078 kind='w', name='averaged initial w') 1079 1080 CALL init_averaging_grid(averaged_scalar_profile, cosmo_grid, & 1081 x = 0.5_wp * lx, y = 0.5_wp * ly, z = z, z0 = z0, & 1082 lonmin = lam_west, lonmax = lam_east, & 1083 latmin = phi_south, latmax = phi_north, & 1084 kind='scalar', name='centre geostrophic scalar') 1085 1086 CALL init_averaging_grid(averaged_w_profile, cosmo_grid, & 1087 x = 0.5_wp * lx, y = 0.5_wp * ly, z = zw, z0 = z0, & 1088 lonmin = lam_west, lonmax = lam_east, & 1089 latmin = phi_south, latmax = phi_north, & 1090 kind='w', name='centre geostrophic w') 1091 1092 CALL init_averaging_grid(south_averaged_scalar_profile, cosmo_grid, & 1093 x = 0.5_wp * lx, y = 0.5_wp * ly, z = z, z0 = z0, & 1094 lonmin = lam_west, lonmax = lam_east, & 1095 latmin = phi_centre - averaging_angle, & 1096 latmax = phi_centre, & 1097 kind='scalar', name='south geostrophic scalar') 1098 1099 CALL init_averaging_grid(north_averaged_scalar_profile, cosmo_grid, & 1100 x = 0.5_wp * lx, y = 0.5_wp * ly, z = z, z0 = z0, & 1101 lonmin = lam_west, lonmax = lam_east, & 1102 latmin = phi_centre, & 1103 latmax = phi_centre + averaging_angle, & 1104 kind='scalar', name='north geostrophic scalar') 1105 1106 CALL init_averaging_grid(west_averaged_scalar_profile, cosmo_grid, & 1107 x = 0.5_wp * lx, y = 0.5_wp * ly, z = z, z0 = z0, & 1108 lonmin = lam_centre - averaging_angle, & 1109 lonmax = lam_centre, & 1110 latmin = phi_south, latmax = phi_north, & 1111 kind='scalar', name='west geostrophic scalar') 1112 1113 CALL init_averaging_grid(east_averaged_scalar_profile, cosmo_grid, & 1114 x = 0.5_wp * lx, y = 0.5_wp * ly, z = z, z0 = z0, & 1115 lonmin = lam_centre, & 1116 lonmax = lam_centre + averaging_angle, & 1117 latmin = phi_south, latmax = phi_north, & 1118 kind='scalar', name='east geostrophic scalar') 1098 1119 1099 1120 … … 1102 1123 ! Section 4: Precompute neighbours and weights for interpolation 1103 1124 !------------------------------------------------------------------------------ 1104 interp_mode = 's' 1105 CALL setup_interpolation(cosmo_grid, palm_grid, palm_intermediate, interp_mode, ic_mode=cfg % ic_mode) 1106 IF (boundary_variables_required) THEN 1107 CALL setup_interpolation(cosmo_grid, scalars_east_grid, scalars_east_intermediate, interp_mode) 1108 CALL setup_interpolation(cosmo_grid, scalars_west_grid, scalars_west_intermediate, interp_mode) 1109 CALL setup_interpolation(cosmo_grid, scalars_north_grid, scalars_north_intermediate, interp_mode) 1110 CALL setup_interpolation(cosmo_grid, scalars_south_grid, scalars_south_intermediate, interp_mode) 1111 CALL setup_interpolation(cosmo_grid, scalars_top_grid, scalars_top_intermediate, interp_mode) 1112 ENDIF 1113 1114 interp_mode = 'u' 1115 CALL setup_interpolation(cosmo_grid, u_initial_grid, u_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode) 1116 IF (boundary_variables_required) THEN 1117 CALL setup_interpolation(cosmo_grid, u_east_grid, u_east_intermediate, interp_mode) 1118 CALL setup_interpolation(cosmo_grid, u_west_grid, u_west_intermediate, interp_mode) 1119 CALL setup_interpolation(cosmo_grid, u_north_grid, u_north_intermediate, interp_mode) 1120 CALL setup_interpolation(cosmo_grid, u_south_grid, u_south_intermediate, interp_mode) 1121 CALL setup_interpolation(cosmo_grid, u_top_grid, u_top_intermediate, interp_mode) 1122 ENDIF 1123 1124 interp_mode = 'v' 1125 CALL setup_interpolation(cosmo_grid, v_initial_grid, v_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode) 1126 IF (boundary_variables_required) THEN 1127 CALL setup_interpolation(cosmo_grid, v_east_grid, v_east_intermediate, interp_mode) 1128 CALL setup_interpolation(cosmo_grid, v_west_grid, v_west_intermediate, interp_mode) 1129 CALL setup_interpolation(cosmo_grid, v_north_grid, v_north_intermediate, interp_mode) 1130 CALL setup_interpolation(cosmo_grid, v_south_grid, v_south_intermediate, interp_mode) 1131 CALL setup_interpolation(cosmo_grid, v_top_grid, v_top_intermediate, interp_mode) 1132 ENDIF 1133 1134 interp_mode = 'w' 1135 CALL setup_interpolation(cosmo_grid, w_initial_grid, w_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode) 1136 IF (boundary_variables_required) THEN 1137 CALL setup_interpolation(cosmo_grid, w_east_grid, w_east_intermediate, interp_mode) 1138 CALL setup_interpolation(cosmo_grid, w_west_grid, w_west_intermediate, interp_mode) 1139 CALL setup_interpolation(cosmo_grid, w_north_grid, w_north_intermediate, interp_mode) 1140 CALL setup_interpolation(cosmo_grid, w_south_grid, w_south_intermediate, interp_mode) 1141 CALL setup_interpolation(cosmo_grid, w_top_grid, w_top_intermediate, interp_mode) 1142 ENDIF 1143 1144 IF (TRIM(cfg % ic_mode) == 'profile') THEN 1145 !TODO: remove this conditional if not needed. 1146 ENDIF 1147 1148 1149 END SUBROUTINE setup_grids 1125 interp_mode = 's' 1126 CALL setup_interpolation(cosmo_grid, palm_grid, palm_intermediate, interp_mode, ic_mode=cfg%ic_mode) 1127 IF (boundary_variables_required) THEN 1128 CALL setup_interpolation(cosmo_grid, scalars_east_grid, scalars_east_intermediate, interp_mode) 1129 CALL setup_interpolation(cosmo_grid, scalars_west_grid, scalars_west_intermediate, interp_mode) 1130 CALL setup_interpolation(cosmo_grid, scalars_north_grid, scalars_north_intermediate, interp_mode) 1131 CALL setup_interpolation(cosmo_grid, scalars_south_grid, scalars_south_intermediate, interp_mode) 1132 CALL setup_interpolation(cosmo_grid, scalars_top_grid, scalars_top_intermediate, interp_mode) 1133 ENDIF 1134 1135 interp_mode = 'u' 1136 CALL setup_interpolation(cosmo_grid, u_initial_grid, u_initial_intermediate, interp_mode, ic_mode=cfg%ic_mode) 1137 IF (boundary_variables_required) THEN 1138 CALL setup_interpolation(cosmo_grid, u_east_grid, u_east_intermediate, interp_mode) 1139 CALL setup_interpolation(cosmo_grid, u_west_grid, u_west_intermediate, interp_mode) 1140 CALL setup_interpolation(cosmo_grid, u_north_grid, u_north_intermediate, interp_mode) 1141 CALL setup_interpolation(cosmo_grid, u_south_grid, u_south_intermediate, interp_mode) 1142 CALL setup_interpolation(cosmo_grid, u_top_grid, u_top_intermediate, interp_mode) 1143 ENDIF 1144 1145 interp_mode = 'v' 1146 CALL setup_interpolation(cosmo_grid, v_initial_grid, v_initial_intermediate, interp_mode, ic_mode=cfg%ic_mode) 1147 IF (boundary_variables_required) THEN 1148 CALL setup_interpolation(cosmo_grid, v_east_grid, v_east_intermediate, interp_mode) 1149 CALL setup_interpolation(cosmo_grid, v_west_grid, v_west_intermediate, interp_mode) 1150 CALL setup_interpolation(cosmo_grid, v_north_grid, v_north_intermediate, interp_mode) 1151 CALL setup_interpolation(cosmo_grid, v_south_grid, v_south_intermediate, interp_mode) 1152 CALL setup_interpolation(cosmo_grid, v_top_grid, v_top_intermediate, interp_mode) 1153 ENDIF 1154 1155 interp_mode = 'w' 1156 CALL setup_interpolation(cosmo_grid, w_initial_grid, w_initial_intermediate, interp_mode, ic_mode=cfg%ic_mode) 1157 IF (boundary_variables_required) THEN 1158 CALL setup_interpolation(cosmo_grid, w_east_grid, w_east_intermediate, interp_mode) 1159 CALL setup_interpolation(cosmo_grid, w_west_grid, w_west_intermediate, interp_mode) 1160 CALL setup_interpolation(cosmo_grid, w_north_grid, w_north_intermediate, interp_mode) 1161 CALL setup_interpolation(cosmo_grid, w_south_grid, w_south_intermediate, interp_mode) 1162 CALL setup_interpolation(cosmo_grid, w_top_grid, w_top_intermediate, interp_mode) 1163 ENDIF 1164 1165 IF (TRIM(cfg%ic_mode) == 'profile') THEN 1166 !TODO: remove this conditional if not needed. 1167 ENDIF 1168 1169 END SUBROUTINE setup_grids 1150 1170 1151 1171 … … 1156 1176 !> vertical interpolation. 1157 1177 !------------------------------------------------------------------------------! 1158 1159 1160 1161 1162 1163 1164 1165 REAL(dp), DIMENSION(:), POINTER :: cosmo_lat, cosmo_lon1166 REAL(dp), DIMENSION(:,:,:), POINTER :: cosmo_h1167 1168 1178 SUBROUTINE setup_interpolation(cosmo_grid, grid, intermediate_grid, kind, ic_mode) 1179 1180 TYPE(grid_definition), INTENT(IN), TARGET :: cosmo_grid 1181 TYPE(grid_definition), INTENT(INOUT), TARGET :: grid, intermediate_grid 1182 CHARACTER, INTENT(IN) :: kind 1183 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: ic_mode 1184 1185 REAL(wp), DIMENSION(:), POINTER :: cosmo_lat, cosmo_lon 1186 REAL(wp), DIMENSION(:,:,:), POINTER :: cosmo_h 1187 1188 LOGICAL :: setup_volumetric 1169 1189 1170 1190 !------------------------------------------------------------------------------ … … 1172 1192 !------------------------------------------------------------------------------ 1173 1193 ! 1174 !-- 1175 1176 1177 ! 1178 !-- 1179 1180 1181 cosmo_lat => cosmo_grid %lat1182 cosmo_lon => cosmo_grid %lon1183 cosmo_h => cosmo_grid %hfl1184 ! 1185 !-- 1186 1187 1188 cosmo_lat => cosmo_grid %lat1189 cosmo_lon => cosmo_grid %lon1190 cosmo_h => cosmo_grid %hhl1191 ! 1192 !-- 1193 1194 1195 cosmo_lat => cosmo_grid %lat1196 cosmo_lon => cosmo_grid %lonu1197 cosmo_h => cosmo_grid %hfl1198 1199 ! 1200 !-- 1201 1202 1203 cosmo_lat => cosmo_grid %latv1204 cosmo_lon => cosmo_grid %lon1205 cosmo_h => cosmo_grid %hfl1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 intermediate_grid % clat, intermediate_grid %clon, &1216 intermediate_grid % ii, intermediate_grid %jj)1217 1218 1219 intermediate_grid % clat, intermediate_grid %clon, &1220 intermediate_grid % ii, intermediate_grid %jj, &1221 intermediate_grid %w_horiz)1194 !-- Select horizontal coordinates according to kind of points (s/w, u, v) 1195 SELECT CASE(kind) 1196 1197 ! 1198 !-- scalars 1199 CASE('s') 1200 1201 cosmo_lat => cosmo_grid%lat 1202 cosmo_lon => cosmo_grid%lon 1203 cosmo_h => cosmo_grid%hfl 1204 ! 1205 !-- vertical velocity 1206 CASE('w') 1207 1208 cosmo_lat => cosmo_grid%lat 1209 cosmo_lon => cosmo_grid%lon 1210 cosmo_h => cosmo_grid%hhl 1211 ! 1212 !-- x velocity 1213 CASE('u') 1214 1215 cosmo_lat => cosmo_grid%lat 1216 cosmo_lon => cosmo_grid%lonu 1217 cosmo_h => cosmo_grid%hfl 1218 1219 ! 1220 !-- y velocity 1221 CASE('v') 1222 1223 cosmo_lat => cosmo_grid%latv 1224 cosmo_lon => cosmo_grid%lon 1225 cosmo_h => cosmo_grid%hfl 1226 1227 CASE DEFAULT 1228 1229 message = "Interpolation quantity '" // kind // "' is not supported." 1230 CALL inifor_abort('setup_interpolation', message) 1231 1232 END SELECT 1233 1234 CALL find_horizontal_neighbours(cosmo_lat, cosmo_lon, & 1235 intermediate_grid%clat, intermediate_grid%clon, & 1236 intermediate_grid%ii, intermediate_grid%jj) 1237 1238 CALL compute_horizontal_interp_weights(cosmo_lat, cosmo_lon, & 1239 intermediate_grid%clat, intermediate_grid%clon, & 1240 intermediate_grid%ii, intermediate_grid%jj, & 1241 intermediate_grid%w_horiz) 1222 1242 1223 1243 !------------------------------------------------------------------------------ … … 1226 1246 1227 1247 ! 1228 !-- 1229 !-- 1230 !-- 1231 !-- 1232 !-- 1233 1234 1235 1236 1237 1238 1239 ALLOCATE( intermediate_grid % h(0:intermediate_grid %nx, &1240 0:intermediate_grid %ny, &1241 0:intermediate_grid %nz) )1242 intermediate_grid %h(:,:,:) = - EARTH_RADIUS1243 1244 ! 1245 !-- 1246 !-- 1247 CALL interpolate_2d(cosmo_h, intermediate_grid %h, intermediate_grid)1248 1249 1250 1251 1248 !-- If profile initialization is chosen, we--somewhat counterintuitively-- 1249 !-- don't need to compute vertical interpolation weights. At least, we 1250 !-- don't need them on the intermediate grid, which fills the entire PALM 1251 !-- domain volume. Instead we need vertical weights for the intermediate 1252 !-- profile grids, which get computed in setup_averaging(). 1253 setup_volumetric = .TRUE. 1254 IF (PRESENT(ic_mode)) THEN 1255 IF (TRIM(ic_mode) == 'profile') setup_volumetric = .FALSE. 1256 ENDIF 1257 1258 IF (setup_volumetric) THEN 1259 ALLOCATE( intermediate_grid%h(0:intermediate_grid%nx, & 1260 0:intermediate_grid%ny, & 1261 0:intermediate_grid%nz) ) 1262 intermediate_grid%h(:,:,:) = - EARTH_RADIUS 1263 1264 ! 1265 !-- For w points, use hhl, for scalars use hfl 1266 !-- compute the full heights for the intermediate grids 1267 CALL interpolate_2d(cosmo_h, intermediate_grid%h, intermediate_grid) 1268 CALL find_vertical_neighbours_and_weights_interp(grid, intermediate_grid) 1269 ENDIF 1270 1271 END SUBROUTINE setup_interpolation 1252 1272 1253 1273 !------------------------------------------------------------------------------! … … 1281 1301 !> grid : Grid variable to be initialized. 1282 1302 !------------------------------------------------------------------------------! 1283 1284 1285 1286 1287 1288 REAL(dp), INTENT(IN) :: xmin, xmax, ymin, ymax1289 REAL(dp), INTENT(IN) :: x0, y0, z01290 REAL(dp), INTENT(IN), TARGET, OPTIONAL :: z(:)1291 REAL(dp), INTENT(IN), TARGET, OPTIONAL :: zw(:)1292 1293 1294 grid %nx = nx1295 grid %ny = ny1296 grid %nz = nz1297 1298 grid %lx = xmax - xmin1299 grid %ly = ymax - ymin1300 1301 grid %x0 = x01302 grid %y0 = y01303 grid %z0 = z01304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 ALLOCATE( grid %x(0:nx) )1315 CALL linspace(xmin, xmax, grid %x)1316 1317 ALLOCATE( grid %y(0:ny) )1318 CALL linspace(ymin, ymax, grid %y)1319 1320 grid %z => z1321 1322 ! 1323 !-- 1324 1325 ALLOCATE( grid %kk(0:nx, 0:ny, 1:nz, 2) )1326 grid %kk(:,:,:,:) = -11327 1328 ALLOCATE( grid %w_verti(0:nx, 0:ny, 1:nz, 2) )1329 grid % w_verti(:,:,:,:) = 0.0_dp1330 1331 1332 1333 1334 ALLOCATE( grid %x(0:nx) )1335 CALL linspace(xmin, xmax, grid %x)1336 1337 ALLOCATE( grid %y(0:ny) )1338 CALL linspace(ymin, ymax, grid %y)1339 1340 ALLOCATE( grid % clon(0:nx, 0:ny), grid %clat(0:nx, 0:ny) )1341 1342 1343 phir = project( grid %y, y0, EARTH_RADIUS ) , & ! = plate-carree latitude1344 lamr = project( grid %x, x0, EARTH_RADIUS ) , & ! = plate-carree longitude1345 1346 phi = grid %clat, &1347 lam = grid %clon, &1348 1349 1350 1351 ! 1352 !-- 1353 ALLOCATE( grid %ii(0:nx, 0:ny, 4), &1354 grid %jj(0:nx, 0:ny, 4) )1355 grid %ii(:,:,:) = -11356 grid %jj(:,:,:) = -11357 1358 ALLOCATE( grid %w_horiz(0:nx, 0:ny, 4) )1359 grid % w_horiz(:,:,:) = 0.0_dp1360 1361 ! 1362 !-- 1363 !-- 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 grid %name(1) = 'x and lon'1377 grid %name(2) = 'y and lat'1378 grid %name(3) = 'z'1379 1380 ! 1381 !-- 1382 !-- 1383 ALLOCATE( grid % x(0:nx), grid %y(0:ny) )1384 ALLOCATE( grid % xu(1:nx), grid %yv(1:ny) )1385 CALL linspace(xmin + 0.5_dp* dx, xmax - 0.5_dp* dx, grid %x)1386 CALL linspace(ymin + 0.5_dp* dy, ymax - 0.5_dp* dy, grid %y)1387 grid %z => z1388 CALL linspace(xmin + dx, xmax - dx, grid %xu)1389 CALL linspace(ymin + dy, ymax - dy, grid %yv)1390 grid %zw => zw1391 1392 grid %depths => depths1393 1394 ! 1395 !-- 1396 1397 ALLOCATE( grid %kk(0:nx, 0:ny, 1:nz, 2) )1398 grid %kk(:,:,:,:) = -11399 1400 ALLOCATE( grid %w_verti(0:nx, 0:ny, 1:nz, 2) )1401 grid % w_verti(:,:,:,:) = 0.0_dp1402 1403 1404 1405 1406 grid %name(1) = 'x and lon'1407 grid %name(2) = 'y and lat'1408 grid %name(3) = 'interpolated hhl or hfl'1409 1410 ! 1411 !-- 1412 !-- 1413 ALLOCATE( grid % x(0:nx), grid %y(0:ny) )1414 ALLOCATE( grid % xu(1:nx), grid %yv(1:ny) )1415 CALL linspace(xmin + 0.5_dp*dx, xmax - 0.5_dp*dx, grid %x)1416 CALL linspace(ymin + 0.5_dp*dy, ymax - 0.5_dp*dy, grid %y)1417 CALL linspace(xmin + dx, xmax - dx, grid %xu)1418 CALL linspace(ymin + dy, ymax - dy, grid %yv)1419 1420 grid %depths => depths1421 1422 ! 1423 !-- 1424 ALLOCATE( grid % clon(0:nx, 0:ny), grid %clat(0:nx, 0:ny) )1425 ALLOCATE( grid % clonu(1:nx, 0:ny), grid %clatu(1:nx, 0:ny) )1426 ALLOCATE( grid % clonv(0:nx, 1:ny), grid %clatv(0:nx, 1:ny) )1427 1428 ! 1429 !-- 1430 !-- 1431 1432 phir = project( grid %y, y0, EARTH_RADIUS ) , & ! = plate-carree latitude1433 lamr = project( grid %x, x0, EARTH_RADIUS ) , & ! = plate-carree longitude1434 1435 phi = grid %clat, &1436 lam = grid %clon, &1437 1438 1439 1440 ! 1441 !-- 1442 1443 phir = project( grid %y, y0, EARTH_RADIUS ), & ! = plate-carree latitude1444 lamr = project( grid %xu, x0, EARTH_RADIUS ), & ! = plate-carree longitude1445 1446 phi = grid %clatu, &1447 lam = grid %clonu, &1448 1449 1450 1451 ! 1452 !-- 1453 1454 phir = project( grid %yv, y0, EARTH_RADIUS ), & ! = plate-carree latitude1455 lamr = project( grid %x, x0, EARTH_RADIUS ), & ! = plate-carree longitude1456 1457 phi = grid %clatv, &1458 lam = grid %clonv, &1459 1460 1461 1462 ! 1463 !-- 1464 ALLOCATE( grid %ii(0:nx, 0:ny, 4), &1465 grid %jj(0:nx, 0:ny, 4) )1466 grid %ii(:,:,:) = -11467 grid %jj(:,:,:) = -11468 1469 ALLOCATE( grid %w_horiz(0:nx, 0:ny, 4) )1470 grid % w_horiz(:,:,:) = 0.0_dp1471 1472 1473 grid %name(1) = 'rlon' ! of COMSO-DE cell centres (scalars)1474 grid %name(2) = 'rlat' ! of COMSO-DE cell centres (scalars)1475 grid %name(3) = 'height'1476 1477 ALLOCATE( grid % lon(0:nx), grid %lat(0:ny) )1478 ALLOCATE( grid % lonu(0:nx), grid %latv(0:ny) )1479 1480 CALL linspace(xmin, xmax, grid %lon)1481 CALL linspace(ymin, ymax, grid %lat)1482 grid % lonu(:) = grid % lon + 0.5_dp * (grid % lx / grid %nx)1483 grid % latv(:) = grid % lat + 0.5_dp * (grid % ly / grid %ny)1484 1485 ! 1486 !-- 1487 !-- 1488 grid %hhl => hhl1489 grid %hfl => hfl1490 grid %depths => depths1491 1492 1493 1494 1495 1496 1497 1498 1303 SUBROUTINE init_grid_definition(kind, xmin, xmax, ymin, ymax, & 1304 x0, y0, z0, nx, ny, nz, z, zw, grid, ic_mode) 1305 CHARACTER(LEN=*), INTENT(IN) :: kind 1306 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: ic_mode 1307 INTEGER, INTENT(IN) :: nx, ny, nz 1308 REAL(wp), INTENT(IN) :: xmin, xmax, ymin, ymax 1309 REAL(wp), INTENT(IN) :: x0, y0, z0 1310 REAL(wp), INTENT(IN), TARGET, OPTIONAL :: z(:) 1311 REAL(wp), INTENT(IN), TARGET, OPTIONAL :: zw(:) 1312 TYPE(grid_definition), INTENT(INOUT) :: grid 1313 1314 grid%nx = nx 1315 grid%ny = ny 1316 grid%nz = nz 1317 1318 grid%lx = xmax - xmin 1319 grid%ly = ymax - ymin 1320 1321 grid%x0 = x0 1322 grid%y0 = y0 1323 grid%z0 = z0 1324 1325 SELECT CASE( TRIM(kind) ) 1326 1327 CASE('boundary') 1328 1329 IF (.NOT.PRESENT(z)) THEN 1330 message = "z has not been passed but is required for 'boundary' grids" 1331 CALL inifor_abort('init_grid_definition', message) 1332 ENDIF 1333 1334 ALLOCATE( grid%x(0:nx) ) 1335 CALL linspace(xmin, xmax, grid%x) 1336 1337 ALLOCATE( grid%y(0:ny) ) 1338 CALL linspace(ymin, ymax, grid%y) 1339 1340 grid%z => z 1341 1342 ! 1343 !-- Allocate neighbour indices and weights 1344 IF (TRIM(ic_mode) .NE. 'profile') THEN 1345 ALLOCATE( grid%kk(0:nx, 0:ny, 1:nz, 2) ) 1346 grid%kk(:,:,:,:) = -1 1347 1348 ALLOCATE( grid%w_verti(0:nx, 0:ny, 1:nz, 2) ) 1349 grid%w_verti(:,:,:,:) = 0.0_wp 1350 ENDIF 1351 1352 CASE('boundary intermediate') 1353 1354 ALLOCATE( grid%x(0:nx) ) 1355 CALL linspace(xmin, xmax, grid%x) 1356 1357 ALLOCATE( grid%y(0:ny) ) 1358 CALL linspace(ymin, ymax, grid%y) 1359 1360 ALLOCATE( grid%clon(0:nx, 0:ny), grid%clat(0:nx, 0:ny) ) 1361 1362 CALL rotate_to_cosmo( & 1363 phir = project( grid%y, y0, EARTH_RADIUS ) , & ! = plate-carree latitude 1364 lamr = project( grid%x, x0, EARTH_RADIUS ) , & ! = plate-carree longitude 1365 phip = phi_cn, lamp = lambda_cn, & 1366 phi = grid%clat, & 1367 lam = grid%clon, & 1368 gam = gam & 1369 ) 1370 1371 ! 1372 !-- Allocate neighbour indices and weights 1373 ALLOCATE( grid%ii(0:nx, 0:ny, 4), & 1374 grid%jj(0:nx, 0:ny, 4) ) 1375 grid%ii(:,:,:) = -1 1376 grid%jj(:,:,:) = -1 1377 1378 ALLOCATE( grid%w_horiz(0:nx, 0:ny, 4) ) 1379 grid%w_horiz(:,:,:) = 0.0_wp 1380 1381 ! 1382 !-- This mode initializes a Cartesian PALM-4U grid and adds the 1383 !-- corresponding latitudes and longitudes of the rotated pole grid. 1384 CASE('palm') 1385 1386 IF (.NOT.PRESENT(z)) THEN 1387 message = "z has not been passed but is required for 'palm' grids" 1388 CALL inifor_abort('init_grid_definition', message) 1389 ENDIF 1390 1391 IF (.NOT.PRESENT(zw)) THEN 1392 message = "zw has not been passed but is required for 'palm' grids" 1393 CALL inifor_abort('init_grid_definition', message) 1394 ENDIF 1395 1396 grid%name(1) = 'x and lon' 1397 grid%name(2) = 'y and lat' 1398 grid%name(3) = 'z' 1399 1400 ! 1401 !-- TODO: Remove use of global dx, dy, dz variables. Consider 1402 !-- TODO: associating global x,y, and z arrays. 1403 ALLOCATE( grid%x(0:nx), grid%y(0:ny) ) 1404 ALLOCATE( grid%xu(1:nx), grid%yv(1:ny) ) 1405 CALL linspace(xmin + 0.5_wp* dx, xmax - 0.5_wp* dx, grid%x) 1406 CALL linspace(ymin + 0.5_wp* dy, ymax - 0.5_wp* dy, grid%y) 1407 grid%z => z 1408 CALL linspace(xmin + dx, xmax - dx, grid%xu) 1409 CALL linspace(ymin + dy, ymax - dy, grid%yv) 1410 grid%zw => zw 1411 1412 grid%depths => depths 1413 1414 ! 1415 !-- Allocate neighbour indices and weights 1416 IF (TRIM(ic_mode) .NE. 'profile') THEN 1417 ALLOCATE( grid%kk(0:nx, 0:ny, 1:nz, 2) ) 1418 grid%kk(:,:,:,:) = -1 1419 1420 ALLOCATE( grid%w_verti(0:nx, 0:ny, 1:nz, 2) ) 1421 grid%w_verti(:,:,:,:) = 0.0_wp 1422 ENDIF 1423 1424 CASE('palm intermediate') 1425 1426 grid%name(1) = 'x and lon' 1427 grid%name(2) = 'y and lat' 1428 grid%name(3) = 'interpolated hhl or hfl' 1429 1430 ! 1431 !-- TODO: Remove use of global dx, dy, dz variables. Consider 1432 !-- TODO: associating global x,y, and z arrays. 1433 ALLOCATE( grid%x(0:nx), grid%y(0:ny) ) 1434 ALLOCATE( grid%xu(1:nx), grid%yv(1:ny) ) 1435 CALL linspace(xmin + 0.5_wp*dx, xmax - 0.5_wp*dx, grid%x) 1436 CALL linspace(ymin + 0.5_wp*dy, ymax - 0.5_wp*dy, grid%y) 1437 CALL linspace(xmin + dx, xmax - dx, grid%xu) 1438 CALL linspace(ymin + dy, ymax - dy, grid%yv) 1439 1440 grid%depths => depths 1441 1442 ! 1443 !-- Allocate rotated-pole coordinates, clon is for (c)osmo-de (lon)gitude 1444 ALLOCATE( grid%clon(0:nx, 0:ny), grid%clat(0:nx, 0:ny) ) 1445 ALLOCATE( grid%clonu(1:nx, 0:ny), grid%clatu(1:nx, 0:ny) ) 1446 ALLOCATE( grid%clonv(0:nx, 1:ny), grid%clatv(0:nx, 1:ny) ) 1447 1448 ! 1449 !-- Compute rotated-pole coordinates of... 1450 !-- ... PALM-4U centres 1451 CALL rotate_to_cosmo( & 1452 phir = project( grid%y, y0, EARTH_RADIUS ) , & ! = plate-carree latitude 1453 lamr = project( grid%x, x0, EARTH_RADIUS ) , & ! = plate-carree longitude 1454 phip = phi_cn, lamp = lambda_cn, & 1455 phi = grid%clat, & 1456 lam = grid%clon, & 1457 gam = gam & 1458 ) 1459 1460 ! 1461 !-- ... PALM-4U u winds 1462 CALL rotate_to_cosmo( & 1463 phir = project( grid%y, y0, EARTH_RADIUS ), & ! = plate-carree latitude 1464 lamr = project( grid%xu, x0, EARTH_RADIUS ), & ! = plate-carree longitude 1465 phip = phi_cn, lamp = lambda_cn, & 1466 phi = grid%clatu, & 1467 lam = grid%clonu, & 1468 gam = gam & 1469 ) 1470 1471 ! 1472 !-- ... PALM-4U v winds 1473 CALL rotate_to_cosmo( & 1474 phir = project( grid%yv, y0, EARTH_RADIUS ), & ! = plate-carree latitude 1475 lamr = project( grid%x, x0, EARTH_RADIUS ), & ! = plate-carree longitude 1476 phip = phi_cn, lamp = lambda_cn, & 1477 phi = grid%clatv, & 1478 lam = grid%clonv, & 1479 gam = gam & 1480 ) 1481 1482 ! 1483 !-- Allocate neighbour indices and weights 1484 ALLOCATE( grid%ii(0:nx, 0:ny, 4), & 1485 grid%jj(0:nx, 0:ny, 4) ) 1486 grid%ii(:,:,:) = -1 1487 grid%jj(:,:,:) = -1 1488 1489 ALLOCATE( grid%w_horiz(0:nx, 0:ny, 4) ) 1490 grid%w_horiz(:,:,:) = 0.0_wp 1491 1492 CASE('cosmo-de') 1493 grid%name(1) = 'rlon' ! of COMSO-DE cell centres (scalars) 1494 grid%name(2) = 'rlat' ! of COMSO-DE cell centres (scalars) 1495 grid%name(3) = 'height' 1496 1497 ALLOCATE( grid%lon(0:nx), grid%lat(0:ny) ) 1498 ALLOCATE( grid%lonu(0:nx), grid%latv(0:ny) ) 1499 1500 CALL linspace(xmin, xmax, grid%lon) 1501 CALL linspace(ymin, ymax, grid%lat) 1502 grid%lonu(:) = grid%lon + 0.5_wp * (grid%lx / grid%nx) 1503 grid%latv(:) = grid%lat + 0.5_wp * (grid%ly / grid%ny) 1504 1505 ! 1506 !-- Point to heights of half levels (hhl) and compute heights of full 1507 !-- levels (hfl) as arithmetic averages 1508 grid%hhl => hhl 1509 grid%hfl => hfl 1510 grid%depths => depths 1511 1512 CASE DEFAULT 1513 message = "Grid kind '" // TRIM(kind) // "' is not recognized." 1514 CALL inifor_abort('init_grid_definition', message) 1515 1516 END SELECT 1517 1518 END SUBROUTINE init_grid_definition 1499 1519 1500 1520 … … 1527 1547 !> avg_grid : averagin grid to be initialized 1528 1548 !------------------------------------------------------------------------------! 1529 1530 1531 1532 1533 1534 REAL(dp), INTENT(IN) :: x, y, z01535 REAL(dp), INTENT(IN), TARGET :: z(:)1536 REAL(dp), INTENT(IN) :: lonmin !< lower longitude bound of the averaging grid region [COSMO rotated-pole rad]1537 REAL(dp), INTENT(IN) :: lonmax !< upper longitude bound of the averaging grid region [COSMO rotated-pole rad]1538 REAL(dp), INTENT(IN) :: latmin !< lower latitude bound of the averaging grid region [COSMO rotated-pole rad]1539 REAL(dp), INTENT(IN) :: latmax !< lower latitude bound of the averaging grid region [COSMO rotated-pole rad]1540 1541 1542 1543 1544 1545 1546 ALLOCATE( avg_grid %x(1) )1547 ALLOCATE( avg_grid %y(1) )1548 avg_grid %x(1) = x1549 avg_grid %y(1) = y1550 avg_grid %z => z1551 avg_grid %z0 = z01552 1553 avg_grid %nz = SIZE(z, 1)1554 1555 ALLOCATE( avg_grid %lon(2) )1556 ALLOCATE( avg_grid %lat(2) )1557 avg_grid %lon(1:2) = (/lonmin, lonmax/)1558 avg_grid %lat(1:2) = (/latmin, latmax/)1559 1560 avg_grid %kind = TRIM(kind)1561 avg_grid %name(1) = TRIM(name)1562 1563 ! 1564 !-- 1565 !-- given by avg_grid % clon, %clat1566 1567 1568 ALLOCATE (avg_grid % kkk(avg_grid % n_columns, avg_grid %nz, 2) )1569 ALLOCATE (avg_grid % w(avg_grid % n_columns, avg_grid %nz, 2) )1570 ! 1571 !-- 1572 SELECT CASE(avg_grid %kind)1549 SUBROUTINE init_averaging_grid(avg_grid, cosmo_grid, x, y, z, z0, & 1550 lonmin, lonmax, latmin, latmax, kind, name) 1551 1552 TYPE(grid_definition), INTENT(INOUT) :: avg_grid 1553 TYPE(grid_definition), INTENT(IN) :: cosmo_grid 1554 REAL(wp), INTENT(IN) :: x, y, z0 1555 REAL(wp), INTENT(IN), TARGET :: z(:) 1556 REAL(wp), INTENT(IN) :: lonmin !< lower longitude bound of the averaging grid region [COSMO rotated-pole rad] 1557 REAL(wp), INTENT(IN) :: lonmax !< upper longitude bound of the averaging grid region [COSMO rotated-pole rad] 1558 REAL(wp), INTENT(IN) :: latmin !< lower latitude bound of the averaging grid region [COSMO rotated-pole rad] 1559 REAL(wp), INTENT(IN) :: latmax !< lower latitude bound of the averaging grid region [COSMO rotated-pole rad] 1560 1561 CHARACTER(LEN=*), INTENT(IN) :: kind 1562 CHARACTER(LEN=*), INTENT(IN) :: name 1563 1564 LOGICAL :: level_based_averaging 1565 1566 ALLOCATE( avg_grid%x(1) ) 1567 ALLOCATE( avg_grid%y(1) ) 1568 avg_grid%x(1) = x 1569 avg_grid%y(1) = y 1570 avg_grid%z => z 1571 avg_grid%z0 = z0 1572 1573 avg_grid%nz = SIZE(z, 1) 1574 1575 ALLOCATE( avg_grid%lon(2) ) 1576 ALLOCATE( avg_grid%lat(2) ) 1577 avg_grid%lon(1:2) = (/lonmin, lonmax/) 1578 avg_grid%lat(1:2) = (/latmin, latmax/) 1579 1580 avg_grid%kind = TRIM(kind) 1581 avg_grid%name(1) = TRIM(name) 1582 1583 ! 1584 !-- Find and store COSMO columns that fall into the coordinate range 1585 !-- given by avg_grid%clon, %clat 1586 CALL get_cosmo_averaging_region(avg_grid, cosmo_grid) 1587 1588 ALLOCATE (avg_grid%kkk(avg_grid%n_columns, avg_grid%nz, 2) ) 1589 ALLOCATE (avg_grid%w(avg_grid%n_columns, avg_grid%nz, 2) ) 1590 ! 1591 !-- Compute average COSMO levels in the averaging region 1592 SELECT CASE(avg_grid%kind) 1573 1593 1574 1594 CASE('scalar', 'u', 'v') 1575 avg_grid % cosmo_h => cosmo_grid %hfl1595 avg_grid%cosmo_h => cosmo_grid%hfl 1576 1596 1577 1597 CASE('w') 1578 avg_grid % cosmo_h => cosmo_grid %hhl1598 avg_grid%cosmo_h => cosmo_grid%hhl 1579 1599 1580 1600 CASE DEFAULT 1581 message = "Averaging grid kind '" // TRIM(avg_grid %kind) // &1601 message = "Averaging grid kind '" // TRIM(avg_grid%kind) // & 1582 1602 "' is not supported. Use 'scalar', 'u', or 'v'." 1583 1603 CALL inifor_abort('get_cosmo_averaging_region', message) 1584 1604 1585 END SELECT 1586 1587 ! 1588 !-- For level-besed averaging, compute average heights 1589 !level_based_averaging = ( TRIM(mode) == 'level' ) 1590 level_based_averaging = ( TRIM(cfg % averaging_mode) == 'level' ) 1591 IF (level_based_averaging) THEN 1592 ALLOCATE(avg_grid % h(1,1,SIZE(avg_grid % cosmo_h, 3)) ) 1605 END SELECT 1606 1607 ! 1608 !-- For level-besed averaging, compute average heights 1609 level_based_averaging = ( TRIM(cfg%averaging_mode) == 'level' ) 1610 IF (level_based_averaging) THEN 1611 ALLOCATE(avg_grid%h(1,1,SIZE(avg_grid%cosmo_h, 3)) ) 1593 1612 1594 CALL average_2d(avg_grid % cosmo_h, avg_grid %h(1,1,:), &1595 avg_grid % iii, avg_grid %jjj)1596 1597 1598 1599 ! 1600 !-- 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 REAL(dp), DIMENSION(:), POINTER :: cosmo_lon, cosmo_lat1613 REAL(dp) :: dlon, dlat1614 1615 1616 1617 1618 SELECT CASE( TRIM(avg_grid %kind) )1613 CALL average_2d(avg_grid%cosmo_h, avg_grid%h(1,1,:), & 1614 avg_grid%iii, avg_grid%jjj) 1615 1616 ENDIF 1617 1618 ! 1619 !-- Compute vertical weights and neighbours 1620 CALL find_vertical_neighbours_and_weights_average( & 1621 avg_grid, level_based_averaging & 1622 ) 1623 1624 END SUBROUTINE init_averaging_grid 1625 1626 1627 SUBROUTINE get_cosmo_averaging_region(avg_grid, cosmo_grid) 1628 TYPE(grid_definition), INTENT(INOUT) :: avg_grid 1629 TYPE(grid_definition), TARGET, INTENT(IN) :: cosmo_grid 1630 1631 REAL(wp), DIMENSION(:), POINTER :: cosmo_lon, cosmo_lat 1632 REAL(wp) :: dlon, dlat 1633 1634 INTEGER :: i, j, imin, imax, jmin, jmax, l, nx, ny 1635 1636 1637 SELECT CASE( TRIM(avg_grid%kind) ) 1619 1638 1620 1639 CASE('scalar', 'w') 1621 cosmo_lon => cosmo_grid %lon1622 cosmo_lat => cosmo_grid %lat1640 cosmo_lon => cosmo_grid%lon 1641 cosmo_lat => cosmo_grid%lat 1623 1642 1624 1643 CASE('u') 1625 cosmo_lon => cosmo_grid %lonu1626 cosmo_lat => cosmo_grid %lat1644 cosmo_lon => cosmo_grid%lonu 1645 cosmo_lat => cosmo_grid%lat 1627 1646 1628 1647 CASE('v') 1629 cosmo_lon => cosmo_grid %lon1630 cosmo_lat => cosmo_grid %latv1648 cosmo_lon => cosmo_grid%lon 1649 cosmo_lat => cosmo_grid%latv 1631 1650 1632 1651 CASE DEFAULT 1633 message = "Averaging grid kind '" // TRIM(avg_grid %kind) // &1652 message = "Averaging grid kind '" // TRIM(avg_grid%kind) // & 1634 1653 "' is not supported. Use 'scalar', 'u', or 'v'." 1635 1654 CALL inifor_abort('get_cosmo_averaging_region', message) 1636 1655 1637 1638 1639 ! 1640 !-- 1641 1642 1643 1644 imin = FLOOR ( (avg_grid %lon(1) - cosmo_lon(0)) / dlon )1645 imax = CEILING( (avg_grid %lon(2) - cosmo_lon(0)) / dlon )1646 1647 jmin = FLOOR ( (avg_grid %lat(1) - cosmo_lat(0)) / dlat )1648 jmax = CEILING( (avg_grid %lat(2) - cosmo_lat(0)) / dlat )1649 1650 message = "Grid " // TRIM(avg_grid %name(1)) // " averages over " // &1651 1652 1653 1654 1655 1656 1657 1658 avg_grid %n_columns = nx * ny1659 1660 ALLOCATE( avg_grid % iii(avg_grid %n_columns), &1661 avg_grid % jjj(avg_grid %n_columns) )1662 1663 1664 DOj = jmin, jmax1665 DOi = imin, imax1666 1667 avg_grid %iii(l) = i1668 avg_grid %jjj(l) = j1669 1670 1671 1672 1656 END SELECT 1657 1658 ! 1659 !-- FIXME: make dlon, dlat parameters of the grid_defintion type 1660 dlon = cosmo_lon(1) - cosmo_lon(0) 1661 dlat = cosmo_lat(1) - cosmo_lat(0) 1662 1663 imin = FLOOR ( (avg_grid%lon(1) - cosmo_lon(0)) / dlon ) 1664 imax = CEILING( (avg_grid%lon(2) - cosmo_lon(0)) / dlon ) 1665 1666 jmin = FLOOR ( (avg_grid%lat(1) - cosmo_lat(0)) / dlat ) 1667 jmax = CEILING( (avg_grid%lat(2) - cosmo_lat(0)) / dlat ) 1668 1669 message = "Grid " // TRIM(avg_grid%name(1)) // " averages over " // & 1670 TRIM(str(imin)) // " <= i <= " // TRIM(str(imax)) // & 1671 " and " // & 1672 TRIM(str(jmin)) // " <= j <= " // TRIM(str(jmax)) 1673 CALL report( 'get_cosmo_averaging_region', message ) 1674 1675 nx = imax - imin + 1 1676 ny = jmax - jmin + 1 1677 avg_grid%n_columns = nx * ny 1678 1679 ALLOCATE( avg_grid%iii(avg_grid%n_columns), & 1680 avg_grid%jjj(avg_grid%n_columns) ) 1681 1682 l = 0 1683 DO j = jmin, jmax 1684 DO i = imin, imax 1685 l = l + 1 1686 avg_grid%iii(l) = i 1687 avg_grid%jjj(l) = j 1688 ENDDO 1689 ENDDO 1690 1691 END SUBROUTINE get_cosmo_averaging_region 1673 1692 1674 1693 … … 1683 1702 !> 'modpoints'. 1684 1703 !------------------------------------------------------------------------------! 1685 1686 1687 1688 1689 REAL(dp), DIMENSION(:), INTENT(INOUT) :: z, dz, dz_stretch_factor_array1690 REAL(dp), DIMENSION(:), INTENT(INOUT) :: dz_stretch_level_start, dz_stretch_level_end1691 REAL(dp), INTENT(IN) :: dz_max, dz_stretch_factor, dz_stretch_level1692 1693 1694 1695 1696 REAL(dp), DIMENSION(:), ALLOCATABLE :: min_dz_stretch_level_end1697 REAL(dp) :: dz_level_end, dz_stretched1698 1699 1700 1701 1702 1704 SUBROUTINE stretched_z(z, dz, dz_max, dz_stretch_factor, dz_stretch_level, & 1705 dz_stretch_level_start, dz_stretch_level_end, & 1706 dz_stretch_factor_array) 1707 1708 REAL(wp), DIMENSION(:), INTENT(INOUT) :: z, dz, dz_stretch_factor_array 1709 REAL(wp), DIMENSION(:), INTENT(INOUT) :: dz_stretch_level_start, dz_stretch_level_end 1710 REAL(wp), INTENT(IN) :: dz_max, dz_stretch_factor, dz_stretch_level 1711 1712 INTEGER :: number_stretch_level_start !< number of user-specified start levels for stretching 1713 INTEGER :: number_stretch_level_end !< number of user-specified end levels for stretching 1714 1715 REAL(wp), DIMENSION(:), ALLOCATABLE :: min_dz_stretch_level_end 1716 REAL(wp) :: dz_level_end, dz_stretched 1717 1718 INTEGER :: dz_stretch_level_end_index(9) !< vertical grid level index until which the vertical grid spacing is stretched 1719 INTEGER :: dz_stretch_level_start_index(9) !< vertical grid level index above which the vertical grid spacing is stretched 1720 INTEGER :: dz_stretch_level_index = 0 1721 INTEGER :: k, n, number_dz 1703 1722 1704 1723 ! 1705 1724 !-- Compute height of u-levels from constant grid length and dz stretch factors 1706 IF ( dz(1) == -1.0_dp ) THEN1707 1708 1709 ELSEIF ( dz(1) <= 0.0_dp ) THEN1710 1711 1712 1725 IF ( dz(1) == -1.0_wp ) THEN 1726 message = 'missing dz' 1727 CALL inifor_abort( 'stretched_z', message) 1728 ELSEIF ( dz(1) <= 0.0_wp ) THEN 1729 WRITE( message, * ) 'dz=', dz(1),' <= 0.0' 1730 CALL inifor_abort( 'stretched_z', message) 1731 ENDIF 1713 1732 1714 1733 ! 1715 1734 !-- Initialize dz_stretch_level_start with the value of dz_stretch_level 1716 1735 !-- if it was set by the user 1717 IF ( dz_stretch_level /= -9999999.9_dp )THEN1718 1719 1736 IF ( dz_stretch_level /= -9999999.9_wp ) THEN 1737 dz_stretch_level_start(1) = dz_stretch_level 1738 ENDIF 1720 1739 1721 1740 ! … … 1727 1746 !-- is used (Attention: The user is not allowed to specify a dz value equal 1728 1747 !-- to the default of dz_max = 999.0). 1729 number_dz = COUNT( dz /= -1.0_dp .AND. dz /= dz_max )1730 1731 -9999999.9_dp )1732 1733 9999999.9_dp )1748 number_dz = COUNT( dz /= -1.0_wp .AND. dz /= dz_max ) 1749 number_stretch_level_start = COUNT( dz_stretch_level_start /= & 1750 -9999999.9_wp ) 1751 number_stretch_level_end = COUNT( dz_stretch_level_end /= & 1752 9999999.9_wp ) 1734 1753 1735 1754 ! 1736 1755 !-- The number of specified end levels +1 has to be the same than the number 1737 1756 !-- of specified dz values 1738 IF ( number_dz /= number_stretch_level_end + 1 )THEN1739 1740 1741 1742 1743 1744 1745 1757 IF ( number_dz /= number_stretch_level_end + 1 ) THEN 1758 WRITE( message, * ) 'The number of values for dz = ', & 1759 number_dz, 'has to be the same than ', & 1760 'the number of values for ', & 1761 'dz_stretch_level_end + 1 = ', & 1762 number_stretch_level_end+1 1763 CALL inifor_abort( 'stretched_z', message) 1764 ENDIF 1746 1765 1747 1766 ! 1748 !-- 1749 !-- 1750 1751 number_dz /= number_stretch_level_start )THEN1752 1753 1754 1755 1756 1757 1758 1767 !-- The number of specified start levels has to be the same or one less than 1768 !-- the number of specified dz values 1769 IF ( number_dz /= number_stretch_level_start + 1 .AND. & 1770 number_dz /= number_stretch_level_start ) THEN 1771 WRITE( message, * ) 'The number of values for dz = ', & 1772 number_dz, 'has to be the same or one ', & 1773 'more than& the number of values for ', & 1774 'dz_stretch_level_start = ', & 1775 number_stretch_level_start 1776 CALL inifor_abort( 'stretched_z', message) 1777 ENDIF 1759 1778 1760 !-- 1761 !-- 1762 1763 number_stretch_level_start /= number_stretch_level_end )THEN1764 1765 1766 1767 1768 1769 1770 1771 1779 !-- The number of specified start levels has to be the same or one more than 1780 !-- the number of specified end levels 1781 IF ( number_stretch_level_start /= number_stretch_level_end + 1 .AND. & 1782 number_stretch_level_start /= number_stretch_level_end ) THEN 1783 WRITE( message, * ) 'The number of values for ', & 1784 'dz_stretch_level_start = ', & 1785 dz_stretch_level_start, 'has to be the ',& 1786 'same or one more than& the number of ', & 1787 'values for dz_stretch_level_end = ', & 1788 number_stretch_level_end 1789 CALL inifor_abort( 'stretched_z', message) 1790 ENDIF 1772 1791 1773 1792 ! 1774 1793 !-- Initialize dz for the free atmosphere with the value of dz_max 1775 IF ( dz(number_stretch_level_start+1) == -1.0_dp .AND. &1776 number_stretch_level_start /= 0 )THEN1777 1778 1794 IF ( dz(number_stretch_level_start+1) == -1.0_wp .AND. & 1795 number_stretch_level_start /= 0 ) THEN 1796 dz(number_stretch_level_start+1) = dz_max 1797 ENDIF 1779 1798 1780 1799 ! … … 1782 1801 !-- atmosphere is desired (dz_stretch_level_end was not specified for the 1783 1802 !-- free atmosphere) 1784 IF ( number_stretch_level_start == number_stretch_level_end + 1 ) THEN 1785 dz_stretch_factor_array(number_stretch_level_start) = & 1786 dz_stretch_factor 1803 IF ( number_stretch_level_start == number_stretch_level_end + 1 ) THEN 1804 dz_stretch_factor_array(number_stretch_level_start) = & 1805 dz_stretch_factor 1806 ENDIF 1807 1808 !-- Allocation of arrays for stretching 1809 ALLOCATE( min_dz_stretch_level_end(number_stretch_level_start) ) 1810 1811 ! 1812 !-- The stretching region has to be large enough to allow for a smooth 1813 !-- transition between two different grid spacings 1814 DO n = 1, number_stretch_level_start 1815 min_dz_stretch_level_end(n) = dz_stretch_level_start(n) + & 1816 4 * MAX( dz(n),dz(n+1) ) 1817 ENDDO 1818 1819 IF ( ANY( min_dz_stretch_level_end(1:number_stretch_level_start) > & 1820 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN 1821 !IF ( ANY( min_dz_stretch_level_end > & 1822 ! dz_stretch_level_end ) ) THEN 1823 message = 'Each dz_stretch_level_end has to be larger ' // & 1824 'than its corresponding value for ' // & 1825 'dz_stretch_level_start + 4*MAX(dz(n),dz(n+1)) '//& 1826 'to allow for smooth grid stretching' 1827 CALL inifor_abort('stretched_z', message) 1828 ENDIF 1829 1830 ! 1831 !-- Stretching must not be applied within the prandtl_layer 1832 !-- (first two grid points). For the default case dz_stretch_level_start 1833 !-- is negative. Therefore the absolut value is checked here. 1834 IF ( ANY( ABS( dz_stretch_level_start ) < dz(1) * 1.5_wp ) ) THEN 1835 WRITE( message, * ) 'Eeach dz_stretch_level_start has to be ',& 1836 'larger than ', dz(1) * 1.5 1837 CALL inifor_abort( 'stretched_z', message) 1838 ENDIF 1839 1840 ! 1841 !-- The stretching has to start and end on a grid level. Therefore 1842 !-- user-specified values have to ''interpolate'' to the next lowest level 1843 IF ( number_stretch_level_start /= 0 ) THEN 1844 dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) - & 1845 dz(1)/2.0) / dz(1) ) & 1846 * dz(1) + dz(1)/2.0 1847 ENDIF 1848 1849 IF ( number_stretch_level_start > 1 ) THEN 1850 DO n = 2, number_stretch_level_start 1851 dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) / & 1852 dz(n) ) * dz(n) 1853 ENDDO 1854 ENDIF 1855 1856 IF ( number_stretch_level_end /= 0 ) THEN 1857 DO n = 1, number_stretch_level_end 1858 dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) / & 1859 dz(n+1) ) * dz(n+1) 1860 ENDDO 1861 ENDIF 1862 1863 ! 1864 !-- Determine stretching factor if necessary 1865 IF ( number_stretch_level_end >= 1 ) THEN 1866 CALL calculate_stretching_factor( number_stretch_level_end, dz, & 1867 dz_stretch_factor_array, & 1868 dz_stretch_level_end, & 1869 dz_stretch_level_start ) 1870 ENDIF 1871 1872 z(1) = dz(1) * 0.5_wp 1873 ! 1874 dz_stretch_level_index = n 1875 dz_stretched = dz(1) 1876 DO k = 2, n 1877 1878 IF ( dz_stretch_level <= z(k-1) .AND. dz_stretched < dz_max ) THEN 1879 1880 dz_stretched = dz_stretched * dz_stretch_factor 1881 dz_stretched = MIN( dz_stretched, dz_max ) 1882 1883 IF ( dz_stretch_level_index == n ) dz_stretch_level_index = k-1 1884 1787 1885 ENDIF 1788 1886 1789 !-- Allocation of arrays for stretching 1790 ALLOCATE( min_dz_stretch_level_end(number_stretch_level_start) ) 1791 1792 ! 1793 !-- The stretching region has to be large enough to allow for a smooth 1794 !-- transition between two different grid spacings 1795 DO n = 1, number_stretch_level_start 1796 min_dz_stretch_level_end(n) = dz_stretch_level_start(n) + & 1797 4 * MAX( dz(n),dz(n+1) ) 1798 ENDDO 1799 1800 IF ( ANY( min_dz_stretch_level_end(1:number_stretch_level_start) > & 1801 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN 1802 !IF ( ANY( min_dz_stretch_level_end > & 1803 ! dz_stretch_level_end ) ) THEN 1804 message = 'Each dz_stretch_level_end has to be larger ' // & 1805 'than its corresponding value for ' // & 1806 'dz_stretch_level_start + 4*MAX(dz(n),dz(n+1)) '//& 1807 'to allow for smooth grid stretching' 1808 CALL inifor_abort('stretched_z', message) 1809 ENDIF 1810 1811 ! 1812 !-- Stretching must not be applied within the prandtl_layer 1813 !-- (first two grid points). For the default case dz_stretch_level_start 1814 !-- is negative. Therefore the absolut value is checked here. 1815 IF ( ANY( ABS( dz_stretch_level_start ) < dz(1) * 1.5_dp ) ) THEN 1816 WRITE( message, * ) 'Eeach dz_stretch_level_start has to be ',& 1817 'larger than ', dz(1) * 1.5 1818 CALL inifor_abort( 'stretched_z', message) 1819 ENDIF 1820 1821 ! 1822 !-- The stretching has to start and end on a grid level. Therefore 1823 !-- user-specified values have to ''interpolate'' to the next lowest level 1824 IF ( number_stretch_level_start /= 0 ) THEN 1825 dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) - & 1826 dz(1)/2.0) / dz(1) ) & 1827 * dz(1) + dz(1)/2.0 1828 ENDIF 1829 1830 IF ( number_stretch_level_start > 1 ) THEN 1831 DO n = 2, number_stretch_level_start 1832 dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) / & 1833 dz(n) ) * dz(n) 1834 ENDDO 1835 ENDIF 1836 1837 IF ( number_stretch_level_end /= 0 ) THEN 1838 DO n = 1, number_stretch_level_end 1839 dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) / & 1840 dz(n+1) ) * dz(n+1) 1841 ENDDO 1842 ENDIF 1843 1844 ! 1845 !-- Determine stretching factor if necessary 1846 IF ( number_stretch_level_end >= 1 ) THEN 1847 CALL calculate_stretching_factor( number_stretch_level_end, dz, & 1848 dz_stretch_factor_array, & 1849 dz_stretch_level_end, & 1850 dz_stretch_level_start ) 1851 ENDIF 1852 1853 z(1) = dz(1) * 0.5_dp 1854 ! 1855 dz_stretch_level_index = n 1856 dz_stretched = dz(1) 1857 DO k = 2, n 1858 1859 IF ( dz_stretch_level <= z(k-1) .AND. dz_stretched < dz_max ) THEN 1860 1861 dz_stretched = dz_stretched * dz_stretch_factor 1862 dz_stretched = MIN( dz_stretched, dz_max ) 1863 1864 IF ( dz_stretch_level_index == n ) dz_stretch_level_index = k-1 1865 1866 ENDIF 1867 1868 z(k) = z(k-1) + dz_stretched 1869 1870 ENDDO 1871 !-- Determine u and v height levels considering the possibility of grid 1872 !-- stretching in several heights. 1873 n = 1 1874 dz_stretch_level_start_index(:) = UBOUND(z, 1) 1875 dz_stretch_level_end_index(:) = UBOUND(z, 1) 1876 dz_stretched = dz(1) 1877 1878 !-- The default value of dz_stretch_level_start is negative, thus the first 1879 !-- condition is always true. Hence, the second condition is necessary. 1880 DO k = 2, UBOUND(z, 1) 1881 IF ( dz_stretch_level_start(n) <= z(k-1) .AND. & 1882 dz_stretch_level_start(n) /= -9999999.9_dp ) THEN 1883 dz_stretched = dz_stretched * dz_stretch_factor_array(n) 1884 1885 IF ( dz(n) > dz(n+1) ) THEN 1886 dz_stretched = MAX( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (higher) dz 1887 ELSE 1888 dz_stretched = MIN( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (lower) dz 1889 ENDIF 1890 1891 IF ( dz_stretch_level_start_index(n) == UBOUND(z, 1) ) & 1892 dz_stretch_level_start_index(n) = k-1 1893 1887 z(k) = z(k-1) + dz_stretched 1888 1889 ENDDO 1890 !-- Determine u and v height levels considering the possibility of grid 1891 !-- stretching in several heights. 1892 n = 1 1893 dz_stretch_level_start_index(:) = UBOUND(z, 1) 1894 dz_stretch_level_end_index(:) = UBOUND(z, 1) 1895 dz_stretched = dz(1) 1896 1897 !-- The default value of dz_stretch_level_start is negative, thus the first 1898 !-- condition is always true. Hence, the second condition is necessary. 1899 DO k = 2, UBOUND(z, 1) 1900 IF ( dz_stretch_level_start(n) <= z(k-1) .AND. & 1901 dz_stretch_level_start(n) /= -9999999.9_wp ) THEN 1902 dz_stretched = dz_stretched * dz_stretch_factor_array(n) 1903 1904 IF ( dz(n) > dz(n+1) ) THEN 1905 dz_stretched = MAX( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (higher) dz 1906 ELSE 1907 dz_stretched = MIN( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (lower) dz 1894 1908 ENDIF 1895 1909 1896 z(k) = z(k-1) + dz_stretched 1910 IF ( dz_stretch_level_start_index(n) == UBOUND(z, 1) ) & 1911 dz_stretch_level_start_index(n) = k-1 1897 1912 1898 ! 1899 !-- Make sure that the stretching ends exactly at dz_stretch_level_end 1900 dz_level_end = ABS( z(k) - dz_stretch_level_end(n) ) 1901 1902 IF ( dz_level_end < dz(n+1)/3.0 ) THEN 1903 z(k) = dz_stretch_level_end(n) 1904 dz_stretched = dz(n+1) 1905 dz_stretch_level_end_index(n) = k 1906 n = n + 1 1907 ENDIF 1908 ENDDO 1909 1910 DEALLOCATE( min_dz_stretch_level_end ) 1911 1912 END SUBROUTINE stretched_z 1913 ENDIF 1914 1915 z(k) = z(k-1) + dz_stretched 1916 1917 ! 1918 !-- Make sure that the stretching ends exactly at dz_stretch_level_end 1919 dz_level_end = ABS( z(k) - dz_stretch_level_end(n) ) 1920 1921 IF ( dz_level_end < dz(n+1)/3.0 ) THEN 1922 z(k) = dz_stretch_level_end(n) 1923 dz_stretched = dz(n+1) 1924 dz_stretch_level_end_index(n) = k 1925 n = n + 1 1926 ENDIF 1927 ENDDO 1928 1929 DEALLOCATE( min_dz_stretch_level_end ) 1930 1931 END SUBROUTINE stretched_z 1913 1932 1914 1933 … … 1928 1947 dz_stretch_level_start ) 1929 1948 1930 REAL( dp), DIMENSION(:), INTENT(IN) :: dz1931 REAL( dp), DIMENSION(:), INTENT(INOUT) :: dz_stretch_factor_array1932 REAL( dp), DIMENSION(:), INTENT(IN) :: dz_stretch_level_end, dz_stretch_level_start1949 REAL(wp), DIMENSION(:), INTENT(IN) :: dz 1950 REAL(wp), DIMENSION(:), INTENT(INOUT) :: dz_stretch_factor_array 1951 REAL(wp), DIMENSION(:), INTENT(IN) :: dz_stretch_level_end, dz_stretch_level_start 1933 1952 1934 1953 INTEGER :: iterations !< number of iterations until stretch_factor_lower/upper_limit is reached … … 1938 1957 INTEGER, INTENT(IN) :: number_end !< number of user-specified end levels for stretching 1939 1958 1940 REAL( dp) :: delta_l !< absolute difference between l and l_rounded1941 REAL( dp) :: delta_stretch_factor !< absolute difference between stretch_factor_1 and stretch_factor_21942 REAL( dp) :: delta_total_new !< sum of delta_l and delta_stretch_factor for the next iteration (should be as small as possible)1943 REAL( dp) :: delta_total_old !< sum of delta_l and delta_stretch_factor for the last iteration1944 REAL( dp) :: distance !< distance between dz_stretch_level_start and dz_stretch_level_end (stretching region)1945 REAL( dp) :: l !< value that fulfil Eq. (5) in the paper mentioned above together with stretch_factor_1 exactly1946 REAL( dp) :: numerator !< numerator of the quotient1947 REAL( dp) :: stretch_factor_1 !< stretching factor that fulfil Eq. (5) togehter with l exactly1948 REAL( dp) :: stretch_factor_2 !< stretching factor that fulfil Eq. (6) togehter with l_rounded exactly1959 REAL(wp) :: delta_l !< absolute difference between l and l_rounded 1960 REAL(wp) :: delta_stretch_factor !< absolute difference between stretch_factor_1 and stretch_factor_2 1961 REAL(wp) :: delta_total_new !< sum of delta_l and delta_stretch_factor for the next iteration (should be as small as possible) 1962 REAL(wp) :: delta_total_old !< sum of delta_l and delta_stretch_factor for the last iteration 1963 REAL(wp) :: distance !< distance between dz_stretch_level_start and dz_stretch_level_end (stretching region) 1964 REAL(wp) :: l !< value that fulfil Eq. (5) in the paper mentioned above together with stretch_factor_1 exactly 1965 REAL(wp) :: numerator !< numerator of the quotient 1966 REAL(wp) :: stretch_factor_1 !< stretching factor that fulfil Eq. (5) togehter with l exactly 1967 REAL(wp) :: stretch_factor_2 !< stretching factor that fulfil Eq. (6) togehter with l_rounded exactly 1949 1968 1950 REAL( dp) :: dz_stretch_factor_array_2(9) = 1.08_dp !< Array that contains all stretch_factor_2 that belongs to stretch_factor_11969 REAL(wp) :: dz_stretch_factor_array_2(9) = 1.08_wp !< Array that contains all stretch_factor_2 that belongs to stretch_factor_1 1951 1970 1952 REAL( dp), PARAMETER :: stretch_factor_interval = 1.0E-06 !< interval for sampling possible stretching factors1953 REAL( dp), PARAMETER :: stretch_factor_lower_limit = 0.88 !< lowest possible stretching factor1954 REAL( dp), PARAMETER :: stretch_factor_upper_limit = 1.12 !< highest possible stretching factor1971 REAL(wp), PARAMETER :: stretch_factor_interval = 1.0E-06 !< interval for sampling possible stretching factors 1972 REAL(wp), PARAMETER :: stretch_factor_lower_limit = 0.88 !< lowest possible stretching factor 1973 REAL(wp), PARAMETER :: stretch_factor_upper_limit = 1.12 !< highest possible stretching factor 1955 1974 1956 1975 … … 1963 1982 delta_total_old = 1.0 1964 1983 1965 IF ( dz(n) > dz(n+1) ) THEN1966 DO WHILE ( stretch_factor_1 >= stretch_factor_lower_limit )1984 IF ( dz(n) > dz(n+1) ) THEN 1985 DO WHILE ( stretch_factor_1 >= stretch_factor_lower_limit ) 1967 1986 1968 1987 stretch_factor_1 = 1.0 - iterations * stretch_factor_interval … … 1972 1991 stretch_factor_1 - distance/dz(n) 1973 1992 1974 IF ( numerator > 0.0 ) THEN1993 IF ( numerator > 0.0 ) THEN 1975 1994 l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0 1976 1995 l_rounded = NINT( l ) … … 1991 2010 !-- stretch_factor_2 would guarantee that the stretched dz(n) is 1992 2011 !-- equal to dz(n+1) after l_rounded grid levels. 1993 IF (delta_total_new < delta_total_old) THEN2012 IF (delta_total_new < delta_total_old) THEN 1994 2013 dz_stretch_factor_array(n) = stretch_factor_1 1995 2014 dz_stretch_factor_array_2(n) = stretch_factor_2 … … 2001 2020 ENDDO 2002 2021 2003 ELSEIF ( dz(n) < dz(n+1) ) THEN2004 DO WHILE ( stretch_factor_1 <= stretch_factor_upper_limit )2022 ELSEIF ( dz(n) < dz(n+1) ) THEN 2023 DO WHILE ( stretch_factor_1 <= stretch_factor_upper_limit ) 2005 2024 2006 2025 stretch_factor_1 = 1.0 + iterations * stretch_factor_interval … … 2027 2046 !-- stretch_factor_2 would guarantee that the stretched dz(n) is 2028 2047 !-- equal to dz(n+1) after l_rounded grid levels. 2029 IF (delta_total_new < delta_total_old) THEN2048 IF (delta_total_new < delta_total_old) THEN 2030 2049 dz_stretch_factor_array(n) = stretch_factor_1 2031 2050 dz_stretch_factor_array_2(n) = stretch_factor_2 … … 2045 2064 !-- interval. If not, print a warning for the user. 2046 2065 IF ( dz_stretch_factor_array_2(n) < stretch_factor_lower_limit .OR. & 2047 dz_stretch_factor_array_2(n) > stretch_factor_upper_limit ) THEN2048 WRITE( message, * ) 'stretch_factor_2 = ', &2066 dz_stretch_factor_array_2(n) > stretch_factor_upper_limit ) THEN 2067 WRITE( message, * ) 'stretch_factor_2 = ', & 2049 2068 dz_stretch_factor_array_2(n), ' which is',& 2050 2069 ' responsible for exactly reaching& dz =',& … … 2067 2086 !> coordinate vector 'z' and stores it in 'zw'. 2068 2087 !------------------------------------------------------------------------------! 2069 2070 2071 REAL(dp), INTENT(IN) :: z(0:)2072 REAL(dp), INTENT(OUT) :: zw(1:)2073 2074 2075 2076 DOk = 1, UBOUND(zw, 1)2077 zw(k) = 0.5_dp * (z(k-1) + z(k))2078 2079 2080 2088 SUBROUTINE midpoints(z, zw) 2089 2090 REAL(wp), INTENT(IN) :: z(0:) 2091 REAL(wp), INTENT(OUT) :: zw(1:) 2092 2093 INTEGER :: k 2094 2095 DO k = 1, UBOUND(zw, 1) 2096 zw(k) = 0.5_wp * (z(k-1) + z(k)) 2097 ENDDO 2098 2099 END SUBROUTINE midpoints 2081 2100 2082 2101 !------------------------------------------------------------------------------! … … 2085 2104 !> Defines INFOR's IO groups. 2086 2105 !------------------------------------------------------------------------------! 2087 2088 2089 2090 2091 2092 2093 2094 ! 2095 !-- 2096 2097 2098 2099 2100 2101 2102 2103 ! 2104 !-- 2105 2106 2107 2108 2109 2110 2111 2112 ! 2113 !-- 2114 !-- 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 ! 2128 !-- 2129 2130 2131 2132 2133 2134 2135 2136 ! 2137 !-- 2138 2139 2140 2141 2142 2143 2144 2145 2106 SUBROUTINE setup_io_groups() 2107 2108 INTEGER :: ngroups 2109 2110 ngroups = 16 2111 ALLOCATE( io_group_list(ngroups) ) 2112 2113 ! 2114 !-- soil temp 2115 io_group_list(1) = init_io_group( & 2116 in_files = soil_files, & 2117 out_vars = output_var_table(1:1), & 2118 in_var_list = input_var_table(1:1), & 2119 kind = 'soil-temperature' & 2120 ) 2121 2122 ! 2123 !-- soil water 2124 io_group_list(2) = init_io_group( & 2125 in_files = soil_files, & 2126 out_vars = output_var_table(2:2), & 2127 in_var_list = input_var_table(2:2), & 2128 kind = 'soil-water' & 2129 ) 2130 2131 ! 2132 !-- potential temperature, surface pressure, specific humidity including 2133 !-- nudging and subsidence, and geostrophic winds ug, vg 2134 io_group_list(3) = init_io_group( & 2135 in_files = flow_files, & 2136 out_vars = [output_var_table(56:64), & ! internal averaged density and pressure profiles 2137 output_var_table(3:8), output_var_table(9:14), & 2138 output_var_table(42:42), output_var_table(43:44), & 2139 output_var_table(49:51), output_var_table(52:54)], & 2140 in_var_list = (/input_var_table(3), input_var_table(17), & ! T, P, QV 2141 input_var_table(4) /), & 2142 kind = 'thermodynamics', & 2143 n_output_quantities = 4 & ! P, Theta, Rho, qv 2144 ) 2145 2146 ! 2147 !-- Moved to therodynamic io_group 2148 !io_group_list(4) = init_io_group( & 2149 ! in_files = flow_files, & 2150 ! out_vars = [output_var_table(9:14), output_var_table(52:54)], & 2151 ! in_var_list = input_var_table(4:4), & 2152 ! kind = 'scalar' & 2153 !) 2154 2155 ! 2156 !-- u and v velocity 2157 io_group_list(5) = init_io_group( & 2158 in_files = flow_files, & 2159 out_vars = [output_var_table(15:26), output_var_table(45:46)], & 2160 !out_vars = output_var_table(15:20), & 2161 in_var_list = input_var_table(5:6), & 2162 !in_var_list = input_var_table(5:5), & 2163 kind = 'velocities' & 2164 ) 2146 2165 2147 2166 ! 2148 !-- 2149 2150 2151 2152 2153 2154 2155 !io_group_list(6) %to_be_processed = .FALSE.2167 !-- v velocity, deprecated! 2168 !io_group_list(6) = init_io_group( & 2169 ! in_files = flow_files, & 2170 ! out_vars = output_var_table(21:26), & 2171 ! in_var_list = input_var_table(6:6), & 2172 ! kind = 'horizontal velocity' & 2173 !) 2174 !io_group_list(6)%to_be_processed = .FALSE. 2156 2175 2157 2176 ! 2158 !-- 2159 2160 2161 2162 2163 2164 2165 ! 2166 !-- 2167 2168 2169 2170 2171 2172 2173 io_group_list(8) %to_be_processed = .FALSE.2174 ! 2175 !-- 2176 2177 2178 2179 2180 2181 2182 io_group_list(9) %to_be_processed = .FALSE.2183 ! 2184 !-- 2185 2186 2187 2188 2189 2190 2191 io_group_list(10) %to_be_processed = .FALSE.2192 ! 2193 !-- 2194 2195 2196 2197 2198 2199 2200 io_group_list(11) %to_be_processed = .FALSE.2201 ! 2202 !-- 2203 2204 2205 2206 2207 2208 2209 io_group_list(12) %to_be_processed = .FALSE.2210 ! 2211 !-- 2212 2213 2214 2215 2216 2217 2218 io_group_list(13) %to_be_processed = .FALSE.2219 ! 2220 !-- 2221 2222 2223 2224 2225 2226 2227 io_group_list(14) %to_be_processed = .FALSE.2228 ! 2229 !-- 2230 2231 2232 2233 2234 2235 2236 io_group_list(15) %to_be_processed = .FALSE.2237 ! 2238 !-- 2239 2240 2241 2242 2243 2244 2245 io_group_list(16) %to_be_processed = .FALSE.2246 2247 2177 !-- w velocity and subsidence and w nudging 2178 io_group_list(7) = init_io_group( & 2179 in_files = flow_files, & 2180 out_vars = [output_var_table(27:32), output_var_table(47:48)], & 2181 in_var_list = input_var_table(7:7), & 2182 kind = 'scalar' & 2183 ) 2184 ! 2185 !-- rain 2186 io_group_list(8) = init_io_group( & 2187 in_files = soil_moisture_files, & 2188 out_vars = output_var_table(33:33), & 2189 in_var_list = input_var_table(8:8), & 2190 kind = 'accumulated' & 2191 ) 2192 io_group_list(8)%to_be_processed = .FALSE. 2193 ! 2194 !-- snow 2195 io_group_list(9) = init_io_group( & 2196 in_files = soil_moisture_files, & 2197 out_vars = output_var_table(34:34), & 2198 in_var_list = input_var_table(9:9), & 2199 kind = 'accumulated' & 2200 ) 2201 io_group_list(9)%to_be_processed = .FALSE. 2202 ! 2203 !-- graupel 2204 io_group_list(10) = init_io_group( & 2205 in_files = soil_moisture_files, & 2206 out_vars = output_var_table(35:35), & 2207 in_var_list = input_var_table(10:10), & 2208 kind = 'accumulated' & 2209 ) 2210 io_group_list(10)%to_be_processed = .FALSE. 2211 ! 2212 !-- evapotranspiration 2213 io_group_list(11) = init_io_group( & 2214 in_files = soil_moisture_files, & 2215 out_vars = output_var_table(37:37), & 2216 in_var_list = input_var_table(11:11), & 2217 kind = 'accumulated' & 2218 ) 2219 io_group_list(11)%to_be_processed = .FALSE. 2220 ! 2221 !-- 2m air temperature 2222 io_group_list(12) = init_io_group( & 2223 in_files = soil_moisture_files, & 2224 out_vars = output_var_table(36:36), & 2225 in_var_list = input_var_table(12:12), & 2226 kind = 'surface' & 2227 ) 2228 io_group_list(12)%to_be_processed = .FALSE. 2229 ! 2230 !-- incoming diffusive sw flux 2231 io_group_list(13) = init_io_group( & 2232 in_files = radiation_files, & 2233 out_vars = output_var_table(38:38), & 2234 in_var_list = input_var_table(13:13), & 2235 kind = 'running average' & 2236 ) 2237 io_group_list(13)%to_be_processed = .FALSE. 2238 ! 2239 !-- incoming direct sw flux 2240 io_group_list(14) = init_io_group( & 2241 in_files = radiation_files, & 2242 out_vars = output_var_table(39:39), & 2243 in_var_list = input_var_table(14:14), & 2244 kind = 'running average' & 2245 ) 2246 io_group_list(14)%to_be_processed = .FALSE. 2247 ! 2248 !-- sw radiation balance 2249 io_group_list(15) = init_io_group( & 2250 in_files = radiation_files, & 2251 out_vars = output_var_table(40:40), & 2252 in_var_list = input_var_table(15:15), & 2253 kind = 'running average' & 2254 ) 2255 io_group_list(15)%to_be_processed = .FALSE. 2256 ! 2257 !-- lw radiation balance 2258 io_group_list(16) = init_io_group( & 2259 in_files = radiation_files, & 2260 out_vars = output_var_table(41:41), & 2261 in_var_list = input_var_table(16:16), & 2262 kind = 'running average' & 2263 ) 2264 io_group_list(16)%to_be_processed = .FALSE. 2265 2266 END SUBROUTINE setup_io_groups 2248 2267 2249 2268 … … 2259 2278 !> on the output quantity Theta. 2260 2279 !------------------------------------------------------------------------------! 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 group %nt = SIZE(in_files)2272 group %nv = SIZE(out_vars)2273 group %n_inputs = SIZE(in_var_list)2274 group %kind = TRIM(kind)2275 ! 2276 !-- 2277 !-- 2278 !-- 2279 !-- 2280 !-- 2281 !-- 2282 2283 group %n_output_quantities = n_output_quantities2284 2285 group % n_output_quantities = group %n_inputs2286 2287 2288 ALLOCATE(group % in_var_list(group %n_inputs))2289 ALLOCATE(group % in_files(group %nt))2290 ALLOCATE(group % out_vars(group %nv))2291 2292 group %in_var_list = in_var_list2293 group %in_files = in_files2294 group %out_vars = out_vars2295 group %to_be_processed = .TRUE.2296 2297 2280 FUNCTION init_io_group(in_files, out_vars, in_var_list, kind, & 2281 n_output_quantities) RESULT(group) 2282 CHARACTER(LEN=PATH), INTENT(IN) :: in_files(:) 2283 CHARACTER(LEN=*), INTENT(IN) :: kind 2284 TYPE(nc_var), INTENT(IN) :: out_vars(:) 2285 TYPE(nc_var), INTENT(IN) :: in_var_list(:) 2286 INTEGER, OPTIONAL :: n_output_quantities 2287 2288 TYPE(io_group) :: group 2289 2290 group%nt = SIZE(in_files) 2291 group%nv = SIZE(out_vars) 2292 group%n_inputs = SIZE(in_var_list) 2293 group%kind = TRIM(kind) 2294 ! 2295 !-- For the 'thermodynamics' IO group, one quantity more than input variables 2296 !-- is needed to compute all output variables of the IO group. Concretely, in 2297 !-- preprocess() the density is computed from T,P or PP,QV in adddition to 2298 !-- the variables Theta, p, qv. In read_input_variables(), 2299 !-- n_output_quantities is used to allocate the correct number of input 2300 !-- buffers. 2301 IF ( PRESENT(n_output_quantities) ) THEN 2302 group%n_output_quantities = n_output_quantities 2303 ELSE 2304 group%n_output_quantities = group%n_inputs 2305 ENDIF 2306 2307 ALLOCATE(group%in_var_list(group%n_inputs)) 2308 ALLOCATE(group%in_files(group%nt)) 2309 ALLOCATE(group%out_vars(group%nv)) 2310 2311 group%in_var_list = in_var_list 2312 group%in_files = in_files 2313 group%out_vars = out_vars 2314 group%to_be_processed = .TRUE. 2315 2316 END FUNCTION init_io_group 2298 2317 2299 2318 … … 2303 2322 !> Deallocates all allocated variables. 2304 2323 !------------------------------------------------------------------------------! 2305 2306 2307 CALL report('fini_grids', 'Deallocating grids', cfg %debug)2308 2309 2310 2311 DEALLOCATE(palm_grid%x, palm_grid%y, palm_grid%z,&2312 palm_grid%xu, palm_grid%yv, palm_grid%zw,&2313 palm_grid%clon, palm_grid%clat,&2314 2315 2316 2317 2318 palm_intermediate%clon, palm_intermediate%clat,&2319 2320 2321 DEALLOCATE(cosmo_grid%lon, cosmo_grid%lat,&2322 cosmo_grid%lonu, cosmo_grid%latv,&2323 2324 2325 2324 SUBROUTINE fini_grids() 2325 2326 CALL report('fini_grids', 'Deallocating grids', cfg%debug) 2327 2328 DEALLOCATE(x, y, z, xu, yv, zw, z_column, zw_column) 2329 2330 DEALLOCATE(palm_grid%x, palm_grid%y, palm_grid%z, & 2331 palm_grid%xu, palm_grid%yv, palm_grid%zw, & 2332 palm_grid%clon, palm_grid%clat, & 2333 palm_grid%clonu, palm_grid%clatu) 2334 2335 DEALLOCATE(palm_intermediate%x, palm_intermediate%y, palm_intermediate%z, & 2336 palm_intermediate%xu, palm_intermediate%yv, palm_intermediate%zw,& 2337 palm_intermediate%clon, palm_intermediate%clat, & 2338 palm_intermediate%clonu, palm_intermediate%clatu) 2339 2340 DEALLOCATE(cosmo_grid%lon, cosmo_grid%lat, & 2341 cosmo_grid%lonu, cosmo_grid%latv, & 2342 cosmo_grid%hfl) 2343 2344 END SUBROUTINE fini_grids 2326 2345 2327 2346 … … 2331 2350 !> Initializes the variable list. 2332 2351 !------------------------------------------------------------------------------! 2333 2334 2335 2336 2337 2338 2339 IF (TRIM(cfg %start_date) == '') THEN2340 2341 2342 2343 2344 nc_source_text = 'COSMO-DE analysis from ' // TRIM(cfg %start_date)2345 2346 2347 2348 2349 2352 SUBROUTINE setup_variable_tables(ic_mode) 2353 CHARACTER(LEN=*), INTENT(IN) :: ic_mode 2354 INTEGER :: n_invar = 0 !< number of variables in the input variable table 2355 INTEGER :: n_outvar = 0 !< number of variables in the output variable table 2356 TYPE(nc_var), POINTER :: var 2357 2358 IF (TRIM(cfg%start_date) == '') THEN 2359 message = 'Simulation start date has not been set.' 2360 CALL inifor_abort('setup_variable_tables', message) 2361 ENDIF 2362 2363 nc_source_text = 'COSMO-DE analysis from ' // TRIM(cfg%start_date) 2364 2365 n_invar = 17 2366 n_outvar = 64 2367 ALLOCATE( input_var_table(n_invar) ) 2368 ALLOCATE( output_var_table(n_outvar) ) 2350 2369 2351 2370 ! … … 2353 2372 !- Section 1: NetCDF input variables 2354 2373 !------------------------------------------------------------------------------ 2355 2356 var %name = 'T_SO'2357 var %to_be_processed = .TRUE.2358 var %is_upside_down = .FALSE.2359 2360 2361 var %name = 'W_SO'2362 var %to_be_processed = .TRUE.2363 var %is_upside_down = .FALSE.2364 2365 2366 var %name = 'T'2367 var %to_be_processed = .TRUE.2368 var %is_upside_down = .TRUE.2369 2370 2371 var %name = 'QV'2372 var %to_be_processed = .TRUE.2373 var %is_upside_down = .TRUE.2374 2375 2376 var %name = 'U'2377 var %to_be_processed = .TRUE.2378 var %is_upside_down = .TRUE.2379 2380 2381 var %name = 'V'2382 var %to_be_processed = .TRUE.2383 var %is_upside_down = .TRUE.2384 2385 2386 var %name = 'W'2387 var %to_be_processed = .TRUE.2388 var %is_upside_down = .TRUE.2389 2390 2391 var %name = 'RAIN_GSP'2392 var %to_be_processed = .TRUE.2393 var %is_upside_down = .FALSE.2394 2395 2396 var %name = 'SNOW_GSP'2397 var %to_be_processed = .TRUE.2398 var %is_upside_down = .FALSE.2399 2400 2401 var %name = 'GRAU_GSP'2402 var %to_be_processed = .TRUE.2403 var %is_upside_down = .FALSE.2404 2405 2406 var %name = 'AEVAP_S'2407 var %to_be_processed = .TRUE.2408 var %is_upside_down = .FALSE.2409 2410 2411 var %name = 'T_2M'2412 var %to_be_processed = .TRUE.2413 var %is_upside_down = .FALSE.2414 2415 2416 var %name = 'ASWDIFD_S'2417 var %to_be_processed = .TRUE.2418 var %is_upside_down = .FALSE.2419 2420 2421 var %name = 'ASWDIR_S'2422 var %to_be_processed = .TRUE.2423 var %is_upside_down = .FALSE.2424 2425 2426 var %name = 'ASOB_S'2427 var %to_be_processed = .TRUE.2428 var %is_upside_down = .FALSE.2429 2430 2431 var %name = 'ATHB_S'2432 var %to_be_processed = .TRUE.2433 var %is_upside_down = .FALSE.2434 2435 2436 var %name = 'P'2437 var %to_be_processed = .TRUE.2438 var %is_upside_down = .TRUE.2374 var => input_var_table(1) 2375 var%name = 'T_SO' 2376 var%to_be_processed = .TRUE. 2377 var%is_upside_down = .FALSE. 2378 2379 var => input_var_table(2) 2380 var%name = 'W_SO' 2381 var%to_be_processed = .TRUE. 2382 var%is_upside_down = .FALSE. 2383 2384 var => input_var_table(3) 2385 var%name = 'T' 2386 var%to_be_processed = .TRUE. 2387 var%is_upside_down = .TRUE. 2388 2389 var => input_var_table(4) 2390 var%name = 'QV' 2391 var%to_be_processed = .TRUE. 2392 var%is_upside_down = .TRUE. 2393 2394 var => input_var_table(5) 2395 var%name = 'U' 2396 var%to_be_processed = .TRUE. 2397 var%is_upside_down = .TRUE. 2398 2399 var => input_var_table(6) 2400 var%name = 'V' 2401 var%to_be_processed = .TRUE. 2402 var%is_upside_down = .TRUE. 2403 2404 var => input_var_table(7) 2405 var%name = 'W' 2406 var%to_be_processed = .TRUE. 2407 var%is_upside_down = .TRUE. 2408 2409 var => input_var_table(8) 2410 var%name = 'RAIN_GSP' 2411 var%to_be_processed = .TRUE. 2412 var%is_upside_down = .FALSE. 2413 2414 var => input_var_table(9) 2415 var%name = 'SNOW_GSP' 2416 var%to_be_processed = .TRUE. 2417 var%is_upside_down = .FALSE. 2418 2419 var => input_var_table(10) 2420 var%name = 'GRAU_GSP' 2421 var%to_be_processed = .TRUE. 2422 var%is_upside_down = .FALSE. 2423 2424 var => input_var_table(11) 2425 var%name = 'AEVAP_S' 2426 var%to_be_processed = .TRUE. 2427 var%is_upside_down = .FALSE. 2428 2429 var => input_var_table(12) 2430 var%name = 'T_2M' 2431 var%to_be_processed = .TRUE. 2432 var%is_upside_down = .FALSE. 2433 2434 var => input_var_table(13) 2435 var%name = 'ASWDIFD_S' 2436 var%to_be_processed = .TRUE. 2437 var%is_upside_down = .FALSE. 2438 2439 var => input_var_table(14) 2440 var%name = 'ASWDIR_S' 2441 var%to_be_processed = .TRUE. 2442 var%is_upside_down = .FALSE. 2443 2444 var => input_var_table(15) 2445 var%name = 'ASOB_S' 2446 var%to_be_processed = .TRUE. 2447 var%is_upside_down = .FALSE. 2448 2449 var => input_var_table(16) 2450 var%name = 'ATHB_S' 2451 var%to_be_processed = .TRUE. 2452 var%is_upside_down = .FALSE. 2453 2454 var => input_var_table(17) 2455 var%name = 'P' 2456 var%to_be_processed = .TRUE. 2457 var%is_upside_down = .TRUE. 2439 2458 2440 2459 ! … … 2446 2465 ! Section 2.1: Realistic forcings, i.e. 3D initial and boundary conditions 2447 2466 !------------------------------------------------------------------------------ 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 output_var_table(3) %averaging_grid => averaged_initial_scalar_profile2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 output_var_table(9) %averaging_grid => averaged_initial_scalar_profile2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 output_var_table(15) %averaging_grid => averaged_initial_scalar_profile2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 output_var_table(21) %averaging_grid => averaged_initial_scalar_profile2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 output_var_table(27) %averaging_grid => averaged_initial_w_profile2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2467 output_var_table(1) = init_nc_var( & 2468 name = 'init_soil_t', & 2469 std_name = "", & 2470 long_name = "initial soil temperature", & 2471 units = "K", & 2472 kind = "init soil", & 2473 input_id = 1, & 2474 output_file = output_file, & 2475 grid = palm_grid, & 2476 intermediate_grid = palm_intermediate & 2477 ) 2478 2479 output_var_table(2) = init_nc_var( & 2480 name = 'init_soil_m', & 2481 std_name = "", & 2482 long_name = "initial soil moisture", & 2483 units = "m^3/m^3", & 2484 kind = "init soil", & 2485 input_id = 1, & 2486 output_file = output_file, & 2487 grid = palm_grid, & 2488 intermediate_grid = palm_intermediate & 2489 ) 2490 2491 output_var_table(3) = init_nc_var( & 2492 name = 'init_atmosphere_pt', & 2493 std_name = "", & 2494 long_name = "initial potential temperature", & 2495 units = "K", & 2496 kind = "init scalar", & 2497 input_id = 1, & ! first in (T, p) IO group 2498 output_file = output_file, & 2499 grid = palm_grid, & 2500 intermediate_grid = palm_intermediate, & 2501 is_profile = (TRIM(ic_mode) == 'profile') & 2502 ) 2503 IF (TRIM(ic_mode) == 'profile') THEN 2504 output_var_table(3)%averaging_grid => averaged_initial_scalar_profile 2505 ENDIF 2506 2507 output_var_table(4) = init_nc_var( & 2508 name = 'ls_forcing_left_pt', & 2509 std_name = "", & 2510 long_name = "large-scale forcing for left model boundary for the potential temperature", & 2511 units = "K", & 2512 kind = "left scalar", & 2513 input_id = 1, & 2514 grid = scalars_west_grid, & 2515 intermediate_grid = scalars_west_intermediate, & 2516 output_file = output_file & 2517 ) 2518 2519 output_var_table(5) = init_nc_var( & 2520 name = 'ls_forcing_right_pt', & 2521 std_name = "", & 2522 long_name = "large-scale forcing for right model boundary for the potential temperature", & 2523 units = "K", & 2524 kind = "right scalar", & 2525 input_id = 1, & 2526 grid = scalars_east_grid, & 2527 intermediate_grid = scalars_east_intermediate, & 2528 output_file = output_file & 2529 ) 2530 2531 output_var_table(6) = init_nc_var( & 2532 name = 'ls_forcing_north_pt', & 2533 std_name = "", & 2534 long_name = "large-scale forcing for north model boundary for the potential temperature", & 2535 units = "K", & 2536 kind = "north scalar", & 2537 input_id = 1, & 2538 grid = scalars_north_grid, & 2539 intermediate_grid = scalars_north_intermediate, & 2540 output_file = output_file & 2541 ) 2542 2543 output_var_table(7) = init_nc_var( & 2544 name = 'ls_forcing_south_pt', & 2545 std_name = "", & 2546 long_name = "large-scale forcing for south model boundary for the potential temperature", & 2547 units = "K", & 2548 kind = "south scalar", & 2549 input_id = 1, & 2550 grid = scalars_south_grid, & 2551 intermediate_grid = scalars_south_intermediate, & 2552 output_file = output_file & 2553 ) 2554 2555 output_var_table(8) = init_nc_var( & 2556 name = 'ls_forcing_top_pt', & 2557 std_name = "", & 2558 long_name = "large-scale forcing for top model boundary for the potential temperature", & 2559 units = "K", & 2560 kind = "top scalar", & 2561 input_id = 1, & 2562 grid = scalars_top_grid, & 2563 intermediate_grid = scalars_top_intermediate, & 2564 output_file = output_file & 2565 ) 2566 2567 output_var_table(9) = init_nc_var( & 2568 name = 'init_atmosphere_qv', & 2569 std_name = "", & 2570 long_name = "initial specific humidity", & 2571 units = "kg/kg", & 2572 kind = "init scalar", & 2573 input_id = 3, & 2574 output_file = output_file, & 2575 grid = palm_grid, & 2576 intermediate_grid = palm_intermediate, & 2577 is_profile = (TRIM(ic_mode) == 'profile') & 2578 ) 2579 IF (TRIM(ic_mode) == 'profile') THEN 2580 output_var_table(9)%averaging_grid => averaged_initial_scalar_profile 2581 ENDIF 2582 2583 output_var_table(10) = init_nc_var( & 2584 name = 'ls_forcing_left_qv', & 2585 std_name = "", & 2586 long_name = "large-scale forcing for left model boundary for the specific humidity", & 2587 units = "kg/kg", & 2588 kind = "left scalar", & 2589 input_id = 3, & 2590 output_file = output_file, & 2591 grid = scalars_west_grid, & 2592 intermediate_grid = scalars_west_intermediate & 2593 ) 2594 2595 output_var_table(11) = init_nc_var( & 2596 name = 'ls_forcing_right_qv', & 2597 std_name = "", & 2598 long_name = "large-scale forcing for right model boundary for the specific humidity", & 2599 units = "kg/kg", & 2600 kind = "right scalar", & 2601 input_id = 3, & 2602 output_file = output_file, & 2603 grid = scalars_east_grid, & 2604 intermediate_grid = scalars_east_intermediate & 2605 ) 2606 2607 output_var_table(12) = init_nc_var( & 2608 name = 'ls_forcing_north_qv', & 2609 std_name = "", & 2610 long_name = "large-scale forcing for north model boundary for the specific humidity", & 2611 units = "kg/kg", & 2612 kind = "north scalar", & 2613 input_id = 3, & 2614 output_file = output_file, & 2615 grid = scalars_north_grid, & 2616 intermediate_grid = scalars_north_intermediate & 2617 ) 2618 2619 output_var_table(13) = init_nc_var( & 2620 name = 'ls_forcing_south_qv', & 2621 std_name = "", & 2622 long_name = "large-scale forcing for south model boundary for the specific humidity", & 2623 units = "kg/kg", & 2624 kind = "south scalar", & 2625 input_id = 3, & 2626 output_file = output_file, & 2627 grid = scalars_south_grid, & 2628 intermediate_grid = scalars_south_intermediate & 2629 ) 2630 2631 output_var_table(14) = init_nc_var( & 2632 name = 'ls_forcing_top_qv', & 2633 std_name = "", & 2634 long_name = "large-scale forcing for top model boundary for the specific humidity", & 2635 units = "kg/kg", & 2636 kind = "top scalar", & 2637 input_id = 3, & 2638 output_file = output_file, & 2639 grid = scalars_top_grid, & 2640 intermediate_grid = scalars_top_intermediate & 2641 ) 2642 2643 output_var_table(15) = init_nc_var( & 2644 name = 'init_atmosphere_u', & 2645 std_name = "", & 2646 long_name = "initial wind component in x direction", & 2647 units = "m/s", & 2648 kind = "init u", & 2649 input_id = 1, & ! first in (U, V) I/O group 2650 output_file = output_file, & 2651 grid = u_initial_grid, & 2652 intermediate_grid = u_initial_intermediate, & 2653 is_profile = (TRIM(ic_mode) == 'profile') & 2654 ) 2655 IF (TRIM(ic_mode) == 'profile') THEN 2656 output_var_table(15)%averaging_grid => averaged_initial_scalar_profile 2657 ENDIF 2658 2659 output_var_table(16) = init_nc_var( & 2660 name = 'ls_forcing_left_u', & 2661 std_name = "", & 2662 long_name = "large-scale forcing for left model boundary for the wind component in x direction", & 2663 units = "m/s", & 2664 kind = "left u", & 2665 input_id = 1, & ! first in (U, V) I/O group 2666 output_file = output_file, & 2667 grid = u_west_grid, & 2668 intermediate_grid = u_west_intermediate & 2669 ) 2670 2671 output_var_table(17) = init_nc_var( & 2672 name = 'ls_forcing_right_u', & 2673 std_name = "", & 2674 long_name = "large-scale forcing for right model boundary for the wind component in x direction", & 2675 units = "m/s", & 2676 kind = "right u", & 2677 input_id = 1, & ! first in (U, V) I/O group 2678 output_file = output_file, & 2679 grid = u_east_grid, & 2680 intermediate_grid = u_east_intermediate & 2681 ) 2682 2683 output_var_table(18) = init_nc_var( & 2684 name = 'ls_forcing_north_u', & 2685 std_name = "", & 2686 long_name = "large-scale forcing for north model boundary for the wind component in x direction", & 2687 units = "m/s", & 2688 kind = "north u", & 2689 input_id = 1, & ! first in (U, V) I/O group 2690 output_file = output_file, & 2691 grid = u_north_grid, & 2692 intermediate_grid = u_north_intermediate & 2693 ) 2694 2695 output_var_table(19) = init_nc_var( & 2696 name = 'ls_forcing_south_u', & 2697 std_name = "", & 2698 long_name = "large-scale forcing for south model boundary for the wind component in x direction", & 2699 units = "m/s", & 2700 kind = "south u", & 2701 input_id = 1, & ! first in (U, V) I/O group 2702 output_file = output_file, & 2703 grid = u_south_grid, & 2704 intermediate_grid = u_south_intermediate & 2705 ) 2706 2707 output_var_table(20) = init_nc_var( & 2708 name = 'ls_forcing_top_u', & 2709 std_name = "", & 2710 long_name = "large-scale forcing for top model boundary for the wind component in x direction", & 2711 units = "m/s", & 2712 kind = "top u", & 2713 input_id = 1, & ! first in (U, V) I/O group 2714 output_file = output_file, & 2715 grid = u_top_grid, & 2716 intermediate_grid = u_top_intermediate & 2717 ) 2718 2719 output_var_table(21) = init_nc_var( & 2720 name = 'init_atmosphere_v', & 2721 std_name = "", & 2722 long_name = "initial wind component in y direction", & 2723 units = "m/s", & 2724 kind = "init v", & 2725 input_id = 2, & ! second in (U, V) I/O group 2726 output_file = output_file, & 2727 grid = v_initial_grid, & 2728 intermediate_grid = v_initial_intermediate, & 2729 is_profile = (TRIM(ic_mode) == 'profile') & 2730 ) 2731 IF (TRIM(ic_mode) == 'profile') THEN 2732 output_var_table(21)%averaging_grid => averaged_initial_scalar_profile 2733 ENDIF 2734 2735 output_var_table(22) = init_nc_var( & 2736 name = 'ls_forcing_left_v', & 2737 std_name = "", & 2738 long_name = "large-scale forcing for left model boundary for the wind component in y direction", & 2739 units = "m/s", & 2740 kind = "right v", & 2741 input_id = 2, & ! second in (U, V) I/O group 2742 output_file = output_file, & 2743 grid = v_west_grid, & 2744 intermediate_grid = v_west_intermediate & 2745 ) 2746 2747 output_var_table(23) = init_nc_var( & 2748 name = 'ls_forcing_right_v', & 2749 std_name = "", & 2750 long_name = "large-scale forcing for right model boundary for the wind component in y direction", & 2751 units = "m/s", & 2752 kind = "right v", & 2753 input_id = 2, & ! second in (U, V) I/O group 2754 output_file = output_file, & 2755 grid = v_east_grid, & 2756 intermediate_grid = v_east_intermediate & 2757 ) 2758 2759 output_var_table(24) = init_nc_var( & 2760 name = 'ls_forcing_north_v', & 2761 std_name = "", & 2762 long_name = "large-scale forcing for north model boundary for the wind component in y direction", & 2763 units = "m/s", & 2764 kind = "north v", & 2765 input_id = 2, & ! second in (U, V) I/O group 2766 output_file = output_file, & 2767 grid = v_north_grid, & 2768 intermediate_grid = v_north_intermediate & 2769 ) 2770 2771 output_var_table(25) = init_nc_var( & 2772 name = 'ls_forcing_south_v', & 2773 std_name = "", & 2774 long_name = "large-scale forcing for south model boundary for the wind component in y direction", & 2775 units = "m/s", & 2776 kind = "south v", & 2777 input_id = 2, & ! second in (U, V) I/O group 2778 output_file = output_file, & 2779 grid = v_south_grid, & 2780 intermediate_grid = v_south_intermediate & 2781 ) 2782 2783 output_var_table(26) = init_nc_var( & 2784 name = 'ls_forcing_top_v', & 2785 std_name = "", & 2786 long_name = "large-scale forcing for top model boundary for the wind component in y direction", & 2787 units = "m/s", & 2788 kind = "top v", & 2789 input_id = 2, & ! second in (U, V) I/O group 2790 output_file = output_file, & 2791 grid = v_top_grid, & 2792 intermediate_grid = v_top_intermediate & 2793 ) 2794 2795 output_var_table(27) = init_nc_var( & 2796 name = 'init_atmosphere_w', & 2797 std_name = "", & 2798 long_name = "initial wind component in z direction", & 2799 units = "m/s", & 2800 kind = "init w", & 2801 input_id = 1, & 2802 output_file = output_file, & 2803 grid = w_initial_grid, & 2804 intermediate_grid = w_initial_intermediate, & 2805 is_profile = (TRIM(ic_mode) == 'profile') & 2806 ) 2807 IF (TRIM(ic_mode) == 'profile') THEN 2808 output_var_table(27)%averaging_grid => averaged_initial_w_profile 2809 ENDIF 2810 2811 output_var_table(28) = init_nc_var( & 2812 name = 'ls_forcing_left_w', & 2813 std_name = "", & 2814 long_name = "large-scale forcing for left model boundary for the wind component in z direction", & 2815 units = "m/s", & 2816 kind = "left w", & 2817 input_id = 1, & 2818 output_file = output_file, & 2819 grid = w_west_grid, & 2820 intermediate_grid = w_west_intermediate & 2821 ) 2822 2823 output_var_table(29) = init_nc_var( & 2824 name = 'ls_forcing_right_w', & 2825 std_name = "", & 2826 long_name = "large-scale forcing for right model boundary for the wind component in z direction", & 2827 units = "m/s", & 2828 kind = "right w", & 2829 input_id = 1, & 2830 output_file = output_file, & 2831 grid = w_east_grid, & 2832 intermediate_grid = w_east_intermediate & 2833 ) 2834 2835 output_var_table(30) = init_nc_var( & 2836 name = 'ls_forcing_north_w', & 2837 std_name = "", & 2838 long_name = "large-scale forcing for north model boundary for the wind component in z direction", & 2839 units = "m/s", & 2840 kind = "north w", & 2841 input_id = 1, & 2842 output_file = output_file, & 2843 grid = w_north_grid, & 2844 intermediate_grid = w_north_intermediate & 2845 ) 2846 2847 output_var_table(31) = init_nc_var( & 2848 name = 'ls_forcing_south_w', & 2849 std_name = "", & 2850 long_name = "large-scale forcing for south model boundary for the wind component in z direction", & 2851 units = "m/s", & 2852 kind = "south w", & 2853 input_id = 1, & 2854 output_file = output_file, & 2855 grid = w_south_grid, & 2856 intermediate_grid = w_south_intermediate & 2857 ) 2858 2859 output_var_table(32) = init_nc_var( & 2860 name = 'ls_forcing_top_w', & 2861 std_name = "", & 2862 long_name = "large-scale forcing for top model boundary for the wind component in z direction", & 2863 units = "m/s", & 2864 kind = "top w", & 2865 input_id = 1, & 2866 output_file = output_file, & 2867 grid = w_top_grid, & 2868 intermediate_grid = w_top_intermediate & 2869 ) 2870 2871 output_var_table(33) = init_nc_var( & 2872 name = 'ls_forcing_soil_rain', & 2873 std_name = "", & 2874 long_name = "large-scale forcing rain", & 2875 units = "kg/m2", & 2876 kind = "surface forcing", & 2877 input_id = 1, & 2878 output_file = output_file, & 2879 grid = palm_grid, & 2880 intermediate_grid = palm_intermediate & 2881 ) 2882 2883 output_var_table(34) = init_nc_var( & 2884 name = 'ls_forcing_soil_snow', & 2885 std_name = "", & 2886 long_name = "large-scale forcing snow", & 2887 units = "kg/m2", & 2888 kind = "surface forcing", & 2889 input_id = 1, & 2890 output_file = output_file, & 2891 grid = palm_grid, & 2892 intermediate_grid = palm_intermediate & 2893 ) 2894 2895 output_var_table(35) = init_nc_var( & 2896 name = 'ls_forcing_soil_graupel', & 2897 std_name = "", & 2898 long_name = "large-scale forcing graupel", & 2899 units = "kg/m2", & 2900 kind = "surface forcing", & 2901 input_id = 1, & 2902 output_file = output_file, & 2903 grid = palm_grid, & 2904 intermediate_grid = palm_intermediate & 2905 ) 2906 2907 output_var_table(36) = init_nc_var( & 2908 name = 'ls_forcing_soil_t_2m', & 2909 std_name = "", & 2910 long_name = "large-scale forcing 2m air temperature", & 2911 units = "kg/m2", & 2912 kind = "surface forcing", & 2913 input_id = 1, & 2914 output_file = output_file, & 2915 grid = palm_grid, & 2916 intermediate_grid = palm_intermediate & 2917 ) 2918 2919 output_var_table(37) = init_nc_var( & 2920 name = 'ls_forcing_soil_evap', & 2921 std_name = "", & 2922 long_name = "large-scale forcing evapo-transpiration", & 2923 units = "kg/m2", & 2924 kind = "surface forcing", & 2925 input_id = 1, & 2926 output_file = output_file, & 2927 grid = palm_grid, & 2928 intermediate_grid = palm_intermediate & 2929 ) 2930 2931 output_var_table(38) = init_nc_var( & 2932 name = 'rad_swd_dif_0', & 2933 std_name = "", & 2934 long_name = "incoming diffuse shortwave radiative flux at the surface", & 2935 units = "W/m2", & 2936 kind = "surface forcing", & 2937 input_id = 1, & 2938 output_file = output_file, & 2939 grid = palm_grid, & 2940 intermediate_grid = palm_intermediate & 2941 ) 2942 2943 output_var_table(39) = init_nc_var( & 2944 name = 'rad_swd_dir_0', & 2945 std_name = "", & 2946 long_name = "incoming direct shortwave radiative flux at the surface", & 2947 units = "W/m2", & 2948 kind = "surface forcing", & 2949 input_id = 1, & 2950 output_file = output_file, & 2951 grid = palm_grid, & 2952 intermediate_grid = palm_intermediate & 2953 ) 2954 2955 output_var_table(40) = init_nc_var( & 2956 name = 'rad_sw_bal_0', & 2957 std_name = "", & 2958 long_name = "shortwave radiation balance at the surface", & 2959 units = "W/m2", & 2960 kind = "surface forcing", & 2961 input_id = 1, & 2962 output_file = output_file, & 2963 grid = palm_grid, & 2964 intermediate_grid = palm_intermediate & 2965 ) 2966 2967 output_var_table(41) = init_nc_var( & 2968 name = 'rad_lw_bal_0', & 2969 std_name = "", & 2970 long_name = "longwave radiation balance at the surface", & 2971 units = "W/m2", & 2972 kind = "surface forcing", & 2973 input_id = 1, & 2974 output_file = output_file, & 2975 grid = palm_grid, & 2976 intermediate_grid = palm_intermediate & 2977 ) 2959 2978 ! 2960 2979 !------------------------------------------------------------------------------ 2961 2980 ! Section 2.2: Idealized large-scale forcings 2962 2981 !------------------------------------------------------------------------------ 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 output_var_table(42) %averaging_grid => averaged_scalar_profile2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 output_var_table(45) %to_be_processed = ls_forcing_variables_required3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 output_var_table(46) %to_be_processed = ls_forcing_variables_required3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 output_var_table(47) %to_be_processed = ls_forcing_variables_required3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 output_var_table(48) %to_be_processed = ls_forcing_variables_required3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 output_var_table(49) %to_be_processed = ls_forcing_variables_required3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 output_var_table(50) %to_be_processed = ls_forcing_variables_required3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 output_var_table(51) %to_be_processed = ls_forcing_variables_required3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 output_var_table(52) %to_be_processed = ls_forcing_variables_required3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 output_var_table(53) %to_be_processed = ls_forcing_variables_required3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 output_var_table(54) %to_be_processed = ls_forcing_variables_required3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 output_var_table(55) %to_be_processed = ls_forcing_variables_required3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 output_var_table(56) %averaging_grid => averaged_scalar_profile3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 output_var_table(57) %averaging_grid => north_averaged_scalar_profile3172 output_var_table(57) % to_be_processed = .NOT. cfg %ug_defined_by_user3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 output_var_table(58) %averaging_grid => south_averaged_scalar_profile3187 output_var_table(58) % to_be_processed = .NOT. cfg %ug_defined_by_user3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 output_var_table(59) %averaging_grid => east_averaged_scalar_profile3202 output_var_table(59) % to_be_processed = .NOT. cfg %ug_defined_by_user3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 output_var_table(60) %averaging_grid => west_averaged_scalar_profile3217 output_var_table(60) % to_be_processed = .NOT. cfg %ug_defined_by_user3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 output_var_table(61) %averaging_grid => north_averaged_scalar_profile3231 output_var_table(61) % to_be_processed = .NOT. cfg %ug_defined_by_user3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 output_var_table(62) %averaging_grid => south_averaged_scalar_profile3246 output_var_table(62) % to_be_processed = .NOT. cfg %ug_defined_by_user3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 output_var_table(63) %averaging_grid => east_averaged_scalar_profile3261 output_var_table(63) % to_be_processed = .NOT. cfg %ug_defined_by_user3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 output_var_table(64) %averaging_grid => west_averaged_scalar_profile3276 output_var_table(64) % to_be_processed = .NOT. cfg %ug_defined_by_user3277 3278 ! 3279 !-- 3280 output_var_table(:) %source = nc_source_text3281 3282 3283 2982 output_var_table(42) = init_nc_var( & 2983 name = 'surface_forcing_surface_pressure', & 2984 std_name = "", & 2985 long_name = "surface pressure", & 2986 units = "Pa", & 2987 kind = "time series", & 2988 input_id = 2, & ! second in (T, p) I/O group 2989 output_file = output_file, & 2990 grid = palm_grid, & 2991 intermediate_grid = palm_intermediate & 2992 ) 2993 output_var_table(42)%averaging_grid => averaged_scalar_profile 2994 2995 output_var_table(43) = init_nc_var( & 2996 name = 'ls_forcing_ug', & 2997 std_name = "", & 2998 long_name = "geostrophic wind (u component)", & 2999 units = "m/s", & 3000 kind = "geostrophic", & 3001 input_id = 1, & 3002 output_file = output_file, & 3003 grid = averaged_scalar_profile, & 3004 intermediate_grid = averaged_scalar_profile & 3005 ) 3006 3007 output_var_table(44) = init_nc_var( & 3008 name = 'ls_forcing_vg', & 3009 std_name = "", & 3010 long_name = "geostrophic wind (v component)", & 3011 units = "m/s", & 3012 kind = "geostrophic", & 3013 input_id = 1, & 3014 output_file = output_file, & 3015 grid = averaged_scalar_profile, & 3016 intermediate_grid = averaged_scalar_profile & 3017 ) 3018 3019 output_var_table(45) = init_nc_var( & 3020 name = 'nudging_u', & 3021 std_name = "", & 3022 long_name = "wind component in x direction", & 3023 units = "m/s", & 3024 kind = "geostrophic", & 3025 input_id = 1, & 3026 output_file = output_file, & 3027 grid = averaged_scalar_profile, & 3028 intermediate_grid = averaged_scalar_profile & 3029 ) 3030 output_var_table(45)%to_be_processed = ls_forcing_variables_required 3031 3032 output_var_table(46) = init_nc_var( & 3033 name = 'nudging_v', & 3034 std_name = "", & 3035 long_name = "wind component in y direction", & 3036 units = "m/s", & 3037 kind = "large-scale scalar forcing", & 3038 input_id = 1, & 3039 output_file = output_file, & 3040 grid = averaged_scalar_profile, & 3041 intermediate_grid = averaged_scalar_profile & 3042 ) 3043 output_var_table(46)%to_be_processed = ls_forcing_variables_required 3044 3045 output_var_table(47) = init_nc_var( & 3046 name = 'ls_forcing_sub_w', & 3047 std_name = "", & 3048 long_name = "subsidence velocity of w", & 3049 units = "m/s", & 3050 kind = "large-scale w forcing", & 3051 input_id = 1, & 3052 output_file = output_file, & 3053 grid = averaged_scalar_profile, & 3054 intermediate_grid = averaged_scalar_profile & 3055 ) 3056 output_var_table(47)%to_be_processed = ls_forcing_variables_required 3057 3058 output_var_table(48) = init_nc_var( & 3059 name = 'nudging_w', & 3060 std_name = "", & 3061 long_name = "wind component in w direction", & 3062 units = "m/s", & 3063 kind = "large-scale w forcing", & 3064 input_id = 1, & 3065 output_file = output_file, & 3066 grid = averaged_w_profile, & 3067 intermediate_grid = averaged_w_profile & 3068 ) 3069 output_var_table(48)%to_be_processed = ls_forcing_variables_required 3070 3071 3072 output_var_table(49) = init_nc_var( & 3073 name = 'ls_forcing_adv_pt', & 3074 std_name = "", & 3075 long_name = "advection of potential temperature", & 3076 units = "K/s", & 3077 kind = "large-scale scalar forcing", & 3078 input_id = 1, & 3079 output_file = output_file, & 3080 grid = averaged_scalar_profile, & 3081 intermediate_grid = averaged_scalar_profile & 3082 ) 3083 output_var_table(49)%to_be_processed = ls_forcing_variables_required 3084 3085 output_var_table(50) = init_nc_var( & 3086 name = 'ls_forcing_sub_pt', & 3087 std_name = "", & 3088 long_name = "subsidence velocity of potential temperature", & 3089 units = "K/s", & 3090 kind = "large-scale scalar forcing", & 3091 input_id = 1, & 3092 output_file = output_file, & 3093 grid = averaged_scalar_profile, & 3094 intermediate_grid = averaged_scalar_profile & 3095 ) 3096 output_var_table(50)%to_be_processed = ls_forcing_variables_required 3097 3098 output_var_table(51) = init_nc_var( & 3099 name = 'nudging_pt', & 3100 std_name = "", & 3101 long_name = "potential temperature", & 3102 units = "K", & 3103 kind = "large-scale scalar forcing", & 3104 input_id = 1, & 3105 output_file = output_file, & 3106 grid = averaged_scalar_profile, & 3107 intermediate_grid = averaged_scalar_profile & 3108 ) 3109 output_var_table(51)%to_be_processed = ls_forcing_variables_required 3110 3111 output_var_table(52) = init_nc_var( & 3112 name = 'ls_forcing_adv_qv', & 3113 std_name = "", & 3114 long_name = "advection of specific humidity", & 3115 units = "kg/kg/s", & 3116 kind = "large-scale scalar forcing", & 3117 input_id = 3, & 3118 output_file = output_file, & 3119 grid = averaged_scalar_profile, & 3120 intermediate_grid = averaged_scalar_profile & 3121 ) 3122 output_var_table(52)%to_be_processed = ls_forcing_variables_required 3123 3124 3125 output_var_table(53) = init_nc_var( & 3126 name = 'ls_forcing_sub_qv', & 3127 std_name = "", & 3128 long_name = "subsidence velocity of specific humidity", & 3129 units = "kg/kg/s", & 3130 kind = "large-scale scalar forcing", & 3131 input_id = 3, & 3132 output_file = output_file, & 3133 grid = averaged_scalar_profile, & 3134 intermediate_grid = averaged_scalar_profile & 3135 ) 3136 output_var_table(53)%to_be_processed = ls_forcing_variables_required 3137 3138 output_var_table(54) = init_nc_var( & 3139 name = 'nudging_qv', & 3140 std_name = "", & 3141 long_name = "specific humidity", & 3142 units = "kg/kg", & 3143 kind = "large-scale scalar forcing", & 3144 input_id = 3, & 3145 output_file = output_file, & 3146 grid = averaged_scalar_profile, & 3147 intermediate_grid = averaged_scalar_profile & 3148 ) 3149 output_var_table(54)%to_be_processed = ls_forcing_variables_required 3150 3151 output_var_table(55) = init_nc_var( & 3152 name = 'nudging_tau', & 3153 std_name = "", & 3154 long_name = "nudging relaxation time scale", & 3155 units = "s", & 3156 kind = "constant scalar profile", & 3157 input_id = 1, & 3158 output_file = output_file, & 3159 grid = averaged_scalar_profile, & 3160 intermediate_grid = averaged_scalar_profile & 3161 ) 3162 output_var_table(55)%to_be_processed = ls_forcing_variables_required 3163 3164 3165 output_var_table(56) = init_nc_var( & 3166 name = 'internal_density_centre', & 3167 std_name = "", & 3168 long_name = "", & 3169 units = "", & 3170 kind = "internal profile", & 3171 input_id = 4, & 3172 output_file = output_file, & 3173 grid = averaged_scalar_profile, & 3174 intermediate_grid = averaged_scalar_profile & 3175 ) 3176 output_var_table(56)%averaging_grid => averaged_scalar_profile 3177 3178 3179 output_var_table(57) = init_nc_var( & 3180 name = 'internal_density_north', & 3181 std_name = "", & 3182 long_name = "", & 3183 units = "", & 3184 kind = "internal profile", & 3185 input_id = 4, & 3186 output_file = output_file, & 3187 grid = north_averaged_scalar_profile, & 3188 intermediate_grid = north_averaged_scalar_profile & 3189 ) 3190 output_var_table(57)%averaging_grid => north_averaged_scalar_profile 3191 output_var_table(57)%to_be_processed = .NOT. cfg%ug_defined_by_user 3192 3193 3194 output_var_table(58) = init_nc_var( & 3195 name = 'internal_density_south', & 3196 std_name = "", & 3197 long_name = "", & 3198 units = "", & 3199 kind = "internal profile", & 3200 input_id = 4, & 3201 output_file = output_file, & 3202 grid = south_averaged_scalar_profile, & 3203 intermediate_grid = south_averaged_scalar_profile & 3204 ) 3205 output_var_table(58)%averaging_grid => south_averaged_scalar_profile 3206 output_var_table(58)%to_be_processed = .NOT. cfg%ug_defined_by_user 3207 3208 3209 output_var_table(59) = init_nc_var( & 3210 name = 'internal_density_east', & 3211 std_name = "", & 3212 long_name = "", & 3213 units = "", & 3214 kind = "internal profile", & 3215 input_id = 4, & 3216 output_file = output_file, & 3217 grid = east_averaged_scalar_profile, & 3218 intermediate_grid = east_averaged_scalar_profile & 3219 ) 3220 output_var_table(59)%averaging_grid => east_averaged_scalar_profile 3221 output_var_table(59)%to_be_processed = .NOT. cfg%ug_defined_by_user 3222 3223 3224 output_var_table(60) = init_nc_var( & 3225 name = 'internal_density_west', & 3226 std_name = "", & 3227 long_name = "", & 3228 units = "", & 3229 kind = "internal profile", & 3230 input_id = 4, & 3231 output_file = output_file, & 3232 grid = west_averaged_scalar_profile, & 3233 intermediate_grid = west_averaged_scalar_profile & 3234 ) 3235 output_var_table(60)%averaging_grid => west_averaged_scalar_profile 3236 output_var_table(60)%to_be_processed = .NOT. cfg%ug_defined_by_user 3237 3238 output_var_table(61) = init_nc_var( & 3239 name = 'internal_pressure_north', & 3240 std_name = "", & 3241 long_name = "", & 3242 units = "", & 3243 kind = "internal profile", & 3244 input_id = 2, & 3245 output_file = output_file, & 3246 grid = north_averaged_scalar_profile, & 3247 intermediate_grid = north_averaged_scalar_profile & 3248 ) 3249 output_var_table(61)%averaging_grid => north_averaged_scalar_profile 3250 output_var_table(61)%to_be_processed = .NOT. cfg%ug_defined_by_user 3251 3252 3253 output_var_table(62) = init_nc_var( & 3254 name = 'internal_pressure_south', & 3255 std_name = "", & 3256 long_name = "", & 3257 units = "", & 3258 kind = "internal profile", & 3259 input_id = 2, & 3260 output_file = output_file, & 3261 grid = south_averaged_scalar_profile, & 3262 intermediate_grid = south_averaged_scalar_profile & 3263 ) 3264 output_var_table(62)%averaging_grid => south_averaged_scalar_profile 3265 output_var_table(62)%to_be_processed = .NOT. cfg%ug_defined_by_user 3266 3267 3268 output_var_table(63) = init_nc_var( & 3269 name = 'internal_pressure_east', & 3270 std_name = "", & 3271 long_name = "", & 3272 units = "", & 3273 kind = "internal profile", & 3274 input_id = 2, & 3275 output_file = output_file, & 3276 grid = east_averaged_scalar_profile, & 3277 intermediate_grid = east_averaged_scalar_profile & 3278 ) 3279 output_var_table(63)%averaging_grid => east_averaged_scalar_profile 3280 output_var_table(63)%to_be_processed = .NOT. cfg%ug_defined_by_user 3281 3282 3283 output_var_table(64) = init_nc_var( & 3284 name = 'internal_pressure_west', & 3285 std_name = "", & 3286 long_name = "", & 3287 units = "", & 3288 kind = "internal profile", & 3289 input_id = 2, & 3290 output_file = output_file, & 3291 grid = west_averaged_scalar_profile, & 3292 intermediate_grid = west_averaged_scalar_profile & 3293 ) 3294 output_var_table(64)%averaging_grid => west_averaged_scalar_profile 3295 output_var_table(64)%to_be_processed = .NOT. cfg%ug_defined_by_user 3296 3297 ! 3298 !-- Attributes shared among all variables 3299 output_var_table(:)%source = nc_source_text 3300 3301 3302 END SUBROUTINE setup_variable_tables 3284 3303 3285 3304 … … 3291 3310 !> 'lod', as defined by the PALM-4U input data standard. 3292 3311 !------------------------------------------------------------------------------! 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 var %name = name3313 var %standard_name = std_name3314 var %long_name = long_name3315 var %units = units3316 var %kind = TRIM(out_var_kind)3317 var %input_id = input_id3318 var % nt = SIZE (output_file %time)3319 var %grid => grid3320 var %intermediate_grid => intermediate_grid3321 3322 3312 FUNCTION init_nc_var(name, std_name, long_name, units, kind, input_id, & 3313 grid, intermediate_grid, output_file, is_profile) & 3314 RESULT(var) 3315 3316 CHARACTER(LEN=*), INTENT(IN) :: name, std_name, long_name, units, kind 3317 INTEGER, INTENT(IN) :: input_id 3318 TYPE(grid_definition), INTENT(IN), TARGET :: grid, intermediate_grid 3319 TYPE(nc_file), INTENT(IN) :: output_file 3320 LOGICAL, INTENT(IN), OPTIONAL :: is_profile 3321 3322 CHARACTER(LEN=LNAME) :: out_var_kind 3323 TYPE(nc_var) :: var 3324 3325 out_var_kind = TRIM(kind) 3326 3327 IF (PRESENT(is_profile)) THEN 3328 IF (is_profile) out_var_kind = TRIM(kind) // ' profile' 3329 ENDIF 3330 3331 var%name = name 3332 var%standard_name = std_name 3333 var%long_name = long_name 3334 var%units = units 3335 var%kind = TRIM(out_var_kind) 3336 var%input_id = input_id 3337 var%nt = SIZE (output_file%time) 3338 var%grid => grid 3339 var%intermediate_grid => intermediate_grid 3340 3341 SELECT CASE( TRIM(out_var_kind) ) 3323 3342 3324 3343 ! … … 3327 3346 !-- TODO: and pass into init_nc_var. 3328 3347 CASE( 'init soil' ) 3329 var %nt = 13330 var %lod = 23331 var %ndim = 33332 var % dimids(1:3) = output_file %dimids_soil3333 var % dimvarids(1:3) = output_file %dimvarids_soil3334 var %to_be_processed = init_variables_required3335 var %is_internal = .FALSE.3336 var %task = "interpolate_2d"3348 var%nt = 1 3349 var%lod = 2 3350 var%ndim = 3 3351 var%dimids(1:3) = output_file%dimids_soil 3352 var%dimvarids(1:3) = output_file%dimvarids_soil 3353 var%to_be_processed = init_variables_required 3354 var%is_internal = .FALSE. 3355 var%task = "interpolate_2d" 3337 3356 3338 3357 CASE( 'init scalar' ) 3339 var %nt = 13340 var %lod = 23341 var %ndim = 33342 var % dimids(1:3) = output_file %dimids_scl3343 var % dimvarids(1:3) = output_file %dimvarids_scl3344 var %to_be_processed = init_variables_required3345 var %is_internal = .FALSE.3346 var %task = "interpolate_3d"3358 var%nt = 1 3359 var%lod = 2 3360 var%ndim = 3 3361 var%dimids(1:3) = output_file%dimids_scl 3362 var%dimvarids(1:3) = output_file%dimvarids_scl 3363 var%to_be_processed = init_variables_required 3364 var%is_internal = .FALSE. 3365 var%task = "interpolate_3d" 3347 3366 3348 3367 CASE( 'init u' ) 3349 var %nt = 13350 var %lod = 23351 var %ndim = 33352 var % dimids(1) = output_file %dimids_vel(1)3353 var % dimids(2) = output_file %dimids_scl(2)3354 var % dimids(3) = output_file %dimids_scl(3)3355 var % dimvarids(1) = output_file %dimvarids_vel(1)3356 var % dimvarids(2) = output_file %dimvarids_scl(2)3357 var % dimvarids(3) = output_file %dimvarids_scl(3)3358 var %to_be_processed = init_variables_required3359 var %is_internal = .FALSE.3360 var %task = "interpolate_3d"3368 var%nt = 1 3369 var%lod = 2 3370 var%ndim = 3 3371 var%dimids(1) = output_file%dimids_vel(1) 3372 var%dimids(2) = output_file%dimids_scl(2) 3373 var%dimids(3) = output_file%dimids_scl(3) 3374 var%dimvarids(1) = output_file%dimvarids_vel(1) 3375 var%dimvarids(2) = output_file%dimvarids_scl(2) 3376 var%dimvarids(3) = output_file%dimvarids_scl(3) 3377 var%to_be_processed = init_variables_required 3378 var%is_internal = .FALSE. 3379 var%task = "interpolate_3d" 3361 3380 3362 3381 CASE( 'init v' ) 3363 var %nt = 13364 var %lod = 23365 var %ndim = 33366 var % dimids(1) = output_file %dimids_scl(1)3367 var % dimids(2) = output_file %dimids_vel(2)3368 var % dimids(3) = output_file %dimids_scl(3)3369 var % dimvarids(1) = output_file %dimvarids_scl(1)3370 var % dimvarids(2) = output_file %dimvarids_vel(2)3371 var % dimvarids(3) = output_file %dimvarids_scl(3)3372 var %to_be_processed = init_variables_required3373 var %is_internal = .FALSE.3374 var %task = "interpolate_3d"3382 var%nt = 1 3383 var%lod = 2 3384 var%ndim = 3 3385 var%dimids(1) = output_file%dimids_scl(1) 3386 var%dimids(2) = output_file%dimids_vel(2) 3387 var%dimids(3) = output_file%dimids_scl(3) 3388 var%dimvarids(1) = output_file%dimvarids_scl(1) 3389 var%dimvarids(2) = output_file%dimvarids_vel(2) 3390 var%dimvarids(3) = output_file%dimvarids_scl(3) 3391 var%to_be_processed = init_variables_required 3392 var%is_internal = .FALSE. 3393 var%task = "interpolate_3d" 3375 3394 3376 3395 CASE( 'init w' ) 3377 var %nt = 13378 var %lod = 23379 var %ndim = 33380 var % dimids(1) = output_file %dimids_scl(1)3381 var % dimids(2) = output_file %dimids_scl(2)3382 var % dimids(3) = output_file %dimids_vel(3)3383 var % dimvarids(1) = output_file %dimvarids_scl(1)3384 var % dimvarids(2) = output_file %dimvarids_scl(2)3385 var % dimvarids(3) = output_file %dimvarids_vel(3)3386 var %to_be_processed = init_variables_required3387 var %is_internal = .FALSE.3388 var %task = "interpolate_3d"3396 var%nt = 1 3397 var%lod = 2 3398 var%ndim = 3 3399 var%dimids(1) = output_file%dimids_scl(1) 3400 var%dimids(2) = output_file%dimids_scl(2) 3401 var%dimids(3) = output_file%dimids_vel(3) 3402 var%dimvarids(1) = output_file%dimvarids_scl(1) 3403 var%dimvarids(2) = output_file%dimvarids_scl(2) 3404 var%dimvarids(3) = output_file%dimvarids_vel(3) 3405 var%to_be_processed = init_variables_required 3406 var%is_internal = .FALSE. 3407 var%task = "interpolate_3d" 3389 3408 3390 3409 CASE( 'init scalar profile', 'init u profile', 'init v profile') 3391 var %nt = 13392 var %lod = 13393 var %ndim = 13394 var % dimids(1) = output_file %dimids_scl(3) !z3395 var % dimvarids(1) = output_file %dimvarids_scl(3) !z3396 var %to_be_processed = init_variables_required3397 var %is_internal = .FALSE.3398 var %task = "average profile"3410 var%nt = 1 3411 var%lod = 1 3412 var%ndim = 1 3413 var%dimids(1) = output_file%dimids_scl(3) !z 3414 var%dimvarids(1) = output_file%dimvarids_scl(3) !z 3415 var%to_be_processed = init_variables_required 3416 var%is_internal = .FALSE. 3417 var%task = "average profile" 3399 3418 3400 3419 CASE( 'init w profile') 3401 var %nt = 13402 var %lod = 13403 var %ndim = 13404 var % dimids(1) = output_file %dimids_vel(3) !z3405 var % dimvarids(1) = output_file %dimvarids_vel(3) !z3406 var %to_be_processed = init_variables_required3407 var %is_internal = .FALSE.3408 var %task = "average profile"3420 var%nt = 1 3421 var%lod = 1 3422 var%ndim = 1 3423 var%dimids(1) = output_file%dimids_vel(3) !z 3424 var%dimvarids(1) = output_file%dimvarids_vel(3) !z 3425 var%to_be_processed = init_variables_required 3426 var%is_internal = .FALSE. 3427 var%task = "average profile" 3409 3428 3410 3429 CASE( 'surface forcing' ) 3411 var %lod = -13412 var %ndim = 33413 var % dimids(3) = output_file %dimid_time3414 var % dimids(1:2) = output_file %dimids_soil(1:2)3415 var % dimvarids(3) = output_file %dimvarid_time3416 var % dimvarids(1:2) = output_file %dimvarids_soil(1:2)3417 var %to_be_processed = surface_forcing_required3418 var %is_internal = .FALSE.3419 var %task = "interpolate_2d"3430 var%lod = -1 3431 var%ndim = 3 3432 var%dimids(3) = output_file%dimid_time 3433 var%dimids(1:2) = output_file%dimids_soil(1:2) 3434 var%dimvarids(3) = output_file%dimvarid_time 3435 var%dimvarids(1:2) = output_file%dimvarids_soil(1:2) 3436 var%to_be_processed = surface_forcing_required 3437 var%is_internal = .FALSE. 3438 var%task = "interpolate_2d" 3420 3439 3421 3440 CASE( 'left scalar', 'right scalar') 3422 var %lod = -13423 var %ndim = 33424 var % dimids(3) = output_file %dimid_time3425 var % dimids(1) = output_file %dimids_scl(2)3426 var % dimids(2) = output_file %dimids_scl(3)3427 var % dimvarids(3) = output_file %dimvarid_time3428 var % dimvarids(1) = output_file %dimvarids_scl(2)3429 var % dimvarids(2) = output_file %dimvarids_scl(3)3430 var %to_be_processed = boundary_variables_required3431 var %is_internal = .FALSE.3432 var %task = "interpolate_3d"3441 var%lod = -1 3442 var%ndim = 3 3443 var%dimids(3) = output_file%dimid_time 3444 var%dimids(1) = output_file%dimids_scl(2) 3445 var%dimids(2) = output_file%dimids_scl(3) 3446 var%dimvarids(3) = output_file%dimvarid_time 3447 var%dimvarids(1) = output_file%dimvarids_scl(2) 3448 var%dimvarids(2) = output_file%dimvarids_scl(3) 3449 var%to_be_processed = boundary_variables_required 3450 var%is_internal = .FALSE. 3451 var%task = "interpolate_3d" 3433 3452 3434 3453 CASE( 'north scalar', 'south scalar') 3435 var %lod = -13436 var %ndim = 33437 var % dimids(3) = output_file %dimid_time3438 var % dimids(1) = output_file %dimids_scl(1)3439 var % dimids(2) = output_file %dimids_scl(3)3440 var % dimvarids(3) = output_file %dimvarid_time3441 var % dimvarids(1) = output_file %dimvarids_scl(1)3442 var % dimvarids(2) = output_file %dimvarids_scl(3)3443 var %to_be_processed = boundary_variables_required3444 var %is_internal = .FALSE.3445 var %task = "interpolate_3d"3454 var%lod = -1 3455 var%ndim = 3 3456 var%dimids(3) = output_file%dimid_time 3457 var%dimids(1) = output_file%dimids_scl(1) 3458 var%dimids(2) = output_file%dimids_scl(3) 3459 var%dimvarids(3) = output_file%dimvarid_time 3460 var%dimvarids(1) = output_file%dimvarids_scl(1) 3461 var%dimvarids(2) = output_file%dimvarids_scl(3) 3462 var%to_be_processed = boundary_variables_required 3463 var%is_internal = .FALSE. 3464 var%task = "interpolate_3d" 3446 3465 3447 3466 CASE( 'top scalar', 'top w' ) 3448 var %lod = -13449 var %ndim = 33450 var % dimids(3) = output_file %dimid_time3451 var % dimids(1) = output_file %dimids_scl(1)3452 var % dimids(2) = output_file %dimids_scl(2)3453 var % dimvarids(3) = output_file %dimvarid_time3454 var % dimvarids(1) = output_file %dimvarids_scl(1)3455 var % dimvarids(2) = output_file %dimvarids_scl(2)3456 var %to_be_processed = boundary_variables_required3457 var %is_internal = .FALSE.3458 var %task = "interpolate_3d"3467 var%lod = -1 3468 var%ndim = 3 3469 var%dimids(3) = output_file%dimid_time 3470 var%dimids(1) = output_file%dimids_scl(1) 3471 var%dimids(2) = output_file%dimids_scl(2) 3472 var%dimvarids(3) = output_file%dimvarid_time 3473 var%dimvarids(1) = output_file%dimvarids_scl(1) 3474 var%dimvarids(2) = output_file%dimvarids_scl(2) 3475 var%to_be_processed = boundary_variables_required 3476 var%is_internal = .FALSE. 3477 var%task = "interpolate_3d" 3459 3478 3460 3479 CASE( 'left u', 'right u' ) 3461 var %lod = -13462 var %ndim = 33463 var % dimids(3) = output_file %dimid_time3464 var % dimids(1) = output_file %dimids_scl(2)3465 var % dimids(2) = output_file %dimids_scl(3)3466 var % dimvarids(3) = output_file %dimvarid_time3467 var % dimvarids(1) = output_file %dimvarids_scl(2)3468 var % dimvarids(2) = output_file %dimvarids_scl(3)3469 var %to_be_processed = boundary_variables_required3470 var %is_internal = .FALSE.3471 var %task = "interpolate_3d"3480 var%lod = -1 3481 var%ndim = 3 3482 var%dimids(3) = output_file%dimid_time 3483 var%dimids(1) = output_file%dimids_scl(2) 3484 var%dimids(2) = output_file%dimids_scl(3) 3485 var%dimvarids(3) = output_file%dimvarid_time 3486 var%dimvarids(1) = output_file%dimvarids_scl(2) 3487 var%dimvarids(2) = output_file%dimvarids_scl(3) 3488 var%to_be_processed = boundary_variables_required 3489 var%is_internal = .FALSE. 3490 var%task = "interpolate_3d" 3472 3491 3473 3492 CASE( 'north u', 'south u' ) 3474 var %lod = -13475 var %ndim = 33476 var % dimids(3) = output_file %dimid_time !t3477 var % dimids(1) = output_file %dimids_vel(1) !x3478 var % dimids(2) = output_file %dimids_scl(3) !z3479 var % dimvarids(3) = output_file %dimvarid_time3480 var % dimvarids(1) = output_file %dimvarids_vel(1)3481 var % dimvarids(2) = output_file %dimvarids_scl(3)3482 var %to_be_processed = boundary_variables_required3483 var %is_internal = .FALSE.3484 var %task = "interpolate_3d"3493 var%lod = -1 3494 var%ndim = 3 3495 var%dimids(3) = output_file%dimid_time !t 3496 var%dimids(1) = output_file%dimids_vel(1) !x 3497 var%dimids(2) = output_file%dimids_scl(3) !z 3498 var%dimvarids(3) = output_file%dimvarid_time 3499 var%dimvarids(1) = output_file%dimvarids_vel(1) 3500 var%dimvarids(2) = output_file%dimvarids_scl(3) 3501 var%to_be_processed = boundary_variables_required 3502 var%is_internal = .FALSE. 3503 var%task = "interpolate_3d" 3485 3504 3486 3505 CASE( 'top u' ) 3487 var %lod = -13488 var %ndim = 33489 var % dimids(3) = output_file %dimid_time !t3490 var % dimids(1) = output_file %dimids_vel(1) !x3491 var % dimids(2) = output_file %dimids_scl(2) !z3492 var % dimvarids(3) = output_file %dimvarid_time3493 var % dimvarids(1) = output_file %dimvarids_vel(1)3494 var % dimvarids(2) = output_file %dimvarids_scl(2)3495 var %to_be_processed = boundary_variables_required3496 var %is_internal = .FALSE.3497 var %task = "interpolate_3d"3506 var%lod = -1 3507 var%ndim = 3 3508 var%dimids(3) = output_file%dimid_time !t 3509 var%dimids(1) = output_file%dimids_vel(1) !x 3510 var%dimids(2) = output_file%dimids_scl(2) !z 3511 var%dimvarids(3) = output_file%dimvarid_time 3512 var%dimvarids(1) = output_file%dimvarids_vel(1) 3513 var%dimvarids(2) = output_file%dimvarids_scl(2) 3514 var%to_be_processed = boundary_variables_required 3515 var%is_internal = .FALSE. 3516 var%task = "interpolate_3d" 3498 3517 3499 3518 CASE( 'left v', 'right v' ) 3500 var %lod = -13501 var %ndim = 33502 var % dimids(3) = output_file %dimid_time3503 var % dimids(1) = output_file %dimids_vel(2)3504 var % dimids(2) = output_file %dimids_scl(3)3505 var % dimvarids(3) = output_file %dimvarid_time3506 var % dimvarids(1) = output_file %dimvarids_vel(2)3507 var % dimvarids(2) = output_file %dimvarids_scl(3)3508 var %to_be_processed = boundary_variables_required3509 var %is_internal = .FALSE.3510 var %task = "interpolate_3d"3519 var%lod = -1 3520 var%ndim = 3 3521 var%dimids(3) = output_file%dimid_time 3522 var%dimids(1) = output_file%dimids_vel(2) 3523 var%dimids(2) = output_file%dimids_scl(3) 3524 var%dimvarids(3) = output_file%dimvarid_time 3525 var%dimvarids(1) = output_file%dimvarids_vel(2) 3526 var%dimvarids(2) = output_file%dimvarids_scl(3) 3527 var%to_be_processed = boundary_variables_required 3528 var%is_internal = .FALSE. 3529 var%task = "interpolate_3d" 3511 3530 3512 3531 CASE( 'north v', 'south v' ) 3513 var %lod = -13514 var %ndim = 33515 var % dimids(3) = output_file %dimid_time !t3516 var % dimids(1) = output_file %dimids_scl(1) !x3517 var % dimids(2) = output_file %dimids_scl(3) !z3518 var % dimvarids(3) = output_file %dimvarid_time3519 var % dimvarids(1) = output_file %dimvarids_scl(1)3520 var % dimvarids(2) = output_file %dimvarids_scl(3)3521 var %to_be_processed = boundary_variables_required3522 var %is_internal = .FALSE.3523 var %task = "interpolate_3d"3532 var%lod = -1 3533 var%ndim = 3 3534 var%dimids(3) = output_file%dimid_time !t 3535 var%dimids(1) = output_file%dimids_scl(1) !x 3536 var%dimids(2) = output_file%dimids_scl(3) !z 3537 var%dimvarids(3) = output_file%dimvarid_time 3538 var%dimvarids(1) = output_file%dimvarids_scl(1) 3539 var%dimvarids(2) = output_file%dimvarids_scl(3) 3540 var%to_be_processed = boundary_variables_required 3541 var%is_internal = .FALSE. 3542 var%task = "interpolate_3d" 3524 3543 3525 3544 CASE( 'top v' ) 3526 var %lod = -13527 var %ndim = 33528 var % dimids(3) = output_file %dimid_time !t3529 var % dimids(1) = output_file %dimids_scl(1) !x3530 var % dimids(2) = output_file %dimids_vel(2) !z3531 var % dimvarids(3) = output_file %dimvarid_time3532 var % dimvarids(1) = output_file %dimvarids_scl(1)3533 var % dimvarids(2) = output_file %dimvarids_vel(2)3534 var %to_be_processed = boundary_variables_required3535 var %is_internal = .FALSE.3536 var %task = "interpolate_3d"3545 var%lod = -1 3546 var%ndim = 3 3547 var%dimids(3) = output_file%dimid_time !t 3548 var%dimids(1) = output_file%dimids_scl(1) !x 3549 var%dimids(2) = output_file%dimids_vel(2) !z 3550 var%dimvarids(3) = output_file%dimvarid_time 3551 var%dimvarids(1) = output_file%dimvarids_scl(1) 3552 var%dimvarids(2) = output_file%dimvarids_vel(2) 3553 var%to_be_processed = boundary_variables_required 3554 var%is_internal = .FALSE. 3555 var%task = "interpolate_3d" 3537 3556 3538 3557 CASE( 'left w', 'right w') 3539 var %lod = -13540 var %ndim = 33541 var % dimids(3) = output_file %dimid_time3542 var % dimids(1) = output_file %dimids_scl(2)3543 var % dimids(2) = output_file %dimids_vel(3)3544 var % dimvarids(3) = output_file %dimvarid_time3545 var % dimvarids(1) = output_file %dimvarids_scl(2)3546 var % dimvarids(2) = output_file %dimvarids_vel(3)3547 var %to_be_processed = boundary_variables_required3548 var %is_internal = .FALSE.3549 var %task = "interpolate_3d"3558 var%lod = -1 3559 var%ndim = 3 3560 var%dimids(3) = output_file%dimid_time 3561 var%dimids(1) = output_file%dimids_scl(2) 3562 var%dimids(2) = output_file%dimids_vel(3) 3563 var%dimvarids(3) = output_file%dimvarid_time 3564 var%dimvarids(1) = output_file%dimvarids_scl(2) 3565 var%dimvarids(2) = output_file%dimvarids_vel(3) 3566 var%to_be_processed = boundary_variables_required 3567 var%is_internal = .FALSE. 3568 var%task = "interpolate_3d" 3550 3569 3551 3570 CASE( 'north w', 'south w' ) 3552 var %lod = -13553 var %ndim = 33554 var % dimids(3) = output_file %dimid_time !t3555 var % dimids(1) = output_file %dimids_scl(1) !x3556 var % dimids(2) = output_file %dimids_vel(3) !z3557 var % dimvarids(3) = output_file %dimvarid_time3558 var % dimvarids(1) = output_file %dimvarids_scl(1)3559 var % dimvarids(2) = output_file %dimvarids_vel(3)3560 var %to_be_processed = boundary_variables_required3561 var %is_internal = .FALSE.3562 var %task = "interpolate_3d"3571 var%lod = -1 3572 var%ndim = 3 3573 var%dimids(3) = output_file%dimid_time !t 3574 var%dimids(1) = output_file%dimids_scl(1) !x 3575 var%dimids(2) = output_file%dimids_vel(3) !z 3576 var%dimvarids(3) = output_file%dimvarid_time 3577 var%dimvarids(1) = output_file%dimvarids_scl(1) 3578 var%dimvarids(2) = output_file%dimvarids_vel(3) 3579 var%to_be_processed = boundary_variables_required 3580 var%is_internal = .FALSE. 3581 var%task = "interpolate_3d" 3563 3582 3564 3583 CASE( 'time series' ) 3565 var %lod = 03566 var %ndim = 13567 var % dimids(1) = output_file %dimid_time !t3568 var % dimvarids(1) = output_file %dimvarid_time3569 var %to_be_processed = .TRUE.3570 var %is_internal = .FALSE.3571 var %task = "average profile"3584 var%lod = 0 3585 var%ndim = 1 3586 var%dimids(1) = output_file%dimid_time !t 3587 var%dimvarids(1) = output_file%dimvarid_time 3588 var%to_be_processed = .TRUE. 3589 var%is_internal = .FALSE. 3590 var%task = "average profile" 3572 3591 3573 3592 CASE( 'constant scalar profile' ) 3574 var %lod = -13575 var %ndim = 23576 var % dimids(2) = output_file %dimid_time !t3577 var % dimids(1) = output_file %dimids_scl(3) !z3578 var % dimvarids(2) = output_file %dimvarid_time3579 var % dimvarids(1) = output_file %dimvarids_scl(3)3580 var %to_be_processed = .TRUE.3581 var %is_internal = .FALSE.3582 var %task = "set profile"3593 var%lod = -1 3594 var%ndim = 2 3595 var%dimids(2) = output_file%dimid_time !t 3596 var%dimids(1) = output_file%dimids_scl(3) !z 3597 var%dimvarids(2) = output_file%dimvarid_time 3598 var%dimvarids(1) = output_file%dimvarids_scl(3) 3599 var%to_be_processed = .TRUE. 3600 var%is_internal = .FALSE. 3601 var%task = "set profile" 3583 3602 3584 3603 CASE( 'large-scale scalar forcing' ) 3585 var %lod = -13586 var %ndim = 23587 var % dimids(2) = output_file %dimid_time !t3588 var % dimids(1) = output_file %dimids_scl(3) !z3589 var % dimvarids(2) = output_file %dimvarid_time3590 var % dimvarids(1) = output_file %dimvarids_scl(3)3591 var %to_be_processed = ls_forcing_variables_required3592 var %is_internal = .FALSE.3593 var %task = "average large-scale profile"3604 var%lod = -1 3605 var%ndim = 2 3606 var%dimids(2) = output_file%dimid_time !t 3607 var%dimids(1) = output_file%dimids_scl(3) !z 3608 var%dimvarids(2) = output_file%dimvarid_time 3609 var%dimvarids(1) = output_file%dimvarids_scl(3) 3610 var%to_be_processed = ls_forcing_variables_required 3611 var%is_internal = .FALSE. 3612 var%task = "average large-scale profile" 3594 3613 3595 3614 CASE( 'geostrophic' ) 3596 var %lod = -13597 var %ndim = 23598 var % dimids(2) = output_file %dimid_time !t3599 var % dimids(1) = output_file %dimids_scl(3) !z3600 var % dimvarids(2) = output_file %dimvarid_time3601 var % dimvarids(1) = output_file %dimvarids_scl(3)3602 var %to_be_processed = .TRUE.3603 var %is_internal = .FALSE.3604 var %task = "geostrophic winds"3615 var%lod = -1 3616 var%ndim = 2 3617 var%dimids(2) = output_file%dimid_time !t 3618 var%dimids(1) = output_file%dimids_scl(3) !z 3619 var%dimvarids(2) = output_file%dimvarid_time 3620 var%dimvarids(1) = output_file%dimvarids_scl(3) 3621 var%to_be_processed = .TRUE. 3622 var%is_internal = .FALSE. 3623 var%task = "geostrophic winds" 3605 3624 3606 3625 CASE( 'large-scale w forcing' ) 3607 var %lod = -13608 var %ndim = 23609 var % dimids(2) = output_file %dimid_time !t3610 var % dimids(1) = output_file %dimids_vel(3) !z3611 var % dimvarids(2) = output_file %dimvarid_time3612 var % dimvarids(1) = output_file %dimvarids_vel(3)3613 var %to_be_processed = ls_forcing_variables_required3614 var %is_internal = .FALSE.3615 var %task = "average large-scale profile"3626 var%lod = -1 3627 var%ndim = 2 3628 var%dimids(2) = output_file%dimid_time !t 3629 var%dimids(1) = output_file%dimids_vel(3) !z 3630 var%dimvarids(2) = output_file%dimvarid_time 3631 var%dimvarids(1) = output_file%dimvarids_vel(3) 3632 var%to_be_processed = ls_forcing_variables_required 3633 var%is_internal = .FALSE. 3634 var%task = "average large-scale profile" 3616 3635 3617 3636 CASE( 'internal profile' ) 3618 var %lod = -13619 var %ndim = 23620 var % dimids(2) = output_file %dimid_time !t3621 var % dimids(1) = output_file %dimids_scl(3) !z3622 var % dimvarids(2) = output_file %dimvarid_time3623 var % dimvarids(1) = output_file %dimvarids_scl(3)3624 var %to_be_processed = .TRUE.3625 var %is_internal = .TRUE.3626 var %task = "internal profile"3637 var%lod = -1 3638 var%ndim = 2 3639 var%dimids(2) = output_file%dimid_time !t 3640 var%dimids(1) = output_file%dimids_scl(3) !z 3641 var%dimvarids(2) = output_file%dimvarid_time 3642 var%dimvarids(1) = output_file%dimvarids_scl(3) 3643 var%to_be_processed = .TRUE. 3644 var%is_internal = .TRUE. 3645 var%task = "internal profile" 3627 3646 3628 3647 CASE DEFAULT … … 3630 3649 CALL inifor_abort ('init_nc_var', message) 3631 3650 3632 3633 3634 3635 3636 3637 3638 3639 CALL report('fini_variables', 'Deallocating variable table', cfg %debug)3640 3641 3642 3643 3644 3645 3646 3647 CALL report('fini_io_groups', 'Deallocating IO groups', cfg %debug)3648 3649 3650 3651 3652 3653 3654 3655 CALL report('fini_file_lists', 'Deallocating file lists', cfg %debug)3656 3657 3658 3651 END SELECT 3652 3653 END FUNCTION init_nc_var 3654 3655 3656 SUBROUTINE fini_variables() 3657 3658 CALL report('fini_variables', 'Deallocating variable table', cfg%debug) 3659 DEALLOCATE( input_var_table ) 3660 3661 END SUBROUTINE fini_variables 3662 3663 3664 SUBROUTINE fini_io_groups() 3665 3666 CALL report('fini_io_groups', 'Deallocating IO groups', cfg%debug) 3667 DEALLOCATE( io_group_list ) 3668 3669 END SUBROUTINE fini_io_groups 3670 3671 3672 SUBROUTINE fini_file_lists() 3673 3674 CALL report('fini_file_lists', 'Deallocating file lists', cfg%debug) 3675 DEALLOCATE( flow_files, soil_files, radiation_files, soil_moisture_files ) 3676 3677 END SUBROUTINE fini_file_lists 3659 3678 3660 3679 … … 3670 3689 !> array will match a COSMO-DE scalar array. 3671 3690 !------------------------------------------------------------------------------! 3672 3673 3674 3675 3676 3677 3678 3679 REAL(dp), ALLOCATABLE :: basic_state_pressure(:)3680 3681 3682 3683 3684 3685 input_buffer(:) %is_preprocessed = .FALSE.3686 3687 SELECT CASE( group %kind )3691 SUBROUTINE preprocess(group, input_buffer, cosmo_grid, iter) 3692 3693 TYPE(io_group), INTENT(INOUT), TARGET :: group 3694 TYPE(container), INTENT(INOUT), ALLOCATABLE :: input_buffer(:) 3695 TYPE(grid_definition), INTENT(IN) :: cosmo_grid 3696 INTEGER, INTENT(IN) :: iter 3697 3698 REAL(wp), ALLOCATABLE :: basic_state_pressure(:) 3699 TYPE(container), ALLOCATABLE :: preprocess_buffer(:) 3700 INTEGER :: hour, dt 3701 INTEGER :: i, j, k 3702 INTEGER :: nx, ny, nz 3703 3704 input_buffer(:)%is_preprocessed = .FALSE. 3705 3706 SELECT CASE( group%kind ) 3688 3707 3689 3708 CASE( 'velocities' ) … … 3694 3713 ! 3695 3714 !-- Allocate u and v arrays with scalar dimensions 3696 nx = SIZE(input_buffer(1) %array, 1)3697 ny = SIZE(input_buffer(1) %array, 2)3698 nz = SIZE(input_buffer(1) %array, 3)3699 ALLOCATE( preprocess_buffer(1) %array(nx, ny, nz) ) ! u buffer3700 ALLOCATE( preprocess_buffer(2) %array(nx, ny, nz) ) ! v buffer3701 3702 CALL run_control('time', 'alloc')3715 nx = SIZE(input_buffer(1)%array, 1) 3716 ny = SIZE(input_buffer(1)%array, 2) 3717 nz = SIZE(input_buffer(1)%array, 3) 3718 ALLOCATE( preprocess_buffer(1)%array(nx, ny, nz) ) ! u buffer 3719 ALLOCATE( preprocess_buffer(2)%array(nx, ny, nz) ) ! v buffer 3720 3721 CALL log_runtime('time', 'alloc') 3703 3722 3704 3723 ! 3705 3724 !-- interpolate U and V to centres 3706 CALL centre_velocities( u_face = input_buffer(1) %array, &3707 v_face = input_buffer(2) %array, &3708 u_centre = preprocess_buffer(1) %array, &3709 v_centre = preprocess_buffer(2) %array )3725 CALL centre_velocities( u_face = input_buffer(1)%array, & 3726 v_face = input_buffer(2)%array, & 3727 u_centre = preprocess_buffer(1)%array, & 3728 v_centre = preprocess_buffer(2)%array ) 3710 3729 3711 cfg %rotation_method = 'rotated-pole'3712 SELECT CASE(cfg %rotation_method)3713 3714 CASE('rotated-pole')3715 ! 3716 !-- rotate U and V to PALM-4U orientation and overwrite U and V with3717 !-- rotated velocities3718 DOk = 1, nz3719 DOj = 1, ny3720 DOi = 1, nx3721 CALL uv2uvrot( urot = preprocess_buffer(1) %array(i,j,k), &3722 vrot = preprocess_buffer(2) %array(i,j,k), &3723 rlat = cosmo_grid %lat(j-1), &3724 rlon = cosmo_grid %lon(i-1), &3725 pollat = phi_cn, &3726 pollon = lambda_cn, &3727 u = input_buffer(1) %array(i,j,k), &3728 v = input_buffer(2) %array(i,j,k) )3729 ENDDO3730 ENDDO3731 ENDDO3732 3733 CASE DEFAULT3734 message = "Rotation method '" // TRIM(cfg %rotation_method) // &3735 "' not recognized."3736 CALL inifor_abort('preprocess', message)3730 cfg%rotation_method = 'rotated-pole' 3731 SELECT CASE(cfg%rotation_method) 3732 3733 CASE('rotated-pole') 3734 ! 3735 !-- rotate U and V to PALM-4U orientation and overwrite U and V with 3736 !-- rotated velocities 3737 DO k = 1, nz 3738 DO j = 1, ny 3739 DO i = 1, nx 3740 CALL uv2uvrot( urot = preprocess_buffer(1)%array(i,j,k), & 3741 vrot = preprocess_buffer(2)%array(i,j,k), & 3742 rlat = cosmo_grid%lat(j-1), & 3743 rlon = cosmo_grid%lon(i-1), & 3744 pollat = phi_cn, & 3745 pollon = lambda_cn, & 3746 u = input_buffer(1)%array(i,j,k), & 3747 v = input_buffer(2)%array(i,j,k) ) 3748 ENDDO 3749 ENDDO 3750 ENDDO 3751 3752 CASE DEFAULT 3753 message = "Rotation method '" // TRIM(cfg%rotation_method) // & 3754 "' not recognized." 3755 CALL inifor_abort('preprocess', message) 3737 3756 3738 3757 END SELECT 3739 3758 3740 input_buffer(1) % array(1,:,:) = 0.0_dp3741 input_buffer(2) % array(1,:,:) = 0.0_dp3742 input_buffer(1) % array(:,1,:) = 0.0_dp3743 input_buffer(2) % array(:,1,:) = 0.0_dp3744 3745 input_buffer(1:2) %is_preprocessed = .TRUE.3746 CALL run_control('time', 'comp')3759 input_buffer(1)%array(1,:,:) = 0.0_wp 3760 input_buffer(2)%array(1,:,:) = 0.0_wp 3761 input_buffer(1)%array(:,1,:) = 0.0_wp 3762 input_buffer(2)%array(:,1,:) = 0.0_wp 3763 3764 input_buffer(1:2)%is_preprocessed = .TRUE. 3765 CALL log_runtime('time', 'comp') 3747 3766 3748 3767 DEALLOCATE( preprocess_buffer ) 3749 CALL run_control('time', 'alloc')3750 3751 message = "Input buffers for group '" // TRIM(group %kind) // "'"//&3768 CALL log_runtime('time', 'alloc') 3769 3770 message = "Input buffers for group '" // TRIM(group%kind) // "'"//& 3752 3771 " preprocessed sucessfully." 3753 3772 CALL report('preprocess', message) 3754 3773 3755 3774 CASE( 'thermodynamics' ) ! T, P, QV 3756 nx = SIZE(input_buffer(1) %array, 1)3757 ny = SIZE(input_buffer(1) %array, 2)3758 nz = SIZE(input_buffer(1) %array, 3)3775 nx = SIZE(input_buffer(1)%array, 1) 3776 ny = SIZE(input_buffer(1)%array, 2) 3777 nz = SIZE(input_buffer(1)%array, 3) 3759 3778 3760 3779 ! 3761 3780 !-- Compute absolute pressure if presure perturbation has been read in. 3762 IF ( TRIM(group % in_var_list(2) %name) == 'PP' ) THEN3781 IF ( TRIM(group%in_var_list(2)%name) == 'PP' ) THEN 3763 3782 message = "Absolute pressure, P, not available, " // & 3764 3783 "computing from pressure preturbation PP." … … 3766 3785 3767 3786 ALLOCATE( basic_state_pressure(1:nz) ) 3768 CALL run_control('time', 'alloc')3769 3770 DO j = 1, ny3771 DO i = 1, nx3772 3773 CALL get_basic_state(cosmo_grid %hfl(i,j,:), BETA, P_SL, T_SL,&3787 CALL log_runtime('time', 'alloc') 3788 3789 DO j = 1, ny 3790 DO i = 1, nx 3791 3792 CALL get_basic_state(cosmo_grid%hfl(i,j,:), BETA, P_SL, T_SL,& 3774 3793 RD, G, basic_state_pressure) 3775 3794 … … 3777 3796 !-- Overwrite pressure perturbation with absolute pressure. HECTO 3778 3797 !-- converts pressure perturbation from hPa to Pa. 3779 input_buffer (2) %array(i,j,:) = &3780 HECTO * input_buffer (2) %array(i,j,:) + &3798 input_buffer (2)%array(i,j,:) = & 3799 HECTO * input_buffer (2)%array(i,j,:) + & 3781 3800 basic_state_pressure(:) 3782 3801 3783 3802 ENDDO 3784 3803 ENDDO 3785 CALL run_control('time', 'comp')3804 CALL log_runtime('time', 'comp') 3786 3805 3787 3806 DEALLOCATE( basic_state_pressure ) 3788 CALL run_control('time', 'alloc')3789 3790 group % in_var_list(2) %name = 'P'3807 CALL log_runtime('time', 'alloc') 3808 3809 group%in_var_list(2)%name = 'P' 3791 3810 3792 3811 ENDIF 3793 3812 ! 3794 3813 !-- mark pressure as preprocessed 3795 input_buffer(2) %is_preprocessed = .TRUE.3814 input_buffer(2)%is_preprocessed = .TRUE. 3796 3815 3797 3816 ! 3798 3817 !-- Copy temperature to the last input buffer array 3799 3818 ALLOCATE( & 3800 input_buffer( group % n_output_quantities ) %array (nx, ny, nz) &3819 input_buffer( group%n_output_quantities )%array (nx, ny, nz) & 3801 3820 ) 3802 input_buffer(group % n_output_quantities) % array(:,:,:) = & 3803 input_buffer(1) % array(:,:,:) 3821 CALL log_runtime('time', 'alloc') 3822 input_buffer(group%n_output_quantities)%array(:,:,:) = & 3823 input_buffer(1)%array(:,:,:) 3804 3824 3805 3825 ! 3806 3826 !-- Convert absolute in place to potential temperature 3807 3827 CALL potential_temperature( & 3808 t = input_buffer(1) %array(:,:,:), &3809 p = input_buffer(2) %array(:,:,:), &3828 t = input_buffer(1)%array(:,:,:), & 3829 p = input_buffer(2)%array(:,:,:), & 3810 3830 p_ref = P_REF, & 3811 3831 r = RD_PALM, & … … 3815 3835 ! 3816 3836 !-- mark potential temperature as preprocessed 3817 input_buffer(1) %is_preprocessed = .TRUE.3837 input_buffer(1)%is_preprocessed = .TRUE. 3818 3838 3819 3839 ! 3820 3840 !-- Convert temperature copy to density 3821 3841 CALL moist_density( & 3822 t_rho = input_buffer(group % n_output_quantities) %array(:,:,:), &3823 p = input_buffer(2) %array(:,:,:), &3824 qv = input_buffer(3) %array(:,:,:), &3842 t_rho = input_buffer(group%n_output_quantities)%array(:,:,:), & 3843 p = input_buffer(2)%array(:,:,:), & 3844 qv = input_buffer(3)%array(:,:,:), & 3825 3845 rd = RD, & 3826 3846 rv = RV & … … 3829 3849 ! 3830 3850 !-- mark qv as preprocessed 3831 input_buffer(3) %is_preprocessed = .TRUE.3851 input_buffer(3)%is_preprocessed = .TRUE. 3832 3852 3833 3853 ! 3834 3854 !-- mark density as preprocessed 3835 input_buffer(group % n_output_quantities) %is_preprocessed = .TRUE.3836 3837 3838 message = "Input buffers for group '" // TRIM(group %kind) // "'"//&3855 input_buffer(group%n_output_quantities)%is_preprocessed = .TRUE. 3856 3857 3858 message = "Input buffers for group '" // TRIM(group%kind) // "'"//& 3839 3859 " preprocessed sucessfully." 3840 3860 CALL report('preprocess', message) 3841 CALL run_control('time', 'comp')3842 3861 3843 3862 CASE( 'scalar' ) ! S or W 3844 input_buffer(:) % is_preprocessed = .TRUE. 3845 CALL run_control('time', 'comp') 3863 input_buffer(:)%is_preprocessed = .TRUE. 3846 3864 3847 3865 CASE( 'soil-temperature' ) ! 3848 3866 3849 CALL fill_water_cells(soiltyp, input_buffer(1) %array, &3850 SIZE(input_buffer(1) %array, 3), &3867 CALL fill_water_cells(soiltyp, input_buffer(1)%array, & 3868 SIZE(input_buffer(1)%array, 3), & 3851 3869 FILL_ITERATIONS) 3852 input_buffer(:) % is_preprocessed = .TRUE. 3853 CALL run_control('time', 'comp') 3870 input_buffer(:)%is_preprocessed = .TRUE. 3854 3871 3855 3872 CASE( 'soil-water' ) ! 3856 3873 3857 CALL fill_water_cells(soiltyp, input_buffer(1) %array, &3858 SIZE(input_buffer(1) %array, 3), &3874 CALL fill_water_cells(soiltyp, input_buffer(1)%array, & 3875 SIZE(input_buffer(1)%array, 3), & 3859 3876 FILL_ITERATIONS) 3860 3877 3861 nx = SIZE(input_buffer(1) %array, 1)3862 ny = SIZE(input_buffer(1) %array, 2)3863 nz = SIZE(input_buffer(1) %array, 3)3864 3865 DO k = 1, nz3866 DO j = 1, ny3867 DO i = 1, nx3868 input_buffer(1) %array(i,j,k) = &3869 input_buffer(1) %array(i,j,k) * d_depth_rho_inv(k)3878 nx = SIZE(input_buffer(1)%array, 1) 3879 ny = SIZE(input_buffer(1)%array, 2) 3880 nz = SIZE(input_buffer(1)%array, 3) 3881 3882 DO k = 1, nz 3883 DO j = 1, ny 3884 DO i = 1, nx 3885 input_buffer(1)%array(i,j,k) = & 3886 input_buffer(1)%array(i,j,k) * d_depth_rho_inv(k) 3870 3887 ENDDO 3871 3888 ENDDO … … 3875 3892 CALL report('preprocess', message) 3876 3893 3877 input_buffer(:) % is_preprocessed = .TRUE. 3878 CALL run_control('time', 'comp') 3894 input_buffer(:)%is_preprocessed = .TRUE. 3879 3895 3880 3896 CASE( 'surface' ) ! 3881 input_buffer(:) % is_preprocessed = .TRUE. 3882 CALL run_control('time', 'comp') 3897 input_buffer(:)%is_preprocessed = .TRUE. 3883 3898 3884 3899 CASE( 'accumulated' ) ! 3885 message = "De-accumulating '" // TRIM(group % in_var_list(1) %name) //&3900 message = "De-accumulating '" // TRIM(group%in_var_list(1)%name) //& 3886 3901 "' in iteration " // TRIM(str(iter)) 3887 3902 CALL report('preprocess', message) … … 3892 3907 3893 3908 ! 3894 !-- input has been accumulated over one hour. Leave as is3895 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral3896 CASE(1)3897 3898 ! 3899 !-- input has been accumulated over two hours. Subtract previous step3900 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral3901 !-- input_buffer(2) %array(:,:,:) carrries two-hour integral3902 CASE(2)3903 CALL deaverage( &3904 avg_1 = input_buffer(1) % array(:,:,:), t1 = 1.0_dp, &3905 avg_2 = input_buffer(2) % array(:,:,:), t2 = 1.0_dp, &3906 avg_3 = input_buffer(1) % array(:,:,:), t3 = 1.0_dp )3907 ! 3908 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral of second hour3909 3910 ! 3911 !-- input has been accumulated over three hours. Subtract previous step3912 !-- input_buffer(1) %array(:,:,:) carrries three-hour integral3913 !-- input_buffer(2) %array(:,:,:) still carrries two-hour integral3914 CASE(3)3915 CALL deaverage( &3916 avg_1 = input_buffer(2) % array(:,:,:), t1 = 1.0_dp, &3917 avg_2 = input_buffer(1) % array(:,:,:), t2 = 1.0_dp, &3918 avg_3 = input_buffer(1) % array(:,:,:), t3 = 1.0_dp )3919 ! 3920 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral of third hourA3921 3922 CASE DEFAULT3923 message = "Invalid averaging period '" // TRIM(str(dt)) // " hours"3924 CALL inifor_abort('preprocess', message)3909 !-- input has been accumulated over one hour. Leave as is 3910 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral 3911 CASE(1) 3912 3913 ! 3914 !-- input has been accumulated over two hours. Subtract previous step 3915 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral 3916 !-- input_buffer(2)%array(:,:,:) carrries two-hour integral 3917 CASE(2) 3918 CALL deaverage( & 3919 avg_1 = input_buffer(1)%array(:,:,:), t1 = 1.0_wp, & 3920 avg_2 = input_buffer(2)%array(:,:,:), t2 = 1.0_wp, & 3921 avg_3 = input_buffer(1)%array(:,:,:), t3 = 1.0_wp ) 3922 ! 3923 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral of second hour 3924 3925 ! 3926 !-- input has been accumulated over three hours. Subtract previous step 3927 !-- input_buffer(1)%array(:,:,:) carrries three-hour integral 3928 !-- input_buffer(2)%array(:,:,:) still carrries two-hour integral 3929 CASE(3) 3930 CALL deaverage( & 3931 avg_1 = input_buffer(2)%array(:,:,:), t1 = 1.0_wp, & 3932 avg_2 = input_buffer(1)%array(:,:,:), t2 = 1.0_wp, & 3933 avg_3 = input_buffer(1)%array(:,:,:), t3 = 1.0_wp ) 3934 ! 3935 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral of third hourA 3936 3937 CASE DEFAULT 3938 message = "Invalid averaging period '" // TRIM(str(dt)) // " hours" 3939 CALL inifor_abort('preprocess', message) 3925 3940 3926 3941 END SELECT 3927 input_buffer(:) % is_preprocessed = .TRUE. 3928 CALL run_control('time', 'comp') 3942 input_buffer(:)%is_preprocessed = .TRUE. 3929 3943 3930 3944 CASE( 'running average' ) ! 3931 message = "De-averaging '" // TRIM(group % in_var_list(1) %name) // &3945 message = "De-averaging '" // TRIM(group%in_var_list(1)%name) // & 3932 3946 "' in iteration " // TRIM(str(iter)) 3933 3947 CALL report('preprocess', message) … … 3939 3953 SELECT CASE(dt) 3940 3954 ! 3941 !-- input has been accumulated over one hour. Leave as is3942 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral3943 CASE(1)3944 3945 ! 3946 !-- input has been accumulated over two hours. Subtract previous step3947 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral3948 !-- input_buffer(2) %array(:,:,:) carrries two-hour integral3949 CASE(2)3950 CALL deaverage( input_buffer(1) % array(:,:,:), 1.0_dp, &3951 input_buffer(2) % array(:,:,:), 2.0_dp, &3952 input_buffer(1) % array(:,:,:), 1.0_dp)3953 ! 3954 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral of second hour3955 3956 ! 3957 !-- input has been accumulated over three hours. Subtract previous step3958 !-- input_buffer(1) %array(:,:,:) carrries three-hour integral3959 !-- input_buffer(2) %array(:,:,:) still carrries two-hour integral3960 CASE(3)3961 CALL deaverage( input_buffer(2) % array(:,:,:), 2.0_dp, &3962 input_buffer(1) % array(:,:,:), 3.0_dp, &3963 input_buffer(1) % array(:,:,:), 1.0_dp)3964 ! 3965 !-- input_buffer(1) %array(:,:,:) carrries one-hour integral of third hourA3966 3967 CASE DEFAULT3968 message = "Invalid averaging period '" // TRIM(str(dt)) // " hours"3969 CALL inifor_abort('preprocess', message)3955 !-- input has been accumulated over one hour. Leave as is 3956 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral 3957 CASE(1) 3958 3959 ! 3960 !-- input has been accumulated over two hours. Subtract previous step 3961 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral 3962 !-- input_buffer(2)%array(:,:,:) carrries two-hour integral 3963 CASE(2) 3964 CALL deaverage( input_buffer(1)%array(:,:,:), 1.0_wp, & 3965 input_buffer(2)%array(:,:,:), 2.0_wp, & 3966 input_buffer(1)%array(:,:,:), 1.0_wp) 3967 ! 3968 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral of second hour 3969 3970 ! 3971 !-- input has been accumulated over three hours. Subtract previous step 3972 !-- input_buffer(1)%array(:,:,:) carrries three-hour integral 3973 !-- input_buffer(2)%array(:,:,:) still carrries two-hour integral 3974 CASE(3) 3975 CALL deaverage( input_buffer(2)%array(:,:,:), 2.0_wp, & 3976 input_buffer(1)%array(:,:,:), 3.0_wp, & 3977 input_buffer(1)%array(:,:,:), 1.0_wp) 3978 ! 3979 !-- input_buffer(1)%array(:,:,:) carrries one-hour integral of third hourA 3980 3981 CASE DEFAULT 3982 message = "Invalid averaging period '" // TRIM(str(dt)) // " hours" 3983 CALL inifor_abort('preprocess', message) 3970 3984 3971 3985 END SELECT 3972 input_buffer(:) %is_preprocessed = .TRUE.3986 input_buffer(:)%is_preprocessed = .TRUE. 3973 3987 3974 3988 CASE DEFAULT 3975 message = "IO group kind '" // TRIM(group %kind) // "' is not supported."3989 message = "IO group kind '" // TRIM(group%kind) // "' is not supported." 3976 3990 CALL inifor_abort('prerpocess', message) 3977 3991 3978 3979 CALL run_control('time', 'comp')3980 3981 3992 END SELECT 3993 CALL log_runtime('time', 'comp') 3994 3995 END SUBROUTINE preprocess 3982 3996 3983 3997 … … 4006 4020 !> array : the soil array (i.e. water content or temperature) 4007 4021 !------------------------------------------------------------------------------! 4008 SUBROUTINE fill_water_cells(soiltyp, array, nz, niter) 4009 INTEGER(hp), DIMENSION(:,:,:), INTENT(IN) :: soiltyp 4010 REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) :: array 4011 INTEGER, INTENT(IN) :: nz, niter 4012 4013 REAL(dp), DIMENSION(nz) :: column 4014 INTEGER(hp), DIMENSION(:,:), ALLOCATABLE :: old_soiltyp, new_soiltyp 4015 INTEGER :: l, i, j, nx, ny, n_cells, ii, jj, iter 4016 INTEGER, DIMENSION(8) :: di, dj 4017 4018 nx = SIZE(array, 1) 4019 ny = SIZE(array, 2) 4020 di = (/ -1, -1, -1, 0, 0, 1, 1, 1 /) 4021 dj = (/ -1, 0, 1, -1, 1, -1, 0, 1 /) 4022 4023 ALLOCATE(old_soiltyp(SIZE(soiltyp,1), & 4024 SIZE(soiltyp,2) )) 4025 4026 ALLOCATE(new_soiltyp(SIZE(soiltyp,1), & 4027 SIZE(soiltyp,2) )) 4028 4029 old_soiltyp(:,:) = soiltyp(:,:,1) 4030 new_soiltyp(:,:) = soiltyp(:,:,1) 4031 4032 DO iter = 1, niter 4033 4034 DO j = 1, ny 4035 DO i = 1, nx 4036 4037 IF (old_soiltyp(i,j) == WATER_ID) THEN 4038 4039 n_cells = 0 4040 column(:) = 0.0_dp 4041 DO l = 1, SIZE(di) 4042 4043 ii = MIN(nx, MAX(1, i + di(l))) 4044 jj = MIN(ny, MAX(1, j + dj(l))) 4045 4046 IF (old_soiltyp(ii,jj) .NE. WATER_ID) THEN 4047 n_cells = n_cells + 1 4048 column(:) = column(:) + array(ii,jj,:) 4049 ENDIF 4050 4051 ENDDO 4052 4053 ! 4054 !-- Overwrite if at least one non-water neighbour cell is available 4055 IF (n_cells > 0) THEN 4056 array(i,j,:) = column(:) / n_cells 4057 new_soiltyp(i,j) = 0 4022 SUBROUTINE fill_water_cells(soiltyp, array, nz, niter) 4023 INTEGER(iwp), DIMENSION(:,:,:), INTENT(IN) :: soiltyp 4024 REAL(wp), DIMENSION(:,:,:), INTENT(INOUT) :: array 4025 INTEGER, INTENT(IN) :: nz, niter 4026 4027 REAL(wp), DIMENSION(nz) :: column 4028 INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE :: old_soiltyp, new_soiltyp 4029 INTEGER :: l, i, j, nx, ny, n_cells, ii, jj, iter 4030 INTEGER, DIMENSION(8) :: di, dj 4031 4032 nx = SIZE(array, 1) 4033 ny = SIZE(array, 2) 4034 di = (/ -1, -1, -1, 0, 0, 1, 1, 1 /) 4035 dj = (/ -1, 0, 1, -1, 1, -1, 0, 1 /) 4036 4037 ALLOCATE(old_soiltyp(SIZE(soiltyp,1), & 4038 SIZE(soiltyp,2) )) 4039 4040 ALLOCATE(new_soiltyp(SIZE(soiltyp,1), & 4041 SIZE(soiltyp,2) )) 4042 4043 old_soiltyp(:,:) = soiltyp(:,:,1) 4044 new_soiltyp(:,:) = soiltyp(:,:,1) 4045 4046 DO iter = 1, niter 4047 4048 DO j = 1, ny 4049 DO i = 1, nx 4050 4051 IF (old_soiltyp(i,j) == WATER_ID) THEN 4052 4053 n_cells = 0 4054 column(:) = 0.0_wp 4055 DO l = 1, SIZE(di) 4056 4057 ii = MIN(nx, MAX(1, i + di(l))) 4058 jj = MIN(ny, MAX(1, j + dj(l))) 4059 4060 IF (old_soiltyp(ii,jj) .NE. WATER_ID) THEN 4061 n_cells = n_cells + 1 4062 column(:) = column(:) + array(ii,jj,:) 4058 4063 ENDIF 4059 4064 4065 ENDDO 4066 4067 ! 4068 !-- Overwrite if at least one non-water neighbour cell is available 4069 IF (n_cells > 0) THEN 4070 array(i,j,:) = column(:) / n_cells 4071 new_soiltyp(i,j) = 0 4060 4072 ENDIF 4061 4073 4062 ENDDO 4063 ENDDO 4064 4065 old_soiltyp(:,:) = new_soiltyp(:,:) 4074 ENDIF 4066 4075 4067 4076 ENDDO 4068 4069 DEALLOCATE(old_soiltyp, new_soiltyp) 4070 4071 END SUBROUTINE fill_water_cells 4077 ENDDO 4078 4079 old_soiltyp(:,:) = new_soiltyp(:,:) 4080 4081 ENDDO 4082 4083 DEALLOCATE(old_soiltyp, new_soiltyp) 4084 4085 END SUBROUTINE fill_water_cells 4072 4086 4073 4087 -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_io.f90 ¶
r3801 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! Improved coding style 30 ! 31 ! 32 ! 3801 2019-03-15 17:14:25Z eckhard 28 33 ! Added routine get_cosmo_grid() to read in COSMO rotated pole from COSMO domain 29 34 ! Moved get_soil_layer_thickness() here from inifor_grid … … 118 123 USE inifor_control 119 124 USE inifor_defs, & 120 ONLY: DATE, SNAME, PATH, PI, dp, hp, TO_RADIANS, TO_DEGREES, VERSION,&125 ONLY: DATE, SNAME, PATH, PI, TO_RADIANS, TO_DEGREES, VERSION, & 121 126 NC_DEPTH_NAME, NC_HHL_NAME, NC_RLAT_NAME, NC_RLON_NAME, & 122 127 NC_ROTATED_POLE_NAME, NC_POLE_LATITUDE_NAME, & 123 NC_POLE_LONGITUDE_NAME, RHO_L 128 NC_POLE_LONGITUDE_NAME, RHO_L, wp, iwp 124 129 USE inifor_types 125 130 USE inifor_util, & … … 133 138 ! ------------ 134 139 !> get_netcdf_variable() reads the netCDF data and metadate for the netCDF 135 !> variable 'in_var %name' from the file 'in_file'. The netCDF data array is140 !> variable 'in_var%name' from the file 'in_file'. The netCDF data array is 136 141 !> stored in the 'buffer' array and metadata added to the respective members of 137 142 !> the given 'in_var'. … … 152 157 !> get_netcdf_variable interface. 153 158 !------------------------------------------------------------------------------! 154 155 156 CHARACTER(LEN=PATH), INTENT(IN):: in_file157 TYPE(nc_var), INTENT(INOUT):: in_var158 INTEGER(hp), ALLOCATABLE, INTENT(INOUT) :: buffer(:,:,:)159 160 161 162 163 164 nf90_inq_varid( ncid, in_var % name, in_var %varid ) .EQ. NF90_NOERR ) THEN165 166 167 168 169 CALL run_control('time', 'read')170 171 172 CALL run_control('time', 'alloc')173 174 CALL check(nf90_get_var( ncid, in_var %varid, buffer, &175 176 177 178 179 180 message = "Failed to read '" // TRIM(in_var %name) // &181 182 183 184 185 186 187 CALL run_control('time', 'read')188 189 159 SUBROUTINE get_netcdf_variable_int(in_file, in_var, buffer) 160 161 CHARACTER(LEN=PATH), INTENT(IN) :: in_file 162 TYPE(nc_var), INTENT(INOUT) :: in_var 163 INTEGER(iwp), ALLOCATABLE, INTENT(INOUT) :: buffer(:,:,:) 164 165 INTEGER :: ncid 166 INTEGER, DIMENSION(3) :: start, count 167 168 IF ( nf90_open( TRIM(in_file), NF90_NOWRITE, ncid ) .EQ. NF90_NOERR .AND. & 169 nf90_inq_varid( ncid, in_var%name, in_var%varid ) .EQ. NF90_NOERR ) THEN 170 171 CALL get_input_dimensions(in_var, ncid) 172 173 CALL get_netcdf_start_and_count(in_var, start, count) 174 CALL log_runtime('time', 'read') 175 176 ALLOCATE( buffer( count(1), count(2), count(3) ) ) 177 CALL log_runtime('time', 'alloc') 178 179 CALL check(nf90_get_var( ncid, in_var%varid, buffer, & 180 start = start, & 181 count = count )) 182 183 ELSE 184 185 message = "Failed to read '" // TRIM(in_var%name) // & 186 "' from file '" // TRIM(in_file) // "'." 187 CALL inifor_abort('get_netcdf_variable', message) 188 189 ENDIF 190 191 CALL check(nf90_close(ncid)) 192 CALL log_runtime('time', 'read') 193 194 END SUBROUTINE get_netcdf_variable_int 190 195 191 196 … … 196 201 !> get_netcdf_variable interface. 197 202 !------------------------------------------------------------------------------! 198 199 200 201 202 REAL(dp), ALLOCATABLE, INTENT(INOUT) :: buffer(:,:,:)203 204 205 206 207 208 nf90_inq_varid( ncid, in_var % name, in_var %varid ) .EQ. NF90_NOERR ) THEN209 210 211 212 213 CALL run_control('time', 'read')214 215 216 CALL run_control('time', 'alloc')217 218 CALL check(nf90_get_var( ncid, in_var %varid, buffer, &219 220 221 222 223 224 message = "Failed to read '" // TRIM(in_var %name) // &225 226 227 228 229 230 231 CALL run_control('time', 'read')232 233 203 SUBROUTINE get_netcdf_variable_real(in_file, in_var, buffer) 204 205 CHARACTER(LEN=PATH), INTENT(IN) :: in_file 206 TYPE(nc_var), INTENT(INOUT) :: in_var 207 REAL(wp), ALLOCATABLE, INTENT(INOUT) :: buffer(:,:,:) 208 209 INTEGER :: ncid 210 INTEGER, DIMENSION(3) :: start, count 211 212 IF ( nf90_open( TRIM(in_file), NF90_NOWRITE, ncid ) .EQ. NF90_NOERR .AND. & 213 nf90_inq_varid( ncid, in_var%name, in_var%varid ) .EQ. NF90_NOERR ) THEN 214 215 CALL get_input_dimensions(in_var, ncid) 216 217 CALL get_netcdf_start_and_count(in_var, start, count) 218 CALL log_runtime('time', 'read') 219 220 ALLOCATE( buffer( count(1), count(2), count(3) ) ) 221 CALL log_runtime('time', 'alloc') 222 223 CALL check(nf90_get_var( ncid, in_var%varid, buffer, & 224 start = start, & 225 count = count )) 226 227 ELSE 228 229 message = "Failed to read '" // TRIM(in_var%name) // & 230 "' from file '" // TRIM(in_file) // "'." 231 CALL inifor_abort('get_netcdf_variable', message) 232 233 ENDIF 234 235 CALL check(nf90_close(ncid)) 236 CALL log_runtime('time', 'read') 237 238 END SUBROUTINE get_netcdf_variable_real 234 239 235 240 … … 240 245 !> netCDF file 'filename'. 241 246 !------------------------------------------------------------------------------! 242 243 244 245 246 REAL(dp), ALLOCATABLE, INTENT(INOUT) :: coords(:)247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 247 SUBROUTINE get_netcdf_dim_vector(filename, coordname, coords) 248 249 CHARACTER(LEN=*), INTENT(IN) :: filename 250 CHARACTER(LEN=*), INTENT(IN) :: coordname 251 REAL(wp), ALLOCATABLE, INTENT(INOUT) :: coords(:) 252 253 INTEGER :: ncid, varid, dimlen 254 INTEGER :: dimids(NF90_MAX_VAR_DIMS) 255 256 IF ( nf90_open( TRIM(filename), NF90_NOWRITE, ncid ) .EQ. NF90_NOERR .AND. & 257 nf90_inq_varid( ncid, coordname, varid ) .EQ. NF90_NOERR ) THEN 258 259 CALL check(nf90_inquire_variable( ncid, varid, dimids = dimids )) 260 CALL check(nf90_inquire_dimension( ncid, dimids(1), len = dimlen )) 261 262 ALLOCATE(coords(dimlen)) 263 CALL check(nf90_get_var( ncid, varid, coords)) 264 265 ELSE 266 267 message = "Failed to read '" // TRIM(coordname) // & 268 "' from file '" // TRIM(filename) // "'." 269 CALL inifor_abort('get_netcdf_dim_vector', message) 270 271 ENDIF 272 273 END SUBROUTINE get_netcdf_dim_vector 269 274 270 275 … … 273 278 ! ------------ 274 279 !> get_input_dimensions() reads dimensions metadata of the netCDF variable given 275 !> by 'in_var %name' into 'in_var' data structure.276 !------------------------------------------------------------------------------! 277 278 279 280 281 282 283 284 CALL check(nf90_get_att( ncid, in_var %varid, "long_name", &285 in_var %long_name))286 287 CALL check(nf90_get_att( ncid, in_var %varid, "units", &288 in_var %units ))289 290 CALL check(nf90_inquire_variable( ncid, in_var %varid, &291 ndims = in_var %ndim, &292 dimids = in_var %dimids ))293 294 DO i = 1, in_var %ndim295 CALL check(nf90_inquire_dimension( ncid, in_var %dimids(i), &296 name = in_var %dimname(i), &297 len = in_var %dimlen(i) ))298 299 300 280 !> by 'in_var%name' into 'in_var' data structure. 281 !------------------------------------------------------------------------------! 282 SUBROUTINE get_input_dimensions(in_var, ncid) 283 284 TYPE(nc_var), INTENT(INOUT) :: in_var 285 INTEGER, INTENT(IN) :: ncid 286 287 INTEGER :: i 288 289 CALL check(nf90_get_att( ncid, in_var%varid, "long_name", & 290 in_var%long_name)) 291 292 CALL check(nf90_get_att( ncid, in_var%varid, "units", & 293 in_var%units )) 294 295 CALL check(nf90_inquire_variable( ncid, in_var%varid, & 296 ndims = in_var%ndim, & 297 dimids = in_var%dimids )) 298 299 DO i = 1, in_var%ndim 300 CALL check(nf90_inquire_dimension( ncid, in_var%dimids(i), & 301 name = in_var%dimname(i), & 302 len = in_var%dimlen(i) )) 303 ENDDO 304 305 END SUBROUTINE get_input_dimensions 301 306 302 307 … … 308 313 !> and _real() for reading input variables.. 309 314 !------------------------------------------------------------------------------! 310 311 312 313 314 315 316 317 IF ( in_var % ndim .LT. 2 .OR. in_var %ndim .GT. 4 ) THEN318 319 320 TRIM(in_var % name) // " with " // TRIM(str(in_var %ndim)) // &321 322 323 324 325 326 327 328 IF ( TRIM(in_var %name) .EQ. 'T_SO' ) THEN329 ! 330 !-- 331 in_var % dimlen(3) = in_var %dimlen(3) - 1332 333 ! 334 !-- 335 336 337 338 IF (in_var %ndim .EQ. 2) THEN339 in_var %dimlen(3) = 1340 341 342 ndim = MIN(in_var %ndim, 3)343 344 count(1:ndim) = in_var %dimlen(1:ndim)345 346 315 SUBROUTINE get_netcdf_start_and_count(in_var, start, count) 316 317 TYPE(nc_var), INTENT(INOUT) :: in_var 318 INTEGER, DIMENSION(3), INTENT(OUT) :: start, count 319 320 INTEGER :: ndim 321 322 IF ( in_var%ndim .LT. 2 .OR. in_var%ndim .GT. 4 ) THEN 323 324 message = "Failed reading NetCDF variable " // & 325 TRIM(in_var%name) // " with " // TRIM(str(in_var%ndim)) // & 326 " dimensions because only two- and and three-dimensional" // & 327 " variables are supported." 328 CALL inifor_abort('get_netcdf_start_and_count', message) 329 330 ENDIF 331 332 start = (/ 1, 1, 1 /) 333 IF ( TRIM(in_var%name) .EQ. 'T_SO' ) THEN 334 ! 335 !-- Skip depth = 0.0 for T_SO and reduce number of depths from 9 to 8 336 in_var%dimlen(3) = in_var%dimlen(3) - 1 337 338 ! 339 !-- Start reading from second level, e.g. depth = 0.005 instead of 0.0 340 start(3) = 2 341 ENDIF 342 343 IF (in_var%ndim .EQ. 2) THEN 344 in_var%dimlen(3) = 1 345 ENDIF 346 347 ndim = MIN(in_var%ndim, 3) 348 count = (/ 1, 1, 1 /) 349 count(1:ndim) = in_var%dimlen(1:ndim) 350 351 END SUBROUTINE get_netcdf_start_and_count 347 352 348 353 … … 353 358 !> output. 354 359 !------------------------------------------------------------------------------! 355 356 357 358 359 360 CALL check(nf90_def_var(ncid, var % name, NF90_FLOAT, var % dimids(1:var % ndim), var %varid))361 CALL check(nf90_put_att(ncid, var % varid, "long_name", var %long_name))362 CALL check(nf90_put_att(ncid, var % varid, "units", var %units))363 IF ( var %lod .GE. 0 ) THEN364 CALL check(nf90_put_att(ncid, var % varid, "lod", var %lod))365 366 CALL check(nf90_put_att(ncid, var % varid, "source", var %source))367 CALL check(nf90_put_att(ncid, var %varid, "_FillValue", NF90_FILL_REAL))368 369 360 SUBROUTINE netcdf_define_variable(var, ncid) 361 362 TYPE(nc_var), INTENT(INOUT) :: var 363 INTEGER, INTENT(IN) :: ncid 364 365 CALL check(nf90_def_var(ncid, var%name, NF90_FLOAT, var%dimids(1:var%ndim), var%varid)) 366 CALL check(nf90_put_att(ncid, var%varid, "long_name", var%long_name)) 367 CALL check(nf90_put_att(ncid, var%varid, "units", var%units)) 368 IF ( var%lod .GE. 0 ) THEN 369 CALL check(nf90_put_att(ncid, var%varid, "lod", var%lod)) 370 ENDIF 371 CALL check(nf90_put_att(ncid, var%varid, "source", var%source)) 372 CALL check(nf90_put_att(ncid, var%varid, "_FillValue", NF90_FILL_REAL)) 373 374 END SUBROUTINE netcdf_define_variable 370 375 371 376 … … 377 382 !> for writing output variables in update_output(). 378 383 !------------------------------------------------------------------------------! 379 380 381 382 383 384 385 386 DO i = 1, var %ndim387 CALL check(nf90_inquire_dimension(ncid, var %dimids(i), &388 389 len = var %dimlen(i) ) )390 391 392 384 SUBROUTINE netcdf_get_dimensions(var, ncid) 385 386 TYPE(nc_var), INTENT(INOUT) :: var 387 INTEGER, INTENT(IN) :: ncid 388 INTEGER :: i 389 CHARACTER(SNAME) :: null 390 391 DO i = 1, var%ndim 392 CALL check(nf90_inquire_dimension(ncid, var%dimids(i), & 393 name = null, & 394 len = var%dimlen(i) ) ) 395 ENDDO 396 397 END SUBROUTINE netcdf_get_dimensions 393 398 394 399 … … 399 404 !> resulting settings in the 'cfg' data structure. 400 405 !------------------------------------------------------------------------------! 401 402 403 404 405 406 407 408 cfg %p0_is_set = .FALSE.409 cfg %ug_defined_by_user = .FALSE.410 cfg %vg_defined_by_user = .FALSE.411 cfg %flow_prefix_is_set = .FALSE.412 cfg %input_prefix_is_set = .FALSE.413 cfg %radiation_prefix_is_set = .FALSE.414 cfg %soil_prefix_is_set = .FALSE.415 cfg %soilmoisture_prefix_is_set = .FALSE.416 417 418 419 420 421 422 423 424 425 426 427 DOWHILE (i .LE. arg_count)428 429 430 431 406 SUBROUTINE parse_command_line_arguments( cfg ) 407 408 TYPE(inifor_config), INTENT(INOUT) :: cfg 409 410 CHARACTER(LEN=PATH) :: option, arg 411 INTEGER :: arg_count, i 412 413 cfg%p0_is_set = .FALSE. 414 cfg%ug_defined_by_user = .FALSE. 415 cfg%vg_defined_by_user = .FALSE. 416 cfg%flow_prefix_is_set = .FALSE. 417 cfg%input_prefix_is_set = .FALSE. 418 cfg%radiation_prefix_is_set = .FALSE. 419 cfg%soil_prefix_is_set = .FALSE. 420 cfg%soilmoisture_prefix_is_set = .FALSE. 421 422 arg_count = COMMAND_ARGUMENT_COUNT() 423 IF (arg_count .GT. 0) THEN 424 425 message = "The -clon and -clat command line options are depricated. " // & 426 "Please remove them form your inifor command and specify the " // & 427 "location of the PALM-4U origin either" // NEW_LINE(' ') // & 428 " - by setting the namelist parameters 'longitude' and 'latitude', or" // NEW_LINE(' ') // & 429 " - by providing a static driver netCDF file via the -static command-line option." 430 431 i = 1 432 DO WHILE (i .LE. arg_count) 433 434 CALL GET_COMMAND_ARGUMENT( i, option ) 435 436 SELECT CASE( TRIM(option) ) 432 437 433 438 CASE( '--averaging-mode' ) 434 439 CALL get_option_argument( i, arg ) 435 cfg %averaging_mode = TRIM(arg)440 cfg%averaging_mode = TRIM(arg) 436 441 437 442 CASE( '-date', '-d', '--date' ) 438 443 CALL get_option_argument( i, arg ) 439 cfg %start_date = TRIM(arg)444 cfg%start_date = TRIM(arg) 440 445 441 446 CASE( '--debug' ) 442 cfg %debug = .TRUE.447 cfg%debug = .TRUE. 443 448 444 449 CASE( '-z0', '-z', '--elevation' ) 445 450 CALL get_option_argument( i, arg ) 446 READ(arg, *) cfg %z0451 READ(arg, *) cfg%z0 447 452 448 453 CASE( '-p0', '-r', '--surface-pressure' ) 449 cfg %p0_is_set = .TRUE.450 CALL get_option_argument( i, arg ) 451 READ(arg, *) cfg %p0454 cfg%p0_is_set = .TRUE. 455 CALL get_option_argument( i, arg ) 456 READ(arg, *) cfg%p0 452 457 453 458 CASE( '-ug', '-u', '--geostrophic-u' ) 454 cfg %ug_defined_by_user = .TRUE.455 CALL get_option_argument( i, arg ) 456 READ(arg, *) cfg %ug459 cfg%ug_defined_by_user = .TRUE. 460 CALL get_option_argument( i, arg ) 461 READ(arg, *) cfg%ug 457 462 458 463 CASE( '-vg', '-v', '--geostrophic-v' ) 459 cfg %vg_defined_by_user = .TRUE.460 CALL get_option_argument( i, arg ) 461 READ(arg, *) cfg %vg464 cfg%vg_defined_by_user = .TRUE. 465 CALL get_option_argument( i, arg ) 466 READ(arg, *) cfg%vg 462 467 463 468 CASE( '-clon', '-clat' ) … … 466 471 CASE( '-path', '-p', '--path' ) 467 472 CALL get_option_argument( i, arg ) 468 cfg %input_path = TRIM(arg)473 cfg%input_path = TRIM(arg) 469 474 470 475 CASE( '-hhl', '-l', '--hhl-file' ) 471 476 CALL get_option_argument( i, arg ) 472 cfg %hhl_file = TRIM(arg)477 cfg%hhl_file = TRIM(arg) 473 478 474 479 CASE( '--input-prefix') 475 480 CALL get_option_argument( i, arg ) 476 cfg %input_prefix = TRIM(arg)477 cfg %input_prefix_is_set = .TRUE.481 cfg%input_prefix = TRIM(arg) 482 cfg%input_prefix_is_set = .TRUE. 478 483 479 484 CASE( '-a', '--averaging-angle' ) 480 485 CALL get_option_argument( i, arg ) 481 READ(arg, *) cfg %averaging_angle486 READ(arg, *) cfg%averaging_angle 482 487 483 488 CASE( '-static', '-t', '--static-driver' ) 484 489 CALL get_option_argument( i, arg ) 485 cfg %static_driver_file = TRIM(arg)490 cfg%static_driver_file = TRIM(arg) 486 491 487 492 CASE( '-soil', '-s', '--soil-file') 488 493 CALL get_option_argument( i, arg ) 489 cfg %soiltyp_file = TRIM(arg)494 cfg%soiltyp_file = TRIM(arg) 490 495 491 496 CASE( '--flow-prefix') 492 497 CALL get_option_argument( i, arg ) 493 cfg %flow_prefix = TRIM(arg)494 cfg %flow_prefix_is_set = .TRUE.498 cfg%flow_prefix = TRIM(arg) 499 cfg%flow_prefix_is_set = .TRUE. 495 500 496 501 CASE( '--radiation-prefix') 497 502 CALL get_option_argument( i, arg ) 498 cfg %radiation_prefix = TRIM(arg)499 cfg %radiation_prefix_is_set = .TRUE.503 cfg%radiation_prefix = TRIM(arg) 504 cfg%radiation_prefix_is_set = .TRUE. 500 505 501 506 CASE( '--soil-prefix') 502 507 CALL get_option_argument( i, arg ) 503 cfg %soil_prefix = TRIM(arg)504 cfg %soil_prefix_is_set = .TRUE.508 cfg%soil_prefix = TRIM(arg) 509 cfg%soil_prefix_is_set = .TRUE. 505 510 506 511 CASE( '--soilmoisture-prefix') 507 512 CALL get_option_argument( i, arg ) 508 cfg %soilmoisture_prefix = TRIM(arg)509 cfg %soilmoisture_prefix_is_set = .TRUE.513 cfg%soilmoisture_prefix = TRIM(arg) 514 cfg%soilmoisture_prefix_is_set = .TRUE. 510 515 511 516 CASE( '-o', '--output' ) 512 517 CALL get_option_argument( i, arg ) 513 cfg %output_file = TRIM(arg)518 cfg%output_file = TRIM(arg) 514 519 515 520 CASE( '-n', '--namelist' ) 516 521 CALL get_option_argument( i, arg ) 517 cfg %namelist_file = TRIM(arg)522 cfg%namelist_file = TRIM(arg) 518 523 519 524 CASE( '-mode', '-i', '--init-mode' ) 520 525 CALL get_option_argument( i, arg ) 521 cfg %ic_mode = TRIM(arg)526 cfg%ic_mode = TRIM(arg) 522 527 523 528 CASE( '-f', '--forcing-mode' ) 524 529 CALL get_option_argument( i, arg ) 525 cfg %bc_mode = TRIM(arg)530 cfg%bc_mode = TRIM(arg) 526 531 527 532 CASE( '--version' ) 528 CALL print_version ()533 CALL print_version 529 534 STOP 530 535 531 536 CASE( '--help' ) 532 CALL print_version ()537 CALL print_version 533 538 PRINT *, "" 534 539 PRINT *, "For a list of command-line options have a look at the README file." … … 539 544 CALL inifor_abort('parse_command_line_arguments', message) 540 545 541 542 543 544 545 546 547 548 549 550 551 552 553 554 546 END SELECT 547 548 i = i + 1 549 550 ENDDO 551 552 ELSE 553 554 message = "No arguments present, using default input and output files" 555 CALL report('parse_command_line_arguments', message) 556 557 ENDIF 558 559 END SUBROUTINE parse_command_line_arguments 555 560 556 561 557 562 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 DOi = 0, number_of_intervals574 575 576 577 578 579 580 581 582 583 563 SUBROUTINE get_datetime_file_list( start_date_string, start_hour, end_hour, & 564 step_hour, input_path, prefix, suffix, & 565 file_list ) 566 567 CHARACTER (LEN=DATE), INTENT(IN) :: start_date_string 568 CHARACTER (LEN=*), INTENT(IN) :: prefix, suffix, input_path 569 INTEGER, INTENT(IN) :: start_hour, end_hour, step_hour 570 CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: file_list(:) 571 572 INTEGER :: number_of_intervals, hour, i 573 CHARACTER(LEN=DATE) :: date_string 574 575 number_of_intervals = CEILING( REAL(end_hour - start_hour) / step_hour ) 576 ALLOCATE( file_list(number_of_intervals + 1) ) 577 578 DO i = 0, number_of_intervals 579 580 hour = start_hour + i * step_hour 581 date_string = add_hours_to(start_date_string, hour) 582 583 file_list(i+1) = TRIM(input_path) // TRIM(prefix) // & 584 TRIM(date_string) // TRIM(suffix) // '.nc' 585 586 ENDDO 587 588 END SUBROUTINE get_datetime_file_list 584 589 585 590 !------------------------------------------------------------------------------! … … 589 594 !> prefixes and suffixes. 590 595 !------------------------------------------------------------------------------! 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 DOi = 1, SIZE(file_list)619 620 621 622 623 624 596 SUBROUTINE get_input_file_list( start_date_string, start_hour, end_hour, & 597 step_hour, input_path, prefix, suffix, & 598 file_list, nocheck ) 599 600 CHARACTER (LEN=DATE), INTENT(IN) :: start_date_string 601 CHARACTER (LEN=*), INTENT(IN) :: prefix, suffix, input_path 602 INTEGER, INTENT(IN) :: start_hour, end_hour, step_hour 603 CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: file_list(:) 604 LOGICAL, OPTIONAL, INTENT(IN) :: nocheck 605 606 INTEGER :: i 607 LOGICAL :: check_files 608 609 CALL get_datetime_file_list( start_date_string, start_hour, end_hour, & 610 step_hour, input_path, prefix, suffix, & 611 file_list ) 612 613 check_files = .TRUE. 614 IF ( PRESENT ( nocheck ) ) THEN 615 IF ( nocheck ) check_files = .FALSE. 616 ENDIF 617 618 IF ( check_files ) THEN 619 620 tip = "Please check if you specified the correct file prefix " // & 621 "using the options --input-prefix, --flow-prefix, etc." 622 623 DO i = 1, SIZE(file_list) 624 CALL verify_file(file_list(i), 'input', tip) 625 ENDDO 626 627 ENDIF 628 629 END SUBROUTINE get_input_file_list 625 630 626 631 … … 630 635 !> Abort INIFOR if the given file is not present. 631 636 !------------------------------------------------------------------------------! 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 637 SUBROUTINE verify_file(file_name, file_kind, tip) 638 639 CHARACTER(LEN=*), INTENT(IN) :: file_name, file_kind 640 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: tip 641 642 IF (.NOT. file_present(file_name)) THEN 643 644 IF (LEN(TRIM(file_name)) == 0) THEN 645 646 message = "No name was given for the " // TRIM(file_kind) // " file." 647 648 ELSE 649 650 message = "The " // TRIM(file_kind) // " file '" // & 651 TRIM(file_name) // "' was not found." 652 653 IF (PRESENT(tip)) THEN 654 message = TRIM(message) // " " // TRIM(tip) 655 ENDIF 656 657 ENDIF 658 659 CALL inifor_abort('verify_file', message) 660 661 ENDIF 662 663 message = "Set up input file name '" // TRIM(file_name) // "'" 664 CALL report('verify_file', message) 665 666 END SUBROUTINE verify_file 662 667 663 668 … … 668 673 !> i+1 of the argument list. 669 674 !------------------------------------------------------------------------------! 670 671 672 673 674 675 676 677 675 SUBROUTINE get_option_argument(i, arg) 676 CHARACTER(LEN=PATH), INTENT(INOUT) :: arg 677 INTEGER, INTENT(INOUT) :: i 678 679 i = i + 1 680 CALL GET_COMMAND_ARGUMENT(i, arg) 681 682 END SUBROUTINE 678 683 679 684 … … 683 688 !> Checks the INIFOR configuration 'cfg' for plausibility. 684 689 !------------------------------------------------------------------------------! 685 SUBROUTINE validate_config(cfg) 686 TYPE(inifor_config), INTENT(IN) :: cfg 687 688 CALL verify_file(cfg % hhl_file, 'HHL') 689 CALL verify_file(cfg % namelist_file, 'NAMELIST') 690 CALL verify_file(cfg % soiltyp_file, 'SOILTYP') 691 692 ! 693 !-- Only check optional static driver file name, if it has been given. 694 IF (TRIM(cfg % static_driver_file) .NE. '') THEN 695 CALL verify_file(cfg % static_driver_file, 'static driver') 696 ENDIF 697 698 SELECT CASE( TRIM(cfg % ic_mode) ) 699 CASE( 'profile', 'volume') 700 CASE DEFAULT 701 message = "Initialization mode '" // TRIM(cfg % ic_mode) //& 702 "' is not supported. " //& 703 "Please select either 'profile' or 'volume', " //& 704 "or omit the -i/--init-mode/-mode option entirely, which corresponds "//& 705 "to the latter." 706 CALL inifor_abort( 'validate_config', message ) 707 END SELECT 708 709 710 SELECT CASE( TRIM(cfg % bc_mode) ) 711 CASE( 'real', 'ideal') 712 CASE DEFAULT 713 message = "Forcing mode '" // TRIM(cfg % bc_mode) //& 714 "' is not supported. " //& 715 "Please select either 'real' or 'ideal', " //& 716 "or omit the -f/--forcing-mode option entirely, which corresponds "//& 717 "to the latter." 718 CALL inifor_abort( 'validate_config', message ) 719 END SELECT 720 721 SELECT CASE( TRIM(cfg % averaging_mode) ) 722 CASE( 'level' ) 723 CASE( 'height' ) 724 message = "Averaging mode '" // TRIM(cfg % averaging_mode) //& 725 "' is currently not supported. " //& 726 "Please use level-based averaging by selecting 'level', " //& 727 "or by omitting the --averaging-mode option entirely." 728 CALL inifor_abort( 'validate_config', message ) 729 CASE DEFAULT 730 message = "Averaging mode '" // TRIM(cfg % averaging_mode) //& 731 "' is not supported. " //& 732 ! "Please select either 'height' or 'level', " //& 733 ! "or omit the --averaging-mode option entirely, which corresponds "//& 734 ! "to the latter." 735 "Please use level-based averaging by selecting 'level', " //& 736 "or by omitting the --averaging-mode option entirely." 737 CALL inifor_abort( 'validate_config', message ) 738 END SELECT 739 740 IF ( cfg % ug_defined_by_user .NEQV. cfg % vg_defined_by_user ) THEN 741 message = "You specified only one component of the geostrophic " // & 742 "wind. Please specify either both or none." 743 CALL inifor_abort( 'validate_config', message ) 744 ENDIF 745 746 END SUBROUTINE validate_config 747 748 749 SUBROUTINE get_cosmo_grid( cfg, soil_file, rlon, rlat, hhl, hfl, depths, & 750 d_depth, d_depth_rho_inv, phi_n, lambda_n, & 751 phi_equat, & 752 lonmin_cosmo, lonmax_cosmo, & 753 latmin_cosmo, latmax_cosmo, & 754 nlon, nlat, nlev, ndepths ) 755 756 TYPE(inifor_config), INTENT(IN) :: cfg 757 CHARACTER(LEN=PATH), INTENT(IN) :: soil_file !< list of soil input files (temperature, moisture, <prefix>YYYYMMDDHH-soil.nc) 758 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: rlon !< longitudes of COSMO-DE's rotated-pole grid 759 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: rlat !< latitudes of COSMO-DE's rotated-pole grid 760 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE, INTENT(OUT) :: hhl !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from external file 761 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE, INTENT(OUT) :: hfl !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl 762 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: depths !< COSMO-DE's TERRA-ML soil layer depths 763 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: d_depth 764 REAL(dp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: d_depth_rho_inv 765 REAL(dp), INTENT(OUT) :: phi_n 766 REAL(dp), INTENT(OUT) :: phi_equat 767 REAL(dp), INTENT(OUT) :: lambda_n 768 REAL(dp), INTENT(OUT) :: lonmin_cosmo !< Minimunm longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 769 REAL(dp), INTENT(OUT) :: lonmax_cosmo !< Maximum longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 770 REAL(dp), INTENT(OUT) :: latmin_cosmo !< Minimunm latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 771 REAL(dp), INTENT(OUT) :: latmax_cosmo !< Maximum latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 772 INTEGER, INTENt(OUT) :: nlon, nlat, nlev, ndepths 773 774 TYPE(nc_var) :: cosmo_var !< COSMO dummy variable, used for reading HHL, rlon, rlat 775 INTEGER :: k 776 777 ! 778 !-- Read in COSMO's heights of half layers (vertical cell faces) 779 cosmo_var % name = NC_HHL_NAME 780 CALL get_netcdf_variable( cfg % hhl_file, cosmo_var, hhl ) 781 CALL get_netcdf_dim_vector( cfg % hhl_file, NC_RLON_NAME, rlon ) 782 CALL get_netcdf_dim_vector( cfg % hhl_file, NC_RLAT_NAME, rlat ) 783 CALL get_netcdf_dim_vector( soil_file, NC_DEPTH_NAME, depths) 784 CALL run_control( 'time', 'read' ) 785 786 CALL reverse( hhl ) 787 nlon = SIZE( hhl, 1 ) 788 nlat = SIZE( hhl, 2 ) 789 nlev = SIZE( hhl, 3 ) 790 ndepths = SIZE( depths ) 791 792 CALL run_control( 'time', 'comp' ) 793 794 ALLOCATE( hfl( nlon, nlat, nlev-1 ) ) 795 ALLOCATE( d_depth( ndepths ), d_depth_rho_inv( ndepths ) ) 796 CALL run_control('time', 'alloc') 797 798 CALL get_soil_layer_thickness( depths, d_depth ) 799 d_depth_rho_inv = 1.0_dp / ( d_depth * RHO_L ) 800 801 ! 802 !-- Compute COSMO's heights of full layers (cell centres) 803 DO k = 1, nlev-1 804 hfl(:,:,k) = 0.5_dp * ( hhl(:,:,k) + & 805 hhl(:,:,k+1) ) 806 ENDDO 807 ! 808 !-- COSMO rotated pole coordinates 809 phi_n = TO_RADIANS & 810 * get_netcdf_variable_attribute( cfg % hhl_file, & 811 NC_ROTATED_POLE_NAME, & 812 NC_POLE_LATITUDE_NAME ) 813 814 lambda_n = TO_RADIANS & 815 * get_netcdf_variable_attribute( cfg % hhl_file, & 816 NC_ROTATED_POLE_NAME, & 817 NC_POLE_LONGITUDE_NAME ) 818 819 phi_equat = 90.0_dp * TO_RADIANS - phi_n 820 821 lonmin_cosmo = MINVAL( rlon ) * TO_RADIANS 822 lonmax_cosmo = MAXVAL( rlon ) * TO_RADIANS 823 latmin_cosmo = MINVAL( rlat ) * TO_RADIANS 824 latmax_cosmo = MAXVAL( rlat ) * TO_RADIANS 825 CALL run_control('time', 'comp') 826 827 END SUBROUTINE get_cosmo_grid 690 SUBROUTINE validate_config(cfg) 691 TYPE(inifor_config), INTENT(IN) :: cfg 692 693 CALL verify_file(cfg%hhl_file, 'HHL') 694 CALL verify_file(cfg%namelist_file, 'NAMELIST') 695 CALL verify_file(cfg%soiltyp_file, 'SOILTYP') 696 697 ! 698 !-- Only check optional static driver file name, if it has been given. 699 IF (TRIM(cfg%static_driver_file) .NE. '') THEN 700 CALL verify_file(cfg%static_driver_file, 'static driver') 701 ENDIF 702 703 SELECT CASE( TRIM(cfg%ic_mode) ) 704 CASE( 'profile', 'volume') 705 CASE DEFAULT 706 message = "Initialization mode '" // TRIM(cfg%ic_mode) //& 707 "' is not supported. " //& 708 "Please select either 'profile' or 'volume', " //& 709 "or omit the -i/--init-mode/-mode option entirely, which corresponds "//& 710 "to the latter." 711 CALL inifor_abort( 'validate_config', message ) 712 END SELECT 713 714 SELECT CASE( TRIM(cfg%bc_mode) ) 715 CASE( 'real', 'ideal') 716 CASE DEFAULT 717 message = "Forcing mode '" // TRIM(cfg%bc_mode) //& 718 "' is not supported. " //& 719 "Please select either 'real' or 'ideal', " //& 720 "or omit the -f/--forcing-mode option entirely, which corresponds "//& 721 "to the latter." 722 CALL inifor_abort( 'validate_config', message ) 723 END SELECT 724 725 SELECT CASE( TRIM(cfg%averaging_mode) ) 726 CASE( 'level' ) 727 CASE( 'height' ) 728 message = "Averaging mode '" // TRIM(cfg%averaging_mode) //& 729 "' is currently not supported. " //& 730 "Please use level-based averaging by selecting 'level', " //& 731 "or by omitting the --averaging-mode option entirely." 732 CALL inifor_abort( 'validate_config', message ) 733 CASE DEFAULT 734 message = "Averaging mode '" // TRIM(cfg%averaging_mode) //& 735 "' is not supported. " //& 736 ! "Please select either 'height' or 'level', " //& 737 ! "or omit the --averaging-mode option entirely, which corresponds "//& 738 ! "to the latter." 739 "Please use level-based averaging by selecting 'level', " //& 740 "or by omitting the --averaging-mode option entirely." 741 CALL inifor_abort( 'validate_config', message ) 742 END SELECT 743 744 IF ( cfg%ug_defined_by_user .NEQV. cfg%vg_defined_by_user ) THEN 745 message = "You specified only one component of the geostrophic " // & 746 "wind. Please specify either both or none." 747 CALL inifor_abort( 'validate_config', message ) 748 ENDIF 749 750 END SUBROUTINE validate_config 751 752 753 SUBROUTINE get_cosmo_grid( cfg, soil_file, rlon, rlat, hhl, hfl, depths, & 754 d_depth, d_depth_rho_inv, phi_n, lambda_n, & 755 phi_equat, & 756 lonmin_cosmo, lonmax_cosmo, & 757 latmin_cosmo, latmax_cosmo, & 758 nlon, nlat, nlev, ndepths ) 759 760 TYPE(inifor_config), INTENT(IN) :: cfg 761 CHARACTER(LEN=PATH), INTENT(IN) :: soil_file !< list of soil input files (temperature, moisture, <prefix>YYYYMMDDHH-soil.nc) 762 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: rlon !< longitudes of COSMO-DE's rotated-pole grid 763 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: rlat !< latitudes of COSMO-DE's rotated-pole grid 764 REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, INTENT(OUT) :: hhl !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from external file 765 REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, INTENT(OUT) :: hfl !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl 766 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: depths !< COSMO-DE's TERRA-ML soil layer depths 767 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: d_depth 768 REAL(wp), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: d_depth_rho_inv 769 REAL(wp), INTENT(OUT) :: phi_n 770 REAL(wp), INTENT(OUT) :: phi_equat 771 REAL(wp), INTENT(OUT) :: lambda_n 772 REAL(wp), INTENT(OUT) :: lonmin_cosmo !< Minimunm longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 773 REAL(wp), INTENT(OUT) :: lonmax_cosmo !< Maximum longitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 774 REAL(wp), INTENT(OUT) :: latmin_cosmo !< Minimunm latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 775 REAL(wp), INTENT(OUT) :: latmax_cosmo !< Maximum latitude of COSMO-DE's rotated-pole grid [COSMO rotated-pole rad] 776 INTEGER, INTENt(OUT) :: nlon, nlat, nlev, ndepths 777 778 TYPE(nc_var) :: cosmo_var !< COSMO dummy variable, used for reading HHL, rlon, rlat 779 INTEGER :: k 780 781 ! 782 !-- Read in COSMO's heights of half layers (vertical cell faces) 783 cosmo_var%name = NC_HHL_NAME 784 CALL get_netcdf_variable( cfg%hhl_file, cosmo_var, hhl ) 785 CALL get_netcdf_dim_vector( cfg%hhl_file, NC_RLON_NAME, rlon ) 786 CALL get_netcdf_dim_vector( cfg%hhl_file, NC_RLAT_NAME, rlat ) 787 CALL get_netcdf_dim_vector( soil_file, NC_DEPTH_NAME, depths) 788 CALL log_runtime( 'time', 'read' ) 789 790 CALL reverse( hhl ) 791 nlon = SIZE( hhl, 1 ) 792 nlat = SIZE( hhl, 2 ) 793 nlev = SIZE( hhl, 3 ) 794 ndepths = SIZE( depths ) 795 796 CALL log_runtime( 'time', 'comp' ) 797 798 ALLOCATE( hfl( nlon, nlat, nlev-1 ) ) 799 ALLOCATE( d_depth( ndepths ), d_depth_rho_inv( ndepths ) ) 800 CALL log_runtime('time', 'alloc') 801 802 CALL get_soil_layer_thickness( depths, d_depth ) 803 d_depth_rho_inv = 1.0_wp / ( d_depth * RHO_L ) 804 805 ! 806 !-- Compute COSMO's heights of full layers (cell centres) 807 DO k = 1, nlev-1 808 hfl(:,:,k) = 0.5_wp * ( hhl(:,:,k) + & 809 hhl(:,:,k+1) ) 810 ENDDO 811 ! 812 !-- COSMO rotated pole coordinates 813 phi_n = TO_RADIANS & 814 * get_netcdf_variable_attribute( cfg%hhl_file, & 815 NC_ROTATED_POLE_NAME, & 816 NC_POLE_LATITUDE_NAME ) 817 818 lambda_n = TO_RADIANS & 819 * get_netcdf_variable_attribute( cfg%hhl_file, & 820 NC_ROTATED_POLE_NAME, & 821 NC_POLE_LONGITUDE_NAME ) 822 823 phi_equat = 90.0_wp * TO_RADIANS - phi_n 824 825 lonmin_cosmo = MINVAL( rlon ) * TO_RADIANS 826 lonmax_cosmo = MAXVAL( rlon ) * TO_RADIANS 827 latmin_cosmo = MINVAL( rlat ) * TO_RADIANS 828 latmax_cosmo = MAXVAL( rlat ) * TO_RADIANS 829 CALL log_runtime('time', 'comp') 830 831 END SUBROUTINE get_cosmo_grid 828 832 829 833 … … 856 860 !> 857 861 !------------------------------------------------------------------------------! 858 859 860 REAL(dp), INTENT(IN) :: depths(:)861 REAL(dp), INTENT(OUT) :: d_depth(:)862 863 864 d_depth(1) = 2.0_dp * depths(1)865 866 862 SUBROUTINE get_soil_layer_thickness(depths, d_depth) 863 864 REAL(wp), INTENT(IN) :: depths(:) 865 REAL(wp), INTENT(OUT) :: d_depth(:) 866 867 d_depth(:) = depths(:) 868 d_depth(1) = 2.0_wp * depths(1) 869 870 END SUBROUTINE get_soil_layer_thickness 867 871 !------------------------------------------------------------------------------! 868 872 ! Description: … … 870 874 !> Check whether the given file is present on the filesystem. 871 875 !------------------------------------------------------------------------------! 872 873 874 875 876 877 876 LOGICAL FUNCTION file_present(filename) 877 CHARACTER(LEN=PATH), INTENT(IN) :: filename 878 879 INQUIRE(FILE=filename, EXIST=file_present) 880 881 END FUNCTION file_present 878 882 879 883 … … 888 892 !> writes the actual data. 889 893 !------------------------------------------------------------------------------! 890 SUBROUTINE setup_netcdf_dimensions(output_file, palm_grid, &891 start_date_string, origin_lon, origin_lat)892 893 894 895 896 REAL(dp), INTENT(IN) :: origin_lon, origin_lat897 898 899 900 901 902 903 REAL(dp) :: z0904 905 906 TRIM(output_file %name) // "' and setting up dimensions."907 908 909 ! 910 !-- 894 SUBROUTINE setup_netcdf_dimensions( output_file, palm_grid, & 895 start_date_string, origin_lon, origin_lat ) 896 897 TYPE(nc_file), INTENT(INOUT) :: output_file 898 TYPE(grid_definition), INTENT(IN) :: palm_grid 899 CHARACTER (LEN=DATE), INTENT(IN) :: start_date_string 900 REAL(wp), INTENT(IN) :: origin_lon, origin_lat 901 902 CHARACTER (LEN=8) :: date_string 903 CHARACTER (LEN=10) :: time_string 904 CHARACTER (LEN=5) :: zone_string 905 CHARACTER (LEN=SNAME) :: history_string 906 INTEGER :: ncid, nx, ny, nz, nt, dimids(3), dimvarids(3) 907 REAL(wp) :: z0 908 909 message = "Initializing PALM-4U dynamic driver file '" // & 910 TRIM(output_file%name) // "' and setting up dimensions." 911 CALL report('setup_netcdf_dimensions', message) 912 913 ! 914 !-- Create the netCDF file as in netCDF-4/HDF5 format if __netcdf4 preprocessor flag is given 911 915 #if defined( __netcdf4 ) 912 CALL check(nf90_create(TRIM(output_file %name), OR(NF90_CLOBBER, NF90_HDF5), ncid))916 CALL check(nf90_create(TRIM(output_file%name), OR(NF90_CLOBBER, NF90_HDF5), ncid)) 913 917 #else 914 CALL check(nf90_create(TRIM(output_file %name), NF90_CLOBBER, ncid))918 CALL check(nf90_create(TRIM(output_file%name), NF90_CLOBBER, ncid)) 915 919 #endif 916 920 … … 918 922 !- Section 1: Define NetCDF dimensions and coordinates 919 923 !------------------------------------------------------------------------------ 920 nt = SIZE(output_file %time)921 nx = palm_grid %nx922 ny = palm_grid %ny923 nz = palm_grid %nz924 z0 = palm_grid %z0924 nt = SIZE(output_file%time) 925 nx = palm_grid%nx 926 ny = palm_grid%ny 927 nz = palm_grid%nz 928 z0 = palm_grid%z0 925 929 926 930 … … 929 933 !- Section 2: Write global NetCDF attributes 930 934 !------------------------------------------------------------------------------ 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 ! 946 !-- 947 !-- 948 !-- 949 950 951 935 CALL date_and_time(DATE=date_string, TIME=time_string, ZONE=zone_string) 936 history_string = & 937 'Created on '// date_string // & 938 ' at ' // time_string(1:2) // ':' // time_string(3:4) // & 939 ' (UTC' // zone_string // ')' 940 941 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'title', 'PALM input file for scenario ...')) 942 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'institution', 'Deutscher Wetterdienst, Offenbach')) 943 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'author', 'Eckhard Kadasch, eckhard.kadasch@dwd.de')) 944 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'history', TRIM(history_string))) 945 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'references', '--')) 946 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'comment', '--')) 947 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_lat', TRIM(real_to_str(origin_lat*TO_DEGREES, '(F18.13)')))) 948 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_lon', TRIM(real_to_str(origin_lon*TO_DEGREES, '(F18.13)')))) 949 ! 950 !-- FIXME: This is the elevation relative to COSMO-DE/D2 sea level and does 951 !-- FIXME: not necessarily comply with DHHN2016 (c.f. PALM Input Data 952 !-- FIXME: Standard v1.9., origin_z) 953 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_z', TRIM(real_to_str(z0, '(F18.13)')))) 954 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'inifor_version', TRIM(VERSION))) 955 CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'palm_version', '--')) 952 956 953 957 ! … … 957 961 !------------------------------------------------------------------------------ 958 962 ! 959 !-- 960 961 962 963 964 ! 965 !-- 966 output_file %dimids_scl = dimids967 968 ! 969 !-- 970 971 972 973 974 975 976 977 978 979 980 981 982 ! 983 !-- 984 output_file %dimvarids_scl = dimvarids985 986 ! 987 !-- 988 CALL check(nf90_def_dim(ncid, "zsoil", SIZE(palm_grid %depths), dimids(3)) )989 ! 990 !-- 991 output_file %dimids_soil = dimids992 993 ! 994 !-- 995 CALL check(nf90_def_var(ncid, "zsoil", NF90_FLOAT, output_file %dimids_soil(3), dimvarids(3)))996 997 998 999 ! 1000 !-- 1001 output_file %dimvarids_soil = dimvarids963 !-- reset dimids first 964 dimids = (/0, 0, 0/) 965 CALL check( nf90_def_dim(ncid, "x", nx+1, dimids(1)) ) 966 CALL check( nf90_def_dim(ncid, "y", ny+1, dimids(2)) ) 967 CALL check( nf90_def_dim(ncid, "z", nz, dimids(3)) ) 968 ! 969 !-- save dimids for later 970 output_file%dimids_scl = dimids 971 972 ! 973 !-- reset dimvarids first 974 dimvarids = (/0, 0, 0/) 975 CALL check(nf90_def_var(ncid, "x", NF90_FLOAT, dimids(1), dimvarids(1))) 976 CALL check(nf90_put_att(ncid, dimvarids(1), "standard_name", "x coordinate of cell centers")) 977 CALL check(nf90_put_att(ncid, dimvarids(1), "units", "m")) 978 979 CALL check(nf90_def_var(ncid, "y", NF90_FLOAT, dimids(2), dimvarids(2))) 980 CALL check(nf90_put_att(ncid, dimvarids(2), "standard_name", "y coordinate of cell centers")) 981 CALL check(nf90_put_att(ncid, dimvarids(2), "units", "m")) 982 983 CALL check(nf90_def_var(ncid, "z", NF90_FLOAT, dimids(3), dimvarids(3))) 984 CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "z coordinate of cell centers")) 985 CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m")) 986 ! 987 !-- save dimvarids for later 988 output_file%dimvarids_scl = dimvarids 989 990 ! 991 !-- overwrite third dimid with the one of depth 992 CALL check(nf90_def_dim(ncid, "zsoil", SIZE(palm_grid%depths), dimids(3)) ) 993 ! 994 !-- save dimids for later 995 output_file%dimids_soil = dimids 996 997 ! 998 !-- overwrite third dimvarid with the one of depth 999 CALL check(nf90_def_var(ncid, "zsoil", NF90_FLOAT, output_file%dimids_soil(3), dimvarids(3))) 1000 CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "depth_below_land")) 1001 CALL check(nf90_put_att(ncid, dimvarids(3), "positive", "down")) 1002 CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m")) 1003 ! 1004 !-- save dimvarids for later 1005 output_file%dimvarids_soil = dimvarids 1002 1006 ! 1003 1007 !------------------------------------------------------------------------------ … … 1005 1009 !------------------------------------------------------------------------------ 1006 1010 ! 1007 !-- 1008 1009 1010 1011 1012 ! 1013 !-- 1014 output_file %dimids_vel = dimids1015 1016 ! 1017 !-- 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 ! 1031 !-- 1032 output_file %dimvarids_vel = dimvarids1011 !-- reset dimids first 1012 dimids = (/0, 0, 0/) 1013 CALL check(nf90_def_dim(ncid, "xu", nx, dimids(1)) ) 1014 CALL check(nf90_def_dim(ncid, "yv", ny, dimids(2)) ) 1015 CALL check(nf90_def_dim(ncid, "zw", nz-1, dimids(3)) ) 1016 ! 1017 !-- save dimids for later 1018 output_file%dimids_vel = dimids 1019 1020 ! 1021 !-- reset dimvarids first 1022 dimvarids = (/0, 0, 0/) 1023 CALL check(nf90_def_var(ncid, "xu", NF90_FLOAT, dimids(1), dimvarids(1))) 1024 CALL check(nf90_put_att(ncid, dimvarids(1), "standard_name", "x coordinate of cell faces")) 1025 CALL check(nf90_put_att(ncid, dimvarids(1), "units", "m")) 1026 1027 CALL check(nf90_def_var(ncid, "yv", NF90_FLOAT, dimids(2), dimvarids(2))) 1028 CALL check(nf90_put_att(ncid, dimvarids(2), "standard_name", "y coordinate of cell faces")) 1029 CALL check(nf90_put_att(ncid, dimvarids(2), "units", "m")) 1030 1031 CALL check(nf90_def_var(ncid, "zw", NF90_FLOAT, dimids(3), dimvarids(3))) 1032 CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "z coordinate of cell faces")) 1033 CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m")) 1034 ! 1035 !-- save dimvarids for later 1036 output_file%dimvarids_vel = dimvarids 1033 1037 1034 1038 ! … … 1036 1040 !- Section 2c: Define time dimension 1037 1041 !------------------------------------------------------------------------------ 1038 CALL check(nf90_def_dim(ncid, "time", nt, output_file %dimid_time) )1039 1040 output_file %dimid_time, &1041 output_file %dimvarid_time))1042 CALL check(nf90_put_att(ncid, output_file %dimvarid_time, "standard_name", "time"))1043 CALL check(nf90_put_att(ncid, output_file %dimvarid_time, "long_name", "time"))1044 CALL check(nf90_put_att(ncid, output_file %dimvarid_time, "units", &1045 1046 1047 1042 CALL check(nf90_def_dim(ncid, "time", nt, output_file%dimid_time) ) 1043 CALL check(nf90_def_var(ncid, "time", NF90_FLOAT, & 1044 output_file%dimid_time, & 1045 output_file%dimvarid_time)) 1046 CALL check(nf90_put_att(ncid, output_file%dimvarid_time, "standard_name", "time")) 1047 CALL check(nf90_put_att(ncid, output_file%dimvarid_time, "long_name", "time")) 1048 CALL check(nf90_put_att(ncid, output_file%dimvarid_time, "units", & 1049 "seconds since " // start_date_string // " UTC")) 1050 1051 CALL check(nf90_enddef(ncid)) 1048 1052 1049 1053 ! … … 1051 1055 !- Section 3: Write grid coordinates 1052 1056 !------------------------------------------------------------------------------ 1053 CALL check(nf90_put_var(ncid, output_file %dimvarids_scl(1), palm_grid%x))1054 CALL check(nf90_put_var(ncid, output_file %dimvarids_scl(2), palm_grid%y))1055 CALL check(nf90_put_var(ncid, output_file %dimvarids_scl(3), palm_grid%z))1056 1057 CALL check(nf90_put_var(ncid, output_file %dimvarids_vel(1), palm_grid%xu))1058 CALL check(nf90_put_var(ncid, output_file %dimvarids_vel(2), palm_grid%yv))1059 CALL check(nf90_put_var(ncid, output_file %dimvarids_vel(3), palm_grid%zw))1060 1061 ! 1062 !-- 1063 CALL check(nf90_put_var(ncid, output_file %dimvarids_soil(3), palm_grid%depths))1064 1065 ! 1066 !-- 1067 CALL check(nf90_put_var(ncid, output_file % dimvarid_time, output_file %time))1068 1069 ! 1070 !-- 1071 1072 1073 1057 CALL check(nf90_put_var(ncid, output_file%dimvarids_scl(1), palm_grid%x)) 1058 CALL check(nf90_put_var(ncid, output_file%dimvarids_scl(2), palm_grid%y)) 1059 CALL check(nf90_put_var(ncid, output_file%dimvarids_scl(3), palm_grid%z)) 1060 1061 CALL check(nf90_put_var(ncid, output_file%dimvarids_vel(1), palm_grid%xu)) 1062 CALL check(nf90_put_var(ncid, output_file%dimvarids_vel(2), palm_grid%yv)) 1063 CALL check(nf90_put_var(ncid, output_file%dimvarids_vel(3), palm_grid%zw)) 1064 1065 ! 1066 !-- TODO Read in soil depths from input file before this. 1067 CALL check(nf90_put_var(ncid, output_file%dimvarids_soil(3), palm_grid%depths)) 1068 1069 ! 1070 !-- Write time vector 1071 CALL check(nf90_put_var(ncid, output_file%dimvarid_time, output_file%time)) 1072 1073 ! 1074 !-- Close the file 1075 CALL check(nf90_close(ncid)) 1076 1077 END SUBROUTINE setup_netcdf_dimensions 1074 1078 1075 1079 … … 1079 1083 !> Defines the netCDF variables to be written to the dynamic driver file 1080 1084 !------------------------------------------------------------------------------! 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 DOi = 1, SIZE(output_variable_table)1097 1098 1099 1100 !to_be_written = ( var % to_be_processed .AND. .NOT. var %is_internal) .OR. &1101 ! ( var %is_internal .AND. debug )1102 to_be_written = ( var % to_be_processed .AND. .NOT. var %is_internal)1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1085 SUBROUTINE setup_netcdf_variables(filename, output_variable_table) 1086 1087 CHARACTER (LEN=*), INTENT(IN) :: filename 1088 TYPE(nc_var), INTENT(INOUT), TARGET :: output_variable_table(:) 1089 1090 TYPE(nc_var), POINTER :: var 1091 INTEGER :: i, ncid 1092 LOGICAL :: to_be_written 1093 1094 message = "Defining variables in dynamic driver '" // TRIM(filename) // "'." 1095 CALL report('setup_netcdf_variables', message) 1096 1097 CALL check(nf90_open(TRIM(filename), NF90_WRITE, ncid)) 1098 CALL check(nf90_redef(ncid)) 1099 1100 DO i = 1, SIZE(output_variable_table) 1101 1102 var => output_variable_table(i) 1103 1104 !to_be_written = ( var%to_be_processed .AND. .NOT. var%is_internal) .OR. & 1105 ! ( var%is_internal .AND. debug ) 1106 to_be_written = ( var%to_be_processed .AND. .NOT. var%is_internal) 1107 1108 IF ( to_be_written ) THEN 1109 message = " variable #" // TRIM(str(i)) // " '" // TRIM(var%name) // "'." 1110 CALL report('setup_netcdf_variables', message) 1111 1112 CALL netcdf_define_variable(var, ncid) 1113 CALL netcdf_get_dimensions(var, ncid) 1114 ENDIF 1115 1116 ENDDO 1117 1118 CALL check(nf90_enddef(ncid)) 1119 CALL check(nf90_close(ncid)) 1120 1121 message = "Dynamic driver '" // TRIM(filename) // "' initialized successfully." 1122 CALL report('setup_netcdf_variables', message) 1123 1124 END SUBROUTINE setup_netcdf_variables 1121 1125 1122 1126 … … 1134 1138 !> record netCDF IDs in the 'in_var_list()' member variable. 1135 1139 !------------------------------------------------------------------------------! 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 message = "Reading data for I/O group '" // TRIM(group % in_var_list(1) %name) // "'."1146 1147 1148 input_file => group %in_files(iter)1140 SUBROUTINE read_input_variables(group, iter, buffer) 1141 TYPE(io_group), INTENT(INOUT), TARGET :: group 1142 INTEGER, INTENT(IN) :: iter 1143 TYPE(container), ALLOCATABLE, INTENT(INOUT) :: buffer(:) 1144 INTEGER :: hour, buf_id 1145 TYPE(nc_var), POINTER :: input_var 1146 CHARACTER(LEN=PATH), POINTER :: input_file 1147 INTEGER :: ivar, nbuffers 1148 1149 message = "Reading data for I/O group '" // TRIM(group%in_var_list(1)%name) // "'." 1150 CALL report('read_input_variables', message) 1151 1152 input_file => group%in_files(iter) 1149 1153 1150 1154 ! … … 1153 1157 !------------------------------------------------------------------------------ 1154 1158 ! 1155 !-- radiation budgets, precipitation 1156 IF (group % kind == 'running average' .OR. & 1157 group % kind == 'accumulated') THEN 1158 1159 IF (SIZE(group % in_var_list) .GT. 1 ) THEN 1160 message = "I/O groups may not contain more than one " // & 1161 "accumulated variable. Group '" // TRIM(group % kind) //& 1162 "' contains " // & 1163 TRIM( str(SIZE(group % in_var_list)) ) // "." 1164 CALL inifor_abort('read_input_variables | accumulation', message) 1159 !-- radiation budgets, precipitation 1160 IF (group%kind == 'running average' .OR. & 1161 group%kind == 'accumulated') THEN 1162 1163 IF (SIZE(group%in_var_list) .GT. 1 ) THEN 1164 message = "I/O groups may not contain more than one " // & 1165 "accumulated variable. Group '" // TRIM(group%kind) //& 1166 "' contains " // & 1167 TRIM( str(SIZE(group%in_var_list)) ) // "." 1168 CALL inifor_abort('read_input_variables | accumulation', message) 1169 ENDIF 1170 1171 ! 1172 !-- use two buffer arrays 1173 nbuffers = 2 1174 IF ( .NOT. ALLOCATED( buffer ) ) ALLOCATE( buffer(nbuffers) ) 1175 1176 ! 1177 !-- hour of the day 1178 hour = iter - 1 1179 ! 1180 !-- chose correct buffer array 1181 buf_id = select_buffer(hour) 1182 1183 CALL log_runtime('time', 'read') 1184 IF ( ALLOCATED(buffer(buf_id)%array) ) DEALLOCATE(buffer(buf_id)%array) 1185 CALL log_runtime('time', 'alloc') 1186 1187 input_var => group%in_var_list(1) 1188 CALL get_netcdf_variable(input_file, input_var, buffer(buf_id)%array) 1189 CALL report('read_input_variables', "Read accumulated " // TRIM(group%in_var_list(1)%name)) 1190 1191 IF ( input_var%is_upside_down ) CALL reverse(buffer(buf_id)%array) 1192 CALL log_runtime('time', 'comp') 1193 1194 !------------------------------------------------------------------------------ 1195 !- Section 2: Load input buffers for normal I/O groups 1196 !------------------------------------------------------------------------------ 1197 ELSE 1198 1199 ! 1200 !-- Allocate one input buffer per input_variable. If more quantities 1201 !-- have to be computed than input variables exist in this group, 1202 !-- allocate more buffers. For instance, in the thermodynamics group, 1203 !-- there are three input variabels (PP, T, Qv) and four quantities 1204 !-- necessart (P, Theta, Rho, qv) for the corresponding output fields 1205 !-- (p0, Theta, qv, ug, and vg) 1206 nbuffers = MAX( group%n_inputs, group%n_output_quantities ) 1207 ALLOCATE( buffer(nbuffers) ) 1208 CALL log_runtime('time', 'alloc') 1209 1210 ! 1211 !-- Read in all input variables, leave extra buffers-if any-untouched. 1212 DO ivar = 1, group%n_inputs 1213 1214 input_var => group%in_var_list(ivar) 1215 1216 ! 1217 ! Check wheather P or PP is present in input file 1218 IF (input_var%name == 'P') THEN 1219 input_var%name = TRIM( get_pressure_varname(input_file) ) 1220 CALL log_runtime('time', 'read') 1165 1221 ENDIF 1166 1222 1167 ! 1168 !-- use two buffer arrays 1169 nbuffers = 2 1170 IF ( .NOT. ALLOCATED( buffer ) ) ALLOCATE( buffer(nbuffers) ) 1171 1172 ! 1173 !-- hour of the day 1174 hour = iter - 1 1175 ! 1176 !-- chose correct buffer array 1177 buf_id = select_buffer(hour) 1178 1179 CALL run_control('time', 'read') 1180 IF ( ALLOCATED(buffer(buf_id) % array) ) DEALLOCATE(buffer(buf_id) % array) 1181 CALL run_control('time', 'alloc') 1182 1183 input_var => group % in_var_list(1) 1184 CALL get_netcdf_variable(input_file, input_var, buffer(buf_id) % array) 1185 CALL report('read_input_variables', "Read accumulated " // TRIM(group % in_var_list(1) % name)) 1186 1187 IF ( input_var % is_upside_down ) CALL reverse(buffer(buf_id) % array) 1188 CALL run_control('time', 'comp') 1189 1190 !------------------------------------------------------------------------------ 1191 !- Section 2: Load input buffers for normal I/O groups 1192 !------------------------------------------------------------------------------ 1193 ELSE 1194 1195 ! 1196 !-- Allocate one input buffer per input_variable. If more quantities 1197 !-- have to be computed than input variables exist in this group, 1198 !-- allocate more buffers. For instance, in the thermodynamics group, 1199 !-- there are three input variabels (PP, T, Qv) and four quantities 1200 !-- necessart (P, Theta, Rho, qv) for the corresponding output fields 1201 !-- (p0, Theta, qv, ug, and vg) 1202 nbuffers = MAX( group % n_inputs, group % n_output_quantities ) 1203 ALLOCATE( buffer(nbuffers) ) 1204 CALL run_control('time', 'alloc') 1205 1206 ! 1207 !-- Read in all input variables, leave extra buffers-if any-untouched. 1208 DO ivar = 1, group % n_inputs 1209 1210 input_var => group % in_var_list(ivar) 1211 1212 ! 1213 ! Check wheather P or PP is present in input file 1214 IF (input_var % name == 'P') THEN 1215 input_var % name = TRIM( get_pressure_varname(input_file) ) 1216 CALL run_control('time', 'read') 1217 ENDIF 1218 1219 CALL get_netcdf_variable(input_file, input_var, buffer(ivar) % array) 1220 1221 IF ( input_var % is_upside_down ) CALL reverse(buffer(ivar) % array) 1222 CALL run_control('time', 'comp') 1223 1224 ENDDO 1225 ENDIF 1226 1227 END SUBROUTINE read_input_variables 1223 CALL get_netcdf_variable(input_file, input_var, buffer(ivar)%array) 1224 1225 IF ( input_var%is_upside_down ) CALL reverse(buffer(ivar)%array) 1226 CALL log_runtime('time', 'comp') 1227 1228 ENDDO 1229 ENDIF 1230 1231 END SUBROUTINE read_input_variables 1228 1232 1229 1233 … … 1234 1238 !> depending on the current hour. 1235 1239 !------------------------------------------------------------------------------! 1236 1237 1238 1239 1240 1241 1242 1243 1240 INTEGER FUNCTION select_buffer(hour) 1241 INTEGER, INTENT(IN) :: hour 1242 INTEGER :: step 1243 1244 select_buffer = 0 1245 step = MODULO(hour, 3) + 1 1246 1247 SELECT CASE(step) 1244 1248 CASE(1, 3) 1245 1249 select_buffer = 1 … … 1249 1253 message = "Invalid step '" // TRIM(str(step)) 1250 1254 CALL inifor_abort('select_buffer', message) 1251 1252 1255 END SELECT 1256 END FUNCTION select_buffer 1253 1257 1254 1258 … … 1259 1263 !> perturbation, 'PP', and returns the appropriate string. 1260 1264 !------------------------------------------------------------------------------! 1261 CHARACTER(LEN=2) FUNCTION get_pressure_varname(input_file) RESULT(var) 1262 CHARACTER(LEN=*) :: input_file 1263 INTEGER :: ncid, varid 1264 1265 CALL check(nf90_open( TRIM(input_file), NF90_NOWRITE, ncid )) 1266 IF ( nf90_inq_varid( ncid, 'P', varid ) .EQ. NF90_NOERR ) THEN 1267 1268 var = 'P' 1269 1270 ELSE IF ( nf90_inq_varid( ncid, 'PP', varid ) .EQ. NF90_NOERR ) THEN 1271 1272 var = 'PP' 1273 CALL report('get_pressure_var', 'Using PP instead of P') 1274 1275 ELSE 1276 1277 message = "Failed to read '" // TRIM(var) // & 1278 "' from file '" // TRIM(input_file) // "'." 1279 CALL inifor_abort('get_pressure_var', message) 1280 1281 ENDIF 1282 1265 CHARACTER(LEN=2) FUNCTION get_pressure_varname(input_file) RESULT(var) 1266 CHARACTER(LEN=*) :: input_file 1267 INTEGER :: ncid, varid 1268 1269 CALL check(nf90_open( TRIM(input_file), NF90_NOWRITE, ncid )) 1270 IF ( nf90_inq_varid( ncid, 'P', varid ) .EQ. NF90_NOERR ) THEN 1271 1272 var = 'P' 1273 1274 ELSE IF ( nf90_inq_varid( ncid, 'PP', varid ) .EQ. NF90_NOERR ) THEN 1275 1276 var = 'PP' 1277 CALL report('get_pressure_var', 'Using PP instead of P') 1278 1279 ELSE 1280 1281 message = "Failed to read '" // TRIM(var) // & 1282 "' from file '" // TRIM(input_file) // "'." 1283 CALL inifor_abort('get_pressure_var', message) 1284 1285 ENDIF 1286 1287 CALL check(nf90_close(ncid)) 1288 1289 END FUNCTION get_pressure_varname 1290 1291 1292 !------------------------------------------------------------------------------! 1293 ! Description: 1294 ! ------------ 1295 !> Read the given global attribute form the given netCDF file. 1296 !------------------------------------------------------------------------------! 1297 FUNCTION get_netcdf_attribute(filename, attribute) RESULT(attribute_value) 1298 1299 CHARACTER(LEN=*), INTENT(IN) :: filename, attribute 1300 REAL(wp) :: attribute_value 1301 1302 INTEGER :: ncid 1303 1304 IF ( nf90_open( TRIM(filename), NF90_NOWRITE, ncid ) == NF90_NOERR ) THEN 1305 1306 CALL check(nf90_get_att(ncid, NF90_GLOBAL, TRIM(attribute), attribute_value)) 1283 1307 CALL check(nf90_close(ncid)) 1284 1308 1285 END FUNCTION get_pressure_varname 1286 1287 1288 !------------------------------------------------------------------------------! 1289 ! Description: 1290 ! ------------ 1291 !> Read the given global attribute form the given netCDF file. 1292 !------------------------------------------------------------------------------! 1293 FUNCTION get_netcdf_attribute(filename, attribute) RESULT(attribute_value) 1294 1295 CHARACTER(LEN=*), INTENT(IN) :: filename, attribute 1296 REAL(dp) :: attribute_value 1297 1298 INTEGER :: ncid 1299 1300 IF ( nf90_open( TRIM(filename), NF90_NOWRITE, ncid ) == NF90_NOERR ) THEN 1301 1302 CALL check(nf90_get_att(ncid, NF90_GLOBAL, TRIM(attribute), attribute_value)) 1303 CALL check(nf90_close(ncid)) 1304 1305 ELSE 1306 1307 message = "Failed to read '" // TRIM(attribute) // & 1308 "' from file '" // TRIM(filename) // "'." 1309 CALL inifor_abort('get_netcdf_attribute', message) 1310 1311 ENDIF 1312 1313 END FUNCTION get_netcdf_attribute 1309 ELSE 1310 1311 message = "Failed to read '" // TRIM(attribute) // & 1312 "' from file '" // TRIM(filename) // "'." 1313 CALL inifor_abort('get_netcdf_attribute', message) 1314 1315 ENDIF 1316 1317 END FUNCTION get_netcdf_attribute 1314 1318 1315 1319 … … 1319 1323 !> Read the attribute of the given variable form the given netCDF file. 1320 1324 !------------------------------------------------------------------------------! 1321 1322 1323 1324 1325 REAL(dp) :: attribute_value1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1325 FUNCTION get_netcdf_variable_attribute(filename, varname, attribute) & 1326 RESULT(attribute_value) 1327 1328 CHARACTER(LEN=*), INTENT(IN) :: filename, varname, attribute 1329 REAL(wp) :: attribute_value 1330 1331 INTEGER :: ncid, varid 1332 1333 IF ( nf90_open( TRIM(filename), NF90_NOWRITE, ncid ) == NF90_NOERR ) THEN 1334 1335 CALL check( nf90_inq_varid( ncid, TRIM( varname ), varid ) ) 1336 CALL check( nf90_get_att( ncid, varid, TRIM( attribute ), & 1337 attribute_value ) ) 1338 CALL check( nf90_close( ncid ) ) 1339 1340 ELSE 1341 1342 message = "Failed to read '" // TRIM( varname ) // ":" // & 1343 TRIM( attribute ) // "' from file '" // TRIM(filename) // "'." 1344 CALL inifor_abort('get_netcdf_variable_attribute', message) 1345 1346 ENDIF 1347 1348 END FUNCTION get_netcdf_variable_attribute 1345 1349 1346 1350 !------------------------------------------------------------------------------! … … 1350 1354 !> variable at the current time step. 1351 1355 !------------------------------------------------------------------------------! 1352 1353 1354 REAL(dp), INTENT(IN) :: array(:,:,:)1355 1356 1357 1358 1359 1360 1361 1362 1363 var % dimids( var % ndim ) == output_file %dimid_time &1364 1365 1366 ! 1367 !-- 1368 ndim = var %ndim1369 IF ( var_is_time_dependent ) ndim = var %ndim - 11370 1371 1372 1373 1374 1375 CALL check(nf90_open(output_file %name, NF90_WRITE, ncid))1376 1377 ! 1378 !-- 1379 SELECT CASE (TRIM(var %kind))1356 SUBROUTINE update_output(var, array, iter, output_file, cfg) 1357 TYPE(nc_var), INTENT(IN) :: var 1358 REAL(wp), INTENT(IN) :: array(:,:,:) 1359 INTEGER, INTENT(IN) :: iter 1360 TYPE(nc_file), INTENT(IN) :: output_file 1361 TYPE(inifor_config) :: cfg 1362 1363 INTEGER :: ncid, ndim, start(4), count(4) 1364 LOGICAL :: var_is_time_dependent 1365 1366 var_is_time_dependent = ( & 1367 var%dimids( var%ndim ) == output_file%dimid_time & 1368 ) 1369 1370 ! 1371 !-- Skip time dimension for output 1372 ndim = var%ndim 1373 IF ( var_is_time_dependent ) ndim = var%ndim - 1 1374 1375 start(:) = (/1,1,1,1/) 1376 start(ndim+1) = iter 1377 count(1:ndim) = var%dimlen(1:ndim) 1378 1379 CALL check(nf90_open(output_file%name, NF90_WRITE, ncid)) 1380 1381 ! 1382 !-- Reduce dimension of output array according to variable kind 1383 SELECT CASE (TRIM(var%kind)) 1380 1384 1381 1385 CASE ( 'init scalar profile', 'init u profile', 'init v profile', & … … 1395 1399 1396 1400 1397 IF (.NOT. SIZE(array, 2) .EQ. var %dimlen(1)) THEN1401 IF (.NOT. SIZE(array, 2) .EQ. var%dimlen(1)) THEN 1398 1402 PRINT *, "inifor: update_output: Dimension ", 1, " of variable ", & 1399 TRIM(var % name), " (", var %dimlen(1), &1403 TRIM(var%name), " (", var%dimlen(1), & 1400 1404 ") does not match the dimension of the output array (", & 1401 1405 SIZE(array, 2), ")." … … 1448 1452 CASE ( 'internal profile' ) 1449 1453 1450 IF ( cfg %debug ) THEN1454 IF ( cfg%debug ) THEN 1451 1455 CALL check(nf90_put_var( ncid, var%varid, array(1,1,:), & 1452 1456 start=start(1:ndim+1), & … … 1461 1465 CASE DEFAULT 1462 1466 1463 message = "Variable kind '" // TRIM(var %kind) // &1467 message = "Variable kind '" // TRIM(var%kind) // & 1464 1468 "' not recognized." 1465 1469 CALL inifor_abort('update_output', message) 1466 1470 1467 1468 1469 1470 1471 1471 END SELECT 1472 1473 CALL check(nf90_close(ncid)) 1474 1475 END SUBROUTINE update_output 1472 1476 1473 1477 … … 1477 1481 !> Checks the status of a netCDF API call and aborts if an error occured 1478 1482 !------------------------------------------------------------------------------! 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1483 SUBROUTINE check(status) 1484 1485 INTEGER, INTENT(IN) :: status 1486 1487 IF (status /= nf90_noerr) THEN 1488 message = "NetCDF API call failed with error: " // & 1489 TRIM( nf90_strerror(status) ) 1490 CALL inifor_abort('io.check', message) 1491 ENDIF 1492 1493 END SUBROUTINE check 1490 1494 1491 1495 END MODULE inifor_io -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_transform.f90 ¶
r3785 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! Improved coding style 30 ! 31 ! 32 ! 3785 2019-03-06 10:41:14Z eckhard 28 33 ! Remove basic state pressure before computing geostrophic wind 29 34 ! - Introduced new level-based profile averaging routine that does not rely on … … 106 111 USE inifor_control 107 112 USE inifor_defs, & 108 ONLY: BETA, dp, G, P_SL, PI, RD, T_SL, TO_DEGREES, TO_RADIANS113 ONLY: BETA, G, P_SL, PI, RD, T_SL, TO_DEGREES, TO_RADIANS, wp 109 114 USE inifor_types 110 115 USE inifor_util, & … … 116 121 117 122 118 119 120 REAL(dp), INTENT(IN) :: in_arr(:)121 REAL(dp), INTENT(OUT) :: out_arr(:)122 123 124 125 126 127 DOk = nz, LBOUND(out_arr, 1), -1128 129 ! 130 !-- 131 !-- 132 !-- 133 !-- 134 IF (outgrid % w(1,k,1) < -1.0_dp .AND. k < nz) THEN135 136 137 out_arr(k) = 0.0_dp138 DOl = 1, 2139 140 outgrid % w(1,k,l) * in_arr(outgrid %kkk(1,k,l) )141 142 143 144 145 123 SUBROUTINE interpolate_1d(in_arr, out_arr, outgrid) 124 TYPE(grid_definition), INTENT(IN) :: outgrid 125 REAL(wp), INTENT(IN) :: in_arr(:) 126 REAL(wp), INTENT(OUT) :: out_arr(:) 127 128 INTEGER :: k, l, nz 129 130 nz = UBOUND(out_arr, 1) 131 132 DO k = nz, LBOUND(out_arr, 1), -1 133 134 ! 135 !-- TODO: Remove IF clause and extrapolate based on a critical vertical 136 !-- TODO: index marking the lower bound of COSMO-DE data coverage. 137 !-- Check for negative interpolation weights indicating grid points 138 !-- below COSMO-DE domain and extrapolate from the top in such cells. 139 IF (outgrid%w(1,k,1) < -1.0_wp .AND. k < nz) THEN 140 out_arr(k) = out_arr(k+1) 141 ELSE 142 out_arr(k) = 0.0_wp 143 DO l = 1, 2 144 out_arr(k) = out_arr(k) + & 145 outgrid%w(1,k,l) * in_arr(outgrid%kkk(1,k,l) ) 146 ENDDO 147 ENDIF 148 ENDDO 149 150 END SUBROUTINE interpolate_1d 146 151 147 152 … … 158 163 !> invar : Array of source data 159 164 !> 160 !> outgrid %kk : Array of vertical neighbour indices. kk(i,j,k,:) contain the165 !> outgrid%kk : Array of vertical neighbour indices. kk(i,j,k,:) contain the 161 166 !> indices of the two vertical neighbors of PALM-4U point (i,j,k) on the 162 167 !> input grid corresponding to the source data invar. 163 168 !> 164 !> outgrid %w_verti : Array of weights for vertical linear interpolation169 !> outgrid%w_verti : Array of weights for vertical linear interpolation 165 170 !> corresponding to neighbour points indexed by kk. 166 171 !> … … 169 174 !> outvar : Array of interpolated data 170 175 !------------------------------------------------------------------------------! 171 172 173 REAL(dp), INTENT(IN) :: in_arr(0:,0:,0:)174 REAL(dp), INTENT(OUT) :: out_arr(0:,0:,:)175 176 177 178 179 180 DOj = LBOUND(out_arr, 2), UBOUND(out_arr, 2)181 DOi = LBOUND(out_arr, 1), UBOUND(out_arr, 1)182 DOk = nz, LBOUND(out_arr, 3), -1183 184 ! 185 !-- 186 !-- 187 !-- 188 !-- 189 IF (outgrid % w_verti(i,j,k,1) < -1.0_dp .AND. k < nz) THEN190 191 192 out_arr(i,j,k) = 0.0_dp193 DOl = 1, 2194 195 outgrid %w_verti(i,j,k,l) * &196 in_arr(i,j,outgrid %kk(i,j,k, l) )197 198 199 200 201 202 176 SUBROUTINE interpolate_1d_arr(in_arr, out_arr, outgrid) 177 TYPE(grid_definition), INTENT(IN) :: outgrid 178 REAL(wp), INTENT(IN) :: in_arr(0:,0:,0:) 179 REAL(wp), INTENT(OUT) :: out_arr(0:,0:,:) 180 181 INTEGER :: i, j, k, l, nz 182 183 nz = UBOUND(out_arr, 3) 184 185 DO j = LBOUND(out_arr, 2), UBOUND(out_arr, 2) 186 DO i = LBOUND(out_arr, 1), UBOUND(out_arr, 1) 187 DO k = nz, LBOUND(out_arr, 3), -1 188 189 ! 190 !-- TODO: Remove IF clause and extrapolate based on a critical vertical 191 !-- TODO: index marking the lower bound of COSMO-DE data coverage. 192 !-- Check for negative interpolation weights indicating grid points 193 !-- below COSMO-DE domain and extrapolate from the top in such cells. 194 IF (outgrid%w_verti(i,j,k,1) < -1.0_wp .AND. k < nz) THEN 195 out_arr(i,j,k) = out_arr(i,j,k+1) 196 ELSE 197 out_arr(i,j,k) = 0.0_wp 198 DO l = 1, 2 199 out_arr(i,j,k) = out_arr(i,j,k) + & 200 outgrid%w_verti(i,j,k,l) * & 201 in_arr(i,j,outgrid%kk(i,j,k, l) ) 202 ENDDO 203 ENDIF 204 ENDDO 205 ENDDO 206 ENDDO 207 END SUBROUTINE interpolate_1d_arr 203 208 204 209 … … 214 219 !> invar : Array of source data 215 220 !> 216 !> outgrid % ii, %jj : Array of neighbour indices in x and y direction.221 !> outgrid%ii,%jj : Array of neighbour indices in x and y direction. 217 222 !> ii(i,j,k,:), and jj(i,j,k,:) contain the four horizontal neighbour points 218 223 !> of PALM-4U point (i,j,k) on the input grid corresponding to the source … … 220 225 ! form of the interpolation weights.) 221 226 !> 222 !> outgrid %w_horiz: Array of weights for horizontal bi-linear interpolation227 !> outgrid%w_horiz: Array of weights for horizontal bi-linear interpolation 223 228 !> corresponding to neighbour points indexed by ii and jj. 224 229 !> … … 227 232 !> outvar : Array of interpolated data 228 233 !------------------------------------------------------------------------------! 229 SUBROUTINE interpolate_2d(invar, outvar, outgrid, ncvar) 230 ! 231 !-- I index 0-based for the indices of the outvar to be consistent with the 232 !-- outgrid indices and interpolation weights. 233 TYPE(grid_definition), INTENT(IN) :: outgrid 234 REAL(dp), INTENT(IN) :: invar(0:,0:,0:) 235 REAL(dp), INTENT(OUT) :: outvar(0:,0:,0:) 236 TYPE(nc_var), INTENT(IN), OPTIONAL :: ncvar 237 238 INTEGER :: i, j, k, l 239 240 ! 241 !-- TODO: check if input dimensions are consistent, i.e. ranges are correct 242 IF ( UBOUND(outvar, 3) .GT. UBOUND(invar, 3) ) THEN 243 message = "Output array for '" // TRIM(ncvar % name) // "' has ' more levels (" // & 244 TRIM(str(UBOUND(outvar, 3))) // ") than input variable ("//& 245 TRIM(str(UBOUND(invar, 3))) // ")." 246 CALL inifor_abort('interpolate_2d', message) 247 ENDIF 248 249 DO k = 0, UBOUND(outvar, 3) 250 DO j = 0, UBOUND(outvar, 2) 251 DO i = 0, UBOUND(outvar, 1) 252 outvar(i,j,k) = 0.0_dp 253 DO l = 1, 4 254 255 outvar(i,j,k) = outvar(i,j,k) + & 256 outgrid % w_horiz(i,j,l) * invar( outgrid % ii(i,j,l), & 257 outgrid % jj(i,j,l), & 258 k ) 259 ENDDO 234 SUBROUTINE interpolate_2d(invar, outvar, outgrid, ncvar) 235 ! 236 !-- I index 0-based for the indices of the outvar to be consistent with the 237 !-- outgrid indices and interpolation weights. 238 TYPE(grid_definition), INTENT(IN) :: outgrid 239 REAL(wp), INTENT(IN) :: invar(0:,0:,0:) 240 REAL(wp), INTENT(OUT) :: outvar(0:,0:,0:) 241 TYPE(nc_var), INTENT(IN), OPTIONAL :: ncvar 242 243 INTEGER :: i, j, k, l 244 245 ! 246 !-- TODO: check if input dimensions are consistent, i.e. ranges are correct 247 IF ( UBOUND(outvar, 3) .GT. UBOUND(invar, 3) ) THEN 248 message = "Output array for '" // TRIM(ncvar%name) // "' has ' more levels (" // & 249 TRIM(str(UBOUND(outvar, 3))) // ") than input variable ("//& 250 TRIM(str(UBOUND(invar, 3))) // ")." 251 CALL inifor_abort('interpolate_2d', message) 252 ENDIF 253 254 DO k = 0, UBOUND(outvar, 3) 255 DO j = 0, UBOUND(outvar, 2) 256 DO i = 0, UBOUND(outvar, 1) 257 outvar(i,j,k) = 0.0_wp 258 DO l = 1, 4 259 260 outvar(i,j,k) = outvar(i,j,k) + & 261 outgrid%w_horiz(i,j,l) * invar( outgrid%ii(i,j,l), & 262 outgrid%jj(i,j,l), & 263 k ) 260 264 ENDDO 261 ENDDO 262 ENDDO 265 ENDDO 266 ENDDO 267 ENDDO 263 268 264 269 END SUBROUTINE interpolate_2d 265 270 266 271 … … 271 276 !> out_arr(:) 272 277 !------------------------------------------------------------------------------! 273 SUBROUTINE average_2d(in_arr, out_arr, ii, jj) 274 REAL(dp), INTENT(IN) :: in_arr(0:,0:,0:) 275 REAL(dp), INTENT(OUT) :: out_arr(0:) 276 INTEGER, INTENT(IN), DIMENSION(:) :: ii, jj 277 278 INTEGER :: i, j, k, l 279 REAL(dp) :: ni 280 281 IF (SIZE(ii) /= SIZE(jj)) THEN 282 message = "Length of 'ii' and 'jj' index lists do not match." // & 283 NEW_LINE(' ') // "ii has " // str(SIZE(ii)) // " elements, " // & 284 NEW_LINE(' ') // "jj has " // str(SIZE(jj)) // "." 285 CALL inifor_abort('average_2d', message) 286 ENDIF 287 288 IF (SIZE(ii) == 0) THEN 289 message = "No columns to average over; " // & 290 "size of index lists 'ii' and 'jj' is zero." 291 CALL inifor_abort('average_2d', message) 292 ENDIF 293 294 DO k = 0, UBOUND(out_arr, 1) 295 296 out_arr(k) = 0.0_dp 297 DO l = 1, UBOUND(ii, 1) 298 i = ii(l) 299 j = jj(l) 300 out_arr(k) = out_arr(k) + in_arr(i, j, k) 301 ENDDO 302 278 SUBROUTINE average_2d(in_arr, out_arr, ii, jj) 279 REAL(wp), INTENT(IN) :: in_arr(0:,0:,0:) 280 REAL(wp), INTENT(OUT) :: out_arr(0:) 281 INTEGER, INTENT(IN), DIMENSION(:) :: ii, jj 282 283 INTEGER :: i, j, k, l 284 REAL(wp) :: ni 285 286 IF (SIZE(ii) /= SIZE(jj)) THEN 287 message = "Length of 'ii' and 'jj' index lists do not match." // & 288 NEW_LINE(' ') // "ii has " // str(SIZE(ii)) // " elements, " // & 289 NEW_LINE(' ') // "jj has " // str(SIZE(jj)) // "." 290 CALL inifor_abort('average_2d', message) 291 ENDIF 292 293 IF (SIZE(ii) == 0) THEN 294 message = "No columns to average over; " // & 295 "size of index lists 'ii' and 'jj' is zero." 296 CALL inifor_abort('average_2d', message) 297 ENDIF 298 299 DO k = 0, UBOUND(out_arr, 1) 300 301 out_arr(k) = 0.0_wp 302 DO l = 1, UBOUND(ii, 1) 303 i = ii(l) 304 j = jj(l) 305 out_arr(k) = out_arr(k) + in_arr(i, j, k) 303 306 ENDDO 304 307 305 ni = 1.0_dp / SIZE(ii) 306 out_arr(:) = out_arr(:) * ni 307 308 END SUBROUTINE average_2d 308 ENDDO 309 310 ni = 1.0_wp / SIZE(ii) 311 out_arr(:) = out_arr(:) * ni 312 313 END SUBROUTINE average_2d 309 314 310 315 … … 320 325 !> as coarse as COSMO, horizontally as fine as PALM). 321 326 !------------------------------------------------------------------------------! 322 323 324 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: source_array325 REAL(dp), DIMENSION(:,:,:), INTENT(OUT) :: palm_array326 REAL(dp), DIMENSION(:,:,:), ALLOCATABLE :: intermediate_array327 328 329 nx = palm_intermediate %nx330 ny = palm_intermediate %ny331 nlev = palm_intermediate %nz332 333 ! 334 !-- 335 !-- 336 !-- 337 338 339 340 341 ! 342 !-- 343 !-- 344 345 346 347 348 327 SUBROUTINE interpolate_3d(source_array, palm_array, palm_intermediate, palm_grid) 328 TYPE(grid_definition), INTENT(IN) :: palm_intermediate, palm_grid 329 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: source_array 330 REAL(wp), DIMENSION(:,:,:), INTENT(OUT) :: palm_array 331 REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: intermediate_array 332 INTEGER :: nx, ny, nlev 333 334 nx = palm_intermediate%nx 335 ny = palm_intermediate%ny 336 nlev = palm_intermediate%nz 337 338 ! 339 !-- Interpolate from COSMO to intermediate grid. Allocating with one 340 !-- less point in the vertical, since scalars like T have 50 instead of 51 341 !-- points in COSMO. 342 ALLOCATE(intermediate_array(0:nx, 0:ny, 0:nlev-1)) ! 343 344 CALL interpolate_2d(source_array, intermediate_array, palm_intermediate) 345 346 ! 347 !-- Interpolate from intermediate grid to palm_grid grid, includes 348 !-- extrapolation for cells below COSMO domain. 349 CALL interpolate_1d_arr(intermediate_array, palm_array, palm_grid) 350 351 DEALLOCATE(intermediate_array) 352 353 END SUBROUTINE interpolate_3d 349 354 350 355 … … 355 360 !> averaging grid 'avg_grid' and store the result in 'profile_array'. 356 361 !------------------------------------------------------------------------------! 357 SUBROUTINE interp_average_profile(source_array, profile_array, avg_grid) 358 TYPE(grid_definition), INTENT(IN) :: avg_grid 359 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: source_array 360 REAL(dp), DIMENSION(:), INTENT(OUT) :: profile_array 361 362 INTEGER :: i_source, j_source, k_profile, k_source, l, m 363 364 REAL :: ni_columns 365 366 profile_array(:) = 0.0_dp 367 368 DO l = 1, avg_grid % n_columns 369 i_source = avg_grid % iii(l) 370 j_source = avg_grid % jjj(l) 371 372 ! 373 !-- Loop over PALM levels 374 DO k_profile = avg_grid % k_min, UBOUND(profile_array, 1) 375 376 ! 377 !-- Loop over vertical interpolation neighbours 378 DO m = 1, 2 379 380 k_source = avg_grid % kkk(l, k_profile, m) 381 382 profile_array(k_profile) = profile_array(k_profile) & 383 + avg_grid % w(l, k_profile, m) & 384 * source_array(i_source, j_source, k_source) 385 ! 386 !-- Loop over vertical interpolation neighbours m 387 ENDDO 388 389 ! 390 !-- Loop over PALM levels k_profile 362 SUBROUTINE interp_average_profile(source_array, profile_array, avg_grid) 363 TYPE(grid_definition), INTENT(IN) :: avg_grid 364 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: source_array 365 REAL(wp), DIMENSION(:), INTENT(OUT) :: profile_array 366 367 INTEGER :: i_source, j_source, k_profile, k_source, l, m 368 369 REAL :: ni_columns 370 371 profile_array(:) = 0.0_wp 372 373 DO l = 1, avg_grid%n_columns 374 i_source = avg_grid%iii(l) 375 j_source = avg_grid%jjj(l) 376 377 ! 378 !-- Loop over PALM levels 379 DO k_profile = avg_grid%k_min, UBOUND(profile_array, 1) 380 381 ! 382 !-- Loop over vertical interpolation neighbours 383 DO m = 1, 2 384 385 k_source = avg_grid%kkk(l, k_profile, m) 386 387 profile_array(k_profile) = profile_array(k_profile) & 388 + avg_grid%w(l, k_profile, m) & 389 * source_array(i_source, j_source, k_source) 390 ! 391 !-- Loop over vertical interpolation neighbours m 391 392 ENDDO 392 393 393 394 ! 394 !-- Loop over horizontal neighbours l395 !-- Loop over PALM levels k_profile 395 396 ENDDO 396 397 397 ni_columns = 1.0_dp / avg_grid % n_columns 398 profile_array(:) = profile_array(:) * ni_columns 399 400 ! 401 !-- Constant extrapolation to the bottom 402 profile_array(1:avg_grid % k_min-1) = profile_array(avg_grid % k_min) 403 404 END SUBROUTINE interp_average_profile 398 ! 399 !-- Loop over horizontal neighbours l 400 ENDDO 401 402 ni_columns = 1.0_wp / avg_grid%n_columns 403 profile_array(:) = profile_array(:) * ni_columns 404 405 ! 406 !-- Constant extrapolation to the bottom 407 profile_array(1:avg_grid%k_min-1) = profile_array(avg_grid%k_min) 408 409 END SUBROUTINE interp_average_profile 405 410 406 411 … … 411 416 !> averaging grid 'avg_grid' and store the result in 'profile_array'. 412 417 !------------------------------------------------------------------------------! 413 414 415 416 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: source_array417 REAL(dp), DIMENSION(:), INTENT(OUT) :: profile_array418 419 420 421 REAL(dp) :: ni_columns422 423 424 425 426 427 428 429 430 431 432 433 profile_array(:) = 0.0_dp434 435 DO l = 1, avg_grid %n_columns436 437 i_source = avg_grid %iii(l)438 j_source = avg_grid %jjj(l)439 440 441 442 443 444 445 ni_columns = 1.0_dp / avg_grid %n_columns446 447 448 418 SUBROUTINE average_profile( source_array, profile_array, avg_grid ) 419 420 TYPE(grid_definition), INTENT(IN) :: avg_grid 421 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: source_array 422 REAL(wp), DIMENSION(:), INTENT(OUT) :: profile_array 423 424 INTEGER :: i_source, j_source, l, nz, nlev 425 426 REAL(wp) :: ni_columns 427 428 nlev = SIZE( source_array, 3 ) 429 nz = SIZE( profile_array, 1 ) 430 431 IF ( nlev /= nz ) THEN 432 message = "Lengths of input and output profiles do not match: " // & 433 "cosmo_pressure(" // TRIM( str( nlev ) ) // & 434 "), profile_array(" // TRIM( str( nz ) ) // ")." 435 CALL inifor_abort('average_pressure_perturbation', message) 436 ENDIF 437 438 profile_array(:) = 0.0_wp 439 440 DO l = 1, avg_grid%n_columns 441 442 i_source = avg_grid%iii(l) 443 j_source = avg_grid%jjj(l) 444 445 profile_array(:) = profile_array(:) & 446 + source_array(i_source, j_source, :) 447 448 ENDDO 449 450 ni_columns = 1.0_wp / avg_grid%n_columns 451 profile_array(:) = profile_array(:) * ni_columns 452 453 END SUBROUTINE average_profile 449 454 450 455 … … 456 461 !> averaging. 457 462 !------------------------------------------------------------------------------! 458 459 460 461 462 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: cosmo_pressure463 REAL(dp), DIMENSION(:), INTENT(OUT) :: profile_array464 465 466 467 REAL(dp) :: ni_columns468 REAL(dp), DIMENSION(:), ALLOCATABLE :: basic_state_pressure469 470 471 472 473 474 475 476 477 478 479 480 481 profile_array(:) = 0.0_dp482 483 DO l = 1, avg_grid %n_columns484 i_source = avg_grid %iii(l)485 j_source = avg_grid %jjj(l)486 487 ! 488 !-- 489 CALL get_basic_state( cosmo_grid %hfl(i_source,j_source,:), BETA, &490 491 492 493 494 495 496 ! 497 !-- 498 499 500 501 502 ni_columns = 1.0_dp / avg_grid %n_columns503 504 505 463 SUBROUTINE average_pressure_perturbation( cosmo_pressure, profile_array, & 464 cosmo_grid, avg_grid ) 465 466 TYPE(grid_definition), INTENT(IN) :: cosmo_grid, avg_grid 467 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: cosmo_pressure 468 REAL(wp), DIMENSION(:), INTENT(OUT) :: profile_array 469 470 INTEGER :: i_source, j_source, l, nz, nlev 471 472 REAL(wp) :: ni_columns 473 REAL(wp), DIMENSION(:), ALLOCATABLE :: basic_state_pressure 474 475 nlev = SIZE( cosmo_pressure, 3 ) 476 nz = SIZE( profile_array, 1 ) 477 478 IF ( nlev /= nz ) THEN 479 message = "Lengths of input and output profiles do not match: " // & 480 "cosmo_pressure(" // TRIM( str( nlev ) ) // & 481 "), profile_array(" // TRIM( str( nz ) ) // ")." 482 CALL inifor_abort('average_pressure_perturbation', message) 483 ENDIF 484 485 ALLOCATE( basic_state_pressure(nz) ) 486 profile_array(:) = 0.0_wp 487 488 DO l = 1, avg_grid%n_columns 489 i_source = avg_grid%iii(l) 490 j_source = avg_grid%jjj(l) 491 492 ! 493 !-- Compute pressure perturbation by removing COSMO basic state pressure 494 CALL get_basic_state( cosmo_grid%hfl(i_source,j_source,:), BETA, & 495 P_SL, T_SL, RD, G, basic_state_pressure ) 496 497 profile_array(:) = profile_array(:) & 498 + cosmo_pressure(i_source, j_source, :) & 499 - basic_state_pressure(:) 500 501 ! 502 !-- Loop over horizontal neighbours l 503 ENDDO 504 505 DEALLOCATE( basic_state_pressure ) 506 507 ni_columns = 1.0_wp / avg_grid%n_columns 508 profile_array(:) = profile_array(:) * ni_columns 509 510 END SUBROUTINE average_pressure_perturbation 506 511 507 512 … … 513 518 !> Extrapolates density linearly from the level 'k_min' downwards. 514 519 !------------------------------------------------------------------------------! 515 516 REAL(dp), DIMENSION(:), INTENT(INOUT) :: rho517 518 519 REAL(dp) :: drhodz, dz, zk, rhok520 521 522 k_min = avg_grid %k_min523 zk = avg_grid %z(k_min)524 525 dz = avg_grid % z(k_min + 1) - avg_grid %z(k_min)526 527 528 rho(1:k_min-1) = rhok + drhodz * (avg_grid %z(1:k_min-1) - zk)529 530 520 SUBROUTINE extrapolate_density(rho, avg_grid) 521 REAL(wp), DIMENSION(:), INTENT(INOUT) :: rho 522 TYPE(grid_definition), INTENT(IN) :: avg_grid 523 524 REAL(wp) :: drhodz, dz, zk, rhok 525 INTEGER :: k_min 526 527 k_min = avg_grid%k_min 528 zk = avg_grid%z(k_min) 529 rhok = rho(k_min) 530 dz = avg_grid%z(k_min + 1) - avg_grid%z(k_min) 531 drhodz = (rho(k_min + 1) - rho(k_min)) / dz 532 533 rho(1:k_min-1) = rhok + drhodz * (avg_grid%z(1:k_min-1) - zk) 534 535 END SUBROUTINE extrapolate_density 531 536 532 537 … … 536 541 !> Driver for extrapolating pressure from PALM level k_min downwards 537 542 !------------------------------------------------------------------------------! 538 539 REAL(dp), DIMENSION(:), INTENT(IN) :: rho540 REAL(dp), DIMENSION(:), INTENT(INOUT) :: p541 542 543 REAL(dp) :: drhodz, dz, zk, rhok544 545 546 k_min = avg_grid %k_min547 zk = avg_grid %z(k_min)548 549 dz = avg_grid % z(k_min + 1) - avg_grid %z(k_min)550 drhodz = 0.5_dp * (rho(k_min + 1) - rho(k_min)) / dz551 552 DOk = 1, k_min-1553 554 avg_grid %z(k), G)555 556 557 543 SUBROUTINE extrapolate_pressure(p, rho, avg_grid) 544 REAL(wp), DIMENSION(:), INTENT(IN) :: rho 545 REAL(wp), DIMENSION(:), INTENT(INOUT) :: p 546 TYPE(grid_definition), INTENT(IN) :: avg_grid 547 548 REAL(wp) :: drhodz, dz, zk, rhok 549 INTEGER :: k, k_min 550 551 k_min = avg_grid%k_min 552 zk = avg_grid%z(k_min) 553 rhok = rho(k_min) 554 dz = avg_grid%z(k_min + 1) - avg_grid%z(k_min) 555 drhodz = 0.5_wp * (rho(k_min + 1) - rho(k_min)) / dz 556 557 DO k = 1, k_min-1 558 p(k) = constant_density_pressure(p(k_min), zk, rhok, drhodz, & 559 avg_grid%z(k), G) 560 ENDDO 561 562 END SUBROUTINE extrapolate_pressure 558 563 559 564 … … 564 569 !> extrapolated pressure at the surface. 565 570 !------------------------------------------------------------------------------! 566 567 REAL(dp), DIMENSION(:), INTENT(IN) :: rho568 REAL(dp), DIMENSION(:), INTENT(INOUT) :: p569 570 571 REAL(dp) :: drhodz, dz, zk, rhok572 573 574 k_min = avg_grid %k_min575 zk = avg_grid %z(k_min)576 577 dz = avg_grid % z(k_min + 1) - avg_grid %z(k_min)578 drhodz = 0.5_dp * (rho(k_min + 1) - rho(k_min)) / dz579 580 581 0.0_dp, G)582 583 584 585 586 587 588 REAL(dp), INTENT(IN) :: pk, zk, rhok, drhodz, g, z589 REAL(dp) :: p590 591 592 593 571 SUBROUTINE get_surface_pressure(p, rho, avg_grid) 572 REAL(wp), DIMENSION(:), INTENT(IN) :: rho 573 REAL(wp), DIMENSION(:), INTENT(INOUT) :: p 574 TYPE(grid_definition), INTENT(IN) :: avg_grid 575 576 REAL(wp) :: drhodz, dz, zk, rhok 577 INTEGER :: k_min 578 579 k_min = avg_grid%k_min 580 zk = avg_grid%z(k_min) 581 rhok = rho(k_min) 582 dz = avg_grid%z(k_min + 1) - avg_grid%z(k_min) 583 drhodz = 0.5_wp * (rho(k_min + 1) - rho(k_min)) / dz 584 585 p(1) = constant_density_pressure(p(k_min), zk, rhok, drhodz, & 586 0.0_wp, G) 587 588 END SUBROUTINE get_surface_pressure 589 590 591 FUNCTION constant_density_pressure(pk, zk, rhok, drhodz, z, g) RESULT(p) 592 593 REAL(wp), INTENT(IN) :: pk, zk, rhok, drhodz, g, z 594 REAL(wp) :: p 595 596 p = pk + ( zk - z ) * g * ( rhok + 0.5*drhodz * (zk - z) ) 597 598 END FUNCTION constant_density_pressure 594 599 595 600 !-----------------------------------------------------------------------------! … … 599 604 !> vg. 600 605 !-----------------------------------------------------------------------------! 601 602 603 604 REAL( dp), DIMENSION(:), INTENT(IN) :: p_north, p_south, p_east, p_west, &606 SUBROUTINE geostrophic_winds(p_north, p_south, p_east, p_west, rho, f3, & 607 Lx, Ly, phi_n, lam_n, phi_g, lam_g, ug, vg) 608 609 REAL(wp), DIMENSION(:), INTENT(IN) :: p_north, p_south, p_east, p_west, & 605 610 rho 606 REAL( dp), INTENT(IN) :: f3, Lx, Ly, phi_n, lam_n, phi_g, lam_g607 REAL( dp), DIMENSION(:), INTENT(OUT) :: ug, vg608 REAL( dp) :: facx, facy609 610 facx = 1.0_ dp / (Lx * f3)611 facy = 1.0_ dp / (Ly * f3)611 REAL(wp), INTENT(IN) :: f3, Lx, Ly, phi_n, lam_n, phi_g, lam_g 612 REAL(wp), DIMENSION(:), INTENT(OUT) :: ug, vg 613 REAL(wp) :: facx, facy 614 615 facx = 1.0_wp / (Lx * f3) 616 facy = 1.0_wp / (Ly * f3) 612 617 ug(:) = - facy / rho(:) * (p_north(:) - p_south(:)) 613 618 vg(:) = facx / rho(:) * (p_east(:) - p_west(:)) … … 617 622 ) 618 623 619 624 END SUBROUTINE geostrophic_winds 620 625 621 626 … … 627 632 !> lngitude of a geographical system centered at x0 and y0. 628 633 !-----------------------------------------------------------------------------! 629 630 REAL(dp), INTENT(IN) :: x(:), y(:), x0, y0, r631 REAL(dp), INTENT(OUT) :: lat(:), lon(:)632 633 REAL(dp) :: ri634 635 ! 636 !-- 637 638 ri = 1.0_dp / r639 640 641 642 634 SUBROUTINE inv_plate_carree(x, y, x0, y0, r, lat, lon) 635 REAL(wp), INTENT(IN) :: x(:), y(:), x0, y0, r 636 REAL(wp), INTENT(OUT) :: lat(:), lon(:) 637 638 REAL(wp) :: ri 639 640 ! 641 !-- TODO check dimensions of lat/lon and y/x match 642 643 ri = 1.0_wp / r 644 645 lat(:) = (y(:) - y0) * ri 646 lon(:) = (x(:) - x0) * ri 647 END SUBROUTINE 643 648 644 649 … … 663 668 !> coordinate xy. 664 669 !------------------------------------------------------------------------------! 665 ELEMENTAL REAL(dp) FUNCTION project(xy, xy0, r)666 REAL(dp), INTENT(IN) :: xy, xy0, r667 REAL(dp) :: ri668 669 ! 670 !-- 671 !-- 672 !-- 673 ri = 1.0_dp / r674 675 676 677 670 ELEMENTAL REAL(wp) FUNCTION project(xy, xy0, r) 671 REAL(wp), INTENT(IN) :: xy, xy0, r 672 REAL(wp) :: ri 673 674 ! 675 !-- If this elemental function is called with a large array as xy, it is 676 !-- computationally more efficient to precompute the inverse radius and 677 !-- then muliply. 678 ri = 1.0_wp / r 679 680 project = (xy - xy0) * ri 681 682 END FUNCTION project 678 683 679 684 … … 684 689 !> compute the geographical latitude of its rotated north pole. 685 690 !------------------------------------------------------------------------------! 686 REAL(dp) FUNCTION phic_to_phin(phi_c)687 REAL(dp), INTENT(IN) :: phi_c688 689 phic_to_phin = 0.5_dp * PI - ABS(phi_c)690 691 691 REAL(wp) FUNCTION phic_to_phin(phi_c) 692 REAL(wp), INTENT(IN) :: phi_c 693 694 phic_to_phin = 0.5_wp * PI - ABS(phi_c) 695 696 END FUNCTION phic_to_phin 692 697 693 698 … … 699 704 !> north pole. 700 705 !------------------------------------------------------------------------------! 701 REAL(dp) FUNCTION lamc_to_lamn(phi_c, lam_c)702 REAL(dp), INTENT(IN) :: phi_c, lam_c703 704 705 IF (phi_c > 0.0_dp) THEN706 707 708 709 706 REAL(wp) FUNCTION lamc_to_lamn(phi_c, lam_c) 707 REAL(wp), INTENT(IN) :: phi_c, lam_c 708 709 lamc_to_lamn = lam_c 710 IF (phi_c > 0.0_wp) THEN 711 lamc_to_lamn = lam_c - SIGN(PI, lam_c) 712 ENDIF 713 714 END FUNCTION lamc_to_lamn 710 715 711 716 … … 718 723 !> rotated-pole coordinate transformations. 719 724 !------------------------------------------------------------------------------! 720 REAL(dp) FUNCTION gamma_from_hemisphere(phi_cg, phi_ref)721 REAL(dp), INTENT(IN) :: phi_cg722 REAL(dp), INTENT(IN) :: phi_ref723 724 725 726 727 728 729 730 731 gamma_from_hemisphere = 0.0_dp732 733 725 REAL(wp) FUNCTION gamma_from_hemisphere(phi_cg, phi_ref) 726 REAL(wp), INTENT(IN) :: phi_cg 727 REAL(wp), INTENT(IN) :: phi_ref 728 729 LOGICAL :: palm_origin_is_south_of_cosmo_origin 730 731 palm_origin_is_south_of_cosmo_origin = (phi_cg < phi_ref) 732 733 IF (palm_origin_is_south_of_cosmo_origin) THEN 734 gamma_from_hemisphere = PI 735 ELSE 736 gamma_from_hemisphere = 0.0_wp 737 ENDIF 738 END FUNCTION gamma_from_hemisphere 734 739 735 740 … … 760 765 !> phi(:,:), lam(:,:): geographical latitudes and logitudes 761 766 !------------------------------------------------------------------------------! 762 SUBROUTINE rotate_to_cosmo(phir, lamr, phip, lamp, phi, lam, gam) 763 REAL(dp), INTENT(IN) :: phir(0:), lamr(0:), phip, lamp, gam 764 REAL(dp), INTENT(OUT) :: phi(0:,0:), lam(0:,0:) 765 766 INTEGER :: i, j 767 SUBROUTINE rotate_to_cosmo(phir, lamr, phip, lamp, phi, lam, gam) 768 REAL(wp), INTENT(IN) :: phir(0:), lamr(0:), phip, lamp, gam 769 REAL(wp), INTENT(OUT) :: phi(0:,0:), lam(0:,0:) 770 771 INTEGER :: i, j 772 773 IF ( SIZE(phi, 1) .NE. SIZE(lam, 1) .OR. & 774 SIZE(phi, 2) .NE. SIZE(lam, 2) ) THEN 775 PRINT *, "inifor: rotate_to_cosmo: Dimensions of phi and lambda do not match. Dimensions are:" 776 PRINT *, "inifor: rotate_to_cosmo: phi: ", SIZE(phi, 1), SIZE(phi, 2) 777 PRINT *, "inifor: rotate_to_cosmo: lam: ", SIZE(lam, 1), SIZE(lam, 2) 778 STOP 779 ENDIF 780 781 IF ( SIZE(phir) .NE. SIZE(phi, 2) .OR. & 782 SIZE(lamr) .NE. SIZE(phi, 1) ) THEN 783 PRINT *, "inifor: rotate_to_cosmo: Dimensions of phir and lamr do not match. Dimensions are:" 784 PRINT *, "inifor: rotate_to_cosmo: phir: ", SIZE(phir), SIZE(phi, 2) 785 PRINT *, "inifor: rotate_to_cosmo: lamr: ", SIZE(lamr), SIZE(phi, 1) 786 STOP 787 ENDIF 788 789 DO j = 0, UBOUND(phir, 1) 790 DO i = 0, UBOUND(lamr, 1) 791 792 phi(i,j) = phirot2phi(phir(j) * TO_DEGREES, & 793 lamr(i) * TO_DEGREES, & 794 phip * TO_DEGREES, & 795 gam * TO_DEGREES) * TO_RADIANS 796 797 lam(i,j) = rlarot2rla(phir(j) * TO_DEGREES, & 798 lamr(i) * TO_DEGREES, & 799 phip * TO_DEGREES, & 800 lamp * TO_DEGREES, & 801 gam * TO_DEGREES) * TO_RADIANS 802 803 ENDDO 804 ENDDO 805 806 END SUBROUTINE rotate_to_cosmo 767 807 768 IF ( SIZE(phi, 1) .NE. SIZE(lam, 1) .OR. &769 SIZE(phi, 2) .NE. SIZE(lam, 2) ) THEN770 PRINT *, "inifor: rotate_to_cosmo: Dimensions of phi and lambda do not match. Dimensions are:"771 PRINT *, "inifor: rotate_to_cosmo: phi: ", SIZE(phi, 1), SIZE(phi, 2)772 PRINT *, "inifor: rotate_to_cosmo: lam: ", SIZE(lam, 1), SIZE(lam, 2)773 STOP774 ENDIF775 776 IF ( SIZE(phir) .NE. SIZE(phi, 2) .OR. &777 SIZE(lamr) .NE. SIZE(phi, 1) ) THEN778 PRINT *, "inifor: rotate_to_cosmo: Dimensions of phir and lamr do not match. Dimensions are:"779 PRINT *, "inifor: rotate_to_cosmo: phir: ", SIZE(phir), SIZE(phi, 2)780 PRINT *, "inifor: rotate_to_cosmo: lamr: ", SIZE(lamr), SIZE(phi, 1)781 STOP782 ENDIF783 784 DO j = 0, UBOUND(phir, 1)785 DO i = 0, UBOUND(lamr, 1)786 787 phi(i,j) = phirot2phi(phir(j) * TO_DEGREES, &788 lamr(i) * TO_DEGREES, &789 phip * TO_DEGREES, &790 gam * TO_DEGREES) * TO_RADIANS791 792 lam(i,j) = rlarot2rla(phir(j) * TO_DEGREES, &793 lamr(i) * TO_DEGREES, &794 phip * TO_DEGREES, &795 lamp * TO_DEGREES, &796 gam * TO_DEGREES) * TO_RADIANS797 798 ENDDO799 ENDDO800 801 END SUBROUTINE rotate_to_cosmo802 803 808 804 809 !------------------------------------------------------------------------------! … … 807 812 !> Rotate the given vector field (x(:), y(:)) by the given 'angle'. 808 813 !------------------------------------------------------------------------------! 809 810 REAL(dp), DIMENSION(:), INTENT(INOUT) :: x, y !< x and y coodrinate in arbitrary units811 REAL(dp), INTENT(IN) :: angle !< rotation angle [deg]812 813 814 REAL(dp) :: sine, cosine, v_rot(2), rotation(2,2)815 816 817 818 ! 819 !-- 820 !-- 821 !-- 822 !-- 823 824 825 DOi = LBOUND(x, 1), UBOUND(x, 1)826 827 828 829 830 831 832 833 834 814 SUBROUTINE rotate_vector_field(x, y, angle) 815 REAL(wp), DIMENSION(:), INTENT(INOUT) :: x, y !< x and y coodrinate in arbitrary units 816 REAL(wp), INTENT(IN) :: angle !< rotation angle [deg] 817 818 INTEGER :: i 819 REAL(wp) :: sine, cosine, v_rot(2), rotation(2,2) 820 821 sine = SIN(angle * TO_RADIANS) 822 cosine = COS(angle * TO_RADIANS) 823 ! 824 !-- RESAHPE() fills columns first, so the rotation matrix becomes 825 !-- 826 !-- rotation = [ cosine -sine ] 827 !-- [ sine cosine ] 828 rotation = RESHAPE( (/cosine, sine, -sine, cosine/), (/2, 2/) ) 829 830 DO i = LBOUND(x, 1), UBOUND(x, 1) 831 832 v_rot(:) = MATMUL(rotation, (/x(i), y(i)/)) 833 834 x(i) = v_rot(1) 835 y(i) = v_rot(2) 836 837 ENDDO 838 839 END SUBROUTINE rotate_vector_field 835 840 836 841 … … 847 852 !> https://www.dwd.de/SharedDocs/downloads/DE/modelldokumentationen/nwv/cosmo_d2/cosmo_d2_dbbeschr_aktuell.pdf?__blob=publicationFile&v=2 848 853 !------------------------------------------------------------------------------! 849 850 851 852 REAL(dp), INTENT(IN) :: phi_n, lam_n, phi_g, lam_g853 REAL(dp) :: delta854 855 856 857 858 859 854 FUNCTION meridian_convergence_rotated(phi_n, lam_n, phi_g, lam_g) & 855 RESULT(delta) 856 857 REAL(wp), INTENT(IN) :: phi_n, lam_n, phi_g, lam_g 858 REAL(wp) :: delta 859 860 delta = atan2( COS(phi_n) * SIN(lam_n - lam_g), & 861 COS(phi_g) * SIN(phi_n) - & 862 SIN(phi_g) * COS(phi_n) * COS(lam_n - lam_g) ) 863 864 END FUNCTION meridian_convergence_rotated 860 865 861 866 !------------------------------------------------------------------------------! … … 903 908 !> 904 909 !------------------------------------------------------------------------------! 905 906 907 908 909 REAL(dp), DIMENSION(0:), INTENT(IN) :: cosmo_lat, cosmo_lon910 REAL(dp), DIMENSION(0:,0:), INTENT(IN) :: palm_clat, palm_clon911 REAL(dp) :: cosmo_dxi, cosmo_dyi912 913 914 REAL(dp) :: lonpos, latpos, lon0, lat0915 916 917 918 919 cosmo_dxi = 1.0_dp / (cosmo_lon(1) - cosmo_lon(0))920 cosmo_dyi = 1.0_dp / (cosmo_lat(1) - cosmo_lat(0))921 922 DO j = 0, UBOUND(palm_clon, 2)!palm_grid %ny923 DO i = 0, UBOUND(palm_clon, 1)!palm_grid %nx924 ! 925 !-- 926 !-- 927 928 929 930 IF (lonpos < 0.0_dp .OR. latpos < 0.0_dp) THEN931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 910 SUBROUTINE find_horizontal_neighbours(cosmo_lat, cosmo_lon, & 911 palm_clat, palm_clon, & 912 palm_ii, palm_jj) 913 914 REAL(wp), DIMENSION(0:), INTENT(IN) :: cosmo_lat, cosmo_lon 915 REAL(wp), DIMENSION(0:,0:), INTENT(IN) :: palm_clat, palm_clon 916 REAL(wp) :: cosmo_dxi, cosmo_dyi 917 INTEGER, DIMENSION(0:,0:,1:), INTENT(OUT) :: palm_ii, palm_jj 918 919 REAL(wp) :: lonpos, latpos, lon0, lat0 920 INTEGER :: i, j 921 922 lon0 = cosmo_lon(0) 923 lat0 = cosmo_lat(0) 924 cosmo_dxi = 1.0_wp / (cosmo_lon(1) - cosmo_lon(0)) 925 cosmo_dyi = 1.0_wp / (cosmo_lat(1) - cosmo_lat(0)) 926 927 DO j = 0, UBOUND(palm_clon, 2)!palm_grid%ny 928 DO i = 0, UBOUND(palm_clon, 1)!palm_grid%nx 929 ! 930 !-- Compute the floating point index corrseponding to PALM-4U grid point 931 !-- location along target grid (COSMO-DE) axes. 932 lonpos = (palm_clon(i,j) - lon0) * cosmo_dxi 933 latpos = (palm_clat(i,j) - lat0) * cosmo_dyi 934 935 IF (lonpos < 0.0_wp .OR. latpos < 0.0_wp) THEN 936 message = "lonpos or latpos out of bounds " // & 937 "while finding interpolation neighbours!" // NEW_LINE(' ') // & 938 " (i,j) = (" // & 939 TRIM(str(i)) // ", " // TRIM(str(j)) // ")" // NEW_LINE(' ') //& 940 " lonpos " // TRIM(real_to_str(lonpos*TO_DEGREES)) // & 941 ", latpos " // TRIM(real_to_str(latpos*TO_DEGREES)) // NEW_LINE(' ') // & 942 " lon0 " // TRIM(real_to_str(lon0 *TO_DEGREES)) // & 943 ", lat0 " // TRIM(real_to_str(lat0*TO_DEGREES)) // NEW_LINE(' ') // & 944 " PALM lon " // TRIM(real_to_str(palm_clon(i,j)*TO_DEGREES)) // & 945 ", PALM lat " // TRIM(real_to_str(palm_clat(i,j)*TO_DEGREES)) 946 CALL inifor_abort('find_horizontal_neighbours', message) 947 ENDIF 948 949 palm_ii(i,j,1) = FLOOR(lonpos) 950 palm_ii(i,j,2) = FLOOR(lonpos) 951 palm_ii(i,j,3) = CEILING(lonpos) 952 palm_ii(i,j,4) = CEILING(lonpos) 953 954 palm_jj(i,j,1) = FLOOR(latpos) 955 palm_jj(i,j,2) = CEILING(latpos) 956 palm_jj(i,j,3) = CEILING(latpos) 957 palm_jj(i,j,4) = FLOOR(latpos) 958 ENDDO 959 ENDDO 960 961 END SUBROUTINE find_horizontal_neighbours 957 962 958 963 … … 963 968 !> column of the given palm grid. 964 969 !------------------------------------------------------------------------------! 965 970 SUBROUTINE find_vertical_neighbours_and_weights_interp( palm_grid, & 966 971 palm_intermediate ) 967 968 969 970 971 972 973 REAL(dp) :: current_height, column_base, column_top, h_top, h_bottom, &974 975 976 nx = palm_grid %nx977 ny = palm_grid %ny978 nz = palm_grid %nz979 nlev = palm_intermediate %nz980 981 ! 982 !-- 983 DOj = 0, ny984 DOi = 0, nx985 986 987 988 column_base = palm_intermediate %h(i,j,0)989 column_top = palm_intermediate %h(i,j,nlev)990 991 ! 992 !-- 993 !-- 994 !-- 995 !-- 996 DOk = 1, nz997 998 ! 999 !-- 1000 !-- 1001 current_height = palm_grid % z(k) + palm_grid %z01002 h_top = palm_intermediate %h(i,j,k_intermediate+1)1003 h_bottom = palm_intermediate %h(i,j,k_intermediate)1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 ! 1014 !-- 1015 palm_grid % w_verti(i,j,k,1:2) = 0.0_dp1016 1017 1018 1019 palm_grid %kk(i,j,k,1:2) = nlev1020 palm_grid % w_verti(i,j,k,1:2) = - 2.0_dp1021 1022 1023 1024 1025 1026 1027 palm_grid %kk(i,j,k,1:2) = 01028 palm_grid % w_verti(i,j,k,1:2) = - 2.0_dp1029 1030 1031 ! 1032 !-- 1033 !-- 1034 DOWHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1)1035 1036 1037 h_top = palm_intermediate %h(i,j,k_intermediate+1)1038 h_bottom = palm_intermediate %h(i,j,k_intermediate)1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 972 TYPE(grid_definition), INTENT(INOUT) :: palm_grid 973 TYPE(grid_definition), INTENT(IN) :: palm_intermediate 974 975 INTEGER :: i, j, k, nx, ny, nz, nlev, k_intermediate 976 LOGICAL :: point_is_below_grid, point_is_above_grid, & 977 point_is_in_current_cell 978 REAL(wp) :: current_height, column_base, column_top, h_top, h_bottom, & 979 weight 980 981 nx = palm_grid%nx 982 ny = palm_grid%ny 983 nz = palm_grid%nz 984 nlev = palm_intermediate%nz 985 986 ! 987 !-- in each column of the fine grid, find vertical neighbours of every cell 988 DO j = 0, ny 989 DO i = 0, nx 990 991 k_intermediate = 0 992 993 column_base = palm_intermediate%h(i,j,0) 994 column_top = palm_intermediate%h(i,j,nlev) 995 996 ! 997 !-- scan through palm_grid column and set neighbour indices in 998 !-- case current_height is either below column_base, in the current 999 !-- cell, or above column_top. Keep increasing current cell index until 1000 !-- the current cell overlaps with the current_height. 1001 DO k = 1, nz 1002 1003 ! 1004 !-- Memorize the top and bottom boundaries of the coarse cell and the 1005 !-- current height within it 1006 current_height = palm_grid%z(k) + palm_grid%z0 1007 h_top = palm_intermediate%h(i,j,k_intermediate+1) 1008 h_bottom = palm_intermediate%h(i,j,k_intermediate) 1009 1010 point_is_above_grid = (current_height > column_top) !22000m, very unlikely 1011 point_is_below_grid = (current_height < column_base) 1012 1013 point_is_in_current_cell = ( & 1014 current_height >= h_bottom .AND. & 1015 current_height < h_top & 1016 ) 1017 1018 ! 1019 !-- set default weights 1020 palm_grid%w_verti(i,j,k,1:2) = 0.0_wp 1021 1022 IF (point_is_above_grid) THEN 1023 1024 palm_grid%kk(i,j,k,1:2) = nlev 1025 palm_grid%w_verti(i,j,k,1:2) = - 2.0_wp 1026 1027 message = "PALM-4U grid extends above COSMO-DE model top." 1028 CALL inifor_abort('find_vertical_neighbours_and_weights', message) 1029 1030 ELSE IF (point_is_below_grid) THEN 1031 1032 palm_grid%kk(i,j,k,1:2) = 0 1033 palm_grid%w_verti(i,j,k,1:2) = - 2.0_wp 1034 1035 ELSE 1036 ! 1037 !-- cycle through intermediate levels until current 1038 !-- intermediate-grid cell overlaps with current_height 1039 DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1) 1040 k_intermediate = k_intermediate + 1 1041 1042 h_top = palm_intermediate%h(i,j,k_intermediate+1) 1043 h_bottom = palm_intermediate%h(i,j,k_intermediate) 1044 point_is_in_current_cell = ( & 1045 current_height >= h_bottom .AND. & 1046 current_height < h_top & 1047 ) 1048 ENDDO 1049 1050 IF (k_intermediate > nlev-1) THEN 1051 message = "Index " // TRIM(str(k_intermediate)) // & 1052 " is above intermediate grid range." 1053 CALL inifor_abort('find_vertical_neighbours', message) 1054 ENDIF 1050 1055 1051 palm_grid % kk(i,j,k,1) = k_intermediate 1052 palm_grid % kk(i,j,k,2) = k_intermediate + 1 1053 1054 ! 1055 !-- compute vertical weights 1056 weight = (h_top - current_height) / (h_top - h_bottom) 1057 palm_grid % w_verti(i,j,k,1) = weight 1058 palm_grid % w_verti(i,j,k,2) = 1.0_dp - weight 1059 ENDIF 1060 1061 ENDDO 1056 palm_grid%kk(i,j,k,1) = k_intermediate 1057 palm_grid%kk(i,j,k,2) = k_intermediate + 1 1058 1059 ! 1060 !-- compute vertical weights 1061 weight = (h_top - current_height) / (h_top - h_bottom) 1062 palm_grid%w_verti(i,j,k,1) = weight 1063 palm_grid%w_verti(i,j,k,2) = 1.0_wp - weight 1064 ENDIF 1062 1065 1063 1066 ENDDO 1064 ENDDO 1065 1066 END SUBROUTINE find_vertical_neighbours_and_weights_interp 1067 1068 ENDDO 1069 ENDDO 1070 1071 END SUBROUTINE find_vertical_neighbours_and_weights_interp 1067 1072 1068 1073 … … 1079 1084 !> iii(:) and jjj(:). 1080 1085 !------------------------------------------------------------------------------! 1081 SUBROUTINE find_vertical_neighbours_and_weights_average( & 1082 avg_grid, level_based_averaging & 1083 ) 1084 1085 TYPE(grid_definition), INTENT(INOUT), TARGET :: avg_grid 1086 LOGICAL :: level_based_averaging 1087 1088 INTEGER :: i, j, k_palm, k_intermediate, l, nlev 1089 LOGICAL :: point_is_below_grid, point_is_above_grid, & 1090 point_is_in_current_cell 1091 REAL(dp) :: current_height, column_base, column_top, h_top, & 1092 h_bottom, weight 1093 REAL(dp), POINTER :: cosmo_h(:,:,:) 1094 1095 1096 avg_grid % k_min = LBOUND(avg_grid % z, 1) 1097 1098 nlev = SIZE(avg_grid % cosmo_h, 3) 1086 SUBROUTINE find_vertical_neighbours_and_weights_average( & 1087 avg_grid, level_based_averaging & 1088 ) 1089 1090 TYPE(grid_definition), INTENT(INOUT), TARGET :: avg_grid 1091 LOGICAL :: level_based_averaging 1092 1093 INTEGER :: i, j, k_palm, k_intermediate, l, nlev 1094 LOGICAL :: point_is_below_grid, point_is_above_grid, & 1095 point_is_in_current_cell 1096 REAL(wp) :: current_height, column_base, column_top, h_top, & 1097 h_bottom, weight 1098 REAL(wp), POINTER :: cosmo_h(:,:,:) 1099 1100 1101 avg_grid%k_min = LBOUND(avg_grid%z, 1) 1102 1103 nlev = SIZE(avg_grid%cosmo_h, 3) 1104 1105 IF (level_based_averaging) THEN 1106 cosmo_h => avg_grid%h 1107 ELSE 1108 cosmo_h => avg_grid%cosmo_h 1109 ENDIF 1110 1111 ! 1112 !-- in each column of the fine grid, find vertical neighbours of every cell 1113 DO l = 1, avg_grid%n_columns 1099 1114 1100 1115 IF (level_based_averaging) THEN 1101 cosmo_h => avg_grid % h 1116 i = 1 1117 j = 1 1102 1118 ELSE 1103 cosmo_h => avg_grid % cosmo_h 1119 i = avg_grid%iii(l) 1120 j = avg_grid%jjj(l) 1104 1121 ENDIF 1105 1122 1106 ! 1107 !-- in each column of the fine grid, find vertical neighbours of every cell 1108 DO l = 1, avg_grid % n_columns 1109 1110 IF (level_based_averaging) THEN 1111 i = 1 1112 j = 1 1123 column_base = cosmo_h(i,j,1) 1124 column_top = cosmo_h(i,j,nlev) 1125 1126 ! 1127 !-- scan through avg_grid column until and set neighbour indices in 1128 !-- case current_height is either below column_base, in the current 1129 !-- cell, or above column_top. Keep increasing current cell index until 1130 !-- the current cell overlaps with the current_height. 1131 k_intermediate = 1 !avg_grid%cosmo_h is indezed 1-based. 1132 DO k_palm = 1, avg_grid%nz 1133 1134 ! 1135 !-- Memorize the top and bottom boundaries of the coarse cell and the 1136 !-- current height within it 1137 current_height = avg_grid%z(k_palm) + avg_grid%z0 1138 h_top = cosmo_h(i,j,k_intermediate+1) 1139 h_bottom = cosmo_h(i,j,k_intermediate) 1140 1141 ! 1142 !-- COSMO column top is located at 22000m, point_is_above_grid is very 1143 !-- unlikely. 1144 point_is_above_grid = (current_height > column_top) 1145 point_is_below_grid = (current_height < column_base) 1146 1147 point_is_in_current_cell = ( & 1148 current_height >= h_bottom .AND. & 1149 current_height < h_top & 1150 ) 1151 1152 ! 1153 !-- set default weights 1154 avg_grid%w(l,k_palm,1:2) = 0.0_wp 1155 1156 IF (point_is_above_grid) THEN 1157 1158 avg_grid%kkk(l,k_palm,1:2) = nlev 1159 avg_grid%w(l,k_palm,1:2) = - 2.0_wp 1160 1161 message = "PALM-4U grid extends above COSMO-DE model top." 1162 CALL inifor_abort('find_vertical_neighbours_and_weights_average', message) 1163 1164 ELSE IF (point_is_below_grid) THEN 1165 1166 avg_grid%kkk(l,k_palm,1:2) = 0 1167 avg_grid%w(l,k_palm,1:2) = - 2.0_wp 1168 avg_grid%k_min = MAX(k_palm + 1, avg_grid%k_min) 1113 1169 ELSE 1114 i = avg_grid % iii(l) 1115 j = avg_grid % jjj(l) 1170 ! 1171 !-- cycle through intermediate levels until current 1172 !-- intermediate-grid cell overlaps with current_height 1173 DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1) 1174 k_intermediate = k_intermediate + 1 1175 1176 h_top = cosmo_h(i,j,k_intermediate+1) 1177 h_bottom = cosmo_h(i,j,k_intermediate) 1178 point_is_in_current_cell = ( & 1179 current_height >= h_bottom .AND. & 1180 current_height < h_top & 1181 ) 1182 ENDDO 1183 1184 ! 1185 !-- k_intermediate = 48 indicates the last section (indices 48 and 49), i.e. 1186 !-- k_intermediate = 49 is not the beginning of a valid cell. 1187 IF (k_intermediate > nlev-1) THEN 1188 message = "Index " // TRIM(str(k_intermediate)) // & 1189 " is above intermediate grid range." 1190 CALL inifor_abort('find_vertical_neighbours', message) 1191 ENDIF 1192 1193 avg_grid%kkk(l,k_palm,1) = k_intermediate 1194 avg_grid%kkk(l,k_palm,2) = k_intermediate + 1 1195 1196 ! 1197 !-- compute vertical weights 1198 weight = (h_top - current_height) / (h_top - h_bottom) 1199 avg_grid%w(l,k_palm,1) = weight 1200 avg_grid%w(l,k_palm,2) = 1.0_wp - weight 1116 1201 ENDIF 1117 1202 1118 column_base = cosmo_h(i,j,1) 1119 column_top = cosmo_h(i,j,nlev) 1120 1121 ! 1122 !-- scan through avg_grid column until and set neighbour indices in 1123 !-- case current_height is either below column_base, in the current 1124 !-- cell, or above column_top. Keep increasing current cell index until 1125 !-- the current cell overlaps with the current_height. 1126 k_intermediate = 1 !avg_grid % cosmo_h is indezed 1-based. 1127 DO k_palm = 1, avg_grid % nz 1128 1129 ! 1130 !-- Memorize the top and bottom boundaries of the coarse cell and the 1131 !-- current height within it 1132 current_height = avg_grid % z(k_palm) + avg_grid % z0 1133 h_top = cosmo_h(i,j,k_intermediate+1) 1134 h_bottom = cosmo_h(i,j,k_intermediate) 1135 1136 ! 1137 !-- COSMO column top is located at 22000m, point_is_above_grid is very 1138 !-- unlikely. 1139 point_is_above_grid = (current_height > column_top) 1140 point_is_below_grid = (current_height < column_base) 1141 1142 point_is_in_current_cell = ( & 1143 current_height >= h_bottom .AND. & 1144 current_height < h_top & 1145 ) 1146 1147 ! 1148 !-- set default weights 1149 avg_grid % w(l,k_palm,1:2) = 0.0_dp 1150 1151 IF (point_is_above_grid) THEN 1152 1153 avg_grid % kkk(l,k_palm,1:2) = nlev 1154 avg_grid % w(l,k_palm,1:2) = - 2.0_dp 1155 1156 message = "PALM-4U grid extends above COSMO-DE model top." 1157 CALL inifor_abort('find_vertical_neighbours_and_weights_average', message) 1158 1159 ELSE IF (point_is_below_grid) THEN 1160 1161 avg_grid % kkk(l,k_palm,1:2) = 0 1162 avg_grid % w(l,k_palm,1:2) = - 2.0_dp 1163 avg_grid % k_min = MAX(k_palm + 1, avg_grid % k_min) 1164 ELSE 1165 ! 1166 !-- cycle through intermediate levels until current 1167 !-- intermediate-grid cell overlaps with current_height 1168 DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1) 1169 k_intermediate = k_intermediate + 1 1170 1171 h_top = cosmo_h(i,j,k_intermediate+1) 1172 h_bottom = cosmo_h(i,j,k_intermediate) 1173 point_is_in_current_cell = ( & 1174 current_height >= h_bottom .AND. & 1175 current_height < h_top & 1176 ) 1177 ENDDO 1178 1179 ! 1180 !-- k_intermediate = 48 indicates the last section (indices 48 and 49), i.e. 1181 !-- k_intermediate = 49 is not the beginning of a valid cell. 1182 IF (k_intermediate > nlev-1) THEN 1183 message = "Index " // TRIM(str(k_intermediate)) // & 1184 " is above intermediate grid range." 1185 CALL inifor_abort('find_vertical_neighbours', message) 1186 ENDIF 1187 1188 avg_grid % kkk(l,k_palm,1) = k_intermediate 1189 avg_grid % kkk(l,k_palm,2) = k_intermediate + 1 1190 1191 ! 1192 !-- compute vertical weights 1193 weight = (h_top - current_height) / (h_top - h_bottom) 1194 avg_grid % w(l,k_palm,1) = weight 1195 avg_grid % w(l,k_palm,2) = 1.0_dp - weight 1196 ENDIF 1197 1198 ! 1199 !-- Loop over PALM levels k 1200 ENDDO 1201 1202 ! 1203 !-- Loop over averaging columns l 1203 ! 1204 !-- Loop over PALM levels k 1204 1205 ENDDO 1206 1207 ! 1208 !-- Loop over averaging columns l 1209 ENDDO 1205 1210 1206 1211 END SUBROUTINE find_vertical_neighbours_and_weights_average 1207 1212 1208 1213 !------------------------------------------------------------------------------! … … 1215 1220 !> Input parameters: 1216 1221 !> ----------------- 1217 !> palm_grid %clon : longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad]1218 !> 1219 !> palm_grid %clat : latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad]1220 !> 1221 !> cosmo_grid %lon : rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad]1222 !> 1223 !> cosmo_grid %lat : rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad]1224 !> 1225 !> cosmo_grid %dxi : inverse grid spacing in the first dimension [m^-1]1226 !> 1227 !> cosmo_grid %dyi : inverse grid spacing in the second dimension [m^-1]1222 !> palm_grid%clon : longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad] 1223 !> 1224 !> palm_grid%clat : latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad] 1225 !> 1226 !> cosmo_grid%lon : rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad] 1227 !> 1228 !> cosmo_grid%lat : rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad] 1229 !> 1230 !> cosmo_grid%dxi : inverse grid spacing in the first dimension [m^-1] 1231 !> 1232 !> cosmo_grid%dyi : inverse grid spacing in the second dimension [m^-1] 1228 1233 !> 1229 1234 !> Output parameters: 1230 1235 !> ------------------ 1231 !> palm_grid %w_horiz(:,:,1-4) : weights for bilinear horizontal interpolation1236 !> palm_grid%w_horiz(:,:,1-4) : weights for bilinear horizontal interpolation 1232 1237 ! 1233 1238 ! COSMO-DE grid … … 1251 1256 ! 1252 1257 !------------------------------------------------------------------------------! 1253 1254 1258 SUBROUTINE compute_horizontal_interp_weights(cosmo_lat, cosmo_lon, & 1259 palm_clat, palm_clon, palm_ii, palm_jj, palm_w_horiz) 1255 1260 1256 REAL(dp), DIMENSION(0:), INTENT(IN) :: cosmo_lat, cosmo_lon1257 REAL(dp) :: cosmo_dxi, cosmo_dyi1258 REAL(dp), DIMENSION(0:,0:), INTENT(IN) :: palm_clat, palm_clon1259 1260 1261 REAL(dp), DIMENSION(0:,0:,1:), INTENT(OUT) :: palm_w_horiz1262 1263 REAL(dp) :: wl, wp1264 1265 1266 cosmo_dxi = 1.0_dp / (cosmo_lon(1) - cosmo_lon(0))1267 cosmo_dyi = 1.0_dp / (cosmo_lat(1) - cosmo_lat(0))1268 1269 DOj = 0, UBOUND(palm_clon, 2)1270 DOi = 0, UBOUND(palm_clon, 1)1271 1272 ! 1273 !-- 1274 wl= ( cosmo_lon(palm_ii(i,j,4)) - palm_clon(i,j) ) * cosmo_dxi1275 1276 ! 1277 !-- 1278 wp= ( cosmo_lat(palm_jj(i,j,2)) - palm_clat(i,j) ) * cosmo_dyi1279 1280 IF (wl > 1.0_dp .OR. wl < 0.0_dp) THEN1281 message = "Horizontal weight wl = " // TRIM(real_to_str(wl)) // &1282 1283 1284 1285 IF (wp > 1.0_dp .OR. wp < 0.0_dp) THEN1286 message = "Horizontal weight wp = " // TRIM(real_to_str(wp)) // &1287 1288 1289 1290 1291 palm_w_horiz(i,j,1) = wl * wp1292 palm_w_horiz(i,j,2) = wl * (1.0_dp - wp)1293 palm_w_horiz(i,j,3) = (1.0_dp - wl) * (1.0_dp - wp)1294 palm_w_horiz(i,j,4) = 1.0_dp - SUM( palm_w_horiz(i,j,1:3) )1295 1296 1297 1261 REAL(wp), DIMENSION(0:), INTENT(IN) :: cosmo_lat, cosmo_lon 1262 REAL(wp) :: cosmo_dxi, cosmo_dyi 1263 REAL(wp), DIMENSION(0:,0:), INTENT(IN) :: palm_clat, palm_clon 1264 INTEGER, DIMENSION(0:,0:,1:), INTENT(IN) :: palm_ii, palm_jj 1265 1266 REAL(wp), DIMENSION(0:,0:,1:), INTENT(OUT) :: palm_w_horiz 1267 1268 REAL(wp) :: wlambda, wphi 1269 INTEGER :: i, j 1270 1271 cosmo_dxi = 1.0_wp / (cosmo_lon(1) - cosmo_lon(0)) 1272 cosmo_dyi = 1.0_wp / (cosmo_lat(1) - cosmo_lat(0)) 1273 1274 DO j = 0, UBOUND(palm_clon, 2) 1275 DO i = 0, UBOUND(palm_clon, 1) 1276 1277 ! 1278 !-- weight in lambda direction 1279 wlambda = ( cosmo_lon(palm_ii(i,j,4)) - palm_clon(i,j) ) * cosmo_dxi 1280 1281 ! 1282 !-- weight in phi direction 1283 wphi = ( cosmo_lat(palm_jj(i,j,2)) - palm_clat(i,j) ) * cosmo_dyi 1284 1285 IF (wlambda > 1.0_wp .OR. wlambda < 0.0_wp) THEN 1286 message = "Horizontal weight wlambda = " // TRIM(real_to_str(wlambda)) // & 1287 " is out bounds." 1288 CALL inifor_abort('compute_horizontal_interp_weights', message) 1289 ENDIF 1290 IF (wphi > 1.0_wp .OR. wphi < 0.0_wp) THEN 1291 message = "Horizontal weight wphi = " // TRIM(real_to_str(wphi)) // & 1292 " is out bounds." 1293 CALL inifor_abort('compute_horizontal_interp_weights', message) 1294 ENDIF 1295 1296 palm_w_horiz(i,j,1) = wlambda * wphi 1297 palm_w_horiz(i,j,2) = wlambda * (1.0_wp - wphi) 1298 palm_w_horiz(i,j,3) = (1.0_wp - wlambda) * (1.0_wp - wphi) 1299 palm_w_horiz(i,j,4) = 1.0_wp - SUM( palm_w_horiz(i,j,1:3) ) 1300 1301 ENDDO 1302 ENDDO 1298 1303 1299 1304 END SUBROUTINE compute_horizontal_interp_weights 1300 1305 1301 1306 … … 1311 1316 !> which means the first centre point has to be omitted and is set to zero. 1312 1317 !------------------------------------------------------------------------------! 1313 1314 REAL(dp), DIMENSION(0:,0:,0:), INTENT(IN) :: u_face, v_face1315 REAL(dp), DIMENSION(0:,0:,0:), INTENT(OUT) :: u_centre, v_centre1316 1317 1318 1319 1320 1321 u_centre(0,:,:) = 0.0_dp1322 u_centre(1:,:,:) = 0.5_dp * ( u_face(0:nx-1,:,:) + u_face(1:,:,:) )1323 1324 v_centre(:,0,:) = 0.0_dp1325 v_centre(:,1:,:) = 0.5_dp * ( v_face(:,0:ny-1,:) + v_face(:,1:,:) )1326 1318 SUBROUTINE centre_velocities(u_face, v_face, u_centre, v_centre) 1319 REAL(wp), DIMENSION(0:,0:,0:), INTENT(IN) :: u_face, v_face 1320 REAL(wp), DIMENSION(0:,0:,0:), INTENT(OUT) :: u_centre, v_centre 1321 INTEGER :: nx, ny 1322 1323 nx = UBOUND(u_face, 1) 1324 ny = UBOUND(u_face, 2) 1325 1326 u_centre(0,:,:) = 0.0_wp 1327 u_centre(1:,:,:) = 0.5_wp * ( u_face(0:nx-1,:,:) + u_face(1:,:,:) ) 1328 1329 v_centre(:,0,:) = 0.0_wp 1330 v_centre(:,1:,:) = 0.5_wp * ( v_face(:,0:ny-1,:) + v_face(:,1:,:) ) 1331 END SUBROUTINE centre_velocities 1327 1332 1328 1333 … … 1332 1337 !> Compute the geographical latitude of a point given in rotated-pole cordinates 1333 1338 !------------------------------------------------------------------------------! 1334 FUNCTION phirot2phi (phirot, rlarot, polphi, polgam) 1335 1336 REAL(dp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1337 REAL(dp), INTENT (IN) :: phirot !< latitude in the rotated system 1338 REAL(dp), INTENT (IN) :: rlarot !< longitude in the rotated system 1339 REAL(dp), INTENT (IN) :: polgam !< angle between the north poles of the systems 1340 1341 REAL(dp) :: phirot2phi !< latitude in the geographical system 1342 1343 REAL(dp) :: zsinpol, zcospol, zphis, zrlas, zarg, zgam 1344 1345 zsinpol = SIN(polphi * TO_RADIANS) 1346 zcospol = COS(polphi * TO_RADIANS) 1347 zphis = phirot * TO_RADIANS 1348 1349 IF (rlarot > 180.0_dp) THEN 1350 zrlas = rlarot - 360.0_dp 1351 ELSE 1352 zrlas = rlarot 1353 ENDIF 1354 zrlas = zrlas * TO_RADIANS 1339 FUNCTION phirot2phi (phirot, rlarot, polphi, polgam) 1340 1341 REAL(wp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1342 REAL(wp), INTENT (IN) :: phirot !< latitude in the rotated system 1343 REAL(wp), INTENT (IN) :: rlarot !< longitude in the rotated system 1344 REAL(wp), INTENT (IN) :: polgam !< angle between the north poles of the systems 1345 1346 REAL(wp) :: phirot2phi !< latitude in the geographical system 1347 1348 REAL(wp) :: zsinpol, zcospol, zphis, zrlas, zarg, zgam 1349 1350 zsinpol = SIN(polphi * TO_RADIANS) 1351 zcospol = COS(polphi * TO_RADIANS) 1352 zphis = phirot * TO_RADIANS 1353 1354 IF (rlarot > 180.0_wp) THEN 1355 zrlas = rlarot - 360.0_wp 1356 ELSE 1357 zrlas = rlarot 1358 ENDIF 1359 zrlas = zrlas * TO_RADIANS 1360 1361 IF (polgam /= 0.0_wp) THEN 1362 zgam = polgam * TO_RADIANS 1363 zarg = zsinpol * SIN (zphis) + & 1364 zcospol * COS(zphis) * ( COS(zrlas) * COS(zgam) - & 1365 SIN(zgam) * SIN(zrlas) ) 1366 ELSE 1367 zarg = zcospol * COS (zphis) * COS (zrlas) + zsinpol * SIN (zphis) 1368 ENDIF 1369 1370 phirot2phi = ASIN (zarg) * TO_DEGREES 1371 1372 END FUNCTION phirot2phi 1373 1374 1375 !------------------------------------------------------------------------------! 1376 ! Description: 1377 ! ------------ 1378 !> Compute the geographical latitude of a point given in rotated-pole cordinates 1379 !------------------------------------------------------------------------------! 1380 FUNCTION phi2phirot (phi, rla, polphi, pollam) 1381 1382 REAL(wp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1383 REAL(wp), INTENT (IN) :: pollam !< longitude of the rotated north pole 1384 REAL(wp), INTENT (IN) :: phi !< latitude in the geographical system 1385 REAL(wp), INTENT (IN) :: rla !< longitude in the geographical system 1386 1387 REAL(wp) :: phi2phirot !< longitude in the rotated system 1388 1389 REAL(wp) :: zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1 1390 1391 zsinpol = SIN(polphi * TO_RADIANS) 1392 zcospol = COS(polphi * TO_RADIANS) 1393 zlampol = pollam * TO_RADIANS 1394 zphi = phi * TO_RADIANS 1395 1396 IF (rla > 180.0_wp) THEN 1397 zrla1 = rla - 360.0_wp 1398 ELSE 1399 zrla1 = rla 1400 ENDIF 1401 zrla = zrla1 * TO_RADIANS 1402 1403 zarg1 = SIN(zphi) * zsinpol 1404 zarg2 = COS(zphi) * zcospol * COS(zrla - zlampol) 1405 1406 phi2phirot = ASIN(zarg1 + zarg2) * TO_DEGREES 1407 1408 END FUNCTION phi2phirot 1409 1410 1411 !------------------------------------------------------------------------------! 1412 ! Description: 1413 ! ------------ 1414 !> Compute the geographical longitude of a point given in rotated-pole cordinates 1415 !------------------------------------------------------------------------------! 1416 FUNCTION rlarot2rla(phirot, rlarot, polphi, pollam, polgam) 1417 1418 REAL(wp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1419 REAL(wp), INTENT (IN) :: pollam !< longitude of the rotated north pole 1420 REAL(wp), INTENT (IN) :: phirot !< latitude in the rotated system 1421 REAL(wp), INTENT (IN) :: rlarot !< longitude in the rotated system 1422 REAL(wp), INTENT (IN) :: polgam !< angle between the north poles of the systems 1423 1424 REAL(wp) :: rlarot2rla !< latitude in the geographical system 1425 1426 REAL(wp) :: zsinpol, zcospol, zlampol, zphis, zrlas, zarg1, zarg2, zgam 1427 1428 zsinpol = SIN(TO_RADIANS * polphi) 1429 zcospol = COS(TO_RADIANS * polphi) 1430 zlampol = TO_RADIANS * pollam 1431 zphis = TO_RADIANS * phirot 1432 1433 IF (rlarot > 180.0_wp) THEN 1434 zrlas = rlarot - 360.0_wp 1435 ELSE 1436 zrlas = rlarot 1437 ENDIF 1438 zrlas = TO_RADIANS * zrlas 1439 1440 IF (polgam /= 0.0_wp) THEN 1441 zgam = TO_RADIANS * polgam 1442 zarg1 = SIN(zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) * & 1443 (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) - & 1444 COS(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) + & 1445 COS(zrlas) * SIN(zgam) ) 1446 1447 zarg2 = COS (zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) * & 1448 (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) + & 1449 SIN(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) + & 1450 COS(zrlas) * SIN(zgam) ) 1451 ELSE 1452 zarg1 = SIN (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis) + & 1453 zcospol * SIN(zphis)) - & 1454 COS (zlampol) * SIN(zrlas) * COS(zphis) 1455 zarg2 = COS (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis) + & 1456 zcospol * SIN(zphis)) + & 1457 SIN (zlampol) * SIN(zrlas) * COS(zphis) 1458 ENDIF 1459 1460 IF (zarg2 == 0.0_wp) zarg2 = 1.0E-20_wp 1461 1462 rlarot2rla = ATAN2(zarg1,zarg2) * TO_DEGREES 1355 1463 1356 IF (polgam /= 0.0_dp) THEN 1357 zgam = polgam * TO_RADIANS 1358 zarg = zsinpol * SIN (zphis) + & 1359 zcospol * COS(zphis) * ( COS(zrlas) * COS(zgam) - & 1360 SIN(zgam) * SIN(zrlas) ) 1361 ELSE 1362 zarg = zcospol * COS (zphis) * COS (zrlas) + zsinpol * SIN (zphis) 1363 ENDIF 1364 1365 phirot2phi = ASIN (zarg) * TO_DEGREES 1366 1367 END FUNCTION phirot2phi 1368 1369 1370 !------------------------------------------------------------------------------! 1371 ! Description: 1372 ! ------------ 1373 !> Compute the geographical latitude of a point given in rotated-pole cordinates 1374 !------------------------------------------------------------------------------! 1375 FUNCTION phi2phirot (phi, rla, polphi, pollam) 1376 1377 REAL(dp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1378 REAL(dp), INTENT (IN) :: pollam !< longitude of the rotated north pole 1379 REAL(dp), INTENT (IN) :: phi !< latitude in the geographical system 1380 REAL(dp), INTENT (IN) :: rla !< longitude in the geographical system 1381 1382 REAL(dp) :: phi2phirot !< longitude in the rotated system 1383 1384 REAL(dp) :: zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1 1385 1386 zsinpol = SIN(polphi * TO_RADIANS) 1387 zcospol = COS(polphi * TO_RADIANS) 1388 zlampol = pollam * TO_RADIANS 1389 zphi = phi * TO_RADIANS 1390 1391 IF (rla > 180.0_dp) THEN 1392 zrla1 = rla - 360.0_dp 1393 ELSE 1394 zrla1 = rla 1395 ENDIF 1396 zrla = zrla1 * TO_RADIANS 1397 1398 zarg1 = SIN(zphi) * zsinpol 1399 zarg2 = COS(zphi) * zcospol * COS(zrla - zlampol) 1400 1401 phi2phirot = ASIN(zarg1 + zarg2) * TO_DEGREES 1402 1403 END FUNCTION phi2phirot 1404 1405 1406 !------------------------------------------------------------------------------! 1407 ! Description: 1408 ! ------------ 1409 !> Compute the geographical longitude of a point given in rotated-pole cordinates 1410 !------------------------------------------------------------------------------! 1411 FUNCTION rlarot2rla(phirot, rlarot, polphi, pollam, polgam) 1412 1413 REAL(dp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1414 REAL(dp), INTENT (IN) :: pollam !< longitude of the rotated north pole 1415 REAL(dp), INTENT (IN) :: phirot !< latitude in the rotated system 1416 REAL(dp), INTENT (IN) :: rlarot !< longitude in the rotated system 1417 REAL(dp), INTENT (IN) :: polgam !< angle between the north poles of the systems 1418 1419 REAL(dp) :: rlarot2rla !< latitude in the geographical system 1420 1421 REAL(dp) :: zsinpol, zcospol, zlampol, zphis, zrlas, zarg1, zarg2, zgam 1422 1423 zsinpol = SIN(TO_RADIANS * polphi) 1424 zcospol = COS(TO_RADIANS * polphi) 1425 zlampol = TO_RADIANS * pollam 1426 zphis = TO_RADIANS * phirot 1427 1428 IF (rlarot > 180.0_dp) THEN 1429 zrlas = rlarot - 360.0_dp 1430 ELSE 1431 zrlas = rlarot 1432 ENDIF 1433 zrlas = TO_RADIANS * zrlas 1434 1435 IF (polgam /= 0.0_dp) THEN 1436 zgam = TO_RADIANS * polgam 1437 zarg1 = SIN(zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) * & 1438 (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) - & 1439 COS(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) + & 1440 COS(zrlas) * SIN(zgam) ) 1441 1442 zarg2 = COS (zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) * & 1443 (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) + & 1444 SIN(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) + & 1445 COS(zrlas) * SIN(zgam) ) 1446 ELSE 1447 zarg1 = SIN (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis) + & 1448 zcospol * SIN(zphis)) - & 1449 COS (zlampol) * SIN(zrlas) * COS(zphis) 1450 zarg2 = COS (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis) + & 1451 zcospol * SIN(zphis)) + & 1452 SIN (zlampol) * SIN(zrlas) * COS(zphis) 1453 ENDIF 1454 1455 IF (zarg2 == 0.0_dp) zarg2 = 1.0E-20_dp 1456 1457 rlarot2rla = ATAN2(zarg1,zarg2) * TO_DEGREES 1458 1459 END FUNCTION rlarot2rla 1464 END FUNCTION rlarot2rla 1460 1465 1461 1466 … … 1465 1470 !> Compute the rotated-pole longitude of a point given in geographical cordinates 1466 1471 !------------------------------------------------------------------------------! 1467 1468 1469 REAL(dp), INTENT (IN) :: polphi !< latitude of the rotated north pole1470 REAL(dp), INTENT (IN) :: pollam !< longitude of the rotated north pole1471 REAL(dp), INTENT (IN) :: phi !< latitude in geographical system1472 REAL(dp), INTENT (IN) :: rla !< longitude in geographical system1473 REAL(dp), INTENT (IN) :: polgam !< angle between the north poles of the systems1474 1475 REAL (KIND=dp) :: rla2rlarot !< latitude in the the rotated system1476 1477 REAL (KIND=dp) :: zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla11478 1479 1480 1481 1482 1483 1484 IF (rla > 180.0_dp) THEN1485 zrla1 = rla - 360.0_dp1486 1487 1488 1489 1490 1491 1492 1493 1494 IF (zarg2 == 0.0_dp) zarg2 = 1.0E-20_dp1495 1496 1497 1498 IF (polgam /= 0.0_dp ) THEN1499 1500 IF (rla2rlarot > 180._dp) rla2rlarot = rla2rlarot - 360.0_dp1501 1502 1503 1472 FUNCTION rla2rlarot ( phi, rla, polphi, pollam, polgam ) 1473 1474 REAL(wp), INTENT (IN) :: polphi !< latitude of the rotated north pole 1475 REAL(wp), INTENT (IN) :: pollam !< longitude of the rotated north pole 1476 REAL(wp), INTENT (IN) :: phi !< latitude in geographical system 1477 REAL(wp), INTENT (IN) :: rla !< longitude in geographical system 1478 REAL(wp), INTENT (IN) :: polgam !< angle between the north poles of the systems 1479 1480 REAL(wp) :: rla2rlarot !< latitude in the the rotated system 1481 1482 REAL(wp) :: zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1 1483 1484 zsinpol = SIN(polphi * TO_RADIANS) 1485 zcospol = COS(polphi * TO_RADIANS) 1486 zlampol = pollam * TO_RADIANS 1487 zphi = phi * TO_RADIANS 1488 1489 IF (rla > 180.0_wp) THEN 1490 zrla1 = rla - 360.0_wp 1491 ELSE 1492 zrla1 = rla 1493 ENDIF 1494 zrla = zrla1 * TO_RADIANS 1495 1496 zarg1 = - SIN (zrla-zlampol) * COS(zphi) 1497 zarg2 = - zsinpol * COS(zphi) * COS(zrla-zlampol) + zcospol * SIN(zphi) 1498 1499 IF (zarg2 == 0.0_wp) zarg2 = 1.0E-20_wp 1500 1501 rla2rlarot = ATAN2 (zarg1,zarg2) * TO_DEGREES 1502 1503 IF (polgam /= 0.0_wp ) THEN 1504 rla2rlarot = polgam + rla2rlarot 1505 IF (rla2rlarot > 180._wp) rla2rlarot = rla2rlarot - 360.0_wp 1506 ENDIF 1507 1508 END FUNCTION rla2rlarot 1504 1509 1505 1510 … … 1510 1515 !> rotated-pole system 1511 1516 !------------------------------------------------------------------------------! 1512 1513 1514 REAL(dp), INTENT (IN) :: u, v !< wind components in the true geographical system1515 REAL(dp), INTENT (IN) :: rlat, rlon !< coordinates in the true geographical system1516 REAL(dp), INTENT (IN) :: pollat, pollon !< latitude and longitude of the north pole of the rotated grid1517 1518 REAL(dp), INTENT (OUT) :: urot, vrot !< wind components in the rotated grid1519 1520 REAL (dp) :: zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm1521 1522 1523 1524 1525 1526 1527 1528 1529 znorm = 1.0_dp / SQRT(zarg1*zarg1 + zarg2*zarg2)1530 1531 1532 1533 1534 1517 SUBROUTINE uv2uvrot(u, v, rlat, rlon, pollat, pollon, urot, vrot) 1518 1519 REAL(wp), INTENT (IN) :: u, v !< wind components in the true geographical system 1520 REAL(wp), INTENT (IN) :: rlat, rlon !< coordinates in the true geographical system 1521 REAL(wp), INTENT (IN) :: pollat, pollon !< latitude and longitude of the north pole of the rotated grid 1522 1523 REAL(wp), INTENT (OUT) :: urot, vrot !< wind components in the rotated grid 1524 1525 REAL (wp) :: zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm 1526 1527 zsinpol = SIN(pollat * TO_RADIANS) 1528 zcospol = COS(pollat * TO_RADIANS) 1529 zlonp = (pollon-rlon) * TO_RADIANS 1530 zlat = rlat * TO_RADIANS 1531 1532 zarg1 = zcospol * SIN(zlonp) 1533 zarg2 = zsinpol * COS(zlat) - zcospol * SIN(zlat) * COS(zlonp) 1534 znorm = 1.0_wp / SQRT(zarg1*zarg1 + zarg2*zarg2) 1535 1536 urot = u * zarg2 * znorm - v * zarg1 * znorm 1537 vrot = u * zarg1 * znorm + v * zarg2 * znorm 1538 1539 END SUBROUTINE uv2uvrot 1535 1540 1536 1541 … … 1541 1546 !> geographical system 1542 1547 !------------------------------------------------------------------------------! 1543 1544 1545 REAL(dp), INTENT(IN) :: urot, vrot !< wind components in the rotated grid1546 REAL(dp), INTENT(IN) :: rlat, rlon !< latitude and longitude in the true geographical system1547 REAL(dp), INTENT(IN) :: pollat, pollon !< latitude and longitude of the north pole of the rotated grid1548 1549 REAL(dp), INTENT(OUT) :: u, v !< wind components in the true geographical system1550 1551 REAL(dp) :: zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm1552 1553 1554 1555 1556 1557 1558 1559 1560 znorm = 1.0_dp / SQRT(zarg1*zarg1 + zarg2*zarg2)1561 1562 1563 1564 1565 1548 SUBROUTINE uvrot2uv (urot, vrot, rlat, rlon, pollat, pollon, u, v) 1549 1550 REAL(wp), INTENT(IN) :: urot, vrot !< wind components in the rotated grid 1551 REAL(wp), INTENT(IN) :: rlat, rlon !< latitude and longitude in the true geographical system 1552 REAL(wp), INTENT(IN) :: pollat, pollon !< latitude and longitude of the north pole of the rotated grid 1553 1554 REAL(wp), INTENT(OUT) :: u, v !< wind components in the true geographical system 1555 1556 REAL(wp) :: zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm 1557 1558 zsinpol = SIN(pollat * TO_RADIANS) 1559 zcospol = COS(pollat * TO_RADIANS) 1560 zlonp = (pollon-rlon) * TO_RADIANS 1561 zlat = rlat * TO_RADIANS 1562 1563 zarg1 = zcospol * SIN(zlonp) 1564 zarg2 = zsinpol * COS(zlat) - zcospol * SIN(zlat) * COS(zlonp) 1565 znorm = 1.0_wp / SQRT(zarg1*zarg1 + zarg2*zarg2) 1566 1567 u = urot * zarg2 * znorm + vrot * zarg1 * znorm 1568 v = - urot * zarg1 * znorm + vrot * zarg2 * znorm 1569 1570 END SUBROUTINE uvrot2uv 1566 1571 1567 1572 END MODULE inifor_transform -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_types.f90 ¶
r3779 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! 30 ! 31 ! 3779 2019-03-05 11:13:35Z eckhard 28 32 ! Improved variable naming 29 33 ! … … 68 72 !> The types module provides derived data types used in INIFOR. 69 73 !------------------------------------------------------------------------------! 70 #if defined ( __netcdf )71 74 MODULE inifor_types 72 75 73 76 USE inifor_defs, & 74 ONLY: dp, DATE, PATH, SNAME, LNAME 77 ONLY: DATE, PATH, SNAME, LNAME, wp 78 79 #if defined ( __netcdf ) 75 80 USE netcdf, & 76 81 ONLY: NF90_MAX_VAR_DIMS, NF90_MAX_NAME 82 #endif 77 83 78 84 IMPLICIT NONE … … 104 110 CHARACTER(LEN=SNAME) :: rotation_method !< selects method for velocity rotation 105 111 106 REAL( dp) :: p0 !< manually specified surface pressure [Pa]107 REAL( dp) :: ug !< manually spefied geostrophic wind component in x direction [m/s]108 REAL( dp) :: vg !< manually spefied geostrophic wind component in y direction [m/s]109 REAL( dp) :: z0 !< elevation of the PALM-4U domain above sea level [m]110 REAL( dp) :: averaging_angle !< latitudal and longitudal width of averaging regions [deg]112 REAL(wp) :: p0 !< manually specified surface pressure [Pa] 113 REAL(wp) :: ug !< manually spefied geostrophic wind component in x direction [m/s] 114 REAL(wp) :: vg !< manually spefied geostrophic wind component in y direction [m/s] 115 REAL(wp) :: z0 !< elevation of the PALM-4U domain above sea level [m] 116 REAL(wp) :: averaging_angle !< latitudal and longitudal width of averaging regions [deg] 111 117 112 118 LOGICAL :: debug !< indicates whether --debug option was given … … 143 149 INTEGER, ALLOCATABLE :: jjj(:) !< profile averaging neighbour indices 144 150 INTEGER, ALLOCATABLE :: kkk(:,:,:) !< indices of vertical interpolation neightbours, kkk(<source column>, <PALM k level>, <neighbour index>) 145 REAL( dp) :: lx !< domain length in the first dimension [m]146 REAL( dp) :: ly !< domain length in the second dimension [m]147 REAL( dp) :: x0 !< x coordinate of PALM-4U domain projection centre, i.e. location of zero distortion148 REAL( dp) :: y0 !< y coordinate of PALM-4U domain projection centre, i.e. location of zwro distortion149 REAL( dp) :: z0 !< displacement of the coordinate origin above sea level [m]150 REAL( dp), ALLOCATABLE :: x(:) !< coordinates of cell centers in x direction [m]151 REAL( dp), ALLOCATABLE :: y(:) !< coordinates of cell centers in y direction [m]152 REAL( dp), POINTER :: z(:) !< coordinates of cell centers in z direction [m]153 REAL( dp), ALLOCATABLE :: h(:,:,:) !< heights grid point for intermediate grids [m]154 REAL( dp), POINTER :: cosmo_h(:,:,:)!< pointer to appropriate COSMO level heights (scalar/w) [m]155 REAL( dp), POINTER :: hhl(:,:,:) !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from156 REAL( dp), POINTER :: hfl(:,:,:) !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl157 REAL( dp), POINTER :: depths(:) !< depths of output soil layers, equal the depths of the source model (e.g. COSMO-DE)158 REAL( dp), ALLOCATABLE :: xu(:) !< coordinates of cell faces in x direction [m]159 REAL( dp), ALLOCATABLE :: yv(:) !< coordinates of cell faces in y direction [m]160 REAL( dp), POINTER :: zw(:) !< coordinates of cell faces in z direction [m]161 REAL( dp), ALLOCATABLE :: lat(:) !< rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad]162 REAL( dp), ALLOCATABLE :: lon(:) !< rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad]163 REAL( dp), ALLOCATABLE :: latv(:) !< rotated-pole latitudes of v winds (face centres in latitudal/y direction) [rad]164 REAL( dp), ALLOCATABLE :: lonu(:) !< rotated-pole latitudes of u winds (face centres in longitudal/x direction) [rad]165 REAL( dp), ALLOCATABLE :: clat(:,:) !< latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad]166 REAL( dp), ALLOCATABLE :: clon(:,:) !< longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad]167 REAL( dp), ALLOCATABLE :: clatu(:,:) !< latitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad]168 REAL( dp), ALLOCATABLE :: clonu(:,:) !< longitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad]169 REAL( dp), ALLOCATABLE :: clatv(:,:) !< latitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad]170 REAL( dp), ALLOCATABLE :: clonv(:,:) !< longitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad]171 REAL( dp), ALLOCATABLE :: w_horiz(:,:,:) !< weights for bilinear horizontal interpolation172 REAL( dp), ALLOCATABLE :: w_verti(:,:,:,:) !< weights for linear vertical interpolation173 REAL( dp), ALLOCATABLE :: w(:,:,:) !< vertical interpolation weights, w(<source_column>, <PALM k level>, <neighbour index>) [-]151 REAL(wp) :: lx !< domain length in the first dimension [m] 152 REAL(wp) :: ly !< domain length in the second dimension [m] 153 REAL(wp) :: x0 !< x coordinate of PALM-4U domain projection centre, i.e. location of zero distortion 154 REAL(wp) :: y0 !< y coordinate of PALM-4U domain projection centre, i.e. location of zwro distortion 155 REAL(wp) :: z0 !< displacement of the coordinate origin above sea level [m] 156 REAL(wp), ALLOCATABLE :: x(:) !< coordinates of cell centers in x direction [m] 157 REAL(wp), ALLOCATABLE :: y(:) !< coordinates of cell centers in y direction [m] 158 REAL(wp), POINTER :: z(:) !< coordinates of cell centers in z direction [m] 159 REAL(wp), ALLOCATABLE :: h(:,:,:) !< heights grid point for intermediate grids [m] 160 REAL(wp), POINTER :: cosmo_h(:,:,:)!< pointer to appropriate COSMO level heights (scalar/w) [m] 161 REAL(wp), POINTER :: hhl(:,:,:) !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from 162 REAL(wp), POINTER :: hfl(:,:,:) !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl 163 REAL(wp), POINTER :: depths(:) !< depths of output soil layers, equal the depths of the source model (e.g. COSMO-DE) 164 REAL(wp), ALLOCATABLE :: xu(:) !< coordinates of cell faces in x direction [m] 165 REAL(wp), ALLOCATABLE :: yv(:) !< coordinates of cell faces in y direction [m] 166 REAL(wp), POINTER :: zw(:) !< coordinates of cell faces in z direction [m] 167 REAL(wp), ALLOCATABLE :: lat(:) !< rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad] 168 REAL(wp), ALLOCATABLE :: lon(:) !< rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad] 169 REAL(wp), ALLOCATABLE :: latv(:) !< rotated-pole latitudes of v winds (face centres in latitudal/y direction) [rad] 170 REAL(wp), ALLOCATABLE :: lonu(:) !< rotated-pole latitudes of u winds (face centres in longitudal/x direction) [rad] 171 REAL(wp), ALLOCATABLE :: clat(:,:) !< latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad] 172 REAL(wp), ALLOCATABLE :: clon(:,:) !< longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad] 173 REAL(wp), ALLOCATABLE :: clatu(:,:) !< latitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad] 174 REAL(wp), ALLOCATABLE :: clonu(:,:) !< longitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad] 175 REAL(wp), ALLOCATABLE :: clatv(:,:) !< latitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad] 176 REAL(wp), ALLOCATABLE :: clonv(:,:) !< longitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad] 177 REAL(wp), ALLOCATABLE :: w_horiz(:,:,:) !< weights for bilinear horizontal interpolation 178 REAL(wp), ALLOCATABLE :: w_verti(:,:,:,:) !< weights for linear vertical interpolation 179 REAL(wp), ALLOCATABLE :: w(:,:,:) !< vertical interpolation weights, w(<source_column>, <PALM k level>, <neighbour index>) [-] 174 180 END TYPE grid_definition 175 181 … … 190 196 INTEGER :: dimvarids_vel(3) !< NetCDF IDs of the grid coordinates of velocities xu, yu, zu. Note that velocities are located at mix of both coordinates, e.g. u(xu, y, z). 191 197 INTEGER :: dimvarids_soil(3) !< NetCDF IDs of the grid coordinates for soil points x, y, depth 192 REAL( dp), POINTER :: time(:) !< vector of output time steps198 REAL(wp), POINTER :: time(:) !< vector of output time steps 193 199 END TYPE nc_file 194 200 … … 199 205 !> Metadata container for netCDF variables 200 206 !------------------------------------------------------------------------------! 207 #if defined ( __netcdf ) 201 208 TYPE nc_var 202 209 INTEGER :: varid !< NetCDF ID of the variable … … 247 254 LOGICAL :: is_preprocessed = .FALSE. !< Inifor flag indicating whether the I/O group has been preprocessed 248 255 END TYPE io_group 249 256 #endif 250 257 251 258 !------------------------------------------------------------------------------! … … 257 264 !------------------------------------------------------------------------------! 258 265 TYPE container 259 REAL( dp), ALLOCATABLE :: array(:,:,:) !< generic data array266 REAL(wp), ALLOCATABLE :: array(:,:,:) !< generic data array 260 267 LOGICAL :: is_preprocessed = .FALSE. !< flag indicating whether input array has been preprocessed 261 268 END TYPE container 262 269 263 270 END MODULE inifor_types 264 #endif265 -
TabularUnified palm/trunk/UTIL/inifor/src/inifor_util.f90 ¶
r3785 r3866 26 26 ! ----------------- 27 27 ! $Id$ 28 ! Use PALM's working precision 29 ! Improved coding style 30 ! 31 ! 32 ! 3785 2019-03-06 10:41:14Z eckhard 28 33 ! Prefixed all INIFOR modules with inifor_ 29 34 ! … … 58 63 !> The util module provides miscellaneous utility routines for INIFOR. 59 64 !------------------------------------------------------------------------------! 60 #if defined ( __netcdf )61 65 MODULE inifor_util 62 66 63 67 USE inifor_defs, & 64 ONLY : dp, PI, DATE, SNAME68 ONLY : PI, DATE, SNAME, wp 65 69 USE inifor_types, & 66 70 ONLY : grid_definition … … 87 91 END TYPE 88 92 89 93 INTERFACE 90 94 91 95 !------------------------------------------------------------------------------! … … 95 99 !> structure. 96 100 !------------------------------------------------------------------------------! 97 98 99 100 101 102 103 104 105 106 101 FUNCTION strptime(string, format, timeinfo) BIND(c, NAME='strptime') 102 IMPORT :: C_CHAR, C_SIZE_T, tm_struct 103 104 IMPLICIT NONE 105 106 CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: string, format 107 TYPE(tm_struct), INTENT(OUT) :: timeinfo 108 109 INTEGER(C_SIZE_T) :: strptime 110 END FUNCTION 107 111 108 112 … … 113 117 !> structure to a string in the given 'format'. 114 118 !------------------------------------------------------------------------------! 115 116 117 118 119 120 121 122 123 124 125 126 119 FUNCTION strftime(string, string_len, format, timeinfo) BIND(c, NAME='strftime') 120 IMPORT :: C_CHAR, C_SIZE_T, tm_struct 121 122 IMPLICIT NONE 123 124 CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(OUT) :: string 125 CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: format 126 INTEGER(C_SIZE_T), INTENT(IN) :: string_len 127 TYPE(tm_struct), INTENT(IN) :: timeinfo 128 129 INTEGER(C_SIZE_T) :: strftime 130 END FUNCTION 127 131 128 132 … … 135 139 !> e.g. increments the date if hours overfow 24. 136 140 !------------------------------------------------------------------------------! 137 138 139 140 141 142 143 144 145 146 147 141 FUNCTION mktime(timeinfo) BIND(c, NAME='mktime') 142 IMPORT :: C_PTR, tm_struct 143 144 IMPLICIT NONE 145 146 TYPE(tm_struct), INTENT(IN) :: timeinfo 147 148 TYPE(C_PTR) :: mktime 149 END FUNCTION 150 151 END INTERFACE 148 152 149 153 CONTAINS … … 156 160 !> format 157 161 !------------------------------------------------------------------------------! 158 CHARACTER(LEN=DATE) FUNCTION add_hours_to(date_string, hours) 159 CHARACTER(LEN=DATE), INTENT(IN) :: date_string 160 INTEGER, INTENT(IN) :: hours 161 162 CHARACTER(KIND=C_CHAR, LEN=*), PARAMETER :: format_string = "%Y%m%d%H" 163 CHARACTER(KIND=C_CHAR, LEN=DATE) :: c_date_string 164 TYPE(C_PTR) :: c_pointer 165 TYPE(tm_struct) :: time_info 166 INTEGER :: err 167 168 c_date_string = date_string 169 170 ! Convert C string to C tm struct 171 CALL init_tm(time_info) 172 err = strptime(c_date_string, format_string, time_info) 162 CHARACTER(LEN=DATE) FUNCTION add_hours_to(date_string, hours) 163 CHARACTER(LEN=DATE), INTENT(IN) :: date_string 164 INTEGER, INTENT(IN) :: hours 165 166 CHARACTER(KIND=C_CHAR, LEN=*), PARAMETER :: format_string = "%Y%m%d%H" 167 CHARACTER(KIND=C_CHAR, LEN=DATE) :: c_date_string 168 TYPE(C_PTR) :: c_pointer 169 TYPE(tm_struct) :: time_info 170 INTEGER :: err 171 172 c_date_string = date_string 173 174 ! Convert C string to C tm struct 175 CALL init_tm(time_info) 176 err = strptime(c_date_string, format_string, time_info) 177 178 ! Manipulate and normalize C tm struct 179 time_info%tm_hour = time_info%tm_hour + hours 180 c_pointer = mktime(time_info) 181 182 ! Convert back to C string 183 err = strftime(c_date_string, INT(DATE, KIND=C_SIZE_T), & 184 format_string, time_info) 185 186 add_hours_to = c_date_string 187 END FUNCTION 188 189 190 !------------------------------------------------------------------------------! 191 ! Description: 192 ! ------------ 193 !> Print all members of the given tm structure 194 !------------------------------------------------------------------------------! 195 SUBROUTINE print_tm(timeinfo) 196 TYPE(tm_struct), INTENT(IN) :: timeinfo 197 198 PRINT *, "sec: ", timeinfo%tm_sec, & !< seconds after the minute [0, 61] 199 "min: ", timeinfo%tm_min, & !< minutes after the hour [0, 59] 200 "hr: ", timeinfo%tm_hour, & !< hours since midnight [0, 23] 201 "day: ", timeinfo%tm_mday, & !< day of the month [1, 31] 202 "mon: ", timeinfo%tm_mon, & !< month since January [0, 11] 203 "yr: ", timeinfo%tm_year, & !< years since 1900 204 "wday:", timeinfo%tm_wday, & !< days since Sunday [0, 6] 205 "yday:", timeinfo%tm_yday, & !< days since January 1st [0, 356] 206 "dst: ", timeinfo%tm_isdst !< Daylight Saving time flag 207 END SUBROUTINE print_tm 208 173 209 174 ! Manipulate and normalize C tm struct175 time_info % tm_hour = time_info % tm_hour + hours176 c_pointer = mktime(time_info)177 178 ! Convert back to C string179 err = strftime(c_date_string, INT(DATE, KIND=C_SIZE_T), &180 format_string, time_info)181 182 add_hours_to = c_date_string183 END FUNCTION184 185 186 !------------------------------------------------------------------------------!187 ! Description:188 ! ------------189 !> Print all members of the given tm structure190 !------------------------------------------------------------------------------!191 SUBROUTINE print_tm(timeinfo)192 TYPE(tm_struct), INTENT(IN) :: timeinfo193 194 PRINT *, "sec: ", timeinfo % tm_sec, & !< seconds after the minute [0, 61]195 "min: ", timeinfo % tm_min, & !< minutes after the hour [0, 59]196 "hr: ", timeinfo % tm_hour, & !< hours since midnight [0, 23]197 "day: ", timeinfo % tm_mday, & !< day of the month [1, 31]198 "mon: ", timeinfo % tm_mon, & !< month since January [0, 11]199 "yr: ", timeinfo % tm_year, & !< years since 1900200 "wday:", timeinfo % tm_wday, & !< days since Sunday [0, 6]201 "yday:", timeinfo % tm_yday, & !< days since January 1st [0, 356]202 "dst: ", timeinfo % tm_isdst !< Daylight Saving time flag203 END SUBROUTINE print_tm204 205 206 210 !------------------------------------------------------------------------------! 207 211 ! Description: … … 209 213 !> Initialize the given tm structure with zero values 210 214 !------------------------------------------------------------------------------! 211 212 213 214 timeinfo %tm_sec = 0215 timeinfo %tm_min = 0216 timeinfo %tm_hour = 0217 timeinfo %tm_mday = 0218 timeinfo %tm_mon = 0219 timeinfo %tm_year = 0220 timeinfo %tm_wday = 0221 timeinfo %tm_yday = 0222 223 224 225 226 timeinfo %tm_isdst = -1227 215 SUBROUTINE init_tm(timeinfo) 216 TYPE(tm_struct), INTENT(INOUT) :: timeinfo 217 218 timeinfo%tm_sec = 0 219 timeinfo%tm_min = 0 220 timeinfo%tm_hour = 0 221 timeinfo%tm_mday = 0 222 timeinfo%tm_mon = 0 223 timeinfo%tm_year = 0 224 timeinfo%tm_wday = 0 225 timeinfo%tm_yday = 0 226 227 ! We use UTC times, so marking Daylight Saving Time (DST) 'not available' 228 ! (< 0). If this is set to 0, mktime will convert the timeinfo to DST and 229 ! add one hour. 230 timeinfo%tm_isdst = -1 231 END SUBROUTINE init_tm 228 232 229 233 … … 234 238 !> and stop 235 239 !------------------------------------------------------------------------------! 236 237 238 REAL(dp), INTENT(IN) :: start, stop239 REAL(dp), INTENT(INOUT) :: array(0:)240 241 242 243 244 245 246 247 248 249 250 251 array(i) = start + REAL(i, dp) / n * (stop - start)252 253 254 255 256 240 SUBROUTINE linspace(start, stop, array) 241 242 REAL(wp), INTENT(IN) :: start, stop 243 REAL(wp), INTENT(INOUT) :: array(0:) 244 INTEGER :: i, n 245 246 n = UBOUND(array, 1) 247 248 IF (n .EQ. 0) THEN 249 250 array(0) = start 251 252 ELSE 253 254 DO i = 0, n 255 array(i) = start + REAL(i, wp) / n * (stop - start) 256 ENDDO 257 258 ENDIF 259 260 END SUBROUTINE linspace 257 261 258 262 … … 263 267 !> (COSMO) to bottom-up (PALM) 264 268 !------------------------------------------------------------------------------! 265 266 267 REAL(dp), INTENT(INOUT) :: input_arr(:,:,:)268 269 270 271 269 SUBROUTINE reverse(input_arr) 270 271 REAL(wp), INTENT(INOUT) :: input_arr(:,:,:) 272 273 input_arr = input_arr(:,:,size(input_arr, 3):1:-1) 274 275 END SUBROUTINE reverse 272 276 273 277 … … 277 281 !> 278 282 !------------------------------------------------------------------------------! 279 280 281 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: avg_1, avg_2282 REAL(dp), INTENT(IN) :: t1, t2, t3283 REAL(dp), DIMENSION(:,:,:), INTENT(OUT) :: avg_3284 285 REAL(dp) :: ti283 SUBROUTINE deaverage(avg_1, t1, avg_2, t2, avg_3, t3) 284 285 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: avg_1, avg_2 286 REAL(wp), INTENT(IN) :: t1, t2, t3 287 REAL(wp), DIMENSION(:,:,:), INTENT(OUT) :: avg_3 288 289 REAL(wp) :: ti 286 290 287 ti = 1.0_dp / t3288 289 290 291 291 ti = 1.0_wp / t3 292 293 avg_3(:,:,:) = ti * ( t2 * avg_2(:,:,:) - t1 * avg_1(:,:,:) ) 294 295 END SUBROUTINE deaverage 292 296 293 297 … … 297 301 !> Compute the COSMO-DE/-D2 basic state pressure profile 298 302 !------------------------------------------------------------------------------! 299 300 301 REAL(dp), INTENT(IN) :: z(1:) !< height [m]302 REAL(dp), INTENT(IN) :: beta !< logarithmic lapse rate, dT / d ln(p) [K]303 REAL(dp), INTENT(IN) :: p_sl !< reference pressure [Pa]304 REAL(dp), INTENT(IN) :: t_sl !< reference tempereature [K]305 REAL(dp), INTENT(IN) :: rd !< ideal gas constant of dry air [J/kg/K]306 REAL(dp), INTENT(IN) :: g !< acceleration of Earth's gravity [m/s^2]307 REAL(dp), INTENT(OUT) :: p0(1:) !< COSMO basic state pressure [Pa]308 REAL(dp) :: root_frac, factor !< precomputed factors309 310 311 root_frac = (2.0_dp * beta * g) / (rd * t_sl*t_sl)312 313 314 factor * ( 1.0_dp - SQRT( 1.0_dp - root_frac * z(:) ) ) &315 316 317 303 SUBROUTINE get_basic_state(z, beta, p_sl, t_sl, rd, g, p0) 304 305 REAL(wp), INTENT(IN) :: z(1:) !< height [m] 306 REAL(wp), INTENT(IN) :: beta !< logarithmic lapse rate, dT / d ln(p) [K] 307 REAL(wp), INTENT(IN) :: p_sl !< reference pressure [Pa] 308 REAL(wp), INTENT(IN) :: t_sl !< reference tempereature [K] 309 REAL(wp), INTENT(IN) :: rd !< ideal gas constant of dry air [J/kg/K] 310 REAL(wp), INTENT(IN) :: g !< acceleration of Earth's gravity [m/s^2] 311 REAL(wp), INTENT(OUT) :: p0(1:) !< COSMO basic state pressure [Pa] 312 REAL(wp) :: root_frac, factor !< precomputed factors 313 314 factor = - t_sl / beta 315 root_frac = (2.0_wp * beta * g) / (rd * t_sl*t_sl) 316 317 p0(:) = p_sl * EXP( & 318 factor * ( 1.0_wp - SQRT( 1.0_wp - root_frac * z(:) ) ) & 319 ) 320 321 END SUBROUTINE get_basic_state 318 322 319 323 … … 326 330 !> theta = T * (p_ref/p)^(R/c_p) = T * e^( R/c_p * ln(p_ref/p) ) 327 331 !------------------------------------------------------------------------------! 328 329 REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) :: t330 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: p331 REAL(dp), INTENT(IN) :: p_ref, r, cp332 REAL(dp) :: rcp333 334 335 336 337 332 SUBROUTINE potential_temperature(t, p, p_ref, r, cp) 333 REAL(wp), DIMENSION(:,:,:), INTENT(INOUT) :: t 334 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: p 335 REAL(wp), INTENT(IN) :: p_ref, r, cp 336 REAL(wp) :: rcp 337 338 rcp = r/cp 339 t(:,:,:) = t(:,:,:) * EXP( rcp * LOG(p_ref / p(:,:,:)) ) 340 341 END SUBROUTINE potential_temperature 338 342 339 343 … … 343 347 !> Compute the density in place of the given temperature (t_rho). 344 348 !------------------------------------------------------------------------------! 345 SUBROUTINE moist_density(t_rho, p, qv, rd, rv) 346 REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) :: t_rho 347 REAL(dp), DIMENSION(:,:,:), INTENT(IN) :: p, qv 348 REAL(dp), INTENT(IN) :: rd, rv 349 350 t_rho(:,:,:) = p(:,:,:) / ( & 351 (rv * qv(:,:,:) + rd * (1.0_dp - qv(:,:,:))) * t_rho(:,:,:) & 352 ) 353 354 END SUBROUTINE moist_density 355 356 357 ! Convert a real number to a string in scientific notation 358 ! showing four significant digits. 359 CHARACTER(LEN=SNAME) FUNCTION real_to_str(val, format) 360 361 REAL(dp), INTENT(IN) :: val 362 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: format 363 364 IF (PRESENT(format)) THEN 365 WRITE(real_to_str, format) val 366 ELSE 367 WRITE(real_to_str, '(E11.4)') val 368 ENDIF 369 real_to_str = ADJUSTL(real_to_str) 370 371 END FUNCTION real_to_str 349 SUBROUTINE moist_density(t_rho, p, qv, rd, rv) 350 REAL(wp), DIMENSION(:,:,:), INTENT(INOUT) :: t_rho 351 REAL(wp), DIMENSION(:,:,:), INTENT(IN) :: p, qv 352 REAL(wp), INTENT(IN) :: rd, rv 353 354 t_rho(:,:,:) = p(:,:,:) / ( & 355 (rv * qv(:,:,:) + rd * (1.0_wp - qv(:,:,:))) * t_rho(:,:,:) & 356 ) 357 358 END SUBROUTINE moist_density 359 360 !------------------------------------------------------------------------------! 361 ! Description: 362 ! ------------ 363 ! Convert a real number to a string in scientific notation showing four 364 ! significant digits. 365 !------------------------------------------------------------------------------! 366 CHARACTER(LEN=SNAME) FUNCTION real_to_str(val, format) 367 368 REAL(wp), INTENT(IN) :: val 369 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: format 370 371 IF (PRESENT( format ) ) THEN 372 WRITE( real_to_str, format ) val 373 ELSE 374 WRITE( real_to_str, '(E11.4)' ) val 375 ENDIF 376 real_to_str = ADJUSTL( real_to_str ) 377 378 END FUNCTION real_to_str 372 379 373 380 … … 377 384 !> Converts the given real value to a string 378 385 !------------------------------------------------------------------------------! 379 380 381 REAL(dp), INTENT(IN) :: val382 383 384 385 386 386 CHARACTER(LEN=16) FUNCTION real_to_str_f(val) 387 388 REAL(wp), INTENT(IN) :: val 389 390 WRITE(real_to_str_f, '(F16.8)') val 391 real_to_str_f = ADJUSTL(real_to_str_f) 392 393 END FUNCTION real_to_str_f 387 394 388 395 … … 392 399 !> Converts the given integer value to a string 393 400 !------------------------------------------------------------------------------! 394 395 396 397 398 399 400 401 401 CHARACTER(LEN=10) FUNCTION str(val) 402 403 INTEGER, INTENT(IN) :: val 404 405 WRITE(str, '(i10)') val 406 str = ADJUSTL(str) 407 408 END FUNCTION str 402 409 403 410 … … 407 414 !> If the given path is not conlcuded by a slash, add one. 408 415 !------------------------------------------------------------------------------! 409 410 411 412 413 414 415 416 417 418 419 420 416 SUBROUTINE normalize_path(path) 417 418 CHARACTER(LEN=*), INTENT(INOUT) :: path 419 INTEGER :: n 420 421 n = LEN_TRIM(path) 422 423 IF (path(n:n) .NE. '/') THEN 424 path = TRIM(path) // '/' 425 ENDIF 426 427 END SUBROUTINE 421 428 422 429 END MODULE inifor_util 423 #endif424
Note: See TracChangeset
for help on using the changeset viewer.