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