MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
gwf-sto.f90
Go to the documentation of this file.
1 !> @brief This module contains the storage package methods
2 !!
3 !! This module contains the methods used to add the effects of storage
4 !! on the groundwater flow equation. The contribution of specific
5 !! storage and specific yield can be represented.
6 !!
7 !<
9 
10  use kindmodule, only: dp, i4b, lgp
11  use constantsmodule, only: dzero, dem6, dem4, dhalf, done, dtwo, &
13  use simvariablesmodule, only: errmsg
18  use basedismodule, only: disbasetype
22  use tvsmodule, only: tvstype, tvs_cr
24 
25  implicit none
26  public :: gwfstotype, sto_cr
27 
28  character(len=LENBUDTXT), dimension(2) :: budtxt = & !< text labels for budget terms
29  &[' STO-SS', ' STO-SY']
30 
31  type, extends(numericalpackagetype) :: gwfstotype
32  integer(I4B), pointer :: istor_coef => null() !< indicates if ss is the storage coefficient
33  integer(I4B), pointer :: iconf_ss => null() !< indicates if ss is 0 below the top of a layer
34  integer(I4B), pointer :: iorig_ss => null() !< indicates if the original storage specific storage formulation should be used
35  integer(I4B), pointer :: iss => null() !< steady state flag: 1 = steady, 0 = transient
36  integer(I4B), pointer :: iusesy => null() !< flag set if any cell is convertible (0, 1)
37  integer(I4B), dimension(:), pointer, contiguous :: iconvert => null() !< confined (0) or convertible (1)
38  real(dp), dimension(:), pointer, contiguous :: ss => null() !< specific storage or storage coefficient
39  real(dp), dimension(:), pointer, contiguous :: sy => null() !< specific yield
40  real(dp), dimension(:), pointer, contiguous :: strgss => null() !< vector of specific storage rates
41  real(dp), dimension(:), pointer, contiguous :: strgsy => null() !< vector of specific yield rates
42  integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound
43  real(dp), pointer :: satomega => null() !< newton-raphson saturation omega
44  integer(I4B), pointer :: integratechanges => null() !< indicates if mid-simulation ss and sy changes should be integrated via an additional matrix formulation term
45  integer(I4B), pointer :: intvs => null() !< TVS (time-varying storage) unit number (0 if unused)
46  type(tvstype), pointer :: tvs => null() !< TVS object
47  real(dp), dimension(:), pointer, contiguous, private :: oldss => null() !< previous time step specific storage
48  real(dp), dimension(:), pointer, contiguous, private :: oldsy => null() !< previous time step specific yield
49  integer(I4B), pointer :: iper => null() !< input context loaded period
50  character(len=:), pointer :: storage !< input context storage string
51  contains
52  procedure :: sto_ar
53  procedure :: sto_rp
54  procedure :: sto_ad
55  procedure :: sto_fc
56  procedure :: sto_fn
57  procedure :: sto_cq
58  procedure :: sto_bd
59  procedure :: sto_save_model_flows
60  procedure :: sto_da
61  procedure :: allocate_scalars
62  procedure, private :: allocate_arrays
63  !procedure, private :: register_handlers
64  procedure, private :: source_options
65  procedure, private :: source_data
66  procedure, private :: log_options
67  procedure, private :: save_old_ss_sy
68  end type
69 
70 contains
71 
72  !> @ brief Create a new package object
73  !!
74  !! Create a new storage (STO) object
75  !!
76  !<
77  subroutine sto_cr(stoobj, name_model, mempath, inunit, iout)
78  ! -- dummy variables
79  type(gwfstotype), pointer :: stoobj !< GwfStoType object
80  character(len=*), intent(in) :: name_model !< name of model
81  character(len=*), intent(in) :: mempath !< input context mem path
82  integer(I4B), intent(in) :: inunit !< package input file unit
83  integer(I4B), intent(in) :: iout !< model listing file unit
84  !
85  ! -- Create the object
86  allocate (stoobj)
87  !
88  ! -- create name and memory path
89  call stoobj%set_names(1, name_model, 'STO', 'STO', mempath)
90  !
91  ! -- Allocate scalars
92  call stoobj%allocate_scalars()
93  !
94  ! -- Set variables
95  stoobj%inunit = inunit
96  stoobj%iout = iout
97  end subroutine sto_cr
98 
99  !> @ brief Allocate and read method for package
100  !!
101  !! Method to allocate and read static data for the STO package.
102  !!
103  !<
104  subroutine sto_ar(this, dis, ibound)
105  ! -- modules
108  ! -- dummy variables
109  class(gwfstotype) :: this !< GwfStoType object
110  class(disbasetype), pointer, intent(in) :: dis !< model discretization object
111  integer(I4B), dimension(:), pointer, contiguous :: ibound !< model ibound array
112  ! -- local variables
113  ! -- formats
114  character(len=*), parameter :: fmtsto = &
115  "(1x,/1x,'STO -- STORAGE PACKAGE, VERSION 1, 5/19/2014', &
116  &' INPUT READ FROM MEMPATH: ', A, //)"
117  !
118  ! --print a message identifying the storage package.
119  write (this%iout, fmtsto) this%input_mempath
120  !
121  ! -- store pointers to arguments that were passed in
122  this%dis => dis
123  this%ibound => ibound
124  !
125  ! -- set pointer to gwf iss
126  call mem_setptr(this%iss, 'ISS', create_mem_path(this%name_model))
127  !
128  ! -- Allocate arrays
129  call this%allocate_arrays(dis%nodes)
130  !!
131  !! -- Register side effect handlers
132  !call this%register_handlers()
133  !
134  ! -- Read storage options
135  call this%source_options()
136  !
137  ! -- read the data block
138  call this%source_data()
139  !
140  ! -- TVS
141  if (this%intvs /= 0) then
142  call this%tvs%ar(this%dis)
143  end if
144  end subroutine sto_ar
145 
146  !> @ brief Read and prepare method for package
147  !!
148  !! Method to read and prepare stress period data for the STO package.
149  !!
150  !<
151  subroutine sto_rp(this)
152  ! -- modules
153  use tdismodule, only: kper
154  implicit none
155  ! -- dummy variables
156  class(gwfstotype) :: this !< GwfStoType object
157  ! -- local variables
158  character(len=16) :: css(0:1)
159  ! -- data
160  data css(0)/' TRANSIENT'/
161  data css(1)/' STEADY-STATE'/
162  !
163  ! -- Store ss and sy values from end of last stress period if needed
164  if (this%integratechanges /= 0) then
165  call this%save_old_ss_sy()
166  end if
167  !
168  ! -- confirm package is active
169  if (this%inunit <= 0) return
170  !
171  ! -- confirm loaded iper
172  if (this%iper /= kper) return
173  !
174  write (this%iout, '(//,1x,a)') 'PROCESSING STORAGE PERIOD DATA'
175  !
176  ! -- set period iss
177  if (this%storage == 'STEADY-STATE') then
178  this%iss = 1
179  else if (this%storage == 'TRANSIENT') then
180  this%iss = 0
181  else
182  write (errmsg, '(a,a)') 'Unknown STORAGE data tag: ', &
183  trim(this%storage)
184  call store_error(errmsg)
185  call store_error_filename(this%input_fname)
186  end if
187  !
188  write (this%iout, '(1x,a)') 'END PROCESSING STORAGE PERIOD DATA'
189  !
190  write (this%iout, '(//1X,A,I0,A,A,/)') &
191  'STRESS PERIOD ', kper, ' IS ', trim(adjustl(css(this%iss)))
192  !
193  ! -- TVS
194  if (this%intvs /= 0) then
195  call this%tvs%rp()
196  end if
197  end subroutine sto_rp
198 
199  !> @ brief Advance the package
200  !!
201  !! Advance data in the STO package.
202  !!
203  !<
204  subroutine sto_ad(this)
205  ! -- modules
206  use tdismodule, only: kstp
207  ! -- dummy variables
208  class(gwfstotype) :: this !< GwfStoType object
209  !
210  ! -- Store ss and sy values from end of last time step if needed
211  if (this%integratechanges /= 0 .and. kstp > 1) then
212  call this%save_old_ss_sy()
213  end if
214  !
215  ! -- TVS
216  if (this%intvs /= 0) then
217  call this%tvs%ad()
218  end if
219  end subroutine sto_ad
220 
221  !> @ brief Fill A and right-hand side for the package
222  !!
223  !! Fill the coefficient matrix and right-hand side with the STO package terms.
224  !!
225  !<
226  subroutine sto_fc(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
227  ! -- modules
228  use tdismodule, only: delt
229  ! -- dummy variables
230  class(gwfstotype) :: this !< GwfStoType object
231  integer(I4B), intent(in) :: kiter !< outer iteration number
232  real(DP), intent(in), dimension(:) :: hold !< previous heads
233  real(DP), intent(in), dimension(:) :: hnew !< current heads
234  class(matrixbasetype), pointer :: matrix_sln !< A matrix
235  integer(I4B), intent(in), dimension(:) :: idxglo !< global index model to solution
236  real(DP), intent(inout), dimension(:) :: rhs !< right-hand side
237  ! -- local variables
238  integer(I4B) :: n
239  integer(I4B) :: idiag
240  real(DP) :: tled
241  real(DP) :: sc1
242  real(DP) :: sc2
243  real(DP) :: rho1
244  real(DP) :: rho2
245  real(DP) :: sc1old
246  real(DP) :: sc2old
247  real(DP) :: rho1old
248  real(DP) :: rho2old
249  real(DP) :: tp
250  real(DP) :: bt
251  real(DP) :: snold
252  real(DP) :: snnew
253  real(DP) :: aterm
254  real(DP) :: rhsterm
255  ! -- formats
256  character(len=*), parameter :: fmtsperror = &
257  &"('DETECTED TIME STEP LENGTH OF ZERO. GWF STORAGE PACKAGE CANNOT BE ', &
258  &'USED UNLESS DELT IS NON-ZERO.')"
259  !
260  ! -- test if steady-state stress period
261  if (this%iss /= 0) return
262  !
263  ! -- Ensure time step length is not zero
264  if (delt == dzero) then
265  write (errmsg, fmtsperror)
266  call store_error(errmsg, terminate=.true.)
267  end if
268  !
269  ! -- set variables
270  tled = done / delt
271  !
272  ! -- loop through and calculate storage contribution to hcof and rhs
273  do n = 1, this%dis%nodes
274  idiag = this%dis%con%ia(n)
275  if (this%ibound(n) < 1) cycle
276  !
277  ! -- aquifer elevations and thickness
278  tp = this%dis%top(n)
279  bt = this%dis%bot(n)
280  !
281  ! -- aquifer saturation
282  if (this%iconvert(n) == 0) then
283  snold = done
284  snnew = done
285  else
286  snold = squadraticsaturation(tp, bt, hold(n), this%satomega)
287  snnew = squadraticsaturation(tp, bt, hnew(n), this%satomega)
288  end if
289  !
290  ! -- storage coefficients
291  sc1 = sscapacity(this%istor_coef, tp, bt, this%dis%area(n), this%ss(n))
292  rho1 = sc1 * tled
293  !
294  if (this%integratechanges /= 0) then
295  ! -- Integration of storage changes (e.g. when using TVS):
296  ! separate the old (start of time step) and new (end of time step)
297  ! primary storage capacities
298  sc1old = sscapacity(this%istor_coef, tp, bt, this%dis%area(n), &
299  this%oldss(n))
300  rho1old = sc1old * tled
301  else
302  ! -- No integration of storage changes: old and new values are
303  ! identical => normal MF6 storage formulation
304  rho1old = rho1
305  end if
306  !
307  ! -- calculate specific storage terms
308  call ssterms(this%iconvert(n), this%iorig_ss, this%iconf_ss, tp, bt, &
309  rho1, rho1old, snnew, snold, hnew(n), hold(n), &
310  aterm, rhsterm)
311  !
312  ! -- add specific storage terms to amat and rhs
313  call matrix_sln%add_value_pos(idxglo(idiag), aterm)
314  rhs(n) = rhs(n) + rhsterm
315  !
316  ! -- specific yield
317  if (this%iconvert(n) /= 0) then
318  rhsterm = dzero
319  !
320  ! -- secondary storage coefficient
321  sc2 = sycapacity(this%dis%area(n), this%sy(n))
322  rho2 = sc2 * tled
323  !
324  if (this%integratechanges /= 0) then
325  ! -- Integration of storage changes (e.g. when using TVS):
326  ! separate the old (start of time step) and new (end of time step)
327  ! secondary storage capacities
328  sc2old = sycapacity(this%dis%area(n), this%oldsy(n))
329  rho2old = sc2old * tled
330  else
331  ! -- No integration of storage changes: old and new values are
332  ! identical => normal MF6 storage formulation
333  rho2old = rho2
334  end if
335  !
336  ! -- calculate specific storage terms
337  call syterms(tp, bt, rho2, rho2old, snnew, snold, &
338  aterm, rhsterm)
339 !
340  ! -- add specific yield terms to amat and rhs
341  call matrix_sln%add_value_pos(idxglo(idiag), aterm)
342  rhs(n) = rhs(n) + rhsterm
343  end if
344  end do
345  end subroutine sto_fc
346 
347  !> @ brief Fill Newton-Raphson terms in A and right-hand side for the package
348  !!
349  !! Fill the coefficient matrix and right-hand side with STO package
350  !! with Newton-Raphson terms.
351  !!
352  !<
353  subroutine sto_fn(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
354  ! -- modules
355  use tdismodule, only: delt
356  ! -- dummy variables
357  class(gwfstotype) :: this !< GwfStoType object
358  integer(I4B), intent(in) :: kiter !< outer iteration number
359  real(DP), intent(in), dimension(:) :: hold !< previous heads
360  real(DP), intent(in), dimension(:) :: hnew !< current heads
361  class(matrixbasetype), pointer :: matrix_sln !< A matrix
362  integer(I4B), intent(in), dimension(:) :: idxglo !< global index model to solution
363  real(DP), intent(inout), dimension(:) :: rhs !< right-hand side
364  ! -- local variables
365  integer(I4B) :: n
366  integer(I4B) :: idiag
367  real(DP) :: tled
368  real(DP) :: sc1
369  real(DP) :: sc2
370  real(DP) :: rho1
371  real(DP) :: rho2
372  real(DP) :: tp
373  real(DP) :: bt
374  real(DP) :: tthk
375  real(DP) :: h
376  real(DP) :: snnew
377  real(DP) :: derv
378  real(DP) :: rterm
379  real(DP) :: drterm
380  !
381  ! -- test if steady-state stress period
382  if (this%iss /= 0) return
383  !
384  ! -- set variables
385  tled = done / delt
386  !
387  ! -- loop through and calculate storage contribution to hcof and rhs
388  do n = 1, this%dis%nodes
389  idiag = this%dis%con%ia(n)
390  if (this%ibound(n) <= 0) cycle
391  !
392  ! -- aquifer elevations and thickness
393  tp = this%dis%top(n)
394  bt = this%dis%bot(n)
395  tthk = tp - bt
396  h = hnew(n)
397  !
398  ! -- aquifer saturation
399  snnew = squadraticsaturation(tp, bt, h)
400  !
401  ! -- storage coefficients
402  sc1 = sscapacity(this%istor_coef, tp, bt, this%dis%area(n), this%ss(n))
403  sc2 = sycapacity(this%dis%area(n), this%sy(n))
404  rho1 = sc1 * tled
405  rho2 = sc2 * tled
406  !
407  ! -- calculate newton terms for specific storage
408  ! and specific yield
409  if (this%iconvert(n) /= 0) then
410  !
411  ! -- calculate saturation derivative
412  derv = squadraticsaturationderivative(tp, bt, h)
413  !
414  ! -- newton terms for specific storage
415  if (this%iconf_ss == 0) then
416  if (this%iorig_ss == 0) then
417  drterm = -rho1 * derv * (h - bt) + rho1 * tthk * snnew * derv
418  else
419  drterm = -(rho1 * derv * h)
420  end if
421  call matrix_sln%add_value_pos(idxglo(idiag), drterm)
422  rhs(n) = rhs(n) + drterm * h
423  end if
424  !
425  ! -- newton terms for specific yield
426  ! only calculated if the current saturation
427  ! is less than one
428  if (snnew < done) then
429  ! -- calculate newton terms for specific yield
430  if (snnew > dzero) then
431  rterm = -rho2 * tthk * snnew
432  drterm = -rho2 * tthk * derv
433  call matrix_sln%add_value_pos(idxglo(idiag), drterm + rho2)
434  rhs(n) = rhs(n) - rterm + drterm * h + rho2 * bt
435  end if
436  end if
437  end if
438  end do
439  end subroutine sto_fn
440 
441  !> @ brief Calculate flows for package
442  !!
443  !! Flow calculation for the STO package components. Components include
444  !! specific storage and specific yield storage.
445  !!
446  !<
447  subroutine sto_cq(this, flowja, hnew, hold)
448  ! -- modules
449  use tdismodule, only: delt
450  ! -- dummy variables
451  class(gwfstotype) :: this !< GwfStoType object
452  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< connection flows
453  real(DP), dimension(:), contiguous, intent(in) :: hnew !< current head
454  real(DP), dimension(:), contiguous, intent(in) :: hold !< previous head
455  ! -- local variables
456  integer(I4B) :: n
457  integer(I4B) :: idiag
458  real(DP) :: rate
459  real(DP) :: tled
460  real(DP) :: sc1
461  real(DP) :: sc2
462  real(DP) :: rho1
463  real(DP) :: rho2
464  real(DP) :: sc1old
465  real(DP) :: sc2old
466  real(DP) :: rho1old
467  real(DP) :: rho2old
468  real(DP) :: tp
469  real(DP) :: bt
470  real(DP) :: snold
471  real(DP) :: snnew
472  real(DP) :: aterm
473  real(DP) :: rhsterm
474  !
475  ! -- initialize strg arrays
476  do n = 1, this%dis%nodes
477  this%strgss(n) = dzero
478  this%strgsy(n) = dzero
479  end do
480  !
481  ! -- Set strt to zero or calculate terms if not steady-state stress period
482  if (this%iss == 0) then
483  !
484  ! -- set variables
485  tled = done / delt
486  !
487  ! -- Calculate storage change
488  do n = 1, this%dis%nodes
489  if (this%ibound(n) <= 0) cycle
490  ! -- aquifer elevations and thickness
491  tp = this%dis%top(n)
492  bt = this%dis%bot(n)
493  !
494  ! -- aquifer saturation
495  if (this%iconvert(n) == 0) then
496  snold = done
497  snnew = done
498  else
499  snold = squadraticsaturation(tp, bt, hold(n), this%satomega)
500  snnew = squadraticsaturation(tp, bt, hnew(n), this%satomega)
501  end if
502  !
503  ! -- primary storage coefficient
504  sc1 = sscapacity(this%istor_coef, tp, bt, this%dis%area(n), this%ss(n))
505  rho1 = sc1 * tled
506  !
507  if (this%integratechanges /= 0) then
508  ! -- Integration of storage changes (e.g. when using TVS):
509  ! separate the old (start of time step) and new (end of time step)
510  ! primary storage capacities
511  sc1old = sscapacity(this%istor_coef, tp, bt, this%dis%area(n), &
512  this%oldss(n))
513  rho1old = sc1old * tled
514  else
515  ! -- No integration of storage changes: old and new values are
516  ! identical => normal MF6 storage formulation
517  rho1old = rho1
518  end if
519  !
520  ! -- calculate specific storage terms and rate
521  call ssterms(this%iconvert(n), this%iorig_ss, this%iconf_ss, tp, bt, &
522  rho1, rho1old, snnew, snold, hnew(n), hold(n), &
523  aterm, rhsterm, rate)
524  !
525  ! -- save rate
526  this%strgss(n) = rate
527  !
528  ! -- add storage term to flowja
529  idiag = this%dis%con%ia(n)
530  flowja(idiag) = flowja(idiag) + rate
531  !
532  ! -- specific yield
533  rate = dzero
534  if (this%iconvert(n) /= 0) then
535  !
536  ! -- secondary storage coefficient
537  sc2 = sycapacity(this%dis%area(n), this%sy(n))
538  rho2 = sc2 * tled
539  !
540  if (this%integratechanges /= 0) then
541  ! -- Integration of storage changes (e.g. when using TVS):
542  ! separate the old (start of time step) and new (end of time
543  ! step) secondary storage capacities
544  sc2old = sycapacity(this%dis%area(n), this%oldsy(n))
545  rho2old = sc2old * tled
546  else
547  ! -- No integration of storage changes: old and new values are
548  ! identical => normal MF6 storage formulation
549  rho2old = rho2
550  end if
551  !
552  ! -- calculate specific yield storage terms and rate
553  call syterms(tp, bt, rho2, rho2old, snnew, snold, &
554  aterm, rhsterm, rate)
555 
556  end if
557  this%strgsy(n) = rate
558  !
559  ! -- add storage term to flowja
560  idiag = this%dis%con%ia(n)
561  flowja(idiag) = flowja(idiag) + rate
562  end do
563  end if
564  end subroutine sto_cq
565 
566  !> @ brief Model budget calculation for package
567  !!
568  !! Budget calculation for the STO package components. Components include
569  !! specific storage and specific yield storage.
570  !!
571  !<
572  subroutine sto_bd(this, isuppress_output, model_budget)
573  ! -- modules
574  use tdismodule, only: delt
576  ! -- dummy variables
577  class(gwfstotype) :: this !< GwfStoType object
578  integer(I4B), intent(in) :: isuppress_output !< flag to suppress model output
579  type(budgettype), intent(inout) :: model_budget !< model budget object
580  ! -- local variables
581  real(DP) :: rin
582  real(DP) :: rout
583  !
584  ! -- Add confined storage rates to model budget
585  call rate_accumulator(this%strgss, rin, rout)
586  call model_budget%addentry(rin, rout, delt, budtxt(1), &
587  isuppress_output, ' STORAGE')
588  !
589  ! -- Add unconfined storage rates to model budget
590  if (this%iusesy == 1) then
591  call rate_accumulator(this%strgsy, rin, rout)
592  call model_budget%addentry(rin, rout, delt, budtxt(2), &
593  isuppress_output, ' STORAGE')
594  end if
595  end subroutine sto_bd
596 
597  !> @ brief Save model flows for package
598  !!
599  !! Save cell-by-cell budget terms for the STO package.
600  !!
601  !<
602  subroutine sto_save_model_flows(this, icbcfl, icbcun)
603  ! -- dummy variables
604  class(gwfstotype) :: this !< GwfStoType object
605  integer(I4B), intent(in) :: icbcfl !< flag to output budget data
606  integer(I4B), intent(in) :: icbcun !< cell-by-cell file unit number
607  ! -- local variables
608  integer(I4B) :: ibinun
609  integer(I4B) :: iprint, nvaluesp, nwidthp
610  character(len=1) :: cdatafmp = ' ', editdesc = ' '
611  real(DP) :: dinact
612  !
613  ! -- Set unit number for binary output
614  if (this%ipakcb < 0) then
615  ibinun = icbcun
616  elseif (this%ipakcb == 0) then
617  ibinun = 0
618  else
619  ibinun = this%ipakcb
620  end if
621  if (icbcfl == 0) ibinun = 0
622  !
623  ! -- Record the storage rates if requested
624  if (ibinun /= 0) then
625  iprint = 0
626  dinact = dzero
627  !
628  ! -- storage(ss)
629  call this%dis%record_array(this%strgss, this%iout, iprint, -ibinun, &
630  budtxt(1), cdatafmp, nvaluesp, &
631  nwidthp, editdesc, dinact)
632  !
633  ! -- storage(sy)
634  if (this%iusesy == 1) then
635  call this%dis%record_array(this%strgsy, this%iout, iprint, -ibinun, &
636  budtxt(2), cdatafmp, nvaluesp, &
637  nwidthp, editdesc, dinact)
638  end if
639  end if
640  end subroutine sto_save_model_flows
641 
642  !> @ brief Deallocate package memory
643  !!
644  !! Deallocate STO package scalars and arrays.
645  !!
646  !<
647  subroutine sto_da(this)
648  ! -- modules
650  ! -- dummy variables
651  class(gwfstotype) :: this !< GwfStoType object
652  !
653  ! -- TVS
654  if (this%intvs /= 0) then
655  call this%tvs%da()
656  deallocate (this%tvs)
657  end if
658  !
659  ! -- Deallocate arrays if package is active
660  if (this%inunit > 0) then
661  call mem_deallocate(this%iconvert)
662  call mem_deallocate(this%ss)
663  call mem_deallocate(this%sy)
664  call mem_deallocate(this%strgss)
665  call mem_deallocate(this%strgsy)
666  !
667  ! -- deallocate TVS arrays
668  if (associated(this%oldss)) then
669  call mem_deallocate(this%oldss)
670  end if
671  if (associated(this%oldsy)) then
672  call mem_deallocate(this%oldsy)
673  end if
674  !
675  ! -- nullify input context pointers
676  nullify (this%iper)
677  nullify (this%storage)
678  end if
679  !
680  ! -- Deallocate scalars
681  call mem_deallocate(this%istor_coef)
682  call mem_deallocate(this%iconf_ss)
683  call mem_deallocate(this%iorig_ss)
684  call mem_deallocate(this%iusesy)
685  call mem_deallocate(this%satomega)
686  call mem_deallocate(this%integratechanges)
687  call mem_deallocate(this%intvs)
688  !
689  ! -- deallocate parent
690  call this%NumericalPackageType%da()
691  end subroutine sto_da
692 
693  !> @ brief Allocate scalars
694  !!
695  !! Allocate and initialize scalars for the STO package. The base numerical
696  !! package allocate scalars method is also called.
697  !!
698  !<
699  subroutine allocate_scalars(this)
700  ! -- modules
702  ! -- dummy variables
703  class(gwfstotype) :: this !< GwfStoType object
704  !
705  ! -- allocate scalars in NumericalPackageType
706  call this%NumericalPackageType%allocate_scalars()
707  !
708  ! -- allocate scalars
709  call mem_allocate(this%istor_coef, 'ISTOR_COEF', this%memoryPath)
710  call mem_allocate(this%iconf_ss, 'ICONF_SS', this%memoryPath)
711  call mem_allocate(this%iorig_ss, 'IORIG_SS', this%memoryPath)
712  call mem_allocate(this%iusesy, 'IUSESY', this%memoryPath)
713  call mem_allocate(this%satomega, 'SATOMEGA', this%memoryPath)
714  call mem_allocate(this%integratechanges, 'INTEGRATECHANGES', &
715  this%memoryPath)
716  call mem_allocate(this%intvs, 'INTVS', this%memoryPath)
717  !
718  ! -- initialize scalars
719  this%istor_coef = 0
720  this%iconf_ss = 0
721  this%iorig_ss = 0
722  this%iusesy = 0
723  this%satomega = dzero
724  this%integratechanges = 0
725  this%intvs = 0
726  end subroutine allocate_scalars
727 
728  !> @ brief Allocate package arrays
729  !!
730  !! Allocate and initialize STO package arrays.
731  !!
732  !<
733  subroutine allocate_arrays(this, nodes)
734  ! -- modules
736  ! -- dummy variables
737  class(gwfstotype), target :: this !< GwfStoType object
738  integer(I4B), intent(in) :: nodes !< active model nodes
739  ! -- local variables
740  integer(I4B) :: n
741  !
742  ! -- Allocate arrays
743  call mem_allocate(this%iconvert, nodes, 'ICONVERT', this%memoryPath)
744  call mem_allocate(this%ss, nodes, 'SS', this%memoryPath)
745  call mem_allocate(this%sy, nodes, 'SY', this%memoryPath)
746  call mem_allocate(this%strgss, nodes, 'STRGSS', this%memoryPath)
747  call mem_allocate(this%strgsy, nodes, 'STRGSY', this%memoryPath)
748  !
749  ! -- set input context pointers
750  if (this%inunit > 0) then
751  call mem_setptr(this%iper, 'IPER', this%input_mempath)
752  call mem_setptr(this%storage, 'STORAGE', this%input_mempath)
753  end if
754  !
755  ! -- Initialize arrays
756  this%iss = 0
757  do n = 1, nodes
758  this%iconvert(n) = 1
759  this%ss(n) = dzero
760  this%sy(n) = dzero
761  this%strgss(n) = dzero
762  this%strgsy(n) = dzero
763  if (this%integratechanges /= 0) then
764  this%oldss(n) = dzero
765  if (this%iusesy /= 0) then
766  this%oldsy(n) = dzero
767  end if
768  end if
769  end do
770  end subroutine allocate_arrays
771 
772  !> @ brief Source input options for package
773  !!
774  !! Source options block parameters for STO package.
775  !!
776  !<
777  subroutine source_options(this)
778  ! -- modules
779  use constantsmodule, only: lenmempath
783  ! -- dummy variables
784  class(gwfstotype) :: this !< GwfStoType object
785  ! -- local variables
786  type(gwfstoparamfoundtype) :: found
787  character(len=LENMEMPATH) :: tvs6_mempath !< mempath of loaded subpackage
788  character(len=LINELENGTH) :: fname
789  !
790  ! -- source package input
791  call mem_set_value(this%ipakcb, 'IPAKCB', this%input_mempath, found%ipakcb)
792  call mem_set_value(this%istor_coef, 'ISTOR_COEF', this%input_mempath, &
793  found%istor_coef)
794  call mem_set_value(this%iconf_ss, 'SS_CONFINED_ONLY', this%input_mempath, &
795  found%ss_confined_only)
796  call mem_set_value(tvs6_mempath, 'TVS6_MEMPATH', this%input_mempath, &
797  found%tvs6_filename)
798  call mem_set_value(this%iorig_ss, 'IORIG_SS', this%input_mempath, &
799  found%iorig_ss)
800  call mem_set_value(this%iconf_ss, 'ICONF_SS', this%input_mempath, &
801  found%iconf_ss)
802  !
803  if (found%ipakcb) then
804  this%ipakcb = -1
805  end if
806  !
807  if (found%ss_confined_only) then
808  this%iorig_ss = 0
809  end if
810  !
811  ! -- enforce 0 or 1 TVS6_FILENAME entries in option block
812  if (filein_fname(fname, 'TVS6_FILENAME', this%input_mempath, &
813  this%input_fname)) then
814  this%intvs = getunit()
815  call openfile(this%intvs, this%iout, fname, 'TVS')
816  call tvs_cr(this%tvs, this%name_model, this%intvs, this%iout)
817  end if
818  !
819  if (found%iconf_ss) then
820  this%iorig_ss = 0
821  end if
822  !
823  ! -- log found options
824  call this%log_options(found)
825  !
826  ! -- set omega value used for saturation calculations
827  if (this%inewton > 0) then
828  this%satomega = dem6
829  end if
830  end subroutine source_options
831 
832  !> @ brief Log found options for package
833  !!
834  !! Log options block for STO package.
835  !!
836  !<
837  subroutine log_options(this, found)
838  ! -- modules
841  ! -- dummy variables
842  class(gwfstotype) :: this !< GwfStoType object
843  type(gwfstoparamfoundtype), intent(in) :: found
844  ! -- local variables
845  ! -- formats
846  character(len=*), parameter :: fmtisvflow = &
847  "(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY FILE &
848  &WHENEVER ICBCFL IS NOT ZERO.')"
849  character(len=*), parameter :: fmtflow = &
850  &"(4x, 'FLOWS WILL BE SAVED TO FILE: ', a, /4x, 'OPENED ON UNIT: ', I7)"
851  character(len=*), parameter :: fmtorigss = &
852  "(4X,'ORIGINAL_SPECIFIC_STORAGE OPTION:',/, &
853  &1X,'The original specific storage formulation will be used')"
854  character(len=*), parameter :: fmtstoc = &
855  "(4X,'STORAGECOEFFICIENT OPTION:',/, &
856  &1X,'Read storage coefficient rather than specific storage')"
857  character(len=*), parameter :: fmtconfss = &
858  "(4X,'SS_CONFINED_ONLY OPTION:',/, &
859  &1X,'Specific storage changes only occur under confined conditions')"
860  !
861  write (this%iout, '(1x,a)') 'PROCESSING STORAGE OPTIONS'
862  !
863  if (found%ipakcb) then
864  write (this%iout, fmtisvflow)
865  end if
866  !
867  if (found%istor_coef) then
868  write (this%iout, fmtstoc)
869  end if
870  !
871  if (found%ss_confined_only) then
872  write (this%iout, fmtconfss)
873  end if
874  !
875  if (found%iorig_ss) then
876  write (this%iout, fmtorigss)
877  end if
878  !
879  if (found%iconf_ss) then
880  write (this%iout, fmtconfss)
881  end if
882  !
883  write (this%iout, '(1x,a)') 'END OF STORAGE OPTIONS'
884  end subroutine log_options
885 
886  !> @ brief Source input data for package
887  !!
888  !! Source griddata block parameters for STO package.
889  !!
890  !<
891  subroutine source_data(this)
892  ! -- modules
895  ! -- dummy variables
896  class(gwfstotype) :: this !< GwfStoType object
897  ! -- local variables
898  character(len=LINELENGTH) :: cellstr
899  logical(LGP) :: isconv
900  character(len=24), dimension(4) :: aname
901  integer(I4B) :: n
902  integer(I4B), dimension(:), pointer, contiguous :: map
903  type(gwfstoparamfoundtype) :: found
904  !
905  ! -- initialize data
906  data aname(1)/' ICONVERT'/
907  data aname(2)/' SPECIFIC STORAGE'/
908  data aname(3)/' SPECIFIC YIELD'/
909  !
910  ! -- set map to reduce data input arrays
911  map => null()
912  if (this%dis%nodes < this%dis%nodesuser) map => this%dis%nodeuser
913  !
914  ! -- copy data from input context
915  call mem_set_value(this%iconvert, 'ICONVERT', this%input_mempath, map, &
916  found%iconvert)
917  call mem_set_value(this%ss, 'SS', this%input_mempath, map, found%ss)
918  call mem_set_value(this%sy, 'SY', this%input_mempath, map, found%sy)
919  !
920  ! -- Check for ICONVERT
921  if (found%iconvert) then
922  isconv = .false.
923  do n = 1, this%dis%nodes
924  if (this%iconvert(n) /= 0) then
925  isconv = .true.
926  this%iusesy = 1
927  exit
928  end if
929  end do
930  else
931  write (errmsg, '(a, a, a)') 'Error in GRIDDATA block: ', &
932  trim(adjustl(aname(1))), ' not found.'
933  call store_error(errmsg)
934  end if
935  !
936  ! -- Check for SS
937  if (found%ss) then
938  ! no-op
939  else
940  write (errmsg, '(a, a, a)') 'Error in GRIDDATA block: ', &
941  trim(adjustl(aname(2))), ' not found.'
942  call store_error(errmsg)
943  end if
944  !
945  ! -- Check for SY
946  if (found%sy) then
947  ! no-op
948  else
949  if (isconv) then
950  write (errmsg, '(a, a, a)') 'Error in GRIDDATA block: ', &
951  trim(adjustl(aname(3))), ' not found.'
952  call store_error(errmsg)
953  end if
954  end if
955  !
956  if (count_errors() > 0) then
957  call store_error_filename(this%input_fname)
958  end if
959  !
960  ! -- Check SS and SY for negative values
961  do n = 1, this%dis%nodes
962  if (this%ss(n) < dzero) then
963  call this%dis%noder_to_string(n, cellstr)
964  write (errmsg, '(a,2(1x,a),1x,g0,1x,a)') &
965  'Error in SS DATA: SS value in cell', trim(adjustl(cellstr)), &
966  'is less than zero (', this%ss(n), ').'
967  call store_error(errmsg)
968  end if
969  if (found%sy) then
970  if (this%sy(n) < dzero) then
971  call this%dis%noder_to_string(n, cellstr)
972  write (errmsg, '(a,2(1x,a),1x,g0,1x,a)') &
973  'Error in SY DATA: SY value in cell', trim(adjustl(cellstr)), &
974  'is less than zero (', this%sy(n), ').'
975  call store_error(errmsg)
976  end if
977  end if
978  end do
979  end subroutine source_data
980 
981  !> @ brief Save old storage property values
982  !!
983  !! Save ss and sy values from the previous time step for use with storage
984  !! integration when integratechanges is non-zero.
985  !!
986  !<
987  subroutine save_old_ss_sy(this)
988  ! -- modules
990  ! -- dummy variables
991  class(gwfstotype) :: this !< GwfStoType object
992  ! -- local variables
993  integer(I4B) :: n
994  !
995  ! -- Allocate TVS arrays if needed
996  if (.not. associated(this%oldss)) then
997  call mem_allocate(this%oldss, this%dis%nodes, 'OLDSS', this%memoryPath)
998  end if
999  if (this%iusesy == 1 .and. .not. associated(this%oldsy)) then
1000  call mem_allocate(this%oldsy, this%dis%nodes, 'OLDSY', this%memoryPath)
1001  end if
1002  !
1003  ! -- Save current specific storage
1004  do n = 1, this%dis%nodes
1005  this%oldss(n) = this%ss(n)
1006  end do
1007  !
1008  ! -- Save current specific yield, if used
1009  if (this%iusesy == 1) then
1010  do n = 1, this%dis%nodes
1011  this%oldsy(n) = this%sy(n)
1012  end do
1013  end if
1014  end subroutine save_old_ss_sy
1015 
1016 end module gwfstomodule
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
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
real(dp), parameter dem4
real constant 1e-4
Definition: Constants.f90:107
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
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
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
This module contains the storage package methods.
Definition: gwf-sto.f90:8
subroutine, public sto_cr(stoobj, name_model, mempath, inunit, iout)
@ brief Create a new package object
Definition: gwf-sto.f90:78
subroutine sto_bd(this, isuppress_output, model_budget)
@ brief Model budget calculation for package
Definition: gwf-sto.f90:573
subroutine source_data(this)
@ brief Source input data for package
Definition: gwf-sto.f90:892
subroutine sto_ar(this, dis, ibound)
@ brief Allocate and read method for package
Definition: gwf-sto.f90:105
subroutine sto_da(this)
@ brief Deallocate package memory
Definition: gwf-sto.f90:648
subroutine sto_fc(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
@ brief Fill A and right-hand side for the package
Definition: gwf-sto.f90:227
subroutine log_options(this, found)
@ brief Log found options for package
Definition: gwf-sto.f90:838
subroutine sto_fn(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
@ brief Fill Newton-Raphson terms in A and right-hand side for the package
Definition: gwf-sto.f90:354
subroutine sto_rp(this)
@ brief Read and prepare method for package
Definition: gwf-sto.f90:152
subroutine sto_cq(this, flowja, hnew, hold)
@ brief Calculate flows for package
Definition: gwf-sto.f90:448
subroutine save_old_ss_sy(this)
@ brief Save old storage property values
Definition: gwf-sto.f90:988
subroutine sto_save_model_flows(this, icbcfl, icbcun)
@ brief Save model flows for package
Definition: gwf-sto.f90:603
subroutine allocate_scalars(this)
@ brief Allocate scalars
Definition: gwf-sto.f90:700
subroutine allocate_arrays(this, nodes)
@ brief Allocate package arrays
Definition: gwf-sto.f90:734
subroutine sto_ad(this)
@ brief Advance the package
Definition: gwf-sto.f90:205
character(len=lenbudtxt), dimension(2) budtxt
Definition: gwf-sto.f90:28
subroutine source_options(this)
@ brief Source input options for package
Definition: gwf-sto.f90:778
This module contains stateless storage subroutines and functions.
pure real(dp) function, public sycapacity(area, sy)
Calculate the specific yield capacity.
pure subroutine, public syterms(top, bot, rho2, rho2old, snnew, snold, aterm, rhsterm, rate)
Calculate the specific yield storage terms.
pure subroutine, public ssterms(iconvert, iorig_ss, iconf_ss, top, bot, rho1, rho1old, snnew, snold, hnew, hold, aterm, rhsterm, rate)
Calculate the specific storage terms.
pure real(dp) function, public sscapacity(istor_coef, top, bot, area, ss)
Calculate the specific storage capacity.
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains the base numerical package type.
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
real(dp) function squadraticsaturation(top, bot, x, eps)
@ brief sQuadraticSaturation
real(dp) function slinearsaturation(top, bot, x)
@ brief sLinearSaturation
real(dp) function squadraticsaturationderivative(top, bot, x, eps)
@ brief Derivative of the quadratic saturation function
real(dp) function sqsaturation(top, bot, x, c1, c2)
@ brief sQSaturation
This module contains the SourceCommonModule.
Definition: SourceCommon.f90:7
logical(lgp) function, public filein_fname(filename, tagname, input_mempath, input_fname)
enforce and set a single input filename provided via FILEIN keyword
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:24
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:23
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:29
This module contains the time-varying storage package methods.
Definition: gwf-tvs.f90:8
subroutine, public tvs_cr(tvs, name_model, inunit, iout)
Create a new TvsType object.
Definition: gwf-tvs.f90:49
Derived type for the Budget object.
Definition: Budget.f90:39