MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
sfrcrosssectionmanager Module Reference

Data Types

type  sfrcrosssectiontype
 
type  sfrcrosssection
 

Functions/Subroutines

subroutine, public cross_section_cr (this, iout, iprpak, nreaches)
 Create a cross-section object. More...
 
subroutine initialize (this, ncrossptstot, ncrosspts, iacross, station, height, roughfraction)
 Initialize a cross-section object. More...
 
subroutine source_table (this, irch, width, mempath, filename)
 Source a reach's cross-section table from its SFRTAB6 subpackage. More...
 
subroutine read_table (this, irch, width, filename)
 Read a cross-section table file for a reach. More...
 
subroutine validate (this, irch)
 Validate cross-section tables. More...
 
subroutine output (this, widths, roughs, kstp, kper)
 Write cross-section tables. More...
 
integer(i4b) function get_ncrossptstot (this)
 Get the total number of cross-section points. More...
 
subroutine pack (this, ncrossptstot, ncrosspts, iacross, station, height, roughfraction)
 Pack the cross-section object. More...
 
subroutine destroy (this)
 Deallocate the cross-section object. More...
 

Function/Subroutine Documentation

◆ cross_section_cr()

subroutine, public sfrcrosssectionmanager::cross_section_cr ( type(sfrcrosssection), pointer  this,
integer(i4b), intent(in), pointer  iout,
integer(i4b), intent(in), pointer  iprpak,
integer(i4b), intent(in), pointer  nreaches 
)

Subroutine to calculate the maximum top width for a reach using the cross-section station data.

Parameters
thisSfrCrossSection object
[in]ioutmodel listing file
[in]iprpakflag for printing table input data
[in]nreachesnumber of reaches

Definition at line 58 of file SfrCrossSectionManager.f90.

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
Here is the caller graph for this function:

◆ destroy()

subroutine sfrcrosssectionmanager::destroy ( class(sfrcrosssection)  this)

Subroutine to deallocate the cross-section object.

Parameters
thisSfrCrossSection object

Definition at line 788 of file SfrCrossSectionManager.f90.

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)

◆ get_ncrossptstot()

integer(i4b) function sfrcrosssectionmanager::get_ncrossptstot ( class(sfrcrosssection)  this)

Function to get the total number of cross-section points to get the new size of the station xsheight data for all reaches.

Definition at line 732 of file SfrCrossSectionManager.f90.

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

◆ initialize()

subroutine sfrcrosssectionmanager::initialize ( class(sfrcrosssection)  this,
integer(i4b), intent(in)  ncrossptstot,
integer(i4b), dimension(this%nreaches), intent(in)  ncrosspts,
integer(i4b), dimension(this%nreaches + 1), intent(in)  iacross,
real(dp), dimension(ncrossptstot), intent(in)  station,
real(dp), dimension(ncrossptstot), intent(in)  height,
real(dp), dimension(ncrossptstot), intent(in)  roughfraction 
)

Subroutine to initialize the cross-section object with the current data.

Parameters
thisSfrCrossSection object
[in]ncrossptstottotal number of cross-section points
[in]ncrossptspointers to cross-section data in data vector
[in]iacrosspointers to cross-section data in data vector
[in]stationcross-section station data
[in]heightcross-section height data
[in]roughfractioncross-section roughness fraction data

Definition at line 87 of file SfrCrossSectionManager.f90.

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

◆ output()

subroutine sfrcrosssectionmanager::output ( class(sfrcrosssection)  this,
real(dp), dimension(this%nreaches), intent(in)  widths,
real(dp), dimension(this%nreaches), intent(in)  roughs,
integer(i4b), intent(in), optional  kstp,
integer(i4b), intent(in), optional  kper 
)

Subroutine to write the cross-section tables to the model listing file.

Parameters
thisSfrCrossSection object
[in]widthsreach widths
[in]roughsreach Manning's roughness coefficients
[in]kstptime step
[in]kperstress period

Definition at line 570 of file SfrCrossSectionManager.f90.

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
This module contains simulation constants.
Definition: Constants.f90:9
@ tableft
left justified table column
Definition: Constants.f90:172
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:237
Here is the call graph for this function:

◆ pack()

subroutine sfrcrosssectionmanager::pack ( class(sfrcrosssection)  this,
integer(i4b), intent(in)  ncrossptstot,
integer(i4b), dimension(this%nreaches), intent(inout)  ncrosspts,
integer(i4b), dimension(this%nreaches + 1), intent(inout)  iacross,
real(dp), dimension(ncrossptstot), intent(inout)  station,
real(dp), dimension(ncrossptstot), intent(inout)  height,
real(dp), dimension(ncrossptstot), intent(inout)  roughfraction 
)

Subroutine to pack the cross-section object into vectors.

Parameters
thisSfrCrossSection object
[in]ncrossptstottotal number of cross-section points
[in,out]ncrossptspointers to cross-section data in data vector
[in,out]iacrosspointers to cross-section data in data vector
[in,out]stationcross-section station data
[in,out]heightcross-section height data
[in,out]roughfractioncross-section roughness fraction data

Definition at line 751 of file SfrCrossSectionManager.f90.

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

◆ read_table()

subroutine sfrcrosssectionmanager::read_table ( class(sfrcrosssection)  this,
integer(i4b), intent(in)  irch,
real(dp), intent(in)  width,
character(len=*), intent(in)  filename 
)

Used only for the PERIOD block's dynamic CROSS_SECTION reissue, whose file path is not known until runtime.

Parameters
thisSfrCrossSection object
[in]irchcurrent reach
[in]widthreach width
[in]filenametable file with station height data

Definition at line 243 of file SfrCrossSectionManager.f90.

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
This module contains block parser methods.
Definition: BlockParser.f90:7
integer(i4b), parameter iuoc
open/close file unit number
Definition: Constants.f90:56
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
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
Here is the call graph for this function:

◆ source_table()

subroutine sfrcrosssectionmanager::source_table ( class(sfrcrosssection)  this,
integer(i4b), intent(in)  irch,
real(dp), intent(in)  width,
character(len=*), intent(in)  mempath,
character(len=*), intent(in)  filename 
)
Parameters
thisSfrCrossSection object
[in]irchcurrent reach
[in]widthreach width
[in]mempathSFRTAB6 input mempath
[in]filenametable file name, for reporting

Definition at line 144 of file SfrCrossSectionManager.f90.

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)
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
Here is the call graph for this function:

◆ validate()

subroutine sfrcrosssectionmanager::validate ( class(sfrcrosssection)  this,
integer(i4b), intent(in)  irch 
)

Subroutine to validate a cross-section table.

Parameters
thisSfrCrossSection object
[in]irchcurrent reach

Definition at line 430 of file SfrCrossSectionManager.f90.

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)
real(dp), parameter dtwothirds
real constant 2/3
Definition: Constants.f90:70
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
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.
Here is the call graph for this function: