MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
flowmodelinterfacemodule Module Reference

Data Types

type  flowmodelinterfacetype
 

Functions/Subroutines

subroutine fmi_df (this, dis, idryinactive)
 Define the flow model interface. More...
 
subroutine fmi_ar (this, ibound)
 Allocate the package. More...
 
subroutine fmi_da (this)
 Deallocate variables. More...
 
subroutine allocate_scalars (this)
 Allocate scalars. More...
 
subroutine allocate_arrays (this, nodes)
 Allocate arrays. More...
 
subroutine source_options (this)
 @ brief Source input options for package More...
 
subroutine source_packagedata (this)
 @ brief Source input options for package More...
 
subroutine read_grid (this)
 Read/validate flow model grid. More...
 
subroutine initialize_bfr (this)
 Initialize the budget file reader. More...
 
subroutine advance_bfr (this)
 Advance the budget file reader. More...
 
subroutine finalize_bfr (this)
 Finalize the budget file reader. More...
 
subroutine initialize_hfr (this)
 Initialize the head file reader. More...
 
subroutine advance_hfr (this)
 Advance the head file reader. More...
 
subroutine finalize_hfr (this)
 Finalize the head file reader. More...
 
subroutine initialize_gwfterms_from_bfr (this)
 Initialize gwf terms from budget file. More...
 
subroutine initialize_gwfterms_from_gwfbndlist (this)
 Initialize gwf terms from a GWF exchange. More...
 
subroutine allocate_gwfpackages (this, ngwfterms)
 Allocate budget packages. More...
 
subroutine deallocate_gwfpackages (this)
 Deallocate memory in the gwfpackages array. More...
 
subroutine get_package_index (this, name, idx)
 Find the package index for the package with the given name. More...
 

Function/Subroutine Documentation

◆ advance_bfr()

subroutine flowmodelinterfacemodule::advance_bfr ( class(flowmodelinterfacetype this)
private

Advance the budget file reader by reading the next chunk of information for the current time step and stress period.

Definition at line 593 of file FlowModelInterface.f90.

594  ! -- modules
595  use tdismodule, only: kstp, kper, endofsimulation
596  ! -- dummy
597  class(FlowModelInterfaceType) :: this
598  ! -- local
599  logical :: success
600  integer(I4B) :: n
601  integer(I4B) :: ipos
602  integer(I4B) :: nu, nr
603  integer(I4B) :: ip, i
604  logical :: readnext
605  ! -- format
606  character(len=*), parameter :: fmtkstpkper = &
607  "(1x,/1x,'FMI READING BUDGET TERMS &
608  &FOR KSTP ', i0, ' KPER ', i0)"
609  character(len=*), parameter :: fmtbudkstpkper = &
610  "(1x,/1x, 'FMI SETTING BUDGET TERMS &
611  &FOR KSTP ', i0, ' AND KPER ', &
612  &i0, ' TO BUDGET FILE TERMS FROM &
613  &KSTP ', i0, ' AND KPER ', i0)"
614  character(len=*), parameter :: fmtbadtdis = &
615  "(4x, 'TIME DISCRETIZATION IN BUDGET FILE &
616  &IS INCOMPATIBLE WITH TIME DISCRETIZATION IN COUPLED MODEL. &
617  &IF THERE IS MORE THAN ONE TIME STEP IN THE BUDGET FILE FOR A &
618  &GIVEN STRESS PERIOD, BUDGET FILE TIME STEPS MUST MATCH THE &
619  &COUPLED MODEL TIME STEPS ONE-FOR-ONE IN THAT STRESS PERIOD.')"
620  !
621  ! -- If the latest record read from the budget file is from a stress
622  ! -- period with only one time step, reuse that record (do not read a
623  ! -- new record) if the running model is still in that same stress period,
624  ! -- or if that record is the last one in the budget file.
625  readnext = .true.
626  if (kstp * kper > 1) then
627  if (this%bfr%header%kstp == 1) then
628  if (this%bfr%endoffile) then
629  readnext = .false.
630  else if (this%bfr%headernext%kper == kper + 1) then
631  readnext = .false.
632  end if
633  else if (this%bfr%endoffile) then
634  write (errmsg, '(4x,a)') 'REACHED END OF GWF BUDGET &
635  &FILE BEFORE READING SUFFICIENT BUDGET INFORMATION FOR THIS &
636  &GWT SIMULATION.'
637  call store_error(errmsg)
638  call store_error_unit(this%iubud)
639  end if
640  end if
641  !
642  ! -- Read the next record
643  if (readnext) then
644  !
645  ! -- Write the current time step and stress period
646  write (this%iout, fmtkstpkper) kstp, kper
647  !
648  ! -- loop through the budget terms for this stress period
649  ! i is the counter for gwf flow packages
650  ip = 1
651  do n = 1, this%bfr%nbudterms
652  call this%bfr%read_record(success, this%iout)
653  if (.not. success) then
654  write (errmsg, '(4x,a)') 'GWF BUDGET READ NOT SUCCESSFUL'
655  call store_error(errmsg)
656  call store_error_unit(this%iubud)
657  end if
658  !
659  ! -- Ensure kper is same between model and budget file
660  if (kper /= this%bfr%header%kper) then
661  write (errmsg, fmtbadtdis)
662  call store_error(errmsg)
663  call store_error_unit(this%iubud)
664  end if
665  !
666  ! -- if budget file kstp > 1, then kstp must match
667  if (this%bfr%header%kstp > 1 .and. (kstp /= this%bfr%header%kstp)) then
668  write (errmsg, fmtbadtdis)
669  call store_error(errmsg)
670  call store_error_unit(this%iubud)
671  end if
672  !
673  ! -- parse based on the type of data, and compress all user node
674  ! numbers into reduced node numbers
675  select type (h => this%bfr%header)
676  type is (budgetfileheadertype)
677  select case (trim(adjustl(h%budtxt)))
678  case ('FLOW-JA-FACE')
679  !
680  ! -- bfr%flowja contains only reduced connections so there is
681  ! a one-to-one match with this%gwfflowja
682  do ipos = 1, size(this%bfr%flowja)
683  this%gwfflowja(ipos) = this%bfr%flowja(ipos)
684  end do
685  case ('DATA-SPDIS')
686  do i = 1, h%nlist
687  nu = this%bfr%nodesrc(i)
688  nr = this%dis%get_nodenumber(nu, 0)
689  if (nr <= 0) cycle
690  this%gwfspdis(1, nr) = this%bfr%auxvar(1, i)
691  this%gwfspdis(2, nr) = this%bfr%auxvar(2, i)
692  this%gwfspdis(3, nr) = this%bfr%auxvar(3, i)
693  end do
694  case ('DATA-SAT')
695  do i = 1, h%nlist
696  nu = this%bfr%nodesrc(i)
697  nr = this%dis%get_nodenumber(nu, 0)
698  if (nr <= 0) cycle
699  this%gwfsat(nr) = this%bfr%auxvar(1, i)
700  end do
701  case ('STO-SS')
702  do nu = 1, this%dis%nodesuser
703  nr = this%dis%get_nodenumber(nu, 0)
704  if (nr <= 0) cycle
705  this%gwfstrgss(nr) = this%bfr%flow(nu)
706  end do
707  case ('STO-SY')
708  do nu = 1, this%dis%nodesuser
709  nr = this%dis%get_nodenumber(nu, 0)
710  if (nr <= 0) cycle
711  this%gwfstrgsy(nr) = this%bfr%flow(nu)
712  end do
713  case default
714  call this%gwfpackages(ip)%copy_values( &
715  h%nlist, &
716  this%bfr%nodesrc, &
717  this%bfr%flow, &
718  this%bfr%auxvar)
719  do i = 1, this%gwfpackages(ip)%nbound
720  nu = this%gwfpackages(ip)%nodelist(i)
721  nr = this%dis%get_nodenumber(nu, 0)
722  this%gwfpackages(ip)%nodelist(i) = nr
723  end do
724  ip = ip + 1
725  end select
726  end select
727  end do
728 
729  ! If this is the final time step, make sure no records
730  ! for this period are being skipped in the budget file.
731  if (endofsimulation .and. .not. this%bfr%endoffile) then
732  if (this%bfr%headernext%kper == kper) then
733  write (errmsg, fmtbadtdis)
734  call store_error(errmsg)
735  call store_error_unit(this%iubud)
736  end if
737  end if
738  else
739  !
740  ! -- write message to indicate that flows are being reused
741  write (this%iout, fmtbudkstpkper) kstp, kper, &
742  this%bfr%header%kstp, this%bfr%header%kper
743  !
744  ! -- set the flag to indicate that flows were not updated
745  this%iflowsupdated = 0
746  end if
logical(lgp), pointer, public endofsimulation
flag indicating end of simulation
Definition: tdis.f90:31
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
Here is the call graph for this function:

◆ advance_hfr()

subroutine flowmodelinterfacemodule::advance_hfr ( class(flowmodelinterfacetype this)
private

Definition at line 764 of file FlowModelInterface.f90.

765  ! modules
766  use tdismodule, only: kstp, kper
767  class(FlowModelInterfaceType) :: this
768  integer(I4B) :: nu, nr, i, ilay
769  integer(I4B) :: ncpl
770  real(DP) :: val
771  logical :: readnext
772  logical :: success
773  character(len=*), parameter :: fmtkstpkper = &
774  "(1x,/1x,'FMI READING HEAD FOR &
775  &KSTP ', i0, ' KPER ', i0)"
776  character(len=*), parameter :: fmthdskstpkper = &
777  "(1x,/1x, 'FMI SETTING HEAD FOR KSTP ', i0, ' AND KPER ', &
778  &i0, ' TO BINARY FILE HEADS FROM KSTP ', i0, ' AND KPER ', i0)"
779  !
780  ! -- If the latest record read from the head file is from a stress
781  ! -- period with only one time step, reuse that record (do not read a
782  ! -- new record) if the running model is still in that same stress period,
783  ! -- or if that record is the last one in the head file.
784  readnext = .true.
785  if (kstp * kper > 1) then
786  if (this%hfr%header%kstp == 1) then
787  if (this%hfr%endoffile) then
788  readnext = .false.
789  else if (this%hfr%headernext%kper == kper + 1) then
790  readnext = .false.
791  end if
792  else if (this%hfr%endoffile) then
793  write (errmsg, '(4x,a)') 'REACHED END OF GWF HEAD &
794  &FILE BEFORE READING SUFFICIENT HEAD INFORMATION FOR THIS &
795  &GWT SIMULATION.'
796  call store_error(errmsg)
797  call store_error_unit(this%iuhds)
798  end if
799  end if
800  !
801  ! -- Read the next record
802  if (readnext) then
803  !
804  ! -- write to list file that heads are being read
805  write (this%iout, fmtkstpkper) kstp, kper
806  !
807  ! -- loop through the layered heads for this time step
808  do ilay = 1, this%hfr%nlay
809  !
810  ! -- read next head chunk
811  call this%hfr%read_record(success, this%iout)
812  if (.not. success) then
813  write (errmsg, '(4x,a)') 'GWF HEAD READ NOT SUCCESSFUL'
814  call store_error(errmsg)
815  call store_error_unit(this%iuhds)
816  end if
817  !
818  ! -- Ensure kper is same between model and head file
819  if (kper /= this%hfr%header%kper) then
820  write (errmsg, '(4x,a)') 'PERIOD NUMBER IN HEAD FILE &
821  &DOES NOT MATCH PERIOD NUMBER IN TRANSPORT MODEL. IF THERE &
822  &IS MORE THAN ONE TIME STEP IN THE HEAD FILE FOR A GIVEN STRESS &
823  &PERIOD, HEAD FILE TIME STEPS MUST MATCH GWT MODEL TIME STEPS &
824  &ONE-FOR-ONE IN THAT STRESS PERIOD.'
825  call store_error(errmsg)
826  call store_error_unit(this%iuhds)
827  end if
828  !
829  ! -- if head file kstp > 1, then kstp must match
830  if (this%hfr%header%kstp > 1 .and. (kstp /= this%hfr%header%kstp)) then
831  write (errmsg, '(4x,a)') 'TIME STEP NUMBER IN HEAD FILE &
832  &DOES NOT MATCH TIME STEP NUMBER IN TRANSPORT MODEL. IF THERE &
833  &IS MORE THAN ONE TIME STEP IN THE HEAD FILE FOR A GIVEN STRESS &
834  &PERIOD, HEAD FILE TIME STEPS MUST MATCH GWT MODEL TIME STEPS &
835  &ONE-FOR-ONE IN THAT STRESS PERIOD.'
836  call store_error(errmsg)
837  call store_error_unit(this%iuhds)
838  end if
839  !
840  ! -- fill the head array for this layer and
841  ! compress into reduced form
842  ncpl = size(this%hfr%head)
843  do i = 1, ncpl
844  nu = (ilay - 1) * ncpl + i
845  nr = this%dis%get_nodenumber(nu, 0)
846  val = this%hfr%head(i)
847  if (nr > 0) this%gwfhead(nr) = val
848  end do
849  end do
850  else
851  write (this%iout, fmthdskstpkper) kstp, kper, &
852  this%hfr%header%kstp, this%hfr%header%kper
853  end if
Here is the call graph for this function:

◆ allocate_arrays()

subroutine flowmodelinterfacemodule::allocate_arrays ( class(flowmodelinterfacetype this,
integer(i4b), intent(in)  nodes 
)

Definition at line 247 of file FlowModelInterface.f90.

249  !modules
250  use constantsmodule, only: dzero
251  ! -- dummy
252  class(FlowModelInterfaceType) :: this
253  integer(I4B), intent(in) :: nodes
254  ! -- local
255  integer(I4B) :: n
256  !
257  ! -- Allocate ibdgwfsat0, which is an indicator array marking cells with
258  ! saturation greater than 0.0 with a value of 1
259  call mem_allocate(this%ibdgwfsat0, nodes, 'IBDGWFSAT0', this%memoryPath)
260  do n = 1, nodes
261  this%ibdgwfsat0(n) = 1
262  end do
263  !
264  ! -- Allocate differently depending on whether or not flows are
265  ! being read from a file.
266  if (this%flows_from_file) then
267  call mem_allocate(this%gwfflowja, this%dis%con%nja, &
268  'GWFFLOWJA', this%memoryPath)
269  call mem_allocate(this%gwfsat, nodes, 'GWFSAT', this%memoryPath)
270  call mem_allocate(this%gwfhead, nodes, 'GWFHEAD', this%memoryPath)
271  call mem_allocate(this%gwfspdis, 3, nodes, 'GWFSPDIS', this%memoryPath)
272  do n = 1, nodes
273  this%gwfsat(n) = done
274  this%gwfhead(n) = dzero
275  this%gwfspdis(:, n) = dzero
276  end do
277  do n = 1, size(this%gwfflowja)
278  this%gwfflowja(n) = dzero
279  end do
280  !
281  ! -- allocate and initialize storage arrays
282  if (this%igwfstrgss == 0) then
283  call mem_allocate(this%gwfstrgss, 1, 'GWFSTRGSS', this%memoryPath)
284  else
285  call mem_allocate(this%gwfstrgss, nodes, 'GWFSTRGSS', this%memoryPath)
286  end if
287  if (this%igwfstrgsy == 0) then
288  call mem_allocate(this%gwfstrgsy, 1, 'GWFSTRGSY', this%memoryPath)
289  else
290  call mem_allocate(this%gwfstrgsy, nodes, 'GWFSTRGSY', this%memoryPath)
291  end if
292  do n = 1, size(this%gwfstrgss)
293  this%gwfstrgss(n) = dzero
294  end do
295  do n = 1, size(this%gwfstrgsy)
296  this%gwfstrgsy(n) = dzero
297  end do
298  ! allocate and initialize cell type array. if the FMI is in a separate
299  ! simulation from the GWF model, we expect cell type to have been read
300  ! already if the binary grid file was provided to FMI. otherwise don't
301  ! initialize the cell type array to any default; unless it is received
302  ! from GWF NPF by an EXG it's undefined as indicated by igwfceltyp = 0
303  if (this%igwfceltyp == 0) &
304  call mem_allocate(this%gwfceltyp, nodes, 'GWFCELTYP', this%memoryPath)
305  !
306  ! -- If there is no fmi package, then there are no flows at all or a
307  ! connected GWF model, so allocate gwfpackages to zero
308  if (this%inunit == 0) call this%allocate_gwfpackages(this%nflowpack)
309  end if
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65

◆ allocate_gwfpackages()

subroutine flowmodelinterfacemodule::allocate_gwfpackages ( class(flowmodelinterfacetype this,
integer(i4b), intent(in)  ngwfterms 
)

gwfpackages is an array of PackageBudget objects. This routine allocates gwfpackages to the proper size and initializes some member variables.

Definition at line 1028 of file FlowModelInterface.f90.

1029  ! -- modules
1030  use constantsmodule, only: lenmempath
1032  ! -- dummy
1033  class(FlowModelInterfaceType) :: this
1034  integer(I4B), intent(in) :: ngwfterms
1035  ! -- local
1036  integer(I4B) :: n
1037  character(len=LENMEMPATH) :: memPath
1038  !
1039  ! -- direct allocate
1040  allocate (this%gwfpackages(ngwfterms))
1041  allocate (this%flowpacknamearray(ngwfterms))
1042  !
1043  ! -- mem_allocate
1044  call mem_allocate(this%igwfmvrterm, ngwfterms, 'IGWFMVRTERM', this%memoryPath)
1045  !
1046  ! -- initialize
1047  this%nflowpack = ngwfterms
1048  do n = 1, this%nflowpack
1049  this%igwfmvrterm(n) = 0
1050  this%flowpacknamearray(n) = ''
1051  !
1052  ! -- Create a mempath for each individual flow package data set
1053  ! of the form, MODELNAME/FMI-FTn
1054  write (mempath, '(a, i0)') trim(this%memoryPath)//'-FT', n
1055  call this%gwfpackages(n)%initialize(mempath)
1056  end do
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27

◆ allocate_scalars()

subroutine flowmodelinterfacemodule::allocate_scalars ( class(flowmodelinterfacetype this)

Definition at line 204 of file FlowModelInterface.f90.

205  ! -- modules
208  ! -- dummy
209  class(FlowModelInterfaceType) :: this
210  ! -- local
211  !
212  ! -- allocate scalars in NumericalPackageType
213  call this%NumericalPackageType%allocate_scalars()
214  !
215  ! -- Allocate
216  call mem_allocate(this%flows_from_file, 'FLOWS_FROM_FILE', this%memoryPath)
217  call mem_allocate(this%iflowsupdated, 'IFLOWSUPDATED', this%memoryPath)
218  call mem_allocate(this%igwfspdis, 'IGWFSPDIS', this%memoryPath)
219  call mem_allocate(this%igwfstrgss, 'IGWFSTRGSS', this%memoryPath)
220  call mem_allocate(this%igwfstrgsy, 'IGWFSTRGSY', this%memoryPath)
221  call mem_allocate(this%igwfceltyp, 'IGWFCELTYP', this%memoryPath)
222  call mem_allocate(this%iubud, 'IUBUD', this%memoryPath)
223  call mem_allocate(this%iuhds, 'IUHDS', this%memoryPath)
224  call mem_allocate(this%iumvr, 'IUMVR', this%memoryPath)
225  call mem_allocate(this%iugrb, 'IUGRB', this%memoryPath)
226  call mem_allocate(this%nflowpack, 'NFLOWPACK', this%memoryPath)
227  call mem_allocate(this%idryinactive, "IDRYINACTIVE", this%memoryPath)
228  !
229  ! !
230  ! -- Initialize
231  this%flows_from_file = .true.
232  this%iflowsupdated = 1
233  this%igwfspdis = 0
234  this%igwfstrgss = 0
235  this%igwfstrgsy = 0
236  this%igwfceltyp = 0
237  this%iubud = 0
238  this%iuhds = 0
239  this%iumvr = 0
240  this%iugrb = 0
241  this%nflowpack = 0
242  this%idryinactive = 1

◆ deallocate_gwfpackages()

subroutine flowmodelinterfacemodule::deallocate_gwfpackages ( class(flowmodelinterfacetype this)

Definition at line 1060 of file FlowModelInterface.f90.

1061  class(FlowModelInterfaceType) :: this
1062  integer(I4B) :: n
1063 
1064  do n = 1, this%nflowpack
1065  call this%gwfpackages(n)%da()
1066  end do

◆ finalize_bfr()

subroutine flowmodelinterfacemodule::finalize_bfr ( class(flowmodelinterfacetype this)

Definition at line 750 of file FlowModelInterface.f90.

751  class(FlowModelInterfaceType) :: this
752  call this%bfr%finalize()

◆ finalize_hfr()

subroutine flowmodelinterfacemodule::finalize_hfr ( class(flowmodelinterfacetype this)

Definition at line 857 of file FlowModelInterface.f90.

858  class(FlowModelInterfaceType) :: this
859  close (this%iuhds)

◆ fmi_ar()

subroutine flowmodelinterfacemodule::fmi_ar ( class(flowmodelinterfacetype this,
integer(i4b), dimension(:), pointer, contiguous  ibound 
)
private

Definition at line 141 of file FlowModelInterface.f90.

142  ! -- modules
143  ! -- dummy
144  class(FlowModelInterfaceType) :: this
145  integer(I4B), dimension(:), pointer, contiguous :: ibound
146  !
147  ! -- store pointers to arguments that were passed in
148  this%ibound => ibound
149  !
150  ! -- Allocate arrays
151  call this%allocate_arrays(this%dis%nodes)

◆ fmi_da()

subroutine flowmodelinterfacemodule::fmi_da ( class(flowmodelinterfacetype this)
private

Definition at line 156 of file FlowModelInterface.f90.

157  ! -- modules
159  ! -- dummy
160  class(FlowModelInterfaceType) :: this
161  ! -- todo: finalize hfr and bfr either here or in a finalize routine
162  !
163  ! -- deallocate any memory stored with gwfpackages
164  call this%deallocate_gwfpackages()
165  !
166  ! -- deallocate fmi arrays
167  deallocate (this%gwfpackages)
168  deallocate (this%flowpacknamearray)
169  call mem_deallocate(this%igwfmvrterm)
170  call mem_deallocate(this%ibdgwfsat0)
171  !
172  if (this%flows_from_file) then
173  call mem_deallocate(this%gwfstrgss)
174  call mem_deallocate(this%gwfstrgsy)
175  call mem_deallocate(this%gwfceltyp)
176  end if
177  !
178  ! -- special treatment, these could be from mem_checkin
179  call mem_deallocate(this%gwfhead, 'GWFHEAD', this%memoryPath)
180  call mem_deallocate(this%gwfsat, 'GWFSAT', this%memoryPath)
181  call mem_deallocate(this%gwfspdis, 'GWFSPDIS', this%memoryPath)
182  call mem_deallocate(this%gwfflowja, 'GWFFLOWJA', this%memoryPath)
183  !
184  ! -- deallocate scalars
185  call mem_deallocate(this%flows_from_file)
186  call mem_deallocate(this%iflowsupdated)
187  call mem_deallocate(this%igwfspdis)
188  call mem_deallocate(this%igwfstrgss)
189  call mem_deallocate(this%igwfstrgsy)
190  call mem_deallocate(this%igwfceltyp)
191  call mem_deallocate(this%iubud)
192  call mem_deallocate(this%iuhds)
193  call mem_deallocate(this%iumvr)
194  call mem_deallocate(this%iugrb)
195  call mem_deallocate(this%nflowpack)
196  call mem_deallocate(this%idryinactive)
197  !
198  ! -- deallocate parent
199  call this%NumericalPackageType%da()

◆ fmi_df()

subroutine flowmodelinterfacemodule::fmi_df ( class(flowmodelinterfacetype this,
class(disbasetype), intent(in), pointer  dis,
integer(i4b), intent(in)  idryinactive 
)
private

Definition at line 85 of file FlowModelInterface.f90.

86  ! -- modules
87  ! -- dummy
88  class(FlowModelInterfaceType) :: this
89  class(DisBaseType), pointer, intent(in) :: dis
90  integer(I4B), intent(in) :: idryinactive
91  ! -- formats
92  character(len=*), parameter :: fmtfmi = &
93  "(1x,/1x,'FMI -- FLOW MODEL INTERFACE, VERSION 2, 8/17/2023', &
94  &' INPUT READ FROM MEMPATH: ', A, //)"
95  character(len=*), parameter :: fmtfmi0 = &
96  "(1x,/1x,'FMI -- FLOW MODEL INTERFACE,'&
97  &' VERSION 2, 8/17/2023')"
98  !
99  ! --print a message identifying the FMI package.
100  if (this%iout > 0) then
101  if (this%inunit /= 0) then
102  write (this%iout, fmtfmi) this%input_mempath
103  else
104  write (this%iout, fmtfmi0)
105  if (this%flows_from_file) then
106  write (this%iout, '(a)') ' FLOWS ARE ASSUMED TO BE ZERO.'
107  else
108  write (this%iout, '(a)') ' FLOWS PROVIDED BY A GWF MODEL IN THIS &
109  &SIMULATION'
110  end if
111  end if
112  end if
113  !
114  ! -- Store pointers
115  this%dis => dis
116  !
117  ! -- Read fmi options
118  if (this%inunit /= 0) then
119  call this%source_options()
120  end if
121  !
122  ! -- Read packagedata options
123  if (this%inunit /= 0 .and. this%flows_from_file) then
124  call this%source_packagedata()
125  call this%initialize_gwfterms_from_bfr()
126  end if
127  !
128  ! -- If GWF-Model exchange is active, setup flow terms
129  if (.not. this%flows_from_file) then
130  call this%initialize_gwfterms_from_gwfbndlist()
131  end if
132  !
133  ! -- Set flag that stops dry flows from being deactivated in a GWE
134  ! transport model since conduction will still be simulated.
135  ! 0: GWE (skip deactivation step); 1: GWT (default: use existing code)
136  this%idryinactive = idryinactive

◆ get_package_index()

subroutine flowmodelinterfacemodule::get_package_index ( class(flowmodelinterfacetype this,
character(len=*), intent(in)  name,
integer(i4b), intent(inout)  idx 
)
private

Definition at line 1070 of file FlowModelInterface.f90.

1071  use bndmodule, only: bndtype, getbndfromlist
1072  class(FlowModelInterfaceType) :: this
1073  character(len=*), intent(in) :: name
1074  integer(I4B), intent(inout) :: idx
1075  ! -- local
1076  integer(I4B) :: ip
1077  !
1078  ! -- Look through all the packages and return the index with name
1079  idx = 0
1080  do ip = 1, size(this%flowpacknamearray)
1081  if (this%flowpacknamearray(ip) == name) then
1082  idx = ip
1083  exit
1084  end if
1085  end do
1086  if (idx == 0) then
1087  call store_error('Error in get_package_index. Could not find '//name, &
1088  terminate=.true.)
1089  end if
This module contains the base boundary package.
class(bndtype) function, pointer, public getbndfromlist(list, idx)
Get boundary from package list.
@ brief BndType
Here is the call graph for this function:

◆ initialize_bfr()

subroutine flowmodelinterfacemodule::initialize_bfr ( class(flowmodelinterfacetype this)

Definition at line 580 of file FlowModelInterface.f90.

581  class(FlowModelInterfaceType) :: this
582  integer(I4B) :: ncrbud
583  call this%bfr%initialize(this%iubud, this%iout, ncrbud)
584  ! todo: need to run through the budget terms
585  ! and do some checking

◆ initialize_gwfterms_from_bfr()

subroutine flowmodelinterfacemodule::initialize_gwfterms_from_bfr ( class(flowmodelinterfacetype this)
private

initialize terms and figure out how many different terms and packages are contained within the file

Definition at line 867 of file FlowModelInterface.f90.

868  ! -- dummy
869  class(FlowModelInterfaceType) :: this
870  ! -- local
871  integer(I4B) :: nflowpack
872  integer(I4B) :: i, ip
873  integer(I4B) :: naux
874  logical :: found_flowja
875  logical :: found_dataspdis
876  logical :: found_datasat
877  logical :: found_stoss
878  logical :: found_stosy
879  integer(I4B), dimension(:), allocatable :: imap
880  !
881  ! -- Calculate the number of gwf flow packages
882  allocate (imap(this%bfr%nbudterms))
883  imap(:) = 0
884  nflowpack = 0
885  found_flowja = .false.
886  found_dataspdis = .false.
887  found_datasat = .false.
888  found_stoss = .false.
889  found_stosy = .false.
890  do i = 1, this%bfr%nbudterms
891  select case (trim(adjustl(this%bfr%budtxtarray(i))))
892  case ('FLOW-JA-FACE')
893  found_flowja = .true.
894  case ('DATA-SPDIS')
895  found_dataspdis = .true.
896  this%igwfspdis = 1
897  case ('DATA-SAT')
898  found_datasat = .true.
899  case ('STO-SS')
900  found_stoss = .true.
901  this%igwfstrgss = 1
902  case ('STO-SY')
903  found_stosy = .true.
904  this%igwfstrgsy = 1
905  case default
906  nflowpack = nflowpack + 1
907  imap(i) = 1
908  end select
909  end do
910  !
911  ! -- allocate gwfpackage arrays
912  call this%allocate_gwfpackages(nflowpack)
913  !
914  ! -- Copy the package name and aux names from budget file reader
915  ! to the gwfpackages derived-type variable
916  ip = 1
917  do i = 1, this%bfr%nbudterms
918  if (imap(i) == 0) cycle
919  call this%gwfpackages(ip)%set_name(this%bfr%dstpackagenamearray(i), &
920  this%bfr%budtxtarray(i))
921  naux = this%bfr%nauxarray(i)
922  call this%gwfpackages(ip)%set_auxname(naux, this%bfr%auxtxtarray(1:naux, i))
923  ip = ip + 1
924  end do
925  !
926  ! -- Copy just the package names for the boundary packages into
927  ! the flowpacknamearray
928  ip = 1
929  do i = 1, size(imap)
930  if (imap(i) == 1) then
931  this%flowpacknamearray(ip) = this%bfr%dstpackagenamearray(i)
932  ip = ip + 1
933  end if
934  end do
935  !
936  ! -- Error if specific discharge, saturation or flowja not found
937  if (.not. found_dataspdis) then
938  write (errmsg, '(4x,a)') 'SPECIFIC DISCHARGE NOT FOUND IN &
939  &BUDGET FILE. SAVE_SPECIFIC_DISCHARGE AND &
940  &SAVE_FLOWS MUST BE ACTIVATED IN THE NPF PACKAGE.'
941  call store_error(errmsg)
942  end if
943  if (.not. found_datasat) then
944  write (errmsg, '(4x,a)') 'SATURATION NOT FOUND IN &
945  &BUDGET FILE. SAVE_SATURATION AND &
946  &SAVE_FLOWS MUST BE ACTIVATED IN THE NPF PACKAGE.'
947  call store_error(errmsg)
948  end if
949  if (.not. found_flowja) then
950  write (errmsg, '(4x,a)') 'FLOWJA NOT FOUND IN &
951  &BUDGET FILE. SAVE_FLOWS MUST &
952  &BE ACTIVATED IN THE NPF PACKAGE.'
953  call store_error(errmsg)
954  end if
955  if (count_errors() > 0) then
956  call store_error_filename(this%input_fname)
957  end if
Here is the call graph for this function:

◆ initialize_gwfterms_from_gwfbndlist()

subroutine flowmodelinterfacemodule::initialize_gwfterms_from_gwfbndlist ( class(flowmodelinterfacetype this)
private

Definition at line 961 of file FlowModelInterface.f90.

962  ! -- modules
963  use bndmodule, only: bndtype, getbndfromlist
964  ! -- dummy
965  class(FlowModelInterfaceType) :: this
966  ! -- local
967  integer(I4B) :: ngwfpack
968  integer(I4B) :: ngwfterms
969  integer(I4B) :: ip
970  integer(I4B) :: imover
971  integer(I4B) :: ntomvr
972  integer(I4B) :: iterm
973  character(len=LENPACKAGENAME) :: budtxt
974  class(BndType), pointer :: packobj => null()
975  !
976  ! -- determine size of gwf terms
977  ngwfpack = this%gwfbndlist%Count()
978  !
979  ! -- Count number of to-mvr terms, but do not include advanced packages
980  ! as those mover terms are not losses from the cell, but rather flows
981  ! within the advanced package
982  ntomvr = 0
983  do ip = 1, ngwfpack
984  packobj => getbndfromlist(this%gwfbndlist, ip)
985  imover = packobj%imover
986  if (packobj%isadvpak /= 0) imover = 0
987  if (imover /= 0) then
988  ntomvr = ntomvr + 1
989  end if
990  end do
991  !
992  ! -- Allocate arrays in fmi of size ngwfterms, which is the number of
993  ! packages plus the number of packages with mover terms.
994  ngwfterms = ngwfpack + ntomvr
995  call this%allocate_gwfpackages(ngwfterms)
996  !
997  ! -- Assign values in the fmi package
998  iterm = 1
999  do ip = 1, ngwfpack
1000  !
1001  ! -- set and store names
1002  packobj => getbndfromlist(this%gwfbndlist, ip)
1003  budtxt = adjustl(packobj%text)
1004  call this%gwfpackages(iterm)%set_name(packobj%packName, budtxt)
1005  this%flowpacknamearray(iterm) = packobj%packName
1006  iterm = iterm + 1
1007  !
1008  ! -- if this package has a mover associated with it, then add another
1009  ! term that corresponds to the mover flows
1010  imover = packobj%imover
1011  if (packobj%isadvpak /= 0) imover = 0
1012  if (imover /= 0) then
1013  budtxt = trim(adjustl(packobj%text))//'-TO-MVR'
1014  call this%gwfpackages(iterm)%set_name(packobj%packName, budtxt)
1015  this%flowpacknamearray(iterm) = packobj%packName
1016  this%igwfmvrterm(iterm) = 1
1017  iterm = iterm + 1
1018  end if
1019  end do
Here is the call graph for this function:

◆ initialize_hfr()

subroutine flowmodelinterfacemodule::initialize_hfr ( class(flowmodelinterfacetype this)
private

Definition at line 756 of file FlowModelInterface.f90.

757  class(FlowModelInterfaceType) :: this
758  call this%hfr%initialize(this%iuhds, this%iout)
759  ! todo: need to run through the head terms
760  ! and do some checking

◆ read_grid()

subroutine flowmodelinterfacemodule::read_grid ( class(flowmodelinterfacetype this)

Definition at line 432 of file FlowModelInterface.f90.

433  ! -- modules
434  use dismodule, only: distype
435  use disvmodule, only: disvtype
436  use disumodule, only: disutype
437  use dis2dmodule, only: dis2dtype
438  use disv2dmodule, only: disv2dtype
439  use disv1dmodule, only: disv1dtype
440  ! -- dummy
441  class(FlowModelInterfaceType) :: this
442  ! -- local
443  integer(I4B) :: user_nodes
444  integer(I4B), allocatable :: idomain1d(:), idomain2d(:, :), idomain3d(:, :, :)
445  ! -- formats
446  character(len=*), parameter :: fmtdiserr = &
447  "('Error in ',a,': Models do not have the same discretization. &
448  &GWF model has ', i0, ' user nodes, this model has ', i0, '. &
449  &Ensure discretization packages, including IDOMAIN, are identical.')"
450  character(len=*), parameter :: fmtidomerr = &
451  "('Error in ',a,': models do not have the same discretization. &
452  &Models have different IDOMAIN arrays. &
453  &Ensure discretization packages, including IDOMAIN, are identical.')"
454 
455  call this%gfr%initialize(this%iugrb)
456 
457  ! load icelltype array
458  if (this%gfr%has_variable("ICELLTYPE")) then
459  this%igwfceltyp = 1
460  call mem_allocate(this%gwfceltyp, this%dis%nodesuser, &
461  'GWFCELTYP', this%memoryPath)
462  call this%gfr%read_int_1d_into("ICELLTYPE", this%gwfceltyp)
463  end if
464 
465  ! check grid equivalence
466  select case (this%gfr%grid_type)
467  case ('DIS')
468  select type (dis => this%dis)
469  type is (distype)
470  user_nodes = this%gfr%read_int("NCELLS")
471  if (user_nodes /= this%dis%nodesuser) then
472  write (errmsg, fmtdiserr) &
473  trim(this%text), user_nodes, this%dis%nodesuser
474  call store_error(errmsg, terminate=.true.)
475  end if
476  idomain1d = this%gfr%read_int_1d("IDOMAIN")
477  idomain3d = reshape(idomain1d, [ &
478  this%gfr%read_int("NCOL"), &
479  this%gfr%read_int("NROW"), &
480  this%gfr%read_int("NLAY") &
481  ])
482  if (.not. all(dis%idomain == idomain3d)) then
483  write (errmsg, fmtidomerr) trim(this%text)
484  call store_error(errmsg, terminate=.true.)
485  end if
486  end select
487  case ('DISV')
488  select type (dis => this%dis)
489  type is (disvtype)
490  user_nodes = this%gfr%read_int("NCELLS")
491  if (user_nodes /= this%dis%nodesuser) then
492  write (errmsg, fmtdiserr) &
493  trim(this%text), user_nodes, this%dis%nodesuser
494  call store_error(errmsg, terminate=.true.)
495  end if
496  idomain1d = this%gfr%read_int_1d("IDOMAIN")
497  idomain2d = reshape(idomain1d, [ &
498  this%gfr%read_int("NCPL"), &
499  this%gfr%read_int("NLAY") &
500  ])
501  if (.not. all(dis%idomain == idomain2d)) then
502  write (errmsg, fmtidomerr) trim(this%text)
503  call store_error(errmsg, terminate=.true.)
504  end if
505  end select
506  case ('DISU')
507  select type (dis => this%dis)
508  type is (disutype)
509  user_nodes = this%gfr%read_int("NODES")
510  if (user_nodes /= this%dis%nodesuser) then
511  write (errmsg, fmtdiserr) &
512  trim(this%text), user_nodes, this%dis%nodesuser
513  call store_error(errmsg, terminate=.true.)
514  end if
515  idomain1d = this%gfr%read_int_1d("IDOMAIN")
516  if (.not. all(dis%idomain == idomain1d)) then
517  write (errmsg, fmtidomerr) trim(this%text)
518  call store_error(errmsg, terminate=.true.)
519  end if
520  end select
521  case ('DIS2D')
522  select type (dis => this%dis)
523  type is (dis2dtype)
524  user_nodes = this%gfr%read_int("NCELLS")
525  if (user_nodes /= this%dis%nodesuser) then
526  write (errmsg, fmtdiserr) &
527  trim(this%text), user_nodes, this%dis%nodesuser
528  call store_error(errmsg, terminate=.true.)
529  end if
530  idomain1d = this%gfr%read_int_1d("IDOMAIN")
531  idomain2d = reshape(idomain1d, [ &
532  this%gfr%read_int("NCOL"), &
533  this%gfr%read_int("NROW") &
534  ])
535  if (.not. all(dis%idomain == idomain2d)) then
536  write (errmsg, fmtidomerr) trim(this%text)
537  call store_error(errmsg, terminate=.true.)
538  end if
539  end select
540  case ('DISV2D')
541  select type (dis => this%dis)
542  type is (disv2dtype)
543  user_nodes = this%gfr%read_int("NODES")
544  if (user_nodes /= this%dis%nodesuser) then
545  write (errmsg, fmtdiserr) &
546  trim(this%text), user_nodes, this%dis%nodesuser
547  call store_error(errmsg, terminate=.true.)
548  end if
549  idomain1d = this%gfr%read_int_1d("IDOMAIN")
550  if (.not. all(dis%idomain == idomain1d)) then
551  write (errmsg, fmtidomerr) trim(this%text)
552  call store_error(errmsg, terminate=.true.)
553  end if
554  end select
555  case ('DISV1D')
556  select type (dis => this%dis)
557  type is (disv1dtype)
558  user_nodes = this%gfr%read_int("NCELLS")
559  if (user_nodes /= this%dis%nodesuser) then
560  write (errmsg, fmtdiserr) &
561  trim(this%text), user_nodes, this%dis%nodesuser
562  call store_error(errmsg, terminate=.true.)
563  end if
564  idomain1d = this%gfr%read_int_1d("IDOMAIN")
565  if (.not. all(dis%idomain == idomain1d)) then
566  write (errmsg, fmtidomerr) trim(this%text)
567  call store_error(errmsg, terminate=.true.)
568  end if
569  end select
570  end select
571 
572  if (allocated(idomain3d)) deallocate (idomain3d)
573  if (allocated(idomain2d)) deallocate (idomain2d)
574  if (allocated(idomain1d)) deallocate (idomain1d)
575 
576  call this%gfr%finalize()
Definition: Dis.f90:1
Structured grid discretization.
Definition: Dis2d.f90:23
Structured grid discretization.
Definition: Dis.f90:23
Unstructured grid discretization.
Definition: Disu.f90:29
Vertex grid discretization.
Definition: Disv2d.f90:25
Vertex grid discretization.
Definition: Disv.f90:25
Here is the call graph for this function:

◆ source_options()

subroutine flowmodelinterfacemodule::source_options ( class(flowmodelinterfacetype this)

Definition at line 314 of file FlowModelInterface.f90.

315  ! -- modules
317  ! -- dummy
318  class(FlowModelInterfaceType) :: this
319  ! -- local
320  logical(LGP) :: found_ipakcb
321  character(len=*), parameter :: fmtisvflow = &
322  "(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY FILE &
323  &WHENEVER ICBCFL IS NOT ZERO AND FLOW IMBALANCE CORRECTION ACTIVE.')"
324 
325  ! -- source package input
326  call mem_set_value(this%ipakcb, 'SAVE_FLOWS', this%input_mempath, &
327  found_ipakcb)
328 
329  write (this%iout, '(1x,a)') 'PROCESSING FMI OPTIONS'
330 
331  if (found_ipakcb) then
332  this%ipakcb = -1
333  write (this%iout, fmtisvflow)
334  end if
335 
336  write (this%iout, '(1x,a)') 'END OF FMI OPTIONS'

◆ source_packagedata()

subroutine flowmodelinterfacemodule::source_packagedata ( class(flowmodelinterfacetype this)

Definition at line 341 of file FlowModelInterface.f90.

342  ! -- modules
346  use openspecmodule, only: access, form
349  ! -- dummy
350  class(FlowModelInterfaceType) :: this
351  ! -- local
352  type(CharacterStringType), dimension(:), contiguous, &
353  pointer :: flowtypes
354  type(CharacterStringType), dimension(:), contiguous, &
355  pointer :: fileops
356  type(CharacterStringType), dimension(:), contiguous, &
357  pointer :: fnames
358  character(len=LINELENGTH) :: flowtype, fileop, fname
359  integer(I4B) :: inunit, n
360  logical(LGP) :: exist
361 
362  call mem_setptr(flowtypes, 'FLOWTYPE', this%input_mempath)
363  call mem_setptr(fileops, 'FILEIN', this%input_mempath)
364  call mem_setptr(fnames, 'FNAME', this%input_mempath)
365 
366  write (this%iout, '(1x,a)') 'PROCESSING FMI PACKAGEDATA'
367 
368  do n = 1, size(flowtypes)
369  flowtype = flowtypes(n)
370  fileop = fileops(n)
371  fname = fnames(n)
372 
373  inquire (file=trim(fname), exist=exist)
374  if (.not. exist) then
375  call store_error('Could not find file '//trim(fname))
376  cycle
377  end if
378 
379  if (fileop /= 'FILEIN') then
380  call store_error('Unexpected packagedata input keyword read: "' &
381  //trim(fileop)//'".')
382  cycle
383  end if
384 
385  select case (flowtype)
386  case ('GWFBUDGET')
387  inunit = getunit()
388  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
389  access, 'OLD')
390  this%iubud = inunit
391  call this%initialize_bfr()
392  case ('GWFHEAD')
393  inunit = getunit()
394  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
395  access, 'OLD')
396  this%iuhds = inunit
397  call this%initialize_hfr()
398  case ('GWFMOVER')
399  inunit = getunit()
400  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
401  access, 'OLD')
402  this%iumvr = inunit
403  call budgetobject_cr_bfr(this%mvrbudobj, 'MVT', this%iumvr, &
404  this%iout)
405  call this%mvrbudobj%fill_from_bfr(this%dis, this%iout)
406  case ('GWFGRID')
407  inunit = getunit()
408  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', &
409  form, access, 'OLD')
410  this%iugrb = inunit
411  call this%read_grid()
412  case default
413  write (errmsg, '(a,3(1x,a))') &
414  'UNKNOWN', trim(adjustl(this%text)), 'PACKAGEDATA:', trim(flowtype)
415  call store_error(errmsg)
416  end select
417  end do
418 
419  write (this%iout, '(1x,a)') 'END OF FMI PACKAGEDATA'
420 
421  if (count_errors() > 0) then
422  call store_error_filename(this%input_fname)
423  end if
424 
425  call memorystore_release('FLOWTYPE', this%input_mempath)
426  call memorystore_release('FILEIN', this%input_mempath)
427  call memorystore_release('FNAME', this%input_mempath)
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
subroutine, public urdaux(naux, inunit, iout, lloc, istart, istop, auxname, line, text)
Read auxiliary variables from an input line.
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
Here is the call graph for this function: