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