MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
tsp-fmi.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b, lgp
7  use simvariablesmodule, only: errmsg
9  use basedismodule, only: disbasetype
10  use listmodule, only: listtype
16 
17  implicit none
18  private
19  public :: tspfmitype
20  public :: fmi_cr
21 
22  character(len=LENPACKAGENAME) :: text = ' GWTFMI'
23 
24  integer(I4B), parameter :: nbditems = 2
25  character(len=LENBUDTXT), dimension(NBDITEMS) :: budtxt
26  data budtxt/' FLOW-ERROR', ' FLOW-CORRECTION'/
27 
29  real(dp), dimension(:), contiguous, pointer :: concpack => null()
30  real(dp), dimension(:), contiguous, pointer :: qmfrommvr => null()
31  end type
32 
34  type(budgetobjecttype), pointer :: ptr
35  end type budobjptrarray
36 
38 
39  integer(I4B), dimension(:), pointer, contiguous :: iatp => null() !< advanced transport package applied to gwfpackages
40  integer(I4B), pointer :: iflowerr => null() !< add the flow error correction
41  real(dp), dimension(:), pointer, contiguous :: flowcorrect => null() !< mass flow correction
42  real(dp), pointer :: eqnsclfac => null() !< governing equation scale factor; =1. for solute; =rhow*cpw for energy
44  dimension(:), pointer, contiguous :: datp => null()
45  type(budobjptrarray), dimension(:), allocatable :: aptbudobj !< flow budget objects for the advanced packages
46 
47  contains
48 
49  procedure :: allocate_arrays => gwtfmi_allocate_arrays
50  procedure :: allocate_gwfpackages => gwtfmi_allocate_gwfpackages
51  procedure :: allocate_scalars => gwtfmi_allocate_scalars
52  procedure :: fmi_rp
53  procedure :: fmi_ad
54  procedure :: fmi_fc
55  procedure :: fmi_cq
56  procedure :: fmi_bd
57  procedure :: fmi_ot_flow
58  procedure :: fmi_da => gwtfmi_da
59  procedure :: gwfsatold
62  procedure :: source_options => gwtfmi_source_options
63  procedure :: set_aptbudobj_pointer
64  procedure :: source_packagedata_other => gwtfmi_source_packagedata_other
65  procedure :: set_active_status
66 
67  end type tspfmitype
68 
69 contains
70 
71  !> @brief Create a new FMI object
72  !<
73  subroutine fmi_cr(fmiobj, name_model, input_mempath, inunit, iout, eqnsclfac, &
74  depvartype)
75  ! -- dummy
76  type(tspfmitype), pointer :: fmiobj
77  character(len=*), intent(in) :: name_model
78  character(len=*), intent(in) :: input_mempath
79  integer(I4B), intent(in) :: inunit
80  integer(I4B), intent(in) :: iout
81  real(dp), intent(in), pointer :: eqnsclfac !< governing equation scale factor
82  character(len=LENVARNAME), intent(in) :: depvartype
83  !
84  ! -- Create the object
85  allocate (fmiobj)
86  !
87  ! -- create name and memory path
88  call fmiobj%set_names(1, name_model, 'FMI', 'FMI', input_mempath)
89  fmiobj%text = text
90  !
91  ! -- Allocate scalars
92  call fmiobj%allocate_scalars()
93  !
94  ! -- Set variables
95  fmiobj%inunit = inunit
96  fmiobj%iout = iout
97  !
98  ! -- Assign label based on dependent variable
99  fmiobj%depvartype = depvartype
100  !
101  ! -- Store pointer to governing equation scale factor
102  fmiobj%eqnsclfac => eqnsclfac
103  end subroutine fmi_cr
104 
105  !> @brief Read and prepare
106  !<
107  subroutine fmi_rp(this, inmvr)
108  ! -- modules
109  use tdismodule, only: kper, kstp
110  ! -- dummy
111  class(tspfmitype) :: this
112  integer(I4B), intent(in) :: inmvr
113  ! -- local
114  ! -- formats
115  !
116  ! --Check to make sure MVT Package is active if mvr flows are available.
117  ! This cannot be checked until RP because exchange doesn't set a pointer
118  ! to mvrbudobj until exg_ar().
119  if (kper * kstp == 1) then
120  if (associated(this%mvrbudobj) .and. inmvr == 0) then
121  write (errmsg, '(a)') 'GWF water mover is active but the GWT MVT &
122  &package has not been specified. activate GWT MVT package.'
123  call store_error(errmsg, terminate=.true.)
124  end if
125  if (.not. associated(this%mvrbudobj) .and. inmvr > 0) then
126  write (errmsg, '(a)') 'GWF water mover terms are not available &
127  &but the GWT MVT package has been activated. Activate GWF-GWT &
128  &exchange or specify GWFMOVER in FMI PACKAGEDATA.'
129  call store_error(errmsg, terminate=.true.)
130  end if
131  end if
132  end subroutine fmi_rp
133 
134  !> @brief Advance routine for FMI object
135  !<
136  subroutine fmi_ad(this, cnew)
137  ! -- modules
138  use constantsmodule, only: dhdry
139  ! -- dummy
140  class(tspfmitype) :: this
141  real(DP), intent(inout), dimension(:) :: cnew
142  ! -- local
143  integer(I4B) :: n
144  character(len=*), parameter :: fmtdry = &
145  &"(/1X,'WARNING: DRY CELL ENCOUNTERED AT ',a,'; RESET AS INACTIVE &
146  &WITH DRY CONCENTRATION = ', G13.5)"
147  character(len=*), parameter :: fmtrewet = &
148  &"(/1X,'DRY CELL REACTIVATED AT ', a,&
149  &' WITH STARTING CONCENTRATION =',G13.5)"
150  !
151  ! -- Set flag to indicated that flows are being updated. For the case where
152  ! flows may be reused (only when flows are read from a file) then set
153  ! the flag to zero to indicate that flows were not updated
154  this%iflowsupdated = 1
155  !
156  ! -- If reading flows from a budget file, read the next set of records
157  if (this%iubud /= 0) then
158  call this%advance_bfr()
159  end if
160  !
161  ! -- If reading heads from a head file, read the next set of records
162  if (this%iuhds /= 0) then
163  call this%advance_hfr()
164  end if
165  !
166  ! -- If mover flows are being read from file, read the next set of records
167  if (this%iumvr /= 0) then
168  call this%mvrbudobj%bfr_advance(this%dis, this%iout)
169  end if
170  !
171  ! -- If advanced package flows are being read from file, read the next set of records
172  if (this%flows_from_file .and. this%inunit /= 0) then
173  do n = 1, size(this%aptbudobj)
174  call this%aptbudobj(n)%ptr%bfr_advance(this%dis, this%iout)
175  end do
176  end if
177  !
178  ! -- set inactive transport cell status
179  if (this%idryinactive /= 0) then
180  call this%set_active_status(cnew)
181  end if
182  end subroutine fmi_ad
183 
184  !> @brief Calculate coefficients and fill matrix and rhs terms associated
185  !! with FMI object
186  !<
187  subroutine fmi_fc(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
188  ! -- dummy
189  class(tspfmitype) :: this
190  integer, intent(in) :: nodes
191  real(DP), intent(in), dimension(nodes) :: cold
192  integer(I4B), intent(in) :: nja
193  class(matrixbasetype), pointer :: matrix_sln
194  integer(I4B), intent(in), dimension(nja) :: idxglo
195  real(DP), intent(inout), dimension(nodes) :: rhs
196  ! -- local
197  integer(I4B) :: n, idiag, idiag_sln
198  real(DP) :: qcorr
199  !
200  ! -- Calculate the flow imbalance error and make a correction for it
201  if (this%iflowerr /= 0) then
202  !
203  ! -- Correct the transport solution for the flow imbalance by adding
204  ! the flow residual to the diagonal
205  do n = 1, nodes
206  idiag = this%dis%con%ia(n)
207  idiag_sln = idxglo(idiag)
208  !call matrix_sln%add_value_pos(idiag_sln, -this%gwfflowja(idiag))
209  qcorr = -this%gwfflowja(idiag) * this%eqnsclfac
210  call matrix_sln%add_value_pos(idiag_sln, qcorr)
211  end do
212  end if
213  end subroutine fmi_fc
214 
215  !> @brief Calculate flow correction
216  !!
217  !! Where there is a flow imbalance for a given cell, a correction may be
218  !! applied if selected
219  !<
220  subroutine fmi_cq(this, cnew, flowja)
221  ! -- modules
222  ! -- dummy
223  class(tspfmitype) :: this
224  real(DP), intent(in), dimension(:) :: cnew
225  real(DP), dimension(:), contiguous, intent(inout) :: flowja
226  ! -- local
227  integer(I4B) :: n
228  integer(I4B) :: idiag
229  real(DP) :: rate
230  !
231  ! -- If not adding flow error correction, return
232  if (this%iflowerr /= 0) then
233  !
234  ! -- Accumulate the flow correction term
235  do n = 1, this%dis%nodes
236  rate = dzero
237  idiag = this%dis%con%ia(n)
238  if (this%ibound(n) > 0) then
239  rate = -this%gwfflowja(idiag) * cnew(n) * this%eqnsclfac
240  end if
241  this%flowcorrect(n) = rate
242  flowja(idiag) = flowja(idiag) + rate
243  end do
244  end if
245  end subroutine fmi_cq
246 
247  !> @brief Calculate budget terms associated with FMI object
248  !<
249  subroutine fmi_bd(this, isuppress_output, model_budget)
250  ! -- modules
251  use tdismodule, only: delt
253  ! -- dummy
254  class(tspfmitype) :: this
255  integer(I4B), intent(in) :: isuppress_output
256  type(budgettype), intent(inout) :: model_budget
257  ! -- local
258  real(DP) :: rin
259  real(DP) :: rout
260  !
261  ! -- flow correction
262  if (this%iflowerr /= 0) then
263  call rate_accumulator(this%flowcorrect, rin, rout)
264  call model_budget%addentry(rin, rout, delt, budtxt(2), isuppress_output)
265  end if
266  end subroutine fmi_bd
267 
268  !> @brief Save budget terms associated with FMI object
269  !<
270  subroutine fmi_ot_flow(this, icbcfl, icbcun)
271  ! -- dummy
272  class(tspfmitype) :: this
273  integer(I4B), intent(in) :: icbcfl
274  integer(I4B), intent(in) :: icbcun
275  ! -- local
276  integer(I4B) :: ibinun
277  integer(I4B) :: iprint, nvaluesp, nwidthp
278  character(len=1) :: cdatafmp = ' ', editdesc = ' '
279  real(DP) :: dinact
280  !
281  ! -- Set unit number for binary output
282  if (this%ipakcb < 0) then
283  ibinun = icbcun
284  elseif (this%ipakcb == 0) then
285  ibinun = 0
286  else
287  ibinun = this%ipakcb
288  end if
289  if (icbcfl == 0) ibinun = 0
290  !
291  ! -- Do not save flow corrections if not active
292  if (this%iflowerr == 0) ibinun = 0
293  !
294  ! -- Record the storage rates if requested
295  if (ibinun /= 0) then
296  iprint = 0
297  dinact = dzero
298  !
299  ! -- flow correction
300  call this%dis%record_array(this%flowcorrect, this%iout, iprint, -ibinun, &
301  budtxt(2), cdatafmp, nvaluesp, &
302  nwidthp, editdesc, dinact)
303  end if
304  end subroutine fmi_ot_flow
305 
306  !> @brief Deallocate variables
307  !!
308  !! Deallocate memory associated with FMI object
309  !<
310  subroutine gwtfmi_da(this)
311  ! -- modules
313  ! -- dummy
314  class(tspfmitype) :: this
315  !
316  ! -- deallocate transport-specific arrays
317  if (associated(this%datp)) then
318  deallocate (this%datp)
319  call mem_deallocate(this%iatp)
320  end if
321  deallocate (this%aptbudobj)
322  call mem_deallocate(this%flowcorrect)
323  !
324  ! -- deallocate transport-specific scalars
325  call mem_deallocate(this%iflowerr)
326  !
327  ! -- deallocate parent
328  call this%FlowModelInterfaceType%fmi_da()
329  end subroutine gwtfmi_da
330 
331  !> @ brief Allocate scalars
332  !!
333  !! Allocate scalar variables for an FMI object
334  !<
335  subroutine gwtfmi_allocate_scalars(this)
336  ! -- modules
338  ! -- dummy
339  class(tspfmitype) :: this
340  ! -- local
341  !
342  ! -- allocate scalars in parent
343  call this%FlowModelInterfaceType%allocate_scalars()
344  !
345  ! -- Allocate
346  call mem_allocate(this%iflowerr, 'IFLOWERR', this%memoryPath)
347  !
348  ! -- Although not a scalar, allocate the advanced package transport
349  ! budget object to zero so that it can be dynamically resized later
350  allocate (this%aptbudobj(0))
351  !
352  ! -- Initialize
353  this%iflowerr = 0
354  end subroutine gwtfmi_allocate_scalars
355 
356  !> @ brief Allocate arrays for FMI object
357  !!
358  !! Method to allocate arrays for the FMI package.
359  !<
360  subroutine gwtfmi_allocate_arrays(this, nodes)
362  ! -- modules
363  use constantsmodule, only: dzero
364  ! -- dummy
365  class(tspfmitype) :: this
366  integer(I4B), intent(in) :: nodes
367  ! -- local
368  integer(I4B) :: n
369  !
370  ! -- allocate parent arrays
371  call this%FlowModelInterfaceType%allocate_arrays(nodes)
372  !
373  ! -- Allocate variables needed for all cases
374  if (this%iflowerr == 0) then
375  call mem_allocate(this%flowcorrect, 1, 'FLOWCORRECT', this%memoryPath)
376  else
377  call mem_allocate(this%flowcorrect, nodes, 'FLOWCORRECT', this%memoryPath)
378  end if
379  do n = 1, size(this%flowcorrect)
380  this%flowcorrect(n) = dzero
381  end do
382  end subroutine gwtfmi_allocate_arrays
383 
384  !> @brief Set gwt transport cell status
385  !!
386  !! Dry GWF cells are treated differently by GWT and GWE. Transport does not
387  !! occur in deactivated GWF cells; however, GWE still simulates conduction
388  !! through dry cells.
389  !<
390  subroutine set_active_status(this, cnew)
391  ! -- modules
392  use constantsmodule, only: dhdry
393  ! -- dummy
394  class(tspfmitype) :: this
395  real(DP), intent(inout), dimension(:) :: cnew
396  ! -- local
397  integer(I4B) :: n
398  integer(I4B) :: m
399  integer(I4B) :: ipos
400  real(DP) :: crewet, tflow, flownm
401  character(len=15) :: nodestr
402  ! -- formats
403  character(len=*), parameter :: fmtoutmsg1 = &
404  "(1x,'WARNING: DRY CELL ENCOUNTERED AT ', a,'; RESET AS INACTIVE WITH &
405  &DRY ', a, '=', G13.5)"
406  character(len=*), parameter :: fmtoutmsg2 = &
407  &"(1x,'DRY CELL REACTIVATED AT', a, 'WITH STARTING', a, '=', G13.5)"
408  !
409  do n = 1, this%dis%nodes
410  ! -- Calculate the ibound-like array that has 0 if saturation
411  ! is zero and 1 otherwise
412  if (this%gwfsat(n) > dzero) then
413  this%ibdgwfsat0(n) = 1
414  else
415  this%ibdgwfsat0(n) = 0
416  end if
417  !
418  ! -- Check if active transport cell is inactive for flow
419  if (this%ibound(n) > 0) then
420  if (this%gwfhead(n) == dhdry) then
421  ! -- transport cell should be made inactive
422  this%ibound(n) = 0
423  cnew(n) = dhdry
424  call this%dis%noder_to_string(n, nodestr)
425  write (this%iout, fmtoutmsg1) &
426  trim(nodestr), trim(adjustl(this%depvartype)), dhdry
427  end if
428  end if
429  end do
430  !
431  ! -- if flow cell is dry, then set gwt%ibound = 0 and conc to dry
432  do n = 1, this%dis%nodes
433  !
434  ! -- Convert dry transport cell to active if flow has rewet
435  if (cnew(n) == dhdry) then
436  if (this%gwfhead(n) /= dhdry) then
437  !
438  ! -- obtain weighted concentration/temperature
439  crewet = dzero
440  tflow = dzero
441  do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
442  m = this%dis%con%ja(ipos)
443  flownm = this%gwfflowja(ipos)
444  if (flownm > 0) then
445  if (this%ibound(m) /= 0) then
446  crewet = crewet + cnew(m) * flownm ! kluge note: apparently no need to multiply flows by eqnsclfac
447  tflow = tflow + this%gwfflowja(ipos) ! since it will divide out below anyway
448  end if
449  end if
450  end do
451  if (tflow > dzero) then
452  crewet = crewet / tflow
453  else
454  crewet = dzero
455  end if
456  !
457  ! -- cell is now wet
458  this%ibound(n) = 1
459  cnew(n) = crewet
460  call this%dis%noder_to_string(n, nodestr)
461  write (this%iout, fmtoutmsg2) &
462  trim(nodestr), trim(adjustl(this%depvartype)), crewet
463  end if
464  end if
465  end do
466  end subroutine set_active_status
467 
468  !> @brief Calculate the previous saturation level
469  !!
470  !! Calculate the groundwater cell head saturation for the end of
471  !! the last time step
472  !<
473  function gwfsatold(this, n, delt) result(satold)
474  ! -- modules
475  ! -- dummy
476  class(tspfmitype) :: this
477  integer(I4B), intent(in) :: n
478  real(dp), intent(in) :: delt
479  ! -- result
480  real(dp) :: satold
481  ! -- local
482  real(dp) :: vcell
483  real(dp) :: vnew
484  real(dp) :: vold
485  !
486  ! -- calculate the value
487  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
488  vnew = vcell * this%gwfsat(n)
489  vold = vnew
490  if (this%igwfstrgss /= 0) vold = vold + this%gwfstrgss(n) * delt
491  if (this%igwfstrgsy /= 0) vold = vold + this%gwfstrgsy(n) * delt
492  satold = vold / vcell
493  end function gwfsatold
494 
495  !> @ brief Source input options for package
496  !<
497  subroutine gwtfmi_source_options(this)
498  ! -- modules
500  ! -- dummy
501  class(tspfmitype) :: this
502  ! -- local
503  logical(LGP) :: found_ipakcb, found_flowerr
504  character(len=*), parameter :: fmtisvflow = &
505  "(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY FILE &
506  &WHENEVER ICBCFL IS NOT ZERO AND FLOW IMBALANCE CORRECTION ACTIVE.')"
507  character(len=*), parameter :: fmtifc = &
508  &"(4x,'MASS WILL BE ADDED OR REMOVED TO COMPENSATE FOR FLOW IMBALANCE.')"
509 
510  write (this%iout, '(1x,a)') 'PROCESSING FMI OPTIONS'
511 
512  call mem_set_value(this%ipakcb, 'SAVE_FLOWS', this%input_mempath, &
513  found_ipakcb)
514  call mem_set_value(this%iflowerr, 'IMBALANCECORRECT', this%input_mempath, &
515  found_flowerr)
516 
517  if (found_ipakcb) then
518  this%ipakcb = -1
519  write (this%iout, fmtisvflow)
520  end if
521  if (found_flowerr) write (this%iout, fmtifc)
522 
523  write (this%iout, '(1x,a)') 'END OF FMI OPTIONS'
524  end subroutine gwtfmi_source_options
525 
526  !> @brief Source a packagedata entry with a model-specific flow type
527  !!
528  !! Any flow type not handled by the base FMI is taken to be the name
529  !! of an advanced GWF package (e.g. LAK-1, SFR-1), and the file is
530  !! read as that package's budget file.
531  !<
532  subroutine gwtfmi_source_packagedata_other(this, flowtype, fname)
533  ! -- modules
534  use openspecmodule, only: access, form
536  ! -- dummy
537  class(tspfmitype) :: this
538  character(len=*), intent(in) :: flowtype !< advanced package name
539  character(len=*), intent(in) :: fname !< advanced package budget file
540  ! -- local
541  type(budgetobjecttype), pointer :: budobjptr
542  type(budobjptrarray), dimension(:), allocatable :: tmpbudobj
543  integer(I4B) :: iapt, inunit, i
544 
545  ! -- expand the size of aptbudobj, which stores a pointer to the budobj
546  iapt = size(this%aptbudobj)
547  allocate (tmpbudobj(iapt))
548  do i = 1, iapt
549  tmpbudobj(i)%ptr => this%aptbudobj(i)%ptr
550  end do
551  deallocate (this%aptbudobj)
552  allocate (this%aptbudobj(iapt + 1))
553  do i = 1, iapt
554  this%aptbudobj(i)%ptr => tmpbudobj(i)%ptr
555  end do
556  deallocate (tmpbudobj)
557 
558  ! -- open the budget file and start filling it
559  iapt = iapt + 1
560  inunit = getunit()
561  call openfile(inunit, this%iout, fname, 'DATA(BINARY)', form, &
562  access, 'OLD')
563  call budgetobject_cr_bfr(budobjptr, flowtype, inunit, &
564  this%iout, colconv2=['GWF '])
565  call budobjptr%fill_from_bfr(this%dis, this%iout)
566  this%aptbudobj(iapt)%ptr => budobjptr
567  end subroutine gwtfmi_source_packagedata_other
568 
569  !> @brief Set the pointer to a budget object
570  !!
571  !! An advanced transport can pass in a name and a
572  !! pointer budget object, and this routine will look through the budget
573  !! objects managed by FMI and point to the one with the same name, such as
574  !! LAK-1, SFR-1, etc.
575  !<
576  subroutine set_aptbudobj_pointer(this, name, budobjptr)
577  ! -- modules
578  class(tspfmitype) :: this
579  ! -- dumm
580  character(len=*), intent(in) :: name
581  type(budgetobjecttype), pointer :: budobjptr
582  ! -- local
583  integer(I4B) :: i
584  !
585  ! -- find and set the pointer
586  do i = 1, size(this%aptbudobj)
587  if (this%aptbudobj(i)%ptr%name == name) then
588  budobjptr => this%aptbudobj(i)%ptr
589  exit
590  end if
591  end do
592  end subroutine set_aptbudobj_pointer
593 
594  !> @brief Initialize the groundwater flow terms based on the budget file
595  !! reader
596  !!
597  !! Initialize terms and figure out how many different terms and packages
598  !! are contained within the file
599  !<
601  ! -- modules
603  ! -- dummy
604  class(tspfmitype) :: this
605  ! -- local
606  integer(I4B) :: nflowpack
607  integer(I4B) :: i, ip
608  integer(I4B) :: naux
609  logical :: found_flowja
610  logical :: found_dataspdis
611  logical :: found_datasat
612  logical :: found_stoss
613  logical :: found_stosy
614  integer(I4B), dimension(:), allocatable :: imap
615  !
616  ! -- Calculate the number of gwf flow packages
617  allocate (imap(this%bfr%nbudterms))
618  imap(:) = 0
619  nflowpack = 0
620  found_flowja = .false.
621  found_dataspdis = .false.
622  found_datasat = .false.
623  found_stoss = .false.
624  found_stosy = .false.
625  do i = 1, this%bfr%nbudterms
626  select case (trim(adjustl(this%bfr%budtxtarray(i))))
627  case ('FLOW-JA-FACE')
628  found_flowja = .true.
629  case ('DATA-SPDIS')
630  found_dataspdis = .true.
631  case ('DATA-SAT')
632  found_datasat = .true.
633  case ('STO-SS')
634  found_stoss = .true.
635  this%igwfstrgss = 1
636  case ('STO-SY')
637  found_stosy = .true.
638  this%igwfstrgsy = 1
639  case default
640  nflowpack = nflowpack + 1
641  imap(i) = 1
642  end select
643  end do
644  !
645  ! -- allocate gwfpackage arrays (gwfpackages, iatp, datp, ...)
646  call this%allocate_gwfpackages(nflowpack)
647  !
648  ! -- Copy the package name and aux names from budget file reader
649  ! to the gwfpackages derived-type variable
650  ip = 1
651  do i = 1, this%bfr%nbudterms
652  if (imap(i) == 0) cycle
653  call this%gwfpackages(ip)%set_name(this%bfr%dstpackagenamearray(i), &
654  this%bfr%budtxtarray(i))
655  naux = this%bfr%nauxarray(i)
656  call this%gwfpackages(ip)%set_auxname(naux, &
657  this%bfr%auxtxtarray(1:naux, i))
658  ip = ip + 1
659  end do
660  !
661  ! -- Copy just the package names for the boundary packages into
662  ! the flowpacknamearray
663  ip = 1
664  do i = 1, size(imap)
665  if (imap(i) == 1) then
666  this%flowpacknamearray(ip) = this%bfr%dstpackagenamearray(i)
667  ip = ip + 1
668  end if
669  end do
670  !
671  ! -- Error if specific discharge, saturation or flowja not found
672  if (.not. found_dataspdis) then
673  write (errmsg, '(a)') 'Specific discharge not found in &
674  &budget file. SAVE_SPECIFIC_DISCHARGE and &
675  &SAVE_FLOWS must be activated in the NPF package.'
676  call store_error(errmsg)
677  end if
678  if (.not. found_datasat) then
679  write (errmsg, '(a)') 'Saturation not found in &
680  &budget file. SAVE_SATURATION and &
681  &SAVE_FLOWS must be activated in the NPF package.'
682  call store_error(errmsg)
683  end if
684  if (.not. found_flowja) then
685  write (errmsg, '(a)') 'FLOWJA not found in &
686  &budget file. SAVE_FLOWS must &
687  &be activated in the NPF package.'
688  call store_error(errmsg)
689  end if
690  if (count_errors() > 0) then
691  call store_error_filename(this%input_fname)
692  end if
693  end subroutine initialize_gwfterms_from_bfr
694 
695  !> @brief Initialize groundwater flow terms from the groundwater budget
696  !!
697  !! Flows are coming from a gwf-gwt exchange object
698  !<
700  ! -- modules
701  use bndmodule, only: bndtype, getbndfromlist
702  ! -- dummy
703  class(tspfmitype) :: this
704  ! -- local
705  integer(I4B) :: ngwfpack
706  integer(I4B) :: ngwfterms
707  integer(I4B) :: ip
708  integer(I4B) :: imover
709  integer(I4B) :: ntomvr
710  integer(I4B) :: iterm
711  character(len=LENPACKAGENAME) :: budtxt
712  class(bndtype), pointer :: packobj => null()
713  !
714  ! -- determine size of gwf terms
715  ngwfpack = this%gwfbndlist%Count()
716  !
717  ! -- Count number of to-mvr terms, but do not include advanced packages
718  ! as those mover terms are not losses from the cell, but rather flows
719  ! within the advanced package
720  ntomvr = 0
721  do ip = 1, ngwfpack
722  packobj => getbndfromlist(this%gwfbndlist, ip)
723  imover = packobj%imover
724  if (packobj%isadvpak /= 0) imover = 0
725  if (imover /= 0) then
726  ntomvr = ntomvr + 1
727  end if
728  end do
729  !
730  ! -- Allocate arrays in fmi of size ngwfterms, which is the number of
731  ! packages plus the number of packages with mover terms.
732  ngwfterms = ngwfpack + ntomvr
733  call this%allocate_gwfpackages(ngwfterms)
734  !
735  ! -- Assign values in the fmi package
736  iterm = 1
737  do ip = 1, ngwfpack
738  !
739  ! -- set and store names
740  packobj => getbndfromlist(this%gwfbndlist, ip)
741  budtxt = adjustl(packobj%text)
742  call this%gwfpackages(iterm)%set_name(packobj%packName, budtxt)
743  this%flowpacknamearray(iterm) = packobj%packName
744  call this%gwfpackages(iterm)%set_auxname(packobj%naux, &
745  packobj%auxname)
746  iterm = iterm + 1
747  !
748  ! -- if this package has a mover associated with it, then add another
749  ! term that corresponds to the mover flows
750  imover = packobj%imover
751  if (packobj%isadvpak /= 0) imover = 0
752  if (imover /= 0) then
753  budtxt = trim(adjustl(packobj%text))//'-TO-MVR'
754  call this%gwfpackages(iterm)%set_name(packobj%packName, budtxt)
755  this%flowpacknamearray(iterm) = packobj%packName
756  call this%gwfpackages(iterm)%set_auxname(packobj%naux, &
757  packobj%auxname)
758  this%igwfmvrterm(iterm) = 1
759  iterm = iterm + 1
760  end if
761  end do
763 
764  !> @brief Initialize an array for storing PackageBudget objects.
765  !!
766  !! This routine allocates gwfpackages (an array of PackageBudget
767  !! objects) to the proper size and initializes member variables.
768  !<
769  subroutine gwtfmi_allocate_gwfpackages(this, ngwfterms)
770  ! -- modules
771  use constantsmodule, only: lenmempath
773  ! -- dummy
774  class(tspfmitype) :: this
775  integer(I4B), intent(in) :: ngwfterms
776  ! -- local
777  integer(I4B) :: n
778  character(len=LENMEMPATH) :: memPath
779  !
780  ! -- direct allocate
781  allocate (this%gwfpackages(ngwfterms))
782  allocate (this%flowpacknamearray(ngwfterms))
783  allocate (this%datp(ngwfterms))
784  !
785  ! -- mem_allocate
786  call mem_allocate(this%iatp, ngwfterms, 'IATP', this%memoryPath)
787  call mem_allocate(this%igwfmvrterm, ngwfterms, 'IGWFMVRTERM', this%memoryPath)
788  !
789  ! -- initialize
790  this%nflowpack = ngwfterms
791  do n = 1, this%nflowpack
792  this%iatp(n) = 0
793  this%igwfmvrterm(n) = 0
794  this%flowpacknamearray(n) = ''
795  !
796  ! -- Create a mempath for each individual flow package data set
797  ! of the form, MODELNAME/FMI-FTn
798  write (mempath, '(a, i0)') trim(this%memoryPath)//'-FT', n
799  call this%gwfpackages(n)%initialize(mempath)
800  end do
801  end subroutine gwtfmi_allocate_gwfpackages
802 
803 end module tspfmimodule
This module contains the base boundary package.
class(bndtype) function, pointer, public getbndfromlist(list, idx)
Get boundary from package list.
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
Definition: Budget.f90:634
subroutine, public budgetobject_cr_bfr(this, name, ibinun, iout, colconv1, colconv2)
Create a new budget object from a binary flow file.
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
real(dp), parameter dhdry
real dry cell constant
Definition: Constants.f90:94
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
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
This module defines variable data types.
Definition: kind.f90:8
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This module contains the PackageBudgetModule Module.
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:204
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
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
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:32
real(dp) function gwfsatold(this, n, delt)
Calculate the previous saturation level.
Definition: tsp-fmi.f90:474
integer(i4b), parameter nbditems
Definition: tsp-fmi.f90:24
subroutine fmi_bd(this, isuppress_output, model_budget)
Calculate budget terms associated with FMI object.
Definition: tsp-fmi.f90:250
character(len=lenbudtxt), dimension(nbditems) budtxt
Definition: tsp-fmi.f90:25
subroutine gwtfmi_allocate_scalars(this)
@ brief Allocate scalars
Definition: tsp-fmi.f90:336
subroutine gwtfmi_allocate_arrays(this, nodes)
@ brief Allocate arrays for FMI object
Definition: tsp-fmi.f90:361
subroutine, public fmi_cr(fmiobj, name_model, input_mempath, inunit, iout, eqnsclfac, depvartype)
Create a new FMI object.
Definition: tsp-fmi.f90:75
subroutine gwtfmi_source_options(this)
@ brief Source input options for package
Definition: tsp-fmi.f90:498
subroutine initialize_gwfterms_from_gwfbndlist(this)
Initialize groundwater flow terms from the groundwater budget.
Definition: tsp-fmi.f90:700
subroutine gwtfmi_allocate_gwfpackages(this, ngwfterms)
Initialize an array for storing PackageBudget objects.
Definition: tsp-fmi.f90:770
subroutine fmi_fc(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
Calculate coefficients and fill matrix and rhs terms associated with FMI object.
Definition: tsp-fmi.f90:188
subroutine initialize_gwfterms_from_bfr(this)
Initialize the groundwater flow terms based on the budget file reader.
Definition: tsp-fmi.f90:601
subroutine fmi_rp(this, inmvr)
Read and prepare.
Definition: tsp-fmi.f90:108
subroutine set_aptbudobj_pointer(this, name, budobjptr)
Set the pointer to a budget object.
Definition: tsp-fmi.f90:577
subroutine set_active_status(this, cnew)
Set gwt transport cell status.
Definition: tsp-fmi.f90:391
subroutine fmi_ot_flow(this, icbcfl, icbcun)
Save budget terms associated with FMI object.
Definition: tsp-fmi.f90:271
character(len=lenpackagename) text
Definition: tsp-fmi.f90:22
subroutine fmi_ad(this, cnew)
Advance routine for FMI object.
Definition: tsp-fmi.f90:137
subroutine fmi_cq(this, cnew, flowja)
Calculate flow correction.
Definition: tsp-fmi.f90:221
subroutine gwtfmi_da(this)
Deallocate variables.
Definition: tsp-fmi.f90:311
subroutine gwtfmi_source_packagedata_other(this, flowtype, fname)
Source a packagedata entry with a model-specific flow type.
Definition: tsp-fmi.f90:533
@ brief BndType
Derived type for the Budget object.
Definition: Budget.f90:40
A generic heterogeneous doubly-linked list.
Definition: List.f90:14
Derived type for storing flows.