Line data Source code
1 : !-----------------------------------------------------------------------
2 : ! $Id$
3 : !===============================================================================
4 : module file_functions
5 :
6 : implicit none
7 :
8 : public :: file_read_1d, file_read_2d
9 :
10 : private ! Default Scope
11 :
12 : contains
13 :
14 : !===============================================================================
15 0 : subroutine file_read_1d( file_unit, path_and_filename, &
16 : num_datapts, entries_per_line, &
17 0 : variable )
18 :
19 : ! Description:
20 : ! This subroutine reads in values from a data file with a number of
21 : ! rows and a declared number of columns (entries_per_line) of data.
22 : ! It reads in the data in the form of:
23 : ! 1 ==> (row 1, column 1); 2 ==> (row 1, column 2); etc.
24 : !
25 : ! Example: a diagram of a data file with 18 total data points
26 : ! (DP1 to DP18), with 4 data points per row.
27 : !
28 : ! i = 1 i = 2 i = 3 i = 4
29 : ! ---------------------------------------
30 : ! k = 1 | DP1 DP2 DP3 DP4
31 : ! |
32 : ! k = 2 | DP5 DP6 DP7 DP8
33 : ! |
34 : ! k = 3 | DP9 DP10 DP11 DP12
35 : ! |
36 : ! k = 4 | DP13 DP14 DP15 DP16
37 : ! |
38 : ! k = 5 | DP17 DP18
39 : !
40 : ! See Michael Falk's comments below for more information.
41 : !-----------------------------------------------------------------------
42 :
43 : use clubb_precision, only: &
44 : core_rknd ! Variable(s)
45 :
46 : use constants_clubb, only: fstderr ! Constant(s)
47 :
48 : implicit none
49 :
50 : integer, intent(in) :: &
51 : file_unit, & ! Unit number of file being read.
52 : num_datapts, & ! Total number of data points being read in.
53 : entries_per_line ! Number of data points
54 : ! on one line of the file being read.
55 :
56 : character(*), intent(in) :: &
57 : path_and_filename ! Path to file and filename of file being read.
58 :
59 : real( kind = core_rknd ), dimension(num_datapts), intent(out) :: &
60 : variable ! Data values output into variable
61 :
62 : integer :: k ! Data file row number.
63 : integer :: i ! Data file column number.
64 : integer :: ierr
65 :
66 : ! ---- Begin Code ----
67 : ! A ThreadLock is necessary here because FORTRAN can only have each file open on
68 : ! one file_unit at a time. For example, suppose we are running CLUBB in parallel
69 : ! with OpenMP using two threads. Suppose the first thread opens the file with file_unit = 0
70 : ! (file_unit is assigned a value based on thread number).
71 : ! Then suppose, that before thread 1 exits, thread 2 opens the same file with file_unit = 1.
72 : ! This would cause FORTRAN to crash.
73 : !$omp critical
74 :
75 : ! Open data file.
76 : open( unit=file_unit, file=path_and_filename, action='read', status='old', &
77 0 : iostat=ierr )
78 0 : if ( ierr /= 0 ) then
79 0 : write(fstderr,*) "CLUBB encountered an error trying to open "//path_and_filename
80 0 : error stop "Error opening forcings file"
81 : end if
82 :
83 : ! Michael Falk wrote this routine to read data files in a particular format for mpace_a.
84 : ! Each line has a specific number of values, until the last line in the file, which
85 : ! has the last few values and then ends. This reads the correct number of values on
86 : ! each line. 24 September 2007
87 :
88 : ! Loop over each full line of the input file.
89 0 : do k = 1, (num_datapts/entries_per_line), 1
90 0 : read(file_unit,*) ( variable( ((k-1)*entries_per_line) + i ), &
91 0 : i=1,entries_per_line )
92 : enddo
93 : ! Read any partial line remaining.
94 0 : if ( mod(num_datapts,entries_per_line) /= 0 ) then
95 0 : k = (num_datapts/entries_per_line)
96 0 : read(file_unit,*) ( variable( (k*entries_per_line) + i ), &
97 0 : i=1,(mod(num_datapts,entries_per_line)) )
98 : endif
99 :
100 : ! Close data file.
101 0 : close( file_unit )
102 :
103 : !$omp end critical
104 :
105 0 : return
106 :
107 : end subroutine file_read_1d
108 :
109 : !===============================================================================
110 0 : subroutine file_read_2d( device, file_path, file_dimension1, &
111 0 : file_dimension2, file_per_line, variable )
112 :
113 : ! Description:
114 : ! Michael Falk wrote this routine to read data files in a particular format for mpace_a.
115 : ! The 2d mpace_a files list the (file_dimension2) values on a given vertical level, then
116 : ! moves to the next level to list its values.
117 : ! Each line has a specific number of values, until the last line on a level, which
118 : ! is short-- it has the last few values and then a line break. The next line, beginning
119 : ! the next level, is full-sized again. 24 September 2007
120 : !
121 : ! References:
122 : ! None
123 : !-------------------------------------------------------------------------------
124 :
125 : use clubb_precision, only: &
126 : core_rknd ! Variable(s)
127 :
128 : implicit none
129 :
130 : integer, intent(in) :: &
131 : device, &
132 : file_dimension1, &
133 : file_dimension2, &
134 : file_per_line
135 :
136 : character(*), intent(in) :: &
137 : file_path
138 :
139 : real( kind = core_rknd ), dimension(file_dimension1,file_dimension2), intent(out) :: &
140 : variable
141 :
142 : integer i, j, k
143 :
144 : ! ---- Begin Code ----
145 :
146 0 : variable = -999._core_rknd ! Initialize to nonsense values
147 :
148 0 : open(device,file=file_path,action='read')
149 :
150 0 : do k=1,(file_dimension1) ! For each level in the data file,
151 0 : do j=0,((file_dimension2/file_per_line)-1)
152 0 : read(device,*) (variable(k,(j*file_per_line)+i), & ! read file_per_line values in,
153 0 : i=1,file_per_line)
154 : end do
155 0 : read (device,*) (variable(k,(j*file_per_line)+i), & ! then read the partial line
156 0 : i=1,(mod(file_dimension2,file_per_line)))
157 : end do ! and then start over at the next level.
158 :
159 0 : close(device)
160 :
161 0 : return
162 : end subroutine file_read_2d
163 :
164 : !===============================================================================
165 :
166 : end module file_functions
|