MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
SfrCrossSectionManager.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b, lgp
4  use constantsmodule, only: dzero, done, &
6 
8  use tablemodule, only: tabletype, table_cr
9 
10  implicit none
11 
12  public :: sfrcrosssection
13  public :: cross_section_cr
14 
16  integer(I4B), pointer :: npoints
17  real(dp), pointer, dimension(:), contiguous :: station => null()
18  real(dp), pointer, dimension(:), contiguous :: height => null()
19  real(dp), pointer, dimension(:), contiguous :: roughfraction => null()
20  logical(LGP), pointer, dimension(:), contiguous :: valid => null()
21  end type sfrcrosssectiontype
22 
24  integer(I4B), pointer :: iout => null()
25  integer(I4B), pointer :: iprpak => null()
26  integer(I4B), pointer :: nreaches => null()
27  integer(I4B), pointer :: invalid => null()
28  character(len=LINELENGTH), dimension(:), allocatable :: filenames
29  integer(I4B), pointer, dimension(:), contiguous :: npoints => null()
31  pointer, dimension(:), contiguous :: cross_sections => null()
32  type(tabletype), pointer :: inputtab => null()
33 
34  contains
35 
36  !
37  ! -- public procedures
38  procedure, public :: initialize
39  procedure, public :: source_table
40  procedure, public :: read_table
41  procedure, public :: get_ncrossptstot
42  procedure, public :: output
43  procedure, public :: pack
44  procedure, public :: destroy
45  !
46  ! -- private procedures
47  procedure, private :: validate
48 
49  end type sfrcrosssection
50 
51 contains
52 
53  !> @brief Create a cross-section object
54  !!
55  !! Subroutine to calculate the maximum top width for a reach using the
56  !! cross-section station data.
57  !<
58  subroutine cross_section_cr(this, iout, iprpak, nreaches)
59  ! -- dummy variables
60  type(sfrcrosssection), pointer :: this !< SfrCrossSection object
61  integer(I4B), pointer, intent(in) :: iout !< model listing file
62  integer(I4B), pointer, intent(in) :: iprpak !< flag for printing table input data
63  integer(I4B), pointer, intent(in) :: nreaches !< number of reaches
64  !
65  ! -- check if table already associated and reset if necessary
66  if (associated(this)) then
67  call this%destroy()
68  deallocate (this)
69  nullify (this)
70  end if
71  !
72  ! -- Create the object
73  allocate (this)
74  !
75  ! -- initialize scalars
76  this%iout => iout
77  this%iprpak => iprpak
78  this%nreaches => nreaches
79  end subroutine cross_section_cr
80 
81  !> @brief Initialize a cross-section object
82  !!
83  !! Subroutine to initialize the cross-section object with the current
84  !! data.
85  !!
86  !<
87  subroutine initialize(this, ncrossptstot, ncrosspts, iacross, &
88  station, height, roughfraction)
89  ! -- dummy variables
90  class(sfrcrosssection) :: this !< SfrCrossSection object
91  integer(I4B), intent(in) :: ncrossptstot !< total number of cross-section points
92  integer(I4B), dimension(this%nreaches), intent(in) :: ncrosspts !< pointers to cross-section data in data vector
93  integer(I4B), dimension(this%nreaches + 1), intent(in) :: iacross !< pointers to cross-section data in data vector
94  real(DP), dimension(ncrossptstot), intent(in) :: station !< cross-section station data
95  real(DP), dimension(ncrossptstot), intent(in) :: height !< cross-section height data
96  real(DP), dimension(ncrossptstot), intent(in) :: roughfraction !< cross-section roughness fraction data
97  ! -- local variables
98  integer(I4B) :: i
99  integer(I4B) :: n
100  integer(I4B) :: npoints
101  integer(I4B) :: i0
102  integer(I4B) :: i1
103  integer(I4B) :: ipos
104  !
105  ! -- allocate scalars
106  allocate (this%invalid)
107  !
108  ! -- initialize scalars
109  this%invalid = 0
110  !
111  ! -- create cross-section container
112  allocate (this%filenames(this%nreaches))
113  allocate (this%npoints(this%nreaches))
114  allocate (this%cross_sections(this%nreaches))
115  do n = 1, this%nreaches
116  npoints = ncrosspts(n)
117  allocate (this%cross_sections(n)%npoints)
118  allocate (this%cross_sections(n)%station(npoints))
119  allocate (this%cross_sections(n)%height(npoints))
120  allocate (this%cross_sections(n)%roughfraction(npoints))
121  allocate (this%cross_sections(n)%valid(npoints))
122  end do
123  !
124  ! -- fill cross-section container with current values
125  do n = 1, this%nreaches
126  this%filenames(n) = 'NONE'
127  this%cross_sections(n)%npoints = ncrosspts(n)
128  this%npoints(n) = ncrosspts(n)
129  i0 = iacross(n)
130  i1 = iacross(n + 1) - 1
131  ipos = 1
132  do i = i0, i1
133  this%cross_sections(n)%station(ipos) = station(i)
134  this%cross_sections(n)%height(ipos) = height(i)
135  this%cross_sections(n)%roughfraction(ipos) = roughfraction(i)
136  this%cross_sections(n)%valid(ipos) = .true.
137  ipos = ipos + 1
138  end do
139  end do
140  end subroutine initialize
141 
142  !> @brief Source a reach's cross-section table from its SFRTAB6 subpackage
143  !<
144  subroutine source_table(this, irch, width, mempath, filename)
148  ! -- dummy variables
149  class(sfrcrosssection) :: this !< SfrCrossSection object
150  integer(I4B), intent(in) :: irch !< current reach
151  real(DP), intent(in) :: width !< reach width
152  character(len=*), intent(in) :: mempath !< SFRTAB6 input mempath
153  character(len=*), intent(in) :: filename !< table file name, for reporting
154  ! -- local variables
155  integer(I4B), pointer :: nrow => null()
156  integer(I4B), pointer :: ncol => null()
157  real(DP), dimension(:), pointer, contiguous :: xfraction => null()
158  real(DP), dimension(:), pointer, contiguous :: height => null()
159  real(DP), dimension(:), pointer, contiguous :: manfraction => null()
160  integer(I4B) :: n, nerr0
161  !
162  ! -- table dimensions, auto-loaded from the SFRTAB6 subpackage input
163  call mem_setptr(nrow, 'NROW', mempath)
164  call mem_setptr(ncol, 'NCOL', mempath)
165  !
166  ! -- errors added below this point belong to this reach's own table
167  nerr0 = count_errors()
168  !
169  if (nrow < 1) then
170  write (errmsg, '(a,1x,i0,3a)') &
171  'TABLE NROW MUST BE > 0 FOR REACH', irch, " ('", &
172  trim(adjustl(filename)), "')"
173  call store_error(errmsg)
174  end if
175  if (ncol < 2) then
176  write (errmsg, '(a,1x,i0,3a)') &
177  'TABLE NCOL MUST BE >= 2 FOR REACH', irch, " ('", &
178  trim(adjustl(filename)), "')"
179  call store_error(errmsg)
180  end if
181  !
182  if (count_errors() > nerr0) then
183  call store_error_filename(filename, terminate=.false.)
184  call memorystore_release('NROW', mempath)
185  call memorystore_release('NCOL', mempath)
186  call memorystore_release('INPUT_FNAME', mempath)
187  return
188  end if
189  !
190  ! -- set the filename and number of points, and reallocate for nrow
191  this%filenames(irch) = filename
192  this%npoints(irch) = nrow
193  deallocate (this%cross_sections(irch)%npoints)
194  deallocate (this%cross_sections(irch)%station)
195  deallocate (this%cross_sections(irch)%height)
196  deallocate (this%cross_sections(irch)%roughfraction)
197  deallocate (this%cross_sections(irch)%valid)
198  allocate (this%cross_sections(irch)%npoints)
199  allocate (this%cross_sections(irch)%station(nrow))
200  allocate (this%cross_sections(irch)%height(nrow))
201  allocate (this%cross_sections(irch)%roughfraction(nrow))
202  allocate (this%cross_sections(irch)%valid(nrow))
203  this%cross_sections(irch)%npoints = nrow
204  !
205  ! -- copy the auto-loaded table data
206  call mem_setptr(xfraction, 'XFRACTION', mempath)
207  call mem_setptr(height, 'HEIGHT', mempath)
208  do n = 1, nrow
209  this%cross_sections(irch)%station(n) = xfraction(n) * width
210  this%cross_sections(irch)%height(n) = height(n)
211  this%cross_sections(irch)%valid(n) = .true.
212  end do
213  if (ncol > 2) then
214  call mem_setptr(manfraction, 'MANFRACTION', mempath)
215  this%cross_sections(irch)%roughfraction = manfraction
216  else
217  this%cross_sections(irch)%roughfraction = done
218  end if
219  !
220  ! -- validate the table
221  call this%validate(irch)
222  !
223  if (count_errors() > nerr0) then
224  call store_error_filename(filename, terminate=.false.)
225  end if
226  !
227  ! -- release this reach's own input context memory
228  call memorystore_release('NROW', mempath)
229  call memorystore_release('NCOL', mempath)
230  call memorystore_release('XFRACTION', mempath)
231  call memorystore_release('HEIGHT', mempath)
232  if (ncol > 2) then
233  call memorystore_release('MANFRACTION', mempath)
234  end if
235  call memorystore_release('INPUT_FNAME', mempath)
236  end subroutine source_table
237 
238  !> @brief Read a cross-section table file for a reach
239  !!
240  !! Used only for the PERIOD block's dynamic CROSS_SECTION reissue, whose
241  !! file path is not known until runtime.
242  !<
243  subroutine read_table(this, irch, width, filename)
244  use constantsmodule, only: iuoc
245  use inputoutputmodule, only: openfile
248  ! -- dummy variables
249  class(sfrcrosssection) :: this !< SfrCrossSection object
250  integer(I4B), intent(in) :: irch !< current reach
251  real(DP), intent(in) :: width !< reach width
252  character(len=*), intent(in) :: filename !< table file with station height data
253  ! -- local variables
254  character(len=LINELENGTH) :: tag
255  character(len=LINELENGTH) :: keyword
256  integer(I4B) :: ierr
257  logical :: isfound
258  logical :: endOfBlock
259  integer(I4B) :: iu
260  integer(I4B) :: n
261  integer(I4B) :: j
262  integer(I4B) :: ipos
263  integer(I4B) :: jmin
264  integer(I4B) :: nerr0
265  type(blockparsertype) :: parser
266  !
267  ! -- initialize local variables
268  j = 0
269  n = 0
270  jmin = 2
271  !
272  ! -- errors added below this point belong to this reach's own table
273  nerr0 = count_errors()
274  !
275  ! -- create a tag with the file name and reach number
276  write (tag, "('Reach',1x,i0,1x,'(',a, ')')") &
277  irch, trim(adjustl(filename))
278  !
279  ! -- open the table file
280  iu = iuoc
281  call openfile(iu, this%iout, filename, 'SFR TABLE')
282  call parser%Initialize(iu, this%iout)
283  !
284  ! -- get dimensions block
285  call parser%GetBlock('DIMENSIONS', isfound, ierr, supportopenclose=.true.)
286  !
287  ! -- parse table dimensions block if detected
288  if (isfound) then
289  !
290  ! -- process the table dimension data
291  if (this%iprpak /= 0) then
292  write (this%iout, '(/1x,a)') &
293  'PROCESSING '//trim(adjustl(tag))//' DIMENSIONS'
294  end if
295  readdims: do
296  call parser%GetNextLine(endofblock)
297  if (endofblock) exit
298  call parser%GetStringCaps(keyword)
299  select case (keyword)
300  case ('NROW')
301  n = parser%GetInteger()
302  if (n < 1) then
303  write (errmsg, '(a,1x,a)') &
304  'TABLE NROW MUST BE > 0 FOR', trim(adjustl(tag))
305  call store_error(errmsg)
306  end if
307  case ('NCOL')
308  j = parser%GetInteger()
309  jmin = 2
310  if (j < jmin) then
311  write (errmsg, '(a,1x,i0,1x,a,1x,a)') &
312  'TABLE NCOL MUST BE >=', jmin, 'FOR', trim(adjustl(tag))
313  call store_error(errmsg)
314  end if
315  case default
316  write (errmsg, '(a,a)') &
317  'UNKNOWN '//trim(adjustl(tag))//' DIMENSIONS keyword: ', &
318  trim(keyword)
319  call store_error(errmsg)
320  end select
321  end do readdims
322  if (this%iprpak /= 0) then
323  write (this%iout, '(1x,a)') &
324  'END OF '//trim(adjustl(tag))//' DIMENSIONS'
325  end if
326  else
327  call store_error('Required DIMENSIONS block not found.')
328  end if
329  !
330  ! -- check that ncol and nrow have been specified
331  if (n < 1) then
332  write (errmsg, '(a)') &
333  'NROW not specified in the table DIMENSIONS block'
334  call store_error(errmsg)
335  end if
336  if (j < 1) then
337  write (errmsg, '(a)') &
338  'NCOL not specified in the table DIMENSIONS block'
339  call store_error(errmsg)
340  end if
341  !
342  ! -- only read the table data if n and j are specified to be greater
343  ! than zero - an error condition exists if n * j = 0
344  if (n * j > 0) then
345  !
346  ! -- set the filename and reset the number of points
347  this%filenames(irch) = filename
348  this%npoints(irch) = n
349  !
350  ! -- deallocate
351  deallocate (this%cross_sections(irch)%npoints)
352  deallocate (this%cross_sections(irch)%station)
353  deallocate (this%cross_sections(irch)%height)
354  deallocate (this%cross_sections(irch)%roughfraction)
355  deallocate (this%cross_sections(irch)%valid)
356  !
357  ! -- reallocate
358  allocate (this%cross_sections(irch)%npoints)
359  allocate (this%cross_sections(irch)%station(n))
360  allocate (this%cross_sections(irch)%height(n))
361  allocate (this%cross_sections(irch)%roughfraction(n))
362  allocate (this%cross_sections(irch)%valid(n))
363  !
364  ! -- initialize
365  this%cross_sections(irch)%npoints = n
366  !
367  ! -- get table block
368  call parser%GetBlock('TABLE', isfound, ierr, supportopenclose=.true.)
369  !
370  ! -- parse well_connections block if detected
371  if (isfound) then
372 
373  ! -- process the table data
374  if (this%iprpak /= 0) then
375  write (this%iout, '(/1x,a)') &
376  'PROCESSING '//trim(adjustl(tag))//' TABLE'
377  end if
378  ipos = 0
379  readtabledata: do
380  call parser%GetNextLine(endofblock)
381  if (endofblock) exit
382  ipos = ipos + 1
383  if (ipos > this%npoints(irch)) then
384  cycle readtabledata
385  end if
386  this%cross_sections(irch)%station(ipos) = parser%GetDouble() * width
387  this%cross_sections(irch)%height(ipos) = parser%GetDouble()
388  if (j > 2) then
389  this%cross_sections(irch)%roughfraction(ipos) = parser%GetDouble()
390  else
391  this%cross_sections(irch)%roughfraction(ipos) = done
392  end if
393  this%cross_sections(irch)%valid(ipos) = .true.
394  end do readtabledata
395 
396  if (this%iprpak /= 0) then
397  write (this%iout, '(1x,a)') &
398  'END OF '//trim(adjustl(tag))//' TABLE'
399  end if
400  else
401  call store_error('Required TABLE block not found.')
402  end if
403  !
404  ! -- error condition if number of rows read are not equal to nrow
405  if (ipos /= this%npoints(irch)) then
406  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
407  'NROW set to', this%npoints(irch), 'but', ipos, 'rows were read'
408  call store_error(errmsg)
409  end if
410  end if
411  !
412  ! -- close the open table file
413  if (iu > 0) then
414  close (iu)
415  end if
416  !
417  ! -- validate the table
418  call this%validate(irch)
419  !
420  if (count_errors() > nerr0) then
421  call store_error_filename(filename, terminate=.false.)
422  end if
423  end subroutine read_table
424 
425  !> @brief Validate cross-section tables
426  !!
427  !! Subroutine to validate a cross-section table.
428  !!
429  !<
430  subroutine validate(this, irch)
431  use constantsmodule, only: dem6, dtwothirds
432  use simmodule, only: store_error
433  use sortmodule, only: unique_values
436  ! -- dummy variables
437  class(sfrcrosssection) :: this !< SfrCrossSection object
438  integer(I4B), intent(in) :: irch !< current reach
439  ! -- local variables
440  logical(LGP) :: station_error
441  logical(LGP) :: height_error
442  logical(LGP) :: height_zero_error
443  logical(LGP) :: roughness_error
444  character(len=LINELENGTH) :: filename
445  integer(I4B) :: npts
446  integer(I4B) :: n
447  integer(I4B) :: i
448  integer(I4B) :: ipos
449  real(DP) :: station
450  real(DP) :: height
451  real(DP) :: roughfraction
452  real(DP) :: aw
453  real(DP) :: rh
454  real(DP) :: dc0
455  real(DP) :: dc1
456  real(DP), dimension(:), allocatable :: heights
457  real(DP), dimension(:), allocatable :: unique_heights
458  real(DP), dimension(3) :: factor
459  !
460  ! -- initialize local variables
461  station_error = .false.
462  height_error = .false.
463  height_zero_error = .true.
464  roughness_error = .false.
465  npts = this%npoints(irch)
466  !
467  ! -- validate the station and height data
468  do n = 1, npts
469  station = this%cross_sections(irch)%station(n)
470  if (station < dzero) then
471  station_error = .true.
472  end if
473  height = this%cross_sections(irch)%height(n)
474  if (height < dzero) then
475  height_error = .true.
476  else if (height == dzero) then
477  height_zero_error = .false.
478  end if
479  roughfraction = this%cross_sections(irch)%roughfraction(n)
480  if (roughfraction <= dzero) then
481  roughness_error = .true.
482  end if
483  if (station_error .and. height_error .and. &
484  roughness_error) then
485  exit
486  end if
487  end do
488  !
489  ! -- write error messages
490  if (station_error .or. height_error .or. &
491  height_zero_error .or. roughness_error) then
492  filename = this%filenames(irch)
493  if (station_error) then
494  write (errmsg, '(3a,1x,i0,1x,a)') &
495  "All xfraction data in '", trim(adjustl(filename)), &
496  "' for reach", irch, 'must be greater than or equal to zero.'
497  call store_error(errmsg)
498  end if
499  if (height_error) then
500  write (errmsg, '(3a,1x,i0,1x,a)') &
501  "All height data in '", trim(adjustl(filename)), &
502  "' for reach", irch, 'must be greater than or equal to zero.'
503  call store_error(errmsg)
504  end if
505  if (height_zero_error) then
506  write (errmsg, '(3a,1x,i0,1x,a)') &
507  "At least one height data value in '", trim(adjustl(filename)), &
508  "' for reach", irch, 'must be equal to zero.'
509  call store_error(errmsg)
510  end if
511  if (roughness_error) then
512  write (errmsg, '(3a,1x,i0,1x,a)') &
513  "All manfraction data in '", trim(adjustl(filename)), &
514  "' for reach", irch, 'must be greater than zero.'
515  call store_error(errmsg)
516  end if
517  end if
518  !
519  ! -- initialize and fill heights
520  allocate (heights(npts))
521  do n = 1, npts
522  heights(n) = this%cross_sections(irch)%height(n)
523  end do
524  !
525  ! -- get unique heights
526  call unique_values(heights, unique_heights)
527  !
528  ! -- calculate the product of the area and the hydraulic radius to
529  ! the 2/3 power
530  do n = 1, size(unique_heights)
531  if (unique_heights(n) <= dzero) cycle
532  ipos = 1
533  do i = -1, 1, 1
534  height = unique_heights(n) + real(i, dp) * dem6
535  aw = get_cross_section_area(npts, this%cross_sections(irch)%station, &
536  this%cross_sections(irch)%height, height)
537  rh = get_hydraulic_radius(npts, this%cross_sections(irch)%station, &
538  this%cross_sections(irch)%height, height)
539  factor(ipos) = aw * rh**dtwothirds
540  ipos = ipos + 1
541  end do
542  !
543  ! -- calculate the derivative
544  dc0 = (factor(2) - factor(1)) / dem6
545  dc1 = (factor(3) - factor(2)) / dem6
546  !
547  ! -- evaluate the difference
548  if (dc0 < dzero .or. dc1 < dzero) then
549  this%invalid = this%invalid + 1
550  height = unique_heights(n)
551  do i = 1, npts
552  if (this%cross_sections(irch)%height(i) == height) then
553  this%cross_sections(irch)%valid(i) = .false.
554  end if
555  end do
556  end if
557  end do
558  !
559  ! -- deallocate local storage
560  deallocate (heights)
561  deallocate (unique_heights)
562  end subroutine validate
563 
564  !> @brief Write cross-section tables
565  !!
566  !! Subroutine to write the cross-section tables to the model
567  !! listing file.
568  !!
569  !<
570  subroutine output(this, widths, roughs, kstp, kper)
571  use constantsmodule, only: tableft
572  use simmodule, only: store_warning
573  ! -- dummy variables
574  class(sfrcrosssection) :: this !< SfrCrossSection object
575  real(DP), dimension(this%nreaches), intent(in) :: widths !< reach widths
576  real(DP), dimension(this%nreaches), intent(in) :: roughs !< reach Manning's roughness coefficients
577  integer(I4B), intent(in), optional :: kstp !< time step
578  integer(I4B), intent(in), optional :: kper !< stress period
579  ! -- local variables
580  character(len=LINELENGTH) :: title
581  character(len=LINELENGTH) :: text
582  character(len=LINELENGTH) :: filename
583  character(len=10) :: cvalid
584  logical(LGP) :: transient
585  integer(I4B) :: kkstp
586  integer(I4B) :: kkper
587  integer(I4B) :: irch
588  integer(I4B) :: n
589  integer(I4B) :: ntabcols
590  integer(I4B) :: ninvalid_reaches
591  real(DP) :: width
592  real(DP) :: xfraction
593  real(DP) :: rough
594  real(DP) :: r
595  integer(I4B), dimension(this%nreaches) :: reach_fail
596  !
597  ! -- initialize local variables
598  kkstp = 0
599  kkper = 0
600  !
601  ! -- process optional parameters
602  if (present(kstp)) then
603  kkstp = kstp
604  end if
605  if (present(kper)) then
606  kkper = kper
607  end if
608  !
609  ! -- set transient boolean
610  if (kkstp > 0 .and. kkper > 0) then
611  transient = .true.
612  else
613  transient = .false.
614  end if
615  !
616  ! -- set reach failure
617  do irch = 1, this%nreaches
618  filename = this%filenames(irch)
619  reach_fail(irch) = 0
620  !
621  ! -- output cross-section data read from a file
622  if (trim(adjustl(filename)) /= 'NONE') then
623  do n = 1, this%npoints(irch)
624  if (.not. this%cross_sections(irch)%valid(n)) then
625  reach_fail(irch) = reach_fail(irch) + 1
626  end if
627  end do
628  end if
629  end do
630  !
631  ! -- iterate over each reach
632  do irch = 1, this%nreaches
633  filename = this%filenames(irch)
634  !
635  ! -- output cross-section data read from a file
636  if (trim(adjustl(filename)) /= 'NONE') then
637  !
638  ! -- build and write the table for a reach, if required, or
639  ! the cross-section is invalid
640  if (this%iprpak > 0 .or. reach_fail(irch) > 0) then
641  !
642  ! -- calculate the number of table columns
643  if (reach_fail(irch) > 0) then
644  ntabcols = 6
645  else
646  ntabcols = 5
647  end if
648  !
649  ! -- reset the input table object
650  write (title, '(a,1x,i0,1x,3a)') &
651  'CROSS_SECTION DATA FOR REACH', irch, "FROM TAB6 FILE ('", &
652  trim(adjustl(filename)), "')"
653  call table_cr(this%inputtab, trim(adjustl(filename)), title)
654  call this%inputtab%table_df(this%npoints(irch), ntabcols, &
655  this%iout, finalize=.false., &
656  transient=transient)
657  if (transient) then
658  call this%inputtab%set_kstpkper(kkstp, kkper)
659  end if
660  text = 'XFRACTION'
661  call this%inputtab%initialize_column(text, 20, alignment=tableft)
662  text = 'STATION'
663  call this%inputtab%initialize_column(text, 20, alignment=tableft)
664  text = 'HEIGHT'
665  call this%inputtab%initialize_column(text, 20, alignment=tableft)
666  text = "MANFRACTION"
667  call this%inputtab%initialize_column(text, 20, alignment=tableft)
668  text = "MANNING'S ROUGHNESS COEFFICIENT"
669  call this%inputtab%initialize_column(text, 20, alignment=tableft)
670  if (reach_fail(irch) > 0) then
671  text = 'NEEDS ADJUSTMENT'
672  call this%inputtab%initialize_column(text, 10, alignment=tableft)
673  end if
674  !
675  ! -- set the width and roughness for the reach
676  width = widths(irch)
677  rough = roughs(irch)
678  !
679  ! -- fill the table
680  do n = 1, this%npoints(irch)
681  xfraction = this%cross_sections(irch)%station(n) / width
682  r = this%cross_sections(irch)%roughfraction(n) * rough
683  call this%inputtab%add_term(xfraction)
684  call this%inputtab%add_term(this%cross_sections(irch)%station(n))
685  call this%inputtab%add_term(this%cross_sections(irch)%height(n))
686  call this%inputtab%add_term(&
687  &this%cross_sections(irch)%roughfraction(n))
688  call this%inputtab%add_term(r)
689  if (reach_fail(irch) > 0) then
690  if (this%cross_sections(irch)%valid(n)) then
691  cvalid = ''
692  else
693  cvalid = 'TRUE'
694  end if
695  call this%inputtab%add_term(cvalid)
696  end if
697  end do
698  !
699  ! -- finalize the table
700  call this%inputtab%finalize_table()
701  end if
702  end if
703  end do
704  !
705  ! -- save warning message and write summary information to the listing file
706  if (this%invalid > 0) then
707  ninvalid_reaches = 0
708  do irch = 1, this%nreaches
709  if (reach_fail(irch) > 0) then
710  ninvalid_reaches = ninvalid_reaches + 1
711  end if
712  end do
713  write (warnmsg, '(a,1x,i0,7(1x,a))') &
714  'Cross-section data for', ninvalid_reaches, &
715  'reaches include one or more points that result in a', &
716  'non-unique depth-conveyance relation. This occurs when', &
717  'there are horizontal sections at non-zero heights', &
718  '(for example, flat overbank sections). This can usually', &
719  'be resolved by adding a small slope to these flat', &
720  'sections. See the cross-section tables in the model', &
721  'listing file for more information.'
722  call store_warning(warnmsg)
723  end if
724  end subroutine output
725 
726  !> @brief Get the total number of cross-section points
727  !!
728  !! Function to get the total number of cross-section points to
729  !! get the new size of the station xsheight data for all reaches.
730  !!
731  !<
732  function get_ncrossptstot(this) result(nptstot)
733  ! -- dummy variables
734  class(sfrcrosssection) :: this
735  ! -- local variables
736  integer(I4B) :: nptstot
737  integer(I4B) :: n
738  !
739  !
740  nptstot = 0
741  do n = 1, this%nreaches
742  nptstot = nptstot + this%npoints(n)
743  end do
744  end function get_ncrossptstot
745 
746  !> @brief Pack the cross-section object
747  !!
748  !! Subroutine to pack the cross-section object into vectors.
749  !!
750  !<
751  subroutine pack(this, ncrossptstot, ncrosspts, iacross, &
752  station, height, roughfraction)
753  ! -- dummy variables
754  class(sfrcrosssection) :: this !< SfrCrossSection object
755  integer(I4B), intent(in) :: ncrossptstot !< total number of cross-section points
756  integer(I4B), dimension(this%nreaches), intent(inout) :: ncrosspts !< pointers to cross-section data in data vector
757  integer(I4B), dimension(this%nreaches + 1), intent(inout) :: iacross !< pointers to cross-section data in data vector
758  real(DP), dimension(ncrossptstot), intent(inout) :: station !< cross-section station data
759  real(DP), dimension(ncrossptstot), intent(inout) :: height !< cross-section height data
760  real(DP), dimension(ncrossptstot), intent(inout) :: roughfraction !< cross-section roughness fraction data
761  ! -- local variables
762  integer(I4B) :: i
763  integer(I4B) :: n
764  integer(I4B) :: npoints
765  integer(I4B) :: ipos
766  !
767  ! -- pack the data
768  ipos = 1
769  iacross(1) = ipos
770  do n = 1, this%nreaches
771  npoints = this%npoints(n)
772  ncrosspts(n) = npoints
773  do i = 1, npoints
774  station(ipos) = this%cross_sections(n)%station(i)
775  height(ipos) = this%cross_sections(n)%height(i)
776  roughfraction(ipos) = this%cross_sections(n)%roughfraction(i)
777  ipos = ipos + 1
778  end do
779  iacross(n + 1) = ipos
780  end do
781  end subroutine pack
782 
783  !> @brief Deallocate the cross-section object
784  !!
785  !! Subroutine to deallocate the cross-section object.
786  !!
787  !<
788  subroutine destroy(this)
789  ! -- dummy variables
790  class(sfrcrosssection) :: this !< SfrCrossSection object
791  ! -- local variables
792  integer(I4B) :: n
793  !
794  ! -- deallocate and nullify pointers
795  deallocate (this%npoints)
796  nullify (this%npoints)
797  do n = 1, this%nreaches
798  deallocate (this%cross_sections(n)%npoints)
799  nullify (this%cross_sections(n)%npoints)
800  deallocate (this%cross_sections(n)%station)
801  nullify (this%cross_sections(n)%station)
802  deallocate (this%cross_sections(n)%height)
803  nullify (this%cross_sections(n)%height)
804  deallocate (this%cross_sections(n)%roughfraction)
805  nullify (this%cross_sections(n)%roughfraction)
806  deallocate (this%cross_sections(n)%valid)
807  nullify (this%cross_sections(n)%valid)
808  end do
809  deallocate (this%cross_sections)
810  nullify (this%cross_sections)
811  !
812  ! -- input table
813  if (associated(this%inputtab)) then
814  call this%inputtab%table_da()
815  deallocate (this%inputtab)
816  nullify (this%inputtab)
817  end if
818  !
819  ! -- deallocate and nullify class scalars
820  deallocate (this%invalid)
821  nullify (this%invalid)
822  !
823  ! -- nullify scalars that are pointers to external variables
824  nullify (this%iout)
825  nullify (this%iprpak)
826  nullify (this%nreaches)
827  end subroutine destroy
828 
829 end module sfrcrosssectionmanager
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
@ tableft
left justified table column
Definition: Constants.f90:172
real(dp), parameter dtwothirds
real constant 2/3
Definition: Constants.f90:70
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter iuoc
open/close file unit number
Definition: Constants.f90:56
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
This module contains stateless sfr subroutines and functions.
real(dp) function, public get_cross_section_area(npts, stations, heights, d)
Calculate the cross-sectional area for a reach.
real(dp) function, public get_hydraulic_radius(npts, stations, heights, d)
Calculate the hydraulic radius for a reach.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
integer(i4b) function get_ncrossptstot(this)
Get the total number of cross-section points.
subroutine, public cross_section_cr(this, iout, iprpak, nreaches)
Create a cross-section object.
subroutine output(this, widths, roughs, kstp, kper)
Write cross-section tables.
subroutine destroy(this)
Deallocate the cross-section object.
subroutine read_table(this, irch, width, filename)
Read a cross-section table file for a reach.
subroutine validate(this, irch)
Validate cross-section tables.
subroutine source_table(this, irch, width, mempath, filename)
Source a reach's cross-section table from its SFRTAB6 subpackage.
subroutine initialize(this, ncrossptstot, ncrosspts, iacross, station, height, roughfraction)
Initialize a cross-section object.
subroutine pack(this, ncrossptstot, ncrosspts, iacross, station, height, roughfraction)
Pack the cross-section object.
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:237
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:204
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
character(len=maxcharlen) warnmsg
warning message string
subroutine, public table_cr(this, name, title)
Definition: Table.f90:87