MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
gwe-est.f90
Go to the documentation of this file.
1 !> -- @ brief Energy Storage and Transfer (EST) Module
2 !!
3 !! The GweEstModule contains the GweEstType, which is related
4 !! to GwtEstModule; however, there are some important differences
5 !! owing to the fact that a sorbed phase is not considered.
6 !! Instead, a single temperature is simulated for each grid
7 !! cell and is representative of both the aqueous and solid
8 !! phases (i.e., instantaneous thermal equilibrium is
9 !! assumed). Also, "thermal bleeding" is accommodated, where
10 !! conductive processes can transport into, through, or
11 !! out of dry cells that are part of the active domain.
12 !<
14 
15  use kindmodule, only: dp, i4b
18  use simmodule, only: store_error, count_errors, &
22  use basedismodule, only: disbasetype
23  use tspfmimodule, only: tspfmitype
25 
26  implicit none
27  public :: gweesttype
28  public :: est_cr
29  !
30  integer(I4B), parameter :: nbditems = 2
31  character(len=LENBUDTXT), dimension(NBDITEMS) :: budtxt
32  data budtxt/' STORAGE-CELLBLK', ' DECAY-AQUEOUS'/
33 
34  !> @ brief Energy storage and transfer
35  !!
36  !! Data and methods for handling changes in temperature
37  !<
38  type, extends(numericalpackagetype) :: gweesttype
39  !
40  ! -- storage
41  real(dp), pointer :: cpw => null() !< heat capacity of water
42  real(dp), pointer :: rhow => null() !< density of water
43  real(dp), pointer :: latheatvap => null() !< latent heat of vaporization
44  real(dp), dimension(:), pointer, contiguous :: cps => null() !< heat capacity of solid
45  real(dp), dimension(:), pointer, contiguous :: rhos => null() !< density of solid
46  real(dp), dimension(:), pointer, contiguous :: porosity => null() !< porosity
47  real(dp), dimension(:), pointer, contiguous :: ratesto => null() !< rate of energy storage
48  !
49  ! -- decay
50  integer(I4B), pointer :: idcy => null() !< order of decay rate (0:none, 1:first, 2:zero)
51  real(dp), dimension(:), pointer, contiguous :: decay => null() !< first or zero order decay rate (aqueous)
52  real(dp), dimension(:), pointer, contiguous :: ratedcy => null() !< rate of decay
53  real(dp), dimension(:), pointer, contiguous :: decaylast => null() !< decay rate used for last iteration (needed for zero order decay)
54  !
55  ! -- misc
56  integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound
57  type(tspfmitype), pointer :: fmi => null() !< pointer to fmi object
58  type(gweinputdatatype), pointer :: gwecommon => null() !< pointer to shared gwe data used by multiple packages but set in est
59  real(dp), pointer :: eqnsclfac => null() !< governing equation scale factor; =rhow*cpw for energy
60 
61  contains
62 
63  procedure :: est_ar
64  procedure :: est_fc
65  procedure :: est_fc_sto
66  procedure :: est_fc_dcy
67  procedure :: est_cq
68  procedure :: est_cq_sto
69  procedure :: est_cq_dcy
70  procedure :: est_bd
71  procedure :: est_ot_flow
72  procedure :: est_da
73  procedure :: allocate_scalars
74  procedure, private :: allocate_arrays
75  procedure, private :: read_options
76  procedure, private :: read_data
77 
78  end type gweesttype
79 
80 contains
81 
82  !> @ brief Create a new EST package object
83  !!
84  !! Create a new EST package
85  !<
86  subroutine est_cr(estobj, name_model, inunit, iout, fmi, eqnsclfac, gwecommon)
87  ! -- dummy
88  type(gweesttype), pointer :: estobj !< unallocated new est object to create
89  character(len=*), intent(in) :: name_model !< name of the model
90  integer(I4B), intent(in) :: inunit !< unit number of WEL package input file
91  integer(I4B), intent(in) :: iout !< unit number of model listing file
92  type(tspfmitype), intent(in), target :: fmi !< fmi package for this GWE model
93  real(dp), intent(in), pointer :: eqnsclfac !< governing equation scale factor
94  type(gweinputdatatype), intent(in), target :: gwecommon !< shared data container for use by multiple GWE packages
95  !
96  ! -- Create the object
97  allocate (estobj)
98  !
99  ! -- create name and memory path
100  call estobj%set_names(1, name_model, 'EST', 'EST')
101  !
102  ! -- Allocate scalars
103  call estobj%allocate_scalars()
104  !
105  ! -- Set variables
106  estobj%inunit = inunit
107  estobj%iout = iout
108  estobj%fmi => fmi
109  estobj%eqnsclfac => eqnsclfac
110  estobj%gwecommon => gwecommon
111  !
112  ! -- Initialize block parser
113  call estobj%parser%Initialize(estobj%inunit, estobj%iout)
114  end subroutine est_cr
115 
116  !> @ brief Allocate and read method for package
117  !!
118  !! Method to allocate and read static data for the package.
119  !<
120  subroutine est_ar(this, dis, ibound)
121  ! -- modules
123  ! -- dummy
124  class(gweesttype), intent(inout) :: this !< GweEstType object
125  class(disbasetype), pointer, intent(in) :: dis !< pointer to dis package
126  integer(I4B), dimension(:), pointer, contiguous :: ibound !< pointer to GWE ibound array
127  ! -- formats
128  character(len=*), parameter :: fmtest = &
129  "(1x,/1x,'EST -- ENERGY STORAGE AND TRANSFER PACKAGE, VERSION 1, &
130  &7/29/2020 INPUT READ FROM UNIT ', i0, //)"
131  !
132  ! --print a message identifying the energy storage and transfer package.
133  write (this%iout, fmtest) this%inunit
134  !
135  ! -- Read options
136  call this%read_options()
137  !
138  ! -- store pointers to arguments that were passed in
139  this%dis => dis
140  this%ibound => ibound
141  !
142  ! -- Allocate arrays
143  call this%allocate_arrays(dis%nodes)
144  !
145  ! -- read the gridded data
146  call this%read_data()
147  !
148  ! -- set data required by other packages
149  call this%gwecommon%set_gwe_dat_ptrs(this%rhow, this%cpw, this%latheatvap, &
150  this%rhos, this%cps)
151  end subroutine est_ar
152 
153  !> @ brief Fill coefficient method for package
154  !!
155  !! Method to calculate and fill coefficients for the package.
156  !<
157  subroutine est_fc(this, nodes, cold, nja, matrix_sln, idxglo, cnew, &
158  rhs, kiter)
159  ! -- modules
160  ! -- dummy
161  class(gweesttype) :: this !< GweEstType object
162  integer, intent(in) :: nodes !< number of nodes
163  real(DP), intent(in), dimension(nodes) :: cold !< temperature at end of last time step
164  integer(I4B), intent(in) :: nja !< number of GWE connections
165  class(matrixbasetype), pointer :: matrix_sln !< solution matrix
166  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
167  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
168  real(DP), intent(in), dimension(nodes) :: cnew !< temperature at end of this time step
169  integer(I4B), intent(in) :: kiter !< solution outer iteration number
170  ! -- local
171  !
172  ! -- storage contribution
173  call this%est_fc_sto(nodes, cold, nja, matrix_sln, idxglo, rhs)
174  !
175  ! -- decay contribution
176  if (this%idcy /= 0) then
177  call this%est_fc_dcy(nodes, cold, cnew, nja, matrix_sln, idxglo, &
178  rhs, kiter)
179  end if
180  end subroutine est_fc
181 
182  !> @ brief Fill storage coefficient method for package
183  !!
184  !! Method to calculate and fill storage coefficients for the package.
185  !<
186  subroutine est_fc_sto(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
187  ! -- modules
188  use tdismodule, only: delt
189  ! -- dummy
190  class(gweesttype) :: this !< GweEstType object
191  integer, intent(in) :: nodes !< number of nodes
192  real(DP), intent(in), dimension(nodes) :: cold !< temperature at end of last time step
193  integer(I4B), intent(in) :: nja !< number of GWE connections
194  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
195  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
196  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
197  ! -- local
198  integer(I4B) :: n, idiag
199  real(DP) :: tled
200  real(DP) :: hhcof, rrhs
201  real(DP) :: vnew, vold, vcell, vsolid, term
202  !
203  ! -- set variables
204  tled = done / delt
205  !
206  ! -- loop through and calculate storage contribution to hcof and rhs
207  do n = 1, this%dis%nodes
208  !
209  ! -- skip if transport inactive
210  if (this%ibound(n) <= 0) cycle
211  !
212  ! -- calculate new and old water volumes and solid volume
213  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
214  vnew = vcell * this%fmi%gwfsat(n) * this%porosity(n)
215  vold = vnew
216  if (this%fmi%igwfstrgss /= 0) vold = vold + this%fmi%gwfstrgss(n) * delt
217  if (this%fmi%igwfstrgsy /= 0) vold = vold + this%fmi%gwfstrgsy(n) * delt
218  vsolid = vcell * (done - this%porosity(n))
219  !
220  ! -- add terms to diagonal and rhs accumulators
221  term = (this%rhos(n) * this%cps(n)) * vsolid
222  hhcof = -(this%eqnsclfac * vnew + term) * tled
223  rrhs = -(this%eqnsclfac * vold + term) * tled * cold(n)
224  idiag = this%dis%con%ia(n)
225  call matrix_sln%add_value_pos(idxglo(idiag), hhcof)
226  rhs(n) = rhs(n) + rrhs
227  end do
228  end subroutine est_fc_sto
229 
230  !> @ brief Fill decay coefficient method for package
231  !!
232  !! Method to calculate and fill decay coefficients for the package.
233  !<
234  subroutine est_fc_dcy(this, nodes, cold, cnew, nja, matrix_sln, &
235  idxglo, rhs, kiter)
236  ! -- modules
237  use tdismodule, only: delt
238  ! -- dummy
239  class(gweesttype) :: this !< GweEstType object
240  integer, intent(in) :: nodes !< number of nodes
241  real(DP), intent(in), dimension(nodes) :: cold !< temperature at end of last time step
242  real(DP), intent(in), dimension(nodes) :: cnew !< temperature at end of this time step
243  integer(I4B), intent(in) :: nja !< number of GWE connections
244  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
245  integer(I4B), intent(in), dimension(nja) :: idxglo !< mapping vector for model (local) to solution (global)
246  real(DP), intent(inout), dimension(nodes) :: rhs !< right-hand side vector for model
247  integer(I4B), intent(in) :: kiter !< solution outer iteration number
248  ! -- local
249  integer(I4B) :: n, idiag
250  real(DP) :: hhcof, rrhs
251  real(DP) :: swtpdt
252  real(DP) :: vcell
253  real(DP) :: decay_rate
254  !
255  ! -- loop through and calculate decay contribution to hcof and rhs
256  do n = 1, this%dis%nodes
257  !
258  ! -- skip if transport inactive
259  if (this%ibound(n) <= 0) cycle
260  !
261  ! -- calculate new and old water volumes
262  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
263  swtpdt = this%fmi%gwfsat(n)
264  !
265  ! -- add decay rate terms to accumulators
266  idiag = this%dis%con%ia(n)
267  if (this%idcy == 1) then
268  !
269  ! -- first order decay rate is a function of temperature, so add ! note: May want to remove first-order decay for temperature and support only zero-order
270  ! to left hand side
271  hhcof = -this%decay(n) * vcell * swtpdt * this%porosity(n) &
272  * this%eqnsclfac
273  call matrix_sln%add_value_pos(idxglo(idiag), hhcof)
274  elseif (this%idcy == 2) then
275  !
276  ! -- Call function to get zero-order decay rate, which may be changed
277  ! from the user-specified rate to prevent negative temperatures ! Important note: still need to think through negative temps
278  decay_rate = get_zero_order_decay(this%decay(n), this%decaylast(n), &
279  kiter, cold(n), cnew(n), delt)
280  ! -- This term does get divided by eqnsclfac for fc purposes because it
281  ! should start out being a rate of energy
282  this%decaylast(n) = decay_rate
283  rrhs = decay_rate * vcell * swtpdt * this%porosity(n)
284  rhs(n) = rhs(n) + rrhs
285  end if
286  !
287  end do
288  end subroutine est_fc_dcy
289 
290  !> @ brief Calculate flows for package
291  !!
292  !! Method to calculate flows for the package.
293  !<
294  subroutine est_cq(this, nodes, cnew, cold, flowja)
295  ! -- modules
296  ! -- dummy
297  class(gweesttype) :: this !< GweEstType object
298  integer(I4B), intent(in) :: nodes !< number of nodes
299  real(DP), intent(in), dimension(nodes) :: cnew !< temperature at end of this time step
300  real(DP), intent(in), dimension(nodes) :: cold !< temperature at end of last time step
301  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
302  ! -- local
303  !
304  ! - storage
305  call this%est_cq_sto(nodes, cnew, cold, flowja)
306  !
307  ! -- decay
308  if (this%idcy /= 0) then
309  call this%est_cq_dcy(nodes, cnew, cold, flowja)
310  end if
311  end subroutine est_cq
312 
313  !> @ brief Calculate storage terms for package
314  !!
315  !! Method to calculate storage terms for the package.
316  !<
317  subroutine est_cq_sto(this, nodes, cnew, cold, flowja)
318  ! -- modules
319  use tdismodule, only: delt
320  ! -- dummy
321  class(gweesttype) :: this !< GweEstType object
322  integer(I4B), intent(in) :: nodes !< number of nodes
323  real(DP), intent(in), dimension(nodes) :: cnew !< temperature at end of this time step
324  real(DP), intent(in), dimension(nodes) :: cold !< temperature at end of last time step
325  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
326  ! -- local
327  integer(I4B) :: n
328  integer(I4B) :: idiag
329  real(DP) :: rate
330  real(DP) :: tled
331  real(DP) :: vwatnew, vwatold, vcell, vsolid, term
332  real(DP) :: hhcof, rrhs
333  !
334  ! -- initialize
335  tled = done / delt
336  !
337  ! -- Calculate storage change
338  do n = 1, nodes
339  this%ratesto(n) = dzero
340  !
341  ! -- skip if transport inactive
342  if (this%ibound(n) <= 0) cycle
343  !
344  ! -- calculate new and old water volumes and solid volume
345  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
346  vwatnew = vcell * this%fmi%gwfsat(n) * this%porosity(n)
347  vwatold = vwatnew
348  if (this%fmi%igwfstrgss /= 0) vwatold = vwatold + this%fmi%gwfstrgss(n) &
349  * delt
350  if (this%fmi%igwfstrgsy /= 0) vwatold = vwatold + this%fmi%gwfstrgsy(n) &
351  * delt
352  vsolid = vcell * (done - this%porosity(n))
353  !
354  ! -- calculate rate
355  term = (this%rhos(n) * this%cps(n)) * vsolid
356  hhcof = -(this%eqnsclfac * vwatnew + term) * tled
357  rrhs = -(this%eqnsclfac * vwatold + term) * tled * cold(n)
358  rate = hhcof * cnew(n) - rrhs
359  this%ratesto(n) = rate
360  idiag = this%dis%con%ia(n)
361  flowja(idiag) = flowja(idiag) + rate
362  end do
363  end subroutine est_cq_sto
364 
365  !> @ brief Calculate decay terms for package
366  !!
367  !! Method to calculate decay terms for the package.
368  !<
369  subroutine est_cq_dcy(this, nodes, cnew, cold, flowja) ! Important note: this handles only decay in water; need to add zero-order (but not first-order?) decay in solid
370  ! -- modules
371  use tdismodule, only: delt
372  ! -- dummy
373  class(gweesttype) :: this !< GweEstType object
374  integer(I4B), intent(in) :: nodes !< number of nodes
375  real(DP), intent(in), dimension(nodes) :: cnew !< temperature at end of this time step
376  real(DP), intent(in), dimension(nodes) :: cold !< temperature at end of last time step
377  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
378  ! -- local
379  integer(I4B) :: n
380  integer(I4B) :: idiag
381  real(DP) :: rate
382  real(DP) :: swtpdt
383  real(DP) :: hhcof, rrhs
384  real(DP) :: vcell
385  real(DP) :: decay_rate
386  !
387  ! -- initialize
388  !
389  ! -- Calculate decay change
390  do n = 1, nodes
391  !
392  ! -- skip if transport inactive
393  this%ratedcy(n) = dzero
394  if (this%ibound(n) <= 0) cycle
395  !
396  ! -- calculate new and old water volumes
397  vcell = this%dis%area(n) * (this%dis%top(n) - this%dis%bot(n))
398  swtpdt = this%fmi%gwfsat(n)
399  !
400  ! -- calculate decay gains and losses
401  rate = dzero
402  hhcof = dzero
403  rrhs = dzero
404  if (this%idcy == 1) then ! Important note: do we need/want first-order decay for temperature???
405  hhcof = -this%decay(n) * vcell * swtpdt * this%porosity(n) &
406  * this%eqnsclfac
407  elseif (this%idcy == 2) then
408  decay_rate = get_zero_order_decay(this%decay(n), this%decaylast(n), &
409  0, cold(n), cnew(n), delt)
410  rrhs = decay_rate * vcell * swtpdt * this%porosity(n) ! Important note: this term does NOT get multiplied by eqnsclfac for cq purposes because it should already be a rate of energy
411  end if
412  rate = hhcof * cnew(n) - rrhs
413  this%ratedcy(n) = rate
414  idiag = this%dis%con%ia(n)
415  flowja(idiag) = flowja(idiag) + rate
416  !
417  end do
418  end subroutine est_cq_dcy
419 
420  !> @ brief Calculate budget terms for package
421  !!
422  !! Method to calculate budget terms for the package.
423  !<
424  subroutine est_bd(this, isuppress_output, model_budget)
425  ! -- modules
426  use tdismodule, only: delt
428  ! -- dummy
429  class(gweesttype) :: this !< GweEstType object
430  integer(I4B), intent(in) :: isuppress_output !< flag to suppress output
431  type(budgettype), intent(inout) :: model_budget !< model budget object
432  ! -- local
433  real(DP) :: rin
434  real(DP) :: rout
435  !
436  ! -- sto
437  call rate_accumulator(this%ratesto, rin, rout)
438  call model_budget%addentry(rin, rout, delt, budtxt(1), &
439  isuppress_output, rowlabel=this%packName)
440  !
441  ! -- dcy
442  if (this%idcy /= 0) then
443  call rate_accumulator(this%ratedcy, rin, rout)
444  call model_budget%addentry(rin, rout, delt, budtxt(2), &
445  isuppress_output, rowlabel=this%packName)
446  end if
447  end subroutine est_bd
448 
449  !> @ brief Output flow terms for package
450  !!
451  !! Method to output terms for the package.
452  !<
453  subroutine est_ot_flow(this, icbcfl, icbcun)
454  ! -- dummy
455  class(gweesttype) :: this !< GweEstType object
456  integer(I4B), intent(in) :: icbcfl !< flag and unit number for cell-by-cell output
457  integer(I4B), intent(in) :: icbcun !< flag indication if cell-by-cell data should be saved
458  ! -- local
459  integer(I4B) :: ibinun
460  !character(len=16), dimension(2) :: aname
461  integer(I4B) :: iprint, nvaluesp, nwidthp
462  character(len=1) :: cdatafmp = ' ', editdesc = ' '
463  real(DP) :: dinact
464  !
465  ! -- Set unit number for binary output
466  if (this%ipakcb < 0) then
467  ibinun = icbcun
468  elseif (this%ipakcb == 0) then
469  ibinun = 0
470  else
471  ibinun = this%ipakcb
472  end if
473  if (icbcfl == 0) ibinun = 0
474  !
475  ! -- Record the storage rate if requested
476  if (ibinun /= 0) then
477  iprint = 0
478  dinact = dzero
479  !
480  ! -- sto
481  call this%dis%record_array(this%ratesto, this%iout, iprint, -ibinun, &
482  budtxt(1), cdatafmp, nvaluesp, &
483  nwidthp, editdesc, dinact)
484  !
485  ! -- dcy
486  if (this%idcy /= 0) &
487  call this%dis%record_array(this%ratedcy, this%iout, iprint, -ibinun, &
488  budtxt(2), cdatafmp, nvaluesp, &
489  nwidthp, editdesc, dinact)
490  end if
491  end subroutine est_ot_flow
492 
493  !> @brief Deallocate memory
494  !!
495  !! Method to deallocate memory for the package.
496  !<
497  subroutine est_da(this)
498  ! -- modules
500  ! -- dummy
501  class(gweesttype) :: this !< GweEstType object
502  !
503  ! -- Deallocate arrays if package was active
504  if (this%inunit > 0) then
505  call mem_deallocate(this%porosity)
506  call mem_deallocate(this%ratesto)
507  call mem_deallocate(this%idcy)
508  call mem_deallocate(this%decay)
509  call mem_deallocate(this%ratedcy)
510  call mem_deallocate(this%decaylast)
511  call mem_deallocate(this%cpw)
512  call mem_deallocate(this%cps)
513  call mem_deallocate(this%rhow)
514  call mem_deallocate(this%rhos)
515  call mem_deallocate(this%latheatvap)
516  this%ibound => null()
517  this%fmi => null()
518  end if
519  !
520  ! -- Scalars
521  !
522  ! -- deallocate parent
523  call this%NumericalPackageType%da()
524  end subroutine est_da
525 
526  !> @ brief Allocate scalar variables for package
527  !!
528  !! Method to allocate scalar variables for the package.
529  !<
530  subroutine allocate_scalars(this)
531  ! -- modules
533  ! -- dummy
534  class(gweesttype) :: this !< GweEstType object
535  ! -- local
536  !
537  ! -- Allocate scalars in NumericalPackageType
538  call this%NumericalPackageType%allocate_scalars()
539  !
540  ! -- Allocate
541  call mem_allocate(this%cpw, 'CPW', this%memoryPath)
542  call mem_allocate(this%rhow, 'RHOW', this%memoryPath)
543  call mem_allocate(this%latheatvap, 'LATHEATVAP', this%memoryPath)
544  call mem_allocate(this%idcy, 'IDCY', this%memoryPath)
545  !
546  ! -- Initialize
547  this%cpw = dzero
548  this%rhow = dzero
549  this%latheatvap = dzero
550  this%idcy = 0
551  end subroutine allocate_scalars
552 
553  !> @ brief Allocate arrays for package
554  !!
555  !! Method to allocate arrays for the package.
556  !<
557  subroutine allocate_arrays(this, nodes)
558  ! -- modules
560  use constantsmodule, only: dzero
561  ! -- dummy
562  class(gweesttype) :: this !< GweEstType object
563  integer(I4B), intent(in) :: nodes !< number of nodes
564  ! -- local
565  integer(I4B) :: n
566  !
567  ! -- Allocate
568  ! -- sto
569  call mem_allocate(this%porosity, nodes, 'POROSITY', this%memoryPath)
570  call mem_allocate(this%ratesto, nodes, 'RATESTO', this%memoryPath)
571  call mem_allocate(this%cps, nodes, 'CPS', this%memoryPath)
572  call mem_allocate(this%rhos, nodes, 'RHOS', this%memoryPath)
573  !
574  ! -- dcy
575  if (this%idcy == 0) then
576  call mem_allocate(this%ratedcy, 1, 'RATEDCY', this%memoryPath)
577  call mem_allocate(this%decay, 1, 'DECAY', this%memoryPath)
578  call mem_allocate(this%decaylast, 1, 'DECAYLAST', this%memoryPath)
579  else
580  call mem_allocate(this%ratedcy, this%dis%nodes, 'RATEDCY', this%memoryPath)
581  call mem_allocate(this%decay, nodes, 'DECAY', this%memoryPath)
582  call mem_allocate(this%decaylast, nodes, 'DECAYLAST', this%memoryPath)
583  end if
584  !
585  ! -- Initialize
586  do n = 1, nodes
587  this%porosity(n) = dzero
588  this%ratesto(n) = dzero
589  this%cps(n) = dzero
590  this%rhos(n) = dzero
591  end do
592  do n = 1, size(this%decay)
593  this%decay(n) = dzero
594  this%ratedcy(n) = dzero
595  this%decaylast(n) = dzero
596  end do
597  end subroutine allocate_arrays
598 
599  !> @ brief Read options for package
600  !!
601  !! Method to read options for the package.
602  !<
603  subroutine read_options(this)
604  ! -- modules
605  use constantsmodule, only: linelength
606  ! -- dummy
607  class(gweesttype) :: this !< GweEstType object
608  ! -- local
609  character(len=LINELENGTH) :: keyword
610  integer(I4B) :: ierr
611  logical :: isfound, endOfBlock
612  ! -- formats
613  character(len=*), parameter :: fmtisvflow = &
614  &"(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY "// &
615  &"FILE WHENEVER ICBCFL IS NOT ZERO.')"
616  character(len=*), parameter :: fmtidcy1 = &
617  "(4x,'FIRST-ORDER DECAY IS ACTIVE. ')"
618  character(len=*), parameter :: fmtidcy2 = &
619  "(4x,'ZERO-ORDER DECAY IS ACTIVE. ')"
620  !
621  ! -- get options block
622  call this%parser%GetBlock('OPTIONS', isfound, ierr, blockrequired=.false., &
623  supportopenclose=.true.)
624  !
625  ! -- parse options block if detected
626  if (isfound) then
627  write (this%iout, '(1x,a)') 'PROCESSING ENERGY STORAGE AND TRANSFER OPTIONS'
628  do
629  call this%parser%GetNextLine(endofblock)
630  if (endofblock) exit
631  call this%parser%GetStringCaps(keyword)
632  select case (keyword)
633  case ('SAVE_FLOWS')
634  this%ipakcb = -1
635  write (this%iout, fmtisvflow)
636  case ('FIRST_ORDER_DECAY')
637  this%idcy = 1
638  write (this%iout, fmtidcy1)
639  case ('ZERO_ORDER_DECAY')
640  this%idcy = 2
641  write (this%iout, fmtidcy2)
642  case ('HEAT_CAPACITY_WATER')
643  this%cpw = this%parser%GetDouble()
644  if (this%cpw <= 0.0) then
645  write (errmsg, '(a)') 'Specified value for the heat capacity of &
646  &water must be greater than 0.0.'
647  call store_error(errmsg)
648  call this%parser%StoreErrorUnit()
649  else
650  write (this%iout, '(4x,a,1pg15.6)') &
651  'Heat capacity of the water has been set to: ', &
652  this%cpw
653  end if
654  case ('DENSITY_WATER')
655  this%rhow = this%parser%GetDouble()
656  if (this%rhow <= 0.0) then
657  write (errmsg, '(a)') 'Specified value for the density of &
658  &water must be greater than 0.0.'
659  call store_error(errmsg)
660  call this%parser%StoreErrorUnit()
661  else
662  write (this%iout, '(4x,a,1pg15.6)') &
663  'Density of the water has been set to: ', &
664  this%rhow
665  end if
666  case ('LATENT_HEAT_VAPORIZATION')
667  this%latheatvap = this%parser%GetDouble()
668  write (this%iout, '(4x,a,1pg15.6)') &
669  'Latent heat of vaporization of the water has been set to: ', &
670  this%latheatvap
671  case default
672  write (errmsg, '(a,a)') 'Unknown EST option: ', trim(keyword)
673  call store_error(errmsg)
674  call this%parser%StoreErrorUnit()
675  end select
676  end do
677  write (this%iout, '(1x,a)') 'END OF ENERGY STORAGE AND TRANSFER OPTIONS'
678  end if
679  end subroutine read_options
680 
681  !> @ brief Read data for package
682  !!
683  !! Method to read data for the package.
684  !<
685  subroutine read_data(this)
686  ! -- modules
687  use constantsmodule, only: linelength
689  ! -- dummy
690  class(gweesttype) :: this !< GweEstType object
691  ! -- local
692  character(len=LINELENGTH) :: keyword
693  character(len=:), allocatable :: line
694  integer(I4B) :: istart, istop, lloc, ierr
695  logical :: isfound, endOfBlock
696  logical, dimension(4) :: lname
697  character(len=24), dimension(4) :: aname
698  ! -- formats
699  ! -- data
700  data aname(1)/' MOBILE DOMAIN POROSITY'/
701  data aname(2)/' DECAY RATE'/
702  data aname(3)/' HEAT CAPACITY OF SOLIDS'/
703  data aname(4)/' DENSITY OF SOLIDS'/
704  !
705  ! -- initialize
706  isfound = .false.
707  lname(:) = .false.
708  !
709  ! -- get griddata block
710  call this%parser%GetBlock('GRIDDATA', isfound, ierr)
711  if (isfound) then
712  write (this%iout, '(1x,a)') 'PROCESSING GRIDDATA'
713  do
714  call this%parser%GetNextLine(endofblock)
715  if (endofblock) exit
716  call this%parser%GetStringCaps(keyword)
717  call this%parser%GetRemainingLine(line)
718  lloc = 1
719  select case (keyword)
720  case ('POROSITY')
721  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
722  this%parser%iuactive, this%porosity, &
723  aname(1))
724  lname(1) = .true.
725  case ('DECAY')
726  if (this%idcy == 0) &
727  call mem_reallocate(this%decay, this%dis%nodes, 'DECAY', &
728  trim(this%memoryPath))
729  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
730  this%parser%iuactive, this%decay, &
731  aname(2))
732  lname(2) = .true.
733  case ('HEAT_CAPACITY_SOLID')
734  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
735  this%parser%iuactive, this%cps, &
736  aname(3))
737  lname(3) = .true.
738  case ('DENSITY_SOLID')
739  call this%dis%read_grid_array(line, lloc, istart, istop, this%iout, &
740  this%parser%iuactive, this%rhos, &
741  aname(4))
742  lname(4) = .true.
743  case default
744  write (errmsg, '(a,a)') 'Unknown griddata tag: ', trim(keyword)
745  call store_error(errmsg)
746  call this%parser%StoreErrorUnit()
747  end select
748  end do
749  write (this%iout, '(1x,a)') 'END PROCESSING GRIDDATA'
750  else
751  write (errmsg, '(a)') 'Required griddata block not found.'
752  call store_error(errmsg)
753  call this%parser%StoreErrorUnit()
754  end if
755  !
756  ! -- Check for required porosity
757  if (.not. lname(1)) then
758  write (errmsg, '(a)') 'Porosity not specified in griddata block.'
759  call store_error(errmsg)
760  end if
761  if (.not. lname(3)) then
762  write (errmsg, '(a)') 'HEAT_CAPACITY_SOLID not specified in griddata block.'
763  call store_error(errmsg)
764  end if
765  if (.not. lname(4)) then
766  write (errmsg, '(a)') 'DENSITY_SOLID not specified in griddata block.'
767  call store_error(errmsg)
768  end if
769  !
770  ! -- Check for required decay/production rate coefficients
771  if (this%idcy > 0) then
772  if (.not. lname(2)) then
773  write (errmsg, '(a)') 'First or zero order decay is &
774  &active but the first rate coefficient is not specified. Decay &
775  &must be specified in griddata block.'
776  call store_error(errmsg)
777  end if
778  else
779  if (lname(2)) then
780  write (warnmsg, '(a)') 'First or zero orer decay &
781  &is not active but decay was specified. Decay will &
782  &have no affect on simulation results.'
783  call store_warning(warnmsg)
784  write (this%iout, '(1x,a)') 'WARNING. '//warnmsg
785  end if
786  end if
787  !
788  ! -- terminate if errors
789  if (count_errors() > 0) then
790  call this%parser%StoreErrorUnit()
791  end if
792  end subroutine read_data
793 
794  !> @ brief Calculate zero-order decay rate and constrain if necessary
795  !!
796  !! Function to calculate the zero-order decay rate from the user specified
797  !! decay rate. If the decay rate is positive, then the decay rate must
798  !! be constrained so that more energy is not removed than is available.
799  !! Without this constraint, negative temperatures could result from
800  !! zero-order decay (no freezing).
801  !<
802  function get_zero_order_decay(decay_rate_usr, decay_rate_last, kiter, &
803  cold, cnew, delt) result(decay_rate)
804  ! -- dummy
805  real(dp), intent(in) :: decay_rate_usr !< user-entered decay rate
806  real(dp), intent(in) :: decay_rate_last !< decay rate used for last iteration
807  integer(I4B), intent(in) :: kiter !< Picard iteration counter
808  real(dp), intent(in) :: cold !< temperature at end of last time step
809  real(dp), intent(in) :: cnew !< temperature at end of this time step
810  real(dp), intent(in) :: delt !< length of time step
811  ! -- return
812  real(dp) :: decay_rate !< returned value for decay rate
813  !
814  ! -- Return user rate if production, otherwise constrain, if necessary
815  if (decay_rate_usr < dzero) then
816  !
817  ! -- Production, no need to limit rate
818  decay_rate = decay_rate_usr
819  else
820  !
821  ! -- Need to ensure decay does not result in negative
822  ! temperature, so reduce the rate if it would result in
823  ! removing more energy than is in the cell. ! kluge note: think through
824  if (kiter == 1) then
825  decay_rate = min(decay_rate_usr, cold / delt) ! kluge note: actually want to use rhow*cpw*cold and rhow*cpw*cnew for rates here and below
826  else
827  decay_rate = decay_rate_last
828  if (cnew < dzero) then
829  decay_rate = decay_rate_last + cnew / delt
830  else if (cnew > cold) then
831  decay_rate = decay_rate_last + cnew / delt
832  end if
833  decay_rate = min(decay_rate_usr, decay_rate)
834  end if
835  decay_rate = max(decay_rate, dzero)
836  end if
837  end function get_zero_order_decay
838 
839 end module gweestmodule
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 dep3
real constant 1000
Definition: Constants.f90:88
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
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
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
– @ brief Energy Storage and Transfer (EST) Module
Definition: gwe-est.f90:13
subroutine est_fc_dcy(this, nodes, cold, cnew, nja, matrix_sln, idxglo, rhs, kiter)
@ brief Fill decay coefficient method for package
Definition: gwe-est.f90:236
subroutine est_cq_sto(this, nodes, cnew, cold, flowja)
@ brief Calculate storage terms for package
Definition: gwe-est.f90:318
integer(i4b), parameter nbditems
Definition: gwe-est.f90:30
subroutine est_cq_dcy(this, nodes, cnew, cold, flowja)
@ brief Calculate decay terms for package
Definition: gwe-est.f90:370
character(len=lenbudtxt), dimension(nbditems) budtxt
Definition: gwe-est.f90:31
subroutine est_fc_sto(this, nodes, cold, nja, matrix_sln, idxglo, rhs)
@ brief Fill storage coefficient method for package
Definition: gwe-est.f90:187
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: gwe-est.f90:804
subroutine allocate_scalars(this)
@ brief Allocate scalar variables for package
Definition: gwe-est.f90:531
subroutine est_ar(this, dis, ibound)
@ brief Allocate and read method for package
Definition: gwe-est.f90:121
subroutine est_fc(this, nodes, cold, nja, matrix_sln, idxglo, cnew, rhs, kiter)
@ brief Fill coefficient method for package
Definition: gwe-est.f90:159
subroutine allocate_arrays(this, nodes)
@ brief Allocate arrays for package
Definition: gwe-est.f90:558
subroutine, public est_cr(estobj, name_model, inunit, iout, fmi, eqnsclfac, gwecommon)
@ brief Create a new EST package object
Definition: gwe-est.f90:87
subroutine est_cq(this, nodes, cnew, cold, flowja)
@ brief Calculate flows for package
Definition: gwe-est.f90:295
subroutine est_bd(this, isuppress_output, model_budget)
@ brief Calculate budget terms for package
Definition: gwe-est.f90:425
subroutine read_data(this)
@ brief Read data for package
Definition: gwe-est.f90:686
subroutine est_da(this)
Deallocate memory.
Definition: gwe-est.f90:498
subroutine read_options(this)
@ brief Read options for package
Definition: gwe-est.f90:604
subroutine est_ot_flow(this, icbcfl, icbcun)
@ brief Output flow terms for package
Definition: gwe-est.f90:454
subroutine, public set_gwe_dat_ptrs(this, gwerhow, gwecpw, gwelatheatvap, gwerhos, gwecps)
Allocate and read data from EST.
This module defines variable data types.
Definition: kind.f90:8
This module contains the base numerical package type.
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 Energy storage and transfer
Definition: gwe-est.f90:38
Data for sharing among multiple packages. Originally read in from.