MODULE error_codes
#include "macro.h"  
  INTEGER, PARAMETER :: SUCCESS = 0
  INTEGER, PARAMETER :: ERR_INVALID_DATA_SETTING = 1
  INTEGER, PARAMETER :: ERR_FILE_NOT_EXIST = ERR_INVALID_DATA_SETTING
  INTEGER, PARAMETER :: ERR_FILE_READING_NOT_COMPLETED = ERR_FILE_NOT_EXIST + 1
  INTEGER, PARAMETER :: ERR_FILE_INVALID_DATA = ERR_FILE_READING_NOT_COMPLETED + 1

  INTEGER, PARAMETER :: ERR_SPATIAL_BOUNDARY_INVALID = 100
  INTEGER, PARAMETER :: ERR_SPATIAL_MINIMUM_DIM_SIZE = ERR_SPATIAL_BOUNDARY_INVALID + 1
  INTEGER, PARAMETER :: ERR_SPATIAL_GRID_SIZE_NOT_UNIFORM = ERR_SPATIAL_MINIMUM_DIM_SIZE + 1
  INTEGER, PARAMETER :: ERR_SPATIAL_GRID_SIZE_NOT_VALID = ERR_SPATIAL_GRID_SIZE_NOT_UNIFORM + 1

  INTEGER, PARAMETER :: ERR_CUDA_INIT = 200
  INTEGER, PARAMETER :: ERR_CUDA_EXECUTE = ERR_CUDA_INIT + 1
  INTEGER, PARAMETER :: ERR_CUDA_ALLOCATE_MEM = ERR_CUDA_EXECUTE + 1
  INTEGER, PARAMETER :: ERR_CUDA_CREATE_STREAM = ERR_CUDA_ALLOCATE_MEM + 1

  
  INTEGER, PARAMETER :: FILENAME_LENGTH = 100, MAX_STR_LEN = 1000

  !error_message = contain the last error information
  !log_string    = contain the information to be written to log file
  CHARACTER(MAX_STR_LEN) :: log_string ="", error_message = ""

  LOGICAL :: is_FirstTime_open_logfile = .TRUE. ! use to renew the log-file
  CHARACTER(FILENAME_LENGTH) :: where2save=".", restart_file="", hostname = ""
  CHARACTER(MAX_STR_LEN) :: full_command = ""
  CHARACTER(FILENAME_LENGTH), PARAMETER :: log_file = 'log_file.txt'
  SAVE
CONTAINS
  !!>****f* data_global/write2log
  !! SYNOPSIS  
  !!   Write to log file
  !! INPUTS 
  !! OUTPUTS 
  !! RETURN
  !!   
  !! SIDE EFFECTS 
  !! HISTORY 
  !! BUGS 
  !!_****
  SUBROUTINE write2log(string_content)
    IMPLICIT NONE
    CHARACTER(*) :: string_content
    LOGICAL :: is_exist
    INTEGER :: fileID

    fileID = get_file_ID()
    
    IF (is_FirstTime_open_logfile .EQ. .TRUE.) THEN
       is_FirstTime_open_logfile = .FALSE.
       OPEN(unit=fileID, file=TRIM(where2save)//'/'//TRIM(log_file), &
            ACTION='write',  STATUS='replace')
    ELSE
       OPEN(unit=fileID, file=TRIM(where2save)//'/'//TRIM(log_file), &
         ACTION='write', ACCESS='append')
    ENDIF
    WRITE(fileID, *) TRIM(string_content)
    CLOSE(fileID)
  END SUBROUTINE write2log

  SUBROUTINE clean_log()
    
  END SUBROUTINE clean_log

    
  !!>****f* data_global/get_file_ID
  !! SYNOPSIS  
  !!   Return an available file ID
  !! INPUTS 
  !! OUTPUTS 
  !! RETURN
  !!   
  !! SIDE EFFECTS 
  !! HISTORY 
  !! BUGS 
  !!_****
  FUNCTION get_file_ID() RESULT(res)
    IMPLICIT NONE
    !! return the available file ID
    LOGICAL:: UNITOK, UNITOP
    INTEGER :: res
    INTEGER :: glob_fileID
!!$    Valid unit numbers are all nonnegative numbers except
!!$    100 through 102. Unit numbers 0, 5, and 6 are associated
!!$    WITH the standard error, standard input, and
!!$    standard output files; any unit can also refer to a pipeline

    UNITOK = .FALSE.
    UNITOP = .FALSE.

    glob_fileID = 10
    INQUIRE (unit=glob_fileID,exist=UNITOK,opened=UNITOP)
    
    DO WHILE (.NOT. (UNITOK .AND. .NOT. UNITOP))
       glob_fileID = glob_fileID + 1
       INQUIRE (unit=glob_fileID,exist=UNITOK,opened=UNITOP)
    END DO
    res = glob_fileID
  END FUNCTION get_file_ID
  
END MODULE error_codes
