MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
InputOutput.f90
Go to the documentation of this file.
1 ! -- MODFLOW 6 utility routines.
2 !
4 
5  use kindmodule, only: dp, i4b, i8b
12  use messagemodule, only: write_message
13  private
17  linear_interpolate, lowcase, read_line, getfilefrompath, &
21 
22 contains
23 
24  !> @brief Open a file
25  !!
26  !! Subroutine to open a file using the specified arguments
27  !<
28  subroutine openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, &
29  filstat_opt, mode_opt)
30  ! -- modules
31  use openspecmodule, only: action
32  implicit none
33  ! -- dummy
34  integer(I4B), intent(inout) :: iu !< unit number
35  integer(I4B), intent(in) :: iout !< output unit number to write a message (iout=0 does not print)
36  character(len=*), intent(in) :: fname !< name of the file
37  character(len=*), intent(in) :: ftype !< file type (e.g. WEL)
38  character(len=*), intent(in), optional :: fmtarg_opt !< file format, default is 'formatted'
39  character(len=*), intent(in), optional :: accarg_opt !< file access, default is 'sequential'
40  character(len=*), intent(in), optional :: filstat_opt !< file status, default is 'old'. Use 'REPLACE' for output file.
41  integer(I4B), intent(in), optional :: mode_opt !< simulation mode that is evaluated to determine if the file should be opened
42  ! -- local
43  character(len=20) :: fmtarg
44  character(len=20) :: accarg
45  character(len=20) :: filstat
46  character(len=20) :: filact
47  integer(I4B) :: imode
48  integer(I4B) :: iflen
49  integer(I4B) :: ivar
50  integer(I4B) :: iuop
51  ! -- formats
52  character(len=*), parameter :: fmtmsg = &
53  "(1x,/1x,'OPENED ',a,/1x,'FILE TYPE:',a,' UNIT ',I4,3x,'STATUS:',a,/ &
54  & 1x,'FORMAT:',a,3x,'ACCESS:',a/1x,'ACTION:',a/)"
55  character(len=*), parameter :: fmtmsg2 = &
56  "(1x,/1x,'DID NOT OPEN ',a,/)"
57  !
58  ! -- Process mode_opt
59  if (present(mode_opt)) then
60  imode = mode_opt
61  else
62  imode = isim_mode
63  end if
64  !
65  ! -- Evaluate if the file should be opened
66  if (isim_mode < imode) then
67  if (iout > 0) then
68  write (iout, fmtmsg2) trim(fname)
69  end if
70  else
71  !
72  ! -- Default is to read an existing text file
73  fmtarg = 'FORMATTED'
74  accarg = 'SEQUENTIAL'
75  filstat = 'OLD'
76  !
77  ! -- Override defaults
78  if (present(fmtarg_opt)) then
79  fmtarg = fmtarg_opt
80  call upcase(fmtarg)
81  end if
82  if (present(accarg_opt)) then
83  accarg = accarg_opt
84  call upcase(accarg)
85  end if
86  if (present(filstat_opt)) then
87  filstat = filstat_opt
88  call upcase(filstat)
89  end if
90  if (filstat == 'OLD') then
91  filact = action(1)
92  else
93  filact = action(2)
94  end if
95  !
96  ! -- size of fname
97  iflen = len_trim(fname)
98  !
99  ! -- Get a free unit number
100  if (iu <= 0) then
101  call freeunitnumber(iu)
102  end if
103  !
104  ! -- Check to see if file is already open, if not then open the file
105  inquire (file=fname(1:iflen), number=iuop)
106  if (iuop > 0) then
107  ivar = -1
108  else
109  open (unit=iu, file=fname(1:iflen), form=fmtarg, access=accarg, &
110  status=filstat, action=filact, iostat=ivar)
111  end if
112  !
113  ! -- Check for an error
114  if (ivar /= 0) then
115  write (errmsg, '(3a,1x,i0,a)') &
116  'Could not open "', fname(1:iflen), '" on unit', iu, '.'
117  if (iuop > 0) then
118  write (errmsg, '(a,1x,a,1x,i0,a)') &
119  trim(errmsg), 'File already open on unit', iuop, '.'
120  end if
121  write (errmsg, '(a,1x,a,1x,a,a)') &
122  trim(errmsg), 'Specified file status', trim(filstat), '.'
123  write (errmsg, '(a,1x,a,1x,a,a)') &
124  trim(errmsg), 'Specified file format', trim(fmtarg), '.'
125  write (errmsg, '(a,1x,a,1x,a,a)') &
126  trim(errmsg), 'Specified file access', trim(accarg), '.'
127  write (errmsg, '(a,1x,a,1x,a,a)') &
128  trim(errmsg), 'Specified file action', trim(filact), '.'
129  write (errmsg, '(a,1x,a,1x,i0,a)') &
130  trim(errmsg), 'IOSTAT error number', ivar, '.'
131  write (errmsg, '(a,1x,a)') &
132  trim(errmsg), 'STOP EXECUTION in subroutine openfile().'
133  call store_error(errmsg, terminate=.true.)
134  end if
135  !
136  ! -- Write a message
137  if (iout > 0) then
138  write (iout, fmtmsg) fname(1:iflen), ftype, iu, filstat, fmtarg, &
139  accarg, filact
140  end if
141  end if
142  !
143  ! -- Return
144  return
145  end subroutine openfile
146 
147  !> @brief Assign a free unopened unit number
148  !!
149  !! Subroutine to assign a free unopened unit number to the iu dummy argument
150  !<
151  subroutine freeunitnumber(iu)
152  ! -- modules
153  implicit none
154  ! -- dummy
155  integer(I4B), intent(inout) :: iu !< next free file unit number
156  ! -- local
157  integer(I4B) :: i
158  logical :: opened
159  !
160  do i = iunext, iulast
161  inquire (unit=i, opened=opened)
162  if (.not. opened) exit
163  end do
164  iu = i
165  iunext = iu + 1
166  !
167  ! -- Return
168  return
169  end subroutine freeunitnumber
170 
171  !> @brief Get a free unit number
172  !!
173  !! Function to get a free unit number that hasn't been used
174  !<
175  function getunit()
176  ! -- modules
177  implicit none
178  ! -- return
179  integer(I4B) :: getunit !< free unit number
180  ! -- local
181  integer(I4B) :: iunit
182  !
183  ! -- code
184  call freeunitnumber(iunit)
185  getunit = iunit
186  !
187  ! -- Return
188  return
189  end function getunit
190 
191  !> @brief Convert to upper case
192  !!
193  !! Subroutine to convert a character string to upper case.
194  !<
195  subroutine upcase(word)
196  implicit none
197  ! -- dummy
198  character(len=*), intent(inout) :: word !< word to convert to upper case
199  ! -- local
200  integer(I4B) :: l
201  integer(I4B) :: idiff
202  integer(I4B) :: k
203  !
204  ! -- Compute the difference between lowercase and uppercase.
205  l = len(word)
206  idiff = ichar('a') - ichar('A')
207  !
208  ! -- Loop through the string and convert any lowercase characters.
209  do k = 1, l
210  IF (word(k:k) >= 'a' .and. word(k:k) <= 'z') &
211  word(k:k) = char(ichar(word(k:k)) - idiff)
212  end do
213  !
214  ! -- Return
215  return
216  end subroutine upcase
217 
218  !> @brief Convert to lower case
219  !!
220  !! Subroutine to convert a character string to lower case.
221  !<
222  subroutine lowcase(word)
223  implicit none
224  ! -- dummy
225  character(len=*) :: word
226  ! -- local
227  integer(I4B) :: idiff, k, l
228  !
229  ! -- Compute the difference between lowercase and uppercase.
230  l = len(word)
231  idiff = ichar('a') - ichar('A')
232  !
233  ! -- Loop through the string and convert any uppercase characters.
234  do k = 1, l
235  if (word(k:k) >= 'A' .and. word(k:k) <= 'Z') then
236  word(k:k) = char(ichar(word(k:k)) + idiff)
237  end if
238  end do
239  !
240  ! -- Return
241  return
242  end subroutine lowcase
243 
244  !> @brief Append processor id to a string
245  !!
246  !! Subroutine to append the processor id to a string before the file extension
247  !! (extension is the string after the last '.' in the string. If there is
248  !! no '.' in the string the processor id is appended to the end of the string.
249  !<
250  subroutine append_processor_id(name, proc_id)
251  ! -- dummy
252  character(len=LINELENGTH), intent(inout) :: name !< file name
253  integer(I4B), intent(in) :: proc_id !< processor id
254  ! -- local
255  character(len=LINELENGTH) :: name_local
256  character(len=LINELENGTH) :: name_processor
257  character(len=LINELENGTH) :: extension_local
258  integer(I4B) :: ipos0
259  integer(I4B) :: ipos1
260  !
261  name_local = name
262  call lowcase(name_local)
263  ipos0 = index(name_local, ".", back=.true.)
264  ipos1 = len_trim(name)
265  if (ipos0 > 0) then
266  write (extension_local, '(a)') name(ipos0:ipos1)
267  else
268  ipos0 = ipos1
269  extension_local = ''
270  end if
271  write (name_processor, '(a,a,i0,a)') &
272  name(1:ipos0 - 1), '.p', proc_id, trim(adjustl(extension_local))
273  name = name_processor
274  !
275  ! -- Return
276  return
277  end subroutine append_processor_id
278 
279  !> @brief Create a formatted line
280  !!
281  !! Subroutine to create a formatted line with specified alignment and column
282  !! separators. Like URWORD, UWWORD works with strings, integers, and floats.
283  !! Can pass an optional format statement, alignment, and column separator.
284  !<
285  subroutine uwword(line, icol, ilen, ncode, c, n, r, fmt, alignment, sep)
286  implicit none
287  ! -- dummy
288  character(len=*), intent(inout) :: line !< line
289  integer(I4B), intent(inout) :: icol !< column to write to line
290  integer(I4B), intent(in) :: ilen !< current length of line
291  integer(I4B), intent(in) :: ncode !< code for data type to write
292  character(len=*), intent(in) :: c !< character data type
293  integer(I4B), intent(in) :: n !< integer data type
294  real(dp), intent(in) :: r !< float data type
295  character(len=*), optional, intent(in) :: fmt !< format statement
296  integer(I4B), optional, intent(in) :: alignment !< alignment specifier
297  character(len=*), optional, intent(in) :: sep !< column separator
298  ! -- local
299  character(len=16) :: cfmt
300  character(len=16) :: cffmt
301  character(len=ILEN) :: cval
302  integer(I4B) :: ialign
303  integer(I4B) :: i
304  integer(I4B) :: ispace
305  integer(I4B) :: istop
306  integer(I4B) :: ipad
307  integer(I4B) :: ireal
308  !
309  ! -- initialize locals
310  ipad = 0
311  ireal = 0
312  !
313  ! -- process dummy variables
314  if (present(fmt)) then
315  cfmt = fmt
316  else
317  select case (ncode)
318  case (tabstring, tabucstring)
319  write (cfmt, '(a,I0,a)') '(a', ilen, ')'
320  case (tabinteger)
321  write (cfmt, '(a,I0,a)') '(I', ilen, ')'
322  case (tabreal)
323  ireal = 1
324  i = ilen - 7
325  write (cfmt, '(a,I0,a,I0,a)') '(1PG', ilen, '.', i, ')'
326  if (r >= dzero) then
327  ipad = 1
328  end if
329  end select
330  end if
331  write (cffmt, '(a,I0,a)') '(a', ilen, ')'
332  !
333  if (present(alignment)) then
334  ialign = alignment
335  else
336  ialign = tabright
337  end if
338  !
339  if (ncode == tabstring .or. ncode == tabucstring) then
340  cval = c
341  if (ncode == tabucstring) then
342  call upcase(cval)
343  end if
344  else if (ncode == tabinteger) then
345  write (cval, cfmt) n
346  else if (ncode == tabreal) then
347  write (cval, cfmt) r
348  end if
349  !
350  ! -- Apply alignment to cval
351  if (len_trim(adjustl(cval)) > ilen) then
352  cval = adjustl(cval)
353  else
354  cval = trim(adjustl(cval))
355  end if
356  if (ialign == tabcenter) then
357  i = len_trim(cval)
358  ispace = (ilen - i) / 2
359  if (ireal > 0) then
360  if (ipad > 0) then
361  cval = ' '//trim(adjustl(cval))
362  else
363  cval = trim(adjustl(cval))
364  end if
365  else
366  cval = repeat(' ', ispace)//trim(cval)
367  end if
368  else if (ialign == tableft) then
369  cval = trim(adjustl(cval))
370  if (ipad > 0) then
371  cval = ' '//trim(adjustl(cval))
372  end if
373  else
374  cval = adjustr(cval)
375  end if
376  if (ncode == tabucstring) then
377  call upcase(cval)
378  end if
379  !
380  ! -- Increment istop to the end of the column
381  istop = icol + ilen - 1
382  !
383  ! -- Write final string to line
384  write (line(icol:istop), cffmt) cval
385  !
386  icol = istop + 1
387  !
388  if (present(sep)) then
389  i = len(sep)
390  istop = icol + i
391  write (line(icol:istop), '(a)') sep
392  icol = istop
393  end if
394  !
395  ! -- Return
396  return
397  end subroutine uwword
398 
399  !> @brief Extract a word from a string
400  !!
401  !! Subroutine to extract a word from a line of text, and optionally
402  !! convert the word to a number. The last character in the line is
403  !! set to blank so that if any problems occur with finding a word,
404  !! istart and istop will point to this blank character. Thus, a word
405  !! will always be returned unless there is a numeric conversion error.
406  !! Be sure that the last character in line is not an important character
407  !! because it will always be set to blank.
408  !!
409  !! A word starts with the first character that is not a space or
410  !! comma, and ends when a subsequent character that is a space
411  !! or comma. Note that these parsing rules do not treat two
412  !! commas separated by one or more spaces as a null word.
413  !!
414  !! For a word that begins with "'" or '"', the word starts with
415  !! the character after the quote and ends with the character preceding
416  !! a subsequent quote. Thus, a quoted word can include spaces and commas.
417  !! The quoted word cannot contain a quote character of the same type
418  !! within the word but can contain a different quote character. For
419  !! example, "WORD'S" or 'WORD"S'.
420  !!
421  !! Number conversion error is written to unit iout if iout is positive;
422  !! error is written to default output if iout is 0; no error message is
423  !! written if iout is negative.
424  !!
425  !<
426  subroutine urword(line, icol, istart, istop, ncode, n, r, iout, in)
427  ! -- dummy
428  character(len=*) :: line !< line to parse
429  integer(I4B), intent(inout) :: icol !< current column in line
430  integer(I4B), intent(inout) :: istart !< starting character position of the word
431  integer(I4B), intent(inout) :: istop !< ending character position of the word
432  integer(I4B), intent(in) :: ncode !< word conversion flag (1) upper case, (2) integer, (3) real number
433  integer(I4B), intent(inout) :: n !< integer data type
434  real(dp), intent(inout) :: r !< float data type
435  integer(I4B), intent(in) :: iout !< output listing file unit
436  integer(I4B), intent(in) :: in !< input file unit number
437  ! -- local
438  character(len=20) string
439  character(len=30) rw
440  character(len=1) tab
441  character(len=1) charend
442  character(len=200) :: msg
443  character(len=linelength) :: msg_line
444  ! -- formats
445  character(len=*), parameter :: fmtmsgout1 = &
446  "(1X,'FILE UNIT ',I4,' : ERROR CONVERTING ""',A, &
447  & '"" TO ',A,' IN LINE:')"
448  character(len=*), parameter :: fmtmsgout2 = "(1x, &
449  & 'KEYBOARD INPUT : ERROR CONVERTING ""',a,'"" TO ',a,' IN LINE:')"
450  character(len=*), parameter :: fmtmsgout3 = "('File unit ', &
451  & I0,': Error converting ""',a,'"" to ',A,' in following line:')"
452  character(len=*), parameter :: fmtmsgout4 = &
453  "('Keyboard input: Error converting ""',a, &
454  & '"" to ',A,' in following line:')"
455  !
456  tab = char(9)
457  !
458  ! -- Set last char in LINE to blank and set ISTART and ISTOP to point
459  ! to this blank as a default situation when no word is found. If
460  ! starting location in LINE is out of bounds, do not look for a word.
461  linlen = len(line)
462  line(linlen:linlen) = ' '
463  istart = linlen
464  istop = linlen
465  linlen = linlen - 1
466  if (icol < 1 .or. icol > linlen) go to 100
467  !
468  ! -- Find start of word, which is indicated by first character that
469  ! is not a blank, a comma, or a tab.
470  do i = icol, linlen
471  if (line(i:i) /= ' ' .and. line(i:i) /= ',' .and. &
472  line(i:i) /= tab) go to 20
473  end do
474  icol = linlen + 1
475  go to 100
476  !
477  ! -- Found start of word. Look for end.
478  ! When word is quoted, only a quote can terminate it.
479  ! search for a single (char(39)) or double (char(34)) quote
480 20 if (line(i:i) == char(34) .or. line(i:i) == char(39)) then
481  if (line(i:i) == char(34)) then
482  charend = char(34)
483  else
484  charend = char(39)
485  end if
486  i = i + 1
487  if (i <= linlen) then
488  do j = i, linlen
489  if (line(j:j) == charend) go to 40
490  end do
491  end if
492  !
493  ! -- When word is not quoted, space, comma, or tab will terminate.
494  else
495  do j = i, linlen
496  if (line(j:j) == ' ' .or. line(j:j) == ',' .or. &
497  line(j:j) == tab) go to 40
498  end do
499  end if
500  !
501  ! -- End of line without finding end of word; set end of word to
502  ! end of line.
503  j = linlen + 1
504  !
505  ! -- Found end of word; set J to point to last character in WORD and
506  ! set ICOL to point to location for scanning for another word.
507 40 icol = j + 1
508  j = j - 1
509  if (j < i) go to 100
510  istart = i
511  istop = j
512  !
513  ! -- Convert word to upper case and RETURN if NCODE is 1.
514  if (ncode == 1) then
515  idiff = ichar('a') - ichar('A')
516  do k = istart, istop
517  if (line(k:k) >= 'a' .and. line(k:k) <= 'z') &
518  line(k:k) = char(ichar(line(k:k)) - idiff)
519  end do
520  return
521  end if
522  !
523  ! -- Convert word to a number if requested.
524 100 if (ncode == 2 .or. ncode == 3) then
525  rw = ' '
526  l = 30 - istop + istart
527  if (l < 1) go to 200
528  rw(l:30) = line(istart:istop)
529  if (ncode == 2) read (rw, '(i30)', err=200) n
530  if (ncode == 3) read (rw, '(f30.0)', err=200) r
531  end if
532  return
533  !
534  ! -- Number conversion error.
535 200 if (ncode == 3) then
536  string = 'a real number'
537  l = 13
538  else
539  string = 'an integer'
540  l = 10
541  end if
542  !
543  ! -- If output unit is negative, set last character of string to 'E'.
544  if (iout < 0) then
545  n = 0
546  r = 0.
547  line(linlen + 1:linlen + 1) = 'E'
548  return
549  !
550  ! -- If output unit is positive; write a message to output unit.
551  else if (iout > 0) then
552  if (in > 0) then
553  write (msg_line, fmtmsgout1) in, line(istart:istop), string(1:l)
554  else
555  write (msg_line, fmtmsgout2) line(istart:istop), string(1:l)
556  end if
557  call write_message(msg_line, iunit=iout, skipbefore=1)
558  call write_message(line, iunit=iout, fmt='(1x,a)')
559  !
560  ! -- If output unit is 0; write a message to default output.
561  else
562  if (in > 0) then
563  write (msg_line, fmtmsgout1) in, line(istart:istop), string(1:l)
564  else
565  write (msg_line, fmtmsgout2) line(istart:istop), string(1:l)
566  end if
567  call write_message(msg_line, iunit=iout, skipbefore=1)
568  call write_message(line, iunit=iout, fmt='(1x,a)')
569  end if
570  !
571  ! -- STOP after storing error message.
572  call lowcase(string)
573  if (in > 0) then
574  write (msg, fmtmsgout3) in, line(istart:istop), trim(string)
575  else
576  write (msg, fmtmsgout4) line(istart:istop), trim(string)
577  end if
578  !
579  call store_error(msg)
580  call store_error(trim(line))
581  call store_error_unit(in)
582  !
583  ! -- Return
584  return
585  end subroutine urword
586 
587  !> @brief Print a label for a list
588  !<
589  subroutine ulstlb(iout, label, caux, ncaux, naux)
590  ! -- dummy
591  character(len=*) :: label
592  character(len=16) :: caux(ncaux)
593  ! -- local
594  character(len=400) buf
595  ! -- constant
596  character(len=1) dash(400)
597  data dash/400*'-'/
598  ! -- formats
599  character(len=*), parameter :: fmtmsgout1 = "(1x, a)"
600  character(len=*), parameter :: fmtmsgout2 = "(1x, 400a)"
601  !
602  ! -- Construct the complete label in BUF. Start with BUF=LABEL.
603  buf = label
604  !
605  ! -- Add auxiliary data names if there are any.
606  nbuf = len(label) + 9
607  if (naux > 0) then
608  do i = 1, naux
609  n1 = nbuf + 1
610  nbuf = nbuf + 16
611  buf(n1:nbuf) = caux(i)
612  end do
613  end if
614  !
615  ! -- Write the label.
616  write (iout, fmtmsgout1) buf(1:nbuf)
617  !
618  ! -- Add a line of dashes.
619  write (iout, fmtmsgout2) (dash(j), j=1, nbuf)
620  !
621  ! -- Return
622  return
623  end subroutine ulstlb
624 
625  !> @brief Write header records for cell-by-cell flow terms for one component
626  !! of flow plus auxiliary data using a list structure
627  !!
628  !! Each item in the list is written by module UBDSVB
629  !<
630  subroutine ubdsv4(kstp, kper, text, naux, auxtxt, ibdchn, &
631  & ncol, nrow, nlay, nlist, iout, delt, pertim, totim)
632  ! -- dummy
633  character(len=16) :: text
634  character(len=16), dimension(:) :: auxtxt
635  real(dp), intent(in) :: delt, pertim, totim
636  ! -- formats
637  character(len=*), parameter :: fmt = &
638  & "(1X,'UBDSV4 SAVING ',A16,' ON UNIT',I7,' AT TIME STEP',I7,"// &
639  & "', STRESS PERIOD',I7)"
640  !
641  ! -- Write unformatted records identifying data
642  if (iout > 0) write (iout, fmt) text, ibdchn, kstp, kper
643  write (ibdchn) kstp, kper, text, ncol, nrow, -nlay
644  write (ibdchn) 5, delt, pertim, totim
645  write (ibdchn) naux + 1
646  if (naux > 0) write (ibdchn) (auxtxt(n), n=1, naux)
647  write (ibdchn) nlist
648  !
649  ! -- Return
650  return
651  end subroutine ubdsv4
652 
653  !> @brief Write one value of cell-by-cell flow plus auxiliary data using a
654  !! list structure
655  !<
656  subroutine ubdsvb(ibdchn, icrl, q, val, nvl, naux, laux)
657  ! -- dummy
658  real(dp), dimension(nvl) :: val
659  real(dp) :: q
660  !
661  ! -- Write cell number and flow rate
662  IF (naux > 0) then
663  n2 = laux + naux - 1
664  write (ibdchn) icrl, q, (val(n), n=laux, n2)
665  else
666  write (ibdchn) icrl, q
667  end if
668  !
669  ! -- Return
670  return
671  end subroutine ubdsvb
672 
673  !> @brief Output column numbers above a matrix printout
674  !!
675  !! nlbl1 is the start column label (number)
676  !! nlbl2 is the stop column label (number)
677  !! nspace is number of blank spaces to leave at start of line
678  !! ncpl is number of column numbers per line
679  !! ndig is number of characters in each column field
680  !! iout is output channel
681  !<
682  subroutine ucolno(nlbl1, nlbl2, nspace, ncpl, ndig, iout)
683  ! -- local
684  character(len=1) :: dot, space, dg, bf
685  dimension :: bf(1000), dg(10)
686  ! -- constants
687  data dg(1), dg(2), dg(3), dg(4), dg(5), dg(6), dg(7), dg(8), dg(9), dg(10)/ &
688  & '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'/
689  data dot, space/'.', ' '/
690  ! -- formats
691  character(len=*), parameter :: fmtmsgout1 = "(1x)"
692  character(len=*), parameter :: fmtmsgout2 = "(1x, 1000a1)"
693  !
694  ! -- Calculate # of columns to be printed (nlbl), width
695  ! of a line (ntot), number of lines (nwrap).
696  if (iout <= 0) return
697  write (iout, fmtmsgout1)
698  !
699  nlbl = nlbl2 - nlbl1 + 1
700  n = nlbl
701  !
702  if (nlbl < ncpl) n = ncpl
703  ntot = nspace + n * ndig
704  !
705  if (ntot > 1000) go to 50
706  nwrap = (nlbl - 1) / ncpl + 1
707  j1 = nlbl1 - ncpl
708  j2 = nlbl1 - 1
709  !
710  ! -- Build and print each line
711  do n = 1, nwrap
712  !
713  ! -- Clear the buffer (BF)
714  do i = 1, 1000
715  bf(i) = space
716  end do
717  nbf = nspace
718  !
719  ! -- Determine first (j1) and last (j2) column # for this line.
720  j1 = j1 + ncpl
721  j2 = j2 + ncpl
722  if (j2 > nlbl2) j2 = nlbl2
723  !
724  ! -- Load the column #'s into the buffer.
725  do j = j1, j2
726  nbf = nbf + ndig
727  i2 = j / 10
728  i1 = j - i2 * 10 + 1
729  bf(nbf) = dg(i1)
730  if (i2 == 0) go to 30
731  i3 = i2 / 10
732  i2 = i2 - i3 * 10 + 1
733  bf(nbf - 1) = dg(i2)
734  if (i3 == 0) go to 30
735  i4 = i3 / 10
736  i3 = i3 - i4 * 10 + 1
737  bf(nbf - 2) = dg(i3)
738  if (i4 == 0) go to 30
739  if (i4 > 9) then
740  ! -- If more than 4 digits, use "X" for 4th digit.
741  bf(nbf - 3) = 'X'
742  else
743  bf(nbf - 3) = dg(i4 + 1)
744  end if
745 30 end do
746  !
747  ! -- Print the contents of the buffer (i.e. print the line).
748  write (iout, fmtmsgout2) (bf(i), i=1, nbf)
749  !
750  end do
751  !
752  ! -- Print a line of dots (for aesthetic purposes only).
753 50 ntot = ntot
754  if (ntot > 1000) ntot = 1000
755  write (iout, fmtmsgout2) (dot, i=1, ntot)
756  !
757  ! -- Return
758  return
759  end subroutine ucolno
760 
761  !> @brief Print 1 layer array
762  !<
763  subroutine ulaprw(buf, text, kstp, kper, ncol, nrow, ilay, iprn, iout)
764  ! -- dummy
765  character(len=16) :: text
766  real(dp), dimension(ncol, nrow) :: buf
767  ! -- formats
768  character(len=*), parameter :: fmtmsgout1 = &
769  & "('1', /2x, a, ' IN LAYER ',I3,' AT END OF TIME STEP ',I3, &
770  & ' IN STRESS PERIOD ',I4/2x,75('-'))"
771  character(len=*), parameter :: fmtmsgout2 = &
772  & "('1',/1x,A,' FOR CROSS SECTION AT END OF TIME STEP',I3, &
773  & ' IN STRESS PERIOD ',I4/1x,79('-'))"
774  character(len=*), parameter :: fmtg10 = &
775  & "(1X,I3,2X,1PG10.3,10(1X,G10.3):/(5X,11(1X,G10.3)))"
776  character(len=*), parameter :: fmtg13 = &
777  & "(1x,I3,2x,1PG13.6,8(1x,G13.6):/(5x,9(1x,G13.6)))"
778  character(len=*), parameter :: fmtf7pt1 = &
779  & "(1x,I3,1x,15(1x,F7.1):/(5x,15(1x,F7.1)))"
780  character(len=*), parameter :: fmtf7pt2 = &
781  & "(1x,I3,1x,15(1x,F7.2):/(5x,15(1x,F7.2)))"
782  character(len=*), parameter :: fmtf7pt3 = &
783  & "(1x,I3,1x,15(1x,F7.3):/(5x,15(1x,F7.3)))"
784  character(len=*), parameter :: fmtf7pt4 = &
785  & "(1x,I3,1x,15(1x,F7.4):/(5x,15(1x,F7.4)))"
786  character(len=*), parameter :: fmtf5pt0 = &
787  & "(1x,I3,1x,20(1x,F5.0):/(5x,20(1x,F5.0)))"
788  character(len=*), parameter :: fmtf5pt1 = &
789  & "(1x,I3,1x,20(1x,F5.1):/(5x,20(1x,F5.1)))"
790  character(len=*), parameter :: fmtf5pt2 = &
791  & "(1x,I3,1x,20(1x,F5.2):/(5x,20(1x,F5.2)))"
792  character(len=*), parameter :: fmtf5pt3 = &
793  & "(1x,I3,1x,20(1x,F5.3):/(5x,20(1x,F5.3)))"
794  character(len=*), parameter :: fmtf5pt4 = &
795  & "(1x,I3,1x,20(1x,F5.4):/(5x,20(1x,F5.4)))"
796  character(len=*), parameter :: fmtg11 = &
797  & "(1x,I3,2x,1PG11.4,9(1x,G11.4):/(5x,10(1x,G11.4)))"
798  character(len=*), parameter :: fmtf6pt0 = &
799  & "(1x,I3,1x,10(1x,F6.0):/(5X,10(1x,F6.0)))"
800  character(len=*), parameter :: fmtf6pt1 = &
801  & "(1x,I3,1x,10(1x,F6.1):/(5x,10(1x,F6.1)))"
802  character(len=*), parameter :: fmtf6pt2 = &
803  & "(1x,I3,1x,10(1x,F6.2):/(5x,10(1x,F6.2)))"
804  character(len=*), parameter :: fmtf6pt3 = &
805  & "(1x,I3,1x,10(1x,F6.3):/(5x,10(1x,F6.3)))"
806  character(len=*), parameter :: fmtf6pt4 = &
807  & "(1x,I3,1x,10(1x,F6.4):/(5x,10(1x,F6.4)))"
808  character(len=*), parameter :: fmtf6pt5 = &
809  & "(1x,I3,1x,10(1x,F6.5):/(5x,10(1x,F6.5)))"
810  character(len=*), parameter :: fmtg12 = &
811  & "(1x,I3,2x,1PG12.5,4(1x,G12.5):/(5x,5(1x,G12.5)))"
812  character(len=*), parameter :: fmtg11pt4 = &
813  & "(1x,I3,2x,1PG11.4,5(1x,G11.4):/(5x,6(1x,G11.4)))"
814  character(len=*), parameter :: fmtg9pt2 = &
815  & "(1x,I3,2x,1PG9.2,6(1x,G9.2):/(5x,7(1x,G9.2)))"
816  !
817  if (iout <= 0) return
818  ! -- Print a header depending on ilay
819  if (ilay > 0) then
820  write (iout, fmtmsgout1) text, ilay, kstp, kper
821  else if (ilay < 0) then
822  write (iout, fmtmsgout2) text, kstp, kper
823  end if
824  !
825  ! -- Make sure the format code (ip or iprn) is between 1 and 21
826  ip = iprn
827  if (ip < 1 .or. ip > 21) ip = 12
828  !
829  ! -- Call the utility module ucolno to print column numbers.
830  if (ip == 1) call ucolno(1, ncol, 0, 11, 11, iout)
831  if (ip == 2) call ucolno(1, ncol, 0, 9, 14, iout)
832  if (ip >= 3 .and. ip <= 6) call ucolno(1, ncol, 3, 15, 8, iout)
833  if (ip >= 7 .and. ip <= 11) call ucolno(1, ncol, 3, 20, 6, iout)
834  if (ip == 12) call ucolno(1, ncol, 0, 10, 12, iout)
835  if (ip >= 13 .and. ip <= 18) call ucolno(1, ncol, 3, 10, 7, iout)
836  if (ip == 19) call ucolno(1, ncol, 0, 5, 13, iout)
837  if (ip == 20) call ucolno(1, ncol, 0, 6, 12, iout)
838  if (ip == 21) call ucolno(1, ncol, 0, 7, 10, iout)
839  !
840  ! -- Loop through the rows printing each one in its entirety.
841  do i = 1, nrow
842  select case (ip)
843  !
844  case (1)
845  ! -- format 11G10.3
846  write (iout, fmtg10) i, (buf(j, i), j=1, ncol)
847  !
848  case (2)
849  ! -- format 9G13.6
850  write (iout, fmtg13) i, (buf(j, i), j=1, ncol)
851  !
852  case (3)
853  ! -- format 15F7.1
854  write (iout, fmtf7pt1) i, (buf(j, i), j=1, ncol)
855  !
856  case (4)
857  ! -- format 15F7.2
858  write (iout, fmtf7pt2) i, (buf(j, i), j=1, ncol)
859  !
860  case (5)
861  ! -- format 15F7.3
862  write (iout, fmtf7pt3) i, (buf(j, i), j=1, ncol)
863  !
864  case (6)
865  ! -- format 15F7.4
866  write (iout, fmtf7pt4) i, (buf(j, i), j=1, ncol)
867  !
868  case (7)
869  ! -- format 20F5.0
870  write (iout, fmtf5pt0) i, (buf(j, i), j=1, ncol)
871  !
872  case (8)
873  ! -- format 20F5.1
874  write (iout, fmtf5pt1) i, (buf(j, i), j=1, ncol)
875  !
876  case (9)
877  ! -- format 20F5.2
878  write (iout, fmtf5pt2) i, (buf(j, i), j=1, ncol)
879  !
880  case (10)
881  ! -- format 20F5.3
882  write (iout, fmtf5pt3) i, (buf(j, i), j=1, ncol)
883  !
884  case (11)
885  ! -- format 20F5.4
886  write (iout, fmtf5pt4) i, (buf(j, i), j=1, ncol)
887  !
888  case (12)
889  ! -- format 10G11.4
890  write (iout, fmtg11) i, (buf(j, i), j=1, ncol)
891  !
892  case (13)
893  ! -- format 10F6.0
894  write (iout, fmtf6pt0) i, (buf(j, i), j=1, ncol)
895  !
896  case (14)
897  ! -- format 10F6.1
898  write (iout, fmtf6pt1) i, (buf(j, i), j=1, ncol)
899  !
900  case (15)
901  ! -- format 10F6.2
902  write (iout, fmtf6pt2) i, (buf(j, i), j=1, ncol)
903  !
904  case (16)
905  ! -- format 10F6.3
906  write (iout, fmtf6pt3) i, (buf(j, i), j=1, ncol)
907  !
908  case (17)
909  ! -- format 10F6.4
910  write (iout, fmtf6pt4) i, (buf(j, i), j=1, ncol)
911  !
912  case (18)
913  ! -- format 10F6.5
914  write (iout, fmtf6pt5) i, (buf(j, i), j=1, ncol)
915  !
916  case (19)
917  ! -- format 5G12.5
918  write (iout, fmtg12) i, (buf(j, i), j=1, ncol)
919  !
920  case (20)
921  ! -- format 6G11.4
922  write (iout, fmtg11pt4) i, (buf(j, i), j=1, ncol)
923  !
924  case (21)
925  ! -- format 7G9.2
926  write (iout, fmtg9pt2) i, (buf(j, i), j=1, ncol)
927  !
928  end select
929  end do
930  !
931  ! -- Flush file
932  flush (iout)
933  !
934  ! -- Return
935  return
936  end subroutine ulaprw
937 
938  !> @brief Save 1 layer array on disk
939  !<
940  subroutine ulasav(buf, text, kstp, kper, pertim, totim, ncol, nrow, &
941  ilay, ichn)
942  ! -- dummy
943  character(len=16) :: text
944  real(dp), dimension(ncol, nrow) :: buf
945  real(dp) :: pertim, totim
946  !
947  ! -- Write an unformatted record containing identifying information
948  write (ichn) kstp, kper, pertim, totim, text, ncol, nrow, ilay
949  !
950  ! -- Write an unformatted record containing array values. The array is
951  ! dimensioned (ncol,nrow)
952  write (ichn) ((buf(ic, ir), ic=1, ncol), ir=1, nrow)
953  !
954  ! -- flush file
955  flush (ichn)
956  !
957  ! -- Return
958  return
959  end subroutine ulasav
960 
961  !> @brief Record cell-by-cell flow terms for one component of flow as a 3-D
962  !! array with extra record to indicate delt, pertim, and totim
963  !<
964  subroutine ubdsv1(kstp, kper, text, ibdchn, buff, ncol, nrow, nlay, iout, &
965  delt, pertim, totim)
966  implicit none
967  ! -- dummy
968  integer(I4B), intent(in) :: kstp
969  integer(I4B), intent(in) :: kper
970  character(len=*), intent(in) :: text
971  integer(I4B), intent(in) :: ibdchn
972  real(dp), dimension(:), intent(in) :: buff
973  integer(I4B), intent(in) :: ncol
974  integer(I4B), intent(in) :: nrow
975  integer(I4B), intent(in) :: nlay
976  integer(I4B), intent(in) :: iout
977  real(dp), intent(in) :: delt
978  real(dp), intent(in) :: pertim
979  real(dp), intent(in) :: totim
980  ! -- format
981  character(len=*), parameter :: fmt = &
982  & "(1X,'UBDSV1 SAVING ',A16,' ON UNIT',I7,' AT TIME STEP',I7,"// &
983  & "', STRESS PERIOD',I7)"
984  !
985  ! -- Write records
986  if (iout > 0) write (iout, fmt) text, ibdchn, kstp, kper
987  write (ibdchn) kstp, kper, text, ncol, nrow, -nlay
988  write (ibdchn) 1, delt, pertim, totim
989  write (ibdchn) buff
990  !
991  ! -- flush file
992  flush (ibdchn)
993  !
994  ! -- Return
995  return
996  end subroutine ubdsv1
997 
998  !> @brief Write header records for cell-by-cell flow terms for one component
999  !! of flow.
1000  !!
1001  !! Each item in the list is written by module ubdsvc
1002  !<
1003  subroutine ubdsv06(kstp, kper, text, modelnam1, paknam1, modelnam2, paknam2, &
1004  ibdchn, naux, auxtxt, ncol, nrow, nlay, nlist, iout, &
1005  delt, pertim, totim)
1006  implicit none
1007  ! -- dummy
1008  integer(I4B), intent(in) :: kstp
1009  integer(I4B), intent(in) :: kper
1010  character(len=*), intent(in) :: text
1011  character(len=*), intent(in) :: modelnam1
1012  character(len=*), intent(in) :: paknam1
1013  character(len=*), intent(in) :: modelnam2
1014  character(len=*), intent(in) :: paknam2
1015  integer(I4B), intent(in) :: naux
1016  character(len=16), dimension(:), intent(in) :: auxtxt
1017  integer(I4B), intent(in) :: ibdchn
1018  integer(I4B), intent(in) :: ncol
1019  integer(I4B), intent(in) :: nrow
1020  integer(I4B), intent(in) :: nlay
1021  integer(I4B), intent(in) :: nlist
1022  integer(I4B), intent(in) :: iout
1023  real(dp), intent(in) :: delt
1024  real(dp), intent(in) :: pertim
1025  real(dp), intent(in) :: totim
1026  ! -- local
1027  integer(I4B) :: n
1028  ! -- format
1029  character(len=*), parameter :: fmt = &
1030  & "(1X,'UBDSV06 SAVING ',A16,' IN MODEL ',A16,' PACKAGE ',A16,"// &
1031  & "'CONNECTED TO MODEL ',A16,' PACKAGE ',A16,"// &
1032  & "' ON UNIT',I7,' AT TIME STEP',I7,', STRESS PERIOD',I7)"
1033  !
1034  ! -- Write unformatted records identifying data.
1035  if (iout > 0) write (iout, fmt) text, modelnam1, paknam1, modelnam2, &
1036  paknam2, ibdchn, kstp, kper
1037  write (ibdchn) kstp, kper, text, ncol, nrow, -nlay
1038  write (ibdchn) 6, delt, pertim, totim
1039  write (ibdchn) modelnam1
1040  write (ibdchn) paknam1
1041  write (ibdchn) modelnam2
1042  write (ibdchn) paknam2
1043  write (ibdchn) naux + 1
1044  if (naux > 0) write (ibdchn) (auxtxt(n), n=1, naux)
1045  write (ibdchn) nlist
1046  !
1047  ! -- Return
1048  return
1049  end subroutine ubdsv06
1050 
1051  !> @brief Write one value of cell-by-cell flow using a list structure.
1052  !!
1053  !! From node (n) and to node (n2) are written to the file
1054  !<
1055  subroutine ubdsvc(ibdchn, n, q, naux, aux)
1056  implicit none
1057  ! -- dummy
1058  integer(I4B), intent(in) :: ibdchn
1059  integer(I4B), intent(in) :: n
1060  real(dp), intent(in) :: q
1061  integer(I4B), intent(in) :: naux
1062  real(dp), dimension(naux), intent(in) :: aux
1063  ! -- local
1064  integer(I4B) :: nn
1065  !
1066  ! -- Write record
1067  if (naux > 0) then
1068  write (ibdchn) n, q, (aux(nn), nn=1, naux)
1069  else
1070  write (ibdchn) n, q
1071  end if
1072  !
1073  ! -- Return
1074  return
1075  end subroutine ubdsvc
1076 
1077  !> @brief Write one value of cell-by-cell flow using a list structure.
1078  !!
1079  !! From node (n) and to node (n2) are written to the file
1080  !<
1081  subroutine ubdsvd(ibdchn, n, n2, q, naux, aux)
1082  implicit none
1083  ! -- dummy
1084  integer(I4B), intent(in) :: ibdchn
1085  integer(I4B), intent(in) :: n
1086  integer(I4B), intent(in) :: n2
1087  real(dp), intent(in) :: q
1088  integer(I4B), intent(in) :: naux
1089  real(dp), dimension(naux), intent(in) :: aux
1090  ! -- local
1091  integer(I4B) :: nn
1092  !
1093  ! -- Write record
1094  if (naux > 0) then
1095  write (ibdchn) n, n2, q, (aux(nn), nn=1, naux)
1096  else
1097  write (ibdchn) n, n2, q
1098  end if
1099  !
1100  ! -- Return
1101  return
1102  end subroutine ubdsvd
1103 
1104  !> @brief Perform a case-insensitive comparison of two words
1105  !<
1106  logical function same_word(word1, word2)
1107  implicit none
1108  ! -- dummy
1109  character(len=*), intent(in) :: word1, word2
1110  ! -- local
1111  character(len=200) :: upword1, upword2
1112  !
1113  upword1 = word1
1114  call upcase(upword1)
1115  upword2 = word2
1116  call upcase(upword2)
1117  same_word = (upword1 == upword2)
1118  !
1119  ! -- Return
1120  return
1121  end function same_word
1122 
1123  !> @brief Function for string manipulation
1124  !<
1125  function str_pad_left(str, width) result(res)
1126  ! -- local
1127  character(len=*), intent(in) :: str
1128  integer, intent(in) :: width
1129  ! -- Return
1130  character(len=max(len_trim(str), width)) :: res
1131  !
1132  res = str
1133  res = adjustr(res)
1134  !
1135  ! -- Return
1136  return
1137  end function
1138 
1139  subroutine unitinquire(iu)
1140  ! -- dummy
1141  integer(I4B) :: iu
1142  ! -- local
1143  character(len=LINELENGTH) :: line
1144  character(len=100) :: fname, ac, act, fm, frm, seq, unf
1145  ! -- format
1146  character(len=*), parameter :: fmta = &
1147  &"('unit:',i4,' name:',a,' access:',a,' action:',a)"
1148  character(len=*), parameter :: fmtb = &
1149  &"(' formatted:',a,' sequential:',a,' unformatted:',a,' form:',a)"
1150  !
1151  ! -- set strings using inquire statement
1152  inquire (unit=iu, name=fname, access=ac, action=act, formatted=fm, &
1153  sequential=seq, unformatted=unf, form=frm)
1154  !
1155  ! -- write the results of the inquire statement
1156  write (line, fmta) iu, trim(fname), trim(ac), trim(act)
1157  call write_message(line)
1158  write (line, fmtb) trim(fm), trim(seq), trim(unf), trim(frm)
1159  call write_message(line)
1160  !
1161  ! -- Return
1162  return
1163  end subroutine unitinquire
1164 
1165  !> @brief Parse a line into words.
1166  !!
1167  !! Blanks and commas are recognized as delimiters. Multiple blanks between
1168  !! words is OK, but multiple commas between words is treated as an error.
1169  !! Quotation marks are not recognized as delimiters.
1170  !<
1171  subroutine parseline(line, nwords, words, inunit, filename)
1172  ! -- modules
1173  use constantsmodule, only: linelength
1174  implicit none
1175  ! -- dummy
1176  character(len=*), intent(in) :: line
1177  integer(I4B), intent(inout) :: nwords
1178  character(len=*), allocatable, dimension(:), intent(inout) :: words
1179  integer(I4B), intent(in), optional :: inunit
1180  character(len=*), intent(in), optional :: filename
1181  ! -- local
1182  integer(I4B) :: i, idum, istart, istop, linelen, lloc
1183  real(dp) :: rdum
1184  !
1185  nwords = 0
1186  if (allocated(words)) then
1187  deallocate (words)
1188  end if
1189  linelen = len(line)
1190  !
1191  ! -- get the number of words in a line and allocate words array
1192  nwords = get_nwords(line)
1193  allocate (words(nwords))
1194  !
1195  ! -- Populate words array and return
1196  lloc = 1
1197  do i = 1, nwords
1198  call urword(line, lloc, istart, istop, 0, idum, rdum, 0, 0)
1199  words(i) = line(istart:istop)
1200  end do
1201  !
1202  ! -- Return
1203  return
1204  end subroutine parseline
1205 
1206  !> @brief Print 1 layer array with user formatting in wrap format
1207  !<
1208  subroutine ulaprufw(ncol, nrow, kstp, kper, ilay, iout, buf, text, userfmt, &
1209  nvalues, nwidth, editdesc)
1210  implicit none
1211  ! -- dummy
1212  integer(I4B), intent(in) :: ncol, nrow, kstp, kper, ilay, iout
1213  real(dp), dimension(ncol, nrow), intent(in) :: buf
1214  character(len=*), intent(in) :: text
1215  character(len=*), intent(in) :: userfmt
1216  integer(I4B), intent(in) :: nvalues, nwidth
1217  character(len=1), intent(in) :: editdesc
1218  ! -- local
1219  integer(I4B) :: i, j, nspaces
1220  ! -- formats
1221  character(len=*), parameter :: fmtmsgout1 = &
1222  "('1',/2X,A,' IN LAYER ',I3,' AT END OF TIME STEP ',I3, &
1223 & ' IN STRESS PERIOD ',I4/2X,75('-'))"
1224  character(len=*), parameter :: fmtmsgout2 = &
1225  "('1',/1X,A,' FOR CROSS SECTION AT END OF TIME STEP',I3, &
1226 & ' IN STRESS PERIOD ',I4/1X,79('-'))"
1227  !
1228  if (iout <= 0) return
1229  ! -- Print a header depending on ILAY
1230  if (ilay > 0) then
1231  write (iout, fmtmsgout1) trim(text), ilay, kstp, kper
1232  else if (ilay < 0) then
1233  write (iout, fmtmsgout2) trim(text), kstp, kper
1234  end if
1235  !
1236  ! -- Print column numbers.
1237  nspaces = 0
1238  if (editdesc == 'F') nspaces = 3
1239  call ucolno(1, ncol, nspaces, nvalues, nwidth + 1, iout)
1240  !
1241  ! -- Loop through the rows, printing each one in its entirety.
1242  do i = 1, nrow
1243  write (iout, userfmt) i, (buf(j, i), j=1, ncol)
1244  end do
1245  !
1246  ! -- flush file
1247  flush (iout)
1248  !
1249  ! -- Return
1250  return
1251  end subroutine ulaprufw
1252 
1253  !> @brief This function reads a line of arbitrary length and returns it.
1254  !!
1255  !! The returned string can be stored in a deferred-length character variable,
1256  !! for example:
1257  !!
1258  !! integer(I4B) :: iu
1259  !! character(len=:), allocatable :: my_string
1260  !! logical :: eof
1261  !! iu = 8
1262  !! open(iu,file='my_file')
1263  !! my_string = read_line(iu, eof)
1264  !<
1265  function read_line(iu, eof) result(astring)
1266  !
1267  implicit none
1268  ! -- dummy
1269  integer(I4B), intent(in) :: iu
1270  logical, intent(out) :: eof
1271  character(len=:), allocatable :: astring
1272  ! -- local
1273  integer(I4B) :: isize, istat
1274  character(len=256) :: buffer
1275  character(len=1000) :: ermsg, fname
1276  character(len=7) :: fmtd
1277  logical :: lop
1278  ! -- formats
1279  character(len=*), parameter :: fmterrmsg1 = &
1280  & "('Error in read_line: File ',i0,' is not open.')"
1281  character(len=*), parameter :: fmterrmsg2 = &
1282  & "('Error in read_line: Attempting to read text ' // &
1283  & 'from unformatted file: ""',a,'""')"
1284  character(len=*), parameter :: fmterrmsg3 = &
1285  & "('Error reading from file ""',a,'"" opened on unit ',i0, &
1286  & ' in read_line.')"
1287  !
1288  astring = ''
1289  eof = .false.
1290  do
1291  read (iu, '(a)', advance='NO', iostat=istat, size=isize, end=99) buffer
1292  if (istat > 0) then
1293  ! Determine error if possible, report it, and stop.
1294  if (iu <= 0) then
1295  ermsg = 'Programming error in call to read_line: '// &
1296  'Attempt to read from unit number <= 0'
1297  else
1298  inquire (unit=iu, opened=lop, name=fname, formatted=fmtd)
1299  if (.not. lop) then
1300  write (ermsg, fmterrmsg1) iu
1301  elseif (fmtd == 'NO' .or. fmtd == 'UNKNOWN') then
1302  write (ermsg, fmterrmsg2) trim(fname)
1303  else
1304  write (ermsg, fmterrmsg3) trim(fname), iu
1305  end if
1306  end if
1307  call store_error(ermsg)
1308  call store_error_unit(iu)
1309  end if
1310  astring = astring//buffer(:isize)
1311  ! -- An end-of-record condition stops the loop.
1312  if (istat < 0) then
1313  return
1314  end if
1315  end do
1316  !
1317  return
1318 99 continue
1319  !
1320  ! An end-of-file condition returns an empty string.
1321  eof = .true.
1322  !
1323  ! -- Return
1324  return
1325  end function read_line
1326 
1327  subroutine getfilefrompath(pathname, filename)
1328  implicit none
1329  ! -- dummy
1330  character(len=*), intent(in) :: pathname
1331  character(len=*), intent(out) :: filename
1332  ! -- local
1333  integer(I4B) :: i, istart, istop, lenpath
1334  character(len=1) :: fs = '/'
1335  character(len=1) :: bs = '\'
1336  !
1337  filename = ''
1338  lenpath = len_trim(pathname)
1339  istart = 1
1340  istop = lenpath
1341  loop: do i = lenpath, 1, -1
1342  if (pathname(i:i) == fs .or. pathname(i:i) == bs) then
1343  if (i == istop) then
1344  istop = istop - 1
1345  else
1346  istart = i + 1
1347  exit loop
1348  end if
1349  end if
1350  end do loop
1351  if (istop >= istart) then
1352  filename = pathname(istart:istop)
1353  end if
1354  !
1355  ! -- Return
1356  return
1357  end subroutine getfilefrompath
1358 
1359  !> @brief Starting at position icol, define string as line(istart:istop).
1360  !!
1361  !! If string can be interpreted as an integer(I4B), return integer in idnum
1362  !! argument. If token is not an integer(I4B), assume it is a boundary name,
1363  !! return NAMEDBOUNDFLAG in idnum, convert string to uppercase and return it
1364  !! in bndname.
1365  !<
1366  subroutine extract_idnum_or_bndname(line, icol, istart, istop, idnum, bndname)
1367  implicit none
1368  ! -- dummy
1369  character(len=*), intent(inout) :: line
1370  integer(I4B), intent(inout) :: icol, istart, istop
1371  integer(I4B), intent(out) :: idnum
1372  character(len=LENBOUNDNAME), intent(out) :: bndname
1373  ! -- local
1374  integer(I4B) :: istat, ndum, ncode = 0
1375  real(dp) :: rdum
1376  !
1377  call urword(line, icol, istart, istop, ncode, ndum, rdum, 0, 0)
1378  read (line(istart:istop), *, iostat=istat) ndum
1379  if (istat == 0) then
1380  idnum = ndum
1381  bndname = ''
1382  else
1383  idnum = namedboundflag
1384  bndname = line(istart:istop)
1385  call upcase(bndname)
1386  end if
1387  !
1388  ! -- Return
1389  return
1390  end subroutine extract_idnum_or_bndname
1391 
1392  !> @brief Read auxiliary variables from an input line
1393  !<
1394  subroutine urdaux(naux, inunit, iout, lloc, istart, istop, auxname, line, text)
1395  ! -- modules
1396  use arrayhandlersmodule, only: expandarray
1397  use constantsmodule, only: lenauxname
1398  ! -- implicit
1399  implicit none
1400  ! -- dummy
1401  integer(I4B), intent(inout) :: naux
1402  integer(I4B), intent(in) :: inunit
1403  integer(I4B), intent(in) :: iout
1404  integer(I4B), intent(inout) :: lloc
1405  integer(I4B), intent(inout) :: istart
1406  integer(I4B), intent(inout) :: istop
1407  character(len=LENAUXNAME), allocatable, dimension(:), intent(inout) :: auxname
1408  character(len=*), intent(inout) :: line
1409  character(len=*), intent(in) :: text
1410  ! -- local
1411  integer(I4B) :: n, linelen
1412  integer(I4B) :: iauxlen
1413  real(dp) :: rval
1414  !
1415  linelen = len(line)
1416  if (naux > 0) then
1417  write (errmsg, '(a)') 'Auxiliary variables already specified. '// &
1418  & 'Auxiliary variables must be specified on one line in the '// &
1419  & 'options block.'
1420  call store_error(errmsg)
1421  call store_error_unit(inunit)
1422  end if
1423  auxloop: do
1424  call urword(line, lloc, istart, istop, 1, n, rval, iout, inunit)
1425  if (istart >= linelen) exit auxloop
1426  iauxlen = istop - istart + 1
1427  if (iauxlen > lenauxname) then
1428  write (errmsg, '(a, a, a, i0, a, i0, a)') &
1429  'Found auxiliary variable (', line(istart:istop), &
1430  ') with a name of size ', iauxlen, &
1431  '. Auxiliary variable names must be len than or equal&
1432  & to ', lenauxname, ' characters.'
1433  call store_error(errmsg)
1434  call store_error_unit(inunit)
1435  end if
1436  naux = naux + 1
1437  call expandarray(auxname)
1438  auxname(naux) = line(istart:istop)
1439  if (iout > 0) then
1440  write (iout, "(4X,'AUXILIARY ',a,' VARIABLE: ',A)") &
1441  trim(adjustl(text)), auxname(naux)
1442  end if
1443  end do auxloop
1444  !
1445  ! -- Return
1446  return
1447  end subroutine urdaux
1448 
1449  !> @brief Define the print or save format
1450  !!
1451  !! Define cdatafmp as a Fortran output format based on user input. Also define
1452  !! nvalues, nwidth, and editdesc.
1453  !!
1454  !! Syntax for linein:
1455  !! COLUMNS nval WIDTH nwid [DIGITS ndig [options]]
1456  !!
1457  !! Where:
1458  !! nval = Number of values per line.
1459  !! nwid = Number of character places to be used for each value.
1460  !! ndig = Number of digits to the right of the decimal point (required
1461  !! for real array).
1462  !! options are:
1463  !! editoption: One of [EXPONENTIAL, FIXED, GENERAL, SCIENTIFIC]
1464  !! A default value should be passed in for editdesc as G, I, E, F, or S.
1465  !! If I is passed in, then the fortran format will be for an integer variable.
1466  !<
1467  subroutine print_format(linein, cdatafmp, editdesc, nvaluesp, nwidthp, inunit)
1468  ! -- dummy
1469  character(len=*), intent(in) :: linein
1470  character(len=*), intent(inout) :: cdatafmp
1471  character(len=*), intent(inout) :: editdesc
1472  integer(I4B), intent(inout) :: nvaluesp
1473  integer(I4B), intent(inout) :: nwidthp
1474  integer(I4B), intent(in) :: inunit
1475  ! -- local
1476  character(len=len(linein)) :: line
1477  character(len=20), dimension(:), allocatable :: words
1478  character(len=100) :: ermsg
1479  integer(I4B) :: ndigits = 0, nwords = 0
1480  integer(I4B) :: i, ierr
1481  logical :: isint
1482  !
1483  ! -- Parse line and initialize values
1484  line(:) = linein(:)
1485  call parseline(line, nwords, words, inunit)
1486  ierr = 0
1487  i = 0
1488  isint = .false.
1489  if (editdesc == 'I') isint = .true.
1490  !
1491  ! -- Check array name
1492  if (nwords < 1) then
1493  ermsg = 'Could not build PRINT_FORMAT from line'//trim(line)
1494  call store_error(trim(ermsg))
1495  ermsg = 'Syntax is: COLUMNS <columns> WIDTH <width> DIGITS &
1496  &<digits> <format>'
1497  call store_error(trim(ermsg))
1498  call store_error_unit(inunit)
1499  end if
1500  !
1501  ermsg = 'Error setting PRINT_FORMAT. Syntax is incorrect in line:'
1502  if (nwords >= 4) then
1503  if (.not. same_word(words(1), 'COLUMNS')) ierr = 1
1504  if (.not. same_word(words(3), 'WIDTH')) ierr = 1
1505  ! -- Read nvalues and nwidth
1506  if (ierr == 0) then
1507  read (words(2), *, iostat=ierr) nvaluesp
1508  end if
1509  if (ierr == 0) then
1510  read (words(4), *, iostat=ierr) nwidthp
1511  end if
1512  else
1513  ierr = 1
1514  end if
1515  if (ierr /= 0) then
1516  call store_error(ermsg)
1517  call store_error(line)
1518  ermsg = 'Syntax is: COLUMNS <columns> WIDTH <width> &
1519  &DIGITS <digits> <format>'
1520  call store_error(trim(ermsg))
1521  call store_error_unit(inunit)
1522  end if
1523  i = 4
1524  !
1525  if (.not. isint) then
1526  ! -- Check for DIGITS specification
1527  if (nwords >= 5) then
1528  if (.not. same_word(words(5), 'DIGITS')) ierr = 1
1529  ! -- Read ndigits
1530  read (words(6), *, iostat=ierr) ndigits
1531  else
1532  ierr = 1
1533  end if
1534  i = i + 2
1535  end if
1536  !
1537  ! -- Check for EXPONENTIAL | FIXED | GENERAL | SCIENTIFIC option.
1538  ! -- Check for LABEL, WRAP, and STRIP options.
1539  do
1540  i = i + 1
1541  if (i <= nwords) then
1542  call upcase(words(i))
1543  select case (words(i))
1544  case ('EXPONENTIAL')
1545  editdesc = 'E'
1546  if (isint) ierr = 1
1547  case ('FIXED')
1548  editdesc = 'F'
1549  if (isint) ierr = 1
1550  case ('GENERAL')
1551  editdesc = 'G'
1552  if (isint) ierr = 1
1553  case ('SCIENTIFIC')
1554  editdesc = 'S'
1555  if (isint) ierr = 1
1556  case default
1557  ermsg = 'Error in format specification. Unrecognized option: '//words(i)
1558  call store_error(ermsg)
1559  ermsg = 'Valid values are EXPONENTIAL, FIXED, GENERAL, or SCIENTIFIC.'
1560  call store_error(ermsg)
1561  call store_error_unit(inunit)
1562  end select
1563  else
1564  exit
1565  end if
1566  end do
1567  if (ierr /= 0) then
1568  call store_error(ermsg)
1569  call store_error(line)
1570  call store_error_unit(inunit)
1571  end if
1572  !
1573  ! -- Build the output format.
1574  select case (editdesc)
1575  case ('I')
1576  call buildintformat(nvaluesp, nwidthp, cdatafmp)
1577  case ('F')
1578  call buildfixedformat(nvaluesp, nwidthp, ndigits, cdatafmp)
1579  case ('E', 'G', 'S')
1580  call buildfloatformat(nvaluesp, nwidthp, ndigits, editdesc, cdatafmp)
1581  end select
1582  !
1583  ! -- Return
1584  return
1585  end subroutine print_format
1586 
1587  !> @brief Build a fixed format for printing or saving a real array
1588  !<
1589  subroutine buildfixedformat(nvalsp, nwidp, ndig, outfmt, prowcolnum)
1590  implicit none
1591  ! -- dummy
1592  integer(I4B), intent(in) :: nvalsp, nwidp, ndig
1593  character(len=*), intent(inout) :: outfmt
1594  logical, intent(in), optional :: prowcolnum ! default true
1595  ! -- local
1596  character(len=8) :: cvalues, cwidth, cdigits
1597  character(len=60) :: ufmt
1598  logical :: prowcolnumlocal
1599  ! -- formats
1600  character(len=*), parameter :: fmtndig = "(i8)"
1601  !
1602  if (present(prowcolnum)) then
1603  prowcolnumlocal = prowcolnum
1604  else
1605  prowcolnumlocal = .true.
1606  end if
1607  !
1608  ! -- Convert integers to characters and left-adjust
1609  write (cdigits, fmtndig) ndig
1610  cdigits = adjustl(cdigits)
1611  !
1612  ! -- Build format for printing to the list file in wrap format
1613  write (cvalues, fmtndig) nvalsp
1614  cvalues = adjustl(cvalues)
1615  write (cwidth, fmtndig) nwidp
1616  cwidth = adjustl(cwidth)
1617  if (prowcolnumlocal) then
1618  ufmt = '(1x,i3,1x,'
1619  else
1620  ufmt = '(5x,'
1621  end if
1622  !
1623  ufmt = trim(ufmt)//cvalues
1624  ufmt = trim(ufmt)//'(1x,f'
1625  ufmt = trim(ufmt)//cwidth
1626  ufmt = trim(ufmt)//'.'
1627  ufmt = trim(ufmt)//cdigits
1628  ufmt = trim(ufmt)//'):/(5x,'
1629  ufmt = trim(ufmt)//cvalues
1630  ufmt = trim(ufmt)//'(1x,f'
1631  ufmt = trim(ufmt)//cwidth
1632  ufmt = trim(ufmt)//'.'
1633  ufmt = trim(ufmt)//cdigits
1634  ufmt = trim(ufmt)//')))'
1635  outfmt = ufmt
1636  !
1637  ! -- Return
1638  return
1639  end subroutine buildfixedformat
1640 
1641  !> @brief Build a floating-point format for printing or saving a real array
1642  !<
1643  subroutine buildfloatformat(nvalsp, nwidp, ndig, editdesc, outfmt, prowcolnum)
1644  implicit none
1645  ! -- dummy
1646  integer(I4B), intent(in) :: nvalsp, nwidp, ndig
1647  character(len=*), intent(in) :: editdesc
1648  character(len=*), intent(inout) :: outfmt
1649  logical, intent(in), optional :: prowcolnum ! default true
1650  ! -- local
1651  character(len=8) :: cvalues, cwidth, cdigits
1652  character(len=60) :: ufmt
1653  logical :: prowcolnumlocal
1654  ! -- formats
1655  character(len=*), parameter :: fmtndig = "(i8)"
1656  !
1657  if (present(prowcolnum)) then
1658  prowcolnumlocal = prowcolnum
1659  else
1660  prowcolnumlocal = .true.
1661  end if
1662  !
1663  ! -- Build the format
1664  write (cdigits, fmtndig) ndig
1665  cdigits = adjustl(cdigits)
1666  ! -- Convert integers to characters and left-adjust
1667  write (cwidth, fmtndig) nwidp
1668  cwidth = adjustl(cwidth)
1669  ! -- Build format for printing to the list file
1670  write (cvalues, fmtndig) (nvalsp - 1)
1671  cvalues = adjustl(cvalues)
1672  if (prowcolnumlocal) then
1673  ufmt = '(1x,i3,2x,1p,'//editdesc
1674  else
1675  ufmt = '(6x,1p,'//editdesc
1676  end if
1677  ufmt = trim(ufmt)//cwidth
1678  ufmt = trim(ufmt)//'.'
1679  ufmt = trim(ufmt)//cdigits
1680  if (nvalsp > 1) then
1681  ufmt = trim(ufmt)//','
1682  ufmt = trim(ufmt)//cvalues
1683  ufmt = trim(ufmt)//'(1x,'
1684  ufmt = trim(ufmt)//editdesc
1685  ufmt = trim(ufmt)//cwidth
1686  ufmt = trim(ufmt)//'.'
1687  ufmt = trim(ufmt)//cdigits
1688  ufmt = trim(ufmt)//')'
1689  end if
1690  !
1691  ufmt = trim(ufmt)//':/(5x,'
1692  write (cvalues, fmtndig) nvalsp
1693  cvalues = adjustl(cvalues)
1694  ufmt = trim(ufmt)//cvalues
1695  ufmt = trim(ufmt)//'(1x,'
1696  ufmt = trim(ufmt)//editdesc
1697  ufmt = trim(ufmt)//cwidth
1698  ufmt = trim(ufmt)//'.'
1699  ufmt = trim(ufmt)//cdigits
1700  ufmt = trim(ufmt)//')))'
1701  outfmt = ufmt
1702  !
1703  ! -- Return
1704  return
1705  end subroutine buildfloatformat
1706 
1707  !> @brief Build a format for printing or saving an integer array
1708  !<
1709  subroutine buildintformat(nvalsp, nwidp, outfmt, prowcolnum)
1710  implicit none
1711  ! -- dummy
1712  integer(I4B), intent(in) :: nvalsp, nwidp
1713  character(len=*), intent(inout) :: outfmt
1714  logical, intent(in), optional :: prowcolnum ! default true
1715  ! -- local
1716  character(len=8) :: cvalues, cwidth
1717  character(len=60) :: ufmt
1718  logical :: prowcolnumlocal
1719  ! -- formats
1720  character(len=*), parameter :: fmtndig = "(i8)"
1721  !
1722  if (present(prowcolnum)) then
1723  prowcolnumlocal = prowcolnum
1724  else
1725  prowcolnumlocal = .true.
1726  end if
1727  !
1728  ! -- Build format for printing to the list file in wrap format
1729  write (cvalues, fmtndig) nvalsp
1730  cvalues = adjustl(cvalues)
1731  write (cwidth, fmtndig) nwidp
1732  cwidth = adjustl(cwidth)
1733  if (prowcolnumlocal) then
1734  ufmt = '(1x,i3,1x,'
1735  else
1736  ufmt = '(5x,'
1737  end if
1738  ufmt = trim(ufmt)//cvalues
1739  ufmt = trim(ufmt)//'(1x,i'
1740  ufmt = trim(ufmt)//cwidth
1741  ufmt = trim(ufmt)//'):/(5x,'
1742  ufmt = trim(ufmt)//cvalues
1743  ufmt = trim(ufmt)//'(1x,i'
1744  ufmt = trim(ufmt)//cwidth
1745  ufmt = trim(ufmt)//')))'
1746  outfmt = ufmt
1747  !
1748  ! -- Return
1749  return
1750  end subroutine buildintformat
1751 
1752  !> @brief Get the number of words in a string
1753  !<
1754  function get_nwords(line)
1755  ! -- return
1756  integer(I4B) :: get_nwords !< number of words in a string
1757  ! -- dummy
1758  character(len=*), intent(in) :: line !< line
1759  ! -- local
1760  integer(I4B) :: linelen
1761  integer(I4B) :: lloc
1762  integer(I4B) :: istart
1763  integer(I4B) :: istop
1764  integer(I4B) :: idum
1765  real(dp) :: rdum
1766  !
1767  ! -- initialize variables
1768  get_nwords = 0
1769  linelen = len(line)
1770  !
1771  ! -- Count words in line and allocate words array
1772  lloc = 1
1773  do
1774  call urword(line, lloc, istart, istop, 0, idum, rdum, 0, 0)
1775  if (istart == linelen) exit
1776  get_nwords = get_nwords + 1
1777  end do
1778  !
1779  ! -- Return
1780  return
1781  end function get_nwords
1782 
1783  !> @brief Move the file pointer.
1784  !!
1785  !! Patterned after fseek, which is not supported as part of the fortran
1786  !! standard. For this subroutine to work the file must have been opened with
1787  !! access='stream' and action='readwrite'.
1788  !<
1789  subroutine fseek_stream(iu, offset, whence, status)
1790  ! -- dummy
1791  integer(I4B), intent(in) :: iu
1792  integer(I4B), intent(in) :: offset
1793  integer(I4B), intent(in) :: whence
1794  integer(I4B), intent(inout) :: status
1795  ! -- local
1796  integer(I8B) :: ipos
1797  !
1798  inquire (unit=iu, size=ipos)
1799  !
1800  select case (whence)
1801  case (0)
1802  !
1803  ! -- whence = 0, offset is relative to start of file
1804  ipos = 0 + offset
1805  case (1)
1806  !
1807  ! -- whence = 1, offset is relative to current pointer position
1808  inquire (unit=iu, pos=ipos)
1809  ipos = ipos + offset
1810  case (2)
1811  !
1812  ! -- whence = 2, offset is relative to end of file
1813  inquire (unit=iu, size=ipos)
1814  ipos = ipos + offset
1815  end select
1816  !
1817  ! -- position the file pointer to ipos
1818  write (iu, pos=ipos, iostat=status)
1819  inquire (unit=iu, pos=ipos)
1820  !
1821  ! -- Return
1822  return
1823  end subroutine fseek_stream
1824 
1825  !> @brief Read until non-comment line found and then return line.
1826  !!
1827  !! Different from u8rdcom in that line is a deferred length character string,
1828  !! which allows any length lines to be read using the get_line subroutine.
1829  !<
1830  subroutine u9rdcom(iin, iout, line, ierr)
1831  ! -- module
1832  use, intrinsic :: iso_fortran_env, only: iostat_end
1833  implicit none
1834  ! -- dummy
1835  integer(I4B), intent(in) :: iin
1836  integer(I4B), intent(in) :: iout
1837  character(len=:), allocatable, intent(inout) :: line
1838  integer(I4B), intent(out) :: ierr
1839  ! -- local
1840  character(len=:), allocatable :: linetemp
1841  character(len=2), parameter :: comment = '//'
1842  character(len=1), parameter :: tab = char(9)
1843  logical :: iscomment
1844  integer(I4B) :: i, j, l, istart, lsize
1845  !
1846  !readerrmsg = ''
1847  line = comment
1848  pcomments: do
1849  call get_line(iin, line, ierr)
1850  if (ierr == iostat_end) then
1851  ! -- End of file reached. Return with ierr = IOSTAT_END
1852  ! and line as an empty string
1853  line = ' '
1854  exit pcomments
1855  elseif (ierr /= 0) then
1856  ! -- Other error...report it
1857  call unitinquire(iin)
1858  write (errmsg, *) 'u9rdcom: Could not read from unit: ', iin
1859  call store_error(errmsg, terminate=.true.)
1860  end if
1861  if (len_trim(line) < 1) then
1862  line = comment
1863  cycle
1864  end if
1865  !
1866  ! -- Ensure that any initial tab characters are treated as spaces
1867  cleartabs: do
1868  !
1869  ! -- adjustl manually to avoid stack overflow
1870  lsize = len(line)
1871  istart = 1
1872  allocate (character(len=lsize) :: linetemp)
1873  do j = 1, lsize
1874  if (line(j:j) /= ' ' .and. line(j:j) /= ',' .and. &
1875  line(j:j) /= char(9)) then
1876  istart = j
1877  exit
1878  end if
1879  end do
1880  linetemp(:) = ' '
1881  linetemp(:) = line(istart:)
1882  line(:) = linetemp(:)
1883  deallocate (linetemp)
1884  !
1885  ! -- check for comment
1886  iscomment = .false.
1887  select case (line(1:1))
1888  case ('#')
1889  iscomment = .true.
1890  exit cleartabs
1891  case ('!')
1892  iscomment = .true.
1893  exit cleartabs
1894  case (tab)
1895  line(1:1) = ' '
1896  cycle cleartabs
1897  case default
1898  if (line(1:2) == comment) iscomment = .true.
1899  if (len_trim(line) < 1) iscomment = .true.
1900  exit cleartabs
1901  end select
1902  end do cleartabs
1903  !
1904  if (.not. iscomment) then
1905  exit pcomments
1906  else
1907  if (iout > 0) then
1908  !find the last non-blank character.
1909  l = len(line)
1910  do i = l, 1, -1
1911  if (line(i:i) /= ' ') then
1912  exit
1913  end if
1914  end do
1915  ! -- print the line up to the last non-blank character.
1916  write (iout, '(1x,a)') line(1:i)
1917  end if
1918  end if
1919  end do pcomments
1920  !
1921  ! -- Return
1922  return
1923  end subroutine u9rdcom
1924 
1925  !> @brief Read an unlimited length line from unit number lun into a deferred-
1926  !! length character string (line).
1927  !!
1928  !! Tack on a single space to the end so that routines like URWORD continue to
1929  !! function as before.
1930  !<
1931  subroutine get_line(lun, line, iostat)
1932  ! -- dummy
1933  integer(I4B), intent(in) :: lun
1934  character(len=:), intent(out), allocatable :: line
1935  integer(I4B), intent(out) :: iostat
1936  ! -- local
1937  integer(I4B), parameter :: buffer_len = maxcharlen
1938  character(len=buffer_len) :: buffer
1939  character(len=:), allocatable :: linetemp
1940  integer(I4B) :: size_read, linesize
1941  !
1942  ! -- initialize
1943  line = ''
1944  linetemp = ''
1945  !
1946  ! -- process
1947  do
1948  read (lun, '(A)', iostat=iostat, advance='no', size=size_read) buffer
1949  if (is_iostat_eor(iostat)) then
1950  linesize = len(line)
1951  deallocate (linetemp)
1952  allocate (character(len=linesize) :: linetemp)
1953  linetemp(:) = line(:)
1954  deallocate (line)
1955  allocate (character(len=linesize + size_read + 1) :: line)
1956  line(:) = linetemp(:)
1957  line(linesize + 1:) = buffer(:size_read)
1958  linesize = len(line)
1959  line(linesize:linesize) = ' '
1960  iostat = 0
1961  exit
1962  else if (iostat == 0) then
1963  linesize = len(line)
1964  deallocate (linetemp)
1965  allocate (character(len=linesize) :: linetemp)
1966  linetemp(:) = line(:)
1967  deallocate (line)
1968  allocate (character(len=linesize + size_read) :: line)
1969  line(:) = linetemp(:)
1970  line(linesize + 1:) = buffer(:size_read)
1971  else
1972  exit
1973  end if
1974  end do
1975  end subroutine get_line
1976 
1977 end module inputoutputmodule
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:44
@ tabcenter
centered table column
Definition: Constants.f90:171
@ tabright
right justified table column
Definition: Constants.f90:172
@ tableft
left justified table column
Definition: Constants.f90:170
@ tabucstring
upper case string table data
Definition: Constants.f90:179
@ tabstring
string table data
Definition: Constants.f90:178
@ tabreal
real table data
Definition: Constants.f90:181
@ tabinteger
integer table data
Definition: Constants.f90:180
integer(i4b), parameter iulast
maximum file unit number (this allows for 9000 open files)
Definition: Constants.f90:57
integer(i4b), parameter namedboundflag
named bound flag
Definition: Constants.f90:48
integer(i4b), parameter iustart
starting file unit number
Definition: Constants.f90:56
integer(i4b), parameter lenbigline
maximum length of a big line
Definition: Constants.f90:15
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition: Constants.f90:34
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:35
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:64
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:46
subroutine, public buildintformat(nvalsp, nwidp, outfmt, prowcolnum)
Build a format for printing or saving an integer array.
subroutine, public urdaux(naux, inunit, iout, lloc, istart, istop, auxname, line, text)
Read auxiliary variables from an input line.
logical function, public same_word(word1, word2)
Perform a case-insensitive comparison of two words.
subroutine, public getfilefrompath(pathname, filename)
subroutine, public ubdsvc(ibdchn, n, q, naux, aux)
Write one value of cell-by-cell flow using a list structure.
subroutine, public extract_idnum_or_bndname(line, icol, istart, istop, idnum, bndname)
Starting at position icol, define string as line(istart:istop).
subroutine, public ucolno(nlbl1, nlbl2, nspace, ncpl, ndig, iout)
Output column numbers above a matrix printout.
subroutine, public ubdsv1(kstp, kper, text, ibdchn, buff, ncol, nrow, nlay, iout, delt, pertim, totim)
Record cell-by-cell flow terms for one component of flow as a 3-D array with extra record to indicate...
subroutine, public ubdsv4(kstp, kper, text, naux, auxtxt, ibdchn, ncol, nrow, nlay, nlist, iout, delt, pertim, totim)
Write header records for cell-by-cell flow terms for one component of flow plus auxiliary data using ...
subroutine, public ubdsvb(ibdchn, icrl, q, val, nvl, naux, laux)
Write one value of cell-by-cell flow plus auxiliary data using a list structure.
integer(i4b) function, public getunit()
Get a free unit number.
subroutine get_line(lun, line, iostat)
Read an unlimited length line from unit number lun into a deferred- length character string (line).
subroutine, public lowcase(word)
Convert to lower case.
subroutine, public ulaprw(buf, text, kstp, kper, ncol, nrow, ilay, iprn, iout)
Print 1 layer array.
subroutine, public parseline(line, nwords, words, inunit, filename)
Parse a line into words.
subroutine, public buildfixedformat(nvalsp, nwidp, ndig, outfmt, prowcolnum)
Build a fixed format for printing or saving a real array.
subroutine, public buildfloatformat(nvalsp, nwidp, ndig, editdesc, outfmt, prowcolnum)
Build a floating-point format for printing or saving a real array.
subroutine, public upcase(word)
Convert to upper case.
integer(i4b) function, public get_nwords(line)
Get the number of words in a string.
subroutine, public u9rdcom(iin, iout, line, ierr)
Read until non-comment line found and then return line.
subroutine, public fseek_stream(iu, offset, whence, status)
Move the file pointer.
character(len=max(len_trim(str), width)) function, public str_pad_left(str, width)
Function for string manipulation.
subroutine, public print_format(linein, cdatafmp, editdesc, nvaluesp, nwidthp, inunit)
Define the print or save format.
subroutine, public ubdsvd(ibdchn, n, n2, q, naux, aux)
Write one value of cell-by-cell flow using a list structure.
subroutine, public ulstlb(iout, label, caux, ncaux, naux)
Print a label for a list.
character(len=:) function, allocatable, public read_line(iu, eof)
This function reads a line of arbitrary length and returns it.
subroutine, public append_processor_id(name, proc_id)
Append processor id to a string.
subroutine, public ulaprufw(ncol, nrow, kstp, kper, ilay, iout, buf, text, userfmt, nvalues, nwidth, editdesc)
Print 1 layer array with user formatting in wrap format.
subroutine freeunitnumber(iu)
Assign a free unopened unit number.
subroutine, public ubdsv06(kstp, kper, text, modelnam1, paknam1, modelnam2, paknam2, ibdchn, naux, auxtxt, ncol, nrow, nlay, nlist, iout, delt, pertim, totim)
Write header records for cell-by-cell flow terms for one component of flow.
subroutine, public ulasav(buf, text, kstp, kper, pertim, totim, ncol, nrow, ilay, ichn)
Save 1 layer array on disk.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
subroutine, public unitinquire(iu)
subroutine, public urword(line, icol, istart, istop, ncode, n, r, iout, in)
Extract a word from a string.
subroutine, public uwword(line, icol, ilen, ncode, c, n, r, fmt, alignment, sep)
Create a formatted line.
This module defines variable data types.
Definition: kind.f90:8
Store and issue logging messages to output units.
Definition: Message.f90:2
subroutine, public write_message(text, iunit, fmt, skipbefore, skipafter, advance)
Write a message to an output unit.
Definition: Message.f90:210
character(len=20), dimension(2) action
Definition: OpenSpec.f90:7
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:168
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
integer(i4b) iunext
next file unit number to assign
integer(i4b) isim_mode
simulation mode