TABLE OF CONTENTS


etsf_io_file_check

[ Top ] [ etsf_io_file ] [ Methods ]

NAME

etsf_io_file_check

FUNCTION

This is a high level routine to check that a file is valid to the specifications. This validity is done on presence of required variables and on conform variable definition. The presence of attributes when required is also done.

INPUTS

OUTPUT

SOURCE

  subroutine etsf_io_file_check(file_name, file_flags, lstat, error_data)
    character(len = *), intent(in)       :: file_name
    integer, intent(in)                  :: file_flags
    logical, intent(out)                 :: lstat
    type(etsf_io_low_error), intent(out) :: error_data

    character(len = *), parameter :: me = "etsf_io_file_check"
    integer :: read_flags
    type(etsf_io_low_error), dimension(etsf_nspecs_data) :: errors
    integer :: i
    
    call etsf_io_file_contents(read_flags, errors, file_name, lstat, error_data)
    if (.not. lstat) then
       call etsf_io_low_error_update(error_data, me)
       return
    end if
    
    do i = 1, etsf_nspecs_data
       if (iand(file_flags, 2 ** (i - 1)) /= 0 .and. &
            & iand(read_flags, 2 ** (i - 1)) == 0) then
          lstat = .false.
          error_data = errors(i)
          call etsf_io_low_error_update(error_data, me)
          return
       end if
    end do
    lstat = .true.
  end subroutine etsf_io_file_check

etsf_io_file_merge

[ Top ] [ etsf_io_file ] [ Methods ]

NAME

etsf_io_file_merge

FUNCTION

This is a high level routine to merge several files into one single. The files to be merged should conform to the ETSF specification on splitted files. The given input files must not be necessarily a complete list to create a non-splitted file. In the case some arrays are still partial, the created output file is a splitted one again, gathering what was possible with respect to the given input files.

INPUTS

OUTPUT

SOURCE

  subroutine etsf_io_file_merge(dest_file, source_files, lstat, error_data)
    character(len = *), intent(in) :: dest_file
    character(len = 256), intent(in) :: source_files(:)
    logical, intent(out) :: lstat
    type(etsf_io_low_error), intent(out) :: error_data

    ! Local variables
    integer :: ncid_to, n_files, i_file, i, ncid
    integer :: etsf_main, grp
    type(file_infos_type), allocatable :: infos_file(:)
    type(etsf_split) :: output_split
    type(etsf_dims) :: output_dims
    type(etsf_groups_flags) :: etsf_variables
    character(len = *), parameter :: me = "etsf_io_file_merge"

    lstat = .false.
    n_files = size(source_files)
    if (n_files <= 0) then
       call etsf_io_low_error_set(error_data, ERROR_MODE_SPEC, ERROR_TYPE_ARG, me, &
            & errmess = "argument 'source_files' has a wrong size.")
       return
    end if

    ! We allocate the dimension definitions.
    allocate(infos_file(n_files))

    !*************************************
    ! Read all definitions from all files.
    !*************************************
    ! We read the different dimensions.
    etsf_main  = etsf_main_none
    do i_file = 1, n_files, 1
       ! We copy the path.
       infos_file(i_file)%path = source_files(i_file)
       ! We get the list of used groups and main variables
       ! We also get the list of all variables in the files.
       call etsf_io_data_contents(trim(source_files(i_file)), &
            & infos_file(i_file)%dims, infos_file(i_file)%split, &
            & grp, etsf_variables, lstat, error_data, &
            & vars_infos = infos_file(i_file)%var_list)
       if (.not. lstat) then
          call file_infos_free(infos_file, i_file)
          deallocate(infos_file)
          call etsf_io_low_error_update(error_data, me)
          return
       end if
       etsf_main  = ior(etsf_main, etsf_variables%main)
    end do


    !*********************************************
    ! Merge the dimensions and split informations.
    !*********************************************
    ! We merge the dimensions, checking that all no my_something
    ! are equal and we create an output_split for all not complete
    ! dimensions after merge.
    output_dims = infos_file(1)%dims
    ! Sum all my_something dimensions, to know if the merging is complete or not.
    do i_file = 2, n_files, 1
       call etsf_io_dims_merge(output_dims, infos_file(i_file)%dims, &
            & lstat, error_data)
       if (.not. lstat) then
          call file_infos_free(infos_file, n_files)
          deallocate(infos_file)
          call etsf_io_low_error_update(error_data, me)
          return
       end if
    end do
    call etsf_io_split_allocate(output_split, output_dims)
    ! We create a new split definition with the split(i) values.
    do i_file = 1, n_files, 1
       call etsf_io_split_merge(output_split, infos_file(i_file)%split, &
            & lstat, error_data)
       if (.not. lstat) goto 1000
    end do


    !*****************************************************
    ! Define all ETSF (non main) variables and dimensions.
    !*****************************************************
    ! We create an output file and define all the variables and dimensions.
    ! All defined dimensions and variables are related to ETSF only,
    ! all other variables and dimensions are ignored.
    ! The main group is also ignored at that time to allow to add new
    ! non ETSF variables.
    if (etsf_main /= etsf_main_none) then
       etsf_variables%main = etsf_main_none
    end if
    call etsf_io_data_init(trim(dest_file), etsf_variables, output_dims, &
         & "Merging files", "", lstat, error_data = error_data, &
         & split_definition = output_split) 
    if (.not. lstat) goto 1000


    !******************************************************
    ! Treat non-ETSF part, define variables and dimensions.
    !******************************************************
    ! We reopen the destination file to add non ETSF elements
    ! and to later add the main group.
    call etsf_io_low_open_modify(ncid_to, trim(dest_file), lstat, &
         & error_data = error_data)
    if (.not. lstat) goto 1000

    ! We define all dimensions and variables that are non-part of ETSF.
    call non_etsf_init(ncid_to, infos_file, lstat, error_data)
    if (.not. lstat) goto 1000

    ! We add the main group.
    if (etsf_main /= etsf_main_none) then
       call etsf_io_main_def(ncid_to, lstat, error_data, flags = etsf_main, &
            & split = output_split)
       if (.not. lstat) goto 1000
    end if

    ! We close the file after the definitions.
    call etsf_io_low_close(ncid_to, lstat, error_data = error_data)
    if (.not. lstat) goto 1000


    !*************************
    ! Copy all ETSF variables.
    !*************************
    ! We copy all the data from read files to the new output file.
    do i_file = 1, n_files, 1
       call etsf_io_data_copy(trim(dest_file), trim(source_files(i_file)), &
            & infos_file(i_file)%dims, lstat, error_data, infos_file(i_file)%split)
       if (.not. lstat) goto 1000
    end do


    !*****************************
    ! Copy all non-ETSF variables.
    !*****************************
    ! We reopen the destination file to copy non ETSF values.
    call etsf_io_low_open_modify(ncid_to, trim(dest_file), lstat, &
         & error_data = error_data)
    if (.not. lstat) goto 1000

    call etsf_io_low_set_write_mode(ncid_to, lstat, error_data = error_data)
    if (.not. lstat) goto 1000

    ! We copy all variables that are non-part of ETSF.
    call non_etsf_copy(ncid_to, infos_file, lstat, error_data)
    if (.not. lstat) goto 1000

    ! We close the file after the copy.
    call etsf_io_low_close(ncid_to, lstat, error_data = error_data)
    if (.not. lstat) goto 1000


    ! If we arrived there, then everything went right.
    lstat = .true.

    ! Last deallocations and/or error freeing before return.
    1000 continue
    call file_infos_free(infos_file, n_files)
    deallocate(infos_file)
    call etsf_io_split_free(output_split)
    if (.not. lstat) call etsf_io_low_error_update(error_data, me)
  end subroutine etsf_io_file_merge