19 integer(I4B),
pointer :: iadvwt => null()
20 real(dp),
pointer :: ats_percel => null()
21 integer(I4B),
dimension(:),
pointer,
contiguous :: ibound => null()
23 real(dp),
pointer :: eqnsclfac => null()
49 subroutine adv_cr(advobj, name_model, inunit, iout, fmi, eqnsclfac)
52 character(len=*),
intent(in) :: name_model
53 integer(I4B),
intent(in) :: inunit
54 integer(I4B),
intent(in) :: iout
56 real(dp),
intent(in),
pointer :: eqnsclfac
62 call advobj%set_names(1, name_model,
'ADV',
'ADV')
65 call advobj%allocate_scalars()
68 advobj%inunit = inunit
71 advobj%eqnsclfac => eqnsclfac
83 character(len=*),
parameter :: fmtadv = &
84 "(1x,/1x,'ADV-- ADVECTION PACKAGE, VERSION 1, 8/25/2017', &
85 &' INPUT READ FROM UNIT ', i0, //)"
88 if (.not.
present(adv_options))
then
92 call this%parser%Initialize(this%inunit, this%iout)
95 write (this%iout, fmtadv) this%inunit
98 call this%read_options()
102 this%iadvwt = adv_options%iAdvScheme
115 integer(I4B),
dimension(:),
pointer,
contiguous,
intent(in) :: ibound
121 this%ibound => ibound
128 subroutine adv_dt(this, dtmax, msg, thetam)
131 real(DP),
intent(out) :: dtmax
132 character(len=*),
intent(inout) :: msg
133 real(DP),
dimension(:),
intent(in) :: thetam
138 integer(I4B) :: nrmax
139 character(len=LINELENGTH) :: cellstr
142 real(DP) :: flowsumpos
143 real(DP) :: flowsumneg
145 real(DP) :: cell_volume
152 if (this%ats_percel ==
dnodata)
then
158 do n = 1, this%dis%nodes
159 if (this%ibound(n) == 0) cycle
162 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
163 if (this%dis%con%mask(ipos) == 0) cycle
164 m = this%dis%con%ja(ipos)
165 if (this%ibound(m) == 0) cycle
166 flownm = this%fmi%gwfflowja(ipos)
167 if (flownm <
dzero)
then
168 flowsumneg = flowsumneg - flownm
170 flowsumpos = flowsumpos + flownm
173 flowmax = max(flowsumneg, flowsumpos)
174 if (flowmax <
dprec) cycle
175 cell_volume = this%dis%get_cell_volume(n, this%dis%top(n))
176 dt = cell_volume * this%fmi%gwfsat(n) * thetam(n) / flowmax
177 dt = dt * this%ats_percel
184 call this%dis%noder_to_string(nrmax, cellstr)
185 write (msg, *) adjustl(trim(this%memoryPath))//
'-'//trim(cellstr)
193 subroutine adv_fc(this, nodes, matrix_sln, idxglo, cnew, rhs)
197 integer,
intent(in) :: nodes
199 integer(I4B),
intent(in),
dimension(:) :: idxglo
200 real(DP),
intent(in),
dimension(:) :: cnew
201 real(DP),
dimension(:),
intent(inout) :: rhs
203 integer(I4B) :: n, m, idiag, ipos
204 real(DP) :: omega, qnm
209 if (this%ibound(n) == 0) cycle
210 idiag = this%dis%con%ia(n)
211 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
212 if (this%dis%con%mask(ipos) == 0) cycle
213 m = this%dis%con%ja(ipos)
214 if (this%ibound(m) == 0) cycle
215 qnm = this%fmi%gwfflowja(ipos) * this%eqnsclfac
216 omega = this%adv_weight(this%iadvwt, ipos, n, m, qnm)
217 call matrix_sln%add_value_pos(idxglo(ipos), qnm * (
done - omega))
218 call matrix_sln%add_value_pos(idxglo(idiag), qnm * omega)
223 if (this%iadvwt == 2)
then
225 if (this%ibound(n) == 0) cycle
226 call this%advtvd(n, cnew, rhs)
240 integer(I4B),
intent(in) :: n
241 real(DP),
dimension(:),
intent(in) :: cnew
242 real(DP),
dimension(:),
intent(inout) :: rhs
245 integer(I4B) :: m, ipos
248 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
249 if (this%dis%con%mask(ipos) == 0) cycle
250 m = this%dis%con%ja(ipos)
251 if (m > n .and. this%ibound(m) /= 0)
then
252 qtvd = this%advqtvd(n, m, ipos, cnew)
253 rhs(n) = rhs(n) - qtvd
254 rhs(m) = rhs(m) + qtvd
264 function advqtvd(this, n, m, iposnm, cnew)
result(qtvd)
271 integer(I4B),
intent(in) :: n
272 integer(I4B),
intent(in) :: m
273 integer(I4B),
intent(in) :: iposnm
274 real(dp),
dimension(:),
intent(in) :: cnew
276 integer(I4B) :: ipos, isympos, iup, idn, i2up, j
277 real(dp) :: qnm, qmax, qupj, elupdn, elup2up
278 real(dp) :: smooth, cdiff, alimiter
284 isympos = this%dis%con%jas(iposnm)
285 qnm = this%fmi%gwfflowja(iposnm)
286 if (qnm > dzero)
then
294 elupdn = this%dis%con%cl1(isympos) + this%dis%con%cl2(isympos)
299 do ipos = this%dis%con%ia(iup) + 1, this%dis%con%ia(iup + 1) - 1
300 j = this%dis%con%ja(ipos)
301 if (this%ibound(j) == 0) cycle
302 qupj = this%fmi%gwfflowja(ipos)
303 isympos = this%dis%con%jas(ipos)
304 if (qupj > qmax)
then
307 elup2up = this%dis%con%cl1(isympos) + this%dis%con%cl2(isympos)
314 cdiff = abs(cnew(idn) - cnew(iup))
315 if (cdiff >
dprec)
then
316 smooth = (cnew(iup) - cnew(i2up)) / elup2up * &
317 elupdn / (cnew(idn) - cnew(iup))
319 if (smooth > dzero)
then
320 alimiter = dtwo * smooth / (done + smooth)
321 qtvd = dhalf * alimiter * qnm * (cnew(idn) - cnew(iup))
322 qtvd = qtvd * this%eqnsclfac
333 real(DP),
intent(in),
dimension(:) :: cnew
334 real(DP),
intent(inout),
dimension(:) :: flowja
336 integer(I4B) :: nodes
337 integer(I4B) :: n, m, idiag, ipos
338 real(DP) :: omega, qnm
342 nodes = this%dis%nodes
344 if (this%ibound(n) == 0) cycle
345 idiag = this%dis%con%ia(n)
346 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
347 m = this%dis%con%ja(ipos)
348 if (this%ibound(m) == 0) cycle
349 qnm = this%fmi%gwfflowja(ipos) * this%eqnsclfac
350 omega = this%adv_weight(this%iadvwt, ipos, n, m, qnm)
351 flowja(ipos) = flowja(ipos) + qnm * omega * cnew(n) + &
352 qnm * (
done - omega) * cnew(m)
357 if (this%iadvwt == 2)
call this%advtvd_bd(cnew, flowja)
365 real(DP),
dimension(:),
intent(in) :: cnew
366 real(DP),
dimension(:),
intent(inout) :: flowja
368 real(DP) :: qtvd, qnm
369 integer(I4B) :: nodes, n, m, ipos
371 nodes = this%dis%nodes
373 if (this%ibound(n) == 0) cycle
374 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
375 m = this%dis%con%ja(ipos)
376 if (this%ibound(m) /= 0)
then
377 qnm = this%fmi%gwfflowja(ipos)
378 qtvd = this%advqtvd(n, m, ipos, cnew)
379 flowja(ipos) = flowja(ipos) + qtvd
394 if (this%inunit > 0)
then
398 this%ibound => null()
405 call this%NumericalPackageType%da()
419 call this%NumericalPackageType%allocate_scalars()
422 call mem_allocate(this%iadvwt,
'IADVWT', this%memoryPath)
423 call mem_allocate(this%ats_percel,
'ATS_PERCEL', this%memoryPath)
444 character(len=LINELENGTH) :: errmsg, keyword
446 logical :: isfound, endOfBlock
448 character(len=*),
parameter :: fmtiadvwt = &
449 &
"(4x,'ADVECTION WEIGHTING SCHEME HAS BEEN SET TO: ', a)"
452 call this%parser%GetBlock(
'OPTIONS', isfound, ierr, blockrequired=.false., &
453 supportopenclose=.true.)
457 write (this%iout,
'(1x,a)')
'PROCESSING ADVECTION OPTIONS'
459 call this%parser%GetNextLine(endofblock)
461 call this%parser%GetStringCaps(keyword)
462 select case (keyword)
464 call this%parser%GetStringCaps(keyword)
465 select case (keyword)
468 write (this%iout, fmtiadvwt)
'UPSTREAM'
471 write (this%iout, fmtiadvwt)
'CENTRAL'
474 write (this%iout, fmtiadvwt)
'TVD'
476 write (errmsg,
'(a, a)') &
477 'Unknown scheme: ', trim(keyword)
479 write (errmsg,
'(a, a)') &
480 'Scheme must be "UPSTREAM", "CENTRAL" or "TVD"'
482 call this%parser%StoreErrorUnit()
485 this%ats_percel = this%parser%GetDouble()
486 if (this%ats_percel == dzero) this%ats_percel = dnodata
487 write (this%iout,
'(4x,a,1pg15.6)') &
488 'User-specified fractional cell distance for adaptive time &
489 &steps: ', this%ats_percel
491 write (errmsg,
'(a,a)')
'Unknown ADVECTION option: ', &
496 write (this%iout,
'(1x,a)')
'END OF ADVECTION OPTIONS'
504 function adv_weight(this, iadvwt, ipos, n, m, qnm)
result(omega)
509 integer,
intent(in) :: iadvwt
510 integer,
intent(in) :: ipos
511 integer,
intent(in) :: n
512 integer,
intent(in) :: m
513 real(dp),
intent(in) :: qnm
521 if (this%dis%con%ihc(this%dis%con%jas(ipos)) == 0)
then
523 lnm =
dhalf * (this%dis%top(n) - this%dis%bot(n))
524 lmn =
dhalf * (this%dis%top(m) - this%dis%bot(m))
527 lnm = this%dis%con%cl1(this%dis%con%jas(ipos))
528 lmn = this%dis%con%cl2(this%dis%con%jas(ipos))
530 omega = lmn / (lnm + lmn)
533 if (qnm >
dzero)
then
This module contains simulation constants.
integer(i4b), parameter linelength
maximum length of a standard line
real(dp), parameter dnodata
real no data constant
real(dp), parameter dhalf
real constant 1/2
real(dp), parameter dzero
real constant zero
real(dp), parameter dprec
real constant machine precision
real(dp), parameter dtwo
real constant 2
real(dp), parameter done
real constant 1
This module defines variable data types.
This module contains the base numerical package type.
This module contains simulation methods.
subroutine, public store_error(msg, terminate)
Store an error message.
subroutine advtvd_bd(this, cnew, flowja)
Add TVD contribution to flowja.
real(dp) function advqtvd(this, n, m, iposnm, cnew)
Calculate TVD.
subroutine adv_df(this, adv_options)
Define ADV object.
subroutine adv_fc(this, nodes, matrix_sln, idxglo, cnew, rhs)
Fill coefficient method for ADV package.
subroutine adv_cq(this, cnew, flowja)
Calculate advection contribution to flowja.
subroutine adv_da(this)
Deallocate memory.
subroutine advtvd(this, n, cnew, rhs)
Calculate TVD.
subroutine adv_ar(this, dis, ibound)
Allocate and read method for package.
real(dp) function adv_weight(this, iadvwt, ipos, n, m, qnm)
@ brief Advection weight
subroutine read_options(this)
Read options.
subroutine, public adv_cr(advobj, name_model, inunit, iout, fmi, eqnsclfac)
@ brief Create a new ADV object
subroutine adv_dt(this, dtmax, msg, thetam)
Calculate maximum time step length.
subroutine allocate_scalars(this)
Allocate scalars specific to the streamflow energy transport (SFE) package.