MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
gwt-mst.f90
Go to the documentation of this file.
1 !> -- @ brief Mobile Storage and Transfer (MST) Module
2 !!
3 !! The GwtMstModule contains the GwtMstType, which is the
4 !! derived type responsible for adding the effects of
5 !! 1. Changes in dissolved solute mass
6 !! 2. Decay of dissolved solute mass
7 !! 3. Sorption
8 !! 4. Decay of sorbed solute mass
9 !<
11 
12  use kindmodule, only: dp, i4b
16  use simmodule, only: store_error, count_errors, &
20  use basedismodule, only: disbasetype
21  use tspfmimodule, only: tspfmitype
22 
23  implicit none
24  public :: gwtmsttype
25  public :: mst_cr
26  !
27  integer(I4B), parameter :: nbditems = 4
28  character(len=LENBUDTXT), dimension(NBDITEMS) :: budtxt
29  data budtxt/' STORAGE-AQUEOUS', ' DECAY-AQUEOUS', &
30  ' STORAGE-SORBED', ' DECAY-SORBED'/
31 
32  !> @ brief Mobile storage and transfer
33  !!
34  !! Data and methods for handling changes in solute storage,
35  !! decay of dissolved solute mass, sorption, and decay of
36  !! sorbed mass.
37  !<
38  type, extends(numericalpackagetype) :: gwtmsttype
39  !
40  ! -- storage
41  real(dp), dimension(:), pointer, contiguous :: porosity => null() !< mobile porosity defined as volume mobile voids per volume of mobile domain
42  real(dp), dimension(:), pointer, contiguous :: thetam => null() !< mobile porosity defined as volume mobile voids per volume of aquifer
43  real(dp), dimension(:), pointer, contiguous :: volfracim => null() !< sum of all immobile domain volume fractions
44  real(dp), dimension(:), pointer, contiguous :: ratesto => null() !< rate of mobile storage
45  !
46  ! -- decay
47  integer(I4B), pointer :: idcy => null() !< order of decay rate (0:none, 1:first, 2:zero)
48  real(dp), dimension(:), pointer, contiguous :: decay => null() !< first or zero order decay rate (aqueous)
49  real(dp), dimension(:), pointer, contiguous :: decay_sorbed => null() !< first or zero order decay rate (sorbed)
50  real(dp), dimension(:), pointer, contiguous :: ratedcy => null() !< rate of decay
51  real(dp), dimension(:), pointer, contiguous :: decaylast => null() !< decay rate used for last iteration (needed for zero order decay)
52  real(dp), dimension(:), pointer, contiguous :: decayslast => null() !< sorbed decay rate used for last iteration (needed for zero order decay)
53  !
54  ! -- sorption
55  integer(I4B), pointer :: isrb => null() !< sorption active flag (0:off, 1:linear, 2:freundlich, 3:langmuir)
56  integer(I4B), pointer :: ioutsorbate => null() !< unit number for sorbate concentration output
57  real(dp), dimension(:), pointer, contiguous :: bulk_density => null() !< bulk density of mobile domain; mass of mobile domain solid per aquifer volume
58  real(dp), dimension(:), pointer, contiguous :: distcoef => null() !< kd distribution coefficient
59  real(dp), dimension(:), pointer, contiguous :: sp2 => null() !< second sorption parameter
60  real(dp), dimension(:), pointer, contiguous :: ratesrb => null() !< rate of sorption
61  real(dp), dimension(:), pointer, contiguous :: ratedcys => null() !< rate of sorbed mass decay
62  real(dp), dimension(:), pointer, contiguous :: csrb => null() !< sorbate concentration
63  !
64  ! -- misc
65  integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound
66  type(tspfmitype), pointer :: fmi => null() !< pointer to fmi object
67 
68  contains
69 
70  procedure :: mst_ar
71  procedure :: mst_fc
72  procedure :: mst_fc_sto
73  procedure :: mst_fc_dcy
74  procedure :: mst_fc_srb
75  procedure :: mst_fc_dcy_srb
76  procedure :: mst_cq
77  procedure :: mst_cq_sto
78  procedure :: mst_cq_dcy
79  procedure :: mst_cq_srb
80  procedure :: mst_cq_dcy_srb
81  procedure :: mst_calc_csrb
82  procedure :: mst_bd
83  procedure :: mst_ot_flow
84  procedure :: mst_ot_dv
85  procedure :: mst_da
86  procedure :: allocate_scalars
87  procedure :: addto_volfracim
88  procedure :: get_volfracm
89  procedure, private :: allocate_arrays
90  procedure, private :: read_options
91  procedure, private :: read_data
92 
93  end type gwtmsttype
94 
95 contains
96 
97  !> @ brief Create a new package object
98  !!
99  !! Create a new MST object
100  !!
101  !<
102  subroutine mst_cr(mstobj, name_model, inunit, iout, fmi)
103  ! -- dummy
104  type(gwtmsttype), pointer :: mstobj !< unallocated new mst object to create
105  character(len=*), intent(in) :: name_model !< name of the model
106  integer(I4B), intent(in) :: inunit !< unit number of WEL package input file
107  integer(I4B), intent(in) :: iout !< unit number of model listing file
108  type(tspfmitype), intent(in), target :: fmi !< fmi package for this GWT model
109  !
110  ! -- Create the object
111  allocate (mstobj)
112  !
113  ! -- create name and memory path
114  call mstobj%set_names(1, name_model, 'MST', 'MST')
115  !
116  ! -- Allocate scalars
117  call mstobj%allocate_scalars()
118  !
119  ! -- Set variables
120  mstobj%inunit = inunit
121  mstobj%iout = iout
122  mstobj%fmi => fmi
123  !
124  ! -- Initialize block parser
125  call mstobj%parser%Initialize(mstobj%inunit, mstobj%iout)
126  end subroutine mst_cr
127 
128  !> @ brief Allocate and read method for package
129  !!
130  !! Method to allocate and read static data for the package.
131  !!
132  !<
133  subroutine mst_ar(this, dis, ibound)
134  ! -- modules
135  ! -- dummy
136  class(gwtmsttype), intent(inout) :: this !< GwtMstType object
137  class(disbasetype), pointer, intent(in) :: dis !< pointer to dis package
138  integer(I4B), dimension(:), pointer, contiguous :: ibound !< pointer to GWT ibound array
139  ! -- local
140  ! -- formats
141  character(len=*), parameter :: fmtmst = &
142  "(1x,/1x,'MST -- MOBILE STORAGE AND TRANSFER PACKAGE, VERSION 1, &
143  &7/29/2020 INPUT READ FROM UNIT ', i0, //)"
144  !
145  ! --print a message identifying the mobile storage and transfer package.
146  write (this%iout, fmtmst) this%inunit
147  !
148  ! -- Read options
149  call this%read_options()
150  !
151  ! -- store pointers to arguments that were passed in
152  this%dis => dis
153  this%ibound => ibound
154  !
155  ! -- Allocate arrays
156  call this%allocate_arrays(dis%nodes)
157  !
158  ! -- read the data block
159  call this%read_data()
160  end subroutine mst_ar
161 
162  !> @ brief Fill coefficient method for package
163  !!
164  !! Method to calculate and fill coefficients for the package.
165  !!
166  !<
167  subroutine mst_fc(this, nodes, cold, nja, matrix_sln, idxglo, cnew, &
168  rhs, kiter)
169  ! -- modules
170  ! -- dummy
171  class(gwtmsttype) :: this !< GwtMstType object
172  integer, intent(in) :: nodes !< number of nodes
173  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
174  integer(I4B), intent(in) :: nja !< number of GWT connections
175  class(matrixbasetype), pointer :: matrix_sln !< solution matrix
176  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
177  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
178  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
179  integer(I4B), intent(in) :: kiter !< solution outer iteration number
180  ! -- local
181  !
182  ! -- storage contribution
183  call this%mst_fc_sto(nodes, cold, nja, matrix_sln, idxglo, rhs)
184  !
185  ! -- decay contribution
186  if (this%idcy /= 0) then
187  call this%mst_fc_dcy(nodes, cold, cnew, nja, matrix_sln, idxglo, &
188  rhs, kiter)
189  end if
190  !
191  ! -- sorption contribution
192  if (this%isrb /= 0) then
193  call this%mst_fc_srb(nodes, cold, nja, matrix_sln, idxglo, rhs, cnew)
194  end if
195  !
196  ! -- decay sorbed contribution
197  if (this%isrb /= 0 .and. this%idcy /= 0) then
198  call this%mst_fc_dcy_srb(nodes, cold, nja, matrix_sln, idxglo, rhs, &
199  cnew, kiter)
200  end if
201  end subroutine mst_fc
202 
203  !> @ brief Fill storage coefficient method for package
204  !!
205  !! Method to calculate and fill storage coefficients for the package.
206  !!
207  !<
208  subroutine mst_fc_sto(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
209  ! -- modules
210  use tdismodule, only: delt
211  ! -- dummy
212  class(gwtmsttype) :: this !< GwtMstType object
213  integer, intent(in) :: nodes !< number of nodes
214  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
215  integer(I4B), intent(in) :: nja !< number of GWT connections
216  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
217  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
218  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
219  ! -- local
220  integer(I4B) :: n, idiag
221  real(DP) :: tled
222  real(DP) :: hhcof, rrhs
223  real(DP) :: vnew, vold
224  !
225  ! -- set variables
226  tled = done / delt
227  !
228  ! -- loop through and calculate storage contribution to hcof and rhs
229  do n = 1, this%dis%nodes
230  !
231  ! -- skip if transport inactive
232  if (this%ibound(n) <= 0) cycle
233  !
234  ! -- calculate new and old water volumes
235  vnew = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n)) * &
236  this%fmi%gwfsat(n) * this%thetam(n)
237  vold = vnew
238  if (this%fmi%igwfstrgss /= 0) vold = vold + this%fmi%gwfstrgss(n) * delt
239  if (this%fmi%igwfstrgsy /= 0) vold = vold + this%fmi%gwfstrgsy(n) * delt
240  !
241  ! -- add terms to diagonal and rhs accumulators
242  hhcof = -vnew * tled
243  rrhs = -vold * tled * cold(n)
244  idiag = this%dis%con%ia(n)
245  call matrix_sln%add_value_pos(idxglo(idiag), hhcof)
246  rhs(n) = rhs(n) + rrhs
247  end do
248  end subroutine mst_fc_sto
249 
250  !> @ brief Fill decay coefficient method for package
251  !!
252  !! Method to calculate and fill decay coefficients for the package.
253  !!
254  !<
255  subroutine mst_fc_dcy(this, nodes, cold, cnew, nja, matrix_sln, &
256  idxglo, rhs, kiter)
257  ! -- modules
258  use tdismodule, only: delt
259  ! -- dummy
260  class(gwtmsttype) :: this !< GwtMstType object
261  integer, intent(in) :: nodes !< number of nodes
262  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
263  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
264  integer(I4B), intent(in) :: nja !< number of GWT connections
265  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
266  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
267  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
268  integer(I4B), intent(in) :: kiter !< solution outer iteration number
269  ! -- local
270  integer(I4B) :: n, idiag
271  real(DP) :: hhcof, rrhs
272  real(DP) :: swtpdt
273  real(DP) :: vcell
274  real(DP) :: decay_rate
275  !
276  ! -- loop through and calculate decay contribution to hcof and rhs
277  do n = 1, this%dis%nodes
278  !
279  ! -- skip if transport inactive
280  if (this%ibound(n) <= 0) cycle
281  !
282  ! -- calculate new and old water volumes
283  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
284  swtpdt = this%fmi%gwfsat(n)
285  !
286  ! -- add decay rate terms to accumulators
287  idiag = this%dis%con%ia(n)
288  if (this%idcy == 1) then
289  !
290  ! -- first order decay rate is a function of concentration, so add
291  ! to left hand side
292  hhcof = -this%decay(n) * vcell * swtpdt * this%thetam(n)
293  call matrix_sln%add_value_pos(idxglo(idiag), hhcof)
294  elseif (this%idcy == 2) then
295  !
296  ! -- Call function to get zero-order decay rate, which may be changed
297  ! from the user-specified rate to prevent negative concentrations
298  decay_rate = get_zero_order_decay(this%decay(n), this%decaylast(n), &
299  kiter, cold(n), cnew(n), delt)
300  this%decaylast(n) = decay_rate
301  rrhs = decay_rate * vcell * swtpdt * this%thetam(n)
302  rhs(n) = rhs(n) + rrhs
303  end if
304  !
305  end do
306  end subroutine mst_fc_dcy
307 
308  !> @ brief Fill sorption coefficient method for package
309  !!
310  !! Method to calculate and fill sorption coefficients for the package.
311  !!
312  !<
313  subroutine mst_fc_srb(this, nodes, cold, nja, matrix_sln, idxglo, rhs, &
314  cnew)
315  ! -- modules
316  use tdismodule, only: delt
317  ! -- dummy
318  class(gwtmsttype) :: this !< GwtMstType object
319  integer, intent(in) :: nodes !< number of nodes
320  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
321  integer(I4B), intent(in) :: nja !< number of GWT connections
322  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
323  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
324  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
325  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
326  ! -- local
327  integer(I4B) :: n, idiag
328  real(DP) :: tled
329  real(DP) :: hhcof, rrhs
330  real(DP) :: swt, swtpdt
331  real(DP) :: vcell
332  real(DP) :: const1
333  real(DP) :: const2
334  real(DP) :: volfracm
335  real(DP) :: rhobm
336  !
337  ! -- set variables
338  tled = done / delt
339  !
340  ! -- loop through and calculate sorption contribution to hcof and rhs
341  do n = 1, this%dis%nodes
342  !
343  ! -- skip if transport inactive
344  if (this%ibound(n) <= 0) cycle
345  !
346  ! -- assign variables
347  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
348  swtpdt = this%fmi%gwfsat(n)
349  swt = this%fmi%gwfsatold(n, delt)
350  idiag = this%dis%con%ia(n)
351  const1 = this%distcoef(n)
352  const2 = 0.
353  if (this%isrb > 1) const2 = this%sp2(n)
354  volfracm = this%get_volfracm(n)
355  rhobm = this%bulk_density(n)
356  call mst_srb_term(this%isrb, volfracm, rhobm, vcell, tled, cnew(n), &
357  cold(n), swtpdt, swt, const1, const2, &
358  hcofval=hhcof, rhsval=rrhs)
359  !
360  ! -- Add hhcof to diagonal and rrhs to right-hand side
361  call matrix_sln%add_value_pos(idxglo(idiag), hhcof)
362  rhs(n) = rhs(n) + rrhs
363  !
364  end do
365  end subroutine mst_fc_srb
366 
367  !> @ brief Calculate sorption terms
368  !!
369  !! Subroutine to calculate sorption terms
370  !!
371  !<
372  subroutine mst_srb_term(isrb, volfracm, rhobm, vcell, tled, cnew, cold, &
373  swnew, swold, const1, const2, rate, hcofval, rhsval)
374  ! -- modules
375  ! -- dummy
376  integer(I4B), intent(in) :: isrb !< sorption flag 1, 2, 3 are linear, freundlich, and langmuir
377  real(DP), intent(in) :: volfracm !< volume fraction of mobile domain (fhat_m)
378  real(DP), intent(in) :: rhobm !< bulk density of mobile domain (rhob_m)
379  real(DP), intent(in) :: vcell !< volume of cell
380  real(DP), intent(in) :: tled !< one over time step length
381  real(DP), intent(in) :: cnew !< concentration at end of this time step
382  real(DP), intent(in) :: cold !< concentration at end of last time step
383  real(DP), intent(in) :: swnew !< cell saturation at end of this time step
384  real(DP), intent(in) :: swold !< cell saturation at end of last time step
385  real(DP), intent(in) :: const1 !< distribution coefficient or freundlich or langmuir constant
386  real(DP), intent(in) :: const2 !< zero, freundlich exponent, or langmuir sorption sites
387  real(DP), intent(out), optional :: rate !< calculated sorption rate
388  real(DP), intent(out), optional :: hcofval !< diagonal contribution to solution coefficient matrix
389  real(DP), intent(out), optional :: rhsval !< contribution to solution right-hand-side
390  ! -- local
391  real(DP) :: term
392  real(DP) :: derv
393  real(DP) :: cbarnew
394  real(DP) :: cbarold
395  real(DP) :: cavg
396  real(DP) :: cbaravg
397  real(DP) :: swavg
398  !
399  ! -- Calculate based on type of sorption
400  if (isrb == 1) then
401  ! -- linear
402  term = -volfracm * rhobm * vcell * tled * const1
403  if (present(hcofval)) hcofval = term * swnew
404  if (present(rhsval)) rhsval = term * swold * cold
405  if (present(rate)) rate = term * swnew * cnew - term * swold * cold
406  else
407  !
408  ! -- calculate average aqueous concentration
409  cavg = dhalf * (cold + cnew)
410  !
411  ! -- set values based on isotherm
412  if (isrb == 2) then
413  ! -- freundlich
414  cbarnew = get_freundlich_conc(cnew, const1, const2)
415  cbarold = get_freundlich_conc(cold, const1, const2)
416  derv = get_freundlich_derivative(cavg, const1, const2)
417  else if (isrb == 3) then
418  ! -- langmuir
419  cbarnew = get_langmuir_conc(cnew, const1, const2)
420  cbarold = get_langmuir_conc(cold, const1, const2)
421  derv = get_langmuir_derivative(cavg, const1, const2)
422  end if
423  !
424  ! -- calculate hcof, rhs, and rate for freundlich and langmuir
425  term = -volfracm * rhobm * vcell * tled
426  cbaravg = (cbarold + cbarnew) * dhalf
427  swavg = (swnew + swold) * dhalf
428  if (present(hcofval)) then
429  hcofval = term * derv * swavg
430  end if
431  if (present(rhsval)) then
432  rhsval = term * derv * swavg * cold - term * cbaravg * (swnew - swold)
433  end if
434  if (present(rate)) then
435  rate = term * derv * swavg * (cnew - cold) &
436  + term * cbaravg * (swnew - swold)
437  end if
438  end if
439  end subroutine mst_srb_term
440 
441  !> @ brief Fill sorption-decay coefficient method for package
442  !!
443  !! Method to calculate and fill sorption-decay coefficients for the package.
444  !!
445  !<
446  subroutine mst_fc_dcy_srb(this, nodes, cold, nja, matrix_sln, idxglo, &
447  rhs, cnew, kiter)
448  ! -- modules
449  use tdismodule, only: delt
450  ! -- dummy
451  class(gwtmsttype) :: this !< GwtMstType object
452  integer, intent(in) :: nodes !< number of nodes
453  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
454  integer(I4B), intent(in) :: nja !< number of GWT connections
455  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
456  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
457  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
458  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
459  integer(I4B), intent(in) :: kiter !< solution outer iteration number
460  ! -- local
461  integer(I4B) :: n, idiag
462  real(DP) :: hhcof, rrhs
463  real(DP) :: vcell
464  real(DP) :: swnew
465  real(DP) :: distcoef
466  real(DP) :: volfracm
467  real(DP) :: rhobm
468  real(DP) :: term
469  real(DP) :: csrb
470  real(DP) :: decay_rate
471  real(DP) :: csrbold
472  real(DP) :: csrbnew
473  !
474  ! -- loop through and calculate sorption contribution to hcof and rhs
475  do n = 1, this%dis%nodes
476  !
477  ! -- skip if transport inactive
478  if (this%ibound(n) <= 0) cycle
479  !
480  ! -- set variables
481  hhcof = dzero
482  rrhs = dzero
483  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
484  swnew = this%fmi%gwfsat(n)
485  distcoef = this%distcoef(n)
486  idiag = this%dis%con%ia(n)
487  volfracm = this%get_volfracm(n)
488  rhobm = this%bulk_density(n)
489  term = this%decay_sorbed(n) * volfracm * rhobm * swnew * vcell
490  !
491  ! -- add sorbed mass decay rate terms to accumulators
492  if (this%idcy == 1) then
493  !
494  if (this%isrb == 1) then
495  !
496  ! -- first order decay rate is a function of concentration, so add
497  ! to left hand side
498  hhcof = -term * distcoef
499  else if (this%isrb == 2) then
500  !
501  ! -- nonlinear Freundlich sorption, so add to RHS
502  csrb = get_freundlich_conc(cnew(n), distcoef, this%sp2(n))
503  rrhs = term * csrb
504  else if (this%isrb == 3) then
505  !
506  ! -- nonlinear Lanmuir sorption, so add to RHS
507  csrb = get_langmuir_conc(cnew(n), distcoef, this%sp2(n))
508  rrhs = term * csrb
509  end if
510  elseif (this%idcy == 2) then
511  !
512  ! -- Call function to get zero-order decay rate, which may be changed
513  ! from the user-specified rate to prevent negative concentrations
514  if (distcoef > dzero) then
515 
516  if (this%isrb == 1) then
517  csrbold = cold(n) * distcoef
518  csrbnew = cnew(n) * distcoef
519  else if (this%isrb == 2) then
520  csrbold = get_freundlich_conc(cold(n), distcoef, this%sp2(n))
521  csrbnew = get_freundlich_conc(cnew(n), distcoef, this%sp2(n))
522  else if (this%isrb == 3) then
523  csrbold = get_langmuir_conc(cold(n), distcoef, this%sp2(n))
524  csrbnew = get_langmuir_conc(cnew(n), distcoef, this%sp2(n))
525  end if
526 
527  decay_rate = get_zero_order_decay(this%decay_sorbed(n), &
528  this%decayslast(n), &
529  kiter, csrbold, csrbnew, delt)
530  this%decayslast(n) = decay_rate
531  rrhs = decay_rate * volfracm * rhobm * swnew * vcell
532  end if
533 
534  end if
535  !
536  ! -- Add hhcof to diagonal and rrhs to right-hand side
537  call matrix_sln%add_value_pos(idxglo(idiag), hhcof)
538  rhs(n) = rhs(n) + rrhs
539  !
540  end do
541  end subroutine mst_fc_dcy_srb
542 
543  !> @ brief Calculate flows for package
544  !!
545  !! Method to calculate flows for the package.
546  !!
547  !<
548  subroutine mst_cq(this, nodes, cnew, cold, flowja)
549  ! -- modules
550  ! -- dummy
551  class(gwtmsttype) :: this !< GwtMstType object
552  integer(I4B), intent(in) :: nodes !< number of nodes
553  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
554  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
555  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
556  ! -- local
557  !
558  ! - storage
559  call this%mst_cq_sto(nodes, cnew, cold, flowja)
560  !
561  ! -- decay
562  if (this%idcy /= 0) then
563  call this%mst_cq_dcy(nodes, cnew, cold, flowja)
564  end if
565  !
566  ! -- sorption
567  if (this%isrb /= 0) then
568  call this%mst_cq_srb(nodes, cnew, cold, flowja)
569  end if
570  !
571  ! -- decay sorbed
572  if (this%isrb /= 0 .and. this%idcy /= 0) then
573  call this%mst_cq_dcy_srb(nodes, cnew, cold, flowja)
574  end if
575  !
576  ! -- calculate csrb
577  if (this%isrb /= 0) then
578  call this%mst_calc_csrb(cnew)
579  end if
580  end subroutine mst_cq
581 
582  !> @ brief Calculate storage terms for package
583  !!
584  !! Method to calculate storage terms for the package.
585  !!
586  !<
587  subroutine mst_cq_sto(this, nodes, cnew, cold, flowja)
588  ! -- modules
589  use tdismodule, only: delt
590  ! -- dummy
591  class(gwtmsttype) :: this !< GwtMstType object
592  integer(I4B), intent(in) :: nodes !< number of nodes
593  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
594  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
595  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
596  ! -- local
597  integer(I4B) :: n
598  integer(I4B) :: idiag
599  real(DP) :: rate
600  real(DP) :: tled
601  real(DP) :: vnew, vold
602  real(DP) :: hhcof, rrhs
603  !
604  ! -- initialize
605  tled = done / delt
606  !
607  ! -- Calculate storage change
608  do n = 1, nodes
609  this%ratesto(n) = dzero
610  !
611  ! -- skip if transport inactive
612  if (this%ibound(n) <= 0) cycle
613  !
614  ! -- calculate new and old water volumes
615  vnew = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n)) * &
616  this%fmi%gwfsat(n) * this%thetam(n)
617  vold = vnew
618  if (this%fmi%igwfstrgss /= 0) vold = vold + this%fmi%gwfstrgss(n) * delt
619  if (this%fmi%igwfstrgsy /= 0) vold = vold + this%fmi%gwfstrgsy(n) * delt
620  !
621  ! -- calculate rate
622  hhcof = -vnew * tled
623  rrhs = -vold * tled * cold(n)
624  rate = hhcof * cnew(n) - rrhs
625  this%ratesto(n) = rate
626  idiag = this%dis%con%ia(n)
627  flowja(idiag) = flowja(idiag) + rate
628  end do
629  end subroutine mst_cq_sto
630 
631  !> @ brief Calculate decay terms for package
632  !!
633  !! Method to calculate decay terms for the package.
634  !!
635  !<
636  subroutine mst_cq_dcy(this, nodes, cnew, cold, flowja)
637  ! -- modules
638  use tdismodule, only: delt
639  ! -- dummy
640  class(gwtmsttype) :: this !< GwtMstType object
641  integer(I4B), intent(in) :: nodes !< number of nodes
642  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
643  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
644  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
645  ! -- local
646  integer(I4B) :: n
647  integer(I4B) :: idiag
648  real(DP) :: rate
649  real(DP) :: swtpdt
650  real(DP) :: hhcof, rrhs
651  real(DP) :: vcell
652  real(DP) :: decay_rate
653  !
654  ! -- initialize
655  !
656  ! -- Calculate decay change
657  do n = 1, nodes
658  !
659  ! -- skip if transport inactive
660  this%ratedcy(n) = dzero
661  if (this%ibound(n) <= 0) cycle
662  !
663  ! -- calculate new and old water volumes
664  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
665  swtpdt = this%fmi%gwfsat(n)
666  !
667  ! -- calculate decay gains and losses
668  rate = dzero
669  hhcof = dzero
670  rrhs = dzero
671  if (this%idcy == 1) then
672  hhcof = -this%decay(n) * vcell * swtpdt * this%thetam(n)
673  elseif (this%idcy == 2) then
674  decay_rate = get_zero_order_decay(this%decay(n), this%decaylast(n), &
675  0, cold(n), cnew(n), delt)
676  rrhs = decay_rate * vcell * swtpdt * this%thetam(n)
677  end if
678  rate = hhcof * cnew(n) - rrhs
679  this%ratedcy(n) = rate
680  idiag = this%dis%con%ia(n)
681  flowja(idiag) = flowja(idiag) + rate
682  !
683  end do
684  end subroutine mst_cq_dcy
685 
686  !> @ brief Calculate sorption terms for package
687  !!
688  !! Method to calculate sorption terms for the package.
689  !!
690  !<
691  subroutine mst_cq_srb(this, nodes, cnew, cold, flowja)
692  ! -- modules
693  use tdismodule, only: delt
694  ! -- dummy
695  class(gwtmsttype) :: this !< GwtMstType object
696  integer(I4B), intent(in) :: nodes !< number of nodes
697  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
698  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
699  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
700  ! -- local
701  integer(I4B) :: n
702  integer(I4B) :: idiag
703  real(DP) :: rate
704  real(DP) :: tled
705  real(DP) :: swt, swtpdt
706  real(DP) :: vcell
707  real(DP) :: volfracm
708  real(DP) :: rhobm
709  real(DP) :: const1
710  real(DP) :: const2
711  !
712  ! -- initialize
713  tled = done / delt
714  !
715  ! -- Calculate sorption change
716  do n = 1, nodes
717  !
718  ! -- initialize rates
719  this%ratesrb(n) = dzero
720  !
721  ! -- skip if transport inactive
722  if (this%ibound(n) <= 0) cycle
723  !
724  ! -- assign variables
725  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
726  swtpdt = this%fmi%gwfsat(n)
727  swt = this%fmi%gwfsatold(n, delt)
728  volfracm = this%get_volfracm(n)
729  rhobm = this%bulk_density(n)
730  const1 = this%distcoef(n)
731  const2 = 0.
732  if (this%isrb > 1) const2 = this%sp2(n)
733  call mst_srb_term(this%isrb, volfracm, rhobm, vcell, tled, cnew(n), &
734  cold(n), swtpdt, swt, const1, const2, &
735  rate=rate)
736  this%ratesrb(n) = rate
737  idiag = this%dis%con%ia(n)
738  flowja(idiag) = flowja(idiag) + rate
739  !
740  end do
741  end subroutine mst_cq_srb
742 
743  !> @ brief Calculate decay-sorption terms for package
744  !!
745  !! Method to calculate decay-sorption terms for the package.
746  !!
747  !<
748  subroutine mst_cq_dcy_srb(this, nodes, cnew, cold, flowja)
749  ! -- modules
750  use tdismodule, only: delt
751  ! -- dummy
752  class(gwtmsttype) :: this !< GwtMstType object
753  integer(I4B), intent(in) :: nodes !< number of nodes
754  real(DP), intent(in), dimension(nodes) :: cnew !< concentration at end of this time step
755  real(DP), intent(in), dimension(nodes) :: cold !< concentration at end of last time step
756  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
757  ! -- local
758  integer(I4B) :: n
759  integer(I4B) :: idiag
760  real(DP) :: rate
761  real(DP) :: hhcof, rrhs
762  real(DP) :: vcell
763  real(DP) :: swnew
764  real(DP) :: distcoef
765  real(DP) :: volfracm
766  real(DP) :: rhobm
767  real(DP) :: term
768  real(DP) :: csrb
769  real(DP) :: csrbnew
770  real(DP) :: csrbold
771  real(DP) :: decay_rate
772  !
773  ! -- Calculate sorbed decay change
774  ! This routine will only be called if sorption and decay are active
775  do n = 1, nodes
776  !
777  ! -- initialize rates
778  this%ratedcys(n) = dzero
779  !
780  ! -- skip if transport inactive
781  if (this%ibound(n) <= 0) cycle
782  !
783  ! -- set variables
784  hhcof = dzero
785  rrhs = dzero
786  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
787  swnew = this%fmi%gwfsat(n)
788  distcoef = this%distcoef(n)
789  volfracm = this%get_volfracm(n)
790  rhobm = this%bulk_density(n)
791  term = this%decay_sorbed(n) * volfracm * rhobm * swnew * vcell
792  !
793  ! -- add sorbed mass decay rate terms to accumulators
794  if (this%idcy == 1) then
795  !
796  if (this%isrb == 1) then
797  !
798  ! -- first order decay rate is a function of concentration, so add
799  ! to left hand side
800  hhcof = -term * distcoef
801  else if (this%isrb == 2) then
802  !
803  ! -- nonlinear Freundlich sorption, so add to RHS
804  csrb = get_freundlich_conc(cnew(n), distcoef, this%sp2(n))
805  rrhs = term * csrb
806  else if (this%isrb == 3) then
807  !
808  ! -- nonlinear Lanmuir sorption, so add to RHS
809  csrb = get_langmuir_conc(cnew(n), distcoef, this%sp2(n))
810  rrhs = term * csrb
811  end if
812  elseif (this%idcy == 2) then
813  !
814  ! -- Call function to get zero-order decay rate, which may be changed
815  ! from the user-specified rate to prevent negative concentrations
816  if (distcoef > dzero) then
817  if (this%isrb == 1) then
818  csrbold = cold(n) * distcoef
819  csrbnew = cnew(n) * distcoef
820  else if (this%isrb == 2) then
821  csrbold = get_freundlich_conc(cold(n), distcoef, this%sp2(n))
822  csrbnew = get_freundlich_conc(cnew(n), distcoef, this%sp2(n))
823  else if (this%isrb == 3) then
824  csrbold = get_langmuir_conc(cold(n), distcoef, this%sp2(n))
825  csrbnew = get_langmuir_conc(cnew(n), distcoef, this%sp2(n))
826  end if
827  decay_rate = get_zero_order_decay(this%decay_sorbed(n), &
828  this%decayslast(n), &
829  0, csrbold, csrbnew, delt)
830  rrhs = decay_rate * volfracm * rhobm * swnew * vcell
831  end if
832  end if
833  !
834  ! -- calculate rate
835  rate = hhcof * cnew(n) - rrhs
836  this%ratedcys(n) = rate
837  idiag = this%dis%con%ia(n)
838  flowja(idiag) = flowja(idiag) + rate
839  !
840  end do
841  end subroutine mst_cq_dcy_srb
842 
843  !> @ brief Calculate sorbed concentration
844  !<
845  subroutine mst_calc_csrb(this, cnew)
846  ! -- dummy
847  class(gwtmsttype) :: this !< GwtMstType object
848  real(DP), intent(in), dimension(:) :: cnew !< concentration at end of this time step
849  ! -- local
850  integer(I4B) :: n
851  real(DP) :: distcoef
852  real(DP) :: csrb
853 
854  ! Calculate sorbed concentration
855  do n = 1, size(cnew)
856  csrb = dzero
857  if (this%ibound(n) > 0) then
858  distcoef = this%distcoef(n)
859  if (this%isrb == 1) then
860  csrb = cnew(n) * distcoef
861  else if (this%isrb == 2) then
862  csrb = get_freundlich_conc(cnew(n), distcoef, this%sp2(n))
863  else if (this%isrb == 3) then
864  csrb = get_langmuir_conc(cnew(n), distcoef, this%sp2(n))
865  end if
866  end if
867  this%csrb(n) = csrb
868  end do
869 
870  end subroutine mst_calc_csrb
871 
872  !> @ brief Calculate budget terms for package
873  !<
874  subroutine mst_bd(this, isuppress_output, model_budget)
875  ! -- modules
876  use tdismodule, only: delt
878  ! -- dummy
879  class(gwtmsttype) :: this !< GwtMstType object
880  integer(I4B), intent(in) :: isuppress_output !< flag to suppress output
881  type(budgettype), intent(inout) :: model_budget !< model budget object
882  ! -- local
883  real(DP) :: rin
884  real(DP) :: rout
885  !
886  ! -- sto
887  call rate_accumulator(this%ratesto, rin, rout)
888  call model_budget%addentry(rin, rout, delt, budtxt(1), &
889  isuppress_output, rowlabel=this%packName)
890  !
891  ! -- dcy
892  if (this%idcy /= 0) then
893  call rate_accumulator(this%ratedcy, rin, rout)
894  call model_budget%addentry(rin, rout, delt, budtxt(2), &
895  isuppress_output, rowlabel=this%packName)
896  end if
897  !
898  ! -- srb
899  if (this%isrb /= 0) then
900  call rate_accumulator(this%ratesrb, rin, rout)
901  call model_budget%addentry(rin, rout, delt, budtxt(3), &
902  isuppress_output, rowlabel=this%packName)
903  end if
904  !
905  ! -- srb dcy
906  if (this%isrb /= 0 .and. this%idcy /= 0) then
907  call rate_accumulator(this%ratedcys, rin, rout)
908  call model_budget%addentry(rin, rout, delt, budtxt(4), &
909  isuppress_output, rowlabel=this%packName)
910  end if
911  end subroutine mst_bd
912 
913  !> @ brief Output flow terms for package
914  !!
915  !! Method to output terms for the package.
916  !!
917  !<
918  subroutine mst_ot_flow(this, icbcfl, icbcun)
919  ! -- dummy
920  class(gwtmsttype) :: this !< GwtMstType object
921  integer(I4B), intent(in) :: icbcfl !< flag and unit number for cell-by-cell output
922  integer(I4B), intent(in) :: icbcun !< flag indication if cell-by-cell data should be saved
923  ! -- local
924  integer(I4B) :: ibinun
925  integer(I4B) :: iprint, nvaluesp, nwidthp
926  character(len=1) :: cdatafmp = ' ', editdesc = ' '
927  real(DP) :: dinact
928  !
929  ! -- Set unit number for binary output
930  if (this%ipakcb < 0) then
931  ibinun = icbcun
932  elseif (this%ipakcb == 0) then
933  ibinun = 0
934  else
935  ibinun = this%ipakcb
936  end if
937  if (icbcfl == 0) ibinun = 0
938  !
939  ! -- Record the storage rate if requested
940  if (ibinun /= 0) then
941  iprint = 0
942  dinact = dzero
943  !
944  ! -- sto
945  call this%dis%record_array(this%ratesto, this%iout, iprint, -ibinun, &
946  budtxt(1), cdatafmp, nvaluesp, &
947  nwidthp, editdesc, dinact)
948  !
949  ! -- dcy
950  if (this%idcy /= 0) &
951  call this%dis%record_array(this%ratedcy, this%iout, iprint, -ibinun, &
952  budtxt(2), cdatafmp, nvaluesp, &
953  nwidthp, editdesc, dinact)
954  !
955  ! -- srb
956  if (this%isrb /= 0) &
957  call this%dis%record_array(this%ratesrb, this%iout, iprint, -ibinun, &
958  budtxt(3), cdatafmp, nvaluesp, &
959  nwidthp, editdesc, dinact)
960  !
961  ! -- dcy srb
962  if (this%isrb /= 0 .and. this%idcy /= 0) &
963  call this%dis%record_array(this%ratedcys, this%iout, iprint, -ibinun, &
964  budtxt(4), cdatafmp, nvaluesp, &
965  nwidthp, editdesc, dinact)
966  end if
967  end subroutine mst_ot_flow
968 
969  !> @brief Save sorbate concentration array to binary file
970  !<
971  subroutine mst_ot_dv(this, idvsave)
972  ! -- dummy
973  class(gwtmsttype) :: this
974  integer(I4B), intent(in) :: idvsave
975  ! -- local
976  character(len=1) :: cdatafmp = ' ', editdesc = ' '
977  integer(I4B) :: ibinun
978  integer(I4B) :: iprint
979  integer(I4B) :: nvaluesp
980  integer(I4B) :: nwidthp
981  real(DP) :: dinact
982 
983  ! Set unit number for sorbate output
984  if (this%ioutsorbate /= 0) then
985  ibinun = 1
986  else
987  ibinun = 0
988  end if
989  if (idvsave == 0) ibinun = 0
990 
991  ! save sorbate concentration array
992  if (ibinun /= 0) then
993  iprint = 0
994  dinact = dhnoflo
995  if (this%ioutsorbate /= 0) then
996  ibinun = this%ioutsorbate
997  call this%dis%record_array(this%csrb, this%iout, iprint, ibinun, &
998  ' SORBATE', cdatafmp, nvaluesp, &
999  nwidthp, editdesc, dinact)
1000  end if
1001  end if
1002 
1003  end subroutine mst_ot_dv
1004 
1005  !> @ brief Deallocate
1006  !!
1007  !! Method to deallocate memory for the package.
1008  !!
1009  !<
1010  subroutine mst_da(this)
1011  ! -- modules
1013  ! -- dummy
1014  class(gwtmsttype) :: this !< GwtMstType object
1015  !
1016  ! -- Deallocate arrays if package was active
1017  if (this%inunit > 0) then
1018  call mem_deallocate(this%porosity)
1019  call mem_deallocate(this%thetam)
1020  call mem_deallocate(this%volfracim)
1021  call mem_deallocate(this%ratesto)
1022  call mem_deallocate(this%idcy)
1023  call mem_deallocate(this%decay)
1024  call mem_deallocate(this%decay_sorbed)
1025  call mem_deallocate(this%ratedcy)
1026  call mem_deallocate(this%decaylast)
1027  call mem_deallocate(this%decayslast)
1028  call mem_deallocate(this%isrb)
1029  call mem_deallocate(this%ioutsorbate)
1030  call mem_deallocate(this%bulk_density)
1031  call mem_deallocate(this%distcoef)
1032  call mem_deallocate(this%sp2)
1033  call mem_deallocate(this%ratesrb)
1034  call mem_deallocate(this%csrb)
1035  call mem_deallocate(this%ratedcys)
1036  this%ibound => null()
1037  this%fmi => null()
1038  end if
1039  !
1040  ! -- Scalars
1041  !
1042  ! -- deallocate parent
1043  call this%NumericalPackageType%da()
1044  end subroutine mst_da
1045 
1046  !> @ brief Allocate scalar variables for package
1047  !!
1048  !! Method to allocate scalar variables for the package.
1049  !!
1050  !<
1051  subroutine allocate_scalars(this)
1052  ! -- modules
1054  ! -- dummy
1055  class(gwtmsttype) :: this !< GwtMstType object
1056  ! -- local
1057  !
1058  ! -- Allocate scalars in NumericalPackageType
1059  call this%NumericalPackageType%allocate_scalars()
1060  !
1061  ! -- Allocate
1062  call mem_allocate(this%isrb, 'ISRB', this%memoryPath)
1063  call mem_allocate(this%ioutsorbate, 'IOUTSORBATE', this%memoryPath)
1064  call mem_allocate(this%idcy, 'IDCY', this%memoryPath)
1065  !
1066  ! -- Initialize
1067  this%isrb = 0
1068  this%ioutsorbate = 0
1069  this%idcy = 0
1070  end subroutine allocate_scalars
1071 
1072  !> @ brief Allocate arrays for package
1073  !!
1074  !! Method to allocate arrays for the package.
1075  !!
1076  !<
1077  subroutine allocate_arrays(this, nodes)
1078  ! -- modules
1080  use constantsmodule, only: dzero
1081  ! -- dummy
1082  class(gwtmsttype) :: this !< GwtMstType object
1083  integer(I4B), intent(in) :: nodes !< number of nodes
1084  ! -- local
1085  integer(I4B) :: n
1086  !
1087  ! -- Allocate
1088  ! -- sto
1089  call mem_allocate(this%porosity, nodes, 'POROSITY', this%memoryPath)
1090  call mem_allocate(this%thetam, nodes, 'THETAM', this%memoryPath)
1091  call mem_allocate(this%volfracim, nodes, 'VOLFRACIM', this%memoryPath)
1092  call mem_allocate(this%ratesto, nodes, 'RATESTO', this%memoryPath)
1093  !
1094  ! -- dcy
1095  if (this%idcy == 0) then
1096  call mem_allocate(this%ratedcy, 1, 'RATEDCY', this%memoryPath)
1097  call mem_allocate(this%decay, 1, 'DECAY', this%memoryPath)
1098  call mem_allocate(this%decaylast, 1, 'DECAYLAST', this%memoryPath)
1099  else
1100  call mem_allocate(this%ratedcy, this%dis%nodes, 'RATEDCY', this%memoryPath)
1101  call mem_allocate(this%decay, nodes, 'DECAY', this%memoryPath)
1102  call mem_allocate(this%decaylast, nodes, 'DECAYLAST', this%memoryPath)
1103  end if
1104  if (this%idcy /= 0 .and. this%isrb /= 0) then
1105  call mem_allocate(this%ratedcys, this%dis%nodes, 'RATEDCYS', &
1106  this%memoryPath)
1107  call mem_allocate(this%decayslast, this%dis%nodes, 'DECAYSLAST', &
1108  this%memoryPath)
1109  else
1110  call mem_allocate(this%ratedcys, 1, 'RATEDCYS', this%memoryPath)
1111  call mem_allocate(this%decayslast, 1, 'DECAYSLAST', this%memoryPath)
1112  end if
1113  call mem_allocate(this%decay_sorbed, 1, 'DECAY_SORBED', &
1114  this%memoryPath)
1115  !
1116  ! -- srb
1117  if (this%isrb == 0) then
1118  call mem_allocate(this%bulk_density, 1, 'BULK_DENSITY', this%memoryPath)
1119  call mem_allocate(this%sp2, 1, 'SP2', this%memoryPath)
1120  call mem_allocate(this%distcoef, 1, 'DISTCOEF', this%memoryPath)
1121  call mem_allocate(this%ratesrb, 1, 'RATESRB', this%memoryPath)
1122  call mem_allocate(this%csrb, 1, 'CSRB', this%memoryPath)
1123  else
1124  call mem_allocate(this%bulk_density, nodes, 'BULK_DENSITY', this%memoryPath)
1125  call mem_allocate(this%distcoef, nodes, 'DISTCOEF', this%memoryPath)
1126  call mem_allocate(this%ratesrb, nodes, 'RATESRB', this%memoryPath)
1127  call mem_allocate(this%csrb, nodes, 'CSRB', this%memoryPath)
1128  if (this%isrb == 1) then
1129  call mem_allocate(this%sp2, 1, 'SP2', this%memoryPath)
1130  else
1131  call mem_allocate(this%sp2, nodes, 'SP2', this%memoryPath)
1132  end if
1133  end if
1134  !
1135  ! -- Initialize
1136  do n = 1, nodes
1137  this%porosity(n) = dzero
1138  this%thetam(n) = dzero
1139  this%volfracim(n) = dzero
1140  this%ratesto(n) = dzero
1141  end do
1142  do n = 1, size(this%decay)
1143  this%decay(n) = dzero
1144  this%ratedcy(n) = dzero
1145  this%decaylast(n) = dzero
1146  end do
1147  do n = 1, size(this%bulk_density)
1148  this%bulk_density(n) = dzero
1149  this%distcoef(n) = dzero
1150  this%ratesrb(n) = dzero
1151  this%csrb(n) = dzero
1152  end do
1153  do n = 1, size(this%sp2)
1154  this%sp2(n) = dzero
1155  end do
1156  do n = 1, size(this%ratedcys)
1157  this%ratedcys(n) = dzero
1158  this%decayslast(n) = dzero
1159  end do
1160  end subroutine allocate_arrays
1161 
1162  !> @ brief Read options for package
1163  !!
1164  !! Method to read options for the package.
1165  !!
1166  !<
1167  subroutine read_options(this)
1168  ! -- modules
1169  use openspecmodule, only: access, form
1170  use inputoutputmodule, only: getunit, openfile
1171  ! -- dummy
1172  class(gwtmsttype) :: this !< GwtMstType object
1173  ! -- local
1174  character(len=LINELENGTH) :: keyword
1175  character(len=LINELENGTH) :: sorption
1176  character(len=MAXCHARLEN) :: fname
1177  integer(I4B) :: ierr
1178  logical :: isfound, endOfBlock
1179  ! -- formats
1180  character(len=*), parameter :: fmtisvflow = &
1181  "(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY FILE &
1182  &WHENEVER ICBCFL IS NOT ZERO.')"
1183  character(len=*), parameter :: fmtlinear = &
1184  &"(4x,'LINEAR SORPTION IS ACTIVE. ')"
1185  character(len=*), parameter :: fmtfreundlich = &
1186  &"(4x,'FREUNDLICH SORPTION IS ACTIVE. ')"
1187  character(len=*), parameter :: fmtlangmuir = &
1188  &"(4x,'LANGMUIR SORPTION IS ACTIVE. ')"
1189  character(len=*), parameter :: fmtidcy1 = &
1190  &"(4x,'FIRST-ORDER DECAY IS ACTIVE. ')"
1191  character(len=*), parameter :: fmtidcy2 = &
1192  &"(4x,'ZERO-ORDER DECAY IS ACTIVE. ')"
1193  character(len=*), parameter :: fmtfileout = &
1194  "(4x,'MST ',1x,a,1x,' WILL BE SAVED TO FILE: ',a,/4x,&
1195  &'OPENED ON UNIT: ',I7)"
1196  !
1197  ! -- get options block
1198  call this%parser%GetBlock('OPTIONS', isfound, ierr, blockrequired=.false., &
1199  supportopenclose=.true.)
1200  !
1201  ! -- parse options block if detected
1202  if (isfound) then
1203  write (this%iout, '(1x,a)') 'PROCESSING MOBILE STORAGE AND TRANSFER OPTIONS'
1204  do
1205  call this%parser%GetNextLine(endofblock)
1206  if (endofblock) exit
1207  call this%parser%GetStringCaps(keyword)
1208  select case (keyword)
1209  case ('SAVE_FLOWS')
1210  this%ipakcb = -1
1211  write (this%iout, fmtisvflow)
1212  case ('SORBTION')
1213  call store_error('SORBTION is not a valid option. Use &
1214  &SORPTION instead.')
1215  call this%parser%StoreErrorUnit()
1216  case ('SORPTION')
1217  call this%parser%GetStringCaps(sorption)
1218  select case (sorption)
1219  case ('LINEAR', '')
1220  this%isrb = 1
1221  write (this%iout, fmtlinear)
1222  case ('FREUNDLICH')
1223  this%isrb = 2
1224  write (this%iout, fmtfreundlich)
1225  case ('LANGMUIR')
1226  this%isrb = 3
1227  write (this%iout, fmtlangmuir)
1228  case default
1229  call store_error('Unknown sorption type was specified ' &
1230  & //'('//trim(adjustl(sorption))//').'// &
1231  &' Sorption must be specified as LINEAR, &
1232  &FREUNDLICH, or LANGMUIR.')
1233  call this%parser%StoreErrorUnit()
1234  end select
1235  case ('FIRST_ORDER_DECAY')
1236  this%idcy = 1
1237  write (this%iout, fmtidcy1)
1238  case ('ZERO_ORDER_DECAY')
1239  this%idcy = 2
1240  write (this%iout, fmtidcy2)
1241  case ('SORBATE')
1242  call this%parser%GetStringCaps(keyword)
1243  if (keyword == 'FILEOUT') then
1244  call this%parser%GetString(fname)
1245  this%ioutsorbate = getunit()
1246  call openfile(this%ioutsorbate, this%iout, fname, 'DATA(BINARY)', &
1247  form, access, 'REPLACE', mode_opt=mnormal)
1248  write (this%iout, fmtfileout) &
1249  'SORBATE', fname, this%ioutsorbate
1250  else
1251  errmsg = 'Optional SORBATE keyword must be '// &
1252  'followed by FILEOUT.'
1253  call store_error(errmsg)
1254  end if
1255  case default
1256  write (errmsg, '(a,a)') 'Unknown MST option: ', trim(keyword)
1257  call store_error(errmsg)
1258  call this%parser%StoreErrorUnit()
1259  end select
1260  end do
1261  write (this%iout, '(1x,a)') 'END OF MOBILE STORAGE AND TRANSFER OPTIONS'
1262  end if
1263  end subroutine read_options
1264 
1265  !> @ brief Read data for package
1266  !!
1267  !! Method to read data for the package.
1268  !!
1269  !<
1270  subroutine read_data(this)
1271  ! -- modules
1272  use constantsmodule, only: linelength
1274  ! -- dummy
1275  class(gwtmsttype) :: this !< GwtMstType object
1276  ! -- local
1277  character(len=LINELENGTH) :: keyword
1278  character(len=:), allocatable :: line
1279  integer(I4B) :: istart, istop, lloc, ierr, n
1280  logical :: isfound, endOfBlock
1281  logical, dimension(6) :: lname
1282  character(len=24), dimension(6) :: aname
1283  ! -- formats
1284  ! -- data
1285  data aname(1)/' MOBILE DOMAIN POROSITY'/
1286  data aname(2)/' BULK DENSITY'/
1287  data aname(3)/'DISTRIBUTION COEFFICIENT'/
1288  data aname(4)/' DECAY RATE'/
1289  data aname(5)/' DECAY SORBED RATE'/
1290  data aname(6)/' SECOND SORPTION PARAM'/
1291  !
1292  ! -- initialize
1293  isfound = .false.
1294  lname(:) = .false.
1295  !
1296  ! -- get griddata block
1297  call this%parser%GetBlock('GRIDDATA', isfound, ierr)
1298  if (isfound) then
1299  write (this%iout, '(1x,a)') 'PROCESSING GRIDDATA'
1300  do
1301  call this%parser%GetNextLine(endofblock)
1302  if (endofblock) exit
1303  call this%parser%GetStringCaps(keyword)
1304  call this%parser%GetRemainingLine(line)
1305  lloc = 1
1306  select case (keyword)
1307  case ('POROSITY')
1308  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
1309  this%parser%iuactive, this%porosity, &
1310  aname(1))
1311  lname(1) = .true.
1312  case ('BULK_DENSITY')
1313  if (this%isrb == 0) &
1314  call mem_reallocate(this%bulk_density, this%dis%nodes, &
1315  'BULK_DENSITY', trim(this%memoryPath))
1316  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
1317  this%parser%iuactive, &
1318  this%bulk_density, aname(2))
1319  lname(2) = .true.
1320  case ('DISTCOEF')
1321  if (this%isrb == 0) &
1322  call mem_reallocate(this%distcoef, this%dis%nodes, 'DISTCOEF', &
1323  trim(this%memoryPath))
1324  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
1325  this%parser%iuactive, this%distcoef, &
1326  aname(3))
1327  lname(3) = .true.
1328  case ('DECAY')
1329  if (this%idcy == 0) &
1330  call mem_reallocate(this%decay, this%dis%nodes, 'DECAY', &
1331  trim(this%memoryPath))
1332  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
1333  this%parser%iuactive, this%decay, &
1334  aname(4))
1335  lname(4) = .true.
1336  case ('DECAY_SORBED')
1337  call mem_reallocate(this%decay_sorbed, this%dis%nodes, &
1338  'DECAY_SORBED', trim(this%memoryPath))
1339  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
1340  this%parser%iuactive, &
1341  this%decay_sorbed, aname(5))
1342  lname(5) = .true.
1343  case ('SP2')
1344  if (this%isrb < 2) &
1345  call mem_reallocate(this%sp2, this%dis%nodes, 'SP2', &
1346  trim(this%memoryPath))
1347  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
1348  this%parser%iuactive, this%sp2, &
1349  aname(6))
1350  lname(6) = .true.
1351  case default
1352  write (errmsg, '(a,a)') 'Unknown GRIDDATA tag: ', trim(keyword)
1353  call store_error(errmsg)
1354  call this%parser%StoreErrorUnit()
1355  end select
1356  end do
1357  write (this%iout, '(1x,a)') 'END PROCESSING GRIDDATA'
1358  else
1359  write (errmsg, '(a)') 'Required GRIDDATA block not found.'
1360  call store_error(errmsg)
1361  call this%parser%StoreErrorUnit()
1362  end if
1363  !
1364  ! -- Check for required porosity
1365  if (.not. lname(1)) then
1366  write (errmsg, '(a)') 'POROSITY not specified in GRIDDATA block.'
1367  call store_error(errmsg)
1368  end if
1369  !
1370  ! -- Check for required sorption variables
1371  if (this%isrb > 0) then
1372  if (.not. lname(2)) then
1373  write (errmsg, '(a)') 'Sorption is active but BULK_DENSITY &
1374  &not specified. BULK_DENSITY must be specified in GRIDDATA block.'
1375  call store_error(errmsg)
1376  end if
1377  if (.not. lname(3)) then
1378  write (errmsg, '(a)') 'Sorption is active but distribution &
1379  &coefficient not specified. DISTCOEF must be specified in &
1380  &GRIDDATA block.'
1381  call store_error(errmsg)
1382  end if
1383  if (this%isrb > 1) then
1384  if (.not. lname(6)) then
1385  write (errmsg, '(a)') 'Freundlich or langmuir sorption is active &
1386  &but SP2 not specified. SP2 must be specified in &
1387  &GRIDDATA block.'
1388  call store_error(errmsg)
1389  end if
1390  end if
1391  else
1392  if (lname(2)) then
1393  write (warnmsg, '(a)') 'Sorption is not active but &
1394  &BULK_DENSITY was specified. BULK_DENSITY will have no affect on &
1395  &simulation results.'
1396  call store_warning(warnmsg)
1397  write (this%iout, '(1x,a)') 'WARNING. '//warnmsg
1398  end if
1399  if (lname(3)) then
1400  write (warnmsg, '(a)') 'Sorption is not active but &
1401  &distribution coefficient was specified. DISTCOEF will have &
1402  &no affect on simulation results.'
1403  call store_warning(warnmsg)
1404  write (this%iout, '(1x,a)') 'WARNING. '//warnmsg
1405  end if
1406  if (lname(6)) then
1407  write (warnmsg, '(a)') 'Sorption is not active but &
1408  &SP2 was specified. SP2 will have &
1409  &no affect on simulation results.'
1410  call store_warning(warnmsg)
1411  write (this%iout, '(1x,a)') 'WARNING. '//warnmsg
1412  end if
1413  end if
1414  !
1415  ! -- Check for required decay/production rate coefficients
1416  if (this%idcy > 0) then
1417  if (.not. lname(4)) then
1418  write (errmsg, '(a)') 'First or zero order decay is &
1419  &active but the first rate coefficient is not specified. DECAY &
1420  &must be specified in GRIDDATA block.'
1421  call store_error(errmsg)
1422  end if
1423  if (.not. lname(5)) then
1424  !
1425  ! -- If DECAY_SORBED not specified and sorption is active, then
1426  ! terminate with an error
1427  if (this%isrb > 0) then
1428  write (errmsg, '(a)') 'DECAY_SORBED not provided in GRIDDATA &
1429  &block but decay and sorption are active. Specify DECAY_SORBED &
1430  &in GRIDDATA block.'
1431  call store_error(errmsg)
1432  end if
1433  end if
1434  else
1435  if (lname(4)) then
1436  write (warnmsg, '(a)') 'First- or zero-order decay &
1437  &is not active but decay was specified. DECAY will &
1438  &have no affect on simulation results.'
1439  call store_warning(warnmsg)
1440  write (this%iout, '(1x,a)') 'WARNING. '//warnmsg
1441  end if
1442  if (lname(5)) then
1443  write (warnmsg, '(a)') 'First- or zero-order decay &
1444  &is not active but DECAY_SORBED was specified. &
1445  &DECAY_SORBED will have no affect on simulation results.'
1446  call store_warning(warnmsg)
1447  write (this%iout, '(1x,a)') 'WARNING. '//warnmsg
1448  end if
1449  end if
1450  !
1451  ! -- terminate if errors
1452  if (count_errors() > 0) then
1453  call this%parser%StoreErrorUnit()
1454  end if
1455  !
1456  ! -- initialize thetam from porosity
1457  do n = 1, size(this%porosity)
1458  this%thetam(n) = this%porosity(n)
1459  end do
1460  end subroutine read_data
1461 
1462  !> @ brief Add volfrac values to volfracim
1463  !!
1464  !! Method to add immobile domain volume fracions, which are stored as a
1465  !! cumulative value in volfracim.
1466  !!
1467  !<
1468  subroutine addto_volfracim(this, volfracim)
1469  ! -- modules
1470  ! -- dummy
1471  class(gwtmsttype) :: this !< GwtMstType object
1472  real(DP), dimension(:), intent(in) :: volfracim !< immobile domain volume fraction that contributes to total immobile volume fraction
1473  ! -- local
1474  integer(I4B) :: n
1475  !
1476  ! -- Add to volfracim
1477  do n = 1, this%dis%nodes
1478  this%volfracim(n) = this%volfracim(n) + volfracim(n)
1479  end do
1480  !
1481  ! -- An immobile domain is adding a volume fraction, so update thetam
1482  ! accordingly.
1483  do n = 1, this%dis%nodes
1484  this%thetam(n) = this%get_volfracm(n) * this%porosity(n)
1485  end do
1486  end subroutine addto_volfracim
1487 
1488  !> @ brief Return mobile domain volume fraction
1489  !!
1490  !! Calculate and return the volume fraction of the aquifer that is mobile
1491  !!
1492  !<
1493  function get_volfracm(this, node) result(volfracm)
1494  ! -- modules
1495  ! -- dummy
1496  class(gwtmsttype) :: this !< GwtMstType object
1497  integer(I4B), intent(in) :: node !< node number
1498  ! -- return
1499  real(dp) :: volfracm
1500  !
1501  volfracm = done - this%volfracim(node)
1502  end function get_volfracm
1503 
1504  !> @ brief Calculate sorption concentration using Freundlich
1505  !!
1506  !! Function to calculate sorption concentration using Freundlich
1507  !!
1508  !<
1509  function get_freundlich_conc(conc, kf, a) result(cbar)
1510  ! -- dummy
1511  real(dp), intent(in) :: conc !< solute concentration
1512  real(dp), intent(in) :: kf !< freundlich constant
1513  real(dp), intent(in) :: a !< freundlich exponent
1514  ! -- return
1515  real(dp) :: cbar
1516  !
1517  if (conc > dzero) then
1518  cbar = kf * conc**a
1519  else
1520  cbar = dzero
1521  end if
1522  end function
1523 
1524  !> @ brief Calculate sorption concentration using Langmuir
1525  !!
1526  !! Function to calculate sorption concentration using Langmuir
1527  !!
1528  !<
1529  function get_langmuir_conc(conc, kl, sbar) result(cbar)
1530  ! -- dummy
1531  real(dp), intent(in) :: conc !< solute concentration
1532  real(dp), intent(in) :: kl !< langmuir constant
1533  real(dp), intent(in) :: sbar !< langmuir sorption sites
1534  ! -- return
1535  real(dp) :: cbar
1536  !
1537  if (conc > dzero) then
1538  cbar = (kl * sbar * conc) / (done + kl * conc)
1539  else
1540  cbar = dzero
1541  end if
1542  end function
1543 
1544  !> @ brief Calculate sorption derivative using Freundlich
1545  !!
1546  !! Function to calculate sorption derivative using Freundlich
1547  !!
1548  !<
1549  function get_freundlich_derivative(conc, kf, a) result(derv)
1550  ! -- dummy
1551  real(dp), intent(in) :: conc !< solute concentration
1552  real(dp), intent(in) :: kf !< freundlich constant
1553  real(dp), intent(in) :: a !< freundlich exponent
1554  ! -- return
1555  real(dp) :: derv
1556  !
1557  if (conc > dzero) then
1558  derv = kf * a * conc**(a - done)
1559  else
1560  derv = dzero
1561  end if
1562  end function
1563 
1564  !> @ brief Calculate sorption derivative using Langmuir
1565  !!
1566  !! Function to calculate sorption derivative using Langmuir
1567  !!
1568  !<
1569  function get_langmuir_derivative(conc, kl, sbar) result(derv)
1570  ! -- dummy
1571  real(dp), intent(in) :: conc !< solute concentration
1572  real(dp), intent(in) :: kl !< langmuir constant
1573  real(dp), intent(in) :: sbar !< langmuir sorption sites
1574  ! -- return
1575  real(dp) :: derv
1576  !
1577  if (conc > dzero) then
1578  derv = (kl * sbar) / (done + kl * conc)**dtwo
1579  else
1580  derv = dzero
1581  end if
1582  end function
1583 
1584  !> @ brief Get effective Freundlich distribution coefficient
1585  !<
1586  function get_freundlich_kd(conc, kf, a) result(kd)
1587  ! -- dummy
1588  real(dp), intent(in) :: conc !< solute concentration
1589  real(dp), intent(in) :: kf !< freundlich constant
1590  real(dp), intent(in) :: a !< freundlich exponent
1591  ! -- return
1592  real(dp) :: kd !< effective distribution coefficient
1593  !
1594  if (conc > dzero) then
1595  kd = kf * conc**(a - done)
1596  else
1597  kd = dzero
1598  end if
1599  end function get_freundlich_kd
1600 
1601  !> @ brief Get effective Langmuir distribution coefficient
1602  !<
1603  function get_langmuir_kd(conc, kl, sbar) result(kd)
1604  ! -- dummy
1605  real(dp), intent(in) :: conc !< solute concentration
1606  real(dp), intent(in) :: kl !< langmuir constant
1607  real(dp), intent(in) :: sbar !< langmuir sorption sites
1608  ! -- return
1609  real(dp) :: kd !< effective distribution coefficient
1610  !
1611  if (conc > dzero) then
1612  kd = (kl * sbar) / (done + kl * conc)
1613  else
1614  kd = dzero
1615  end if
1616  end function get_langmuir_kd
1617 
1618  !> @ brief Calculate zero-order decay rate and constrain if necessary
1619  !!
1620  !! Function to calculate the zero-order decay rate from the user specified
1621  !! decay rate. If the decay rate is positive, then the decay rate must
1622  !! be constrained so that more mass is not removed than is available.
1623  !! Without this constraint, negative concentrations could result from
1624  !! zero-order decay.
1625  !<
1626  function get_zero_order_decay(decay_rate_usr, decay_rate_last, kiter, &
1627  cold, cnew, delt) result(decay_rate)
1628  ! -- dummy
1629  real(dp), intent(in) :: decay_rate_usr !< user-entered decay rate
1630  real(dp), intent(in) :: decay_rate_last !< decay rate used for last iteration
1631  integer(I4B), intent(in) :: kiter !< Picard iteration counter
1632  real(dp), intent(in) :: cold !< concentration at end of last time step
1633  real(dp), intent(in) :: cnew !< concentration at end of this time step
1634  real(dp), intent(in) :: delt !< length of time step
1635  ! -- return
1636  real(dp) :: decay_rate !< returned value for decay rate
1637  !
1638  ! -- Return user rate if production, otherwise constrain, if necessary
1639  if (decay_rate_usr < dzero) then
1640  !
1641  ! -- Production, no need to limit rate
1642  decay_rate = decay_rate_usr
1643  else
1644  !
1645  ! -- Need to ensure decay does not result in negative
1646  ! concentration, so reduce the rate if it would result in
1647  ! removing more mass than is in the cell.
1648  if (kiter == 1) then
1649  decay_rate = min(decay_rate_usr, cold / delt)
1650  else
1651  decay_rate = decay_rate_last
1652  if (cnew < dzero) then
1653  decay_rate = decay_rate_last + cnew / delt
1654  else if (cnew > cold) then
1655  decay_rate = decay_rate_last + cnew / delt
1656  end if
1657  decay_rate = min(decay_rate_usr, decay_rate)
1658  end if
1659  decay_rate = max(decay_rate, dzero)
1660  end if
1661  end function get_zero_order_decay
1662 
1663 end module gwtmstmodule
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
Definition: Budget.f90:632
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
@ mnormal
normal output mode
Definition: Constants.f90:206
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:93
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 maxcharlen
maximum length of char string
Definition: Constants.f90:47
real(dp), parameter dtwo
real constant 2
Definition: Constants.f90:79
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
– @ brief Mobile Storage and Transfer (MST) Module
Definition: gwt-mst.f90:10
subroutine mst_srb_term(isrb, volfracm, rhobm, vcell, tled, cnew, cold, swnew, swold, const1, const2, rate, hcofval, rhsval)
@ brief Calculate sorption terms
Definition: gwt-mst.f90:374
subroutine mst_cq_srb(this, nodes, cnew, cold, flowja)
@ brief Calculate sorption terms for package
Definition: gwt-mst.f90:692
subroutine mst_calc_csrb(this, cnew)
@ brief Calculate sorbed concentration
Definition: gwt-mst.f90:846
subroutine addto_volfracim(this, volfracim)
@ brief Add volfrac values to volfracim
Definition: gwt-mst.f90:1469
real(dp) function get_zero_order_decay(decay_rate_usr, decay_rate_last, kiter, cold, cnew, delt)
@ brief Calculate zero-order decay rate and constrain if necessary
Definition: gwt-mst.f90:1628
character(len=lenbudtxt), dimension(nbditems) budtxt
Definition: gwt-mst.f90:28
subroutine mst_cq(this, nodes, cnew, cold, flowja)
@ brief Calculate flows for package
Definition: gwt-mst.f90:549
subroutine mst_bd(this, isuppress_output, model_budget)
@ brief Calculate budget terms for package
Definition: gwt-mst.f90:875
subroutine allocate_arrays(this, nodes)
@ brief Allocate arrays for package
Definition: gwt-mst.f90:1078
real(dp) function get_freundlich_derivative(conc, kf, a)
@ brief Calculate sorption derivative using Freundlich
Definition: gwt-mst.f90:1550
real(dp) function get_langmuir_kd(conc, kl, sbar)
@ brief Get effective Langmuir distribution coefficient
Definition: gwt-mst.f90:1604
subroutine mst_cq_dcy_srb(this, nodes, cnew, cold, flowja)
@ brief Calculate decay-sorption terms for package
Definition: gwt-mst.f90:749
real(dp) function get_freundlich_conc(conc, kf, a)
@ brief Calculate sorption concentration using Freundlich
Definition: gwt-mst.f90:1510
real(dp) function get_volfracm(this, node)
@ brief Return mobile domain volume fraction
Definition: gwt-mst.f90:1494
subroutine mst_ot_dv(this, idvsave)
Save sorbate concentration array to binary file.
Definition: gwt-mst.f90:972
subroutine mst_ot_flow(this, icbcfl, icbcun)
@ brief Output flow terms for package
Definition: gwt-mst.f90:919
subroutine read_options(this)
@ brief Read options for package
Definition: gwt-mst.f90:1168
subroutine mst_ar(this, dis, ibound)
@ brief Allocate and read method for package
Definition: gwt-mst.f90:134
subroutine mst_fc_srb(this, nodes, cold, nja, matrix_sln, idxglo, rhs, cnew)
@ brief Fill sorption coefficient method for package
Definition: gwt-mst.f90:315
subroutine mst_cq_dcy(this, nodes, cnew, cold, flowja)
@ brief Calculate decay terms for package
Definition: gwt-mst.f90:637
subroutine read_data(this)
@ brief Read data for package
Definition: gwt-mst.f90:1271
subroutine allocate_scalars(this)
@ brief Allocate scalar variables for package
Definition: gwt-mst.f90:1052
subroutine mst_fc_dcy_srb(this, nodes, cold, nja, matrix_sln, idxglo, rhs, cnew, kiter)
@ brief Fill sorption-decay coefficient method for package
Definition: gwt-mst.f90:448
subroutine mst_da(this)
@ brief Deallocate
Definition: gwt-mst.f90:1011
subroutine mst_fc_dcy(this, nodes, cold, cnew, nja, matrix_sln, idxglo, rhs, kiter)
@ brief Fill decay coefficient method for package
Definition: gwt-mst.f90:257
integer(i4b), parameter nbditems
Definition: gwt-mst.f90:27
subroutine mst_fc(this, nodes, cold, nja, matrix_sln, idxglo, cnew, rhs, kiter)
@ brief Fill coefficient method for package
Definition: gwt-mst.f90:169
real(dp) function get_freundlich_kd(conc, kf, a)
@ brief Get effective Freundlich distribution coefficient
Definition: gwt-mst.f90:1587
subroutine mst_fc_sto(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
@ brief Fill storage coefficient method for package
Definition: gwt-mst.f90:209
real(dp) function get_langmuir_derivative(conc, kl, sbar)
@ brief Calculate sorption derivative using Langmuir
Definition: gwt-mst.f90:1570
subroutine, public mst_cr(mstobj, name_model, inunit, iout, fmi)
@ brief Create a new package object
Definition: gwt-mst.f90:103
subroutine mst_cq_sto(this, nodes, cnew, cold, flowja)
@ brief Calculate storage terms for package
Definition: gwt-mst.f90:588
real(dp) function get_langmuir_conc(conc, kl, sbar)
@ brief Calculate sorption concentration using Langmuir
Definition: gwt-mst.f90:1530
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
This module contains the base numerical package type.
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:236
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
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
character(len=maxcharlen) warnmsg
warning message string
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:29
Derived type for the Budget object.
Definition: Budget.f90:39
@ brief Mobile storage and transfer
Definition: gwt-mst.f90:38