MODFLOW 6  version 6.9.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 source_packagedata_other (this, flowtype, fname)
 Source a packagedata entry with a model-specific flow type. 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 605 of file FlowModelInterface.f90.

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

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

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

1041  ! -- modules
1042  use constantsmodule, only: lenmempath
1044  ! -- dummy
1045  class(FlowModelInterfaceType) :: this
1046  integer(I4B), intent(in) :: ngwfterms
1047  ! -- local
1048  integer(I4B) :: n
1049  character(len=LENMEMPATH) :: memPath
1050  !
1051  ! -- direct allocate
1052  allocate (this%gwfpackages(ngwfterms))
1053  allocate (this%flowpacknamearray(ngwfterms))
1054  !
1055  ! -- mem_allocate
1056  call mem_allocate(this%igwfmvrterm, ngwfterms, 'IGWFMVRTERM', this%memoryPath)
1057  !
1058  ! -- initialize
1059  this%nflowpack = ngwfterms
1060  do n = 1, this%nflowpack
1061  this%igwfmvrterm(n) = 0
1062  this%flowpacknamearray(n) = ''
1063  !
1064  ! -- Create a mempath for each individual flow package data set
1065  ! of the form, MODELNAME/FMI-FTn
1066  write (mempath, '(a, i0)') trim(this%memoryPath)//'-FT', n
1067  call this%gwfpackages(n)%initialize(mempath)
1068  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 207 of file FlowModelInterface.f90.

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

◆ deallocate_gwfpackages()

subroutine flowmodelinterfacemodule::deallocate_gwfpackages ( class(flowmodelinterfacetype)  this)

Definition at line 1072 of file FlowModelInterface.f90.

1073  class(FlowModelInterfaceType) :: this
1074  integer(I4B) :: n
1075 
1076  do n = 1, this%nflowpack
1077  call this%gwfpackages(n)%da()
1078  end do

◆ finalize_bfr()

subroutine flowmodelinterfacemodule::finalize_bfr ( class(flowmodelinterfacetype)  this)

Definition at line 762 of file FlowModelInterface.f90.

763  class(FlowModelInterfaceType) :: this
764  call this%bfr%finalize()

◆ finalize_hfr()

subroutine flowmodelinterfacemodule::finalize_hfr ( class(flowmodelinterfacetype)  this)

Definition at line 869 of file FlowModelInterface.f90.

870  class(FlowModelInterfaceType) :: this
871  close (this%iuhds)

◆ fmi_ar()

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

Definition at line 142 of file FlowModelInterface.f90.

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

◆ fmi_da()

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

Definition at line 157 of file FlowModelInterface.f90.

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

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

1083  use bndmodule, only: bndtype, getbndfromlist
1084  class(FlowModelInterfaceType) :: this
1085  character(len=*), intent(in) :: name
1086  integer(I4B), intent(inout) :: idx
1087  ! -- local
1088  integer(I4B) :: ip
1089  !
1090  ! -- Look through all the packages and return the index with name
1091  idx = 0
1092  do ip = 1, size(this%flowpacknamearray)
1093  if (this%flowpacknamearray(ip) == name) then
1094  idx = ip
1095  exit
1096  end if
1097  end do
1098  if (idx == 0) then
1099  call store_error('Error in get_package_index. Could not find '//name, &
1100  terminate=.true.)
1101  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 592 of file FlowModelInterface.f90.

593  class(FlowModelInterfaceType) :: this
594  integer(I4B) :: ncrbud
595  call this%bfr%initialize(this%iubud, this%iout, ncrbud)
596  ! todo: need to run through the budget terms
597  ! 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 879 of file FlowModelInterface.f90.

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

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

◆ initialize_hfr()

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

Definition at line 768 of file FlowModelInterface.f90.

769  class(FlowModelInterfaceType) :: this
770  call this%hfr%initialize(this%iuhds, this%iout)
771  ! todo: need to run through the head terms
772  ! and do some checking

