!----------------------------------------------------------------------- ! $Id: file_functions.F90 5623 2012-01-17 17:55:26Z connork@uwm.edu $ !=============================================================================== module file_functions implicit none public :: file_read_1d, file_read_2d private ! Default Scope contains !=============================================================================== subroutine file_read_1d( file_unit, path_and_filename, & num_datapts, entries_per_line, variable ) ! Description: ! This subroutine reads in values from a data file with a number of ! rows and a declared number of columns (entries_per_line) of data. ! It reads in the data in the form of: ! 1 ==> (row 1, column 1); 2 ==> (row 1, column 2); etc. ! ! Example: a diagram of a data file with 18 total data points ! (DP1 to DP18), with 4 data points per row. ! ! i = 1 i = 2 i = 3 i = 4 ! --------------------------------------- ! k = 1 | DP1 DP2 DP3 DP4 ! | ! k = 2 | DP5 DP6 DP7 DP8 ! | ! k = 3 | DP9 DP10 DP11 DP12 ! | ! k = 4 | DP13 DP14 DP15 DP16 ! | ! k = 5 | DP17 DP18 ! ! See Michael Falk's comments below for more information. !----------------------------------------------------------------------- use clubb_precision, only: & core_rknd ! Variable(s) use constants_clubb, only: fstderr ! Constant(s) implicit none integer, intent(in) :: & file_unit, & ! Unit number of file being read. num_datapts, & ! Total number of data points being read in. entries_per_line ! Number of data points ! on one line of the file being read. character(*), intent(in) :: & path_and_filename ! Path to file and filename of file being read. real( kind = core_rknd ), dimension(num_datapts), intent(out) :: & variable ! Data values output into variable integer :: k ! Data file row number. integer :: i ! Data file column number. integer :: ierr ! ---- Begin Code ---- ! A ThreadLock is necessary here because FORTRAN can only have each file open on ! one file_unit at a time. For example, suppose we are running CLUBB in parallel ! with OpenMP using two threads. Suppose the first thread opens the file with file_unit = 0 ! (file_unit is assigned a value based on thread number). ! Then suppose, that before thread 1 exits, thread 2 opens the same file with file_unit = 1. ! This would cause FORTRAN to crash. !$omp critical ! Open data file. open( unit=file_unit, file=path_and_filename, action='read', status='old', & iostat=ierr ) if ( ierr /= 0 ) then write(fstderr,*) "CLUBB encountered an error trying to open "//path_and_filename stop "Error opening forcings file" end if ! Michael Falk wrote this routine to read data files in a particular format for mpace_a. ! Each line has a specific number of values, until the last line in the file, which ! has the last few values and then ends. This reads the correct number of values on ! each line. 24 September 2007 ! Loop over each full line of the input file. do k = 1, (num_datapts/entries_per_line), 1 read(file_unit,*) ( variable( ((k-1)*entries_per_line) + i ), & i=1,entries_per_line ) enddo ! Read any partial line remaining. if ( mod(num_datapts,entries_per_line) /= 0 ) then k = (num_datapts/entries_per_line) read(file_unit,*) ( variable( (k*entries_per_line) + i ), & i=1,(mod(num_datapts,entries_per_line)) ) endif ! Close data file. close( file_unit ) !$omp end critical return end subroutine file_read_1d !=============================================================================== subroutine file_read_2d( device, file_path, file_dimension1, & file_dimension2, file_per_line, variable ) ! Description: ! Michael Falk wrote this routine to read data files in a particular format for mpace_a. ! The 2d mpace_a files list the (file_dimension2) values on a given vertical level, then ! moves to the next level to list its values. ! Each line has a specific number of values, until the last line on a level, which ! is short-- it has the last few values and then a line break. The next line, beginning ! the next level, is full-sized again. 24 September 2007 ! ! References: ! None !------------------------------------------------------------------------------- use clubb_precision, only: & core_rknd ! Variable(s) implicit none integer, intent(in) :: & device, & file_dimension1, & file_dimension2, & file_per_line character(*), intent(in) :: & file_path real( kind = core_rknd ), dimension(file_dimension1,file_dimension2), intent(out) :: & variable integer i, j, k ! ---- Begin Code ---- variable = -999._core_rknd ! Initialize to nonsense values open(device,file=file_path,action='read') do k=1,(file_dimension1) ! For each level in the data file, do j=0,((file_dimension2/file_per_line)-1) read(device,*) (variable(k,(j*file_per_line)+i), & ! read file_per_line values in, i=1,file_per_line) end do read (device,*) (variable(k,(j*file_per_line)+i), & ! then read the partial line i=1,(mod(file_dimension2,file_per_line))) end do ! and then start over at the next level. close(device) return end subroutine file_read_2d !=============================================================================== end module file_functions