!----------------------------------------------------------------------
! NEMO system team, System and Interface for oceanic RElocable Nesting
!----------------------------------------------------------------------
!
! MODULE: multi
!
!
! DESCRIPTION:
!> This module manage multi file structure
!
!> @details
!> define type TMULTI:
!> TYPE(TMULTI) :: tl_multi
!>
!> @author
!> J.Paul
! REVISION HISTORY:
!> @date 2013 - Initial Version
!
!> @note Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
!----------------------------------------------------------------------
MODULE multi
USE kind ! F90 kind parameter
USE logger ! log file manager
USE fct ! basic useful function
USE dim ! dimension manager
USE att ! attribute manager
USE var ! variable manager
USE file ! file manager
IMPLICIT NONE
PRIVATE
! NOTE_avoid_public_variables_if_possible
! type and variable
PUBLIC :: TMULTI ! multi file structure
! function and subroutine
PUBLIC :: ASSIGNMENT(=) !< copy multi structure
PUBLIC :: multi_init !< initialise mpp structure
PUBLIC :: multi_clean !< clean mpp strcuture
PUBLIC :: multi_print !< print information about mpp structure
PUBLIC :: multi_add_file !< add one proc strucutre in mpp structure
! PUBLIC :: multi_del_file !< delete one proc strucutre in mpp structure
! PUBLIC :: multi_move_file !< overwrite proc strucutre in mpp structure
!> @struct TMULTI
TYPE TMULTI
! general
INTEGER(i4) :: i_nfile = 0 !< number of files
INTEGER(i4) :: i_nvar = 0 !< total number of variables
TYPE(TFILE), DIMENSION(:), POINTER :: t_file => NULL() !< files composing multi
END TYPE
INTERFACE ASSIGNMENT(=)
MODULE PROCEDURE multi__copy ! copy multi file structure
END INTERFACE
CONTAINS
!-------------------------------------------------------------------
!> @brief
!> This function copy multi file structure in another multi file
!> structure
!> @details
!> file variable value are copied in a temporary table,
!> so input and output file structure value do not point on the same
!> "memory cell", and so on are independant.
!>
!> @warning to avoid infinite loop, do not use any function inside
!> this subroutine
!>
!> @author J.Paul
!> - Nov, 2013- Initial Version
!
!> @param[out] td_multi1 : file structure
!> @param[in] td_multi2 : file structure
!-------------------------------------------------------------------
!> @code
SUBROUTINE multi__copy( td_multi1, td_multi2 )
IMPLICIT NONE
! Argument
TYPE(TMULTI), INTENT(OUT) :: td_multi1
TYPE(TMULTI), INTENT(IN) :: td_multi2
! loop indices
INTEGER(i4) :: ji
!----------------------------------------------------------------
CALL logger_trace("COPY: mulit file ")
td_multi1%i_nfile = td_multi2%i_nfile
td_multi1%i_nvar = td_multi2%i_nvar
! copy variable structure
IF( ASSOCIATED(td_multi1%t_file) ) DEALLOCATE(td_multi1%t_file)
IF( ASSOCIATED(td_multi2%t_file) .AND. td_multi1%i_nfile > 0 )THEN
ALLOCATE( td_multi1%t_file(td_multi1%i_nfile) )
DO ji=1,td_multi1%i_nfile
td_multi1%t_file(ji) = td_multi2%t_file(ji)
ENDDO
ENDIF
END SUBROUTINE multi__copy
!> @endcode
!-------------------------------------------------------------------
!> @brief This subroutine initialize multi file structure.
!
!> @author J.Paul
!> - Nov, 2013- Initial Version
!
!> @param[in] cd_varfile : variable location information (from namelist)
!> @return td_multi : multi structure
!-------------------------------------------------------------------
! @code
FUNCTION multi_init(cd_varfile)
IMPLICIT NONE
! Argument
CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: cd_varfile
! function
TYPE(TMULTI) :: multi_init
! local variable
CHARACTER(LEN=lc) :: cl_name
CHARACTER(LEN=lc) :: cl_file
CHARACTER(LEN=lc) :: cl_matrix
INTEGER(i4) :: il_fileid
TYPE(TVAR) :: tl_var
TYPE(TFILE) :: tl_file
TYPE(TMULTI) :: tl_multi
! loop indices
INTEGER(i4) :: ji
!----------------------------------------------------------------
ji=1
DO WHILE( TRIM(cd_varfile(ji)) /= '' )
cl_name=fct_lower(fct_split(cd_varfile(ji),1,':'))
cl_file=fct_split(cd_varfile(ji),2,':')
IF( TRIM(cl_name) /= '' )THEN
IF( TRIM(cl_file) /= '' )THEN
cl_matrix=''
IF( fct_is_num(cl_file(1:1)) )THEN
cl_matrix=TRIM(cl_file)
WRITE(cl_file,'(a,i2.2)')'data_',ji
ENDIF
! get file id
tl_file=file_init(TRIM(cl_file))
il_fileid=multi_add_file(tl_multi,tl_file)
! define variable
tl_var=var_init(TRIM(cl_name))
CALL var_read_matrix(tl_var, cl_matrix)
! add variable
CALL file_add_var(tl_multi%t_file(il_fileid),tl_var)
! update total number of variable
tl_multi%i_nvar=tl_multi%i_nvar+1
! clean structure
CALL var_clean(tl_var)
ELSE
CALL logger_error("MULTI INIT: file name matching variable "//&
& TRIM(cl_name)//" is empty. check namelist.")
ENDIF
ELSE
CALL logger_error("MULTI INIT: variable name "//&
& "is empty. check namelist.")
ENDIF
ji=ji+1
ENDDO
! save result
multi_init=tl_multi
END FUNCTION multi_init
! @endcode
!-------------------------------------------------------------------
!> @brief This subroutine clean multi file strucutre.
!
!> @author J.Paul
!> - Nov, 2013- Initial Version
!
!> @param[in] td_multi : multi file structure
!-------------------------------------------------------------------
! @code
SUBROUTINE multi_clean(td_multi)
IMPLICIT NONE
! Argument
TYPE(TMULTI), INTENT(INOUT) :: td_multi
! local variable
TYPE(TMULTI) :: tl_multi ! empty multi file structure
! loop indices
INTEGER(i4) :: ji
!----------------------------------------------------------------
CALL logger_info( " CLEAN: reset multi file " )
IF( ASSOCIATED( td_multi%t_file ) )THEN
DO ji=td_multi%i_nfile,1,-1
CALL file_clean(td_multi%t_file(ji))
ENDDO
DEALLOCATE(td_multi%t_file)
ENDIF
! replace by empty structure
td_multi=tl_multi
END SUBROUTINE multi_clean
! @endcode
!-------------------------------------------------------------------
!> @brief This subroutine print some information about mpp strucutre.
!
!> @author J.Paul
!> - Nov, 2013- Initial Version
!
!> @param[in] td_mpp : mpp structure
!-------------------------------------------------------------------
! @code
SUBROUTINE multi_print(td_multi)
IMPLICIT NONE
! Argument
TYPE(TMULTI), INTENT(IN) :: td_multi
! local variable
! loop indices
INTEGER(i4) :: ji
INTEGER(i4) :: jj
!----------------------------------------------------------------
! print file
IF( td_multi%i_nfile /= 0 .AND. ASSOCIATED(td_multi%t_file) )THEN
WRITE(*,'(/a,i3)') 'MULTI: total number of file: ',&
& td_multi%i_nfile
WRITE(*,'(6x,a,i3)') ' total number of variable: ',&
& td_multi%i_nvar
DO ji=1,td_multi%i_nfile
WRITE(*,'(3x,3a)') 'FILE ',TRIM(td_multi%t_file(ji)%c_name),&
& ' CONTAINS'
DO jj=1,td_multi%t_file(ji)%i_nvar
IF( ASSOCIATED(td_multi%t_file(ji)%t_var) )THEN
WRITE(*,'(6x,a/)') TRIM(td_multi%t_file(ji)%t_var(jj)%c_name)
ENDIF
ENDDO
ENDDO
ENDIF
END SUBROUTINE multi_print
! @endcode
!-------------------------------------------------------------------
!> @brief
!> This subroutine add file to multi file structure.
!>
!> @detail
!
!> @author J.Paul
!> - Nov, 2013- Initial Version
!
!> @param[inout] td_multi : multi file strcuture
!> @param[in] td_file : file strcuture
!> @return file id in multi structure
!-------------------------------------------------------------------
!> @code
FUNCTION multi_add_file( td_multi, td_file )
IMPLICIT NONE
! Argument
TYPE(TMULTI), INTENT(INOUT) :: td_multi
TYPE(TFILE) , INTENT(IN) :: td_file
! function
INTEGER(i4) :: multi_add_file
! local variable
INTEGER(i4) :: il_status
INTEGER(i4) :: il_fileid
TYPE(TFILE), DIMENSION(:), ALLOCATABLE :: tl_file
!----------------------------------------------------------------
il_fileid=0
IF( ASSOCIATED(td_multi%t_file) )THEN
il_fileid=file_get_id(td_multi%t_file(:),TRIM(td_file%c_name))
ENDIF
IF( il_fileid /= 0 )THEN
multi_add_file=il_fileid
ELSE
CALL logger_trace("MULTI ADD FILE: add file "//&
& TRIM(td_file%c_name)//" in multi structure")
IF( td_multi%i_nfile > 0 )THEN
!
! already other file in multi structure
ALLOCATE( tl_file(td_multi%i_nfile), stat=il_status )
IF(il_status /= 0 )THEN
CALL logger_error( " MULTI ADD FILE: not enough space to put file &
& in multi structure")
ELSE
! save temporary multi structure
tl_file(:)=td_multi%t_file(:)
DEALLOCATE( td_multi%t_file )
ALLOCATE( td_multi%t_file(td_multi%i_nfile+1), stat=il_status)
IF(il_status /= 0 )THEN
CALL logger_error( " MULTI ADD FILE: not enough space to put "//&
& "file in multi structure ")
ENDIF
! copy file in multi before
td_multi%t_file(1:td_multi%i_nfile) = tl_file(:)
DEALLOCATE(tl_file)
ENDIF
ELSE
! no processor in mpp structure
IF( ASSOCIATED(td_multi%t_file) )THEN
DEALLOCATE(td_multi%t_file)
ENDIF
ALLOCATE( td_multi%t_file(td_multi%i_nfile+1), stat=il_status )
IF(il_status /= 0 )THEN
CALL logger_error( " MULTI ADD FILE: not enough space to put "//&
& "file in multi structure " )
ENDIF
ENDIF
td_multi%i_nfile=td_multi%i_nfile+1
! add new file
td_multi%t_file(td_multi%i_nfile)=td_file
multi_add_file=td_multi%i_nfile
ENDIF
END FUNCTION multi_add_file
!> @endcode
END MODULE multi