22 character(len=LENPACKAGENAME) ::
text =
' GWTFMI'
25 character(len=LENBUDTXT),
dimension(NBDITEMS) ::
budtxt
26 data budtxt/
' FLOW-ERROR',
' FLOW-CORRECTION'/
29 real(dp),
dimension(:),
contiguous,
pointer :: concpack => null()
30 real(dp),
dimension(:),
contiguous,
pointer :: qmfrommvr => null()
39 integer(I4B),
dimension(:),
pointer,
contiguous :: iatp => null()
40 integer(I4B),
pointer :: iflowerr => null()
41 real(dp),
dimension(:),
pointer,
contiguous :: flowcorrect => null()
42 real(dp),
pointer :: eqnsclfac => null()
44 dimension(:),
pointer,
contiguous :: datp => null()
74 subroutine fmi_cr(fmiobj, name_model, inunit, iout, eqnsclfac, depvartype)
77 character(len=*),
intent(in) :: name_model
78 integer(I4B),
intent(in) :: inunit
79 integer(I4B),
intent(in) :: iout
80 real(dp),
intent(in),
pointer :: eqnsclfac
81 character(len=LENVARNAME),
intent(in) :: depvartype
87 call fmiobj%set_names(1, name_model,
'FMI',
'FMI')
91 call fmiobj%allocate_scalars()
94 fmiobj%inunit = inunit
98 call fmiobj%parser%Initialize(fmiobj%inunit, fmiobj%iout)
101 fmiobj%depvartype = depvartype
104 fmiobj%eqnsclfac => eqnsclfac
114 integer(I4B),
intent(in) :: inmvr
122 if (
associated(this%mvrbudobj) .and. inmvr == 0)
then
123 write (
errmsg,
'(a)')
'GWF water mover is active but the GWT MVT &
124 &package has not been specified. activate GWT MVT package.'
127 if (.not.
associated(this%mvrbudobj) .and. inmvr > 0)
then
128 write (
errmsg,
'(a)')
'GWF water mover terms are not available &
129 &but the GWT MVT package has been activated. Activate GWF-GWT &
130 &exchange or specify GWFMOVER in FMI PACKAGEDATA.'
143 real(DP),
intent(inout),
dimension(:) :: cnew
146 character(len=*),
parameter :: fmtdry = &
147 &
"(/1X,'WARNING: DRY CELL ENCOUNTERED AT ',a,'; RESET AS INACTIVE &
148 &WITH DRY CONCENTRATION = ', G13.5)"
149 character(len=*),
parameter :: fmtrewet = &
150 &
"(/1X,'DRY CELL REACTIVATED AT ', a,&
151 &' WITH STARTING CONCENTRATION =',G13.5)"
156 this%iflowsupdated = 1
159 if (this%iubud /= 0)
then
160 call this%advance_bfr()
164 if (this%iuhds /= 0)
then
165 call this%advance_hfr()
169 if (this%iumvr /= 0)
then
170 call this%mvrbudobj%bfr_advance(this%dis, this%iout)
174 if (this%flows_from_file .and. this%inunit /= 0)
then
175 do n = 1,
size(this%aptbudobj)
176 call this%aptbudobj(n)%ptr%bfr_advance(this%dis, this%iout)
181 if (this%idryinactive /= 0)
then
182 call this%set_active_status(cnew)
189 subroutine fmi_fc(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
192 integer,
intent(in) :: nodes
193 real(DP),
intent(in),
dimension(nodes) :: cold
194 integer(I4B),
intent(in) :: nja
196 integer(I4B),
intent(in),
dimension(nja) :: idxglo
197 real(DP),
intent(inout),
dimension(nodes) :: rhs
199 integer(I4B) :: n, idiag, idiag_sln
203 if (this%iflowerr /= 0)
then
208 idiag = this%dis%con%ia(n)
209 idiag_sln = idxglo(idiag)
211 qcorr = -this%gwfflowja(idiag) * this%eqnsclfac
212 call matrix_sln%add_value_pos(idiag_sln, qcorr)
226 real(DP),
intent(in),
dimension(:) :: cnew
227 real(DP),
dimension(:),
contiguous,
intent(inout) :: flowja
230 integer(I4B) :: idiag
234 if (this%iflowerr /= 0)
then
237 do n = 1, this%dis%nodes
239 idiag = this%dis%con%ia(n)
240 if (this%ibound(n) > 0)
then
241 rate = -this%gwfflowja(idiag) * cnew(n) * this%eqnsclfac
243 this%flowcorrect(n) = rate
244 flowja(idiag) = flowja(idiag) + rate
251 subroutine fmi_bd(this, isuppress_output, model_budget)
257 integer(I4B),
intent(in) :: isuppress_output
258 type(
budgettype),
intent(inout) :: model_budget
264 if (this%iflowerr /= 0)
then
266 call model_budget%addentry(rin, rout,
delt,
budtxt(2), isuppress_output)
275 integer(I4B),
intent(in) :: icbcfl
276 integer(I4B),
intent(in) :: icbcun
278 integer(I4B) :: ibinun
279 integer(I4B) :: iprint, nvaluesp, nwidthp
280 character(len=1) :: cdatafmp =
' ', editdesc =
' '
284 if (this%ipakcb < 0)
then
286 elseif (this%ipakcb == 0)
then
291 if (icbcfl == 0) ibinun = 0
294 if (this%iflowerr == 0) ibinun = 0
297 if (ibinun /= 0)
then
302 call this%dis%record_array(this%flowcorrect, this%iout, iprint, -ibinun, &
303 budtxt(2), cdatafmp, nvaluesp, &
304 nwidthp, editdesc, dinact)
320 call this%deallocate_gwfpackages()
323 if (
associated(this%datp))
then
324 deallocate (this%datp)
325 deallocate (this%gwfpackages)
326 deallocate (this%flowpacknamearray)
331 deallocate (this%aptbudobj)
334 if (this%flows_from_file)
then
358 call this%NumericalPackageType%da()
373 call this%FlowModelInterfaceType%allocate_scalars()
376 call mem_allocate(this%iflowerr,
'IFLOWERR', this%memoryPath)
380 allocate (this%aptbudobj(0))
396 integer(I4B),
intent(in) :: nodes
401 call this%FlowModelInterfaceType%allocate_arrays(nodes)
404 if (this%iflowerr == 0)
then
405 call mem_allocate(this%flowcorrect, 1,
'FLOWCORRECT', this%memoryPath)
407 call mem_allocate(this%flowcorrect, nodes,
'FLOWCORRECT', this%memoryPath)
409 do n = 1,
size(this%flowcorrect)
410 this%flowcorrect(n) =
dzero
425 real(DP),
intent(inout),
dimension(:) :: cnew
430 real(DP) :: crewet, tflow, flownm
431 character(len=15) :: nodestr
433 character(len=*),
parameter :: fmtoutmsg1 = &
434 "(1x,'WARNING: DRY CELL ENCOUNTERED AT ', a,'; RESET AS INACTIVE WITH &
435 &DRY ', a, '=', G13.5)"
436 character(len=*),
parameter :: fmtoutmsg2 = &
437 &
"(1x,'DRY CELL REACTIVATED AT', a, 'WITH STARTING', a, '=', G13.5)"
439 do n = 1, this%dis%nodes
442 if (this%gwfsat(n) > dzero)
then
443 this%ibdgwfsat0(n) = 1
445 this%ibdgwfsat0(n) = 0
449 if (this%ibound(n) > 0)
then
450 if (this%gwfhead(n) ==
dhdry)
then
454 call this%dis%noder_to_string(n, nodestr)
455 write (this%iout, fmtoutmsg1) &
456 trim(nodestr), trim(adjustl(this%depvartype)),
dhdry
462 do n = 1, this%dis%nodes
465 if (cnew(n) ==
dhdry)
then
466 if (this%gwfhead(n) /=
dhdry)
then
471 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
472 m = this%dis%con%ja(ipos)
473 flownm = this%gwfflowja(ipos)
475 if (this%ibound(m) /= 0)
then
476 crewet = crewet + cnew(m) * flownm
477 tflow = tflow + this%gwfflowja(ipos)
481 if (tflow > dzero)
then
482 crewet = crewet / tflow
490 call this%dis%noder_to_string(n, nodestr)
491 write (this%iout, fmtoutmsg2) &
492 trim(nodestr), trim(adjustl(this%depvartype)), crewet
507 integer(I4B),
intent(in) :: n
508 real(dp),
intent(in) :: delt
517 vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
518 vnew = vcell * this%gwfsat(n)
520 if (this%igwfstrgss /= 0) vold = vold + this%gwfstrgss(n) * delt
521 if (this%igwfstrgsy /= 0) vold = vold + this%gwfstrgsy(n) * delt
522 satold = vold / vcell
535 character(len=LINELENGTH) :: keyword
537 logical :: isfound, endOfBlock
538 character(len=*),
parameter :: fmtisvflow = &
539 "(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY FILE &
540 &WHENEVER ICBCFL IS NOT ZERO AND FLOW IMBALANCE CORRECTION ACTIVE.')"
541 character(len=*),
parameter :: fmtifc = &
542 &
"(4x,'MASS WILL BE ADDED OR REMOVED TO COMPENSATE FOR FLOW IMBALANCE.')"
545 call this%parser%GetBlock(
'OPTIONS', isfound, ierr, blockrequired=.false., &
546 supportopenclose=.true.)
550 write (this%iout,
'(1x,a)')
'PROCESSING FMI OPTIONS'
552 call this%parser%GetNextLine(endofblock)
554 call this%parser%GetStringCaps(keyword)
555 select case (keyword)
558 write (this%iout, fmtisvflow)
559 case (
'FLOW_IMBALANCE_CORRECTION')
560 write (this%iout, fmtifc)
563 write (
errmsg,
'(a,a)')
'Unknown FMI option: ', &
566 call this%parser%StoreErrorUnit()
569 write (this%iout,
'(1x,a)')
'END OF FMI OPTIONS'
587 character(len=LINELENGTH) :: keyword, fname
588 character(len=LENPACKAGENAME) :: pname
591 integer(I4B) :: inunit
593 logical :: isfound, endOfBlock
594 logical :: blockrequired
600 blockrequired = .true.
603 call this%parser%GetBlock(
'PACKAGEDATA', isfound, ierr, &
604 blockrequired=blockrequired, &
605 supportopenclose=.true.)
609 write (this%iout,
'(1x,a)')
'PROCESSING FMI PACKAGEDATA'
611 call this%parser%GetNextLine(endofblock)
613 call this%parser%GetStringCaps(keyword)
614 select case (keyword)
616 call this%parser%GetStringCaps(keyword)
617 if (keyword /=
'FILEIN')
then
618 call store_error(
'GWFBUDGET keyword must be followed by '// &
619 '"FILEIN" then by filename.')
620 call this%parser%StoreErrorUnit()
622 call this%parser%GetString(fname)
624 inquire (file=trim(fname), exist=exist)
625 if (.not. exist)
then
626 call store_error(
'Could not find file '//trim(fname))
627 call this%parser%StoreErrorUnit()
629 call openfile(inunit, this%iout, fname,
'DATA(BINARY)',
form, &
632 call this%initialize_bfr()
634 call this%parser%GetStringCaps(keyword)
635 if (keyword /=
'FILEIN')
then
636 call store_error(
'GWFHEAD keyword must be followed by '// &
637 '"FILEIN" then by filename.')
638 call this%parser%StoreErrorUnit()
640 call this%parser%GetString(fname)
641 inquire (file=trim(fname), exist=exist)
642 if (.not. exist)
then
643 call store_error(
'Could not find file '//trim(fname))
644 call this%parser%StoreErrorUnit()
647 call openfile(inunit, this%iout, fname,
'DATA(BINARY)',
form, &
650 call this%initialize_hfr()
652 call this%parser%GetStringCaps(keyword)
653 if (keyword /=
'FILEIN')
then
654 call store_error(
'GWFMOVER keyword must be followed by '// &
655 '"FILEIN" then by filename.')
656 call this%parser%StoreErrorUnit()
658 call this%parser%GetString(fname)
660 call openfile(inunit, this%iout, fname,
'DATA(BINARY)',
form, &
665 call this%mvrbudobj%fill_from_bfr(this%dis, this%iout)
669 allocate (tmpbudobj(iapt))
670 do i = 1,
size(this%aptbudobj)
671 tmpbudobj(i)%ptr => this%aptbudobj(i)%ptr
673 deallocate (this%aptbudobj)
674 allocate (this%aptbudobj(iapt + 1))
675 do i = 1,
size(tmpbudobj)
676 this%aptbudobj(i)%ptr => tmpbudobj(i)%ptr
678 deallocate (tmpbudobj)
683 call this%parser%GetStringCaps(keyword)
684 if (keyword /=
'FILEIN')
then
685 call store_error(
'Package name must be followed by '// &
686 '"FILEIN" then by filename.')
687 call this%parser%StoreErrorUnit()
689 call this%parser%GetString(fname)
691 call openfile(inunit, this%iout, fname,
'DATA(BINARY)',
form, &
694 this%iout, colconv2=[
'GWF '])
695 call budobjptr%fill_from_bfr(this%dis, this%iout)
696 this%aptbudobj(iapt)%ptr => budobjptr
699 write (this%iout,
'(1x,a)')
'END OF FMI PACKAGEDATA'
714 character(len=*),
intent(in) :: name
720 do i = 1,
size(this%aptbudobj)
721 if (this%aptbudobj(i)%ptr%name == name)
then
722 budobjptr => this%aptbudobj(i)%ptr
741 integer(I4B) :: nflowpack
742 integer(I4B) :: i, ip
744 logical :: found_flowja
745 logical :: found_dataspdis
746 logical :: found_datasat
747 logical :: found_stoss
748 logical :: found_stosy
749 integer(I4B),
dimension(:),
allocatable :: imap
752 allocate (imap(this%bfr%nbudterms))
755 found_flowja = .false.
756 found_dataspdis = .false.
757 found_datasat = .false.
758 found_stoss = .false.
759 found_stosy = .false.
760 do i = 1, this%bfr%nbudterms
761 select case (trim(adjustl(this%bfr%budtxtarray(i))))
762 case (
'FLOW-JA-FACE')
763 found_flowja = .true.
765 found_dataspdis = .true.
767 found_datasat = .true.
775 nflowpack = nflowpack + 1
781 call this%allocate_gwfpackages(nflowpack)
786 do i = 1, this%bfr%nbudterms
787 if (imap(i) == 0) cycle
788 call this%gwfpackages(ip)%set_name(this%bfr%dstpackagenamearray(i), &
789 this%bfr%budtxtarray(i))
790 naux = this%bfr%nauxarray(i)
791 call this%gwfpackages(ip)%set_auxname(naux, &
792 this%bfr%auxtxtarray(1:naux, i))
800 if (imap(i) == 1)
then
801 this%flowpacknamearray(ip) = this%bfr%dstpackagenamearray(i)
807 if (.not. found_dataspdis)
then
808 write (
errmsg,
'(a)')
'Specific discharge not found in &
809 &budget file. SAVE_SPECIFIC_DISCHARGE and &
810 &SAVE_FLOWS must be activated in the NPF package.'
813 if (.not. found_datasat)
then
814 write (
errmsg,
'(a)')
'Saturation not found in &
815 &budget file. SAVE_SATURATION and &
816 &SAVE_FLOWS must be activated in the NPF package.'
819 if (.not. found_flowja)
then
820 write (
errmsg,
'(a)')
'FLOWJA not found in &
821 &budget file. SAVE_FLOWS must &
822 &be activated in the NPF package.'
826 call this%parser%StoreErrorUnit()
840 integer(I4B) :: ngwfpack
841 integer(I4B) :: ngwfterms
843 integer(I4B) :: imover
844 integer(I4B) :: ntomvr
845 integer(I4B) :: iterm
846 character(len=LENPACKAGENAME) :: budtxt
847 class(
bndtype),
pointer :: packobj => null()
850 ngwfpack = this%gwfbndlist%Count()
858 imover = packobj%imover
859 if (packobj%isadvpak /= 0) imover = 0
860 if (imover /= 0)
then
867 ngwfterms = ngwfpack + ntomvr
868 call this%allocate_gwfpackages(ngwfterms)
876 budtxt = adjustl(packobj%text)
877 call this%gwfpackages(iterm)%set_name(packobj%packName, budtxt)
878 this%flowpacknamearray(iterm) = packobj%packName
879 call this%gwfpackages(iterm)%set_auxname(packobj%naux, &
885 imover = packobj%imover
886 if (packobj%isadvpak /= 0) imover = 0
887 if (imover /= 0)
then
888 budtxt = trim(adjustl(packobj%text))//
'-TO-MVR'
889 call this%gwfpackages(iterm)%set_name(packobj%packName, budtxt)
890 this%flowpacknamearray(iterm) = packobj%packName
891 call this%gwfpackages(iterm)%set_auxname(packobj%naux, &
893 this%igwfmvrterm(iterm) = 1
910 integer(I4B),
intent(in) :: ngwfterms
913 character(len=LENMEMPATH) :: memPath
916 allocate (this%gwfpackages(ngwfterms))
917 allocate (this%flowpacknamearray(ngwfterms))
918 allocate (this%datp(ngwfterms))
921 call mem_allocate(this%iatp, ngwfterms,
'IATP', this%memoryPath)
922 call mem_allocate(this%igwfmvrterm, ngwfterms,
'IGWFMVRTERM', this%memoryPath)
925 this%nflowpack = ngwfterms
926 do n = 1, this%nflowpack
928 this%igwfmvrterm(n) = 0
929 this%flowpacknamearray(n) =
''
933 write (mempath,
'(a, i0)') trim(this%memoryPath)//
'-FT', n
934 call this%gwfpackages(n)%initialize(mempath)
950 do n = 1, this%nflowpack
951 call this%gwfpackages(n)%da()
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.
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
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.
integer(i4b), parameter linelength
maximum length of a standard line
real(dp), parameter dhdry
real dry cell constant
integer(i4b), parameter lenpackagename
maximum length of the package name
integer(i4b), parameter lenvarname
maximum length of a variable name
real(dp), parameter dhalf
real constant 1/2
real(dp), parameter dem6
real constant 1e-6
real(dp), parameter dzero
real constant zero
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
integer(i4b), parameter lenmempath
maximum length of the memory path
real(dp), parameter done
real constant 1
This module defines variable data types.
This module contains the PackageBudgetModule Module.
This module contains simulation methods.
subroutine, public store_error(msg, terminate)
Store an error message.
integer(i4b) function, public count_errors()
Return number of errors.
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
This module contains simulation variables.
character(len=maxcharlen) errmsg
error message string
integer(i4b), pointer, public kstp
current time step number
integer(i4b), pointer, public kper
current stress period number
real(dp), pointer, public delt
length of the current time step
real(dp) function gwfsatold(this, n, delt)
Calculate the previous saturation level.
integer(i4b), parameter nbditems
subroutine fmi_bd(this, isuppress_output, model_budget)
Calculate budget terms associated with FMI object.
subroutine gwtfmi_deallocate_gwfpackages(this)
Deallocate memory.
character(len=lenbudtxt), dimension(nbditems) budtxt
subroutine gwtfmi_allocate_scalars(this)
@ brief Allocate scalars
subroutine gwtfmi_allocate_arrays(this, nodes)
@ brief Allocate arrays for FMI object
subroutine initialize_gwfterms_from_gwfbndlist(this)
Initialize groundwater flow terms from the groundwater budget.
subroutine gwtfmi_allocate_gwfpackages(this, ngwfterms)
Initialize an array for storing PackageBudget objects.
subroutine fmi_fc(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
Calculate coefficients and fill matrix and rhs terms associated with FMI object.
subroutine initialize_gwfterms_from_bfr(this)
Initialize the groundwater flow terms based on the budget file reader.
subroutine fmi_rp(this, inmvr)
Read and prepare.
subroutine gwtfmi_read_options(this)
Read options from input file.
subroutine set_aptbudobj_pointer(this, name, budobjptr)
Set the pointer to a budget object.
subroutine set_active_status(this, cnew)
Set gwt transport cell status.
subroutine fmi_ot_flow(this, icbcfl, icbcun)
Save budget terms associated with FMI object.
character(len=lenpackagename) text
subroutine fmi_ad(this, cnew)
Advance routine for FMI object.
subroutine fmi_cq(this, cnew, flowja)
Calculate flow correction.
subroutine gwtfmi_da(this)
Deallocate variables.
subroutine gwtfmi_read_packagedata(this)
Read PACKAGEDATA block.
subroutine, public fmi_cr(fmiobj, name_model, inunit, iout, eqnsclfac, depvartype)
Create a new FMI object.
Derived type for the Budget object.
A generic heterogeneous doubly-linked list.
Derived type for storing flows.