◆ read_grid()

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

Definition at line 444 of file FlowModelInterface.f90.

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

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

◆ source_packagedata()

subroutine flowmodelinterfacemodule::source_packagedata ( class(flowmodelinterfacetype)  this)

Definition at line 344 of file FlowModelInterface.f90.

345  ! -- modules
349  use openspecmodule, only: access, form
352  ! -- dummy
353  class(FlowModelInterfaceType) :: this
354  ! -- local
355  type(CharacterStringType), dimension(:), contiguous, &
356  pointer :: flowtypes
357  type(CharacterStringType), dimension(:), contiguous, &
358  pointer :: fileops
359  type(CharacterStringType), dimension(:), contiguous, &
360  pointer :: fnames
361  character(len=LINELENGTH) :: flowtype, fileop, fname
362  integer(I4B) :: inunit, n
363  logical(LGP) :: exist
364 
365  call mem_setptr(flowtypes, 'FLOWTYPE', this%input_mempath)
366  call mem_setptr(fileops, 'FILEIN', this%input_mempath)
367  call mem_setptr(fnames, 'FNAME', this%input_mempath)
368 
369  write (this%iout, '(1x,a)') 'PROCESSING FMI PACKAGEDATA'
370 
371  do n = 1, size(flowtypes)
372  flowtype = flowtypes(n)
373  fileop = fileops(n)
374  fname = fnames(n)
375 
376  inquire (file=trim(fname), exist=exist)
377  if (.not. exist) then
378  call store_error('Could not find file '//trim(fname))
379  cycle
380  end if
381 
382  if (fileop /= 'FILEIN') then
383  call store_error('Unexpected packagedata input keyword read: "' &
384  //trim(fileop)//'".')
385  cycle
386  end if
387 
388  select case (flowtype)
389  case ('GWFBUDGET')
390  inunit = getunit()
391  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
392  access, 'OLD')
393  this%iubud = inunit
394  call this%initialize_bfr()
395  case ('GWFHEAD')
396  inunit = getunit()
397  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
398  access, 'OLD')
399  this%iuhds = inunit
400  call this%initialize_hfr()
401  case ('GWFMOVER')
402  inunit = getunit()
403  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
404  access, 'OLD')
405  this%iumvr = inunit
406  call budgetobject_cr_bfr(this%mvrbudobj, 'MVT', this%iumvr, &
407  this%iout)
408  call this%mvrbudobj%fill_from_bfr(this%dis, this%iout)
409  case ('GWFGRID')
410  inunit = getunit()
411  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', &
412  form, access, 'OLD')
413  this%iugrb = inunit
414  call this%read_grid()
415  case default
416  call this%source_packagedata_other(flowtype, fname)
417  end select
418  end do
419 
420  write (this%iout, '(1x,a)') 'END OF FMI PACKAGEDATA'
421 
422  if (count_errors() > 0) then
423  call store_error_filename(this%input_fname)
424  end if
425 
426  call memorystore_release('FLOWTYPE', this%input_mempath)
427  call memorystore_release('FILEIN', this%input_mempath)
428  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:

◆ source_packagedata_other()

subroutine flowmodelinterfacemodule::source_packagedata_other ( class(flowmodelinterfacetype)  this,
character(len=*), intent(in)  flowtype,
character(len=*), intent(in)  fname 
)
Parameters
[in]flowtypepackagedata flow type
[in]fnamepackagedata file name

Definition at line 432 of file FlowModelInterface.f90.

433  class(FlowModelInterfaceType) :: this
434  character(len=*), intent(in) :: flowtype !< packagedata flow type
435  character(len=*), intent(in) :: fname !< packagedata file name
436 
437  write (errmsg, '(a,3(1x,a))') &
438  'UNKNOWN', trim(adjustl(this%text)), 'PACKAGEDATA:', trim(flowtype)
439  call store_error(errmsg)
Here is the call graph for this function: