Changeset 4597 for palm


Ignore:
Timestamp:
Jul 9, 2020 7:21:53 PM (4 years ago)
Author:
gronemeier
Message:

Summary:

bugfix: - write unlimited dimension in netcdf4-parallel mode

  • prevent unused-variable warning if preprocessor directives are not given

new : - added optional argument to dom_def_dim to allow that dimension variables can be written

by every PE

change: - set parallel access mode to independent per default (netCDF4 output files)

Details:

data_output_module.f90:

bugfix: - write unlimited dimension in netcdf4-parallel mode
new : - added optional argument to dom_def_dim to allow that dimension variables can be written

by every PE

data_output_netcdf4_module.f90:

bugfix: - allow writing of unlimited dimensions in parallel mode

  • prevent unused-variable warning if preprocessor directives are not given

change: - set parallel access mode to independent per default
new : - dimension variables can be written by every PE

data_output_binary_module.f90:

change: update argument list of routine binary_init_dimension due to changes in interface

Location:
palm/trunk/SOURCE
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • palm/trunk/SOURCE/data_output_binary_module.f90

    r4579 r4597  
    2424! -----------------
    2525! $Id$
     26! change: update argument list of routine binary_init_dimension due to changes in interface
     27!
     28! 4579 2020-06-25 20:05:07Z gronemeier
    2629! corrected formatting to follow PALM coding standard
    2730!
     
    6871    INCLUDE "mpif.h"
    6972#endif
    70 
    7173
    7274    CHARACTER(LEN=*), PARAMETER ::  config_file_name = 'BINARY_TO_NETCDF_CONFIG'  !< name of config file
     
    8890    INTEGER ::  output_group_comm               !< MPI communicator addressing all MPI ranks which participate in output
    8991
    90     INTEGER, DIMENSION(:), ALLOCATABLE ::  files_highest_variable_id  !< highest assigned ID of
    91                                                                       !< variable or dimension in a file
    92 
    93     LOGICAL ::  binary_open_file_first_call = .TRUE.  !< true if binary_open_file routine was not
    94                                                       !< called yet
    95     LOGICAL ::  config_file_open = .FALSE.            !< true if config file is opened and not
    96                                                       !< closed
     92    INTEGER, DIMENSION(:), ALLOCATABLE ::  files_highest_variable_id  !< highest assigned ID of variable or dimension in a file
     93
     94    LOGICAL ::  binary_open_file_first_call = .TRUE.  !< true if binary_open_file routine was not called yet
     95    LOGICAL ::  config_file_open = .FALSE.            !< true if config file is opened and not closed
    9796    LOGICAL ::  print_debug_output = .FALSE.          !< if true, debug output is printed
    9897
     
    165164
    166165    INTEGER, INTENT(IN) ::  dom_global_id              !< global id within a file defined by DOM
    167     INTEGER, INTENT(IN) ::  master_output_rank         !< MPI rank executing tasks which must be
    168                                                        !< executed by a single PE
    169     INTEGER, INTENT(IN) ::  mpi_comm_of_output_group   !< MPI communicator specifying the rank group
    170                                                        !< participating in output
     166    INTEGER, INTENT(IN) ::  master_output_rank         !< MPI rank executing tasks which must be executed by a single PE
     167    INTEGER, INTENT(IN) ::  mpi_comm_of_output_group   !< MPI communicator specifying the rank group participating in output
    171168    INTEGER, INTENT(IN) ::  program_debug_output_unit  !< file unit number for debug output
    172169
     
    174171
    175172
    176     file_suffix       = file_suffix_of_output_group
    177     output_group_comm = mpi_comm_of_output_group
    178     master_rank       = master_output_rank
     173    file_suffix        = file_suffix_of_output_group
     174    output_group_comm  = mpi_comm_of_output_group
     175    master_rank        = master_output_rank
    179176
    180177    debug_output_unit  = program_debug_output_unit
    181178    print_debug_output = debug_output
    182179
    183     global_id_in_file = dom_global_id
     180    global_id_in_file  = dom_global_id
    184181
    185182 END SUBROUTINE binary_init_module
     
    204201    INTEGER, INTENT(OUT) ::  return_value  !< return value
    205202
    206     INTEGER, DIMENSION(:), ALLOCATABLE ::  files_highest_variable_id_tmp  !< temporary list of given
    207                                                                           !< variable IDs in file
     203    INTEGER, DIMENSION(:), ALLOCATABLE ::  files_highest_variable_id_tmp  !< temporary list of given variable IDs in file
    208204
    209205    LOGICAL ::  file_exists  !< true if file to be opened already exists
     
    238234!
    239235!--       Remove any pre-existing file
    240           INQUIRE( FILE=TRIM( config_file_name ) // TRIM( file_suffix ), EXIST = file_exists )
     236          INQUIRE( FILE=TRIM( config_file_name ) // TRIM( file_suffix ), EXIST=file_exists )
    241237
    242238          IF ( file_exists )  THEN
    243              CALL internal_message( 'debug', routine_name // ': Remove existing file ' //          &
     239             CALL internal_message( 'debug', routine_name //                                       &
     240                                    ': Remove existing file ' //                                   &
    244241                                    TRIM( config_file_name ) // TRIM( file_suffix ) )
    245242             !> @note Fortran2008 feature 'EXECUTE_COMMAND_LINE' not yet supported by
    246243             !>       PGI 18.10 compiler. Hence, non-standard 'SYSTEM' call must be used
    247              ! CALL EXECUTE_COMMAND_LINE(                                                &
     244             ! CALL EXECUTE_COMMAND_LINE( &
    248245             !         COMMAND='rm ' // TRIM( config_file_name ) // TRIM( file_suffix ), &
    249246             !         WAIT=.TRUE., EXITSTAT=return_value )
     
    288285
    289286       IF ( file_exists )  THEN
    290           CALL internal_message( 'debug', routine_name // ': remove existing file ' //             &
    291                                  TRIM( bin_filename ) )
     287          CALL internal_message( 'debug', routine_name //                                          &
     288                                 ': remove existing file ' // TRIM( bin_filename ) )
    292289          !> @note Fortran2008 feature 'EXECUTE_COMMAND_LINE' not yet supported by
    293290          !>       PGI 18.10 compiler. Hence, non-standard 'SYSTEM' call must be used
     
    320317!--       Extend file-variable/dimension-ID list by 1 and set it to 0 for new file.
    321318          IF ( ALLOCATED( files_highest_variable_id ) )  THEN
    322              ALLOCATE( files_highest_variable_id_tmp( SIZE( files_highest_variable_id ) ) )
     319             ALLOCATE( files_highest_variable_id_tmp(SIZE( files_highest_variable_id )) )
    323320             files_highest_variable_id_tmp = files_highest_variable_id
    324321             DEALLOCATE( files_highest_variable_id )
     
    333330       ELSE
    334331          return_value = 1
    335           CALL internal_message( 'error', routine_name // ': could not open file "' //             &
    336                                  TRIM( file_name ) // '"')
     332          CALL internal_message( 'error', routine_name //                                          &
     333                                 ': could not open file "' // TRIM( file_name ) // '"')
    337334       ENDIF
    338335
     
    349346                                    value_int16, value_int32, value_real32, value_real64,          &
    350347                                    return_value )
    351 
    352348
    353349    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'binary_write_attribute'  !< name of this routine
     
    372368    return_value = 0
    373369
    374     CALL internal_message( 'debug', TRIM( routine_name ) // ': write attribute ' //                &
    375                            TRIM( attribute_name ) )
     370    CALL internal_message( 'debug', TRIM( routine_name ) //                                        &
     371                           ': write attribute ' // TRIM( attribute_name ) )
    376372!
    377373!-- Write attribute to file
     
    418414! ------------
    419415!> Initialize dimension. Write information in file header and save dimension values to be later
    420 !< written to file.
     416!> written to file.
    421417!--------------------------------------------------------------------------------------------------!
    422418 SUBROUTINE binary_init_dimension( mode, file_id, dimension_id, variable_id, dimension_name,       &
    423                                    dimension_type, dimension_length, return_value )
     419                                   dimension_type, dimension_length, write_only_by_master_rank,    &
     420                                   return_value )
    424421
    425422    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'binary_init_dimension'  !< name of this routine
     
    436433    INTEGER, INTENT(OUT) ::  variable_id       !< variable ID
    437434
     435    LOGICAL, INTENT(IN) ::  write_only_by_master_rank  !< true if only master rank shall write variable
     436
    438437
    439438    return_value = 0
     
    441440    CALL internal_message( 'debug', routine_name // ': init dimension ' // TRIM( dimension_name ) )
    442441!
    443 !-- Check mode (not required, added for compatibility reasons only)
     442!-- Required for compatibility reasons
    444443    IF ( TRIM( mode ) == mode_binary )  CONTINUE
    445444!
     
    458457!-- Define variable associated with dimension
    459458    CALL binary_init_variable( mode, file_id, variable_id, dimension_name, dimension_type,         &
    460                                (/ dimension_id /), is_global=.TRUE., return_value=return_value )
     459                               (/ dimension_id /),                                                 &
     460                               write_only_by_master_rank=write_only_by_master_rank,                &
     461                               return_value=return_value )
     462
    461463    IF ( return_value /= 0 )  THEN
    462464       CALL internal_message( 'error', routine_name //                                             &
     
    472474!--------------------------------------------------------------------------------------------------!
    473475 SUBROUTINE binary_init_variable( mode, file_id, variable_id, variable_name, variable_type,        &
    474                                   dimension_ids, is_global, return_value )
     476                                  dimension_ids, write_only_by_master_rank, return_value )
    475477
    476478    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'binary_init_variable'  !< name of this routine
    477479
     480    CHARACTER(LEN=*),       INTENT(IN) ::  mode            !< operation mode
    478481    CHARACTER(LEN=charlen)             ::  output_string   !< output string
    479     CHARACTER(LEN=*),       INTENT(IN) ::  mode            !< operation mode
    480482    CHARACTER(LEN=charlen), INTENT(IN) ::  variable_name   !< name of variable
    481483    CHARACTER(LEN=charlen), INTENT(IN) ::  variable_type   !< data type of variable
     
    487489    INTEGER, DIMENSION(:), INTENT(IN) ::  dimension_ids  !< list of dimension IDs used by variable
    488490
    489     LOGICAL, INTENT(IN)  ::  is_global  !< true if variable is global (same on all PE)
     491    LOGICAL, INTENT(IN) ::  write_only_by_master_rank  !< true if only master rank shall write variable
    490492
    491493
     
    494496    CALL internal_message( 'debug', routine_name // ': init variable ' // TRIM( variable_name ) )
    495497!
    496 !-- Check mode (not required, added for compatibility reasons only)
     498!-- Required for compatibility reasons
    497499    IF ( TRIM( mode ) == mode_binary )  CONTINUE
    498 !
    499 !-- Check if variable is global (not required, added for compatibility reasons only)
    500     IF ( is_global )  CONTINUE
     500    IF ( write_only_by_master_rank )  CONTINUE
    501501!
    502502!-- Assign variable ID
     
    533533
    534534    WRITE( temp_string, * ) file_id
    535     CALL internal_message( 'debug', routine_name // ': finalize file definition (file_id=' //      &
    536                            TRIM( temp_string ) // ')' )
     535    CALL internal_message( 'debug', routine_name //                                                &
     536                           ': finalize file definition (file_id=' // TRIM( temp_string ) // ')' )
    537537
    538538    output_string = '*** end file header ***'
     
    547547!--------------------------------------------------------------------------------------------------!
    548548 SUBROUTINE binary_write_variable(                                                                 &
    549                            file_id, variable_id, bounds_start, value_counts, bounds_origin,        &
    550                            is_global,                                                              &
    551                            values_char_0d,   values_char_1d,   values_char_2d,   values_char_3d,   &
    552                            values_int8_0d,   values_int8_1d,   values_int8_2d,   values_int8_3d,   &
    553                            values_int16_0d,  values_int16_1d,  values_int16_2d,  values_int16_3d,  &
    554                            values_int32_0d,  values_int32_1d,  values_int32_2d,  values_int32_3d,  &
    555                            values_intwp_0d,  values_intwp_1d,  values_intwp_2d,  values_intwp_3d,  &
    556                            values_real32_0d, values_real32_1d, values_real32_2d, values_real32_3d, &
    557                            values_real64_0d, values_real64_1d, values_real64_2d, values_real64_3d, &
    558                            values_realwp_0d, values_realwp_1d, values_realwp_2d, values_realwp_3d, &
    559                            return_value )
    560 
     549               file_id, variable_id, bounds_start, value_counts, bounds_origin,                    &
     550               write_only_by_master_rank,                                                          &
     551               values_char_0d,   values_char_1d,   values_char_2d,   values_char_3d,               &
     552               values_int8_0d,   values_int8_1d,   values_int8_2d,   values_int8_3d,               &
     553               values_int16_0d,  values_int16_1d,  values_int16_2d,  values_int16_3d,              &
     554               values_int32_0d,  values_int32_1d,  values_int32_2d,  values_int32_3d,              &
     555               values_intwp_0d,  values_intwp_1d,  values_intwp_2d,  values_intwp_3d,              &
     556               values_real32_0d, values_real32_1d, values_real32_2d, values_real32_3d,             &
     557               values_real64_0d, values_real64_1d, values_real64_2d, values_real64_3d,             &
     558               values_realwp_0d, values_realwp_1d, values_realwp_2d, values_realwp_3d,             &
     559               return_value )
    561560
    562561    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'binary_write_variable'  !< name of this routine
     
    570569
    571570    INTEGER, INTENT(IN)  ::  file_id       !< file ID
     571    INTEGER, INTENT(OUT) ::  return_value  !< return value
    572572    INTEGER, INTENT(IN)  ::  variable_id   !< variable ID
    573     INTEGER, INTENT(OUT) ::  return_value  !< return value
    574573
    575574    INTEGER, DIMENSION(:), INTENT(IN) ::  bounds_origin  !< starting index of each dimension
     
    594593    INTEGER(iwp),    POINTER, CONTIGUOUS, INTENT(IN), OPTIONAL, DIMENSION(:,:,:) ::  values_intwp_3d  !< output variable
    595594
    596     LOGICAL, INTENT(IN) ::  is_global  !< true if variable is global (same on all PE)
     595    LOGICAL, INTENT(IN) ::  write_only_by_master_rank  !< true if only master rank shall write variable
    597596
    598597    REAL(KIND=4), POINTER,             INTENT(IN), OPTIONAL                   ::  values_real32_0d  !< output variable
     
    614613    WRITE( temp_string, '(": write variable ",I6," into file ",I6)' ) variable_id, file_id
    615614    CALL internal_message( 'debug', routine_name // TRIM( temp_string ) )
    616 
    617     IF ( is_global )  CONTINUE  ! reqired to prevent compiler warning
     615!
     616!-- Required for compatibility reasons
     617    IF ( write_only_by_master_rank )  CONTINUE
    618618
    619619    IF ( .NOT. ANY( value_counts == 0 ) )  THEN
     
    695695          WRITE( file_id )  values_int32_3d
    696696!
    697 !--    working-precision integer output
     697!--    Working-precision integer output
    698698       ELSEIF ( PRESENT( values_intwp_0d ) )  THEN
    699699          output_string = 'intwp'
     
    749749          WRITE( file_id )  values_real64_3d
    750750!
    751 !--    working-precision real output
     751!--    Working-precision real output
    752752       ELSEIF ( PRESENT( values_realwp_0d ) )  THEN
    753753          output_string = 'realwp'
  • palm/trunk/SOURCE/data_output_module.f90

    r4579 r4597  
    2424! -----------------
    2525! $Id$
     26! bugfix: - write unlimited dimension in netcdf4-parallel mode
     27! new   : - added optional argument to dom_def_dim to allow that dimension variables can be written
     28!           by every PE
     29!
     30! 4579 2020-06-25 20:05:07Z gronemeier
    2631! corrected formatting to follow PALM coding standard
    2732!
     
    116121
    117122    TYPE variable_type
    118        CHARACTER(LEN=charlen)                            ::  data_type = ''       !< data type
    119        CHARACTER(LEN=charlen)                            ::  name                 !< variable name
    120        INTEGER                                           ::  id = no_id           !< id within file
    121        LOGICAL                                           ::  is_global = .FALSE.  !< true if global variable
    122        CHARACTER(LEN=charlen), DIMENSION(:), ALLOCATABLE ::  dimension_names      !< list of dimension names used by variable
    123        INTEGER,                DIMENSION(:), ALLOCATABLE ::  dimension_ids        !< list of dimension ids used by variable
    124        TYPE(attribute_type),   DIMENSION(:), ALLOCATABLE ::  attributes           !< list of attributes
     123       CHARACTER(LEN=charlen) ::  data_type = ''                              !< data type
     124       CHARACTER(LEN=charlen) ::  name                                        !< variable name
     125       INTEGER                ::  id = no_id                                  !< id within file
     126       LOGICAL                ::  write_only_by_master_rank = .FALSE.         !< true if only master rank shall write variable
     127       CHARACTER(LEN=charlen), DIMENSION(:), ALLOCATABLE ::  dimension_names  !< list of dimension names used by variable
     128       INTEGER,                DIMENSION(:), ALLOCATABLE ::  dimension_ids    !< list of dimension ids used by variable
     129       TYPE(attribute_type),   DIMENSION(:), ALLOCATABLE ::  attributes       !< list of attributes
    125130    END TYPE variable_type
    126131
    127132    TYPE dimension_type
    128        CHARACTER(LEN=charlen)                     ::  data_type = ''        !< data type
    129        CHARACTER(LEN=charlen)                     ::  name                  !< dimension name
    130        INTEGER                                    ::  id = no_id            !< dimension id within file
    131        INTEGER                                    ::  length                !< length of dimension
    132        INTEGER                                    ::  length_mask           !< length of masked dimension
    133        INTEGER                                    ::  variable_id = no_id   !< associated variable id within file
    134        LOGICAL                                    ::  is_masked = .FALSE.   !< true if masked
     133       CHARACTER(LEN=charlen) ::  data_type = ''                            !< data type
     134       CHARACTER(LEN=charlen) ::  name                                      !< dimension name
     135       INTEGER                ::  id = no_id                                !< dimension id within file
     136       INTEGER                ::  length                                    !< length of dimension
     137       INTEGER                ::  length_mask                               !< length of masked dimension
     138       INTEGER                ::  variable_id = no_id                       !< associated variable id within file
     139       LOGICAL                ::  is_masked = .FALSE.                       !< true if masked
     140       LOGICAL                ::  write_only_by_master_rank = .FALSE.       !< true if only master rank shall write variable
    135141       INTEGER,         DIMENSION(2)              ::  bounds                !< lower and upper bound of dimension
    136142       INTEGER,         DIMENSION(:), ALLOCATABLE ::  masked_indices        !< list of masked indices of dimension
     
    365371!> given which is then used to fill the entire dimension.
    366372!> An optional mask can be given to mask limited dimensions.
     373!> Per default, a dimension is written to file only by the output master rank. However, this
     374!> behaviour can be changed via the optional parameter 'write_only_by_master_rank'.
    367375!> Example call:
    368376!>   - fixed dimension with 100 entries (values known):
     
    382390!>                             output_type='real32', bounds=(/1/), &
    383391!>                             values_real32=(/fill_value/) )
     392!>   - dimension values must be written by all MPI ranks later
     393!>     (e.g. the master output rank does not know all dimension values):
     394!>       status = dom_def_dim( file_name='my_output_file_name', dimension_name='my_dimension', &
     395!>                             output_type='real32', bounds=(/1,100/), &
     396!>                             values_real32=(/fill_value/), write_only_by_master_rank = .FALSE. )
    384397!>
     398!> @note The optional argument 'write_only_by_master_rank' is set true by default to reduce the
     399!>       number of file accesses. If dimension values must, however, be written by all MPI ranks
     400!>       (e.g. each rank only knows parts of the values), 'write_only_by_master_rank' must be set
     401!>       false to allow each rank to write values to the file for this dimension.
     402!>       Values must be written after definition stage via calling dom_write_var.
    385403!> @todo Convert given values into selected output_type.
    386404!--------------------------------------------------------------------------------------------------!
     
    388406                       values_int8, values_int16, values_int32, values_intwp,                      &
    389407                       values_real32, values_real64, values_realwp,                                &
    390                        mask )                                                                      &
     408                       mask, write_only_by_master_rank )                                           &
    391409             RESULT( return_value )
    392410
     
    401419    INTEGER ::  i             !< loop index
    402420    INTEGER ::  j             !< loop index
    403     INTEGER ::  ndims = 0     !< number of dimensions in file
     421    INTEGER ::  ndims         !< number of dimensions in file
    404422    INTEGER ::  return_value  !< return value
    405423
    406     INTEGER,         DIMENSION(:), INTENT(IN)           ::  bounds         !< lower and upper bound of dimension variable
    407     INTEGER(KIND=1), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_int8    !< values of dimension
    408     INTEGER(KIND=2), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_int16   !< values of dimension
    409     INTEGER(KIND=4), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_int32   !< values of dimension
    410     INTEGER(iwp),    DIMENSION(:), INTENT(IN), OPTIONAL ::  values_intwp   !< values of dimension
    411 
    412     LOGICAL,         DIMENSION(:), INTENT(IN), OPTIONAL ::  mask           !< mask of dimesion
    413 
    414     REAL(KIND=4),    DIMENSION(:), INTENT(IN), OPTIONAL ::  values_real32  !< values of dimension
    415     REAL(KIND=8),    DIMENSION(:), INTENT(IN), OPTIONAL ::  values_real64  !< values of dimension
    416     REAL(wp),        DIMENSION(:), INTENT(IN), OPTIONAL ::  values_realwp  !< values of dimension
     424    INTEGER,         DIMENSION(:), INTENT(IN)           ::  bounds        !< lower and upper bound of dimension variable
     425    INTEGER(KIND=1), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_int8   !< values of dimension
     426    INTEGER(KIND=2), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_int16  !< values of dimension
     427    INTEGER(KIND=4), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_int32  !< values of dimension
     428    INTEGER(iwp),    DIMENSION(:), INTENT(IN), OPTIONAL ::  values_intwp  !< values of dimension
     429
     430    LOGICAL, INTENT(IN), OPTIONAL ::  write_only_by_master_rank  !< true if only master rank shall write this variable
     431
     432    LOGICAL, DIMENSION(:), INTENT(IN), OPTIONAL ::  mask  !< mask of dimesion
     433
     434    REAL(KIND=4), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_real32  !< values of dimension
     435    REAL(KIND=8), DIMENSION(:), INTENT(IN), OPTIONAL ::  values_real64  !< values of dimension
     436    REAL(wp),     DIMENSION(:), INTENT(IN), OPTIONAL ::  values_realwp  !< values of dimension
    417437
    418438    TYPE(dimension_type)                            ::  dimension       !< new dimension
     
    421441
    422442    return_value = 0
     443    ndims = 0
    423444
    424445    CALL internal_message( 'debug', routine_name //                                                &
     
    429450    dimension%name      = TRIM( dimension_name )
    430451    dimension%data_type = TRIM( output_type )
     452
     453    IF ( PRESENT( write_only_by_master_rank ) )  THEN
     454       dimension%write_only_by_master_rank = write_only_by_master_rank
     455    ELSE
     456       dimension%write_only_by_master_rank = .TRUE.
     457    ENDIF
    431458!
    432459!-- Check dimension bounds and allocate dimension according to bounds
     
    692719                         return_value = 1
    693720                         CALL internal_message( 'error', routine_name //                           &
    694                                         ': file already has a variable of this name defined. ' //  &
    695                                         'Defining a dimension of the same name is not allowed ' // &
    696                                         '(dimension "' // TRIM( dimension_name ) //                &
    697                                        '", file "' // TRIM( file_name ) // '")!' )
     721                                 ': file already has a variable of this name defined. ' //         &
     722                                 'Defining a dimension of the same name is not allowed ' //        &
     723                                 '(dimension "' // TRIM( dimension_name ) //                       &
     724                                 '", file "' // TRIM( file_name ) // '")!' )
    698725                         EXIT
    699726                      ENDIF
     
    754781! ------------
    755782!> Add variable to database.
    756 !> If a variable is identical for each MPI rank, the optional argument 'is_global' should be set to
    757 !> .TRUE. This flags the variable to be a global variable and is later only written once by the
    758 !> master output rank.
    759783!> Example call:
    760784!>   dom_def_var( file_name =  'my_output_file_name', &
     
    774798!>       or
    775799!>          ALLOCATE( u(<z>,<y>,<x>) )
    776 !--------------------------------------------------------------------------------------------------!
    777  FUNCTION dom_def_var( file_name, variable_name, dimension_names, output_type, is_global )         &
     800!> @note The optional argument 'write_only_by_master_rank' can be used to reduce the number of file
     801!>       accesses. If a variable is identical on each MPI rank, setting 'write_only_by_master_rank'
     802!>       allows the underlying output modules to skip the write command if possible for MPI ranks
     803!>       other than the master output rank.
     804!>       As restrictions may apply for different output modules, it might be possible that this
     805!>       option is ignored internally. Hence, all MPI ranks must still participate in the
     806!>       dom_write_var calls in any case.
     807!--------------------------------------------------------------------------------------------------!
     808 FUNCTION dom_def_var( file_name, variable_name, dimension_names, output_type,                     &
     809                       write_only_by_master_rank )                                                 &
    778810             RESULT( return_value )
    779811
     
    792824    INTEGER ::  return_value  !< return value
    793825
    794     LOGICAL                       ::  found      !< true if requested dimension is defined in file
    795     LOGICAL, INTENT(IN), OPTIONAL ::  is_global  !< true if variable is global (same on all PE)
     826    LOGICAL                       ::  found                      !< true if requested dimension is defined in file
     827    LOGICAL, INTENT(IN), OPTIONAL ::  write_only_by_master_rank  !< true if only master rank shall write this variable
    796828
    797829    TYPE(variable_type)                            ::  variable       !< new variable
     
    815847    variable%data_type = TRIM( output_type )
    816848
    817     IF ( PRESENT( is_global ) )  THEN
    818        variable%is_global = is_global
     849    IF ( PRESENT( write_only_by_master_rank ) )  THEN
     850       variable%write_only_by_master_rank = write_only_by_master_rank
    819851    ELSE
    820        variable%is_global = .FALSE.
     852       variable%write_only_by_master_rank = .FALSE.
    821853    ENDIF
    822854!
     
    830862             return_value = 1
    831863             CALL internal_message( 'error', routine_name //                                       &
    832                           ': file already initialized. No further variable definition allowed ' // &
    833                           '(variable "' // TRIM( variable_name ) //                                &
    834                           '", file "' // TRIM( file_name ) // '")!' )
     864                     ': file already initialized. No further variable definition allowed ' //      &
     865                     '(variable "' // TRIM( variable_name ) //                                     &
     866                     '", file "' // TRIM( file_name ) // '")!' )
    835867             EXIT
    836868
     
    842874                   return_value = 1
    843875                   CALL internal_message( 'error', routine_name //                                 &
    844                                         ': file already has a dimension of this name defined. ' // &
    845                                         'Defining a variable of the same name is not allowed ' //  &
    846                                         '(variable "' // TRIM( variable_name ) //                  &
    847                                         '", file "' // TRIM( file_name ) // '")!' )
     876                           ': file already has a dimension of this name defined. ' //              &
     877                           'Defining a variable of the same name is not allowed ' //               &
     878                           '(variable "' // TRIM( variable_name ) //                               &
     879                           '", file "' // TRIM( file_name ) // '")!' )
    848880                   EXIT
    849881                ENDIF
     
    863895                      return_value = 1
    864896                      CALL internal_message( 'error', routine_name //                              &
    865                                  ': required dimension "'// TRIM( variable%dimension_names(i) ) // &
    866                                  '" for variable is not defined ' //                               &
    867                                  '(variable "' // TRIM( variable_name ) //                         &
    868                                  '", file "' // TRIM( file_name ) // '")!' )
     897                              ': required dimension "'//  TRIM( variable%dimension_names(i) ) //  &
     898                              '" for variable is not defined ' //                                  &
     899                              '(variable "' // TRIM( variable_name ) //                            &
     900                              '", file "' // TRIM( file_name ) // '")!' )
    869901                      EXIT
    870902                   ENDIF
     
    9761008    INTEGER ::  return_value  !< return value
    9771009
     1010    LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    9781011    LOGICAL                       ::  append_internal  !< same as 'append'
    979     LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    9801012
    9811013    TYPE(attribute_type) ::  attribute  !< new attribute
     
    10391071    INTEGER ::  return_value  !< return value
    10401072
     1073    LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    10411074    LOGICAL                       ::  append_internal  !< same as 'append'
    1042     LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    10431075
    10441076    TYPE(attribute_type) ::  attribute  !< new attribute
     
    11111143    INTEGER ::  return_value  !< return value
    11121144
     1145    LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    11131146    LOGICAL                       ::  append_internal  !< same as 'append'
    1114     LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    11151147
    11161148    TYPE(attribute_type) ::  attribute  !< new attribute
     
    11741206    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'dom_def_att_int32'  !< name of routine
    11751207
    1176 
    11771208    CHARACTER(LEN=*),      INTENT(IN)           ::  attribute_name          !< name of attribute
    11781209    CHARACTER(LEN=*),      INTENT(IN)           ::  file_name               !< name of file
     
    11841215    INTEGER ::  return_value  !< return value
    11851216
     1217    LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    11861218    LOGICAL                       ::  append_internal  !< same as 'append'
    1187     LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    11881219
    11891220    TYPE(attribute_type) ::  attribute  !< new attribute
     
    12541285    INTEGER ::  return_value  !< return value
    12551286
     1287    LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    12561288    LOGICAL                       ::  append_internal  !< same as 'append'
    1257     LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    12581289
    12591290    REAL(KIND=4), INTENT(IN) ::  value  !< attribute value
     
    13261357    INTEGER ::  return_value  !< return value
    13271358
     1359    LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    13281360    LOGICAL                       ::  append_internal  !< same as 'append'
    1329     LOGICAL, INTENT(IN), OPTIONAL ::  append           !< if true, append value to existing value
    13301361
    13311362    REAL(KIND=8), INTENT(IN) ::  value  !< attribute value
     
    15841615    INTEGER, DIMENSION(:),   INTENT(IN)  ::  bounds_end             !< end index per dimension of variable
    15851616    INTEGER, DIMENSION(:),   INTENT(IN)  ::  bounds_start           !< start index per dimension of variable
    1586 
    15871617    INTEGER, DIMENSION(:),   ALLOCATABLE ::  bounds_origin          !< first index of each dimension
    15881618    INTEGER, DIMENSION(:),   ALLOCATABLE ::  bounds_start_internal  !< start index per dim. for output after masking
     
    15901620    INTEGER, DIMENSION(:,:), ALLOCATABLE ::  masked_indices         !< list containing all output indices along a dimension
    15911621
    1592     LOGICAL ::  do_output  !< true if any data lies within given range of masked dimension
    1593     LOGICAL ::  is_global  !< true if variable is global
     1622    LOGICAL ::  do_output                  !< true if any data lies within given range of masked dimension
     1623    LOGICAL ::  write_only_by_master_rank  !< true if only master rank shall write variable
    15941624
    15951625    INTEGER(KIND=1), POINTER, INTENT(IN), OPTIONAL                   ::  values_int8_0d             !< output variable
     
    16871717!-- Search for variable within file
    16881718    CALL find_var_in_file( file_name, variable_name, file_format, file_id, variable_id,            &
    1689                            is_global, dimension_list, return_value=return_value  )
     1719                           write_only_by_master_rank, dimension_list, return_value=return_value  )
    16901720
    16911721    IF ( return_value == 0 )  THEN
     
    17401770!
    17411771!--    Mask and resort variable
    1742 !--    character output
     1772!--    Character output
    17431773       IF ( PRESENT( values_char_0d ) )  THEN
    17441774          values_char_0d_pointer => values_char_0d
     
    18451875                      values_int8_3d_resorted(i,j,k) = values_int8_3d(masked_indices(3,k),         &
    18461876                                                                      masked_indices(2,j),         &
    1847                                                                       masked_indices(1,i)  )
     1877                                                                      masked_indices(1,i))
    18481878                   ENDDO
    18491879                ENDDO
     
    22252255!--          Character output
    22262256             IF ( PRESENT( values_char_0d ) )  THEN
    2227                  CALL binary_write_variable( file_id, variable_id,                                 &
    2228                          bounds_start_internal, value_counts, bounds_origin, is_global,            &
    2229                         values_char_0d=values_char_0d_pointer, return_value=output_return_value )
     2257                CALL binary_write_variable( file_id, variable_id,                                  &
     2258                        bounds_start_internal, value_counts, bounds_origin,                        &
     2259                        write_only_by_master_rank, values_char_0d=values_char_0d_pointer,          &
     2260                        return_value=output_return_value )
    22302261             ELSEIF ( PRESENT( values_char_1d ) )  THEN
    22312262                CALL binary_write_variable( file_id, variable_id,                                  &
    2232                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2233                         values_char_1d=values_char_1d_pointer, return_value=output_return_value )
     2263                        bounds_start_internal, value_counts, bounds_origin,                        &
     2264                        write_only_by_master_rank, values_char_1d=values_char_1d_pointer,          &
     2265                        return_value=output_return_value )
    22342266             ELSEIF ( PRESENT( values_char_2d ) )  THEN
    22352267                CALL binary_write_variable( file_id, variable_id,                                  &
    2236                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2237                         values_char_2d=values_char_2d_pointer, return_value=output_return_value )
     2268                        bounds_start_internal, value_counts, bounds_origin,                        &
     2269                        write_only_by_master_rank, values_char_2d=values_char_2d_pointer,          &
     2270                        return_value=output_return_value )
    22382271             ELSEIF ( PRESENT( values_char_3d ) )  THEN
    22392272                CALL binary_write_variable( file_id, variable_id,                                  &
    2240                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2241                         values_char_3d=values_char_3d_pointer, return_value=output_return_value )
     2273                        bounds_start_internal, value_counts, bounds_origin,                        &
     2274                        write_only_by_master_rank, values_char_3d=values_char_3d_pointer,          &
     2275                        return_value=output_return_value )
    22422276!
    22432277!--          8bit integer output
    22442278             ELSEIF ( PRESENT( values_int8_0d ) )  THEN
    22452279                CALL binary_write_variable( file_id, variable_id,                                  &
    2246                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2247                         values_int8_0d=values_int8_0d_pointer, return_value=output_return_value )
     2280                        bounds_start_internal, value_counts, bounds_origin,                        &
     2281                        write_only_by_master_rank, values_int8_0d=values_int8_0d_pointer,          &
     2282                        return_value=output_return_value )
    22482283             ELSEIF ( PRESENT( values_int8_1d ) )  THEN
    22492284                CALL binary_write_variable( file_id, variable_id,                                  &
    2250                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2251                         values_int8_1d=values_int8_1d_pointer, return_value=output_return_value )
     2285                        bounds_start_internal, value_counts, bounds_origin,                        &
     2286                        write_only_by_master_rank, values_int8_1d=values_int8_1d_pointer,          &
     2287                        return_value=output_return_value )
    22522288             ELSEIF ( PRESENT( values_int8_2d ) )  THEN
    22532289                CALL binary_write_variable( file_id, variable_id,                                  &
    2254                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2255                         values_int8_2d=values_int8_2d_pointer, return_value=output_return_value )
     2290                        bounds_start_internal, value_counts, bounds_origin,                        &
     2291                        write_only_by_master_rank, values_int8_2d=values_int8_2d_pointer,          &
     2292                        return_value=output_return_value )
    22562293             ELSEIF ( PRESENT( values_int8_3d ) )  THEN
    22572294                CALL binary_write_variable( file_id, variable_id,                                  &
    2258                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2259                         values_int8_3d=values_int8_3d_pointer, return_value=output_return_value )
     2295                        bounds_start_internal, value_counts, bounds_origin,                        &
     2296                        write_only_by_master_rank, values_int8_3d=values_int8_3d_pointer,          &
     2297                        return_value=output_return_value )
    22602298!
    22612299!--          16bit integer output
    22622300             ELSEIF ( PRESENT( values_int16_0d ) )  THEN
    22632301                CALL binary_write_variable( file_id, variable_id,                                  &
    2264                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2265                         values_int16_0d=values_int16_0d_pointer, return_value=output_return_value )
     2302                        bounds_start_internal, value_counts, bounds_origin,                        &
     2303                        write_only_by_master_rank, values_int16_0d=values_int16_0d_pointer,        &
     2304                        return_value=output_return_value )
    22662305             ELSEIF ( PRESENT( values_int16_1d ) )  THEN
    22672306                CALL binary_write_variable( file_id, variable_id,                                  &
    2268                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2269                         values_int16_1d=values_int16_1d_pointer, return_value=output_return_value )
     2307                        bounds_start_internal, value_counts, bounds_origin,                        &
     2308                        write_only_by_master_rank, values_int16_1d=values_int16_1d_pointer,        &
     2309                        return_value=output_return_value )
    22702310             ELSEIF ( PRESENT( values_int16_2d ) )  THEN
    22712311                CALL binary_write_variable( file_id, variable_id,                                  &
    2272                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2273                         values_int16_2d=values_int16_2d_pointer, return_value=output_return_value )
     2312                        bounds_start_internal, value_counts, bounds_origin,                        &
     2313                        write_only_by_master_rank, values_int16_2d=values_int16_2d_pointer,        &
     2314                        return_value=output_return_value )
    22742315             ELSEIF ( PRESENT( values_int16_3d ) )  THEN
    22752316                CALL binary_write_variable( file_id, variable_id,                                  &
    2276                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2277                         values_int16_3d=values_int16_3d_pointer, return_value=output_return_value )
     2317                        bounds_start_internal, value_counts, bounds_origin,                        &
     2318                        write_only_by_master_rank, values_int16_3d=values_int16_3d_pointer,        &
     2319                        return_value=output_return_value )
    22782320!
    22792321!--          32bit integer output
    22802322             ELSEIF ( PRESENT( values_int32_0d ) )  THEN
    22812323                CALL binary_write_variable( file_id, variable_id,                                  &
    2282                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2283                         values_int32_0d=values_int32_0d_pointer, return_value=output_return_value )
     2324                        bounds_start_internal, value_counts, bounds_origin,                        &
     2325                        write_only_by_master_rank, values_int32_0d=values_int32_0d_pointer,        &
     2326                        return_value=output_return_value )
    22842327             ELSEIF ( PRESENT( values_int32_1d ) )  THEN
    22852328                CALL binary_write_variable( file_id, variable_id,                                  &
    2286                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2287                         values_int32_1d=values_int32_1d_pointer, return_value=output_return_value )
     2329                        bounds_start_internal, value_counts, bounds_origin,                        &
     2330                        write_only_by_master_rank, values_int32_1d=values_int32_1d_pointer,        &
     2331                        return_value=output_return_value )
    22882332             ELSEIF ( PRESENT( values_int32_2d ) )  THEN
    22892333                CALL binary_write_variable( file_id, variable_id,                                  &
    2290                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2291                         values_int32_2d=values_int32_2d_pointer, return_value=output_return_value )
     2334                        bounds_start_internal, value_counts, bounds_origin,                        &
     2335                        write_only_by_master_rank, values_int32_2d=values_int32_2d_pointer,        &
     2336                        return_value=output_return_value )
    22922337             ELSEIF ( PRESENT( values_int32_3d ) )  THEN
    22932338                CALL binary_write_variable( file_id, variable_id,                                  &
    2294                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2295                         values_int32_3d=values_int32_3d_pointer, return_value=output_return_value )
     2339                        bounds_start_internal, value_counts, bounds_origin,                        &
     2340                        write_only_by_master_rank, values_int32_3d=values_int32_3d_pointer,        &
     2341                        return_value=output_return_value )
    22962342!
    22972343!--          Working-precision integer output
    22982344             ELSEIF ( PRESENT( values_intwp_0d ) )  THEN
    22992345                CALL binary_write_variable( file_id, variable_id,                                  &
    2300                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2301                         values_intwp_0d=values_intwp_0d_pointer, return_value=output_return_value )
     2346                        bounds_start_internal, value_counts, bounds_origin,                        &
     2347                        write_only_by_master_rank, values_intwp_0d=values_intwp_0d_pointer,        &
     2348                        return_value=output_return_value )
    23022349             ELSEIF ( PRESENT( values_intwp_1d ) )  THEN
    23032350                CALL binary_write_variable( file_id, variable_id,                                  &
    2304                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2305                         values_intwp_1d=values_intwp_1d_pointer, return_value=output_return_value )
     2351                        bounds_start_internal, value_counts, bounds_origin,                        &
     2352                        write_only_by_master_rank, values_intwp_1d=values_intwp_1d_pointer,        &
     2353                        return_value=output_return_value )
    23062354             ELSEIF ( PRESENT( values_intwp_2d ) )  THEN
    23072355                CALL binary_write_variable( file_id, variable_id,                                  &
    2308                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2309                         values_intwp_2d=values_intwp_2d_pointer, return_value=output_return_value )
     2356                        bounds_start_internal, value_counts, bounds_origin,                        &
     2357                        write_only_by_master_rank, values_intwp_2d=values_intwp_2d_pointer,        &
     2358                        return_value=output_return_value )
    23102359             ELSEIF ( PRESENT( values_intwp_3d ) )  THEN
    23112360                CALL binary_write_variable( file_id, variable_id,                                  &
    2312                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2313                         values_intwp_3d=values_intwp_3d_pointer, return_value=output_return_value )
     2361                        bounds_start_internal, value_counts, bounds_origin,                        &
     2362                        write_only_by_master_rank, values_intwp_3d=values_intwp_3d_pointer,        &
     2363                        return_value=output_return_value )
    23142364!
    23152365!--          32bit real output
    23162366             ELSEIF ( PRESENT( values_real32_0d ) )  THEN
    23172367                CALL binary_write_variable( file_id, variable_id,                                  &
    2318                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2319                         values_real32_0d=values_real32_0d_pointer, return_value=output_return_value )
     2368                        bounds_start_internal, value_counts, bounds_origin,                        &
     2369                        write_only_by_master_rank, values_real32_0d=values_real32_0d_pointer,      &
     2370                        return_value=output_return_value )
    23202371             ELSEIF ( PRESENT( values_real32_1d ) )  THEN
    23212372                CALL binary_write_variable( file_id, variable_id,                                  &
    2322                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2323                         values_real32_1d=values_real32_1d_pointer, return_value=output_return_value )
     2373                        bounds_start_internal, value_counts, bounds_origin,                        &
     2374                        write_only_by_master_rank, values_real32_1d=values_real32_1d_pointer,      &
     2375                        return_value=output_return_value )
    23242376             ELSEIF ( PRESENT( values_real32_2d ) )  THEN
    23252377                CALL binary_write_variable( file_id, variable_id,                                  &
    2326                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2327                         values_real32_2d=values_real32_2d_pointer, return_value=output_return_value )
     2378                        bounds_start_internal, value_counts, bounds_origin,                        &
     2379                        write_only_by_master_rank, values_real32_2d=values_real32_2d_pointer,      &
     2380                        return_value=output_return_value )
    23282381             ELSEIF ( PRESENT( values_real32_3d ) )  THEN
    23292382                CALL binary_write_variable( file_id, variable_id,                                  &
    2330                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2331                         values_real32_3d=values_real32_3d_pointer, return_value=output_return_value )
     2383                        bounds_start_internal, value_counts, bounds_origin,                        &
     2384                        write_only_by_master_rank, values_real32_3d=values_real32_3d_pointer,      &
     2385                        return_value=output_return_value )
    23322386!
    23332387!--          64bit real output
    23342388             ELSEIF ( PRESENT( values_real64_0d ) )  THEN
    23352389                CALL binary_write_variable( file_id, variable_id,                                  &
    2336                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2337                         values_real64_0d=values_real64_0d_pointer, return_value=output_return_value )
     2390                        bounds_start_internal, value_counts, bounds_origin,                        &
     2391                        write_only_by_master_rank, values_real64_0d=values_real64_0d_pointer,      &
     2392                        return_value=output_return_value )
    23382393             ELSEIF ( PRESENT( values_real64_1d ) )  THEN
    23392394                CALL binary_write_variable( file_id, variable_id,                                  &
    2340                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2341                         values_real64_1d=values_real64_1d_pointer, return_value=output_return_value )
     2395                        bounds_start_internal, value_counts, bounds_origin,                        &
     2396                        write_only_by_master_rank, values_real64_1d=values_real64_1d_pointer,      &
     2397                        return_value=output_return_value )
    23422398             ELSEIF ( PRESENT( values_real64_2d ) )  THEN
    23432399                CALL binary_write_variable( file_id, variable_id,                                  &
    2344                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2345                         values_real64_2d=values_real64_2d_pointer, return_value=output_return_value )
     2400                        bounds_start_internal, value_counts, bounds_origin,                        &
     2401                        write_only_by_master_rank, values_real64_2d=values_real64_2d_pointer,      &
     2402                        return_value=output_return_value )
    23462403             ELSEIF ( PRESENT( values_real64_3d ) )  THEN
    23472404                CALL binary_write_variable( file_id, variable_id,                                  &
    2348                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2349                         values_real64_3d=values_real64_3d_pointer, return_value=output_return_value )
    2350 !
    2351 !--          working-precision real output
     2405                        bounds_start_internal, value_counts, bounds_origin,                        &
     2406                        write_only_by_master_rank, values_real64_3d=values_real64_3d_pointer,      &
     2407                        return_value=output_return_value )
     2408!
     2409!--          Working-precision real output
    23522410             ELSEIF ( PRESENT( values_realwp_0d ) )  THEN
    23532411                CALL binary_write_variable( file_id, variable_id,                                  &
    2354                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2355                         values_realwp_0d=values_realwp_0d_pointer, return_value=output_return_value )
     2412                        bounds_start_internal, value_counts, bounds_origin,                        &
     2413                        write_only_by_master_rank, values_realwp_0d=values_realwp_0d_pointer,      &
     2414                        return_value=output_return_value )
    23562415             ELSEIF ( PRESENT( values_realwp_1d ) )  THEN
    23572416                CALL binary_write_variable( file_id, variable_id,                                  &
    2358                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2359                         values_realwp_1d=values_realwp_1d_pointer, return_value=output_return_value )
     2417                        bounds_start_internal, value_counts, bounds_origin,                        &
     2418                        write_only_by_master_rank, values_realwp_1d=values_realwp_1d_pointer,      &
     2419                        return_value=output_return_value )
    23602420             ELSEIF ( PRESENT( values_realwp_2d ) )  THEN
    23612421                CALL binary_write_variable( file_id, variable_id,                                  &
    2362                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2363                         values_realwp_2d=values_realwp_2d_pointer, return_value=output_return_value )
     2422                        bounds_start_internal, value_counts, bounds_origin,                        &
     2423                        write_only_by_master_rank, values_realwp_2d=values_realwp_2d_pointer,      &
     2424                        return_value=output_return_value )
    23642425             ELSEIF ( PRESENT( values_realwp_3d ) )  THEN
    23652426                CALL binary_write_variable( file_id, variable_id,                                  &
    2366                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2367                         values_realwp_3d=values_realwp_3d_pointer, return_value=output_return_value )
     2427                        bounds_start_internal, value_counts, bounds_origin,                        &
     2428                        write_only_by_master_rank, values_realwp_3d=values_realwp_3d_pointer,      &
     2429                        return_value=output_return_value )
    23682430             ELSE
    23692431                return_value = 1
     
    23772439          CASE ( 'netcdf4-parallel', 'netcdf4-serial' )
    23782440!
    2379 !--          Character output
     2441!--          Character integer output
    23802442             IF ( PRESENT( values_char_0d ) )  THEN
    2381                  CALL netcdf4_write_variable( file_id, variable_id,                                &
    2382                          bounds_start_internal, value_counts, bounds_origin, is_global,            &
    2383                         values_char_0d=values_char_0d_pointer, return_value=output_return_value )
     2443                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2444                        bounds_start_internal, value_counts, bounds_origin,                        &
     2445                        write_only_by_master_rank, values_char_0d=values_char_0d_pointer,          &
     2446                        return_value=output_return_value )
    23842447             ELSEIF ( PRESENT( values_char_1d ) )  THEN
    2385                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2386                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2387                         values_char_1d=values_char_1d_pointer, return_value=output_return_value )
     2448                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2449                        bounds_start_internal, value_counts, bounds_origin,                        &
     2450                        write_only_by_master_rank, values_char_1d=values_char_1d_pointer,          &
     2451                        return_value=output_return_value )
    23882452             ELSEIF ( PRESENT( values_char_2d ) )  THEN
    2389                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2390                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2391                         values_char_2d=values_char_2d_pointer, return_value=output_return_value )
     2453                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2454                        bounds_start_internal, value_counts, bounds_origin,                        &
     2455                        write_only_by_master_rank, values_char_2d=values_char_2d_pointer,          &
     2456                        return_value=output_return_value )
    23922457             ELSEIF ( PRESENT( values_char_3d ) )  THEN
    2393                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2394                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2395                         values_char_3d=values_char_3d_pointer, return_value=output_return_value )
     2458                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2459                        bounds_start_internal, value_counts, bounds_origin,                        &
     2460                        write_only_by_master_rank, values_char_3d=values_char_3d_pointer,          &
     2461                        return_value=output_return_value )
    23962462!
    23972463!--          8bit integer output
    23982464             ELSEIF ( PRESENT( values_int8_0d ) )  THEN
    2399                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2400                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2401                         values_int8_0d=values_int8_0d_pointer, return_value=output_return_value )
     2465                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2466                        bounds_start_internal, value_counts, bounds_origin,                        &
     2467                        write_only_by_master_rank, values_int8_0d=values_int8_0d_pointer,          &
     2468                        return_value=output_return_value )
    24022469             ELSEIF ( PRESENT( values_int8_1d ) )  THEN
    2403                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2404                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2405                         values_int8_1d=values_int8_1d_pointer, return_value=output_return_value )
     2470                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2471                        bounds_start_internal, value_counts, bounds_origin,                        &
     2472                        write_only_by_master_rank, values_int8_1d=values_int8_1d_pointer,          &
     2473                        return_value=output_return_value )
    24062474             ELSEIF ( PRESENT( values_int8_2d ) )  THEN
    2407                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2408                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2409                         values_int8_2d=values_int8_2d_pointer, return_value=output_return_value )
     2475                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2476                        bounds_start_internal, value_counts, bounds_origin,                        &
     2477                        write_only_by_master_rank, values_int8_2d=values_int8_2d_pointer,          &
     2478                        return_value=output_return_value )
    24102479             ELSEIF ( PRESENT( values_int8_3d ) )  THEN
    2411                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2412                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2413                         values_int8_3d=values_int8_3d_pointer, return_value=output_return_value )
     2480                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2481                        bounds_start_internal, value_counts, bounds_origin,                        &
     2482                        write_only_by_master_rank, values_int8_3d=values_int8_3d_pointer,          &
     2483                        return_value=output_return_value )
    24142484!
    24152485!--          16bit integer output
    24162486             ELSEIF ( PRESENT( values_int16_0d ) )  THEN
    2417                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2418                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2419                         values_int16_0d=values_int16_0d_pointer, return_value=output_return_value )
     2487                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2488                        bounds_start_internal, value_counts, bounds_origin,                        &
     2489                        write_only_by_master_rank, values_int16_0d=values_int16_0d_pointer,        &
     2490                        return_value=output_return_value )
    24202491             ELSEIF ( PRESENT( values_int16_1d ) )  THEN
    2421                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2422                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2423                         values_int16_1d=values_int16_1d_pointer, return_value=output_return_value )
     2492                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2493                        bounds_start_internal, value_counts, bounds_origin,                        &
     2494                        write_only_by_master_rank, values_int16_1d=values_int16_1d_pointer,        &
     2495                        return_value=output_return_value )
    24242496             ELSEIF ( PRESENT( values_int16_2d ) )  THEN
    2425                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2426                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2427                         values_int16_2d=values_int16_2d_pointer, return_value=output_return_value )
     2497                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2498                        bounds_start_internal, value_counts, bounds_origin,                        &
     2499                        write_only_by_master_rank, values_int16_2d=values_int16_2d_pointer,        &
     2500                        return_value=output_return_value )
    24282501             ELSEIF ( PRESENT( values_int16_3d ) )  THEN
    2429                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2430                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2431                         values_int16_3d=values_int16_3d_pointer, return_value=output_return_value )
     2502                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2503                        bounds_start_internal, value_counts, bounds_origin,                        &
     2504                        write_only_by_master_rank, values_int16_3d=values_int16_3d_pointer,        &
     2505                        return_value=output_return_value )
    24322506!
    24332507!--          32bit integer output
    24342508             ELSEIF ( PRESENT( values_int32_0d ) )  THEN
    2435                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2436                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2437                         values_int32_0d=values_int32_0d_pointer, return_value=output_return_value )
     2509                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2510                        bounds_start_internal, value_counts, bounds_origin,                        &
     2511                        write_only_by_master_rank, values_int32_0d=values_int32_0d_pointer,        &
     2512                        return_value=output_return_value )
    24382513             ELSEIF ( PRESENT( values_int32_1d ) )  THEN
    2439                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2440                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2441                         values_int32_1d=values_int32_1d_pointer, return_value=output_return_value )
     2514                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2515                        bounds_start_internal, value_counts, bounds_origin,                        &
     2516                        write_only_by_master_rank, values_int32_1d=values_int32_1d_pointer,        &
     2517                        return_value=output_return_value )
    24422518             ELSEIF ( PRESENT( values_int32_2d ) )  THEN
    2443                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2444                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2445                         values_int32_2d=values_int32_2d_pointer, return_value=output_return_value )
     2519                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2520                        bounds_start_internal, value_counts, bounds_origin,                        &
     2521                        write_only_by_master_rank, values_int32_2d=values_int32_2d_pointer,        &
     2522                        return_value=output_return_value )
    24462523             ELSEIF ( PRESENT( values_int32_3d ) )  THEN
    2447                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2448                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2449                         values_int32_3d=values_int32_3d_pointer, return_value=output_return_value )
     2524                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2525                        bounds_start_internal, value_counts, bounds_origin,                        &
     2526                        write_only_by_master_rank, values_int32_3d=values_int32_3d_pointer,        &
     2527                        return_value=output_return_value )
    24502528!
    24512529!--          Working-precision integer output
    24522530             ELSEIF ( PRESENT( values_intwp_0d ) )  THEN
    2453                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2454                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2455                         values_intwp_0d=values_intwp_0d_pointer, return_value=output_return_value )
     2531                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2532                        bounds_start_internal, value_counts, bounds_origin,                        &
     2533                        write_only_by_master_rank, values_intwp_0d=values_intwp_0d_pointer,        &
     2534                        return_value=output_return_value )
    24562535             ELSEIF ( PRESENT( values_intwp_1d ) )  THEN
    2457                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2458                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2459                         values_intwp_1d=values_intwp_1d_pointer, return_value=output_return_value )
     2536                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2537                        bounds_start_internal, value_counts, bounds_origin,                        &
     2538                        write_only_by_master_rank, values_intwp_1d=values_intwp_1d_pointer,        &
     2539                        return_value=output_return_value )
    24602540             ELSEIF ( PRESENT( values_intwp_2d ) )  THEN
    2461                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2462                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2463                         values_intwp_2d=values_intwp_2d_pointer, return_value=output_return_value )
     2541                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2542                        bounds_start_internal, value_counts, bounds_origin,                        &
     2543                        write_only_by_master_rank, values_intwp_2d=values_intwp_2d_pointer,        &
     2544                        return_value=output_return_value )
    24642545             ELSEIF ( PRESENT( values_intwp_3d ) )  THEN
    2465                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2466                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2467                         values_intwp_3d=values_intwp_3d_pointer, return_value=output_return_value )
     2546                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2547                        bounds_start_internal, value_counts, bounds_origin,                        &
     2548                        write_only_by_master_rank, values_intwp_3d=values_intwp_3d_pointer,        &
     2549                        return_value=output_return_value )
    24682550!
    24692551!--          32bit real output
    24702552             ELSEIF ( PRESENT( values_real32_0d ) )  THEN
    2471                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2472                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2473                         values_real32_0d=values_real32_0d_pointer, return_value=output_return_value )
     2553                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2554                        bounds_start_internal, value_counts, bounds_origin,                        &
     2555                        write_only_by_master_rank, values_real32_0d=values_real32_0d_pointer,      &
     2556                        return_value=output_return_value )
    24742557             ELSEIF ( PRESENT( values_real32_1d ) )  THEN
    2475                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2476                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2477                         values_real32_1d=values_real32_1d_pointer, return_value=output_return_value )
     2558                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2559                        bounds_start_internal, value_counts, bounds_origin,                        &
     2560                        write_only_by_master_rank, values_real32_1d=values_real32_1d_pointer,      &
     2561                        return_value=output_return_value )
    24782562             ELSEIF ( PRESENT( values_real32_2d ) )  THEN
    2479                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2480                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2481                         values_real32_2d=values_real32_2d_pointer, return_value=output_return_value )
     2563                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2564                        bounds_start_internal, value_counts, bounds_origin,                        &
     2565                        write_only_by_master_rank, values_real32_2d=values_real32_2d_pointer,      &
     2566                        return_value=output_return_value )
    24822567             ELSEIF ( PRESENT( values_real32_3d ) )  THEN
    2483                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2484                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2485                         values_real32_3d=values_real32_3d_pointer, return_value=output_return_value )
     2568                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2569                        bounds_start_internal, value_counts, bounds_origin,                        &
     2570                        write_only_by_master_rank, values_real32_3d=values_real32_3d_pointer,      &
     2571                        return_value=output_return_value )
    24862572!
    24872573!--          64bit real output
    24882574             ELSEIF ( PRESENT( values_real64_0d ) )  THEN
    2489                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2490                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2491                         values_real64_0d=values_real64_0d_pointer, return_value=output_return_value )
     2575                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2576                        bounds_start_internal, value_counts, bounds_origin,                        &
     2577                        write_only_by_master_rank, values_real64_0d=values_real64_0d_pointer,      &
     2578                        return_value=output_return_value )
    24922579             ELSEIF ( PRESENT( values_real64_1d ) )  THEN
    2493                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2494                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2495                         values_real64_1d=values_real64_1d_pointer, return_value=output_return_value )
     2580                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2581                        bounds_start_internal, value_counts, bounds_origin,                        &
     2582                        write_only_by_master_rank, values_real64_1d=values_real64_1d_pointer,      &
     2583                        return_value=output_return_value )
    24962584             ELSEIF ( PRESENT( values_real64_2d ) )  THEN
    2497                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2498                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2499                         values_real64_2d=values_real64_2d_pointer, return_value=output_return_value )
     2585                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2586                        bounds_start_internal, value_counts, bounds_origin,                        &
     2587                        write_only_by_master_rank, values_real64_2d=values_real64_2d_pointer,      &
     2588                        return_value=output_return_value )
    25002589             ELSEIF ( PRESENT( values_real64_3d ) )  THEN
    2501                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2502                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2503                         values_real64_3d=values_real64_3d_pointer, return_value=output_return_value )
    2504 !
    2505 !--          working-precision real output
     2590                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2591                        bounds_start_internal, value_counts, bounds_origin,                        &
     2592                        write_only_by_master_rank, values_real64_3d=values_real64_3d_pointer,      &
     2593                        return_value=output_return_value )
     2594!
     2595!--          Working-precision real output
    25062596             ELSEIF ( PRESENT( values_realwp_0d ) )  THEN
    2507                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2508                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2509                         values_realwp_0d=values_realwp_0d_pointer, return_value=output_return_value )
     2597                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2598                        bounds_start_internal, value_counts, bounds_origin,                        &
     2599                        write_only_by_master_rank, values_realwp_0d=values_realwp_0d_pointer,      &
     2600                        return_value=output_return_value )
    25102601             ELSEIF ( PRESENT( values_realwp_1d ) )  THEN
    2511                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2512                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2513                         values_realwp_1d=values_realwp_1d_pointer, return_value=output_return_value )
     2602                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2603                        bounds_start_internal, value_counts, bounds_origin,                        &
     2604                        write_only_by_master_rank, values_realwp_1d=values_realwp_1d_pointer,      &
     2605                        return_value=output_return_value )
    25142606             ELSEIF ( PRESENT( values_realwp_2d ) )  THEN
    2515                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2516                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2517                         values_realwp_2d=values_realwp_2d_pointer, return_value=output_return_value )
     2607                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2608                        bounds_start_internal, value_counts, bounds_origin,                        &
     2609                        write_only_by_master_rank, values_realwp_2d=values_realwp_2d_pointer,      &
     2610                        return_value=output_return_value )
    25182611             ELSEIF ( PRESENT( values_realwp_3d ) )  THEN
    2519                 CALL netcdf4_write_variable( file_id, variable_id,                                 &
    2520                         bounds_start_internal, value_counts, bounds_origin, is_global,             &
    2521                         values_realwp_3d=values_realwp_3d_pointer, return_value=output_return_value )
     2612                CALL netcdf4_write_variable( TRIM( file_format(9:) ), file_id, variable_id,        &
     2613                        bounds_start_internal, value_counts, bounds_origin,                        &
     2614                        write_only_by_master_rank, values_realwp_3d=values_realwp_3d_pointer,      &
     2615                        return_value=output_return_value )
    25222616             ELSE
    25232617                return_value = 1
     
    25852679
    25862680             CASE ( 'netcdf4-parallel', 'netcdf4-serial' )
    2587                 CALL netcdf4_finalize( files(f)%id, output_return_value )
     2681                CALL netcdf4_finalize( TRIM( files(f)%format(9:) ), files(f)%id,                   &
     2682                                       output_return_value )
    25882683
    25892684             CASE DEFAULT
     
    28532948                return_value = 1
    28542949                CALL internal_message( 'error',                                                    &
    2855                                     routine_name //                                                &
    2856                                     ': requested dimension/variable "' // TRIM( variable_name ) // &
    2857                                     '" for attribute "' // TRIM( attribute%name ) //               &
    2858                                     '" does not exist in file "' // TRIM( file_name ) // '"' )
     2950                        routine_name //                                                            &
     2951                        ': requested dimension/variable "' // TRIM( variable_name ) //            &
     2952                        '" for attribute "' // TRIM( attribute%name ) //                           &
     2953                        '" does not exist in file "' // TRIM( file_name ) // '"' )
    28592954             ENDIF
    28602955
     
    29483043          DO  i = 1, nvars
    29493044             dimension_is_used(d) =                                                                &
    2950                          ANY( files(f)%dimensions(d)%name == files(f)%variables(i)%dimension_names )
     3045                ANY( files(f)%dimensions(d)%name == files(f)%variables(i)%dimension_names )
    29513046             IF ( dimension_is_used(d) )  EXIT
    29523047          ENDDO
     
    30643159                                       file%dimensions(d)%id, file%dimensions(d)%name,             &
    30653160                                       file%dimensions(d)%data_type, file%dimensions(d)%length,    &
    3066                                        file%dimensions(d)%variable_id, return_value )
     3161                                       file%dimensions(d)%variable_id,                             &
     3162                                       file%dimensions(d)%write_only_by_master_rank, return_value )
    30673163
    30683164          ELSE
     
    30703166!--          Initialize masked dimension
    30713167             CALL init_file_dimension( file%format, file%id, file%name,                            &
    3072                                      file%dimensions(d)%id, file%dimensions(d)%name,               &
    3073                                      file%dimensions(d)%data_type, file%dimensions(d)%length_mask, &
    3074                                      file%dimensions(d)%variable_id, return_value )
     3168                     file%dimensions(d)%id, file%dimensions(d)%name,                               &
     3169                     file%dimensions(d)%data_type, file%dimensions(d)%length_mask,                 &
     3170                     file%dimensions(d)%variable_id,                                               &
     3171                     file%dimensions(d)%write_only_by_master_rank, return_value )
    30753172
    30763173          ENDIF
     
    31043201                     file%variables(d)%id, file%variables(d)%name, file%variables(d)%data_type,    &
    31053202                     file%variables(d)%dimension_ids,                                              &
    3106                      file%variables(d)%is_global, return_value )
     3203                     file%variables(d)%write_only_by_master_rank, return_value )
    31073204
    31083205             IF ( return_value == 0  .AND.  ALLOCATED( file%variables(d)%attributes ) )  THEN
     
    31343231 SUBROUTINE init_file_dimension( file_format, file_id, file_name,                                  &
    31353232                                 dimension_id, dimension_name, dimension_type, dimension_length,   &
    3136                                  variable_id, return_value )
     3233                                 variable_id, write_only_by_master_rank, return_value )
    31373234
    31383235    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'init_file_dimension'  !< file format chosen for file
     
    31503247    INTEGER, INTENT(OUT) ::  variable_id          !< associated variable ID
    31513248
     3249    LOGICAL, INTENT(IN)  ::  write_only_by_master_rank  !< true if only master rank shall write variable
     3250
    31523251
    31533252    return_value = 0
     
    31613260       CASE ( 'binary' )
    31623261          CALL binary_init_dimension( 'binary', file_id, dimension_id, variable_id,                &
    3163                                        dimension_name, dimension_type, dimension_length,           &
    3164                                        return_value=output_return_value )
     3262                  dimension_name, dimension_type, dimension_length, write_only_by_master_rank,     &
     3263                  return_value=output_return_value )
    31653264
    31663265       CASE ( 'netcdf4-serial' )
    31673266          CALL netcdf4_init_dimension( 'serial', file_id, dimension_id, variable_id,               &
    3168                                        dimension_name, dimension_type, dimension_length,           &
    3169                                        return_value=output_return_value )
     3267                  dimension_name, dimension_type, dimension_length, write_only_by_master_rank,     &
     3268                  return_value=output_return_value )
    31703269
    31713270       CASE ( 'netcdf4-parallel' )
    31723271          CALL netcdf4_init_dimension( 'parallel', file_id, dimension_id, variable_id,             &
    3173                                        dimension_name, dimension_type, dimension_length,           &
    3174                                        return_value=output_return_value )
     3272                  dimension_name, dimension_type, dimension_length, write_only_by_master_rank,     &
     3273                  return_value=output_return_value )
    31753274
    31763275       CASE DEFAULT
     
    31973296 SUBROUTINE init_file_variable( file_format, file_id, file_name,                                   &
    31983297                                variable_id, variable_name, variable_type, dimension_ids,          &
    3199                                 is_global, return_value )
     3298                                write_only_by_master_rank, return_value )
    32003299
    32013300    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'init_file_variable'  !< file format chosen for file
     
    32133312    INTEGER, DIMENSION(:), INTENT(IN) ::  dimension_ids  !< list of dimension IDs used by variable
    32143313
    3215     LOGICAL, INTENT(IN)  ::  is_global  !< true if variable is global
     3314    LOGICAL, INTENT(IN)  ::  write_only_by_master_rank  !< true if only master rank shall write variable
    32163315
    32173316
     
    32263325       CASE ( 'binary' )
    32273326          CALL binary_init_variable( 'binary', file_id, variable_id, variable_name,                &
    3228                   variable_type, dimension_ids, is_global, return_value=output_return_value )
     3327                  variable_type, dimension_ids, write_only_by_master_rank,                         &
     3328                  return_value=output_return_value )
    32293329
    32303330       CASE ( 'netcdf4-serial' )
    32313331          CALL netcdf4_init_variable( 'serial', file_id, variable_id, variable_name,               &
    3232                   variable_type, dimension_ids, is_global, return_value=output_return_value )
     3332                  variable_type, dimension_ids, write_only_by_master_rank,                         &
     3333                  return_value=output_return_value )
    32333334
    32343335       CASE ( 'netcdf4-parallel' )
    32353336          CALL netcdf4_init_variable( 'parallel', file_id, variable_id, variable_name,             &
    3236                   variable_type, dimension_ids, is_global, return_value=output_return_value )
     3337                  variable_type, dimension_ids, write_only_by_master_rank,                         &
     3338                  return_value=output_return_value )
    32373339
    32383340       CASE DEFAULT
     
    32683370
    32693371    INTEGER, INTENT(IN) ::  file_id              !< file ID
     3372    INTEGER             ::  return_value         !< return value
    32703373    INTEGER             ::  output_return_value  !< return value of a called output routine
    3271     INTEGER             ::  return_value         !< return value
    32723374    INTEGER, INTENT(IN) ::  variable_id          !< variable ID
    32733375
     
    33353437
    33363438             CASE( 'char' )
    3337                 CALL netcdf4_write_attribute( file_id=file_id, variable_id=variable_id,            &
    3338                         attribute_name=attribute%name, value_char=attribute%value_char,            &
    3339                         return_value=output_return_value )
     3439                CALL netcdf4_write_attribute( mode=file_format(9:), file_id=file_id,               &
     3440                        variable_id=variable_id, attribute_name=attribute%name,                    &
     3441                        value_char=attribute%value_char, return_value=output_return_value )
    33403442
    33413443             CASE( 'int8' )
    3342                 CALL netcdf4_write_attribute( file_id=file_id, variable_id=variable_id,            &
    3343                         attribute_name=attribute%name, value_int8=attribute%value_int8,            &
    3344                         return_value=output_return_value )
     3444                CALL netcdf4_write_attribute( mode=file_format(9:), file_id=file_id,               &
     3445                        variable_id=variable_id, attribute_name=attribute%name,                    &
     3446                        value_int8=attribute%value_int8, return_value=output_return_value )
    33453447
    33463448             CASE( 'int16' )
    3347                 CALL netcdf4_write_attribute( file_id=file_id, variable_id=variable_id,            &
    3348                         attribute_name=attribute%name, value_int16=attribute%value_int16,          &
    3349                         return_value=output_return_value )
     3449                CALL netcdf4_write_attribute( mode=file_format(9:), file_id=file_id,               &
     3450                        variable_id=variable_id, attribute_name=attribute%name,                    &
     3451                        value_int16=attribute%value_int16, return_value=output_return_value )
    33503452
    33513453             CASE( 'int32' )
    3352                 CALL netcdf4_write_attribute( file_id=file_id, variable_id=variable_id,            &
    3353                         attribute_name=attribute%name, value_int32=attribute%value_int32,          &
    3354                         return_value=output_return_value )
     3454                CALL netcdf4_write_attribute( mode=file_format(9:), file_id=file_id,               &
     3455                        variable_id=variable_id, attribute_name=attribute%name,                    &
     3456                        value_int32=attribute%value_int32, return_value=output_return_value )
    33553457
    33563458             CASE( 'real32' )
    3357                 CALL netcdf4_write_attribute( file_id=file_id, variable_id=variable_id,            &
    3358                         attribute_name=attribute%name, value_real32=attribute%value_real32,        &
    3359                         return_value=output_return_value )
     3459                CALL netcdf4_write_attribute( mode=file_format(9:), file_id=file_id,               &
     3460                        variable_id=variable_id, attribute_name=attribute%name,                    &
     3461                        value_real32=attribute%value_real32, return_value=output_return_value )
    33603462
    33613463             CASE( 'real64' )
    3362                 CALL netcdf4_write_attribute( file_id=file_id, variable_id=variable_id,            &
    3363                         attribute_name=attribute%name, value_real64=attribute%value_real64,        &
    3364                         return_value=output_return_value )
     3464                CALL netcdf4_write_attribute( mode=file_format(9:), file_id=file_id,               &
     3465                        variable_id=variable_id, attribute_name=attribute%name,                    &
     3466                        value_real64=attribute%value_real64, return_value=output_return_value )
    33653467
    33663468             CASE DEFAULT
     
    34083510    INTEGER, INTENT(OUT) ::  return_value  !< return value
    34093511
    3410     LOGICAL ::  found = .FALSE. !< true if dimension required by variable was found in dimension list
     3512    LOGICAL ::  found !< true if dimension required by variable was found in dimension list
    34113513
    34123514    TYPE(dimension_type), DIMENSION(:), INTENT(IN) ::  dimensions  !< list of dimensions in file
     
    34153517
    34163518
    3417     return_value  = 0
     3519    return_value = 0
     3520    found = .FALSE.
    34183521    ndims = SIZE( dimensions )
    34193522    nvars = SIZE( variables )
     
    34733576
    34743577       CASE ( 'netcdf4-parallel', 'netcdf4-serial' )
    3475           CALL netcdf4_stop_file_header_definition( file_id, output_return_value )
     3578          CALL netcdf4_stop_file_header_definition( file_format(9:), file_id, output_return_value )
    34763579
    34773580       CASE DEFAULT
     
    35003603!--------------------------------------------------------------------------------------------------!
    35013604 SUBROUTINE find_var_in_file( file_name, variable_name, file_format, file_id, variable_id,         &
    3502                               is_global, dimensions, return_value )
     3605                              write_only_by_master_rank, dimensions, return_value )
    35033606
    35043607    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'find_var_in_file'  !< name of routine
     
    35173620    INTEGER, DIMENSION(:), ALLOCATABLE ::  dimension_ids  !< list of dimension IDs used by variable
    35183621
    3519     LOGICAL              ::  found      !< true if requested variable found in requested file
    3520     LOGICAL, INTENT(OUT) ::  is_global  !< true if variable is global
     3622    LOGICAL              ::  found                      !< true if requested variable found in requested file
     3623    LOGICAL, INTENT(OUT) ::  write_only_by_master_rank  !< true if only master rank shall write variable
    35213624
    35223625    TYPE(dimension_type), DIMENSION(:), ALLOCATABLE, INTENT(OUT) ::  dimensions  !< list of dimensions used by variable
     
    35463649             IF ( TRIM( variable_name ) == TRIM( files(f)%variables(d)%name ) )  THEN
    35473650
    3548                 variable_id    = files(f)%variables(d)%id
    3549                 is_global = files(f)%variables(d)%is_global
     3651                variable_id = files(f)%variables(d)%id
     3652                write_only_by_master_rank = files(f)%variables(d)%write_only_by_master_rank
    35503653
    35513654                ALLOCATE( dimension_ids(SIZE( files(f)%variables(d)%dimension_ids )) )
     
    35783681                IF ( TRIM( variable_name ) == TRIM( files(f)%dimensions(d)%name ) )  THEN
    35793682
    3580                    variable_id    = files(f)%dimensions(d)%variable_id
    3581                    is_global = .TRUE.
     3683                   variable_id = files(f)%dimensions(d)%variable_id
     3684                   write_only_by_master_rank = files(f)%dimensions(d)%write_only_by_master_rank
    35823685
    35833686                   ALLOCATE( dimensions(1) )
     
    37413844
    37423845    INTEGER, PARAMETER ::  indent_depth = 3        !< space per indentation
    3743     INTEGER, PARAMETER ::  max_keyname_length = 6  !< length of longest key name
     3846    INTEGER, PARAMETER ::  max_keyname_length = 8  !< length of longest key name
    37443847
    37453848    CHARACTER(LEN=50) ::  write_format1  !< format for write statements
     
    38053908    SUBROUTINE print_attributes( indent_level, attributes )
    38063909
    3807        INTEGER, PARAMETER  ::  max_keyname_length = 6  !< length of longest key name
     3910       INTEGER, PARAMETER ::  max_keyname_length = 6  !< length of longest key name
    38083911
    38093912       CHARACTER(LEN=50) ::  write_format1  !< format for write statements
     
    38653968    SUBROUTINE print_dimensions( indent_level, dimensions )
    38663969
    3867        INTEGER, PARAMETER  ::  max_keyname_length = 15  !< length of longest key name
     3970       INTEGER, PARAMETER ::  max_keyname_length = 26  !< length of longest key name
    38683971
    38693972       CHARACTER(LEN=50) ::  write_format1  !< format for write statements
     
    39004003          WRITE( debug_output_unit, TRIM( write_format2 ) // ',I7)' )                              &
    39014004             'id', dimensions(i)%id
     4005          WRITE( debug_output_unit, TRIM( write_format2 ) // ',L1)' )                              &
     4006             'write only by master rank', dimensions(i)%write_only_by_master_rank
    39024007          WRITE( debug_output_unit, TRIM( write_format2 ) // ',I7)' )                              &
    39034008             'length', dimensions(i)%length
     
    40804185    SUBROUTINE print_variables( indent_level, variables )
    40814186
    4082        INTEGER, PARAMETER  ::  max_keyname_length = 16  !< length of longest key name
     4187       INTEGER, PARAMETER ::  max_keyname_length = 26  !< length of longest key name
    40834188
    40844189       CHARACTER(LEN=50) ::  write_format1  !< format for write statements
     
    41114216             'id', variables(i)%id
    41124217          WRITE( debug_output_unit, TRIM( write_format2 ) // ',L1)' )                              &
    4113              'is global', variables(i)%is_global
     4218             'write only by master rank', variables(i)%write_only_by_master_rank
    41144219
    41154220          WRITE( debug_output_unit, TRIM( write_format2 ) // ',A)', ADVANCE='no' )                 &
  • palm/trunk/SOURCE/data_output_netcdf4_module.f90

    r4579 r4597  
    2424! -----------------
    2525! $Id$
     26! bugfix: - allow writing of unlimited dimensions in parallel mode
     27!         - prevent unused-variable warning if preprocessor directives are not given
     28! change: - set parallel access mode to independent per default
     29! new   : - dimension variables can be written by every PE
     30!
     31! 4579 2020-06-25 20:05:07Z gronemeier
    2632! corrected formatting to follow PALM coding standard
    2733!
     
    5359!> NetCDF output module to write data to NetCDF files.
    5460!> This is either done in parallel mode via parallel NetCDF4 I/O or in serial mode only by PE0.
     61!>
     62!> @bug 'mode' is not always checked. If a routine is called with an unknown mode (e.g. a typo),
     63!>      this does not throw any error.
    5564!--------------------------------------------------------------------------------------------------!
    5665 MODULE data_output_netcdf4_module
     
    8291    INTEGER ::  global_id_in_file = -1  !< value of global ID within a file
    8392    INTEGER ::  master_rank             !< master rank for tasks to be executed by single PE only
     93    INTEGER ::  my_rank                 !< MPI rank of processor
    8494    INTEGER ::  output_group_comm       !< MPI communicator addressing all MPI ranks which participate in output
    8595
     
    150160                                 program_debug_output_unit, debug_output, dom_global_id )
    151161
     162    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'netcdf4_init_module'  !< name of this routine
     163
    152164    CHARACTER(LEN=*), INTENT(IN) ::  file_suffix_of_output_group  !> file-name suffix added to each file;
    153165                                                                  !> must be unique for each output group
     
    157169    INTEGER, INTENT(IN) ::  mpi_comm_of_output_group   !< MPI communicator specifying the rank group participating in output
    158170    INTEGER, INTENT(IN) ::  program_debug_output_unit  !< file unit number for debug output
     171    INTEGER             ::  return_value               !< return value
    159172
    160173    LOGICAL, INTENT(IN) ::  debug_output  !< if true, debug output is printed
     
    165178    master_rank = master_output_rank
    166179
     180#if defined( __parallel )
     181    CALL MPI_COMM_RANK( output_group_comm, my_rank, return_value )
     182    IF ( return_value /= 0 )  THEN
     183       CALL internal_message( 'error', routine_name // ': MPI_COMM_RANK error' )
     184    ENDIF
     185#else
     186    my_rank = master_rank
     187    return_value = 0
     188!
     189!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     190    IF ( .FALSE. )  CALL internal_message( 'debug', routine_name // ': dummy message' )
     191#endif
     192
    167193    debug_output_unit = program_debug_output_unit
    168194    print_debug_output = debug_output
     
    185211
    186212    INTEGER, INTENT(OUT) ::  file_id       !< file ID
    187     INTEGER              ::  my_rank       !< MPI rank of processor
    188213    INTEGER              ::  nc_stat       !< netcdf return value
    189214    INTEGER, INTENT(OUT) ::  return_value  !< return value
     
    199224
    200225#if defined( __netcdf4 )
    201 #if defined( __parallel )
    202        CALL MPI_COMM_RANK( output_group_comm, my_rank, return_value )
    203        IF ( return_value /= 0 )  THEN
    204           CALL internal_message( 'error', routine_name // ': MPI_COMM_RANK error' )
    205        ENDIF
    206        IF ( my_rank /= master_rank )  THEN
    207           return_value = 1
    208           CALL internal_message( 'error', routine_name //                                          &
    209                                  ': trying to define a NetCDF file in serial mode by an MPI ' //   &
    210                                  'rank other than the master output rank. Serial NetCDF ' //       &
    211                                  'files can only be defined by the master output rank!' )
    212        ENDIF
    213 #else
    214        my_rank = master_rank
    215        return_value = 0
    216 #endif
    217 
    218        IF ( return_value == 0 )                                                                    &
    219           nc_stat = NF90_CREATE( TRIM( file_name ) // TRIM( file_suffix ),                         &
    220                                  IOR( NF90_NOCLOBBER, NF90_NETCDF4 ), file_id )
     226
     227       IF ( return_value == 0 )  THEN
     228          IF ( my_rank == master_rank )  THEN
     229             nc_stat = NF90_CREATE( TRIM( file_name ) // TRIM( file_suffix ),                      &
     230                                    IOR( NF90_NOCLOBBER, NF90_NETCDF4 ),                           &
     231                                    file_id )
     232          ELSE
     233             nc_stat = 0
     234          ENDIF
     235       ENDIF
    221236#else
    222237       nc_stat = 0
     
    245260       nc_stat = 0
    246261       return_value = 1
    247        CALL internal_message( 'error', routine_name // ': selected mode "' //                      &
    248                                        TRIM( mode ) // '" must be either "' //                     &
    249                                        mode_serial // '" or "' // mode_parallel // '"' )
     262       CALL internal_message( 'error', routine_name //                                             &
     263                              ': selected mode "' // TRIM( mode ) // '" must be either "' //       &
     264                              mode_serial // '" or "' // mode_parallel // '"' )
    250265    ENDIF
    251266
     
    266281!> Write attribute to netcdf file.
    267282!--------------------------------------------------------------------------------------------------!
    268  SUBROUTINE netcdf4_write_attribute( file_id, variable_id, attribute_name,                         &
     283 SUBROUTINE netcdf4_write_attribute( mode, file_id, variable_id, attribute_name,                   &
    269284                                     value_char, value_int8, value_int16, value_int32,             &
    270285                                     value_real32, value_real64, return_value )
     
    273288
    274289    CHARACTER(LEN=*), INTENT(IN)           ::  attribute_name  !< name of attribute
     290    CHARACTER(LEN=*), INTENT(IN)           ::  mode            !< operation mode (either parallel or serial)
    275291    CHARACTER(LEN=*), INTENT(IN), OPTIONAL ::  value_char      !< value of attribute
    276292
     
    292308    return_value = 0
    293309
    294     IF ( variable_id == global_id_in_file )  THEN
    295        target_id = NF90_GLOBAL
    296     ELSE
    297        target_id = variable_id
    298     ENDIF
    299 
    300     CALL internal_message( 'debug', routine_name //                                                &
    301                            ': write attribute "' // TRIM( attribute_name ) // '"' )
    302 
    303     IF ( PRESENT( value_char ) )  THEN
    304        nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), TRIM( value_char ) )
    305     ELSEIF ( PRESENT( value_int8 ) )  THEN
    306        nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_int8 )
    307     ELSEIF ( PRESENT( value_int16 ) )  THEN
    308        nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_int16 )
    309     ELSEIF ( PRESENT( value_int32 ) )  THEN
    310        nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_int32 )
    311     ELSEIF ( PRESENT( value_real32 ) )  THEN
    312        nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_real32 )
    313     ELSEIF ( PRESENT( value_real64 ) )  THEN
    314        nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_real64 )
    315     ELSE
    316        return_value = 1
    317        CALL internal_message( 'error', routine_name //                                             &
    318                               ': no value given for attribute "' // TRIM( attribute_name ) // '"' )
    319     ENDIF
    320 
    321     IF ( return_value == 0 )  THEN
    322        IF ( nc_stat /= NF90_NOERR )  THEN
     310    IF ( .NOT. ( TRIM( mode ) == mode_serial  .AND.  my_rank /= master_rank ) )  THEN
     311
     312       IF ( variable_id == global_id_in_file )  THEN
     313          target_id = NF90_GLOBAL
     314       ELSE
     315          target_id = variable_id
     316       ENDIF
     317
     318       CALL internal_message( 'debug', routine_name //                                             &
     319                              ': write attribute "' // TRIM( attribute_name ) // '"' )
     320
     321       IF ( PRESENT( value_char ) )  THEN
     322          nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), TRIM( value_char ) )
     323       ELSEIF ( PRESENT( value_int8 ) )  THEN
     324          nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_int8 )
     325       ELSEIF ( PRESENT( value_int16 ) )  THEN
     326          nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_int16 )
     327       ELSEIF ( PRESENT( value_int32 ) )  THEN
     328          nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_int32 )
     329       ELSEIF ( PRESENT( value_real32 ) )  THEN
     330          nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_real32 )
     331       ELSEIF ( PRESENT( value_real64 ) )  THEN
     332          nc_stat = NF90_PUT_ATT( file_id, target_id, TRIM( attribute_name ), value_real64 )
     333       ELSE
    323334          return_value = 1
    324335          CALL internal_message( 'error', routine_name //                                          &
    325                                  ': NetCDF error while writing attribute "' //                     &
    326                                  TRIM( attribute_name ) // '": ' // NF90_STRERROR( nc_stat ) )
    327        ENDIF
     336                                 ': no value given for attribute "' // TRIM( attribute_name ) //   &
     337                                 '"' )
     338       ENDIF
     339
     340       IF ( return_value == 0 )  THEN
     341          IF ( nc_stat /= NF90_NOERR )  THEN
     342             return_value = 1
     343             CALL internal_message( 'error', routine_name //                                       &
     344                                    ': NetCDF error while writing attribute "' //                  &
     345                                    TRIM( attribute_name ) // '": ' // NF90_STRERROR( nc_stat ) )
     346          ENDIF
     347       ENDIF
     348
    328349    ENDIF
    329350#else
    330351    return_value = 1
     352!
     353!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     354    IF ( .FALSE. )  THEN
     355       nc_stat = LEN( routine_name )
     356       target_id = 0
     357    ENDIF
    331358#endif
    332359
     
    339366!--------------------------------------------------------------------------------------------------!
    340367 SUBROUTINE netcdf4_init_dimension( mode, file_id, dimension_id, variable_id,                      &
    341                                     dimension_name, dimension_type, dimension_length, return_value )
     368                                    dimension_name, dimension_type, dimension_length,              &
     369                                    write_only_by_master_rank, return_value )
    342370
    343371    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'netcdf4_init_dimension'  !< name of this routine
     
    355383    INTEGER, INTENT(OUT) ::  variable_id          !< variable ID
    356384
     385    LOGICAL, INTENT(IN) ::  write_only_by_master_rank  !< true if only master rank shall write variable
     386
    357387
    358388#if defined( __netcdf4 )
    359389    return_value = 0
    360390    variable_id = -1
    361 
    362     CALL internal_message( 'debug', routine_name //                                                &
    363                            ': init dimension "' // TRIM( dimension_name ) // '"' )
    364 !
    365 !-- Check if dimension is unlimited
    366     IF ( dimension_length < 0 )  THEN
    367        nc_dimension_length = NF90_UNLIMITED
    368     ELSE
    369        nc_dimension_length = dimension_length
    370     ENDIF
    371 !
    372 !-- Define dimension in file
    373     nc_stat = NF90_DEF_DIM( file_id, dimension_name, nc_dimension_length, dimension_id )
    374 
    375     IF ( nc_stat == NF90_NOERR )  THEN
    376 !
    377 !--    Define variable holding dimension values in file
    378        CALL netcdf4_init_variable( mode, file_id, variable_id, dimension_name, dimension_type,     &
    379                                    (/ dimension_id /), is_global=.TRUE., return_value=return_value )
    380 
    381     ELSE
    382        return_value = 1
    383        CALL internal_message( 'error', routine_name //                                             &
    384                               ': NetCDF error while initializing dimension "' //                   &
    385                               TRIM( dimension_name ) // '": ' // NF90_STRERROR( nc_stat ) )
     391    dimension_id = -1
     392
     393    IF ( .NOT. ( TRIM( mode ) == mode_serial  .AND.  my_rank /= master_rank ) )  THEN
     394
     395       CALL internal_message( 'debug', routine_name //                                             &
     396                              ': init dimension "' // TRIM( dimension_name ) // '"' )
     397!
     398!--    Check if dimension is unlimited
     399       IF ( dimension_length < 0 )  THEN
     400          nc_dimension_length = NF90_UNLIMITED
     401       ELSE
     402          nc_dimension_length = dimension_length
     403       ENDIF
     404!
     405!--    Define dimension in file
     406       nc_stat = NF90_DEF_DIM( file_id, dimension_name, nc_dimension_length, dimension_id )
     407
     408       IF ( nc_stat == NF90_NOERR )  THEN
     409!
     410!--       Define variable holding dimension values in file
     411          CALL netcdf4_init_variable( mode, file_id, variable_id, dimension_name, dimension_type,  &
     412                                      (/ dimension_id /),                                          &
     413                                      write_only_by_master_rank=write_only_by_master_rank,         &
     414                                      return_value=return_value )
     415
     416       ELSE
     417          return_value = 1
     418          CALL internal_message( 'error', routine_name //                                          &
     419                                 ': NetCDF error while initializing dimension "' //                &
     420                                 TRIM( dimension_name ) // '": ' // NF90_STRERROR( nc_stat ) )
     421       ENDIF
     422
    386423    ENDIF
    387424#else
     
    389426    variable_id = -1
    390427    dimension_id = -1
     428!
     429!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     430    IF ( .FALSE. )  THEN
     431       nc_stat = LEN( routine_name )
     432       nc_dimension_length = 0
     433    ENDIF
    391434#endif
    392435
     
    399442!--------------------------------------------------------------------------------------------------!
    400443 SUBROUTINE netcdf4_init_variable( mode, file_id, variable_id, variable_name, variable_type,       &
    401                                    dimension_ids, is_global, return_value )
     444                                   dimension_ids, write_only_by_master_rank, return_value )
    402445
    403446    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'netcdf4_init_variable'  !< name of this routine
     
    407450    CHARACTER(LEN=*), INTENT(IN) ::  variable_type  !< data type of variable
    408451
    409     INTEGER, INTENT(IN)  ::  file_id           !< file ID
    410     INTEGER              ::  nc_stat           !< netcdf return value
    411     INTEGER              ::  nc_variable_type  !< netcdf data type
    412     INTEGER, INTENT(OUT) ::  return_value      !< return value
    413     INTEGER, INTENT(OUT) ::  variable_id       !< variable ID
    414 
     452    INTEGER, INTENT(IN)  ::  file_id                 !< file ID
     453    INTEGER              ::  nc_stat                 !< netcdf return value
     454    INTEGER              ::  nc_variable_type        !< netcdf data type
     455    INTEGER, INTENT(OUT) ::  return_value            !< return value
     456    INTEGER, INTENT(OUT) ::  variable_id             !< variable ID
     457#if defined( __netcdf4_parallel )
     458    INTEGER              ::  parallel_access_mode    !< either NF90_INDEPENDENT or NF90_COLLECTIVE
     459    INTEGER              ::  unlimited_dimension_id  !< ID of unlimited dimension in file
     460#endif
    415461    INTEGER, DIMENSION(:), INTENT(IN) ::  dimension_ids  !< list of dimension IDs used by variable
    416462
    417     LOGICAL, INTENT(IN)  ::  is_global  !< true if variable is global (same on all PE)
     463    LOGICAL, INTENT(IN) ::  write_only_by_master_rank  !< true if only master rank shall write variable
    418464
    419465
    420466#if defined( __netcdf4 )
    421467    return_value = 0
    422 
    423     WRITE( temp_string, * ) is_global
    424     CALL internal_message( 'debug', routine_name //                                                &
    425                            ': init variable "' // TRIM( variable_name ) //                         &
    426                            '" ( is_global = ' // TRIM( temp_string ) // ')' )
    427 
    428     nc_variable_type = get_netcdf_data_type( variable_type )
    429 
    430     IF ( nc_variable_type /= -1 )  THEN
    431 !
    432 !--    Define variable in file
    433        nc_stat = NF90_DEF_VAR( file_id, variable_name, nc_variable_type, dimension_ids, variable_id )
    434 
    435 !
    436 !--    Define how variable can be accessed by PEs in parallel netcdf file
    437        IF ( nc_stat == NF90_NOERR  .AND.  TRIM( mode ) == mode_parallel )  THEN
     468    variable_id = -1
     469
     470    IF ( ( TRIM( mode ) == mode_serial  .AND.  my_rank == master_rank )                            &
     471         .OR.  TRIM( mode ) == mode_parallel )  THEN
     472
     473       WRITE( temp_string, * ) write_only_by_master_rank
     474       CALL internal_message( 'debug', routine_name //                                             &
     475                              ': init variable "' // TRIM( variable_name ) //                      &
     476                              '" ( write_only_by_master_rank = ' // TRIM( temp_string ) // ')' )
     477
     478       nc_variable_type = get_netcdf_data_type( variable_type )
     479
     480       IF ( nc_variable_type /= -1 )  THEN
     481!
     482!--       Define variable in file
     483          nc_stat = NF90_DEF_VAR( file_id, variable_name, nc_variable_type,                        &
     484                                  dimension_ids, variable_id )
     485
    438486#if defined( __netcdf4_parallel )
    439           IF ( is_global )  THEN
    440              nc_stat = NF90_VAR_PAR_ACCESS( file_id, variable_id, NF90_INDEPENDENT )
    441           ELSE
    442              nc_stat = NF90_VAR_PAR_ACCESS( file_id, variable_id, NF90_COLLECTIVE )
     487!
     488!--       Define how variable can be accessed by PEs in parallel netcdf file
     489          IF ( nc_stat == NF90_NOERR  .AND.  TRIM( mode ) == mode_parallel )  THEN
     490!
     491!--          If the variable uses an unlimited dimension, its access mode must be 'collective',
     492!--          otherwise it can be set to independent.
     493!--          Hence, get ID of unlimited dimension in file (if any) and check if it is used by
     494!--          the variable.
     495             nc_stat = NF90_INQUIRE( file_id, UNLIMITEDDIMID=unlimited_dimension_id )
     496
     497             IF ( nc_stat == NF90_NOERR )  THEN
     498                IF ( ANY( dimension_ids == unlimited_dimension_id ) )  THEN
     499                   parallel_access_mode = NF90_COLLECTIVE
     500                ELSE
     501                   parallel_access_mode = NF90_INDEPENDENT
     502                ENDIF
     503
     504                nc_stat = NF90_VAR_PAR_ACCESS( file_id, variable_id, parallel_access_mode )
     505             ENDIF
    443506          ENDIF
    444 #else
    445           CONTINUE
    446 #endif
    447        ENDIF
    448 
    449        IF ( nc_stat /= NF90_NOERR )  THEN
     507#endif
     508
     509          IF ( nc_stat /= NF90_NOERR )  THEN
     510             return_value = 1
     511             CALL internal_message( 'error', routine_name //                                       &
     512                                    ': NetCDF error while initializing variable "' //              &
     513                                    TRIM( variable_name ) // '": ' // NF90_STRERROR( nc_stat ) )
     514          ENDIF
     515
     516       ELSE
    450517          return_value = 1
    451           CALL internal_message( 'error', routine_name //                                          &
    452                                  ': NetCDF error while initializing variable "' //                 &
    453                                  TRIM( variable_name ) // '": ' // NF90_STRERROR( nc_stat ) )
    454        ENDIF
    455 
    456     ELSE
     518       ENDIF
     519
     520    ELSEIF ( TRIM( mode ) /= mode_serial  .AND.  TRIM( mode ) /= mode_parallel )  THEN
    457521       return_value = 1
     522       CALL internal_message( 'error', routine_name //                                             &
     523                              ': selected mode "' // TRIM( mode ) // '" must be either "' //       &
     524                              mode_serial // '" or "' // mode_parallel // '"' )
    458525    ENDIF
    459526
     
    461528    return_value = 1
    462529    variable_id = -1
     530!
     531!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     532    IF ( .FALSE. )  THEN
     533       nc_stat = LEN( routine_name )
     534       nc_variable_type = get_netcdf_data_type( '' )
     535    ENDIF
    463536#endif
    464537
     
    470543!> Leave file definition state.
    471544!--------------------------------------------------------------------------------------------------!
    472  SUBROUTINE netcdf4_stop_file_header_definition( file_id, return_value )
     545 SUBROUTINE netcdf4_stop_file_header_definition( mode, file_id, return_value )
    473546
    474547    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'netcdf4_stop_file_header_definition'  !< name of this routine
     548
     549    CHARACTER(LEN=*), INTENT(IN) ::  mode  !< operation mode (either parallel or serial)
    475550
    476551    INTEGER, INTENT(IN)  ::  file_id        !< file ID
     
    483558    return_value = 0
    484559
    485     WRITE( temp_string, * ) file_id
    486     CALL internal_message( 'debug', routine_name //                                                &
    487                            ': finalize file definition (file_id=' // TRIM( temp_string ) // ')' )
    488 !
    489 !-- Set general no fill, otherwise the performance drops significantly
    490     nc_stat = NF90_SET_FILL( file_id, NF90_NOFILL, old_fill_mode )
    491 
    492     IF ( nc_stat == NF90_NOERR )  THEN
    493        nc_stat = NF90_ENDDEF( file_id )
    494     ENDIF
    495 
    496     IF ( nc_stat /= NF90_NOERR )  THEN
    497        return_value = 1
    498        CALL internal_message( 'error', routine_name //                                             &
    499                               ': NetCDF error: ' // NF90_STRERROR( nc_stat ) )
     560    IF ( .NOT. ( TRIM( mode ) == mode_serial  .AND.  my_rank /= master_rank ) )  THEN
     561
     562       WRITE( temp_string, * ) file_id
     563       CALL internal_message( 'debug', routine_name //                                             &
     564                              ': finalize file definition (file_id=' // TRIM( temp_string ) // ')' )
     565!
     566!--    Set general no fill, otherwise the performance drops significantly
     567       nc_stat = NF90_SET_FILL( file_id, NF90_NOFILL, old_fill_mode )
     568
     569       IF ( nc_stat == NF90_NOERR )  THEN
     570          nc_stat = NF90_ENDDEF( file_id )
     571       ENDIF
     572
     573       IF ( nc_stat /= NF90_NOERR )  THEN
     574          return_value = 1
     575          CALL internal_message( 'error', routine_name //                                          &
     576                                 ': NetCDF error: ' // NF90_STRERROR( nc_stat ) )
     577       ENDIF
     578
    500579    ENDIF
    501580#else
    502581    return_value = 1
     582!
     583!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     584    IF ( .FALSE. )  THEN
     585       nc_stat = LEN( routine_name )
     586       old_fill_mode = 0
     587    ENDIF
    503588#endif
    504589
     
    511596!--------------------------------------------------------------------------------------------------!
    512597 SUBROUTINE netcdf4_write_variable(                                                                &
    513                file_id, variable_id, bounds_start, value_counts, bounds_origin,                    &
    514                is_global,                                                                          &
     598               mode, file_id, variable_id, bounds_start, value_counts, bounds_origin,              &
     599               write_only_by_master_rank,                                                          &
    515600               values_char_0d,   values_char_1d,   values_char_2d,   values_char_3d,               &
    516601               values_int8_0d,   values_int8_1d,   values_int8_2d,   values_int8_3d,               &
     
    525610    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'netcdf4_write_variable'  !< name of this routine
    526611
     612    CHARACTER(LEN=*), INTENT(IN) ::  mode  !< operation mode (either parallel or serial)
     613
    527614    CHARACTER(LEN=1), POINTER,             INTENT(IN), OPTIONAL                   ::  values_char_0d  !< output variable
    528615    CHARACTER(LEN=1), POINTER, CONTIGUOUS, INTENT(IN), OPTIONAL, DIMENSION(:)     ::  values_char_1d  !< output variable
     
    530617    CHARACTER(LEN=1), POINTER, CONTIGUOUS, INTENT(IN), OPTIONAL, DIMENSION(:,:,:) ::  values_char_3d  !< output variable
    531618
    532     INTEGER              ::  d             !< loop index
    533     INTEGER, INTENT(IN)  ::  file_id       !< file ID
    534     INTEGER              ::  my_rank       !< MPI rank of processor
    535     INTEGER              ::  nc_stat       !< netcdf return value
    536     INTEGER              ::  ndims         !< number of dimensions of variable in file
    537     INTEGER, INTENT(OUT) ::  return_value  !< return value
    538     INTEGER, INTENT(IN)  ::  variable_id   !< variable ID
     619    INTEGER              ::  d                       !< loop index
     620    INTEGER, INTENT(IN)  ::  file_id                 !< file ID
     621    INTEGER              ::  nc_stat                 !< netcdf return value
     622    INTEGER              ::  ndims                   !< number of dimensions of variable in file
     623    INTEGER, INTENT(OUT) ::  return_value            !< return value
     624    INTEGER              ::  unlimited_dimension_id  !< ID of unlimited dimension in file
     625    INTEGER, INTENT(IN)  ::  variable_id             !< variable ID
    539626
    540627    INTEGER, DIMENSION(:),              INTENT(IN)  ::  bounds_origin      !< starting index of each dimension
     
    561648    INTEGER(iwp),    POINTER, CONTIGUOUS, INTENT(IN), OPTIONAL, DIMENSION(:,:,:) ::  values_intwp_3d  !< output variable
    562649
    563     LOGICAL, INTENT(IN) ::  is_global  !< true if variable is global (same on all PE)
     650    LOGICAL, INTENT(IN) ::  write_only_by_master_rank  !< true if only master rank shall write variable
     651    LOGICAL             ::  write_data                 !< true if variable shall be written to file
    564652
    565653    REAL(KIND=4), POINTER,             INTENT(IN), OPTIONAL                   ::  values_real32_0d  !< output variable
     
    578666
    579667#if defined( __netcdf4 )
    580 
    581 #if defined( __parallel )
    582     CALL MPI_COMM_RANK( output_group_comm, my_rank, return_value )
    583     IF ( return_value /= 0 )  THEN
    584        CALL internal_message( 'error', routine_name // ': MPI_COMM_RANK error' )
    585     ENDIF
    586 #else
    587     my_rank = master_rank
    588668    return_value = 0
    589 #endif
    590 
    591     IF ( return_value == 0  .AND.  ( .NOT. is_global .OR. my_rank == master_rank ) )  THEN
     669    write_data = .FALSE.
     670!
     671!-- Check whether this PE write any data to file
     672    IF ( TRIM( mode ) == mode_serial )  THEN
     673
     674       IF ( my_rank == master_rank )  write_data = .TRUE.
     675
     676    ELSEIF ( TRIM( mode ) == mode_parallel )  THEN
     677!
     678!--    Check for collective access mode.
     679!--    This cannot be checked directly but indirect via the presence of any unlimited dimensions
     680!--    If any dimension is unlimited, variable access must be collective and all PEs must
     681!--    participate in writing
     682       ndims = SIZE( bounds_start )
     683       ALLOCATE( dimension_ids(ndims) )
     684
     685       nc_stat = NF90_INQUIRE_VARIABLE( file_id, variable_id, DIMIDS=dimension_ids )
     686       nc_stat = NF90_INQUIRE( file_id, UNLIMITEDDIMID=unlimited_dimension_id )
     687
     688       IF ( ANY( dimension_ids == unlimited_dimension_id ) )  THEN
     689          write_data = .TRUE.
     690!
     691!--    If access is independent, check if only master rank shall write
     692       ELSEIF ( write_only_by_master_rank )  THEN
     693          IF ( my_rank == master_rank )  write_data = .TRUE.
     694!
     695!--    If all PEs can write, check if there are any data to be written
     696       ELSEIF ( ALL( value_counts > 0, DIM=1 ) )  THEN
     697          write_data = .TRUE.
     698       ENDIF
     699
     700    ELSE
     701       return_value = 1
     702       CALL internal_message( 'error', routine_name //                                             &
     703                              ': selected mode "' // TRIM( mode ) // '" must be either "' //       &
     704                              mode_serial // '" or "' // mode_parallel // '"' )
     705    ENDIF
     706
     707    IF ( write_data )  THEN
    592708
    593709       WRITE( temp_string, * ) variable_id
     
    595711
    596712       ndims = SIZE( bounds_start )
    597 
    598 !
    599 !--    character output
     713!
     714!--    Character output
    600715       IF ( PRESENT( values_char_0d ) )  THEN
    601716          nc_stat = NF90_PUT_VAR( file_id, variable_id, (/ values_char_0d /),                      &
     
    723838                                  count = value_counts )
    724839!
    725 !--    working-precision real output
     840!--    Working-precision real output
    726841       ELSEIF ( PRESENT( values_realwp_0d ) )  THEN
    727842          nc_stat = NF90_PUT_VAR( file_id, variable_id, (/ values_realwp_0d /),                    &
     
    757872             WRITE( temp_string, * )  NF90_STRERROR( nc_stat )
    758873
    759              ALLOCATE( dimension_ids(ndims) )
     874             IF ( .NOT. ALLOCATED( dimension_ids ) )  ALLOCATE( dimension_ids(ndims) )
    760875             ALLOCATE( dimension_lengths(ndims) )
    761876
     
    793908#else
    794909    return_value = 1
     910!
     911!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     912    IF ( .FALSE. )  THEN
     913       nc_stat = LEN( routine_name )
     914       IF ( write_data )  unlimited_dimension_id = 0
     915       IF ( ALLOCATED( dimension_ids ) )  d = 0
     916       IF ( ALLOCATED( dimension_lengths ) )  ndims = 0
     917    ENDIF
    795918#endif
    796919
     
    802925!> Close netcdf file.
    803926!--------------------------------------------------------------------------------------------------!
    804  SUBROUTINE netcdf4_finalize( file_id, return_value )
     927 SUBROUTINE netcdf4_finalize( mode, file_id, return_value )
    805928
    806929    CHARACTER(LEN=*), PARAMETER ::  routine_name = 'netcdf4_finalize'  !< name of routine
     930
     931    CHARACTER(LEN=*), INTENT(IN) ::  mode  !< operation mode (either parallel or serial)
    807932
    808933    INTEGER, INTENT(IN)  ::  file_id       !< file ID
     
    812937
    813938#if defined( __netcdf4 )
    814     WRITE( temp_string, * ) file_id
    815     CALL internal_message( 'debug', routine_name //                                                &
    816                            ': close file (file_id=' // TRIM( temp_string ) // ')' )
    817 
    818     nc_stat = NF90_CLOSE( file_id )
    819     IF ( nc_stat == NF90_NOERR )  THEN
    820        return_value = 0
    821     ELSE
    822        return_value = 1
    823        CALL internal_message( 'error', routine_name //                                             &
    824                               ': NetCDF error: ' // NF90_STRERROR( nc_stat ) )
     939    return_value = 0
     940
     941    IF ( .NOT. ( TRIM( mode ) == mode_serial  .AND.  my_rank /= master_rank ) )  THEN
     942
     943       WRITE( temp_string, * ) file_id
     944       CALL internal_message( 'debug', routine_name //                                             &
     945                              ': close file (file_id=' // TRIM( temp_string ) // ')' )
     946
     947       nc_stat = NF90_CLOSE( file_id )
     948       IF ( nc_stat == NF90_NOERR )  THEN
     949          return_value = 0
     950       ELSE
     951          return_value = 1
     952          CALL internal_message( 'error', routine_name //                                          &
     953                                 ': NetCDF error: ' // NF90_STRERROR( nc_stat ) )
     954       ENDIF
     955
    825956    ENDIF
    826957#else
    827958    return_value = 1
     959!
     960!-- Dummy commands to prevent "unused-variable" warning if preprocessor is not set
     961    IF ( .FALSE. )  THEN
     962       nc_stat = 0
     963       temp_string = routine_name
     964    ENDIF
    828965#endif
    829966
Note: See TracChangeset for help on using the changeset viewer.