source: palm/trunk/UTIL/inifor/src/inifor.f90 @ 3779

Last change on this file since 3779 was 3779, checked in by eckhard, 5 years ago

inifor: bugfix: Fixes issue #815 with geostrophic wind profiles

  • Property svn:keywords set to Id
File size: 23.3 KB
RevLine 
[2696]1!> @file src/inifor.f90
2!------------------------------------------------------------------------------!
[2718]3! This file is part of the PALM model system.
[2696]4!
[2718]5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
[2696]8! version.
9!
[2718]10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
[2696]13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
[3779]17! Copyright 2017-2019 Leibniz Universitaet Hannover
18! Copyright 2017-2019 Deutscher Wetterdienst Offenbach
[2696]19!------------------------------------------------------------------------------!
20!
21! Current revisions:
22! -----------------
[3183]23!
24!
25! Former revisions:
26! -----------------
27! $Id: inifor.f90 3779 2019-03-05 11:13:35Z eckhard $
[3779]28! Average geostrophic wind components on coarse COSMO levels instead of fine PALM levels
29! Remove --debug netCDF output of internal pressure profiles
30!
31! 3680 2019-01-18 14:54:12Z knoop
[3618]32! Prefixed all INIFOR modules with inifor_
33!
34!
35! 3615 2018-12-10 07:21:03Z raasch
[3615]36! bugfix: abort replaced by inifor_abort
37!
38! 3613 2018-12-07 18:20:37Z eckhard
[3613]39! Moved version output to setup_parameters()
40!
41! 3557 2018-11-22 16:01:22Z eckhard
[3557]42! Updated documentation
43!
44! 3537 2018-11-20 10:53:14Z eckhard
[3537]45! Print version number on program start
46!
47!
48! 3456 2018-10-30 14:29:54Z eckhard
[3456]49! NetCDf output of internal arrays only with --debug option
50!
51!
52! 3401 2018-10-23 09:33:31Z eckhard
[3401]53! Re-compute geostrophic winds every time step
54!
55! 3395 2018-10-22 17:32:49Z eckhard
[3395]56! Added main loop support for computation of geostrophic winds and surface
57!     pressure
58! Cleaned up terminal output, show some meVssages only with --debug option
59!
60! 3183 2018-07-27 14:25:55Z suehring
[3182]61! Introduced new PALM grid stretching
62! Renamend initial-condition mode variable 'mode' to 'ic_mode'
63! Improved log messages
[2696]64!
65!
[3183]66! 3182 2018-07-27 13:36:03Z suehring
[2696]67! Initial revision
68!
69!
70!
71! Authors:
72! --------
[3557]73!> @author Eckhard Kadasch, (Deutscher Wetterdienst, Offenbach)
[2696]74!
75! Description:
76! ------------
77!> INIFOR is an interpolation tool for generating meteorological initialization
78!> and forcing data for the urban climate model PALM-4U. The required
79!> meteorological fields are interpolated from output data of the mesoscale
[3779]80!> model COSMO. This is the main program file.
[2696]81!------------------------------------------------------------------------------!
82 PROGRAM inifor
[3680]83#if defined ( __netcdf )
[2696]84
[3618]85    USE inifor_control
86    USE inifor_defs
87    USE inifor_grid,                                                           &
[2696]88        ONLY:  setup_parameters, setup_grids, setup_variable_tables,           &
89               setup_io_groups, fini_grids, fini_variables, fini_io_groups,    &
[3182]90               fini_file_lists, preprocess, origin_lon, origin_lat,            &
[2696]91               output_file, io_group_list, output_var_table,                   &
[3395]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
[3618]95    USE inifor_io
96    USE inifor_transform,                                                      &
[3779]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
[3618]101    USE inifor_types
[2696]102   
103    IMPLICIT NONE
104   
[3557]105    INTEGER ::  igroup !< loop index for IO groups
106    INTEGER ::  ivar   !< loop index for output variables
107    INTEGER ::  iter   !< loop index for time steps
108
109    REAL(dp), ALLOCATABLE, DIMENSION(:,:,:)     ::  output_arr !< array buffer for interpolated quantities
110    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  rho_centre !< density profile of the centre averaging domain
[3779]111    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  ug_cosmo   !< profile of the geostrophic wind in x direction on COSMO levels
112    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  vg_cosmo   !< profile of the geostrophic wind in y direction on COSMO levels
113    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  ug_palm    !< profile of the geostrophic wind in x direction interpolated onto PALM levels
114    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  vg_palm    !< profile of the geostrophic wind in y direction interpolated onto PALM levels
[3557]115    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  rho_north  !< density profile of the northern averaging domain
116    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  rho_south  !< density profile of the southern averaging domain
117    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  rho_east   !< density profile of the eastern averaging domain
118    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  rho_west   !< density profile of the western averaging domain
119    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  p_north    !< pressure profile of the northern averaging domain
120    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  p_south    !< pressure profile of the southern averaging domain
121    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  p_east     !< pressure profile of the eastern averaging domain
122    REAL(dp), ALLOCATABLE, DIMENSION(:), TARGET ::  p_west     !< pressure profile of the western averaging domain
123
124    REAL(dp), POINTER, DIMENSION(:) ::  internal_arr !< pointer to the currently processed internal array (density, pressure)
[3779]125    REAL(dp), POINTER, DIMENSION(:) ::  ug_vg_palm   !< pointer to the currently processed geostrophic wind component
[3557]126
127    TYPE(nc_var), POINTER        ::  output_var      !< pointer to the currently processed output variable
128    TYPE(io_group), POINTER      ::  group           !< pointer to the currently processed IO group
129    TYPE(container), ALLOCATABLE ::  input_buffer(:) !< buffer of the current IO group's input arrays
130
131    LOGICAL, SAVE ::  ug_vg_have_been_computed = .FALSE. !< flag for managing geostrophic wind allocation and computation
132    LOGICAL, SAVE ::  debugging_output = .TRUE.          !< flag controllging output of internal variables
[2696]133   
134!> \mainpage About INIFOR
135!>  ...
136!
137!------------------------------------------------------------------------------
138!- Section 1: Initialization
139!------------------------------------------------------------------------------
140 CALL run_control('init', 'void')
141
[3557]142!
143!-- Initialize INIFOR's parameters from command-line interface and namelists
[2696]144    CALL setup_parameters()
145
[3557]146!
147!-- Initialize all grids, including interpolation neighbours and weights
[2696]148    CALL setup_grids()
149 CALL run_control('time', 'init')
150
[3557]151!
152!-- Initialize the netCDF output file and define dimensions
[3182]153    CALL setup_netcdf_dimensions(output_file, palm_grid, cfg % start_date,    &
154                                 origin_lon, origin_lat)
[2696]155 CALL run_control('time', 'write')
156
[3557]157!
158!-- Set up the tables containing the input and output variables and set
159!-- the corresponding netCDF dimensions for each output variable
[3182]160    CALL setup_variable_tables(cfg % ic_mode)
[2696]161 CALL run_control('time', 'write')
162
[3557]163!
164!-- Add the output variables to the netCDF output file
[3456]165    CALL setup_netcdf_variables(output_file % name, output_var_table,          &
166                                cfg % debug)
[2696]167
[3182]168    CALL setup_io_groups()
[2696]169 CALL run_control('time', 'init')
170
171!------------------------------------------------------------------------------
172!- Section 2: Main loop
173!------------------------------------------------------------------------------
174    DO igroup = 1, SIZE(io_group_list)
175
176       group => io_group_list(igroup)
177       IF ( group % to_be_processed )  THEN
178         
179          DO iter = 1, group % nt 
180
181!------------------------------------------------------------------------------
182!- Section 2.1: Read and preprocess input data
183!------------------------------------------------------------------------------
184             CALL read_input_variables(group, iter, input_buffer)
185 CALL run_control('time', 'read')
186
187             CALL preprocess(group, input_buffer, cosmo_grid, iter)
188 CALL run_control('time', 'comp')
189
[3182]190             !TODO: move this assertion into 'preprocess'.
[2696]191             IF ( .NOT. ALL(input_buffer(:) % is_preprocessed .AND. .TRUE.) )  THEN
192                message = "Input buffers for group '" // TRIM(group % kind) // &
193                   "' could not be preprocessed sucessfully."
[3615]194                CALL inifor_abort('main loop', message)
[2696]195             END IF
196
197!------------------------------------------------------------------------------
198!- Section 2.2: Interpolate each output variable of the group
199!------------------------------------------------------------------------------
200             DO ivar = 1, group % nv
201
202                output_var => group % out_vars( ivar )
203
204                IF ( output_var % to_be_processed .AND.                        &
205                     iter .LE. output_var % nt )  THEN
206
207                   message = "Processing '" // TRIM(output_var % name) //      &
208                             "' (" // TRIM(output_var % kind) //               &
209                             "), iteration " // TRIM(str(iter)) //" of " //    &
210                             TRIM(str(output_var % nt))
211                   CALL report('main loop', message)
212
213                   SELECT CASE( TRIM(output_var % task) )
214
215                   CASE( 'interpolate_2d' ) 
216                   
217                      SELECT CASE( TRIM(output_var % kind) )
218                       
219                      CASE( 'init soil' )
220
221                         ALLOCATE( output_arr( 0:output_var % grid % nx,       &
222                                               0:output_var % grid % ny,       &
223                                               SIZE(output_var % grid % depths) ) )
224
225                      CASE ( 'surface forcing' )
226
227                         ALLOCATE( output_arr( 0:output_var % grid % nx,       &
228                                               0:output_var % grid % ny, 1 ) )
229
230                      CASE DEFAULT
231
[3182]232                          message = "'" // TRIM(output_var % kind) // "' is not a soil variable"
[3615]233                          CALL inifor_abort("main loop", message)
[2696]234
235                      END SELECT
236 CALL run_control('time', 'alloc')
237
238                      CALL interpolate_2d(input_buffer(output_var % input_id) % array(:,:,:), &
239                              output_arr(:,:,:), output_var % intermediate_grid, output_var)
240 CALL run_control('time', 'comp')
241
242
243                   CASE ( 'interpolate_3d' )
244
245                      ALLOCATE( output_arr( 0:output_var % grid % nx,          &
246                                            0:output_var % grid % ny,          &
[3182]247                                            1:output_var % grid % nz ) )
[2696]248
249 CALL run_control('time', 'alloc')
250                      CALL interpolate_3d(                                     &
251                         input_buffer(output_var % input_id) % array(:,:,:),   &
252                         output_arr(:,:,:),                                    &
253                         output_var % intermediate_grid,                       &
254                         output_var % grid)
255 CALL run_control('time', 'comp')
256
257                   CASE ( 'average profile' )
258
259                      ALLOCATE( output_arr( 0:output_var % grid % nx,          &
260                                            0:output_var % grid % ny,          &
[3182]261                                            1:output_var % grid % nz ) )
[2696]262 CALL run_control('time', 'alloc')
263                     
[3779]264                      CALL interp_average_profile(                             &
[2696]265                         input_buffer(output_var % input_id) % array(:,:,:),   &
[3395]266                         output_arr(0,0,:),                                    &
267                         output_var % averaging_grid)
268
269                      IF ( TRIM(output_var % name) ==                          &
270                           'surface_forcing_surface_pressure' )  THEN
271
272                         IF ( cfg % p0_is_set )  THEN
273                            output_arr(0,0,1) = p0
274                         ELSE
275                            CALL get_surface_pressure(                         &
276                               output_arr(0,0,:), rho_centre,                  &
277                               output_var % averaging_grid)
278                         END IF
279
280                      END IF
[2696]281 CALL run_control('time', 'comp')
282
[3395]283                   CASE ( 'internal profile' )
284
285                      message = "Averaging of internal profile for variable '" //&
286                         TRIM(output_var % name) // "' is not supported."
287
288                      SELECT CASE (TRIM(output_var % name))
289
290                      CASE('internal_density_centre')
[3779]291                         ALLOCATE( rho_centre( 1:cosmo_grid % nz) )
[3395]292                         internal_arr => rho_centre
293
294                      CASE('internal_density_north')
[3779]295                         ALLOCATE( rho_north( 1:cosmo_grid % nz) )
[3395]296                         internal_arr => rho_north
297
298                      CASE('internal_density_south')
[3779]299                         ALLOCATE( rho_south( 1:cosmo_grid % nz) )
[3395]300                         internal_arr => rho_south
301
302                      CASE('internal_density_east')
[3779]303                         ALLOCATE( rho_east( 1:cosmo_grid % nz) )
[3395]304                         internal_arr => rho_east
305
306                      CASE('internal_density_west')
[3779]307                         ALLOCATE( rho_west( 1:cosmo_grid % nz) )
[3395]308                         internal_arr => rho_west
309
310                      CASE('internal_pressure_north')
[3779]311                         ALLOCATE( p_north( 1:cosmo_grid % nz) )
[3395]312                         internal_arr => p_north
313
314                      CASE('internal_pressure_south')
[3779]315                         ALLOCATE( p_south( 1:cosmo_grid % nz) )
[3395]316                         internal_arr => p_south
317
318                      CASE('internal_pressure_east')
[3779]319                         ALLOCATE( p_east( 1:cosmo_grid % nz) )
[3395]320                         internal_arr => p_east
321
322                      CASE('internal_pressure_west')
[3779]323                         ALLOCATE( p_west( 1:cosmo_grid % nz) )
[3395]324                         internal_arr => p_west
325
326                      CASE DEFAULT
[3615]327                         CALL inifor_abort('main loop', message)
[3395]328
329                      END SELECT
330 CALL run_control('time', 'alloc')
331
332
[3779]333                      SELECT CASE( TRIM( output_var % name ) )
[3395]334
[3779]335                      CASE( 'internal_pressure_north',                         &
336                            'internal_pressure_south',                         &
337                            'internal_pressure_east',                          &
338                            'internal_pressure_west' )
[3395]339
[3779]340                         CALL average_pressure_perturbation(                   &
341                            input_buffer(output_var % input_id) % array(:,:,:),&
342                            internal_arr(:),                                   &
343                            cosmo_grid, output_var % averaging_grid            &
344                         )
[3395]345
[3779]346                      CASE DEFAULT
[3395]347
[3779]348                         CALL average_profile(                                 &
349                            input_buffer(output_var % input_id) % array(:,:,:),&
350                            internal_arr(:),                                   &
351                            cosmo_grid, output_var % averaging_grid            &
352                         )
[3395]353
[3779]354                      END SELECT
[3395]355
356
[3779]357!
358!--                   Output of geostrophic pressure profiles (with --debug
359!--                   option) is currently deactivated, since they are now
360!--                   defined on averaged COSMO levels instead of PALM levels
361!--                   (requires definiton of COSMO levels in netCDF output.)
362                      !IF (.TRUE.)  THEN
363                      !   ALLOCATE( output_arr(1,1,1:output_var % grid % nz) )
364                      !   output_arr(1,1,:) = internal_arr(:)
365                      !END IF
[3395]366 CALL run_control('time', 'comp')
367
[3557]368!
369!--                This case gets called twice, the first time for ug, the
370!--                second time for vg. We compute ug and vg at the first call
[3779]371!--                and keep both of them around for the second call.
[3395]372                   CASE ( 'geostrophic winds' )
373
374                      IF (.NOT. ug_vg_have_been_computed )  THEN
[3779]375                         ALLOCATE( ug_palm(output_var % grid % nz) )
376                         ALLOCATE( vg_palm(output_var % grid % nz) )
377                         ALLOCATE( ug_cosmo(cosmo_grid % nz) )
378                         ALLOCATE( vg_cosmo(cosmo_grid % nz) )
[3395]379
[3779]380                         IF ( cfg % ug_defined_by_user )  THEN
381                            ug_palm = cfg % ug
382                            vg_palm = cfg % vg
[3395]383                         ELSE
[3557]384                            CALL geostrophic_winds( p_north, p_south, p_east,  &
385                                                    p_west, rho_centre, f3,    &
386                                                    averaging_width_ew,        &
387                                                    averaging_width_ns,        &
388                                                    phi_n, lambda_n,           &
389                                                    phi_centre, lam_centre,    &
[3779]390                                                    ug_cosmo, vg_cosmo )
391
392                            CALL interpolate_1d( ug_cosmo, ug_palm,             &
393                                                 output_var % grid )
394
395                            CALL interpolate_1d( vg_cosmo, vg_palm,             &
396                                                 output_var % grid )
[3395]397                         END IF
398
399                         ug_vg_have_been_computed = .TRUE.
400
401                      END IF
402
[3557]403!
[3779]404!--                   Select output array of current geostrophic wind component
[3395]405                      SELECT CASE(TRIM(output_var % name))
406                      CASE ('ls_forcing_ug')
[3779]407                         ug_vg_palm => ug_palm
[3395]408                      CASE ('ls_forcing_vg')
[3779]409                         ug_vg_palm => vg_palm
[3395]410                      END SELECT
411
412                      ALLOCATE( output_arr(1,1,output_var % grid % nz) )
[3779]413                      output_arr(1,1,:) = ug_vg_palm(:)
[3395]414
[2696]415                   CASE ( 'average scalar' )
416
417                      ALLOCATE( output_arr(1,1,1) )
418 CALL run_control('time', 'alloc')
419                      output_arr(1,1,1) = p0
420 CALL run_control('time', 'comp')
421
[3182]422                   CASE ( 'set profile' )
[2696]423                     
[3182]424                      ALLOCATE( output_arr( 1, 1, 1:nz ) )
[2696]425 CALL run_control('time', 'alloc')
426
427                      SELECT CASE (TRIM(output_var % name))
428
[3182]429                      CASE('nudging_tau')
430                          output_arr(1, 1, :) = NUDGING_TAU
431
[2696]432                      CASE DEFAULT
433                          message = "'" // TRIM(output_var % name) //          &
434                             "' is not a valid '" // TRIM(output_var % kind) //&
435                             "' variable kind."
[3615]436                          CALL inifor_abort('main loop', message)
[2696]437                      END SELECT
438 CALL run_control('time', 'comp')
439
[3182]440                   CASE('average large-scale profile')
441                      message = "Averaging of large-scale forcing profiles " //&
442                                "has not been implemented, yet."
[3615]443                      CALL inifor_abort('main loop', message)
[3182]444
[2696]445                   CASE DEFAULT
446                      message = "Processing task '" // TRIM(output_var % task) //&
447                               "' not recognized."
[3615]448                      CALL inifor_abort('', message)
[2696]449
450                   END SELECT
451 CALL run_control('time', 'comp')
452
453!------------------------------------------------------------------------------
454!- Section 2.3: Write current time step of current variable
455!------------------------------------------------------------------------------
[3779]456!
457!--                Output of geostrophic pressure profiles (with --debug
458!--                option) is currently deactivated, since they are now
459!--                defined on averaged COSMO levels instead of PALM levels
460!--                (requires definiton of COSMO levels in netCDF output.)
461                   !IF (.NOT. output_var % is_internal .OR. debugging_output)  THEN
462
463                   IF (.NOT. output_var % is_internal)  THEN
[3395]464                      message = "Writing variable '" // TRIM(output_var%name) // "'."
465                      CALL report('main loop', message)
[3456]466                      CALL update_output(output_var, output_arr, iter,         &
467                                         output_file, cfg)
[2696]468 CALL run_control('time', 'write')
[3395]469                   END IF
[2696]470
[3395]471                   IF (ALLOCATED(output_arr))  DEALLOCATE(output_arr)
[2696]472 CALL run_control('time', 'alloc')
473
474                END IF
475
[3557]476!
477!--          output variable loop
478             END DO
[2696]479
[3401]480             ug_vg_have_been_computed = .FALSE.
[3395]481             IF ( group % kind == 'thermodynamics' )  THEN
482                DEALLOCATE( rho_centre )
[3779]483                DEALLOCATE( ug_palm )
484                DEALLOCATE( vg_palm )
485                DEALLOCATE( ug_cosmo )
486                DEALLOCATE( vg_cosmo )
487                IF ( .NOT. cfg % ug_defined_by_user )  THEN
[3395]488                   DEALLOCATE( rho_north )
489                   DEALLOCATE( rho_south )
490                   DEALLOCATE( rho_east )
491                   DEALLOCATE( rho_west )
492                   DEALLOCATE( p_north )
493                   DEALLOCATE( p_south )
494                   DEALLOCATE( p_east )
495                   DEALLOCATE( p_west )
496                END IF
497             END IF
498
[3557]499!
500!--          Keep input buffer around for averaged (radiation) and
501!--          accumulated COSMO quantities (precipitation).
[2696]502             IF ( group % kind == 'running average' .OR. &
503                  group % kind == 'accumulated' )  THEN
504             ELSE
[3395]505                CALL report('main loop', 'Deallocating input buffer', cfg % debug)
[2696]506                DEALLOCATE(input_buffer)
507             END IF
508 CALL run_control('time', 'alloc')
509
[3557]510!
511!--       time steps / input files loop
512          END DO
[2696]513
514          IF (ALLOCATED(input_buffer))  THEN
[3395]515             CALL report('main loop', 'Deallocating input buffer', cfg % debug)
[2696]516             DEALLOCATE(input_buffer)
517          END IF
518 CALL run_control('time', 'alloc')
519
520       ELSE
521
[3182]522          message = "Skipping IO group " // TRIM(str(igroup)) // " '" // TRIM(group % kind) // "'"
[2696]523          IF ( ALLOCATED(group % in_var_list) )  THEN
524              message = TRIM(message) // " with input variable '" //           &
525              TRIM(group % in_var_list(1) % name) // "'."
526          END IF
527
[3395]528          CALL report('main loop', message, cfg % debug)
[2696]529
[3557]530!
531!--    IO group % to_be_processed conditional
532       END IF
[2696]533
[3557]534!
535!-- IO groups loop
536    END DO
[2696]537
538!------------------------------------------------------------------------------
539!- Section 3: Clean up.
540!------------------------------------------------------------------------------
541    CALL fini_file_lists()
542    CALL fini_io_groups()
543    CALL fini_variables()
544    !CALL fini_grids()
545 CALL run_control('time', 'alloc')
546 CALL run_control('report', 'void')
547
[3182]548    message = "Finished writing dynamic driver '" // TRIM(output_file % name) // &
[2696]549              "' successfully."
550    CALL report('main loop', message)
551
552
[3680]553#endif
[2696]554 END PROGRAM inifor
Note: See TracBrowser for help on using the repository browser.