MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
BudgetFileReader.f90
Go to the documentation of this file.
2 
3  use kindmodule
7 
8  implicit none
9 
10  private
12 
14  character(len=16) :: budtxt
15  integer(I4B) :: nval, idum1, idum2, imeth
16  real(dp) :: delt
17  character(len=16) :: srcmodelname, srcpackagename
18  character(len=16) :: dstmodelname, dstpackagename
19  integer(I4B) :: ndat, naux, nlist
20  character(len=16), dimension(:), allocatable :: auxtxt
21  contains
22  procedure :: get_str
23  end type budgetfileheadertype
24 
26  logical :: hasimeth1flowja = .false.
27  integer(I4B) :: nbudterms
28  character(len=16), dimension(:), allocatable :: budtxtarray
29  integer(I4B), dimension(:), allocatable :: imetharray
30  integer(I4B), dimension(:), allocatable :: nauxarray
31  character(len=16), dimension(:, :), allocatable :: auxtxtarray
32  real(dp), dimension(:), allocatable :: flowja
33  integer(I4B), dimension(:), allocatable :: nodesrc
34  integer(I4B), dimension(:), allocatable :: nodedst
35  real(dp), dimension(:), allocatable :: flow
36  real(dp), dimension(:, :), allocatable :: auxvar
37  character(len=16), dimension(:), allocatable :: dstpackagenamearray
38  contains
39  procedure :: initialize
40  procedure :: read_header
41  procedure :: read_record
42  procedure :: rewind
43  procedure :: finalize
44  end type budgetfilereadertype
45 
46 contains
47 
48  !< @brief initialize
49  !<
50  subroutine initialize(this, iu, iout, ncrbud)
51  ! -- dummy
52  class(budgetfilereadertype) :: this
53  integer(I4B), intent(in) :: iu
54  integer(I4B), intent(in) :: iout
55  integer(I4B), intent(out) :: ncrbud
56  ! -- local
57  integer(I4B) :: ibudterm
58  integer(I4B) :: kstp_last, kper_last
59  integer(I4B) :: maxaux
60  logical :: success
61  !
62  this%inunit = iu
63  this%nbudterms = 0
64  ncrbud = 0
65  maxaux = 0
66  call this%rewind()
67  !
68  ! -- Determine number of budget terms within a time step
69  if (iout > 0) &
70  write (iout, '(a)') &
71  'Reading budget file to determine number of terms per time step.'
72  !
73  ! -- Read through the first set of data for time step 1 and stress period 1
74  do
75  call this%read_record(success)
76  if (.not. success) exit
77  this%nbudterms = this%nbudterms + 1
78  select type (h => this%header)
79  type is (budgetfileheadertype)
80  if (h%naux > maxaux) maxaux = h%naux
81  end select
82 
83  if (this%endoffile) exit
84  if (this%header%kstp /= this%headernext%kstp .or. &
85  this%header%kper /= this%headernext%kper) &
86  exit
87  end do
88  kstp_last = this%header%kstp
89  kper_last = this%header%kper
90  allocate (this%budtxtarray(this%nbudterms))
91  allocate (this%imetharray(this%nbudterms))
92  allocate (this%dstpackagenamearray(this%nbudterms))
93  allocate (this%nauxarray(this%nbudterms))
94  allocate (this%auxtxtarray(maxaux, this%nbudterms))
95  this%auxtxtarray(:, :) = ''
96  call this%rewind()
97  !
98  ! -- Now read through again and store budget text names
99  do ibudterm = 1, this%nbudterms
100  call this%read_record(success, iout)
101  if (.not. success) exit
102  select type (h => this%header)
103  type is (budgetfileheadertype)
104  this%budtxtarray(ibudterm) = h%budtxt
105  this%imetharray(ibudterm) = h%imeth
106  this%dstpackagenamearray(ibudterm) = h%dstpackagename
107  this%nauxarray(ibudterm) = h%naux
108  if (h%naux > 0) then
109  this%auxtxtarray(1:h%naux, ibudterm) = h%auxtxt(:)
110  end if
111  if (h%srcmodelname == h%dstmodelname) then
112  if (allocated(this%nodesrc)) ncrbud = max(ncrbud, maxval(this%nodesrc))
113  end if
114  end select
115  end do
116  call this%rewind()
117  if (iout > 0) &
118  write (iout, '(a, i0, a)') 'Detected ', this%nbudterms, &
119  ' unique flow terms in budget file.'
120  end subroutine initialize
121 
122  !< @brief read header only
123  !<
124  subroutine read_header(this, success, iout)
125  ! -- dummy
126  class(budgetfilereadertype), intent(inout) :: this
127  logical, intent(out) :: success
128  integer(I4B), intent(in), optional :: iout
129  ! -- local
130  integer(I4B) :: iostat
131  integer(I8B) :: pos
132  character(len=LINELENGTH) :: errmsg
133  !
134  success = .true.
135  select type (h => this%header)
136  type is (budgetfileheadertype)
137  h%kstp = 0
138  h%kper = 0
139  h%budtxt = ''
140  h%nval = 0
141  h%idum1 = 0
142  h%idum2 = 0
143  h%imeth = 0
144  h%srcmodelname = ''
145  h%srcpackagename = ''
146  h%dstmodelname = ''
147  h%dstpackagename = ''
148  h%ndat = 0
149  h%naux = 0
150  h%nlist = 0
151  if (allocated(h%auxtxt)) deallocate (h%auxtxt)
152 
153  inquire (unit=this%inunit, pos=h%pos)
154  read (this%inunit, iostat=iostat) h%kstp, h%kper, &
155  h%budtxt, h%nval, h%idum1, h%idum2
156  if (iostat /= 0) then
157  success = .false.
158  if (iostat < 0) this%endoffile = .true.
159  return
160  end if
161  read (this%inunit) h%imeth, h%delt, h%pertim, h%totim
162  if (h%imeth == 6) then
163  read (this%inunit) h%srcmodelname
164  read (this%inunit) h%srcpackagename
165  read (this%inunit) h%dstmodelname
166  read (this%inunit) h%dstpackagename
167  read (this%inunit) h%ndat
168  h%naux = h%ndat - 1
169  if (allocated(h%auxtxt)) deallocate (h%auxtxt)
170  allocate (h%auxtxt(h%naux))
171  read (this%inunit) h%auxtxt
172  read (this%inunit) h%nlist
173  elseif (h%imeth /= 1) then
174  write (errmsg, '(a, a)') 'ERROR READING: ', trim(h%budtxt)
175  call store_error(errmsg)
176  write (errmsg, '(a, i0)') 'INVALID METHOD CODE DETECTED: ', h%imeth
177  call store_error(errmsg)
178  call store_error_unit(this%inunit)
179  end if
180  end select
181  inquire (unit=this%inunit, pos=pos)
182  this%header%size = pos - this%header%pos
183  end subroutine read_header
184 
185  !< @brief read record
186  !<
187  subroutine read_record(this, success, iout)
188  ! -- modules
190  ! -- dummy
191  class(budgetfilereadertype), intent(inout) :: this
192  logical, intent(out) :: success
193  integer(I4B), intent(in), optional :: iout
194  ! -- local
195  integer(I4B) :: i, n, iout_opt
196  !
197  if (present(iout)) then
198  iout_opt = iout
199  else
200  iout_opt = 0
201  end if
202  !
203  call this%read_header(success, iout_opt)
204  if (.not. success) return
205  !
206  select type (h => this%header)
207  type is (budgetfileheadertype)
208  if (h%imeth == 1) then
209  if (trim(adjustl(h%budtxt)) == 'FLOW-JA-FACE') then
210  if (allocated(this%flowja)) deallocate (this%flowja)
211  allocate (this%flowja(h%nval))
212  read (this%inunit) this%flowja
213  this%hasimeth1flowja = .true.
214  else
215  h%nval = h%nval * h%idum1 * abs(h%idum2)
216  if (allocated(this%flow)) deallocate (this%flow)
217  allocate (this%flow(h%nval))
218  if (allocated(this%nodesrc)) deallocate (this%nodesrc)
219  allocate (this%nodesrc(h%nval))
220  read (this%inunit) this%flow
221  do i = 1, h%nval
222  this%nodesrc(i) = i
223  end do
224  end if
225  elseif (h%imeth == 6) then
226  if (allocated(this%nodesrc)) deallocate (this%nodesrc)
227  allocate (this%nodesrc(h%nlist))
228  if (allocated(this%nodedst)) deallocate (this%nodedst)
229  allocate (this%nodedst(h%nlist))
230  if (allocated(this%flow)) deallocate (this%flow)
231  allocate (this%flow(h%nlist))
232  if (allocated(this%auxvar)) deallocate (this%auxvar)
233  allocate (this%auxvar(h%naux, h%nlist))
234  read (this%inunit) (this%nodesrc(n), this%nodedst(n), this%flow(n), &
235  (this%auxvar(i, n), i=1, h%naux), n=1, h%nlist)
236  end if
237 
238  if (iout_opt > 0) then
239  write (iout_opt, '(1pg15.6, a, 1x, a)') h%totim, h%budtxt, &
240  h%dstpackagename
241  end if
242  end select
243  !
244  call this%peek_record()
245  end subroutine read_record
246 
247  !< @brief finalize
248  !<
249  subroutine finalize(this)
250  class(budgetfilereadertype) :: this
251  close (this%inunit)
252  if (allocated(this%flowja)) deallocate (this%flowja)
253  if (allocated(this%nodesrc)) deallocate (this%nodesrc)
254  if (allocated(this%nodedst)) deallocate (this%nodedst)
255  if (allocated(this%flow)) deallocate (this%flow)
256  if (allocated(this%auxvar)) deallocate (this%auxvar)
257  if (allocated(this%header)) deallocate (this%header)
258  if (allocated(this%headernext)) deallocate (this%headernext)
259  end subroutine finalize
260 
261  !> @brief Get a string representation of the budget file header.
262  function get_str(this) result(str)
263  class(budgetfileheadertype), intent(in) :: this
264  character(len=:), allocatable :: str
265  character(len=LENHUGELINE) :: temp
266 
267  write (temp, '(*(G0))') &
268  'Budget file header (pos: ', this%pos, &
269  ', kper: ', this%kper, &
270  ', kstp: ', this%kstp, &
271  ', delt: ', this%delt, &
272  ', pertim: ', this%pertim, &
273  ', totim: ', this%totim, &
274  ', budtxt: ', trim(this%budtxt), &
275  ', nval: ', this%nval, &
276  ', idum1: ', this%idum1, &
277  ', idum2: ', this%idum2, &
278  ', imeth: ', this%imeth, &
279  ', srcmodel: ', trim(this%srcmodelname), &
280  ', srcpackage: ', trim(this%srcpackagename), &
281  ', dstmodel: ', trim(this%dstmodelname), &
282  ', dstpackage: ', trim(this%dstpackagename), &
283  ', ndat: ', this%ndat, &
284  ', naux: ', this%naux, &
285  ', nlist: ', this%nlist, &
286  ')'
287  str = trim(temp)
288  end function get_str
289 
290  subroutine rewind (this)
291  class(budgetfilereadertype), intent(inout) :: this
292 
293  rewind(this%inunit)
294  this%endoffile = .false.
295  if (allocated(this%header)) deallocate (this%header)
296  if (allocated(this%headernext)) deallocate (this%headernext)
297  allocate (budgetfileheadertype :: this%header)
298  allocate (budgetfileheadertype :: this%headernext)
299  this%header%pos = 1
300  this%headernext%pos = 1
301  end subroutine rewind
302 
303 end module budgetfilereadermodule
subroutine read_header(this, success, iout)
character(len=:) function, allocatable get_str(this)
Get a string representation of the budget file header.
subroutine read_record(this, success, iout)
subroutine initialize(this, iu, iout, ncrbud)
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenhugeline
maximum length of a huge line
Definition: Constants.f90:16
subroutine, public fseek_stream(iu, offset, whence, status)
Move the file pointer.
This module defines variable data types.
Definition: kind.f90:8
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:169