Index: palm/trunk/UTIL/binary_to_netcdf.f90
===================================================================
--- palm/trunk/UTIL/binary_to_netcdf.f90	(revision 4075)
+++ palm/trunk/UTIL/binary_to_netcdf.f90	(revision 4107)
@@ -82,18 +82,23 @@
 
 
-   CHARACTER(LEN=200)            ::  temp_string      !< dummy string
-
-   CHARACTER(LEN=:), ALLOCATABLE ::  filename_prefix  !< prefix of names of files to be read
-
-   CHARACTER(LEN=*), PARAMETER   ::  routine_name = 'binary_to_netcdf'             !< name of routine
-   CHARACTER(LEN=*), PARAMETER   ::  config_file_name = 'BINARY_TO_NETCDF_CONFIG'  !< name of configuration file
-
-   CHARACTER(LEN=charlen_internal), DIMENSION(:), ALLOCATABLE ::  filename_list  !< list of netcdf file names
+   CHARACTER(LEN=charlen_internal)                            ::  temp_string      !< dummy string
+   CHARACTER(LEN=:),                              ALLOCATABLE ::  filename_prefix  !< prefix of names of files to be read
+   CHARACTER(LEN=charlen_internal), DIMENSION(:), ALLOCATABLE ::  group_names      !< names of output groups
+   CHARACTER(LEN=charlen_internal), DIMENSION(:), ALLOCATABLE ::  filename_list    !< list of netcdf file names
+
+   CHARACTER(LEN=*), PARAMETER   ::  routine_name = 'binary_to_netcdf'                  !< name of routine
+   CHARACTER(LEN=*), PARAMETER   ::  config_file_name_base = 'BINARY_TO_NETCDF_CONFIG'  !< name of config file
+   CHARACTER(LEN=*), PARAMETER   ::  &
+      config_file_list_name = 'BINARY_CONFIG_LIST'  !< file containing list of binary config files of each output group
 
    INTEGER(iwp) ::  charlen            !< length of characters (strings) in binary file
    INTEGER(iwp) ::  dom_global_id      !< global ID within a single file defined by DOM
+   INTEGER      ::  dom_master_rank    !< master MPI rank in DOM (rank which wrote additional information in DOM)
+   INTEGER      ::  dom_nrank          !< number of MPI ranks used by DOM
    INTEGER(iwp) ::  file_index         !< loop index to loop over files
+   INTEGER      ::  group              !< loop index to loop over groups
    INTEGER(iwp) ::  nc_file_id         !< ID of netcdf output file
    INTEGER(iwp) ::  nfiles             !< number of output files defined in config file
+   INTEGER      ::  ngroup             !< number of output-file groups
    INTEGER      ::  return_value       !< return value
    INTEGER      ::  your_return_value  !< returned value of called routine
@@ -104,6 +109,7 @@
    INTEGER(iwp)    ::  dummy_intwp  !< dummy variable used for reading
 
-   INTEGER, PARAMETER ::  bin_file_unit = 2     !< Fortran unit of binary file
-   INTEGER, PARAMETER ::  config_file_unit = 1  !< Fortran unit of configuration file
+   INTEGER, PARAMETER ::  bin_file_unit = 12          !< Fortran unit of binary file
+   INTEGER, PARAMETER ::  config_file_unit = 11       !< Fortran unit of configuration file
+   INTEGER, PARAMETER ::  config_file_list_unit = 10  !< Fortran unit of file containing config-file list
 
    INTEGER, DIMENSION(:), ALLOCATABLE ::  dim_id_netcdf  !< mapped dimension id within NetCDF file:
@@ -126,35 +132,51 @@
    return_value = 0
 
-   CALL internal_message( 'info', routine_name // ': Start converting binary files...' )
-
-   CALL read_config( your_return_value )
-
-   IF ( your_return_value == 0 )  THEN
-      DO  file_index = 1, nfiles
-
-         CALL internal_message( 'info', routine_name // &
-                                ': create file ' // TRIM( filename_list(file_index) ) )
-
-         CALL read_binary_header( TRIM( filename_list(file_index) ), your_return_value )
+   CALL internal_message( 'info', 'Start ' // routine_name // ' ...' )
+
+   CALL get_group_names( return_value )
+
+   IF ( return_value == 0 )  THEN
+
+      !-- Go through each group of output files (all marked by same file suffix)
+      DO  group = 1, ngroup
+
+         CALL internal_message( 'info', 'Start converting ' // TRIM( group_names(group) ) // &
+                                ' binary files:' )
+
+         CALL read_config( TRIM( group_names(group) ), your_return_value )
 
          IF ( your_return_value == 0 )  THEN
-            CALL define_netcdf_files( TRIM( filename_list(file_index) ), your_return_value )
+            DO  file_index = 1, nfiles
+
+               CALL internal_message( 'info', 'Create file ' // TRIM( filename_list(file_index) ) )
+
+               CALL read_binary_header( TRIM( filename_list(file_index) ), your_return_value )
+
+               IF ( your_return_value == 0 )  THEN
+                  CALL define_netcdf_files( TRIM( filename_list(file_index) ), your_return_value )
+               ELSE
+                  return_value = your_return_value
+               ENDIF
+
+               IF ( your_return_value == 0 )  THEN
+                  CALL convert_data_to_netcdf( TRIM( filename_list(file_index) ), your_return_value )
+               ELSE
+                  return_value = your_return_value
+               ENDIF
+
+            ENDDO
          ELSE
             return_value = your_return_value
          ENDIF
 
-         IF ( your_return_value == 0 )  THEN
-            CALL convert_data_to_netcdf( TRIM( filename_list(file_index) ), your_return_value )
-         ELSE
-            return_value = your_return_value
-         ENDIF
+         IF ( ALLOCATED( filename_list   ) )  DEALLOCATE( filename_list   )
+         IF ( ALLOCATED( filename_prefix ) )  DEALLOCATE( filename_prefix )
 
       ENDDO
-   ELSE
-      return_value = your_return_value
+
    ENDIF
 
    IF ( return_value == 0 )  THEN
-      CALL internal_message( 'info', routine_name // ': Execution finished' )
+      CALL internal_message( 'info', 'Execution finished' )
    ELSE
       CALL internal_message( 'error', routine_name // ': Error during execution! Check results!' )
@@ -168,10 +190,95 @@
 ! Description:
 ! ------------
+!> Check if any configuration file is present in the current directory and get the list of all
+!> these files and extract the output-group names.
+!--------------------------------------------------------------------------------------------------!
+SUBROUTINE get_group_names( return_value )
+
+   CHARACTER(LEN=charlen_internal) ::  file_name  !< file name read from list
+
+   CHARACTER(LEN=*), PARAMETER ::  routine_name = 'get_group_names'  !< name of routine
+
+   INTEGER              ::  i             !< loop index
+   INTEGER              ::  io_stat       !< status of Fortran I/O operations
+   INTEGER, INTENT(OUT) ::  return_value  !< return value
+
+
+   CALL internal_message( 'info', 'Check if anything to convert...' )
+
+   !-- Search for configuration files and save the list of file names in a separate file
+   CALL EXECUTE_COMMAND_LINE( &
+           COMMAND='find . -type f -name "' // config_file_name_base // '*" | ' // &
+                   'sed -r "s/^\.\/(' // config_file_name_base // ')?(.+)$/\1\2/" > ' // &
+                   config_file_list_name, &
+           WAIT=.TRUE., &
+           EXITSTAT=return_value )
+
+   !-- Read the config-file-name list and extract the group names from the file names
+   IF ( return_value /= 0 )  THEN
+
+      CALL internal_message( 'error', routine_name // &
+                             ': error while searching for configuration files: ' // &
+                             'System returned non-zero exit status. ' // &
+                             'Please report this error to the developers!' )
+
+   ELSE
+
+      OPEN( config_file_list_unit, FILE=config_file_list_name, FORM='formatted', &
+            STATUS='OLD', IOSTAT=io_stat )
+
+      !-- Count the configuration files
+      ngroup = 0
+      DO WHILE ( io_stat == 0 )
+         READ( config_file_list_unit, '(A)', IOSTAT=io_stat )  file_name
+         IF ( io_stat == 0 )  ngroup = ngroup + 1
+      ENDDO
+      REWIND( config_file_list_unit )
+
+      IF ( ngroup /= 0 )  THEN
+
+         ALLOCATE( group_names(ngroup) )
+
+         !-- Extract the group names
+         DO  i = 1, ngroup
+            READ( config_file_list_unit, '(A)', IOSTAT=io_stat )  file_name
+            IF ( INDEX( TRIM( file_name ), config_file_name_base ) == 1 )  THEN
+               IF ( TRIM( file_name ) ==  TRIM( config_file_name_base ) )  THEN
+                  group_names(i) = ''
+               ELSE
+                  group_names(i) = file_name(LEN_TRIM( config_file_name_base )+1:)
+               ENDIF
+            ELSE
+               return_value = 1
+               CALL internal_message( 'error', routine_name // &
+                                      ': error while getting list of binary config files: ' // &
+                                      'Unexpected text found in file list. ' // &
+                                      'Please report this error to the developers!' )
+               EXIT
+            ENDIF
+         ENDDO
+
+      ELSE
+         CALL internal_message( 'info', 'No configuration files found. ' // &
+                                'No binary files to convert to NetCDF.' )
+      ENDIF
+
+      CLOSE( config_file_list_unit )
+
+   ENDIF
+
+END SUBROUTINE get_group_names
+
+!--------------------------------------------------------------------------------------------------!
+! Description:
+! ------------
 !> Read configuration file.
 !--------------------------------------------------------------------------------------------------!
-SUBROUTINE read_config( return_value )
+SUBROUTINE read_config( group_name, return_value )
 
    CHARACTER(LEN=:), ALLOCATABLE ::  read_string                   !< string read from file
+   CHARACTER(LEN=*), INTENT(IN)  ::  group_name                    !< group name
    CHARACTER(LEN=*), PARAMETER   ::  routine_name = 'read_config'  !< name of routine
+
+   CHARACTER(LEN=charlen_internal) ::  config_file_name  !< config file name with additional suffix
 
    CHARACTER(LEN=charlen_internal), DIMENSION(:), ALLOCATABLE ::  filename_list_tmp  !< temporary list of file names
@@ -183,4 +290,6 @@
 
    return_value = 0
+
+   config_file_name = config_file_name_base // group_name
 
    OPEN( config_file_unit, FILE=config_file_name, FORM='unformatted', &
@@ -196,4 +305,14 @@
    IF ( return_value == 0 )  THEN
 
+      READ( config_file_unit ) dom_nrank
+
+      IF ( dom_nrank > 1000000 )  THEN
+         dom_nrank = 1000000
+         CALL internal_message( 'info', routine_name // &
+                 ': number of MPI ranks used in PALM is greater than the maximum ' // &
+                 'amount I can handle. I will only consider the first 1000000 output files.' )
+      ENDIF
+
+      READ( config_file_unit ) dom_master_rank
       READ( config_file_unit ) filename_prefix_length
 
@@ -201,7 +320,5 @@
 
       READ( config_file_unit ) filename_prefix
-
       READ( config_file_unit ) charlen
-
       READ( config_file_unit ) dom_global_id
 
@@ -233,5 +350,5 @@
                ENDIF
 
-               filename_list(nfiles) = TRIM( read_string )
+               filename_list(nfiles) = TRIM( read_string ) // group_name
 
             ENDIF
@@ -280,6 +397,7 @@
    return_value = 0
 
-   !-- Open binary file of PE0
-   bin_filename = TRIM( filename_prefix ) // TRIM( bin_filename_body ) // '_000000'
+   !-- Open binary file written by dom_master_rank
+   WRITE( bin_filename , '(A,I6.6)' ) &
+      TRIM( filename_prefix ) // TRIM( bin_filename_body ) // '_', dom_master_rank
 
    CALL internal_message( 'debug', routine_name // ': read file ' // TRIM( bin_filename ) )
@@ -426,4 +544,6 @@
    ENDDO  ! iterate over file header
 
+   CLOSE( bin_file_unit )
+
 END SUBROUTINE read_binary_header
 
@@ -679,5 +799,5 @@
 
    !-- Open binary files of every possible PE
-   DO  pe_id = 0, 999999
+   DO  pe_id = 0, dom_nrank - 1
 
       WRITE( bin_filename, '(A, I6.6)' ) &
@@ -689,42 +809,37 @@
       IF ( file_exists )  THEN
 
-         !-- Open file and skip header (file of PE0 is already opened)
-         IF ( pe_id /= 0 )  THEN
-
-            OPEN( bin_file_unit, FILE=bin_filename, FORM='UNFORMATTED', STATUS='OLD' )
-
-            CALL internal_message( 'debug', routine_name // &
-                                   ': read binary file ' // TRIM( bin_filename ) )
-
-            read_string = ''
-            DO WHILE ( TRIM( read_string ) /= '*** end file header ***' )
-
-               READ( bin_file_unit ) read_string
-
-               SELECT CASE ( TRIM( read_string ) )
-
-                  CASE ( 'char' )
-                     READ( bin_file_unit ) read_string
-
-                  CASE ( 'int8' )
-                     READ( bin_file_unit ) dummy_int8
-
-                  CASE ( 'int16' )
-                     READ( bin_file_unit ) dummy_int16
-
-                  CASE ( 'int32' )
-                     READ( bin_file_unit ) dummy_int32
-
-                  CASE ( 'real32' )
-                     READ( bin_file_unit ) dummy_real32
-
-                  CASE ( 'real64' )
-                     READ( bin_file_unit ) dummy_real64
-
-               END SELECT
-
-            ENDDO
-
-         ENDIF
+         OPEN( bin_file_unit, FILE=bin_filename, FORM='UNFORMATTED', STATUS='OLD' )
+
+         CALL internal_message( 'debug', routine_name // &
+                                ': read binary file ' // TRIM( bin_filename ) )
+
+         read_string = ''
+         DO WHILE ( TRIM( read_string ) /= '*** end file header ***' )
+
+            READ( bin_file_unit ) read_string
+
+            SELECT CASE ( TRIM( read_string ) )
+
+               CASE ( 'char' )
+                  READ( bin_file_unit ) read_string
+
+               CASE ( 'int8' )
+                  READ( bin_file_unit ) dummy_int8
+
+               CASE ( 'int16' )
+                  READ( bin_file_unit ) dummy_int16
+
+               CASE ( 'int32' )
+                  READ( bin_file_unit ) dummy_int32
+
+               CASE ( 'real32' )
+                  READ( bin_file_unit ) dummy_real32
+
+               CASE ( 'real64' )
+                  READ( bin_file_unit ) dummy_real64
+
+            END SELECT
+
+         ENDDO
 
          !-- Read variable data
@@ -873,8 +988,4 @@
          CLOSE( bin_file_unit )
 
-      ELSE
-
-         EXIT
-
       ENDIF  ! if file exists
 
