MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
gwf-lak.f90
Go to the documentation of this file.
1 module lakmodule
2  !
3  use kindmodule, only: dp, i4b, lgp
6  dzero, dprec, dem30, dem9, dem6, dem5, &
7  dem4, dem2, dem1, dhalf, dp7, dp999, done, &
10  dgravity, dcd, &
12  lenpakloc, dnodata, &
21  use bndmodule, only: bndtype
23  use tablemodule, only: tabletype, table_cr
24  use observemodule, only: observetype
25  use obsmodule, only: obstype
26  use geomutilmodule, only: get_node
28  use basedismodule, only: disbasetype
31  use mathutilmodule, only: is_close
33  use basedismodule, only: disbasetype
36  !
37  implicit none
38  !
39  private
40  public :: laktype
41  public :: lak_create
42  !
43  character(len=LENFTYPE) :: ftype = 'LAK'
44  character(len=LENPACKAGENAME) :: text = ' LAK'
45  !
47  real(dp), dimension(:), pointer, contiguous :: tabstage => null()
48  real(dp), dimension(:), pointer, contiguous :: tabvolume => null()
49  real(dp), dimension(:), pointer, contiguous :: tabsarea => null()
50  real(dp), dimension(:), pointer, contiguous :: tabwarea => null()
51  end type laktabtype
52  !
53  type, extends(bndtype) :: laktype
54  ! -- scalars
55  ! -- characters
56  character(len=16), dimension(:), pointer, contiguous :: clakbudget => null()
57  character(len=16), dimension(:), pointer, contiguous :: cauxcbc => null()
58  ! -- control variables
59  ! -- integers
60  integer(I4B), pointer :: iprhed => null()
61  integer(I4B), pointer :: istageout => null()
62  integer(I4B), pointer :: ibudgetout => null()
63  integer(I4B), pointer :: ibudcsv => null()
64  integer(I4B), pointer :: ipakcsv => null()
65  integer(I4B), pointer :: cbcauxitems => null()
66  integer(I4B), pointer :: nlakes => null()
67  integer(I4B), pointer :: noutlets => null()
68  integer(I4B), pointer :: ntables => null()
69  real(dp), pointer :: convlength => null()
70  real(dp), pointer :: convtime => null()
71  real(dp), pointer :: outdmax => null()
72  integer(I4B), pointer :: igwhcopt => null()
73  integer(I4B), pointer :: iconvchk => null()
74  integer(I4B), pointer :: iconvresidchk => null()
75  integer(I4B), pointer :: maxlakit => null() !< maximum number of iterations in LAK solve
76  real(dp), pointer :: surfdep => null()
77  real(dp), pointer :: dmaxchg => null()
78  real(dp), pointer :: delh => null()
79  real(dp), pointer :: pdmax => null()
80  integer(I4B), pointer :: check_attr => null()
81  ! -- for budgets
82  integer(I4B), pointer :: bditems => null()
83  ! -- vectors
84  ! -- lake data
85  integer(I4B), dimension(:), pointer, contiguous :: nlakeconn => null()
86  integer(I4B), dimension(:), pointer, contiguous :: idxlakeconn => null()
87  integer(I4B), dimension(:), pointer, contiguous :: ntabrow => null()
88  real(dp), dimension(:), pointer, contiguous :: strt => null()
89  real(dp), dimension(:), pointer, contiguous :: laketop => null()
90  real(dp), dimension(:), pointer, contiguous :: lakebot => null()
91  real(dp), dimension(:), pointer, contiguous :: sareamax => null()
92  character(len=LENBOUNDNAME), dimension(:), pointer, &
93  contiguous :: lakename => null()
94  character(len=8), dimension(:), pointer, contiguous :: status => null()
95  real(dp), dimension(:), pointer, contiguous :: avail => null()
96  real(dp), dimension(:), pointer, contiguous :: lkgwsink => null()
97  real(dp), dimension(:), pointer, contiguous :: stage => null()
98  real(dp), dimension(:), pointer, contiguous :: rainfall => null()
99  real(dp), dimension(:), pointer, contiguous :: evaporation => null()
100  real(dp), dimension(:), pointer, contiguous :: runoff => null()
101  real(dp), dimension(:), pointer, contiguous :: inflow => null()
102  real(dp), dimension(:), pointer, contiguous :: withdrawal => null()
103  real(dp), dimension(:, :), pointer, contiguous :: lauxvar => null()
104  !
105  ! -- table data
106  integer(I4B), dimension(:), pointer, contiguous :: ialaktab => null()
107  real(dp), dimension(:), pointer, contiguous :: tabstage => null()
108  real(dp), dimension(:), pointer, contiguous :: tabvolume => null()
109  real(dp), dimension(:), pointer, contiguous :: tabsarea => null()
110  real(dp), dimension(:), pointer, contiguous :: tabwarea => null()
111  !
112  ! -- lake solution data
113  integer(I4B), dimension(:), pointer, contiguous :: ncncvr => null()
114  real(dp), dimension(:), pointer, contiguous :: surfin => null()
115  real(dp), dimension(:), pointer, contiguous :: surfout => null()
116  real(dp), dimension(:), pointer, contiguous :: surfout1 => null()
117  real(dp), dimension(:), pointer, contiguous :: precip => null()
118  real(dp), dimension(:), pointer, contiguous :: precip1 => null()
119  real(dp), dimension(:), pointer, contiguous :: evap => null()
120  real(dp), dimension(:), pointer, contiguous :: evap1 => null()
121  real(dp), dimension(:), pointer, contiguous :: evapo => null()
122  real(dp), dimension(:), pointer, contiguous :: withr => null()
123  real(dp), dimension(:), pointer, contiguous :: withr1 => null()
124  real(dp), dimension(:), pointer, contiguous :: flwin => null()
125  real(dp), dimension(:), pointer, contiguous :: flwiter => null()
126  real(dp), dimension(:), pointer, contiguous :: flwiter1 => null()
127  real(dp), dimension(:), pointer, contiguous :: seep => null()
128  real(dp), dimension(:), pointer, contiguous :: seep1 => null()
129  real(dp), dimension(:), pointer, contiguous :: seep0 => null()
130  real(dp), dimension(:), pointer, contiguous :: stageiter => null()
131  real(dp), dimension(:), pointer, contiguous :: chterm => null()
132  !
133  ! -- lake convergence
134  integer(I4B), dimension(:), pointer, contiguous :: iseepc => null()
135  integer(I4B), dimension(:), pointer, contiguous :: idhc => null()
136  real(dp), dimension(:), pointer, contiguous :: en1 => null()
137  real(dp), dimension(:), pointer, contiguous :: en2 => null()
138  real(dp), dimension(:), pointer, contiguous :: r1 => null()
139  real(dp), dimension(:), pointer, contiguous :: r2 => null()
140  real(dp), dimension(:), pointer, contiguous :: dh0 => null()
141  real(dp), dimension(:), pointer, contiguous :: s0 => null()
142  real(dp), dimension(:), pointer, contiguous :: qgwf0 => null()
143  !
144  ! -- lake connection data
145  integer(I4B), dimension(:), pointer, contiguous :: imap => null()
146  integer(I4B), dimension(:), pointer, contiguous :: cellid => null()
147  integer(I4B), dimension(:), pointer, contiguous :: nodesontop => null()
148  integer(I4B), dimension(:), pointer, contiguous :: ictype => null()
149  real(dp), dimension(:), pointer, contiguous :: bedleak => null()
150  real(dp), dimension(:), pointer, contiguous :: belev => null()
151  real(dp), dimension(:), pointer, contiguous :: telev => null()
152  real(dp), dimension(:), pointer, contiguous :: connlength => null()
153  real(dp), dimension(:), pointer, contiguous :: connwidth => null()
154  real(dp), dimension(:), pointer, contiguous :: sarea => null()
155  real(dp), dimension(:), pointer, contiguous :: warea => null()
156  real(dp), dimension(:), pointer, contiguous :: satcond => null()
157  real(dp), dimension(:), pointer, contiguous :: simcond => null()
158  real(dp), dimension(:), pointer, contiguous :: simlakgw => null()
159  !
160  ! -- lake outlet data
161  integer(I4B), dimension(:), pointer, contiguous :: lakein => null()
162  integer(I4B), dimension(:), pointer, contiguous :: lakeout => null()
163  integer(I4B), dimension(:), pointer, contiguous :: iouttype => null()
164  real(dp), dimension(:), pointer, contiguous :: outrate => null()
165  real(dp), dimension(:), pointer, contiguous :: outinvert => null()
166  real(dp), dimension(:), pointer, contiguous :: outwidth => null()
167  real(dp), dimension(:), pointer, contiguous :: outrough => null()
168  real(dp), dimension(:), pointer, contiguous :: outslope => null()
169  real(dp), dimension(:), pointer, contiguous :: simoutrate => null()
170  !
171  ! -- lake output data
172  real(dp), dimension(:), pointer, contiguous :: qauxcbc => null()
173  real(dp), dimension(:), pointer, contiguous :: dbuff => null()
174  real(dp), dimension(:), pointer, contiguous :: qleak => null()
175  real(dp), dimension(:), pointer, contiguous :: qsto => null()
176  !
177  ! -- pointer to gwf iss and gwf hk
178  integer(I4B), pointer :: gwfiss => null()
179  real(dp), dimension(:), pointer, contiguous :: gwfk11 => null()
180  real(dp), dimension(:), pointer, contiguous :: gwfk33 => null()
181  real(dp), dimension(:), pointer, contiguous :: gwfsat => null()
182  integer(I4B), pointer :: gwfik33 => null()
183  !
184  ! -- package x, xold, and ibound
185  integer(I4B), dimension(:), pointer, contiguous :: iboundpak => null() !package ibound
186  real(dp), dimension(:), pointer, contiguous :: xnewpak => null() !package x vector
187  real(dp), dimension(:), pointer, contiguous :: xoldpak => null() !package xold vector
188  !
189  ! -- lake budget object
190  type(budgetobjecttype), pointer :: budobj => null()
191  !
192  ! -- lake table objects
193  type(tabletype), pointer :: stagetab => null()
194  type(tabletype), pointer :: pakcsvtab => null()
195  !
196  ! -- density variables
197  integer(I4B), pointer :: idense
198  real(dp), dimension(:, :), pointer, contiguous :: denseterms => null()
199  !
200  ! -- viscosity variables
201  real(dp), dimension(:, :), pointer, contiguous :: viscratios => null() !< viscosity ratios (1: lak vsc ratio; 2: gwf vsc ratio)
202  !
203  ! -- type bound procedures
204 
205  contains
206 
207  procedure :: lak_allocate_scalars
208  procedure :: lak_allocate_arrays
209  procedure :: bnd_options => lak_options
210  procedure :: read_dimensions => lak_read_dimensions
211  procedure :: read_initial_attr => lak_read_initial_attr
212  procedure :: set_pointers => lak_set_pointers
213  procedure :: bnd_ar => lak_ar
214  procedure :: bnd_rp => lak_rp
215  procedure :: bnd_ad => lak_ad
216  procedure :: bnd_cf => lak_cf
217  procedure :: bnd_fc => lak_fc
218  procedure :: bnd_fn => lak_fn
219  procedure :: bnd_cc => lak_cc
220  procedure :: bnd_cq => lak_cq
221  procedure :: bnd_ot_model_flows => lak_ot_model_flows
222  procedure :: bnd_ot_package_flows => lak_ot_package_flows
223  procedure :: bnd_ot_dv => lak_ot_dv
224  procedure :: bnd_ot_bdsummary => lak_ot_bdsummary
225  procedure :: bnd_da => lak_da
226  procedure :: define_listlabel
227  ! -- methods for observations
228  procedure, public :: bnd_obs_supported => lak_obs_supported
229  procedure, public :: bnd_df_obs => lak_df_obs
230  procedure, public :: bnd_rp_obs => lak_rp_obs
231  procedure, public :: bnd_bd_obs => lak_bd_obs
232  ! -- private procedures
233  procedure, private :: lak_read_lakes
234  procedure, private :: lak_read_lake_connections
235  procedure, private :: lak_read_outlets
236  procedure, private :: lak_read_tables
237  procedure, private :: lak_read_table
238  procedure, private :: lak_check_valid
239  procedure, private :: lak_set_stressperiod
240  procedure, private :: lak_set_attribute_error
241  procedure, private :: lak_bound_update
242  procedure, private :: lak_calculate_sarea
243  procedure, private :: lak_calculate_warea
244  procedure, private :: lak_calculate_conn_warea
245  procedure, public :: lak_calculate_vol
246  procedure, private :: lak_calculate_conductance
247  procedure, private :: lak_calculate_cond_head
248  procedure, private :: lak_calculate_conn_conductance
249  procedure, private :: lak_calculate_exchange
250  procedure, private :: lak_calculate_conn_exchange
251  procedure, private :: lak_estimate_conn_exchange
252  procedure, private :: lak_calculate_storagechange
253  procedure, private :: lak_calculate_rainfall
254  procedure, private :: lak_calculate_runoff
255  procedure, private :: lak_calculate_inflow
256  procedure, private :: lak_calculate_external
257  procedure, private :: lak_calculate_withdrawal
258  procedure, private :: lak_calculate_evaporation
259  procedure, private :: lak_calculate_outlet_inflow
260  procedure, private :: lak_calculate_outlet_outflow
261  procedure, private :: lak_get_internal_inlet
262  procedure, private :: lak_get_internal_outlet
263  procedure, private :: lak_get_external_outlet
264  procedure, private :: lak_get_internal_mover
265  procedure, private :: lak_get_external_mover
266  procedure, private :: lak_get_outlet_tomover
267  procedure, private :: lak_accumulate_chterm
268  procedure, private :: lak_vol2stage
269  procedure, private :: lak_solve
270  procedure, private :: lak_bisection
271  procedure, private :: lak_calculate_available
272  procedure, private :: lak_calculate_residual
273  procedure, private :: lak_linear_interpolation
274  procedure, private :: lak_setup_budobj
275  procedure, private :: lak_fill_budobj
276  procedure, private :: laktables_to_vectors
277  ! -- table
278  procedure, private :: lak_setup_tableobj
279  ! -- density
280  procedure :: lak_activate_density
281  procedure, private :: lak_calculate_density_exchange
282  ! -- viscosity
284  end type laktype
285 
286 contains
287 
288  !> @brief Create a new LAK Package and point bndobj to the new package
289  !<
290  subroutine lak_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname)
291  ! -- dummy
292  class(bndtype), pointer :: packobj
293  integer(I4B), intent(in) :: id
294  integer(I4B), intent(in) :: ibcnum
295  integer(I4B), intent(in) :: inunit
296  integer(I4B), intent(in) :: iout
297  character(len=*), intent(in) :: namemodel
298  character(len=*), intent(in) :: pakname
299  ! -- local
300  type(laktype), pointer :: lakobj
301  !
302  ! -- allocate the object and assign values to object variables
303  allocate (lakobj)
304  packobj => lakobj
305  !
306  ! -- create name and memory path
307  call packobj%set_names(ibcnum, namemodel, pakname, ftype)
308  packobj%text = text
309  !
310  ! -- allocate scalars
311  call lakobj%lak_allocate_scalars()
312  !
313  ! -- initialize package
314  call packobj%pack_initialize()
315  !
316  packobj%inunit = inunit
317  packobj%iout = iout
318  packobj%id = id
319  packobj%ibcnum = ibcnum
320  packobj%ncolbnd = 3
321  packobj%iscloc = 0 ! not supported
322  packobj%isadvpak = 1
323  packobj%ictMemPath = create_mem_path(namemodel, 'NPF')
324  !
325  ! -- Return
326  return
327  end subroutine lak_create
328 
329  !> @brief Allocate scalar members
330  !<
331  subroutine lak_allocate_scalars(this)
332  ! -- dummy
333  class(laktype), intent(inout) :: this
334  !
335  ! -- call standard BndType allocate scalars
336  call this%BndType%allocate_scalars()
337  !
338  ! -- allocate the object and assign values to object variables
339  call mem_allocate(this%iprhed, 'IPRHED', this%memoryPath)
340  call mem_allocate(this%istageout, 'ISTAGEOUT', this%memoryPath)
341  call mem_allocate(this%ibudgetout, 'IBUDGETOUT', this%memoryPath)
342  call mem_allocate(this%ibudcsv, 'IBUDCSV', this%memoryPath)
343  call mem_allocate(this%ipakcsv, 'IPAKCSV', this%memoryPath)
344  call mem_allocate(this%nlakes, 'NLAKES', this%memoryPath)
345  call mem_allocate(this%noutlets, 'NOUTLETS', this%memoryPath)
346  call mem_allocate(this%ntables, 'NTABLES', this%memoryPath)
347  call mem_allocate(this%convlength, 'CONVLENGTH', this%memoryPath)
348  call mem_allocate(this%convtime, 'CONVTIME', this%memoryPath)
349  call mem_allocate(this%outdmax, 'OUTDMAX', this%memoryPath)
350  call mem_allocate(this%igwhcopt, 'IGWHCOPT', this%memoryPath)
351  call mem_allocate(this%iconvchk, 'ICONVCHK', this%memoryPath)
352  call mem_allocate(this%iconvresidchk, 'ICONVRESIDCHK', this%memoryPath)
353  call mem_allocate(this%maxlakit, 'MAXLAKIT', this%memoryPath)
354  call mem_allocate(this%surfdep, 'SURFDEP', this%memoryPath)
355  call mem_allocate(this%dmaxchg, 'DMAXCHG', this%memoryPath)
356  call mem_allocate(this%delh, 'DELH', this%memoryPath)
357  call mem_allocate(this%pdmax, 'PDMAX', this%memoryPath)
358  call mem_allocate(this%check_attr, 'CHECK_ATTR', this%memoryPath)
359  call mem_allocate(this%bditems, 'BDITEMS', this%memoryPath)
360  call mem_allocate(this%cbcauxitems, 'CBCAUXITEMS', this%memoryPath)
361  call mem_allocate(this%idense, 'IDENSE', this%memoryPath)
362  !
363  ! -- Set values
364  this%iprhed = 0
365  this%istageout = 0
366  this%ibudgetout = 0
367  this%ibudcsv = 0
368  this%ipakcsv = 0
369  this%nlakes = 0
370  this%noutlets = 0
371  this%ntables = 0
372  this%convlength = done
373  this%convtime = done
374  this%outdmax = dzero
375  this%igwhcopt = 0
376  this%iconvchk = 1
377  this%iconvresidchk = 1
378  this%maxlakit = maxadpit
379  this%surfdep = dzero
380  this%dmaxchg = dem5
381  this%delh = dp999 * this%dmaxchg
382  this%pdmax = dem1
383  this%bditems = 11
384  this%cbcauxitems = 1
385  this%idense = 0
386  this%ivsc = 0
387  !
388  ! -- Return
389  return
390  end subroutine lak_allocate_scalars
391 
392  !> @brief Allocate scalar members
393  !<
394  subroutine lak_allocate_arrays(this)
395  ! -- modules
396  ! -- dummy
397  class(laktype), intent(inout) :: this
398  ! -- local
399  integer(I4B) :: i
400  !
401  ! -- call standard BndType allocate scalars
402  call this%BndType%allocate_arrays()
403  !
404  ! -- allocate character array for budget text
405  allocate (this%clakbudget(this%bditems))
406  !
407  !-- fill clakbudget
408  this%clakbudget(1) = ' GWF'
409  this%clakbudget(2) = ' RAINFALL'
410  this%clakbudget(3) = ' EVAPORATION'
411  this%clakbudget(4) = ' RUNOFF'
412  this%clakbudget(5) = ' EXT-INFLOW'
413  this%clakbudget(6) = ' WITHDRAWAL'
414  this%clakbudget(7) = ' EXT-OUTFLOW'
415  this%clakbudget(8) = ' STORAGE'
416  this%clakbudget(9) = ' CONSTANT'
417  this%clakbudget(10) = ' FROM-MVR'
418  this%clakbudget(11) = ' TO-MVR'
419  !
420  ! -- allocate and initialize dbuff
421  if (this%istageout > 0) then
422  call mem_allocate(this%dbuff, this%nlakes, 'DBUFF', this%memoryPath)
423  do i = 1, this%nlakes
424  this%dbuff(i) = dzero
425  end do
426  else
427  call mem_allocate(this%dbuff, 0, 'DBUFF', this%memoryPath)
428  end if
429  !
430  ! -- allocate character array for budget text
431  allocate (this%cauxcbc(this%cbcauxitems))
432  !
433  ! -- allocate and initialize qauxcbc
434  call mem_allocate(this%qauxcbc, this%cbcauxitems, 'QAUXCBC', this%memoryPath)
435  do i = 1, this%cbcauxitems
436  this%qauxcbc(i) = dzero
437  end do
438  !
439  ! -- allocate qleak and qsto
440  call mem_allocate(this%qleak, this%maxbound, 'QLEAK', this%memoryPath)
441  do i = 1, this%maxbound
442  this%qleak(i) = dzero
443  end do
444  call mem_allocate(this%qsto, this%nlakes, 'QSTO', this%memoryPath)
445  do i = 1, this%nlakes
446  this%qsto(i) = dzero
447  end do
448  !
449  ! -- allocate denseterms to size 0
450  call mem_allocate(this%denseterms, 3, 0, 'DENSETERMS', this%memoryPath)
451  !
452  ! -- allocate viscratios to size 0
453  call mem_allocate(this%viscratios, 2, 0, 'VISCRATIOS', this%memoryPath)
454  !
455  ! -- Return
456  return
457  end subroutine lak_allocate_arrays
458 
459  !> @brief Read the dimensions for this package
460  !<
461  subroutine lak_read_lakes(this)
462  ! -- modules
463  use constantsmodule, only: linelength
466  ! -- dummy
467  class(laktype), intent(inout) :: this
468  ! -- local
469  character(len=LINELENGTH) :: text
470  character(len=LENBOUNDNAME) :: bndName, bndNameTemp
471  character(len=9) :: cno
472  character(len=50), dimension(:), allocatable :: caux
473  integer(I4B) :: ierr, ival
474  logical(LGP) :: isfound, endOfBlock
475  integer(I4B) :: n
476  integer(I4B) :: ii, jj
477  integer(I4B) :: iaux
478  integer(I4B) :: itmp
479  integer(I4B) :: nlak
480  integer(I4B) :: nconn
481  integer(I4B), dimension(:), pointer, contiguous :: nboundchk
482  real(DP), pointer :: bndElem => null()
483  !
484  ! -- initialize itmp
485  itmp = 0
486  !
487  ! -- allocate lake data
488  call mem_allocate(this%nlakeconn, this%nlakes, 'NLAKECONN', this%memoryPath)
489  call mem_allocate(this%idxlakeconn, this%nlakes + 1, 'IDXLAKECONN', &
490  this%memoryPath)
491  call mem_allocate(this%ntabrow, this%nlakes, 'NTABROW', this%memoryPath)
492  call mem_allocate(this%strt, this%nlakes, 'STRT', this%memoryPath)
493  call mem_allocate(this%laketop, this%nlakes, 'LAKETOP', this%memoryPath)
494  call mem_allocate(this%lakebot, this%nlakes, 'LAKEBOT', this%memoryPath)
495  call mem_allocate(this%sareamax, this%nlakes, 'SAREAMAX', this%memoryPath)
496  call mem_allocate(this%stage, this%nlakes, 'STAGE', this%memoryPath)
497  call mem_allocate(this%rainfall, this%nlakes, 'RAINFALL', this%memoryPath)
498  call mem_allocate(this%evaporation, this%nlakes, 'EVAPORATION', &
499  this%memoryPath)
500  call mem_allocate(this%runoff, this%nlakes, 'RUNOFF', this%memoryPath)
501  call mem_allocate(this%inflow, this%nlakes, 'INFLOW', this%memoryPath)
502  call mem_allocate(this%withdrawal, this%nlakes, 'WITHDRAWAL', this%memoryPath)
503  call mem_allocate(this%lauxvar, this%naux, this%nlakes, 'LAUXVAR', &
504  this%memoryPath)
505  call mem_allocate(this%avail, this%nlakes, 'AVAIL', this%memoryPath)
506  call mem_allocate(this%lkgwsink, this%nlakes, 'LKGWSINK', this%memoryPath)
507  call mem_allocate(this%ncncvr, this%nlakes, 'NCNCVR', this%memoryPath)
508  call mem_allocate(this%surfin, this%nlakes, 'SURFIN', this%memoryPath)
509  call mem_allocate(this%surfout, this%nlakes, 'SURFOUT', this%memoryPath)
510  call mem_allocate(this%surfout1, this%nlakes, 'SURFOUT1', this%memoryPath)
511  call mem_allocate(this%precip, this%nlakes, 'PRECIP', this%memoryPath)
512  call mem_allocate(this%precip1, this%nlakes, 'PRECIP1', this%memoryPath)
513  call mem_allocate(this%evap, this%nlakes, 'EVAP', this%memoryPath)
514  call mem_allocate(this%evap1, this%nlakes, 'EVAP1', this%memoryPath)
515  call mem_allocate(this%evapo, this%nlakes, 'EVAPO', this%memoryPath)
516  call mem_allocate(this%withr, this%nlakes, 'WITHR', this%memoryPath)
517  call mem_allocate(this%withr1, this%nlakes, 'WITHR1', this%memoryPath)
518  call mem_allocate(this%flwin, this%nlakes, 'FLWIN', this%memoryPath)
519  call mem_allocate(this%flwiter, this%nlakes, 'FLWITER', this%memoryPath)
520  call mem_allocate(this%flwiter1, this%nlakes, 'FLWITER1', this%memoryPath)
521  call mem_allocate(this%seep, this%nlakes, 'SEEP', this%memoryPath)
522  call mem_allocate(this%seep1, this%nlakes, 'SEEP1', this%memoryPath)
523  call mem_allocate(this%seep0, this%nlakes, 'SEEP0', this%memoryPath)
524  call mem_allocate(this%stageiter, this%nlakes, 'STAGEITER', this%memoryPath)
525  call mem_allocate(this%chterm, this%nlakes, 'CHTERM', this%memoryPath)
526  !
527  ! -- lake boundary and stages
528  call mem_allocate(this%iboundpak, this%nlakes, 'IBOUND', this%memoryPath)
529  call mem_allocate(this%xnewpak, this%nlakes, 'XNEWPAK', this%memoryPath)
530  call mem_allocate(this%xoldpak, this%nlakes, 'XOLDPAK', this%memoryPath)
531  !
532  ! -- lake iteration variables
533  call mem_allocate(this%iseepc, this%nlakes, 'ISEEPC', this%memoryPath)
534  call mem_allocate(this%idhc, this%nlakes, 'IDHC', this%memoryPath)
535  call mem_allocate(this%en1, this%nlakes, 'EN1', this%memoryPath)
536  call mem_allocate(this%en2, this%nlakes, 'EN2', this%memoryPath)
537  call mem_allocate(this%r1, this%nlakes, 'R1', this%memoryPath)
538  call mem_allocate(this%r2, this%nlakes, 'R2', this%memoryPath)
539  call mem_allocate(this%dh0, this%nlakes, 'DH0', this%memoryPath)
540  call mem_allocate(this%s0, this%nlakes, 'S0', this%memoryPath)
541  call mem_allocate(this%qgwf0, this%nlakes, 'QGWF0', this%memoryPath)
542  !
543  ! -- allocate character storage not managed by the memory manager
544  allocate (this%lakename(this%nlakes)) ! ditch after boundnames allocated??
545  allocate (this%status(this%nlakes))
546  !
547  do n = 1, this%nlakes
548  this%ntabrow(n) = 0
549  this%status(n) = 'ACTIVE'
550  this%laketop(n) = -dep20
551  this%lakebot(n) = dep20
552  this%sareamax(n) = dzero
553  this%iboundpak(n) = 1
554  this%xnewpak(n) = dep20
555  this%xoldpak(n) = dep20
556  !
557  ! -- initialize boundary values to zero
558  this%rainfall(n) = dzero
559  this%evaporation(n) = dzero
560  this%runoff(n) = dzero
561  this%inflow(n) = dzero
562  this%withdrawal(n) = dzero
563  end do
564  !
565  ! -- allocate local storage for aux variables
566  if (this%naux > 0) then
567  allocate (caux(this%naux))
568  end if
569  !
570  ! -- allocate and initialize temporary variables
571  allocate (nboundchk(this%nlakes))
572  do n = 1, this%nlakes
573  nboundchk(n) = 0
574  end do
575  !
576  ! -- read lake well data
577  ! -- get lakes block
578  call this%parser%GetBlock('PACKAGEDATA', isfound, ierr, &
579  supportopenclose=.true.)
580  !
581  ! -- parse locations block if detected
582  if (isfound) then
583  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
584  ' PACKAGEDATA'
585  nlak = 0
586  nconn = 0
587  do
588  call this%parser%GetNextLine(endofblock)
589  if (endofblock) exit
590  n = this%parser%GetInteger()
591  !
592  if (n < 1 .or. n > this%nlakes) then
593  write (errmsg, '(a,1x,i0)') 'lakeno MUST BE > 0 and <= ', this%nlakes
594  call store_error(errmsg)
595  cycle
596  end if
597  !
598  ! -- increment nboundchk
599  nboundchk(n) = nboundchk(n) + 1
600  !
601  ! -- strt
602  this%strt(n) = this%parser%GetDouble()
603  !
604  ! nlakeconn
605  ival = this%parser%GetInteger()
606  !
607  if (ival < 0) then
608  write (errmsg, '(a,1x,i0)') 'nlakeconn MUST BE >= 0 for lake ', n
609  call store_error(errmsg)
610  end if
611  !
612  nconn = nconn + ival
613  this%nlakeconn(n) = ival
614  !
615  ! -- get aux data
616  do iaux = 1, this%naux
617  call this%parser%GetString(caux(iaux))
618  end do
619  !
620  ! -- set default bndName
621  write (cno, '(i9.9)') n
622  bndname = 'Lake'//cno
623  !
624  ! -- lakename
625  if (this%inamedbound /= 0) then
626  call this%parser%GetStringCaps(bndnametemp)
627  if (bndnametemp /= '') then
628  bndname = bndnametemp
629  end if
630  end if
631  this%lakename(n) = bndname
632  !
633  ! -- fill time series aware data
634  ! -- fill aux data
635  do jj = 1, this%naux
636  text = caux(jj)
637  ii = n
638  bndelem => this%lauxvar(jj, ii)
639  call read_value_or_time_series_adv(text, ii, jj, bndelem, &
640  this%packName, 'AUX', &
641  this%tsManager, this%iprpak, &
642  this%auxname(jj))
643  end do
644  !
645  nlak = nlak + 1
646  end do
647  !
648  ! -- check for duplicate or missing lakes
649  do n = 1, this%nlakes
650  if (nboundchk(n) == 0) then
651  write (errmsg, '(a,1x,i0)') 'NO DATA SPECIFIED FOR LAKE', n
652  call store_error(errmsg)
653  else if (nboundchk(n) > 1) then
654  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
655  'DATA FOR LAKE', n, 'SPECIFIED', nboundchk(n), 'TIMES'
656  call store_error(errmsg)
657  end if
658  end do
659  !
660  write (this%iout, '(1x,a)') 'END OF '//trim(adjustl(this%text))// &
661  ' PACKAGEDATA'
662  else
663  call store_error('REQUIRED PACKAGEDATA BLOCK NOT FOUND.')
664  end if
665  !
666  ! -- terminate if any errors were detected
667  if (count_errors() > 0) then
668  call this%parser%StoreErrorUnit()
669  end if
670  !
671  ! -- set MAXBOUND
672  this%MAXBOUND = nconn
673  write (this%iout, '(//4x,a,i7)') 'MAXBOUND = ', this%maxbound
674  !
675  ! -- set idxlakeconn
676  this%idxlakeconn(1) = 1
677  do n = 1, this%nlakes
678  this%idxlakeconn(n + 1) = this%idxlakeconn(n) + this%nlakeconn(n)
679  end do
680  !
681  ! -- deallocate local storage for aux variables
682  if (this%naux > 0) then
683  deallocate (caux)
684  end if
685  !
686  ! -- deallocate local storage for nboundchk
687  deallocate (nboundchk)
688  !
689  ! -- Return
690  return
691  end subroutine lak_read_lakes
692 
693  !> @brief Read the lake connections for this package
694  !<
695  subroutine lak_read_lake_connections(this)
698  ! -- dummy
699  class(laktype), intent(inout) :: this
700  ! -- local
701  character(len=LINELENGTH) :: keyword, cellid
702  integer(I4B) :: ierr, ival
703  logical(LGP) :: isfound, endOfBlock
704  logical(LGP) :: is_lake_bed
705  real(DP) :: rval
706  integer(I4B) :: j, n
707  integer(I4B) :: nn
708  integer(I4B) :: ipos, ipos0
709  integer(I4B) :: icellid, icellid0
710  real(DP) :: top
711  real(DP) :: bot
712  integer(I4B), dimension(:), pointer, contiguous :: nboundchk
713  character(len=LENVARNAME) :: ctypenm
714  !
715  ! -- allocate local storage
716  allocate (nboundchk(this%MAXBOUND))
717  do n = 1, this%MAXBOUND
718  nboundchk(n) = 0
719  end do
720  !
721  ! -- get connectiondata block
722  call this%parser%GetBlock('CONNECTIONDATA', isfound, ierr, &
723  supportopenclose=.true.)
724  !
725  ! -- parse connectiondata block if detected
726  if (isfound) then
727  ! -- allocate connection data using memory manager
728  call mem_allocate(this%imap, this%MAXBOUND, 'IMAP', this%memoryPath)
729  call mem_allocate(this%cellid, this%MAXBOUND, 'CELLID', this%memoryPath)
730  call mem_allocate(this%nodesontop, this%MAXBOUND, 'NODESONTOP', &
731  this%memoryPath)
732  call mem_allocate(this%ictype, this%MAXBOUND, 'ICTYPE', this%memoryPath)
733  call mem_allocate(this%bedleak, this%MAXBOUND, 'BEDLEAK', this%memoryPath) ! don't need to save this - use a temporary vector
734  call mem_allocate(this%belev, this%MAXBOUND, 'BELEV', this%memoryPath)
735  call mem_allocate(this%telev, this%MAXBOUND, 'TELEV', this%memoryPath)
736  call mem_allocate(this%connlength, this%MAXBOUND, 'CONNLENGTH', &
737  this%memoryPath)
738  call mem_allocate(this%connwidth, this%MAXBOUND, 'CONNWIDTH', &
739  this%memoryPath)
740  call mem_allocate(this%sarea, this%MAXBOUND, 'SAREA', this%memoryPath)
741  call mem_allocate(this%warea, this%MAXBOUND, 'WAREA', this%memoryPath)
742  call mem_allocate(this%satcond, this%MAXBOUND, 'SATCOND', this%memoryPath)
743  call mem_allocate(this%simcond, this%MAXBOUND, 'SIMCOND', this%memoryPath)
744  call mem_allocate(this%simlakgw, this%MAXBOUND, 'SIMLAKGW', this%memoryPath)
745  !
746  ! -- process the lake connection data
747  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
748  ' LAKE_CONNECTIONS'
749  do
750  call this%parser%GetNextLine(endofblock)
751  if (endofblock) exit
752  n = this%parser%GetInteger()
753  !
754  if (n < 1 .or. n > this%nlakes) then
755  write (errmsg, '(a,1x,i0)') 'lakeno MUST BE > 0 and <= ', this%nlakes
756  call store_error(errmsg)
757  cycle
758  end if
759  !
760  ! -- read connection number
761  ival = this%parser%GetInteger()
762  if (ival < 1 .or. ival > this%nlakeconn(n)) then
763  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
764  'iconn FOR LAKE ', n, 'MUST BE > 1 and <= ', this%nlakeconn(n)
765  call store_error(errmsg)
766  cycle
767  end if
768  !
769  j = ival
770  ipos = this%idxlakeconn(n) + ival - 1
771  !
772  ! -- set imap
773  this%imap(ipos) = n
774  !
775  !
776  ! -- increment nboundchk
777  nboundchk(ipos) = nboundchk(ipos) + 1
778  !
779  ! -- read gwfnodes from the line
780  call this%parser%GetCellid(this%dis%ndim, cellid)
781  nn = this%dis%noder_from_cellid(cellid, &
782  this%parser%iuactive, this%iout)
783  !
784  ! -- determine if a valid cell location was provided
785  if (nn < 1) then
786  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
787  'INVALID cellid FOR LAKE ', n, 'connection', j
788  call store_error(errmsg)
789  end if
790  !
791  ! -- set gwf cellid for connection
792  this%cellid(ipos) = nn
793  this%nodesontop(ipos) = nn
794  !
795  ! -- read ictype
796  call this%parser%GetStringCaps(keyword)
797  select case (keyword)
798  case ('VERTICAL')
799  this%ictype(ipos) = 0
800  case ('HORIZONTAL')
801  this%ictype(ipos) = 1
802  case ('EMBEDDEDH')
803  this%ictype(ipos) = 2
804  case ('EMBEDDEDV')
805  this%ictype(ipos) = 3
806  case default
807  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,a,a)') &
808  'UNKNOWN ctype FOR LAKE ', n, 'connection', j, &
809  '(', trim(keyword), ')'
810  call store_error(errmsg)
811  end select
812  write (ctypenm, '(a16)') keyword
813  !
814  ! -- bed leakance
815  !this%bedleak(ipos) = this%parser%GetDouble() !TODO: use this when NONE keyword deprecated
816  call this%parser%GetStringCaps(keyword)
817  select case (keyword)
818  case ('NONE')
819  is_lake_bed = .false.
820  this%bedleak(ipos) = dnodata
821  !
822  ! -- create warning message
823  write (warnmsg, '(2(a,1x,i0,1x),a,1pe8.1,a)') &
824  'BEDLEAK for connection', j, 'in lake', n, 'is specified to '// &
825  'be NONE. Lake connections where the lake-GWF connection '// &
826  'conductance is solely a function of aquifer properties '// &
827  'in the connected GWF cell should be specified with a '// &
828  'DNODATA (', dnodata, ') value.'
829  !
830  ! -- create deprecation warning
831  call deprecation_warning('CONNECTIONDATA', 'bedleak=NONE', '6.4.3', &
832  warnmsg, this%parser%GetUnit())
833  case default
834  read (keyword, *) rval
835  if (is_close(rval, dnodata)) then
836  is_lake_bed = .false.
837  else
838  is_lake_bed = .true.
839  end if
840  this%bedleak(ipos) = rval
841  end select
842  !
843  if (is_lake_bed .and. this%bedleak(ipos) < dzero) then
844  write (errmsg, '(a,1x,i0,1x,a)') 'bedleak FOR LAKE ', n, 'MUST BE >= 0'
845  call store_error(errmsg)
846  end if
847  !
848  ! -- belev
849  this%belev(ipos) = this%parser%GetDouble()
850  !
851  ! -- telev
852  this%telev(ipos) = this%parser%GetDouble()
853  !
854  ! -- connection length
855  rval = this%parser%GetDouble()
856  if (rval <= dzero) then
857  if (this%ictype(ipos) == 1 .or. this%ictype(ipos) == 2 .or. &
858  this%ictype(ipos) == 3) then
859  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,a,1x,a)') &
860  'connection length (connlen) FOR LAKE ', n, &
861  ', CONNECTION NO.', j, ', MUST BE > 0 FOR SPECIFIED ', &
862  'connection type (ctype)', ctypenm
863  call store_error(errmsg)
864  else
865  rval = dzero
866  end if
867  end if
868  this%connlength(ipos) = rval
869  !
870  ! -- connection width
871  rval = this%parser%GetDouble()
872  if (rval < dzero) then
873  if (this%ictype(ipos) == 1) then
874  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
875  'cell width (connwidth) FOR LAKE ', n, &
876  ' HORIZONTAL CONNECTION ', j, 'MUST BE >= 0'
877  call store_error(errmsg)
878  else
879  rval = dzero
880  end if
881  end if
882  this%connwidth(ipos) = rval
883  end do
884  write (this%iout, '(1x,a)') &
885  'END OF '//trim(adjustl(this%text))//' CONNECTIONDATA'
886  else
887  call store_error('REQUIRED CONNECTIONDATA BLOCK NOT FOUND.')
888  end if
889  !
890  ! -- terminate if any errors were detected
891  if (count_errors() > 0) then
892  call this%parser%StoreErrorUnit()
893  end if
894  !
895  ! -- check that embedded lakes have only one connection
896  do n = 1, this%nlakes
897  j = 0
898  do ipos = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
899  if (this%ictype(ipos) /= 2 .and. this%ictype(ipos) /= 3) cycle
900  j = j + 1
901  if (j > 1) then
902  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
903  'nlakeconn FOR LAKE', n, 'EMBEDDED CONNECTION', j, ' EXCEEDS 1.'
904  call store_error(errmsg)
905  end if
906  end do
907  end do
908  ! -- check that an embedded lake is not in the same cell as a lake
909  ! with a vertical connection
910  do n = 1, this%nlakes
911  ipos0 = this%idxlakeconn(n)
912  icellid0 = this%cellid(ipos0)
913  if (this%ictype(ipos0) /= 2 .and. this%ictype(ipos0) /= 3) cycle
914  do nn = 1, this%nlakes
915  if (nn == n) cycle
916  j = 0
917  do ipos = this%idxlakeconn(nn), this%idxlakeconn(nn + 1) - 1
918  j = j + 1
919  icellid = this%cellid(ipos)
920  if (icellid == icellid0) then
921  if (this%ictype(ipos) == 0) then
922  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,1x,i0,1x,a)') &
923  'EMBEDDED LAKE', n, &
924  'CANNOT COINCIDE WITH VERTICAL CONNECTION', j, &
925  'IN LAKE', nn, '.'
926  call store_error(errmsg)
927  end if
928  end if
929  end do
930  end do
931  end do
932  !
933  ! -- process the data
934  do n = 1, this%nlakes
935  j = 0
936  do ipos = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
937  j = j + 1
938  nn = this%cellid(ipos)
939  top = this%dis%top(nn)
940  bot = this%dis%bot(nn)
941  ! vertical connection
942  if (this%ictype(ipos) == 0) then
943  this%telev(ipos) = top + this%surfdep
944  this%belev(ipos) = top
945  this%lakebot(n) = min(this%belev(ipos), this%lakebot(n))
946  ! horizontal connection
947  else if (this%ictype(ipos) == 1) then
948  if (this%belev(ipos) == this%telev(ipos)) then
949  this%telev(ipos) = top
950  this%belev(ipos) = bot
951  else
952  if (this%belev(ipos) >= this%telev(ipos)) then
953  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
954  'telev FOR LAKE ', n, ' HORIZONTAL CONNECTION ', j, &
955  'MUST BE >= belev'
956  call store_error(errmsg)
957  else if (this%belev(ipos) < bot) then
958  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,1x,g15.7,1x,a)') &
959  'belev FOR LAKE ', n, ' HORIZONTAL CONNECTION ', j, &
960  'MUST BE >= cell bottom (', bot, ')'
961  call store_error(errmsg)
962  else if (this%telev(ipos) > top) then
963  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,1x,g15.7,1x,a)') &
964  'telev FOR LAKE ', n, ' HORIZONTAL CONNECTION ', j, &
965  'MUST BE <= cell top (', top, ')'
966  call store_error(errmsg)
967  end if
968  end if
969  this%laketop(n) = max(this%telev(ipos), this%laketop(n))
970  this%lakebot(n) = min(this%belev(ipos), this%lakebot(n))
971  ! embedded connections
972  else if (this%ictype(ipos) == 2 .or. this%ictype(ipos) == 3) then
973  this%telev(ipos) = top
974  this%belev(ipos) = bot
975  this%lakebot(n) = bot
976  end if
977  !
978  ! -- check for missing or duplicate lake connections
979  if (nboundchk(ipos) == 0) then
980  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
981  'NO DATA SPECIFIED FOR LAKE', n, 'CONNECTION', j
982  call store_error(errmsg)
983  else if (nboundchk(ipos) > 1) then
984  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,1x,i0,1x,a)') &
985  'DATA FOR LAKE', n, 'CONNECTION', j, &
986  'SPECIFIED', nboundchk(ipos), 'TIMES'
987  call store_error(errmsg)
988  end if
989  !
990  ! -- set laketop if it has not been assigned
991  end do
992  if (this%laketop(n) == -dep20) then
993  this%laketop(n) = this%lakebot(n) + 100.
994  end if
995  end do
996  !
997  ! -- deallocate local variable
998  deallocate (nboundchk)
999  !
1000  ! -- write summary of lake_connection error messages
1001  if (count_errors() > 0) then
1002  call this%parser%StoreErrorUnit()
1003  end if
1004  !
1005  ! -- Return
1006  return
1007  end subroutine lak_read_lake_connections
1008 
1009  !> @brief Read the lake tables for this package
1010  !<
1011  subroutine lak_read_tables(this)
1012  use constantsmodule, only: linelength
1013  use simmodule, only: store_error, count_errors
1014  ! -- dummy
1015  class(laktype), intent(inout) :: this
1016  ! -- local
1017  type(laktabtype), dimension(:), allocatable :: laketables
1018  character(len=LINELENGTH) :: line
1019  character(len=LINELENGTH) :: keyword
1020  integer(I4B) :: ierr
1021  logical(LGP) :: isfound, endOfBlock
1022  integer(I4B) :: n
1023  integer(I4B) :: iconn
1024  integer(I4B) :: ntabs
1025  integer(I4B), dimension(:), pointer, contiguous :: nboundchk
1026  !
1027  ! -- skip of no outlets
1028  if (this%ntables < 1) return
1029  !
1030  ! -- allocate and initialize nboundchk
1031  allocate (nboundchk(this%nlakes))
1032  do n = 1, this%nlakes
1033  nboundchk(n) = 0
1034  end do
1035  !
1036  ! -- allocate derived type for table data
1037  allocate (laketables(this%nlakes))
1038  !
1039  ! -- get lake_tables block
1040  call this%parser%GetBlock('TABLES', isfound, ierr, &
1041  supportopenclose=.true.)
1042  !
1043  ! -- parse lake_tables block if detected
1044  if (isfound) then
1045  ntabs = 0
1046  ! -- process the lake table data
1047  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
1048  ' LAKE_TABLES'
1049  readtable: do
1050  call this%parser%GetNextLine(endofblock)
1051  if (endofblock) exit
1052  n = this%parser%GetInteger()
1053  !
1054  if (n < 1 .or. n > this%nlakes) then
1055  write (errmsg, '(a,1x,i0)') 'lakeno MUST BE > 0 and <= ', this%nlakes
1056  call store_error(errmsg)
1057  cycle readtable
1058  end if
1059  !
1060  ! -- increment ntab and nboundchk
1061  ntabs = ntabs + 1
1062  nboundchk(n) = nboundchk(n) + 1
1063  !
1064  ! -- read FILE keyword
1065  call this%parser%GetStringCaps(keyword)
1066  select case (keyword)
1067  case ('TAB6')
1068  call this%parser%GetStringCaps(keyword)
1069  if (trim(adjustl(keyword)) /= 'FILEIN') then
1070  errmsg = 'TAB6 keyword must be followed by "FILEIN" '// &
1071  'then by filename.'
1072  call store_error(errmsg)
1073  cycle readtable
1074  end if
1075  call this%parser%GetString(line)
1076  call this%lak_read_table(n, line, laketables(n))
1077  case default
1078  write (errmsg, '(a,1x,i0,1x,a)') &
1079  'LAKE TABLE ENTRY for LAKE ', n, 'MUST INCLUDE TAB6 KEYWORD'
1080  call store_error(errmsg)
1081  cycle readtable
1082  end select
1083  end do readtable
1084  !
1085  write (this%iout, '(1x,a)') &
1086  'END OF '//trim(adjustl(this%text))//' LAKE_TABLES'
1087  !
1088  ! -- check for missing or duplicate lake connections
1089  if (ntabs < this%ntables) then
1090  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
1091  'TABLE DATA ARE SPECIFIED', ntabs, &
1092  'TIMES BUT NTABLES IS SET TO', this%ntables
1093  call store_error(errmsg)
1094  end if
1095  do n = 1, this%nlakes
1096  if (this%ntabrow(n) > 0 .and. nboundchk(n) > 1) then
1097  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1098  'TABLE DATA FOR LAKE', n, 'SPECIFIED', nboundchk(n), 'TIMES'
1099  call store_error(errmsg)
1100  end if
1101  end do
1102  else
1103  call store_error('REQUIRED TABLES BLOCK NOT FOUND.')
1104  end if
1105  !
1106  ! -- deallocate local storage
1107  deallocate (nboundchk)
1108  !
1109  ! -- write summary of lake_table error messages
1110  if (count_errors() > 0) then
1111  call this%parser%StoreErrorUnit()
1112  end if
1113  !
1114  ! -- convert laketables to vectors
1115  call this%laktables_to_vectors(laketables)
1116  !
1117  ! -- destroy laketables
1118  do n = 1, this%nlakes
1119  if (this%ntabrow(n) > 0) then
1120  deallocate (laketables(n)%tabstage)
1121  deallocate (laketables(n)%tabvolume)
1122  deallocate (laketables(n)%tabsarea)
1123  iconn = this%idxlakeconn(n)
1124  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
1125  deallocate (laketables(n)%tabwarea)
1126  end if
1127  end if
1128  end do
1129  deallocate (laketables)
1130  !
1131  ! -- Return
1132  return
1133  end subroutine lak_read_tables
1134 
1135  !> @brief Copy the laketables structure data into flattened vectors that are
1136  !! stored in the memory manager
1137  !<
1138  subroutine laktables_to_vectors(this, laketables)
1139  class(laktype), intent(inout) :: this
1140  type(laktabtype), intent(in), dimension(:), contiguous :: laketables
1141  integer(I4B) :: n
1142  integer(I4B) :: ntabrows
1143  integer(I4B) :: j
1144  integer(I4B) :: ipos
1145  integer(I4B) :: iconn
1146  !
1147  ! -- allocate index array for lak tables
1148  call mem_allocate(this%ialaktab, this%nlakes + 1, 'IALAKTAB', this%memoryPath)
1149  !
1150  ! -- Move the laktables structure information into flattened arrays
1151  this%ialaktab(1) = 1
1152  do n = 1, this%nlakes
1153  ! -- ialaktab contains a pointer into the flattened lak table data
1154  this%ialaktab(n + 1) = this%ialaktab(n) + this%ntabrow(n)
1155  end do
1156  !
1157  ! -- Allocate vectors for storing all lake table data
1158  ntabrows = this%ialaktab(this%nlakes + 1) - 1
1159  call mem_allocate(this%tabstage, ntabrows, 'TABSTAGE', this%memoryPath)
1160  call mem_allocate(this%tabvolume, ntabrows, 'TABVOLUME', this%memoryPath)
1161  call mem_allocate(this%tabsarea, ntabrows, 'TABSAREA', this%memoryPath)
1162  call mem_allocate(this%tabwarea, ntabrows, 'TABWAREA', this%memoryPath)
1163  !
1164  ! -- Copy data from laketables into vectors
1165  do n = 1, this%nlakes
1166  j = 1
1167  do ipos = this%ialaktab(n), this%ialaktab(n + 1) - 1
1168  this%tabstage(ipos) = laketables(n)%tabstage(j)
1169  this%tabvolume(ipos) = laketables(n)%tabvolume(j)
1170  this%tabsarea(ipos) = laketables(n)%tabsarea(j)
1171  iconn = this%idxlakeconn(n)
1172  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
1173  !
1174  ! -- tabwarea only filled for ictype 2 and 3
1175  this%tabwarea(ipos) = laketables(n)%tabwarea(j)
1176  else
1177  this%tabwarea(ipos) = dzero
1178  end if
1179  j = j + 1
1180  end do
1181  end do
1182  !
1183  ! -- Return
1184  return
1185  end subroutine laktables_to_vectors
1186 
1187  !> @brief Read the lake table for this package
1188  !<
1189  subroutine lak_read_table(this, ilak, filename, laketable)
1190  use constantsmodule, only: linelength
1191  use inputoutputmodule, only: openfile
1192  use simmodule, only: store_error, count_errors
1193  ! -- dummy
1194  class(laktype), intent(inout) :: this
1195  integer(I4B), intent(in) :: ilak
1196  character(len=*), intent(in) :: filename
1197  type(laktabtype), intent(inout) :: laketable
1198  ! -- local
1199  character(len=LINELENGTH) :: keyword
1200  integer(I4B) :: ierr
1201  logical(LGP) :: isfound, endOfBlock
1202  integer(I4B) :: iu
1203  integer(I4B) :: n
1204  integer(I4B) :: ipos
1205  integer(I4B) :: j
1206  integer(I4B) :: jmin
1207  integer(I4B) :: iconn
1208  real(DP) :: vol
1209  real(DP) :: sa
1210  real(DP) :: wa
1211  real(DP) :: v
1212  real(DP) :: v0
1213  type(blockparsertype) :: parser
1214  ! -- formats
1215  character(len=*), parameter :: fmttaberr = &
1216  &'(a,1x,i0,1x,a,1x,g15.6,1x,a,1x,i0,1x,a,1x,i0,1x,a,1x,g15.6,1x,a)'
1217  !
1218  ! -- initialize locals
1219  n = 0
1220  j = 0
1221  !
1222  ! -- open the table file
1223  iu = 0
1224  call openfile(iu, this%iout, filename, 'LAKE TABLE')
1225  call parser%Initialize(iu, this%iout)
1226  !
1227  ! -- get dimensions block
1228  call parser%GetBlock('DIMENSIONS', isfound, ierr, supportopenclose=.true.)
1229  !
1230  ! -- parse lak table dimensions block if detected
1231  if (isfound) then
1232  ! -- process the lake table dimension data
1233  if (this%iprpak /= 0) then
1234  write (this%iout, '(/1x,a)') &
1235  'PROCESSING '//trim(adjustl(this%text))//' DIMENSIONS'
1236  end if
1237  readdims: do
1238  call parser%GetNextLine(endofblock)
1239  if (endofblock) exit
1240  call parser%GetStringCaps(keyword)
1241  select case (keyword)
1242  case ('NROW')
1243  n = parser%GetInteger()
1244 
1245  if (n < 1) then
1246  write (errmsg, '(a)') 'LAKE TABLE NROW MUST BE > 0'
1247  call store_error(errmsg)
1248  end if
1249  case ('NCOL')
1250  j = parser%GetInteger()
1251 
1252  if (this%ictype(ilak) == 2 .or. this%ictype(ilak) == 3) then
1253  jmin = 4
1254  else
1255  jmin = 3
1256  end if
1257  if (j < jmin) then
1258  write (errmsg, '(a,1x,i0)') 'LAKE TABLE NCOL MUST BE >= ', jmin
1259  call store_error(errmsg)
1260  end if
1261  !
1262  case default
1263  write (errmsg, '(a,a)') &
1264  'UNKNOWN '//trim(this%text)//' DIMENSIONS KEYWORD: ', trim(keyword)
1265  call store_error(errmsg)
1266  end select
1267  end do readdims
1268  if (this%iprpak /= 0) then
1269  write (this%iout, '(1x,a)') &
1270  'END OF '//trim(adjustl(this%text))//' DIMENSIONS'
1271  end if
1272  else
1273  call store_error('REQUIRED DIMENSIONS BLOCK NOT FOUND.')
1274  end if
1275  !
1276  ! -- check that ncol and nrow have been specified
1277  if (n < 1) then
1278  write (errmsg, '(a)') &
1279  'NROW NOT SPECIFIED IN THE LAKE TABLE DIMENSIONS BLOCK'
1280  call store_error(errmsg)
1281  end if
1282  if (j < 1) then
1283  write (errmsg, '(a)') &
1284  'NCOL NOT SPECIFIED IN THE LAKE TABLE DIMENSIONS BLOCK'
1285  call store_error(errmsg)
1286  end if
1287  !
1288  ! -- only read the lake table data if n and j are specified to be greater
1289  ! than zero
1290  if (n * j > 0) then
1291  !
1292  ! -- allocate space
1293  this%ntabrow(ilak) = n
1294  allocate (laketable%tabstage(n))
1295  allocate (laketable%tabvolume(n))
1296  allocate (laketable%tabsarea(n))
1297  ipos = this%idxlakeconn(ilak)
1298  if (this%ictype(ipos) == 2 .or. this%ictype(ipos) == 3) then
1299  allocate (laketable%tabwarea(n))
1300  end if
1301  !
1302  ! -- get table block
1303  call parser%GetBlock('TABLE', isfound, ierr, supportopenclose=.true.)
1304  !
1305  ! -- parse well_connections block if detected
1306  if (isfound) then
1307  !
1308  ! -- process the table data
1309  if (this%iprpak /= 0) then
1310  write (this%iout, '(/1x,a)') &
1311  'PROCESSING '//trim(adjustl(this%text))//' TABLE'
1312  end if
1313  iconn = this%idxlakeconn(ilak)
1314  ipos = 0
1315  readtabledata: do
1316  call parser%GetNextLine(endofblock)
1317  if (endofblock) exit
1318  ipos = ipos + 1
1319  if (ipos > this%ntabrow(ilak)) then
1320  cycle readtabledata
1321  end if
1322  laketable%tabstage(ipos) = parser%GetDouble()
1323  laketable%tabvolume(ipos) = parser%GetDouble()
1324  laketable%tabsarea(ipos) = parser%GetDouble()
1325  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
1326  laketable%tabwarea(ipos) = parser%GetDouble()
1327  end if
1328  end do readtabledata
1329  !
1330  if (this%iprpak /= 0) then
1331  write (this%iout, '(1x,a)') &
1332  'END OF '//trim(adjustl(this%text))//' TABLE'
1333  end if
1334  else
1335  call store_error('REQUIRED TABLE BLOCK NOT FOUND.')
1336  end if
1337  !
1338  ! -- error condition if number of rows read are not equal to nrow
1339  if (ipos /= this%ntabrow(ilak)) then
1340  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1341  'NROW SET TO', this%ntabrow(ilak), 'BUT', ipos, 'ROWS WERE READ'
1342  call store_error(errmsg)
1343  end if
1344  !
1345  ! -- set lake bottom based on table if it is an embedded lake
1346  iconn = this%idxlakeconn(ilak)
1347  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
1348  do n = 1, this%ntabrow(ilak)
1349  vol = laketable%tabvolume(n)
1350  sa = laketable%tabsarea(n)
1351  wa = laketable%tabwarea(n)
1352  vol = vol * sa * wa
1353  ! -- check if all entries are zero
1354  if (vol > dzero) exit
1355  ! -- set lake bottom
1356  this%lakebot(ilak) = laketable%tabstage(n)
1357  this%belev(ilak) = laketable%tabstage(n)
1358  end do
1359  ! -- set maximum surface area for rainfall
1360  n = this%ntabrow(ilak)
1361  this%sareamax(ilak) = laketable%tabsarea(n)
1362  end if
1363  !
1364  ! -- verify the table data
1365  do n = 2, this%ntabrow(ilak)
1366  v = laketable%tabstage(n)
1367  v0 = laketable%tabstage(n - 1)
1368  if (v <= v0) then
1369  write (errmsg, fmttaberr) &
1370  'TABLE STAGE ENTRY', n, '(', laketable%tabstage(n), ') FOR LAKE ', &
1371  ilak, 'MUST BE GREATER THAN THE PREVIOUS STAGE ENTRY', &
1372  n - 1, '(', laketable%tabstage(n - 1), ')'
1373  call store_error(errmsg)
1374  end if
1375  v = laketable%tabvolume(n)
1376  v0 = laketable%tabvolume(n - 1)
1377  if (v <= v0) then
1378  write (errmsg, fmttaberr) &
1379  'TABLE VOLUME ENTRY', n, '(', laketable%tabvolume(n), &
1380  ') FOR LAKE ', &
1381  ilak, 'MUST BE GREATER THAN THE PREVIOUS VOLUME ENTRY', &
1382  n - 1, '(', laketable%tabvolume(n - 1), ')'
1383  call store_error(errmsg)
1384  end if
1385  v = laketable%tabsarea(n)
1386  v0 = laketable%tabsarea(n - 1)
1387  if (v < v0) then
1388  write (errmsg, fmttaberr) &
1389  'TABLE SURFACE AREA ENTRY', n, '(', &
1390  laketable%tabsarea(n), ') FOR LAKE ', ilak, &
1391  'MUST BE GREATER THAN OR EQUAL TO THE PREVIOUS SURFACE AREA ENTRY', &
1392  n - 1, '(', laketable%tabsarea(n - 1), ')'
1393  call store_error(errmsg)
1394  end if
1395  iconn = this%idxlakeconn(ilak)
1396  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
1397  v = laketable%tabwarea(n)
1398  v0 = laketable%tabwarea(n - 1)
1399  if (v < v0) then
1400  write (errmsg, fmttaberr) &
1401  'TABLE EXCHANGE AREA ENTRY', n, '(', &
1402  laketable%tabwarea(n), ') FOR LAKE ', ilak, &
1403  'MUST BE GREATER THAN OR EQUAL TO THE PREVIOUS EXCHANGE AREA '// &
1404  'ENTRY', n - 1, '(', laketable%tabwarea(n - 1), ')'
1405  call store_error(errmsg)
1406  end if
1407  end if
1408  end do
1409  end if
1410  !
1411  ! -- write summary of lake table error messages
1412  if (count_errors() > 0) then
1413  call parser%StoreErrorUnit()
1414  end if
1415  !
1416  ! Close the table file and clear other parser members
1417  call parser%Clear()
1418  !
1419  ! -- Return
1420  return
1421  end subroutine lak_read_table
1422 
1423  !> @brief Read the lake outlets for this package
1424  !<
1425  subroutine lak_read_outlets(this)
1426  use constantsmodule, only: linelength
1427  use simmodule, only: store_error, count_errors
1429  ! -- dummy
1430  class(laktype), intent(inout) :: this
1431  ! -- local
1432  character(len=LINELENGTH) :: text, keyword
1433  character(len=LENBOUNDNAME) :: bndName
1434  character(len=9) :: citem
1435  integer(I4B) :: ierr, ival
1436  logical(LGP) :: isfound, endOfBlock
1437  integer(I4B) :: n
1438  integer(I4B) :: jj
1439  integer(I4B), dimension(:), pointer, contiguous :: nboundchk
1440  real(DP), pointer :: bndElem => null()
1441  !
1442  ! -- get well_connections block
1443  call this%parser%GetBlock('OUTLETS', isfound, ierr, &
1444  supportopenclose=.true., blockrequired=.false.)
1445  !
1446  ! -- parse outlets block if detected
1447  if (isfound) then
1448  if (this%noutlets > 0) then
1449  !
1450  ! -- allocate and initialize local variables
1451  allocate (nboundchk(this%noutlets))
1452  do n = 1, this%noutlets
1453  nboundchk(n) = 0
1454  end do
1455  !
1456  ! -- allocate outlet data using memory manager
1457  call mem_allocate(this%lakein, this%NOUTLETS, 'LAKEIN', this%memoryPath)
1458  call mem_allocate(this%lakeout, this%NOUTLETS, 'LAKEOUT', this%memoryPath)
1459  call mem_allocate(this%iouttype, this%NOUTLETS, 'IOUTTYPE', &
1460  this%memoryPath)
1461  call mem_allocate(this%outrate, this%NOUTLETS, 'OUTRATE', this%memoryPath)
1462  call mem_allocate(this%outinvert, this%NOUTLETS, 'OUTINVERT', &
1463  this%memoryPath)
1464  call mem_allocate(this%outwidth, this%NOUTLETS, 'OUTWIDTH', &
1465  this%memoryPath)
1466  call mem_allocate(this%outrough, this%NOUTLETS, 'OUTROUGH', &
1467  this%memoryPath)
1468  call mem_allocate(this%outslope, this%NOUTLETS, 'OUTSLOPE', &
1469  this%memoryPath)
1470  call mem_allocate(this%simoutrate, this%NOUTLETS, 'SIMOUTRATE', &
1471  this%memoryPath)
1472  !
1473  ! -- initialize outlet rate
1474  do n = 1, this%noutlets
1475  this%outrate(n) = dzero
1476  end do
1477  !
1478  ! -- process the lake connection data
1479  write (this%iout, '(/1x,a)') &
1480  'PROCESSING '//trim(adjustl(this%text))//' OUTLETS'
1481  readoutlet: do
1482  call this%parser%GetNextLine(endofblock)
1483  if (endofblock) exit
1484  n = this%parser%GetInteger()
1485 
1486  if (n < 1 .or. n > this%noutlets) then
1487  write (errmsg, '(a,1x,i0)') &
1488  'outletno MUST BE > 0 and <= ', this%noutlets
1489  call store_error(errmsg)
1490  cycle readoutlet
1491  end if
1492  !
1493  ! -- increment nboundchk
1494  nboundchk(n) = nboundchk(n) + 1
1495  !
1496  ! -- read outlet lakein
1497  ival = this%parser%GetInteger()
1498  if (ival < 1 .or. ival > this%nlakes) then
1499  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
1500  'lakein FOR OUTLET ', n, 'MUST BE > 0 and <= ', this%nlakes
1501  call store_error(errmsg)
1502  cycle readoutlet
1503  end if
1504  this%lakein(n) = ival
1505  !
1506  ! -- read outlet lakeout
1507  ival = this%parser%GetInteger()
1508  if (ival < 0 .or. ival > this%nlakes) then
1509  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
1510  'lakeout FOR OUTLET ', n, 'MUST BE >= 0 and <= ', this%nlakes
1511  call store_error(errmsg)
1512  cycle readoutlet
1513  end if
1514  this%lakeout(n) = ival
1515  !
1516  ! -- read ictype
1517  call this%parser%GetStringCaps(keyword)
1518  select case (keyword)
1519  case ('SPECIFIED')
1520  this%iouttype(n) = 0
1521  case ('MANNING')
1522  this%iouttype(n) = 1
1523  case ('WEIR')
1524  this%iouttype(n) = 2
1525  case default
1526  write (errmsg, '(a,1x,i0,1x,a,a,a)') &
1527  'UNKNOWN couttype FOR OUTLET ', n, '(', trim(keyword), ')'
1528  call store_error(errmsg)
1529  cycle readoutlet
1530  end select
1531  !
1532  ! -- build bndname for outlet
1533  write (citem, '(i9.9)') n
1534  bndname = 'OUTLET'//citem
1535  !
1536  ! -- set a few variables for timeseries aware variables
1537  jj = 1
1538  !
1539  ! -- outlet invert
1540  call this%parser%GetString(text)
1541  bndelem => this%outinvert(n)
1542  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1543  this%packName, 'BND', &
1544  this%tsManager, this%iprpak, &
1545  'INVERT')
1546  !
1547  ! -- outlet width
1548  call this%parser%GetString(text)
1549  bndelem => this%outwidth(n)
1550  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1551  this%packName, 'BND', &
1552  this%tsManager, this%iprpak, 'WIDTH')
1553  !
1554  ! -- outlet roughness
1555  call this%parser%GetString(text)
1556  bndelem => this%outrough(n)
1557  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1558  this%packName, 'BND', &
1559  this%tsManager, this%iprpak, 'ROUGH')
1560  !
1561  ! -- outlet slope
1562  call this%parser%GetString(text)
1563  bndelem => this%outslope(n)
1564  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1565  this%packName, 'BND', &
1566  this%tsManager, this%iprpak, 'SLOPE')
1567  end do readoutlet
1568  write (this%iout, '(1x,a)') 'END OF '//trim(adjustl(this%text))// &
1569  ' OUTLETS'
1570  !
1571  ! -- check for duplicate or missing outlets
1572  do n = 1, this%noutlets
1573  if (nboundchk(n) == 0) then
1574  write (errmsg, '(a,1x,i0)') 'NO DATA SPECIFIED FOR OUTLET', n
1575  call store_error(errmsg)
1576  else if (nboundchk(n) > 1) then
1577  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1578  'DATA FOR OUTLET', n, 'SPECIFIED', nboundchk(n), 'TIMES'
1579  call store_error(errmsg)
1580  end if
1581  end do
1582  !
1583  ! -- deallocate local storage
1584  deallocate (nboundchk)
1585  else
1586  write (errmsg, '(a,1x,a)') &
1587  'AN OUTLETS BLOCK SHOULD NOT BE SPECIFIED IF NOUTLETS IS NOT', &
1588  'SPECIFIED OR IS SPECIFIED TO BE 0.'
1589  call store_error(errmsg)
1590  end if
1591  !
1592  else
1593  if (this%noutlets > 0) then
1594  call store_error('REQUIRED OUTLETS BLOCK NOT FOUND.')
1595  end if
1596  end if
1597  !
1598  ! -- write summary of lake_connection error messages
1599  ierr = count_errors()
1600  if (ierr > 0) then
1601  call this%parser%StoreErrorUnit()
1602  end if
1603  !
1604  ! -- Return
1605  return
1606  end subroutine lak_read_outlets
1607 
1608  !> @brief Read the dimensions for this package
1609  !<
1610  subroutine lak_read_dimensions(this)
1611  use constantsmodule, only: linelength
1612  use simmodule, only: store_error, count_errors
1613  ! -- dummy
1614  class(laktype), intent(inout) :: this
1615  ! -- local
1616  character(len=LINELENGTH) :: keyword
1617  integer(I4B) :: ierr
1618  logical(LGP) :: isfound, endOfBlock
1619  !
1620  ! -- initialize dimensions to -1
1621  this%nlakes = -1
1622  this%maxbound = -1
1623  !
1624  ! -- get dimensions block
1625  call this%parser%GetBlock('DIMENSIONS', isfound, ierr, &
1626  supportopenclose=.true.)
1627  !
1628  ! -- parse dimensions block if detected
1629  if (isfound) then
1630  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
1631  ' DIMENSIONS'
1632  do
1633  call this%parser%GetNextLine(endofblock)
1634  if (endofblock) exit
1635  call this%parser%GetStringCaps(keyword)
1636  select case (keyword)
1637  case ('NLAKES')
1638  this%nlakes = this%parser%GetInteger()
1639  write (this%iout, '(4x,a,i7)') 'NLAKES = ', this%nlakes
1640  case ('NOUTLETS')
1641  this%noutlets = this%parser%GetInteger()
1642  write (this%iout, '(4x,a,i7)') 'NOUTLETS = ', this%noutlets
1643  case ('NTABLES')
1644  this%ntables = this%parser%GetInteger()
1645  write (this%iout, '(4x,a,i7)') 'NTABLES = ', this%ntables
1646  case default
1647  write (errmsg, '(a,a)') &
1648  'UNKNOWN '//trim(this%text)//' DIMENSION: ', trim(keyword)
1649  call store_error(errmsg)
1650  end select
1651  end do
1652  write (this%iout, '(1x,a)') &
1653  'END OF '//trim(adjustl(this%text))//' DIMENSIONS'
1654  else
1655  call store_error('REQUIRED DIMENSIONS BLOCK NOT FOUND.')
1656  end if
1657  !
1658  if (this%nlakes < 0) then
1659  write (errmsg, '(a)') &
1660  'NLAKES WAS NOT SPECIFIED OR WAS SPECIFIED INCORRECTLY.'
1661  call store_error(errmsg)
1662  end if
1663  !
1664  ! -- stop if errors were encountered in the DIMENSIONS block
1665  if (count_errors() > 0) then
1666  call this%parser%StoreErrorUnit()
1667  end if
1668  !
1669  ! -- read lakes block
1670  call this%lak_read_lakes()
1671  !
1672  ! -- read lake_connections block
1673  call this%lak_read_lake_connections()
1674  !
1675  ! -- read tables block
1676  call this%lak_read_tables()
1677  !
1678  ! -- read outlets block
1679  call this%lak_read_outlets()
1680  !
1681  ! -- Call define_listlabel to construct the list label that is written
1682  ! when PRINT_INPUT option is used.
1683  call this%define_listlabel()
1684  !
1685  ! -- setup the budget object
1686  call this%lak_setup_budobj()
1687  !
1688  ! -- setup the stage table object
1689  call this%lak_setup_tableobj()
1690  !
1691  ! -- Return
1692  return
1693  end subroutine lak_read_dimensions
1694 
1695  !> @brief Read the initial parameters for this package
1696  !<
1697  subroutine lak_read_initial_attr(this)
1698  use constantsmodule, only: linelength
1700  use simmodule, only: store_error, count_errors
1702  ! -- dummy
1703  class(laktype), intent(inout) :: this
1704  ! -- local
1705  character(len=LINELENGTH) :: text
1706  integer(I4B) :: j, jj, n
1707  integer(I4B) :: nn
1708  integer(I4B) :: idx
1709  real(DP) :: top
1710  real(DP) :: bot
1711  real(DP) :: k
1712  real(DP) :: area
1713  real(DP) :: length
1714  real(DP) :: s
1715  real(DP) :: dx
1716  real(DP) :: c
1717  real(DP) :: sa
1718  real(DP) :: wa
1719  real(DP) :: v
1720  real(DP) :: fact
1721  real(DP) :: c1
1722  real(DP) :: c2
1723  real(DP), allocatable, dimension(:) :: clb, caq
1724  character(len=14) :: cbedleak
1725  character(len=14) :: cbedcond
1726  character(len=10), dimension(0:3) :: ctype
1727  character(len=15) :: nodestr
1728  real(DP), pointer :: bndElem => null()
1729  ! -- data
1730  data ctype(0)/'VERTICAL '/
1731  data ctype(1)/'HORIZONTAL'/
1732  data ctype(2)/'EMBEDDEDH '/
1733  data ctype(3)/'EMBEDDEDV '/
1734  !
1735  ! -- initialize xnewpak and set stage
1736  do n = 1, this%nlakes
1737  this%xnewpak(n) = this%strt(n)
1738  write (text, '(g15.7)') this%strt(n)
1739  jj = 1 ! For STAGE
1740  bndelem => this%stage(n)
1741  call read_value_or_time_series_adv(text, n, jj, bndelem, this%packName, &
1742  'BND', this%tsManager, this%iprpak, &
1743  'STAGE')
1744  end do
1745  !
1746  ! -- initialize status (iboundpak) of lakes to active
1747  do n = 1, this%nlakes
1748  if (this%status(n) == 'CONSTANT') then
1749  this%iboundpak(n) = -1
1750  else if (this%status(n) == 'INACTIVE') then
1751  this%iboundpak(n) = 0
1752  else if (this%status(n) == 'ACTIVE ') then
1753  this%iboundpak(n) = 1
1754  end if
1755  end do
1756  !
1757  ! -- set boundname for each connection
1758  if (this%inamedbound /= 0) then
1759  do n = 1, this%nlakes
1760  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
1761  this%boundname(j) = this%lakename(n)
1762  end do
1763  end do
1764  end if
1765  !
1766  ! -- copy boundname into boundname_cst
1767  call this%copy_boundname()
1768  !
1769  ! -- set pointer to gwf iss and gwf hk
1770  call mem_setptr(this%gwfiss, 'ISS', create_mem_path(this%name_model))
1771  call mem_setptr(this%gwfk11, 'K11', create_mem_path(this%name_model, 'NPF'))
1772  call mem_setptr(this%gwfk33, 'K33', create_mem_path(this%name_model, 'NPF'))
1773  call mem_setptr(this%gwfik33, 'IK33', create_mem_path(this%name_model, 'NPF'))
1774  call mem_setptr(this%gwfsat, 'SAT', create_mem_path(this%name_model, 'NPF'))
1775  !
1776  ! -- allocate temporary storage
1777  allocate (clb(this%MAXBOUND))
1778  allocate (caq(this%MAXBOUND))
1779  !
1780  ! -- calculate saturated conductance for each connection
1781  do n = 1, this%nlakes
1782  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
1783  nn = this%cellid(j)
1784  top = this%dis%top(nn)
1785  bot = this%dis%bot(nn)
1786  ! vertical connection
1787  if (this%ictype(j) == 0) then
1788  area = this%dis%area(nn)
1789  this%sarea(j) = area
1790  this%warea(j) = area
1791  this%sareamax(n) = this%sareamax(n) + area
1792  if (this%gwfik33 == 0) then
1793  k = this%gwfk11(nn)
1794  else
1795  k = this%gwfk33(nn)
1796  end if
1797  length = dhalf * (top - bot)
1798  ! horizontal connection
1799  else if (this%ictype(j) == 1) then
1800  area = (this%telev(j) - this%belev(j)) * this%connwidth(j)
1801  ! -- recalculate area if connected cell is confined and lake
1802  ! connection top and bot are equal to the cell top and bot
1803  if (top == this%telev(j) .and. bot == this%belev(j)) then
1804  if (this%icelltype(nn) == 0) then
1805  area = this%gwfsat(nn) * (top - bot) * this%connwidth(j)
1806  end if
1807  end if
1808  this%sarea(j) = dzero
1809  this%warea(j) = area
1810  this%sareamax(n) = this%sareamax(n) + dzero
1811  k = this%gwfk11(nn)
1812  length = this%connlength(j)
1813  ! embedded horizontal connection
1814  else if (this%ictype(j) == 2) then
1815  area = done
1816  this%sarea(j) = dzero
1817  this%warea(j) = area
1818  this%sareamax(n) = this%sareamax(n) + dzero
1819  k = this%gwfk11(nn)
1820  length = this%connlength(j)
1821  ! embedded vertical connection
1822  else if (this%ictype(j) == 3) then
1823  area = done
1824  this%sarea(j) = dzero
1825  this%warea(j) = area
1826  this%sareamax(n) = this%sareamax(n) + dzero
1827  if (this%gwfik33 == 0) then
1828  k = this%gwfk11(nn)
1829  else
1830  k = this%gwfk33(nn)
1831  end if
1832  length = this%connlength(j)
1833  end if
1834  if (is_close(this%bedleak(j), dnodata)) then
1835  clb(j) = dnodata
1836  else if (this%bedleak(j) > dzero) then
1837  clb(j) = done / this%bedleak(j)
1838  else
1839  clb(j) = dzero
1840  end if
1841  if (k > dzero) then
1842  caq(j) = length / k
1843  else
1844  caq(j) = dzero
1845  end if
1846  if (is_close(this%bedleak(j), dnodata)) then
1847  this%satcond(j) = area / caq(j)
1848  else if (clb(j) * caq(j) > dzero) then
1849  this%satcond(j) = area / (clb(j) + caq(j))
1850  else
1851  this%satcond(j) = dzero
1852  end if
1853  end do
1854  end do
1855  !
1856  ! -- write a summary of the conductance
1857  if (this%iprpak > 0) then
1858  write (this%iout, '(//,29x,a,/)') &
1859  'INTERFACE CONDUCTANCE BETWEEN LAKE AND AQUIFER CELLS'
1860  write (this%iout, '(1x,a)') &
1861  & ' LAKE CONNECTION CONNECTION LAKEBED'// &
1862  & ' C O N D U C T A N C E S '
1863  write (this%iout, '(1x,a)') &
1864  & ' NUMBER NUMBER CELLID DIRECTION LEAKANCE'// &
1865  & ' LAKEBED AQUIFER COMBINED'
1866  write (this%iout, "(1x,108('-'))")
1867  do n = 1, this%nlakes
1868  idx = 0
1869  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
1870  idx = idx + 1
1871  fact = done
1872  if (this%ictype(j) == 1) then
1873  fact = this%telev(j) - this%belev(j)
1874  if (abs(fact) > dzero) then
1875  fact = done / fact
1876  end if
1877  end if
1878  nn = this%cellid(j)
1879  area = this%warea(j)
1880  c1 = dzero
1881  if (is_close(clb(j), dnodata)) then
1882  cbedleak = ' NONE '
1883  cbedcond = ' NONE '
1884  else if (clb(j) > dzero) then
1885  c1 = area * fact / clb(j)
1886  write (cbedleak, '(g14.5)') this%bedleak(j)
1887  write (cbedcond, '(g14.5)') c1
1888  else
1889  write (cbedleak, '(g14.5)') c1
1890  write (cbedcond, '(g14.5)') c1
1891  end if
1892  c2 = dzero
1893  if (caq(j) > dzero) then
1894  c2 = area * fact / caq(j)
1895  end if
1896  call this%dis%noder_to_string(nn, nodestr)
1897  write (this%iout, &
1898  '(1x,i10,1x,i10,1x,a15,1x,a10,2(1x,a14),2(1x,g14.5))') &
1899  n, idx, nodestr, ctype(this%ictype(j)), cbedleak, &
1900  cbedcond, c2, this%satcond(j) * fact
1901  end do
1902  end do
1903  write (this%iout, "(1x,108('-'))")
1904  write (this%iout, '(1x,a)') &
1905  'IF VERTICAL CONNECTION, CONDUCTANCE (L^2/T) IS &
1906  &BETWEEN AQUIFER CELL AND OVERLYING LAKE CELL.'
1907  write (this%iout, '(1x,a)') &
1908  'IF HORIZONTAL CONNECTION, CONDUCTANCES ARE PER &
1909  &UNIT SATURATED THICKNESS (L/T).'
1910  write (this%iout, '(1x,a)') &
1911  'IF EMBEDDED CONNECTION, CONDUCTANCES ARE PER &
1912  &UNIT EXCHANGE AREA (1/T).'
1913  !
1914  ! write(this%iout,*) n, idx, nodestr, this%sarea(j), this%warea(j)
1915  !
1916  ! -- calculate stage, surface area, wetted area, volume relation
1917  do n = 1, this%nlakes
1918  write (this%iout, '(//1x,a,1x,i10)') 'STAGE/VOLUME RELATION FOR LAKE ', n
1919  write (this%iout, '(/1x,5(a14))') ' STAGE', ' SURFACE AREA', &
1920  & ' WETTED AREA', ' CONDUCTANCE', &
1921  & ' VOLUME'
1922  write (this%iout, "(1x,70('-'))")
1923  dx = (this%laketop(n) - this%lakebot(n)) / 150.
1924  s = this%lakebot(n)
1925  do j = 1, 151
1926  call this%lak_calculate_conductance(n, s, c)
1927  call this%lak_calculate_sarea(n, s, sa)
1928  call this%lak_calculate_warea(n, s, wa, s)
1929  call this%lak_calculate_vol(n, s, v)
1930  write (this%iout, '(1x,5(E14.5))') s, sa, wa, c, v
1931  s = s + dx
1932  end do
1933  write (this%iout, "(1x,70('-'))")
1934  !
1935  write (this%iout, '(//1x,a,1x,i10)') 'STAGE/VOLUME RELATION FOR LAKE ', n
1936  write (this%iout, '(/1x,4(a14))') ' ', ' ', &
1937  & ' CALCULATED', ' STAGE'
1938  write (this%iout, '(1x,4(a14))') ' STAGE', ' VOLUME', &
1939  & ' STAGE', ' DIFFERENCE'
1940  write (this%iout, "(1x,56('-'))")
1941  s = this%lakebot(n) - dx
1942  do j = 1, 156
1943  call this%lak_calculate_vol(n, s, v)
1944  call this%lak_vol2stage(n, v, c)
1945  write (this%iout, '(1x,4(E14.5))') s, v, c, s - c
1946  s = s + dx
1947  end do
1948  write (this%iout, "(1x,56('-'))")
1949  end do
1950  end if
1951  !
1952  ! -- finished with pointer to gwf hydraulic conductivity
1953  this%gwfk11 => null()
1954  this%gwfk33 => null()
1955  this%gwfsat => null()
1956  this%gwfik33 => null()
1957  !
1958  ! -- deallocate temporary storage
1959  deallocate (clb)
1960  deallocate (caq)
1961  !
1962  ! -- Return
1963  return
1964  end subroutine lak_read_initial_attr
1965 
1966  !> @brief Perform linear interpolation of two vectors.
1967  !!
1968  !! Function assumes x data is sorted in ascending order
1969  !<
1970  subroutine lak_linear_interpolation(this, n, x, y, z, v)
1971  ! -- dummy
1972  class(laktype), intent(inout) :: this
1973  integer(I4B), intent(in) :: n
1974  real(DP), dimension(n), intent(in) :: x
1975  real(DP), dimension(n), intent(in) :: y
1976  real(DP), intent(in) :: z
1977  real(DP), intent(inout) :: v
1978  ! -- local
1979  integer(I4B) :: i
1980  real(DP) :: dx, dydx
1981  ! code
1982  v = dzero
1983  ! below bottom of range - set to lowest value
1984  if (z <= x(1)) then
1985  v = y(1)
1986  ! above highest value
1987  ! slope calculated from interval between n and n-1
1988  else if (z > x(n)) then
1989  dx = x(n) - x(n - 1)
1990  dydx = dzero
1991  if (abs(dx) > dzero) then
1992  dydx = (y(n) - y(n - 1)) / dx
1993  end if
1994  dx = (z - x(n))
1995  v = y(n) + dydx * dx
1996  ! between lowest and highest value in current interval
1997  else
1998  do i = 2, n
1999  dx = x(i) - x(i - 1)
2000  dydx = dzero
2001  if (z >= x(i - 1) .and. z <= x(i)) then
2002  if (abs(dx) > dzero) then
2003  dydx = (y(i) - y(i - 1)) / dx
2004  end if
2005  dx = (z - x(i - 1))
2006  v = y(i - 1) + dydx * dx
2007  exit
2008  end if
2009  end do
2010  end if
2011  !
2012  ! -- Return
2013  return
2014  end subroutine lak_linear_interpolation
2015 
2016  !> @brief Calculate the surface area of a lake at a given stage
2017  !<
2018  subroutine lak_calculate_sarea(this, ilak, stage, sarea)
2019  ! -- dummy
2020  class(laktype), intent(inout) :: this
2021  integer(I4B), intent(in) :: ilak
2022  real(DP), intent(in) :: stage
2023  real(DP), intent(inout) :: sarea
2024  ! -- local
2025  integer(I4B) :: i
2026  integer(I4B) :: ifirst
2027  integer(I4B) :: ilast
2028  real(DP) :: topl
2029  real(DP) :: botl
2030  real(DP) :: sat
2031  real(DP) :: sa
2032  !
2033  sarea = dzero
2034  i = this%ntabrow(ilak)
2035  if (i > 0) then
2036  ifirst = this%ialaktab(ilak)
2037  ilast = this%ialaktab(ilak + 1) - 1
2038  if (stage <= this%tabstage(ifirst)) then
2039  sarea = this%tabsarea(ifirst)
2040  else if (stage >= this%tabstage(ilast)) then
2041  sarea = this%tabsarea(ilast)
2042  else
2043  call this%lak_linear_interpolation(i, this%tabstage(ifirst:ilast), &
2044  this%tabsarea(ifirst:ilast), &
2045  stage, sarea)
2046  end if
2047  else
2048  do i = this%idxlakeconn(ilak), this%idxlakeconn(ilak + 1) - 1
2049  topl = this%telev(i)
2050  botl = this%belev(i)
2051  sat = squadraticsaturation(topl, botl, stage)
2052  sa = sat * this%sarea(i)
2053  sarea = sarea + sa
2054  end do
2055  end if
2056  !
2057  ! -- Return
2058  return
2059  end subroutine lak_calculate_sarea
2060 
2061  !> @brief Calculate the wetted area of a lake at a given stage.
2062  !<
2063  subroutine lak_calculate_warea(this, ilak, stage, warea, hin)
2064  ! -- dummy
2065  class(laktype), intent(inout) :: this
2066  integer(I4B), intent(in) :: ilak
2067  real(DP), intent(in) :: stage
2068  real(DP), intent(inout) :: warea
2069  real(DP), optional, intent(inout) :: hin
2070  ! -- local
2071  integer(I4B) :: i
2072  integer(I4B) :: igwfnode
2073  real(DP) :: head
2074  real(DP) :: wa
2075  !
2076  warea = dzero
2077  do i = this%idxlakeconn(ilak), this%idxlakeconn(ilak + 1) - 1
2078  if (present(hin)) then
2079  head = hin
2080  else
2081  igwfnode = this%cellid(i)
2082  head = this%xnew(igwfnode)
2083  end if
2084  call this%lak_calculate_conn_warea(ilak, i, stage, head, wa)
2085  warea = warea + wa
2086  end do
2087  !
2088  ! -- Return
2089  return
2090  end subroutine lak_calculate_warea
2091 
2092  !> @brief Calculate the wetted area of a lake connection at a given stage
2093  !<
2094  subroutine lak_calculate_conn_warea(this, ilak, iconn, stage, head, wa)
2095  ! -- dummy
2096  class(laktype), intent(inout) :: this
2097  integer(I4B), intent(in) :: ilak
2098  integer(I4B), intent(in) :: iconn
2099  real(DP), intent(in) :: stage
2100  real(DP), intent(in) :: head
2101  real(DP), intent(inout) :: wa
2102  ! -- local
2103  integer(I4B) :: i
2104  integer(I4B) :: ifirst
2105  integer(I4B) :: ilast
2106  integer(I4B) :: node
2107  real(DP) :: topl
2108  real(DP) :: botl
2109  real(DP) :: vv
2110  real(DP) :: sat
2111  !
2112  wa = dzero
2113  topl = this%telev(iconn)
2114  botl = this%belev(iconn)
2115  call this%lak_calculate_cond_head(iconn, stage, head, vv)
2116  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
2117  if (vv > topl) vv = topl
2118  i = this%ntabrow(ilak)
2119  ifirst = this%ialaktab(ilak)
2120  ilast = this%ialaktab(ilak + 1) - 1
2121  if (vv <= this%tabstage(ifirst)) then
2122  wa = this%tabwarea(ifirst)
2123  else if (vv >= this%tabstage(ilast)) then
2124  wa = this%tabwarea(ilast)
2125  else
2126  call this%lak_linear_interpolation(i, this%tabstage(ifirst:ilast), &
2127  this%tabwarea(ifirst:ilast), &
2128  vv, wa)
2129  end if
2130  else
2131  node = this%cellid(iconn)
2132  ! -- confined cell
2133  if (this%icelltype(node) == 0) then
2134  sat = done
2135  ! -- convertible cell
2136  else
2137  sat = squadraticsaturation(topl, botl, vv)
2138  end if
2139  wa = sat * this%warea(iconn)
2140  end if
2141  !
2142  ! -- Return
2143  return
2144  end subroutine lak_calculate_conn_warea
2145 
2146  !> @brief Calculate the volume of a lake at a given stage
2147  !<
2148  subroutine lak_calculate_vol(this, ilak, stage, volume)
2149  ! -- dummy
2150  class(laktype), intent(inout) :: this
2151  integer(I4B), intent(in) :: ilak
2152  real(DP), intent(in) :: stage
2153  real(DP), intent(inout) :: volume
2154  ! -- local
2155  integer(I4B) :: i
2156  integer(I4B) :: ifirst
2157  integer(I4B) :: ilast
2158  real(DP) :: topl
2159  real(DP) :: botl
2160  real(DP) :: ds
2161  real(DP) :: sa
2162  real(DP) :: v
2163  real(DP) :: sat
2164  !
2165  volume = dzero
2166  i = this%ntabrow(ilak)
2167  if (i > 0) then
2168  ifirst = this%ialaktab(ilak)
2169  ilast = this%ialaktab(ilak + 1) - 1
2170  if (stage <= this%tabstage(ifirst)) then
2171  volume = this%tabvolume(ifirst)
2172  else if (stage >= this%tabstage(ilast)) then
2173  ds = stage - this%tabstage(ilast)
2174  sa = this%tabsarea(ilast)
2175  volume = this%tabvolume(ilast) + ds * sa
2176  else
2177  call this%lak_linear_interpolation(i, this%tabstage(ifirst:ilast), &
2178  this%tabvolume(ifirst:ilast), &
2179  stage, volume)
2180  end if
2181  else
2182  do i = this%idxlakeconn(ilak), this%idxlakeconn(ilak + 1) - 1
2183  topl = this%telev(i)
2184  botl = this%belev(i)
2185  sat = squadraticsaturation(topl, botl, stage)
2186  sa = sat * this%sarea(i)
2187  if (stage < botl) then
2188  v = dzero
2189  else if (stage > botl .and. stage < topl) then
2190  v = sa * (stage - botl)
2191  else
2192  v = sa * (topl - botl) + sa * (stage - topl)
2193  end if
2194  volume = volume + v
2195  end do
2196  end if
2197  !
2198  ! -- Return
2199  return
2200  end subroutine lak_calculate_vol
2201 
2202  !> @brief Calculate the total conductance for a lake at a provided stage
2203  !<
2204  subroutine lak_calculate_conductance(this, ilak, stage, conductance)
2205  ! -- dummy
2206  class(laktype), intent(inout) :: this
2207  integer(I4B), intent(in) :: ilak
2208  real(DP), intent(in) :: stage
2209  real(DP), intent(inout) :: conductance
2210  ! -- local
2211  integer(I4B) :: i
2212  real(DP) :: c
2213  !
2214  conductance = dzero
2215  do i = this%idxlakeconn(ilak), this%idxlakeconn(ilak + 1) - 1
2216  call this%lak_calculate_conn_conductance(ilak, i, stage, stage, c)
2217  conductance = conductance + c
2218  end do
2219  !
2220  ! -- Return
2221  return
2222  end subroutine lak_calculate_conductance
2223 
2224  !> @brief Calculate the controlling lake stage or groundwater head used to
2225  !! calculate the conductance for a lake connection from a provided stage and
2226  !! groundwater head
2227  !<
2228  subroutine lak_calculate_cond_head(this, iconn, stage, head, vv)
2229  ! -- dummy
2230  class(laktype), intent(inout) :: this
2231  integer(I4B), intent(in) :: iconn
2232  real(DP), intent(in) :: stage
2233  real(DP), intent(in) :: head
2234  real(DP), intent(inout) :: vv
2235  ! -- local
2236  real(DP) :: ss
2237  real(DP) :: hh
2238  real(DP) :: topl
2239  real(DP) :: botl
2240  !
2241  topl = this%telev(iconn)
2242  botl = this%belev(iconn)
2243  ss = min(stage, topl)
2244  hh = min(head, topl)
2245  if (this%igwhcopt > 0) then
2246  vv = hh
2247  else if (this%inewton > 0) then
2248  vv = max(ss, hh)
2249  else
2250  vv = dhalf * (ss + hh)
2251  end if
2252  !
2253  ! -- Return
2254  return
2255  end subroutine lak_calculate_cond_head
2256 
2257  !> @brief Calculate the conductance for a lake connection at a provided stage
2258  !! and groundwater head
2259  !<
2260  subroutine lak_calculate_conn_conductance(this, ilak, iconn, stage, head, cond)
2261  ! -- dummy
2262  class(laktype), intent(inout) :: this
2263  integer(I4B), intent(in) :: ilak
2264  integer(I4B), intent(in) :: iconn
2265  real(DP), intent(in) :: stage
2266  real(DP), intent(in) :: head
2267  real(DP), intent(inout) :: cond
2268  ! -- local
2269  integer(I4B) :: node
2270  !real(DP) :: ss
2271  !real(DP) :: hh
2272  real(DP) :: vv
2273  real(DP) :: topl
2274  real(DP) :: botl
2275  real(DP) :: sat
2276  real(DP) :: wa
2277  real(DP) :: vscratio
2278  !
2279  cond = dzero
2280  vscratio = done
2281  topl = this%telev(iconn)
2282  botl = this%belev(iconn)
2283  call this%lak_calculate_cond_head(iconn, stage, head, vv)
2284  sat = squadraticsaturation(topl, botl, vv)
2285  ! vertical connection
2286  ! use full saturated conductance if top and bottom of the lake connection
2287  ! are equal
2288  if (this%ictype(iconn) == 0) then
2289  if (abs(topl - botl) < dprec) then
2290  sat = done
2291  end if
2292  ! horizontal connection
2293  ! use full saturated conductance if the connected cell is not convertible
2294  else if (this%ictype(iconn) == 1) then
2295  node = this%cellid(iconn)
2296  if (this%icelltype(node) == 0) then
2297  sat = done
2298  end if
2299  ! embedded connection
2300  else if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
2301  node = this%cellid(iconn)
2302  if (this%icelltype(node) == 0) then
2303  vv = this%telev(iconn)
2304  call this%lak_calculate_conn_warea(ilak, iconn, vv, vv, wa)
2305  else
2306  call this%lak_calculate_conn_warea(ilak, iconn, stage, head, wa)
2307  end if
2308  sat = wa
2309  end if
2310  !
2311  ! -- account for viscosity effects (if vsc active)
2312  if (this%ivsc == 1) then
2313  ! flow from lake to aquifer
2314  if (stage > head) then
2315  vscratio = this%viscratios(1, iconn)
2316  ! flow from aquifer to lake
2317  else
2318  vscratio = this%viscratios(2, iconn)
2319  end if
2320  end if
2321  cond = sat * this%satcond(iconn) * vscratio
2322  !
2323  ! -- Return
2324  return
2325  end subroutine lak_calculate_conn_conductance
2326 
2327  !> @brief Calculate the total groundwater-lake flow at a provided stage
2328  !<
2329  subroutine lak_calculate_exchange(this, ilak, stage, totflow)
2330  ! -- dummy
2331  class(laktype), intent(inout) :: this
2332  integer(I4B), intent(in) :: ilak
2333  real(DP), intent(in) :: stage
2334  real(DP), intent(inout) :: totflow
2335  ! -- local
2336  integer(I4B) :: j
2337  integer(I4B) :: igwfnode
2338  real(DP) :: flow
2339  real(DP) :: hgwf
2340  !
2341  totflow = dzero
2342  do j = this%idxlakeconn(ilak), this%idxlakeconn(ilak + 1) - 1
2343  igwfnode = this%cellid(j)
2344  hgwf = this%xnew(igwfnode)
2345  call this%lak_calculate_conn_exchange(ilak, j, stage, hgwf, flow)
2346  totflow = totflow + flow
2347  end do
2348  !
2349  ! -- Return
2350  return
2351  end subroutine lak_calculate_exchange
2352 
2353  !> @brief Calculate the groundwater-lake flow at a provided stage and
2354  !! groundwater head
2355  !<
2356  subroutine lak_calculate_conn_exchange(this, ilak, iconn, stage, head, flow, &
2357  gwfhcof, gwfrhs)
2358  ! -- dummy
2359  class(laktype), intent(inout) :: this
2360  integer(I4B), intent(in) :: ilak
2361  integer(I4B), intent(in) :: iconn
2362  real(DP), intent(in) :: stage
2363  real(DP), intent(in) :: head
2364  real(DP), intent(inout) :: flow
2365  real(DP), intent(inout), optional :: gwfhcof
2366  real(DP), intent(inout), optional :: gwfrhs
2367  ! -- local
2368  real(DP) :: botl
2369  real(DP) :: cond
2370  real(DP) :: ss
2371  real(DP) :: hh
2372  real(DP) :: gwfhcof0
2373  real(DP) :: gwfrhs0
2374  !
2375  flow = dzero
2376  call this%lak_calculate_conn_conductance(ilak, iconn, stage, head, cond)
2377  botl = this%belev(iconn)
2378  !
2379  ! -- Set ss to stage or botl
2380  if (stage >= botl) then
2381  ss = stage
2382  else
2383  ss = botl
2384  end if
2385  !
2386  ! -- set hh to head or botl
2387  if (head >= botl) then
2388  hh = head
2389  else
2390  hh = botl
2391  end if
2392  !
2393  ! -- calculate flow, positive into lake
2394  flow = cond * (hh - ss)
2395  !
2396  ! -- Calculate gwfhcof and gwfrhs
2397  if (head >= botl) then
2398  gwfhcof0 = -cond
2399  gwfrhs0 = -cond * ss
2400  else
2401  gwfhcof0 = dzero
2402  gwfrhs0 = flow
2403  end if
2404  !
2405  ! Add density contributions, if active
2406  if (this%idense /= 0) then
2407  call this%lak_calculate_density_exchange(iconn, stage, head, cond, botl, &
2408  flow, gwfhcof0, gwfrhs0)
2409  end if
2410  !
2411  ! -- If present update gwfhcof and gwfrhs
2412  if (present(gwfhcof)) gwfhcof = gwfhcof0
2413  if (present(gwfrhs)) gwfrhs = gwfrhs0
2414  !
2415  ! -- Return
2416  return
2417  end subroutine lak_calculate_conn_exchange
2418 
2419  !> @brief Calculate the groundwater-lake flow at a provided stage and
2420  !! groundwater head
2421  !<
2422  subroutine lak_estimate_conn_exchange(this, iflag, ilak, iconn, idry, stage, &
2423  head, flow, source, gwfhcof, gwfrhs)
2424  ! -- dummy
2425  class(laktype), intent(inout) :: this
2426  integer(I4B), intent(in) :: iflag
2427  integer(I4B), intent(in) :: ilak
2428  integer(I4B), intent(in) :: iconn
2429  integer(I4B), intent(inout) :: idry
2430  real(DP), intent(in) :: stage
2431  real(DP), intent(in) :: head
2432  real(DP), intent(inout) :: flow
2433  real(DP), intent(inout) :: source
2434  real(DP), intent(inout), optional :: gwfhcof
2435  real(DP), intent(inout), optional :: gwfrhs
2436  ! -- local
2437  real(DP) :: gwfhcof0, gwfrhs0
2438  !
2439  flow = dzero
2440  idry = 0
2441  call this%lak_calculate_conn_exchange(ilak, iconn, stage, head, flow, &
2442  gwfhcof0, gwfrhs0)
2443  if (iflag == 1) then
2444  if (flow > dzero) then
2445  source = source + flow
2446  end if
2447  else if (iflag == 2) then
2448  if (-flow > source) then
2449  flow = -source
2450  source = dzero
2451  idry = 1
2452  else if (flow < dzero) then
2453  source = source + flow
2454  end if
2455  end if
2456  !
2457  ! -- Set gwfhcof and gwfrhs if present
2458  if (present(gwfhcof)) gwfhcof = gwfhcof0
2459  if (present(gwfrhs)) gwfrhs = gwfrhs0
2460  !
2461  ! -- Return
2462  return
2463  end subroutine lak_estimate_conn_exchange
2464 
2465  !> @brief Calculate the storage change in a lake based on provided stages
2466  !! and a passed delt
2467  !<
2468  subroutine lak_calculate_storagechange(this, ilak, stage, stage0, delt, dvr)
2469  ! -- dummy
2470  class(laktype), intent(inout) :: this
2471  integer(I4B), intent(in) :: ilak
2472  real(DP), intent(in) :: stage
2473  real(DP), intent(in) :: stage0
2474  real(DP), intent(in) :: delt
2475  real(DP), intent(inout) :: dvr
2476  ! -- local
2477  real(DP) :: v
2478  real(DP) :: v0
2479  !
2480  dvr = dzero
2481  if (this%gwfiss /= 1) then
2482  call this%lak_calculate_vol(ilak, stage, v)
2483  call this%lak_calculate_vol(ilak, stage0, v0)
2484  dvr = (v0 - v) / delt
2485  end if
2486  !
2487  ! -- Return
2488  return
2489  end subroutine lak_calculate_storagechange
2490 
2491  !> @brief Calculate the rainfall for a lake
2492  !<
2493  subroutine lak_calculate_rainfall(this, ilak, stage, ra)
2494  ! -- dummy
2495  class(laktype), intent(inout) :: this
2496  integer(I4B), intent(in) :: ilak
2497  real(DP), intent(in) :: stage
2498  real(DP), intent(inout) :: ra
2499  ! -- local
2500  integer(I4B) :: iconn
2501  real(DP) :: sa
2502  !
2503  ! -- rainfall
2504  iconn = this%idxlakeconn(ilak)
2505  if (this%ictype(iconn) == 2 .or. this%ictype(iconn) == 3) then
2506  sa = this%sareamax(ilak)
2507  else
2508  call this%lak_calculate_sarea(ilak, stage, sa)
2509  end if
2510  ra = this%rainfall(ilak) * sa
2511  !
2512  ! -- Return
2513  return
2514  end subroutine lak_calculate_rainfall
2515 
2516  !> @brief Calculate runoff to a lake
2517  !<
2518  subroutine lak_calculate_runoff(this, ilak, ro)
2519  ! -- dummy
2520  class(laktype), intent(inout) :: this
2521  integer(I4B), intent(in) :: ilak
2522  real(DP), intent(inout) :: ro
2523  !
2524  ! -- runoff
2525  ro = this%runoff(ilak)
2526  !
2527  ! -- Return
2528  return
2529  end subroutine lak_calculate_runoff
2530 
2531  !> @brief Calculate specified inflow to a lake
2532  !<
2533  subroutine lak_calculate_inflow(this, ilak, qin)
2534  ! -- dummy
2535  class(laktype), intent(inout) :: this
2536  integer(I4B), intent(in) :: ilak
2537  real(DP), intent(inout) :: qin
2538  !
2539  ! -- inflow to lake
2540  qin = this%inflow(ilak)
2541  !
2542  ! -- Return
2543  return
2544  end subroutine lak_calculate_inflow
2545 
2546  !> @brief Calculate the external flow terms to a lake
2547  !<
2548  subroutine lak_calculate_external(this, ilak, ex)
2549  ! -- dummy
2550  class(laktype), intent(inout) :: this
2551  integer(I4B), intent(in) :: ilak
2552  real(DP), intent(inout) :: ex
2553  !
2554  ! -- If mover is active, add receiver water to rhs and
2555  ! store available water (as positive value)
2556  ex = dzero
2557  if (this%imover == 1) then
2558  ex = this%pakmvrobj%get_qfrommvr(ilak)
2559  end if
2560  !
2561  ! -- Return
2562  return
2563  end subroutine lak_calculate_external
2564 
2565  !> @brief Calculate the withdrawal from a lake subject to an available volume
2566  !<
2567  subroutine lak_calculate_withdrawal(this, ilak, avail, wr)
2568  ! -- dummy
2569  class(laktype), intent(inout) :: this
2570  integer(I4B), intent(in) :: ilak
2571  real(DP), intent(inout) :: avail
2572  real(DP), intent(inout) :: wr
2573  !
2574  ! -- withdrawals - limit to sum of inflows and available volume
2575  wr = this%withdrawal(ilak)
2576  if (wr > avail) then
2577  wr = -avail
2578  else
2579  if (wr > dzero) then
2580  wr = -wr
2581  end if
2582  end if
2583  avail = avail + wr
2584  !
2585  ! -- Return
2586  return
2587  end subroutine lak_calculate_withdrawal
2588 
2589  !> @brief Calculate the evaporation from a lake at a provided stage subject
2590  !! to an available volume
2591  !<
2592  subroutine lak_calculate_evaporation(this, ilak, stage, avail, ev)
2593  ! -- dummy
2594  class(laktype), intent(inout) :: this
2595  integer(I4B), intent(in) :: ilak
2596  real(DP), intent(in) :: stage
2597  real(DP), intent(inout) :: avail
2598  real(DP), intent(inout) :: ev
2599  ! -- local
2600  real(DP) :: sa
2601  !
2602  ! -- evaporation - limit to sum of inflows and available volume
2603  call this%lak_calculate_sarea(ilak, stage, sa)
2604  ev = sa * this%evaporation(ilak)
2605  if (ev > avail) then
2606  if (is_close(avail, dprec)) then
2607  ev = dzero
2608  else
2609  ev = -avail
2610  end if
2611  else
2612  ev = -ev
2613  end if
2614  avail = avail + ev
2615  !
2616  ! -- Return
2617  return
2618  end subroutine lak_calculate_evaporation
2619 
2620  !> @brief Calculate the outlet inflow to a lake
2621  !<
2622  subroutine lak_calculate_outlet_inflow(this, ilak, outinf)
2623  ! -- dummy
2624  class(laktype), intent(inout) :: this
2625  integer(I4B), intent(in) :: ilak
2626  real(DP), intent(inout) :: outinf
2627  ! -- local
2628  integer(I4B) :: n
2629  !
2630  outinf = dzero
2631  do n = 1, this%noutlets
2632  if (this%lakeout(n) == ilak) then
2633  outinf = outinf - this%simoutrate(n)
2634  if (this%imover == 1) then
2635  outinf = outinf - this%pakmvrobj%get_qtomvr(n)
2636  end if
2637  end if
2638  end do
2639  !
2640  ! -- Return
2641  return
2642  end subroutine lak_calculate_outlet_inflow
2643 
2644  !> @brief Calculate the outlet outflow from a lake
2645  !<
2646  subroutine lak_calculate_outlet_outflow(this, ilak, stage, avail, outoutf)
2647  ! -- dummy
2648  class(laktype), intent(inout) :: this
2649  integer(I4B), intent(in) :: ilak
2650  real(DP), intent(in) :: stage
2651  real(DP), intent(inout) :: avail
2652  real(DP), intent(inout) :: outoutf
2653  ! -- local
2654  integer(I4B) :: n
2655  real(DP) :: g
2656  real(DP) :: d
2657  real(DP) :: c
2658  real(DP) :: gsm
2659  real(DP) :: rate
2660  !
2661  outoutf = dzero
2662  do n = 1, this%noutlets
2663  if (this%lakein(n) == ilak) then
2664  rate = dzero
2665  d = stage - this%outinvert(n)
2666  if (this%outdmax > dzero) then
2667  if (d > this%outdmax) d = this%outdmax
2668  end if
2669  g = dgravity * this%convlength * this%convtime * this%convtime
2670  select case (this%iouttype(n))
2671  ! specified rate
2672  case (0)
2673  rate = this%outrate(n)
2674  if (-rate > avail) then
2675  rate = -avail
2676  end if
2677  ! manning
2678  case (1)
2679  if (d > dzero) then
2680  c = (this%convlength**donethird) * this%convtime
2681  gsm = dzero
2682  if (this%outrough(n) > dzero) then
2683  gsm = done / this%outrough(n)
2684  end if
2685  rate = -c * gsm * this%outwidth(n) * (d**dfivethirds) * &
2686  sqrt(this%outslope(n))
2687  end if
2688  ! weir
2689  case (2)
2690  if (d > dzero) then
2691  rate = -dtwothirds * dcd * this%outwidth(n) * d * &
2692  sqrt(dtwo * g * d)
2693  end if
2694  end select
2695  this%simoutrate(n) = rate
2696  avail = avail + rate
2697  outoutf = outoutf + rate
2698  end if
2699  end do
2700  !
2701  ! -- Return
2702  return
2703  end subroutine lak_calculate_outlet_outflow
2704 
2705  !> @brief Get the outlet inflow to a lake from another lake
2706  !<
2707  subroutine lak_get_internal_inlet(this, ilak, outinf)
2708  ! -- dummy
2709  class(laktype), intent(inout) :: this
2710  integer(I4B), intent(in) :: ilak
2711  real(DP), intent(inout) :: outinf
2712  ! -- local
2713  integer(I4B) :: n
2714  !
2715  outinf = dzero
2716  do n = 1, this%noutlets
2717  if (this%lakeout(n) == ilak) then
2718  outinf = outinf - this%simoutrate(n)
2719  if (this%imover == 1) then
2720  outinf = outinf - this%pakmvrobj%get_qtomvr(n)
2721  end if
2722  end if
2723  end do
2724  !
2725  ! -- Return
2726  return
2727  end subroutine lak_get_internal_inlet
2728 
2729  !> @brief Get the outlet from a lake to another lake
2730  !<
2731  subroutine lak_get_internal_outlet(this, ilak, outoutf)
2732  ! -- dummy
2733  class(laktype), intent(inout) :: this
2734  integer(I4B), intent(in) :: ilak
2735  real(DP), intent(inout) :: outoutf
2736  ! -- local
2737  integer(I4B) :: n
2738  !
2739  outoutf = dzero
2740  do n = 1, this%noutlets
2741  if (this%lakein(n) == ilak) then
2742  if (this%lakeout(n) < 1) cycle
2743  outoutf = outoutf + this%simoutrate(n)
2744  end if
2745  end do
2746  !
2747  ! -- Return
2748  return
2749  end subroutine lak_get_internal_outlet
2750 
2751  !> @brief Get the outlet outflow from a lake to an external boundary
2752  !<
2753  subroutine lak_get_external_outlet(this, ilak, outoutf)
2754  ! -- dummy
2755  class(laktype), intent(inout) :: this
2756  integer(I4B), intent(in) :: ilak
2757  real(DP), intent(inout) :: outoutf
2758  ! -- local
2759  integer(I4B) :: n
2760  !
2761  outoutf = dzero
2762  do n = 1, this%noutlets
2763  if (this%lakein(n) == ilak) then
2764  if (this%lakeout(n) > 0) cycle
2765  outoutf = outoutf + this%simoutrate(n)
2766  end if
2767  end do
2768  !
2769  ! -- Return
2770  return
2771  end subroutine lak_get_external_outlet
2772 
2773  !> @brief Get the mover outflow from a lake to an external boundary
2774  !<
2775  subroutine lak_get_external_mover(this, ilak, outoutf)
2776  ! -- dummy
2777  class(laktype), intent(inout) :: this
2778  integer(I4B), intent(in) :: ilak
2779  real(DP), intent(inout) :: outoutf
2780  ! -- local
2781  integer(I4B) :: n
2782  !
2783  outoutf = dzero
2784  if (this%imover == 1) then
2785  do n = 1, this%noutlets
2786  if (this%lakein(n) == ilak) then
2787  if (this%lakeout(n) > 0) cycle
2788  outoutf = outoutf + this%pakmvrobj%get_qtomvr(n)
2789  end if
2790  end do
2791  end if
2792  !
2793  ! -- Return
2794  return
2795  end subroutine lak_get_external_mover
2796 
2797  !> @brief Get the mover outflow from a lake to another lake
2798  !<
2799  subroutine lak_get_internal_mover(this, ilak, outoutf)
2800  ! -- dummy
2801  class(laktype), intent(inout) :: this
2802  integer(I4B), intent(in) :: ilak
2803  real(DP), intent(inout) :: outoutf
2804  ! -- local
2805  integer(I4B) :: n
2806  !
2807  outoutf = dzero
2808  if (this%imover == 1) then
2809  do n = 1, this%noutlets
2810  if (this%lakein(n) == ilak) then
2811  if (this%lakeout(n) < 1) cycle
2812  outoutf = outoutf + this%pakmvrobj%get_qtomvr(n)
2813  end if
2814  end do
2815  end if
2816  !
2817  ! -- Return
2818  return
2819  end subroutine lak_get_internal_mover
2820 
2821  !> @brief Get the outlet to mover from a lake
2822  !<
2823  subroutine lak_get_outlet_tomover(this, ilak, outoutf)
2824  ! -- dummy
2825  class(laktype), intent(inout) :: this
2826  integer(I4B), intent(in) :: ilak
2827  real(DP), intent(inout) :: outoutf
2828  ! -- local
2829  integer(I4B) :: n
2830  !
2831  outoutf = dzero
2832  if (this%imover == 1) then
2833  do n = 1, this%noutlets
2834  if (this%lakein(n) == ilak) then
2835  outoutf = outoutf + this%pakmvrobj%get_qtomvr(n)
2836  end if
2837  end do
2838  end if
2839  !
2840  ! -- Return
2841  return
2842  end subroutine lak_get_outlet_tomover
2843 
2844  !> @brief Determine the stage from a provided volume
2845  !<
2846  subroutine lak_vol2stage(this, ilak, vol, stage)
2847  ! -- dummy
2848  class(laktype), intent(inout) :: this
2849  integer(I4B), intent(in) :: ilak
2850  real(DP), intent(in) :: vol
2851  real(DP), intent(inout) :: stage
2852  ! -- local
2853  integer(I4B) :: i
2854  integer(I4B) :: ibs
2855  real(DP) :: s0, s1, sm
2856  real(DP) :: v0, v1, vm
2857  real(DP) :: f0, f1, fm
2858  real(DP) :: sa
2859  real(DP) :: en0, en1
2860  real(DP) :: ds, ds0
2861  real(DP) :: denom
2862  !
2863  s0 = this%lakebot(ilak)
2864  call this%lak_calculate_vol(ilak, s0, v0)
2865  s1 = this%laketop(ilak)
2866  call this%lak_calculate_vol(ilak, s1, v1)
2867  ! -- zero volume
2868  if (vol <= v0) then
2869  stage = s0
2870  ! -- linear relation between stage and volume above top of lake
2871  else if (vol >= v1) then
2872  call this%lak_calculate_sarea(ilak, s1, sa)
2873  stage = s1 + (vol - v1) / sa
2874  ! -- use combination of secant and bisection
2875  else
2876  en0 = s0
2877  en1 = s1
2878  ! sm = s1 ! causes divide by zero in 1st line in secantbisection loop
2879  ! sm = s0 ! causes divide by zero in 1st line in secantbisection loop
2880  sm = dzero
2881  f0 = vol - v0
2882  f1 = vol - v1
2883  ibs = 0
2884  secantbisection: do i = 1, 150
2885  denom = f1 - f0
2886  if (denom /= dzero) then
2887  ds = f1 * (s1 - s0) / denom
2888  else
2889  ibs = 13
2890  end if
2891  if (i == 1) then
2892  ds0 = ds
2893  end if
2894  ! -- use bisection if end points are exceeded
2895  if (sm < en0 .or. sm > en1) ibs = 13
2896  ! -- use bisection if secant method stagnates or if
2897  ! ds exceeds previous ds - bisection would occur
2898  ! after conditions exceeded in 13 iterations
2899  if (ds * ds0 < dprec .or. abs(ds) > abs(ds0)) ibs = ibs + 1
2900  if (ibs > 12) then
2901  ds = dhalf * (s1 - s0)
2902  ibs = 0
2903  end if
2904  sm = s1 - ds
2905  if (abs(ds) < dem6) then
2906  exit secantbisection
2907  end if
2908  call this%lak_calculate_vol(ilak, sm, vm)
2909  fm = vol - vm
2910  s0 = s1
2911  f0 = f1
2912  s1 = sm
2913  f1 = fm
2914  ds0 = ds
2915  end do secantbisection
2916  stage = sm
2917  if (abs(ds) >= dem6) then
2918  write (this%iout, '(1x,a,1x,i0,4(1x,a,1x,g15.6))') &
2919  & 'LAK_VOL2STAGE failed for lake', ilak, 'volume error =', fm, &
2920  & 'finding stage (', stage, ') for volume =', vol, &
2921  & 'final change in stage =', ds
2922  end if
2923  end if
2924  !
2925  ! -- Return
2926  return
2927  end subroutine lak_vol2stage
2928 
2929  !> @brief Determine if a valid lake or outlet number has been specified
2930  function lak_check_valid(this, itemno) result(ierr)
2931  ! -- modules
2932  use simmodule, only: store_error
2933  ! -- return
2934  integer(I4B) :: ierr
2935  ! -- dummy
2936  class(laktype), intent(inout) :: this
2937  integer(I4B), intent(in) :: itemno
2938  ! -- local
2939  integer(I4B) :: ival
2940  !
2941  ierr = 0
2942  ival = abs(itemno)
2943  if (itemno > 0) then
2944  if (ival < 1 .or. ival > this%nlakes) then
2945  write (errmsg, '(a,1x,i0,1x,a,1x,i0,a)') &
2946  'LAKENO', itemno, 'must be greater than 0 and less than or equal to', &
2947  this%nlakes, '.'
2948  call store_error(errmsg)
2949  ierr = 1
2950  end if
2951  else
2952  if (ival < 1 .or. ival > this%noutlets) then
2953  write (errmsg, '(a,1x,i0,1x,a,1x,i0,a)') &
2954  'IOUTLET', itemno, 'must be greater than 0 and less than or equal to', &
2955  this%noutlets, '.'
2956  call store_error(errmsg)
2957  ierr = 1
2958  end if
2959  end if
2960  !
2961  ! -- Return
2962  return
2963  end function lak_check_valid
2964 
2965  !> @brief Set a stress period attribute for lakweslls(itemno) using keywords
2966  !<
2967  subroutine lak_set_stressperiod(this, itemno)
2968  ! -- modules
2970  use simmodule, only: store_error
2971  ! -- dummy
2972  class(laktype), intent(inout) :: this
2973  integer(I4B), intent(in) :: itemno
2974  ! -- local
2975  character(len=LINELENGTH) :: text
2976  character(len=LINELENGTH) :: caux
2977  character(len=LINELENGTH) :: keyword
2978  integer(I4B) :: ierr
2979  integer(I4B) :: ii
2980  integer(I4B) :: jj
2981  real(DP), pointer :: bndElem => null()
2982  !
2983  ! -- read line
2984  call this%parser%GetStringCaps(keyword)
2985  select case (keyword)
2986  case ('STATUS')
2987  ierr = this%lak_check_valid(itemno)
2988  if (ierr /= 0) then
2989  goto 999
2990  end if
2991  call this%parser%GetStringCaps(text)
2992  this%status(itemno) = text(1:8)
2993  if (text == 'CONSTANT') then
2994  this%iboundpak(itemno) = -1
2995  else if (text == 'INACTIVE') then
2996  this%iboundpak(itemno) = 0
2997  else if (text == 'ACTIVE') then
2998  this%iboundpak(itemno) = 1
2999  else
3000  write (errmsg, '(a,a)') &
3001  'Unknown '//trim(this%text)//' lak status keyword: ', text//'.'
3002  call store_error(errmsg)
3003  end if
3004  case ('STAGE')
3005  ierr = this%lak_check_valid(itemno)
3006  if (ierr /= 0) then
3007  goto 999
3008  end if
3009  call this%parser%GetString(text)
3010  jj = 1 ! For STAGE
3011  bndelem => this%stage(itemno)
3012  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3013  this%packName, 'BND', this%tsManager, &
3014  this%iprpak, 'STAGE')
3015  case ('RAINFALL')
3016  ierr = this%lak_check_valid(itemno)
3017  if (ierr /= 0) then
3018  goto 999
3019  end if
3020  call this%parser%GetString(text)
3021  jj = 1 ! For RAINFALL
3022  bndelem => this%rainfall(itemno)
3023  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3024  this%packName, 'BND', this%tsManager, &
3025  this%iprpak, 'RAINFALL')
3026  if (this%rainfall(itemno) < dzero) then
3027  write (errmsg, '(a,i0,a,G0,a)') &
3028  'Lake ', itemno, ' was assigned a rainfall value of ', &
3029  this%rainfall(itemno), '. Rainfall must be positive.'
3030  call store_error(errmsg)
3031  end if
3032  case ('EVAPORATION')
3033  ierr = this%lak_check_valid(itemno)
3034  if (ierr /= 0) then
3035  goto 999
3036  end if
3037  call this%parser%GetString(text)
3038  jj = 1 ! For EVAPORATION
3039  bndelem => this%evaporation(itemno)
3040  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3041  this%packName, 'BND', this%tsManager, &
3042  this%iprpak, 'EVAPORATION')
3043  if (this%evaporation(itemno) < dzero) then
3044  write (errmsg, '(a,i0,a,G0,a)') &
3045  'Lake ', itemno, ' was assigned an evaporation value of ', &
3046  this%evaporation(itemno), '. Evaporation must be positive.'
3047  call store_error(errmsg)
3048  end if
3049  case ('RUNOFF')
3050  ierr = this%lak_check_valid(itemno)
3051  if (ierr /= 0) then
3052  goto 999
3053  end if
3054  call this%parser%GetString(text)
3055  jj = 1 ! For RUNOFF
3056  bndelem => this%runoff(itemno)
3057  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3058  this%packName, 'BND', this%tsManager, &
3059  this%iprpak, 'RUNOFF')
3060  if (this%runoff(itemno) < dzero) then
3061  write (errmsg, '(a,i0,a,G0,a)') &
3062  'Lake ', itemno, ' was assigned a runoff value of ', &
3063  this%runoff(itemno), '. Runoff must be positive.'
3064  call store_error(errmsg)
3065  end if
3066  case ('INFLOW')
3067  ierr = this%lak_check_valid(itemno)
3068  if (ierr /= 0) then
3069  goto 999
3070  end if
3071  call this%parser%GetString(text)
3072  jj = 1 ! For specified INFLOW
3073  bndelem => this%inflow(itemno)
3074  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3075  this%packName, 'BND', this%tsManager, &
3076  this%iprpak, 'INFLOW')
3077  if (this%inflow(itemno) < dzero) then
3078  write (errmsg, '(a,i0,a,G0,a)') &
3079  'Lake ', itemno, ' was assigned an inflow value of ', &
3080  this%inflow(itemno), '. Inflow must be positive.'
3081  call store_error(errmsg)
3082  end if
3083  case ('WITHDRAWAL')
3084  ierr = this%lak_check_valid(itemno)
3085  if (ierr /= 0) then
3086  goto 999
3087  end if
3088  call this%parser%GetString(text)
3089  jj = 1 ! For specified WITHDRAWAL
3090  bndelem => this%withdrawal(itemno)
3091  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3092  this%packName, 'BND', this%tsManager, &
3093  this%iprpak, 'WITHDRAWAL')
3094  if (this%withdrawal(itemno) < dzero) then
3095  write (errmsg, '(a,i0,a,G0,a)') &
3096  'Lake ', itemno, ' was assigned a withdrawal value of ', &
3097  this%withdrawal(itemno), '. Withdrawal must be positive.'
3098  call store_error(errmsg)
3099  end if
3100  case ('RATE')
3101  ierr = this%lak_check_valid(-itemno)
3102  if (ierr /= 0) then
3103  goto 999
3104  end if
3105  call this%parser%GetString(text)
3106  jj = 1 ! For specified OUTLET RATE
3107  bndelem => this%outrate(itemno)
3108  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3109  this%packName, 'BND', this%tsManager, &
3110  this%iprpak, 'RATE')
3111  case ('INVERT')
3112  ierr = this%lak_check_valid(-itemno)
3113  if (ierr /= 0) then
3114  goto 999
3115  end if
3116  call this%parser%GetString(text)
3117  jj = 1 ! For OUTLET INVERT
3118  bndelem => this%outinvert(itemno)
3119  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3120  this%packName, 'BND', this%tsManager, &
3121  this%iprpak, 'INVERT')
3122  case ('WIDTH')
3123  ierr = this%lak_check_valid(-itemno)
3124  if (ierr /= 0) then
3125  goto 999
3126  end if
3127  call this%parser%GetString(text)
3128  jj = 1 ! For OUTLET WIDTH
3129  bndelem => this%outwidth(itemno)
3130  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3131  this%packName, 'BND', this%tsManager, &
3132  this%iprpak, 'WIDTH')
3133  case ('ROUGH')
3134  ierr = this%lak_check_valid(-itemno)
3135  if (ierr /= 0) then
3136  goto 999
3137  end if
3138  call this%parser%GetString(text)
3139  jj = 1 ! For OUTLET ROUGHNESS
3140  bndelem => this%outrough(itemno)
3141  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3142  this%packName, 'BND', this%tsManager, &
3143  this%iprpak, 'ROUGH')
3144  case ('SLOPE')
3145  ierr = this%lak_check_valid(-itemno)
3146  if (ierr /= 0) then
3147  goto 999
3148  end if
3149  call this%parser%GetString(text)
3150  jj = 1 ! For OUTLET SLOPE
3151  bndelem => this%outslope(itemno)
3152  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3153  this%packName, 'BND', this%tsManager, &
3154  this%iprpak, 'SLOPE')
3155  case ('AUXILIARY')
3156  ierr = this%lak_check_valid(itemno)
3157  if (ierr /= 0) then
3158  goto 999
3159  end if
3160  call this%parser%GetStringCaps(caux)
3161  do jj = 1, this%naux
3162  if (trim(adjustl(caux)) /= trim(adjustl(this%auxname(jj)))) cycle
3163  call this%parser%GetString(text)
3164  ii = itemno
3165  bndelem => this%lauxvar(jj, ii)
3166  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
3167  this%packName, 'AUX', &
3168  this%tsManager, this%iprpak, &
3169  this%auxname(jj))
3170  exit
3171  end do
3172  case default
3173  write (errmsg, '(2a)') &
3174  'Unknown '//trim(this%text)//' lak data keyword: ', &
3175  trim(keyword)//'.'
3176  end select
3177  !
3178  ! -- Return
3179 999 return
3180  end subroutine lak_set_stressperiod
3181 
3182  !> @brief Issue a parameter error for lakweslls(ilak)
3183  !!
3184  !! Read itmp and new boundaries if itmp > 0
3185  !<
3186  subroutine lak_set_attribute_error(this, ilak, keyword, msg)
3187  ! -- modules
3188  use simmodule, only: store_error
3189  ! -- dummy
3190  class(laktype), intent(inout) :: this
3191  integer(I4B), intent(in) :: ilak
3192  character(len=*), intent(in) :: keyword
3193  character(len=*), intent(in) :: msg
3194  !
3195  if (len(msg) == 0) then
3196  write (errmsg, '(a,1x,a,1x,i0,1x,a)') &
3197  keyword, ' for LAKE', ilak, 'has already been set.'
3198  else
3199  write (errmsg, '(a,1x,a,1x,i0,1x,a)') keyword, ' for LAKE', ilak, msg
3200  end if
3201  call store_error(errmsg)
3202  ! -- Return
3203  return
3204  end subroutine lak_set_attribute_error
3205 
3206  !> @brief Set options specific to LakType
3207  !!
3208  !! lak_options overrides BndType%bnd_options
3209  !<
3210  subroutine lak_options(this, option, found)
3211  ! -- modules
3213  use openspecmodule, only: access, form
3214  use simmodule, only: store_error
3216  ! -- dummy
3217  class(laktype), intent(inout) :: this
3218  character(len=*), intent(inout) :: option
3219  logical(LGP), intent(inout) :: found
3220  ! -- local
3221  character(len=MAXCHARLEN) :: fname, keyword
3222  real(DP) :: r
3223  ! -- formats
3224  character(len=*), parameter :: fmtlengthconv = &
3225  &"(4x, 'LENGTH CONVERSION VALUE (',g15.7,') SPECIFIED.')"
3226  character(len=*), parameter :: fmttimeconv = &
3227  &"(4x, 'TIME CONVERSION VALUE (',g15.7,') SPECIFIED.')"
3228  character(len=*), parameter :: fmtoutdmax = &
3229  &"(4x, 'MAXIMUM OUTLET WATER DEPTH (',g15.7,') SPECIFIED.')"
3230  character(len=*), parameter :: fmtlakeopt = &
3231  &"(4x, 'LAKE ', a, ' VALUE (',g15.7,') SPECIFIED.')"
3232  character(len=*), parameter :: fmtlakbin = &
3233  "(4x, 'LAK ', 1x, a, 1x, ' WILL BE SAVED TO FILE: ', &
3234  &a, /4x, 'OPENED ON UNIT: ', I0)"
3235  character(len=*), parameter :: fmtiter = &
3236  &"(4x, 'MAXIMUM LAK ITERATION VALUE (',i0,') SPECIFIED.')"
3237  character(len=*), parameter :: fmtdmaxchg = &
3238  &"(4x, 'MAXIMUM STAGE CHANGE VALUE (',g0,') SPECIFIED.')"
3239  !
3240  found = .true.
3241  select case (option)
3242  case ('PRINT_STAGE')
3243  this%iprhed = 1
3244  write (this%iout, '(4x,a)') trim(adjustl(this%text))// &
3245  ' STAGES WILL BE PRINTED TO LISTING FILE.'
3246  case ('STAGE')
3247  call this%parser%GetStringCaps(keyword)
3248  if (keyword == 'FILEOUT') then
3249  call this%parser%GetString(fname)
3250  this%istageout = getunit()
3251  call openfile(this%istageout, this%iout, fname, 'DATA(BINARY)', &
3252  form, access, 'REPLACE', mode_opt=mnormal)
3253  write (this%iout, fmtlakbin) 'STAGE', trim(adjustl(fname)), &
3254  this%istageout
3255  else
3256  call store_error('OPTIONAL STAGE KEYWORD MUST BE FOLLOWED BY FILEOUT')
3257  end if
3258  case ('BUDGET')
3259  call this%parser%GetStringCaps(keyword)
3260  if (keyword == 'FILEOUT') then
3261  call this%parser%GetString(fname)
3262  this%ibudgetout = getunit()
3263  call openfile(this%ibudgetout, this%iout, fname, 'DATA(BINARY)', &
3264  form, access, 'REPLACE', mode_opt=mnormal)
3265  write (this%iout, fmtlakbin) 'BUDGET', trim(adjustl(fname)), &
3266  this%ibudgetout
3267  else
3268  call store_error('OPTIONAL BUDGET KEYWORD MUST BE FOLLOWED BY FILEOUT')
3269  end if
3270  case ('BUDGETCSV')
3271  call this%parser%GetStringCaps(keyword)
3272  if (keyword == 'FILEOUT') then
3273  call this%parser%GetString(fname)
3274  this%ibudcsv = getunit()
3275  call openfile(this%ibudcsv, this%iout, fname, 'CSV', &
3276  filstat_opt='REPLACE')
3277  write (this%iout, fmtlakbin) 'BUDGET CSV', trim(adjustl(fname)), &
3278  this%ibudcsv
3279  else
3280  call store_error('OPTIONAL BUDGETCSV KEYWORD MUST BE FOLLOWED BY &
3281  &FILEOUT')
3282  end if
3283  case ('PACKAGE_CONVERGENCE')
3284  call this%parser%GetStringCaps(keyword)
3285  if (keyword == 'FILEOUT') then
3286  call this%parser%GetString(fname)
3287  this%ipakcsv = getunit()
3288  call openfile(this%ipakcsv, this%iout, fname, 'CSV', &
3289  filstat_opt='REPLACE', mode_opt=mnormal)
3290  write (this%iout, fmtlakbin) 'PACKAGE_CONVERGENCE', &
3291  trim(adjustl(fname)), this%ipakcsv
3292  else
3293  call store_error('OPTIONAL PACKAGE_CONVERGENCE KEYWORD MUST BE '// &
3294  'FOLLOWED BY FILEOUT')
3295  end if
3296  case ('MOVER')
3297  this%imover = 1
3298  write (this%iout, '(4x,A)') 'MOVER OPTION ENABLED'
3299  case ('LENGTH_CONVERSION')
3300  this%convlength = this%parser%GetDouble()
3301  write (this%iout, fmtlengthconv) this%convlength
3302  case ('TIME_CONVERSION')
3303  this%convtime = this%parser%GetDouble()
3304  write (this%iout, fmttimeconv) this%convtime
3305  case ('SURFDEP')
3306  r = this%parser%GetDouble()
3307  if (r < dzero) then
3308  r = dzero
3309  end if
3310  this%surfdep = r
3311  write (this%iout, fmtlakeopt) 'SURFDEP', this%surfdep
3312  case ('MAXIMUM_ITERATIONS')
3313  this%maxlakit = this%parser%GetInteger()
3314  write (this%iout, fmtiter) this%maxlakit
3315  case ('MAXIMUM_STAGE_CHANGE')
3316  r = this%parser%GetDouble()
3317  this%dmaxchg = r
3318  this%delh = dp999 * r
3319  write (this%iout, fmtdmaxchg) this%dmaxchg
3320  !
3321  ! -- right now these are options that are only available in the
3322  ! development version and are not included in the documentation.
3323  ! These options are only available when IDEVELOPMODE in
3324  ! constants module is set to 1
3325  case ('DEV_GROUNDWATER_HEAD_CONDUCTANCE')
3326  call this%parser%DevOpt()
3327  this%igwhcopt = 1
3328  write (this%iout, '(4x,a)') &
3329  'CONDUCTANCE FOR HORIZONTAL CONNECTIONS WILL BE CALCULATED &
3330  &USING THE GROUNDWATER HEAD'
3331  case ('DEV_MAXIMUM_OUTLET_DEPTH')
3332  call this%parser%DevOpt()
3333  this%outdmax = this%parser%GetDouble()
3334  write (this%iout, fmtoutdmax) this%outdmax
3335  case ('DEV_NO_FINAL_CHECK')
3336  call this%parser%DevOpt()
3337  this%iconvchk = 0
3338  write (this%iout, '(4x,a)') &
3339  'A FINAL CONVERGENCE CHECK OF THE CHANGE IN LAKE STAGES &
3340  &WILL NOT BE MADE'
3341  case ('DEV_NO_FINAL_RESIDUAL_CHECK')
3342  call this%parser%DevOpt()
3343  this%iconvresidchk = 0
3344  write (this%iout, '(4x,a)') &
3345  'A FINAL CONVERGENCE CHECK OF THE CHANGE IN LAKE RESIDUALS &
3346  &WILL NOT BE MADE'
3347  case ('DEV_MAXIMUM_PERCENT_DIFFERENCE')
3348  call this%parser%DevOpt()
3349  r = this%parser%GetDouble()
3350  if (r < dzero) then
3351  r = dem1
3352  end if
3353  this%pdmax = r
3354  write (this%iout, fmtlakeopt) 'MAXIMUM_PERCENT_DIFFERENCE', this%pdmax
3355  case default
3356  !
3357  ! -- No options found
3358  found = .false.
3359  end select
3360  !
3361  ! -- Return
3362  return
3363  end subroutine lak_options
3364 
3365  !> @brief Allocate and Read
3366  !!
3367  !! Create new LAK package and point bndobj to the new package
3368  !<
3369  subroutine lak_ar(this)
3370  ! -- dummy
3371  class(laktype), intent(inout) :: this
3372  !
3373  call this%obs%obs_ar()
3374  !
3375  ! -- Allocate arrays in LAK and in package superclass
3376  call this%lak_allocate_arrays()
3377  !
3378  ! -- read optional initial package parameters
3379  call this%read_initial_attr()
3380  !
3381  ! -- setup pakmvrobj
3382  if (this%imover /= 0) then
3383  allocate (this%pakmvrobj)
3384  call this%pakmvrobj%ar(this%noutlets, this%nlakes, this%memoryPath)
3385  end if
3386  !
3387  ! -- Return
3388  return
3389  end subroutine lak_ar
3390 
3391  !> @brief Read and Prepare
3392  !!
3393  !! Read itmp and read new boundaries if itmp > 0
3394  !<
3395  subroutine lak_rp(this)
3396  ! -- modules
3397  use constantsmodule, only: linelength
3398  use tdismodule, only: kper, nper
3399  use simmodule, only: store_error, count_errors
3400  ! -- dummy
3401  class(laktype), intent(inout) :: this
3402  ! -- local
3403  character(len=LINELENGTH) :: title
3404  character(len=LINELENGTH) :: line
3405  character(len=LINELENGTH) :: text
3406  logical(LGP) :: isfound
3407  logical(LGP) :: endOfBlock
3408  integer(I4B) :: ierr
3409  integer(I4B) :: node
3410  integer(I4B) :: n
3411  integer(I4B) :: itemno
3412  integer(I4B) :: j
3413  ! -- formats
3414  character(len=*), parameter :: fmtblkerr = &
3415  &"('Looking for BEGIN PERIOD iper. Found ', a, ' instead.')"
3416  character(len=*), parameter :: fmtlsp = &
3417  &"(1X,/1X,'REUSING ',A,'S FROM LAST STRESS PERIOD')"
3418  !
3419  ! -- set nbound to maxbound
3420  this%nbound = this%maxbound
3421  !
3422  ! -- Set ionper to the stress period number for which a new block of data
3423  ! will be read.
3424  if (this%inunit == 0) return
3425  !
3426  ! -- get stress period data
3427  if (this%ionper < kper) then
3428  !
3429  ! -- get period block
3430  call this%parser%GetBlock('PERIOD', isfound, ierr, &
3431  supportopenclose=.true., &
3432  blockrequired=.false.)
3433  if (isfound) then
3434  !
3435  ! -- read ionper and check for increasing period numbers
3436  call this%read_check_ionper()
3437  else
3438  !
3439  ! -- PERIOD block not found
3440  if (ierr < 0) then
3441  ! -- End of file found; data applies for remainder of simulation.
3442  this%ionper = nper + 1
3443  else
3444  ! -- Found invalid block
3445  call this%parser%GetCurrentLine(line)
3446  write (errmsg, fmtblkerr) adjustl(trim(line))
3447  call store_error(errmsg)
3448  call this%parser%StoreErrorUnit()
3449  end if
3450  end if
3451  end if
3452  !
3453  ! -- Read data if ionper == kper
3454  if (this%ionper == kper) then
3455  !
3456  ! -- setup table for period data
3457  if (this%iprpak /= 0) then
3458  !
3459  ! -- reset the input table object
3460  title = trim(adjustl(this%text))//' PACKAGE ('// &
3461  trim(adjustl(this%packName))//') DATA FOR PERIOD'
3462  write (title, '(a,1x,i6)') trim(adjustl(title)), kper
3463  call table_cr(this%inputtab, this%packName, title)
3464  call this%inputtab%table_df(1, 4, this%iout, finalize=.false.)
3465  text = 'NUMBER'
3466  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
3467  text = 'KEYWORD'
3468  call this%inputtab%initialize_column(text, 20, alignment=tableft)
3469  do n = 1, 2
3470  write (text, '(a,1x,i6)') 'VALUE', n
3471  call this%inputtab%initialize_column(text, 15, alignment=tabcenter)
3472  end do
3473  end if
3474  !
3475  ! -- read the data
3476  this%check_attr = 1
3477  stressperiod: do
3478  call this%parser%GetNextLine(endofblock)
3479  if (endofblock) exit
3480  !
3481  ! -- get lake or outlet number
3482  itemno = this%parser%GetInteger()
3483  !
3484  ! -- read data from the rest of the line
3485  call this%lak_set_stressperiod(itemno)
3486  !
3487  ! -- write line to table
3488  if (this%iprpak /= 0) then
3489  call this%parser%GetCurrentLine(line)
3490  call this%inputtab%line_to_columns(line)
3491  end if
3492  end do stressperiod
3493  !
3494  if (this%iprpak /= 0) then
3495  call this%inputtab%finalize_table()
3496  end if
3497  !
3498  ! -- using stress period data from the previous stress period
3499  else
3500  write (this%iout, fmtlsp) trim(this%filtyp)
3501  end if
3502  !
3503  ! -- write summary of lake stress period error messages
3504  if (count_errors() > 0) then
3505  call this%parser%StoreErrorUnit()
3506  end if
3507  !
3508  ! -- fill bound array with lake stage, conductance, and bottom elevation
3509  do n = 1, this%nlakes
3510  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
3511  node = this%cellid(j)
3512  this%nodelist(j) = node
3513  this%bound(1, j) = this%xnewpak(n)
3514  this%bound(2, j) = this%satcond(j)
3515  this%bound(3, j) = this%belev(j)
3516  end do
3517  end do
3518  !
3519  ! -- copy lakein into iprmap so mvr budget contains lake instead of outlet
3520  if (this%imover == 1) then
3521  do n = 1, this%noutlets
3522  this%pakmvrobj%iprmap(n) = this%lakein(n)
3523  end do
3524  end if
3525  !
3526  ! -- Return
3527  return
3528  end subroutine lak_rp
3529 
3530  !> @brief Add package connection to matrix
3531  !<
3532  subroutine lak_ad(this)
3533  ! -- modules
3535  ! -- dummy
3536  class(laktype) :: this
3537  ! -- local
3538  integer(I4B) :: n
3539  integer(I4B) :: j
3540  integer(I4B) :: iaux
3541  !
3542  ! -- Advance the time series
3543  call this%TsManager%ad()
3544  !
3545  ! -- update auxiliary variables by copying from the derived-type time
3546  ! series variable into the bndpackage auxvar variable so that this
3547  ! information is properly written to the GWF budget file
3548  if (this%naux > 0) then
3549  do n = 1, this%nlakes
3550  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
3551  do iaux = 1, this%naux
3552  if (this%noupdateauxvar(iaux) /= 0) cycle
3553  this%auxvar(iaux, j) = this%lauxvar(iaux, n)
3554  end do
3555  end do
3556  end do
3557  end if
3558  !
3559  ! -- Update or restore state
3560  if (ifailedstepretry == 0) then
3561  !
3562  ! -- copy xnew into xold and set xnewpak to stage for
3563  ! constant stage lakes
3564  do n = 1, this%nlakes
3565  this%xoldpak(n) = this%xnewpak(n)
3566  this%stageiter(n) = this%xnewpak(n)
3567  if (this%iboundpak(n) < 0) then
3568  this%xnewpak(n) = this%stage(n)
3569  end if
3570  this%seep0(n) = dzero
3571  end do
3572  else
3573  !
3574  ! -- copy xold back into xnew as this is a
3575  ! retry of this time step
3576  do n = 1, this%nlakes
3577  this%xnewpak(n) = this%xoldpak(n)
3578  this%stageiter(n) = this%xnewpak(n)
3579  if (this%iboundpak(n) < 0) then
3580  this%xnewpak(n) = this%stage(n)
3581  end if
3582  this%seep0(n) = dzero
3583  end do
3584  end if
3585  !
3586  ! -- pakmvrobj ad
3587  if (this%imover == 1) then
3588  call this%pakmvrobj%ad()
3589  end if
3590  !
3591  ! -- For each observation, push simulated value and corresponding
3592  ! simulation time from "current" to "preceding" and reset
3593  ! "current" value.
3594  call this%obs%obs_ad()
3595  !
3596  ! -- Return
3597  return
3598  end subroutine lak_ad
3599 
3600  !> @brief Formulate the HCOF and RHS terms
3601  !!
3602  !! Skip if no lakes, otherwise calculate hcof and rhs
3603  !<
3604  subroutine lak_cf(this)
3605  ! -- dummy
3606  class(laktype) :: this
3607  ! -- local
3608  integer(I4B) :: j, n
3609  integer(I4B) :: igwfnode
3610  real(DP) :: hlak, bottom_lake
3611  !
3612  ! -- save groundwater seepage for lake solution
3613  do n = 1, this%nlakes
3614  this%seep0(n) = this%seep(n)
3615  end do
3616  !
3617  ! -- save variables for convergence check
3618  do n = 1, this%nlakes
3619  this%s0(n) = this%xnewpak(n)
3620  call this%lak_calculate_exchange(n, this%s0(n), this%qgwf0(n))
3621  end do
3622  !
3623  ! -- find highest active cell
3624  do n = 1, this%nlakes
3625  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
3626  ! -- skip horizontal connections
3627  if (this%ictype(j) /= 0) then
3628  cycle
3629  end if
3630  igwfnode = this%nodesontop(j)
3631  if (this%ibound(igwfnode) == 0) then
3632  call this%dis%highest_active(igwfnode, this%ibound)
3633  end if
3634  this%nodelist(j) = igwfnode
3635  this%cellid(j) = igwfnode
3636  end do
3637  end do
3638  !
3639  ! -- reset ibound for cells where lake stage is above the bottom
3640  ! of the lake in the cell or the lake is inactive - only applied to
3641  ! vertical connections
3642  do n = 1, this%nlakes
3643  !
3644  hlak = this%xnewpak(n)
3645  !
3646  ! -- Go through lake connections
3647  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
3648  !
3649  ! -- assign gwf node number
3650  igwfnode = this%cellid(j)
3651  !
3652  ! -- skip inactive or constant head GWF cells
3653  if (this%ibound(igwfnode) < 1) then
3654  cycle
3655  end if
3656  !
3657  ! -- skip horizontal connections
3658  if (this%ictype(j) /= 0) then
3659  cycle
3660  end if
3661  !
3662  ! -- skip embedded lakes
3663  if (this%ictype(j) == 2 .or. this%ictype(j) == 3) then
3664  cycle
3665  end if
3666  !
3667  ! -- Mark ibound for wet lakes or inactive lakes; reset to 1 otherwise
3668  bottom_lake = this%belev(j)
3669  if (hlak > bottom_lake .or. this%iboundpak(n) == 0) then
3670  this%ibound(igwfnode) = iwetlake
3671  else
3672  this%ibound(igwfnode) = 1
3673  end if
3674  end do
3675  !
3676  end do
3677  !
3678  ! -- Store the lake stage and cond in bound array for other
3679  ! packages, such as the BUY package
3680  call this%lak_bound_update()
3681  !
3682  ! -- Return
3683  return
3684  end subroutine lak_cf
3685 
3686  !> @brief Copy rhs and hcof into solution rhs and amat
3687  !<
3688  subroutine lak_fc(this, rhs, ia, idxglo, matrix_sln)
3689  ! -- dummy
3690  class(laktype) :: this
3691  real(DP), dimension(:), intent(inout) :: rhs
3692  integer(I4B), dimension(:), intent(in) :: ia
3693  integer(I4B), dimension(:), intent(in) :: idxglo
3694  class(matrixbasetype), pointer :: matrix_sln
3695  ! -- local
3696  integer(I4B) :: j, n
3697  integer(I4B) :: igwfnode
3698  integer(I4B) :: ipossymd
3699  !
3700  ! -- pakmvrobj fc
3701  if (this%imover == 1) then
3702  call this%pakmvrobj%fc()
3703  end if
3704  !
3705  ! -- make a stab at a solution
3706  call this%lak_solve()
3707  !
3708  ! -- add terms to the gwf matrix
3709  do n = 1, this%nlakes
3710  if (this%iboundpak(n) == 0) cycle
3711  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
3712  igwfnode = this%cellid(j)
3713  if (this%ibound(igwfnode) < 1) cycle
3714  ipossymd = idxglo(ia(igwfnode))
3715  call matrix_sln%add_value_pos(ipossymd, this%hcof(j))
3716  rhs(igwfnode) = rhs(igwfnode) + this%rhs(j)
3717  end do
3718  end do
3719  !
3720  ! -- Return
3721  return
3722  end subroutine lak_fc
3723 
3724  !> @brief Fill newton terms
3725  !<
3726  subroutine lak_fn(this, rhs, ia, idxglo, matrix_sln)
3727  ! -- dummy
3728  class(laktype) :: this
3729  real(DP), dimension(:), intent(inout) :: rhs
3730  integer(I4B), dimension(:), intent(in) :: ia
3731  integer(I4B), dimension(:), intent(in) :: idxglo
3732  class(matrixbasetype), pointer :: matrix_sln
3733  ! -- local
3734  integer(I4B) :: j, n
3735  integer(I4B) :: ipos
3736  integer(I4B) :: igwfnode
3737  integer(I4B) :: idry
3738  real(DP) :: hlak
3739  real(DP) :: avail
3740  real(DP) :: ra
3741  real(DP) :: ro
3742  real(DP) :: qinf
3743  real(DP) :: ex
3744  real(DP) :: head
3745  real(DP) :: q
3746  real(DP) :: q1
3747  real(DP) :: rterm
3748  real(DP) :: drterm
3749  !
3750  do n = 1, this%nlakes
3751  if (this%iboundpak(n) == 0) cycle
3752  hlak = this%xnewpak(n)
3753  call this%lak_calculate_available(n, hlak, avail, &
3754  ra, ro, qinf, ex, this%delh)
3755  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
3756  igwfnode = this%cellid(j)
3757  ipos = ia(igwfnode)
3758  head = this%xnew(igwfnode)
3759  if (-this%hcof(j) > dzero) then
3760  if (this%ibound(igwfnode) > 0) then
3761  ! -- estimate lake-aquifer exchange with perturbed groundwater head
3762  ! exchange is relative to the lake
3763  !avail = DEP20
3764  call this%lak_estimate_conn_exchange(2, n, j, idry, hlak, &
3765  head + this%delh, q1, avail)
3766  q1 = -q1
3767  ! -- calculate unperturbed lake-aquifer exchange
3768  q = this%hcof(j) * head - this%rhs(j)
3769  ! -- calculate rterm
3770  rterm = this%hcof(j) * head
3771  ! -- calculate derivative
3772  drterm = (q1 - q) / this%delh
3773  ! -- add terms to convert conductance formulation into
3774  ! newton-raphson formulation
3775  call matrix_sln%add_value_pos(idxglo(ipos), drterm - this%hcof(j))
3776  rhs(igwfnode) = rhs(igwfnode) - rterm + drterm * head
3777  end if
3778  end if
3779  end do
3780  end do
3781  !
3782  ! -- Return
3783  return
3784  end subroutine lak_fn
3785 
3786  !> @brief Final convergence check for package
3787  !<
3788  subroutine lak_cc(this, innertot, kiter, iend, icnvgmod, cpak, ipak, dpak)
3789  ! -- modules
3790  use tdismodule, only: totim, kstp, kper, delt
3791  ! -- dummy
3792  class(laktype), intent(inout) :: this
3793  integer(I4B), intent(in) :: innertot
3794  integer(I4B), intent(in) :: kiter
3795  integer(I4B), intent(in) :: iend
3796  integer(I4B), intent(in) :: icnvgmod
3797  character(len=LENPAKLOC), intent(inout) :: cpak
3798  integer(I4B), intent(inout) :: ipak
3799  real(DP), intent(inout) :: dpak
3800  ! -- local
3801  character(len=LENPAKLOC) :: cloc
3802  character(len=LINELENGTH) :: tag
3803  integer(I4B) :: icheck
3804  integer(I4B) :: ipakfail
3805  integer(I4B) :: locdhmax
3806  integer(I4B) :: locresidmax
3807  integer(I4B) :: locdgwfmax
3808  integer(I4B) :: locdqoutmax
3809  integer(I4B) :: locdqfrommvrmax
3810  integer(I4B) :: ntabrows
3811  integer(I4B) :: ntabcols
3812  integer(I4B) :: n
3813  real(DP) :: q
3814  real(DP) :: q0
3815  real(DP) :: qtolfact
3816  real(DP) :: area
3817  real(DP) :: gwf0
3818  real(DP) :: gwf
3819  real(DP) :: dh
3820  real(DP) :: resid
3821  real(DP) :: dgwf
3822  real(DP) :: hlak0
3823  real(DP) :: hlak
3824  real(DP) :: qout0
3825  real(DP) :: qout
3826  real(DP) :: dqout
3827  real(DP) :: inf
3828  real(DP) :: ra
3829  real(DP) :: ro
3830  real(DP) :: qinf
3831  real(DP) :: ex
3832  real(DP) :: dhmax
3833  real(DP) :: residmax
3834  real(DP) :: dgwfmax
3835  real(DP) :: dqoutmax
3836  real(DP) :: dqfrommvr
3837  real(DP) :: dqfrommvrmax
3838  !
3839  ! -- initialize local variables
3840  icheck = this%iconvchk
3841  ipakfail = 0
3842  locdhmax = 0
3843  locresidmax = 0
3844  locdgwfmax = 0
3845  locdqoutmax = 0
3846  locdqfrommvrmax = 0
3847  dhmax = dzero
3848  residmax = dzero
3849  dgwfmax = dzero
3850  dqoutmax = dzero
3851  dqfrommvrmax = dzero
3852  !
3853  ! -- if not saving package convergence data on check convergence if
3854  ! the model is considered converged
3855  if (this%ipakcsv == 0) then
3856  if (icnvgmod == 0) then
3857  icheck = 0
3858  end if
3859  !
3860  ! -- saving package convergence data
3861  else
3862  !
3863  ! -- header for package csv
3864  if (.not. associated(this%pakcsvtab)) then
3865  !
3866  ! -- determine the number of columns and rows
3867  ntabrows = 1
3868  ntabcols = 11
3869  if (this%noutlets > 0) then
3870  ntabcols = ntabcols + 2
3871  end if
3872  if (this%imover == 1) then
3873  ntabcols = ntabcols + 2
3874  end if
3875  !
3876  ! -- setup table
3877  call table_cr(this%pakcsvtab, this%packName, '')
3878  call this%pakcsvtab%table_df(ntabrows, ntabcols, this%ipakcsv, &
3879  lineseparator=.false., separator=',', &
3880  finalize=.false.)
3881  !
3882  ! -- add columns to package csv
3883  tag = 'total_inner_iterations'
3884  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
3885  tag = 'totim'
3886  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
3887  tag = 'kper'
3888  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
3889  tag = 'kstp'
3890  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
3891  tag = 'nouter'
3892  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
3893  tag = 'dvmax'
3894  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3895  tag = 'dvmax_loc'
3896  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3897  tag = 'residmax'
3898  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3899  tag = 'residmax_loc'
3900  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3901  tag = 'dgwfmax'
3902  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3903  tag = 'dgwfmax_loc'
3904  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3905  if (this%noutlets > 0) then
3906  tag = 'dqoutmax'
3907  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3908  tag = 'dqoutmax_loc'
3909  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3910  end if
3911  if (this%imover == 1) then
3912  tag = 'dqfrommvrmax'
3913  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
3914  tag = 'dqfrommvrmax_loc'
3915  call this%pakcsvtab%initialize_column(tag, 16, alignment=tableft)
3916  end if
3917  end if
3918  end if
3919  !
3920  ! -- perform package convergence check
3921  if (icheck /= 0) then
3922  final_check: do n = 1, this%nlakes
3923  if (this%iboundpak(n) < 1) cycle
3924  !
3925  ! -- set previous and current lake stage
3926  hlak0 = this%s0(n)
3927  hlak = this%xnewpak(n)
3928  !
3929  ! -- stage difference
3930  dh = hlak0 - hlak
3931  !
3932  ! -- calculate surface area
3933  call this%lak_calculate_sarea(n, hlak, area)
3934  !
3935  ! -- set the Q to length factor
3936  if (area > dzero) then
3937  qtolfact = delt / area
3938  else
3939  qtolfact = dzero
3940  end if
3941  !
3942  ! -- difference in the residual
3943  call this%lak_calculate_residual(n, hlak, resid)
3944  resid = resid * qtolfact
3945  !
3946  ! -- change in gwf exchange
3947  dgwf = dzero
3948  if (area > dzero) then
3949  gwf0 = this%qgwf0(n)
3950  call this%lak_calculate_exchange(n, hlak, gwf)
3951  dgwf = (gwf0 - gwf) * qtolfact
3952  end if
3953  !
3954  ! -- change in outflows
3955  dqout = dzero
3956  if (this%noutlets > 0) then
3957  if (area > dzero) then
3958  call this%lak_calculate_available(n, hlak0, inf, ra, ro, qinf, ex)
3959  call this%lak_calculate_outlet_outflow(n, hlak0, inf, qout0)
3960  call this%lak_calculate_available(n, hlak, inf, ra, ro, qinf, ex)
3961  call this%lak_calculate_outlet_outflow(n, hlak, inf, qout)
3962  dqout = (qout0 - qout) * qtolfact
3963  end if
3964  end if
3965  !
3966  ! -- q from mvr
3967  dqfrommvr = dzero
3968  if (this%imover == 1) then
3969  q = this%pakmvrobj%get_qfrommvr(n)
3970  q0 = this%pakmvrobj%get_qfrommvr0(n)
3971  dqfrommvr = qtolfact * (q0 - q)
3972  end if
3973  !
3974  ! -- evaluate magnitude of differences
3975  if (n == 1) then
3976  locdhmax = n
3977  dhmax = dh
3978  locdgwfmax = n
3979  residmax = resid
3980  locresidmax = n
3981  dgwfmax = dgwf
3982  locdqoutmax = n
3983  dqoutmax = dqout
3984  dqfrommvrmax = dqfrommvr
3985  locdqfrommvrmax = n
3986  else
3987  if (abs(dh) > abs(dhmax)) then
3988  locdhmax = n
3989  dhmax = dh
3990  end if
3991  if (abs(resid) > abs(residmax)) then
3992  locresidmax = n
3993  residmax = resid
3994  end if
3995  if (abs(dgwf) > abs(dgwfmax)) then
3996  locdgwfmax = n
3997  dgwfmax = dgwf
3998  end if
3999  if (abs(dqout) > abs(dqoutmax)) then
4000  locdqoutmax = n
4001  dqoutmax = dqout
4002  end if
4003  if (abs(dqfrommvr) > abs(dqfrommvrmax)) then
4004  dqfrommvrmax = dqfrommvr
4005  locdqfrommvrmax = n
4006  end if
4007  end if
4008  end do final_check
4009  !
4010  ! -- set dpak and cpak
4011  if (abs(dhmax) > abs(dpak)) then
4012  ipak = locdhmax
4013  dpak = dhmax
4014  write (cloc, "(a,'-',a)") &
4015  trim(this%packName), 'stage'
4016  cpak = trim(cloc)
4017  end if
4018  if (abs(residmax) > abs(dpak)) then
4019  ipak = locresidmax
4020  dpak = residmax
4021  write (cloc, "(a,'-',a)") &
4022  trim(this%packName), 'residual'
4023  cpak = trim(cloc)
4024  end if
4025  if (abs(dgwfmax) > abs(dpak)) then
4026  ipak = locdgwfmax
4027  dpak = dgwfmax
4028  write (cloc, "(a,'-',a)") &
4029  trim(this%packName), 'gwf'
4030  cpak = trim(cloc)
4031  end if
4032  if (this%noutlets > 0) then
4033  if (abs(dqoutmax) > abs(dpak)) then
4034  ipak = locdqoutmax
4035  dpak = dqoutmax
4036  write (cloc, "(a,'-',a)") &
4037  trim(this%packName), 'outlet'
4038  cpak = trim(cloc)
4039  end if
4040  end if
4041  if (this%imover == 1) then
4042  if (abs(dqfrommvrmax) > abs(dpak)) then
4043  ipak = locdqfrommvrmax
4044  dpak = dqfrommvrmax
4045  write (cloc, "(a,'-',a)") trim(this%packName), 'qfrommvr'
4046  cpak = trim(cloc)
4047  end if
4048  end if
4049  !
4050  ! -- write convergence data to package csv
4051  if (this%ipakcsv /= 0) then
4052  !
4053  ! -- write the data
4054  call this%pakcsvtab%add_term(innertot)
4055  call this%pakcsvtab%add_term(totim)
4056  call this%pakcsvtab%add_term(kper)
4057  call this%pakcsvtab%add_term(kstp)
4058  call this%pakcsvtab%add_term(kiter)
4059  call this%pakcsvtab%add_term(dhmax)
4060  call this%pakcsvtab%add_term(locdhmax)
4061  call this%pakcsvtab%add_term(residmax)
4062  call this%pakcsvtab%add_term(locresidmax)
4063  call this%pakcsvtab%add_term(dgwfmax)
4064  call this%pakcsvtab%add_term(locdgwfmax)
4065  if (this%noutlets > 0) then
4066  call this%pakcsvtab%add_term(dqoutmax)
4067  call this%pakcsvtab%add_term(locdqoutmax)
4068  end if
4069  if (this%imover == 1) then
4070  call this%pakcsvtab%add_term(dqfrommvrmax)
4071  call this%pakcsvtab%add_term(locdqfrommvrmax)
4072  end if
4073  !
4074  ! -- finalize the package csv
4075  if (iend == 1) then
4076  call this%pakcsvtab%finalize_table()
4077  end if
4078  end if
4079  end if
4080  !
4081  ! -- Return
4082  return
4083  end subroutine lak_cc
4084 
4085  !> @brief Calculate flows
4086  !<
4087  subroutine lak_cq(this, x, flowja, iadv)
4088  ! -- modules
4089  use tdismodule, only: delt
4090  ! -- dummy
4091  class(laktype), intent(inout) :: this
4092  real(DP), dimension(:), intent(in) :: x
4093  real(DP), dimension(:), contiguous, intent(inout) :: flowja
4094  integer(I4B), optional, intent(in) :: iadv
4095  ! -- local
4096  real(DP) :: rrate
4097  real(DP) :: chratin, chratout
4098  ! -- for budget
4099  integer(I4B) :: j, n
4100  real(DP) :: hlak
4101  real(DP) :: v0, v1
4102  !
4103  call this%lak_solve(update=.false.)
4104  !
4105  ! -- call base functionality in bnd_cq. This will calculate lake-gwf flows
4106  ! and put them into this%simvals
4107  call this%BndType%bnd_cq(x, flowja, iadv=1)
4108  !
4109  ! -- calculate several budget terms
4110  chratin = dzero
4111  chratout = dzero
4112  do n = 1, this%nlakes
4113  this%chterm(n) = dzero
4114  if (this%iboundpak(n) == 0) cycle
4115  hlak = this%xnewpak(n)
4116  call this%lak_calculate_vol(n, hlak, v1)
4117  !
4118  ! -- add budget terms for active lakes
4119  if (this%iboundpak(n) /= 0) then
4120  !
4121  ! -- rainfall
4122  rrate = this%precip(n)
4123  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4124  !
4125  ! -- evaporation
4126  rrate = this%evap(n)
4127  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4128  !
4129  ! -- runoff
4130  rrate = this%runoff(n)
4131  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4132  !
4133  ! -- inflow
4134  rrate = this%inflow(n)
4135  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4136  !
4137  ! -- withdrawals
4138  rrate = this%withr(n)
4139  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4140  !
4141  ! -- add lake storage changes
4142  rrate = dzero
4143  if (this%iboundpak(n) > 0) then
4144  if (this%gwfiss /= 1) then
4145  call this%lak_calculate_vol(n, this%xoldpak(n), v0)
4146  rrate = -(v1 - v0) / delt
4147  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4148  end if
4149  end if
4150  this%qsto(n) = rrate
4151  !
4152  ! -- add external outlets
4153  call this%lak_get_external_outlet(n, rrate)
4154  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4155  !
4156  ! -- add mover terms
4157  if (this%imover == 1) then
4158  if (this%iboundpak(n) /= 0) then
4159  rrate = this%pakmvrobj%get_qfrommvr(n)
4160  else
4161  rrate = dzero
4162  end if
4163  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4164  end if
4165  end if
4166  end do
4167  !
4168  ! -- gwf flow and constant flow to lake
4169  do n = 1, this%nlakes
4170  rrate = dzero
4171  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
4172  ! simvals is from aquifer perspective, and so it is positive
4173  ! for flow into the aquifer. Need to switch sign for lake
4174  ! perspective.
4175  rrate = -this%simvals(j)
4176  this%qleak(j) = rrate
4177  if (this%iboundpak(n) /= 0) then
4178  call this%lak_accumulate_chterm(n, rrate, chratin, chratout)
4179  end if
4180  end do
4181  end do
4182  !
4183  ! -- fill the budget object
4184  call this%lak_fill_budobj()
4185  !
4186  ! -- Return
4187  return
4188  end subroutine lak_cq
4189 
4190  !> @brief Output LAK package flow terms
4191  !<
4192  subroutine lak_ot_package_flows(this, icbcfl, ibudfl)
4193  use tdismodule, only: kstp, kper, delt, pertim, totim
4194  class(laktype) :: this
4195  integer(I4B), intent(in) :: icbcfl
4196  integer(I4B), intent(in) :: ibudfl
4197  integer(I4B) :: ibinun
4198  !
4199  ! -- write the flows from the budobj
4200  ibinun = 0
4201  if (this%ibudgetout /= 0) then
4202  ibinun = this%ibudgetout
4203  end if
4204  if (icbcfl == 0) ibinun = 0
4205  if (ibinun > 0) then
4206  call this%budobj%save_flows(this%dis, ibinun, kstp, kper, delt, &
4207  pertim, totim, this%iout)
4208  end if
4209  !
4210  ! -- Print lake flows table
4211  if (ibudfl /= 0 .and. this%iprflow /= 0) then
4212  call this%budobj%write_flowtable(this%dis, kstp, kper)
4213  end if
4214  !
4215  ! -- Return
4216  return
4217  end subroutine lak_ot_package_flows
4218 
4219  !> @brief Write flows to binary file and/or print flows to budget
4220  !<
4221  subroutine lak_ot_model_flows(this, icbcfl, ibudfl, icbcun, imap)
4222  class(laktype) :: this
4223  integer(I4B), intent(in) :: icbcfl
4224  integer(I4B), intent(in) :: ibudfl
4225  integer(I4B), intent(in) :: icbcun
4226  integer(I4B), dimension(:), optional, intent(in) :: imap
4227  !
4228  ! -- write the flows from the budobj
4229  call this%BndType%bnd_ot_model_flows(icbcfl, ibudfl, icbcun, this%imap)
4230  !
4231  ! -- Return
4232  return
4233  end subroutine lak_ot_model_flows
4234 
4235  !> @brief Save LAK-calculated values to binary file
4236  !<
4237  subroutine lak_ot_dv(this, idvsave, idvprint)
4238  use tdismodule, only: kstp, kper, pertim, totim
4239  use constantsmodule, only: dhnoflo, dhdry
4240  use inputoutputmodule, only: ulasav
4241  class(laktype) :: this
4242  integer(I4B), intent(in) :: idvsave
4243  integer(I4B), intent(in) :: idvprint
4244  integer(I4B) :: ibinun
4245  integer(I4B) :: n
4246  real(DP) :: v
4247  real(DP) :: d
4248  real(DP) :: stage
4249  real(DP) :: sa
4250  real(DP) :: wa
4251  !
4252  ! -- set unit number for binary dependent variable output
4253  ibinun = 0
4254  if (this%istageout /= 0) then
4255  ibinun = this%istageout
4256  end if
4257  if (idvsave == 0) ibinun = 0
4258  !
4259  ! -- write lake binary output
4260  if (ibinun > 0) then
4261  do n = 1, this%nlakes
4262  v = this%xnewpak(n)
4263  d = v - this%lakebot(n)
4264  if (this%iboundpak(n) == 0) then
4265  v = dhnoflo
4266  else if (d <= dzero) then
4267  v = dhdry
4268  end if
4269  this%dbuff(n) = v
4270  end do
4271  call ulasav(this%dbuff, ' STAGE', kstp, kper, pertim, totim, &
4272  this%nlakes, 1, 1, ibinun)
4273  end if
4274  !
4275  ! -- Print lake stage table
4276  if (idvprint /= 0 .and. this%iprhed /= 0) then
4277  !
4278  ! -- set table kstp and kper
4279  call this%stagetab%set_kstpkper(kstp, kper)
4280  !
4281  ! -- write data
4282  do n = 1, this%nlakes
4283  if (this%iboundpak(n) == 0) then
4284  stage = dhnoflo
4285  sa = dhnoflo
4286  wa = dhnoflo
4287  v = dhnoflo
4288  else
4289  stage = this%xnewpak(n)
4290  call this%lak_calculate_sarea(n, stage, sa)
4291  call this%lak_calculate_warea(n, stage, wa)
4292  call this%lak_calculate_vol(n, stage, v)
4293  end if
4294  if (this%inamedbound == 1) then
4295  call this%stagetab%add_term(this%lakename(n))
4296  end if
4297  call this%stagetab%add_term(n)
4298  call this%stagetab%add_term(stage)
4299  call this%stagetab%add_term(sa)
4300  call this%stagetab%add_term(wa)
4301  call this%stagetab%add_term(v)
4302  end do
4303  end if
4304  !
4305  ! -- Return
4306  return
4307  end subroutine lak_ot_dv
4308 
4309  !> @brief Write LAK budget to listing file
4310  !<
4311  subroutine lak_ot_bdsummary(this, kstp, kper, iout, ibudfl)
4312  ! -- module
4313  use tdismodule, only: totim, delt
4314  ! -- dummy
4315  class(laktype) :: this !< LakType object
4316  integer(I4B), intent(in) :: kstp !< time step number
4317  integer(I4B), intent(in) :: kper !< period number
4318  integer(I4B), intent(in) :: iout !< flag and unit number for the model listing file
4319  integer(I4B), intent(in) :: ibudfl !< flag indicating budget should be written
4320  !
4321  call this%budobj%write_budtable(kstp, kper, iout, ibudfl, totim, delt)
4322  !
4323  ! -- Return
4324  return
4325  end subroutine lak_ot_bdsummary
4326 
4327  !> @brief Deallocate objects
4328  !<
4329  subroutine lak_da(this)
4330  ! -- modules
4332  ! -- dummy
4333  class(laktype) :: this
4334  !
4335  ! -- arrays
4336  deallocate (this%lakename)
4337  deallocate (this%status)
4338  deallocate (this%clakbudget)
4339  call mem_deallocate(this%dbuff)
4340  deallocate (this%cauxcbc)
4341  call mem_deallocate(this%qauxcbc)
4342  call mem_deallocate(this%qleak)
4343  call mem_deallocate(this%qsto)
4344  call mem_deallocate(this%denseterms)
4345  call mem_deallocate(this%viscratios)
4346  !
4347  ! -- tables
4348  if (this%ntables > 0) then
4349  call mem_deallocate(this%ialaktab)
4350  call mem_deallocate(this%tabstage)
4351  call mem_deallocate(this%tabvolume)
4352  call mem_deallocate(this%tabsarea)
4353  call mem_deallocate(this%tabwarea)
4354  end if
4355  !
4356  ! -- budobj
4357  call this%budobj%budgetobject_da()
4358  deallocate (this%budobj)
4359  nullify (this%budobj)
4360  !
4361  ! -- outlets
4362  if (this%noutlets > 0) then
4363  call mem_deallocate(this%lakein)
4364  call mem_deallocate(this%lakeout)
4365  call mem_deallocate(this%iouttype)
4366  call mem_deallocate(this%outrate)
4367  call mem_deallocate(this%outinvert)
4368  call mem_deallocate(this%outwidth)
4369  call mem_deallocate(this%outrough)
4370  call mem_deallocate(this%outslope)
4371  call mem_deallocate(this%simoutrate)
4372  end if
4373  !
4374  ! -- stage table
4375  if (this%iprhed > 0) then
4376  call this%stagetab%table_da()
4377  deallocate (this%stagetab)
4378  nullify (this%stagetab)
4379  end if
4380  !
4381  ! -- package csv table
4382  if (this%ipakcsv > 0) then
4383  if (associated(this%pakcsvtab)) then
4384  call this%pakcsvtab%table_da()
4385  deallocate (this%pakcsvtab)
4386  nullify (this%pakcsvtab)
4387  end if
4388  end if
4389  !
4390  ! -- scalars
4391  call mem_deallocate(this%iprhed)
4392  call mem_deallocate(this%istageout)
4393  call mem_deallocate(this%ibudgetout)
4394  call mem_deallocate(this%ibudcsv)
4395  call mem_deallocate(this%ipakcsv)
4396  call mem_deallocate(this%nlakes)
4397  call mem_deallocate(this%noutlets)
4398  call mem_deallocate(this%ntables)
4399  call mem_deallocate(this%convlength)
4400  call mem_deallocate(this%convtime)
4401  call mem_deallocate(this%outdmax)
4402  call mem_deallocate(this%igwhcopt)
4403  call mem_deallocate(this%iconvchk)
4404  call mem_deallocate(this%iconvresidchk)
4405  call mem_deallocate(this%maxlakit)
4406  call mem_deallocate(this%surfdep)
4407  call mem_deallocate(this%dmaxchg)
4408  call mem_deallocate(this%delh)
4409  call mem_deallocate(this%pdmax)
4410  call mem_deallocate(this%check_attr)
4411  call mem_deallocate(this%bditems)
4412  call mem_deallocate(this%cbcauxitems)
4413  call mem_deallocate(this%idense)
4414  !
4415  call mem_deallocate(this%nlakeconn)
4416  call mem_deallocate(this%idxlakeconn)
4417  call mem_deallocate(this%ntabrow)
4418  call mem_deallocate(this%strt)
4419  call mem_deallocate(this%laketop)
4420  call mem_deallocate(this%lakebot)
4421  call mem_deallocate(this%sareamax)
4422  call mem_deallocate(this%stage)
4423  call mem_deallocate(this%rainfall)
4424  call mem_deallocate(this%evaporation)
4425  call mem_deallocate(this%runoff)
4426  call mem_deallocate(this%inflow)
4427  call mem_deallocate(this%withdrawal)
4428  call mem_deallocate(this%lauxvar)
4429  call mem_deallocate(this%avail)
4430  call mem_deallocate(this%lkgwsink)
4431  call mem_deallocate(this%ncncvr)
4432  call mem_deallocate(this%surfin)
4433  call mem_deallocate(this%surfout)
4434  call mem_deallocate(this%surfout1)
4435  call mem_deallocate(this%precip)
4436  call mem_deallocate(this%precip1)
4437  call mem_deallocate(this%evap)
4438  call mem_deallocate(this%evap1)
4439  call mem_deallocate(this%evapo)
4440  call mem_deallocate(this%withr)
4441  call mem_deallocate(this%withr1)
4442  call mem_deallocate(this%flwin)
4443  call mem_deallocate(this%flwiter)
4444  call mem_deallocate(this%flwiter1)
4445  call mem_deallocate(this%seep)
4446  call mem_deallocate(this%seep1)
4447  call mem_deallocate(this%seep0)
4448  call mem_deallocate(this%stageiter)
4449  call mem_deallocate(this%chterm)
4450  !
4451  ! -- lake boundary and stages
4452  call mem_deallocate(this%iboundpak)
4453  call mem_deallocate(this%xnewpak)
4454  call mem_deallocate(this%xoldpak)
4455  !
4456  ! -- lake iteration variables
4457  call mem_deallocate(this%iseepc)
4458  call mem_deallocate(this%idhc)
4459  call mem_deallocate(this%en1)
4460  call mem_deallocate(this%en2)
4461  call mem_deallocate(this%r1)
4462  call mem_deallocate(this%r2)
4463  call mem_deallocate(this%dh0)
4464  call mem_deallocate(this%s0)
4465  call mem_deallocate(this%qgwf0)
4466  !
4467  ! -- lake connection variables
4468  call mem_deallocate(this%imap)
4469  call mem_deallocate(this%cellid)
4470  call mem_deallocate(this%nodesontop)
4471  call mem_deallocate(this%ictype)
4472  call mem_deallocate(this%bedleak)
4473  call mem_deallocate(this%belev)
4474  call mem_deallocate(this%telev)
4475  call mem_deallocate(this%connlength)
4476  call mem_deallocate(this%connwidth)
4477  call mem_deallocate(this%sarea)
4478  call mem_deallocate(this%warea)
4479  call mem_deallocate(this%satcond)
4480  call mem_deallocate(this%simcond)
4481  call mem_deallocate(this%simlakgw)
4482  !
4483  ! -- pointers to gwf variables
4484  nullify (this%gwfiss)
4485  !
4486  ! -- Parent object
4487  call this%BndType%bnd_da()
4488  !
4489  ! -- Return
4490  return
4491  end subroutine lak_da
4492 
4493  !> @brief Define the list heading that is written to iout when PRINT_INPUT
4494  !! option is used
4495  !<
4496  subroutine define_listlabel(this)
4497  ! -- modules
4498  class(laktype), intent(inout) :: this
4499  !
4500  ! -- create the header list label
4501  this%listlabel = trim(this%filtyp)//' NO.'
4502  if (this%dis%ndim == 3) then
4503  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
4504  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
4505  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
4506  elseif (this%dis%ndim == 2) then
4507  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
4508  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
4509  else
4510  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
4511  end if
4512  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'STRESS RATE'
4513  if (this%inamedbound == 1) then
4514  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
4515  end if
4516  !
4517  ! -- Return
4518  return
4519  end subroutine define_listlabel
4520 
4521  !> @brief Set pointers to model arrays and variables so that a package has
4522  !! access to these things
4523  !<
4524  subroutine lak_set_pointers(this, neq, ibound, xnew, xold, flowja)
4525  ! -- dummy
4526  class(laktype) :: this
4527  integer(I4B), pointer :: neq
4528  integer(I4B), dimension(:), pointer, contiguous :: ibound
4529  real(DP), dimension(:), pointer, contiguous :: xnew
4530  real(DP), dimension(:), pointer, contiguous :: xold
4531  real(DP), dimension(:), pointer, contiguous :: flowja
4532  !
4533  ! -- call base BndType set_pointers
4534  call this%BndType%set_pointers(neq, ibound, xnew, xold, flowja)
4535  !
4536  ! -- Set the LAK pointers
4537  !
4538  ! -- set package pointers
4539  !istart = this%dis%nodes + this%ioffset + 1
4540  !iend = istart + this%nlakes - 1
4541  !this%iboundpak => this%ibound(istart:iend)
4542  !this%xnewpak => this%xnew(istart:iend)
4543  !
4544  ! -- initialize xnewpak
4545  !do n = 1, this%nlakes
4546  ! this%xnewpak(n) = DEP20
4547  !end do
4548  !
4549  ! -- Return
4550  return
4551  end subroutine lak_set_pointers
4552 
4553  !> @brief Procedures related to observations (type-bound)
4554  !!
4555  !! Return true because LAK package supports observations. Overrides
4556  !! BndType%bnd_obs_supported()
4557  !<
4558  logical function lak_obs_supported(this)
4559  ! -- dummy
4560  class(laktype) :: this
4561  !
4562  lak_obs_supported = .true.
4563  !
4564  ! -- Return
4565  return
4566  end function lak_obs_supported
4567 
4568  !> @brief Store observation type supported by LAK package. Overrides
4569  !! BndType%bnd_df_obs
4570  !<
4571  subroutine lak_df_obs(this)
4572  ! -- dummy
4573  class(laktype) :: this
4574  ! -- local
4575  integer(I4B) :: indx
4576  !
4577  ! -- Store obs type and assign procedure pointer
4578  ! for stage observation type.
4579  call this%obs%StoreObsType('stage', .false., indx)
4580  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4581  !
4582  ! -- Store obs type and assign procedure pointer
4583  ! for ext-inflow observation type.
4584  call this%obs%StoreObsType('ext-inflow', .true., indx)
4585  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4586  !
4587  ! -- Store obs type and assign procedure pointer
4588  ! for outlet-inflow observation type.
4589  call this%obs%StoreObsType('outlet-inflow', .true., indx)
4590  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4591  !
4592  ! -- Store obs type and assign procedure pointer
4593  ! for inflow observation type.
4594  call this%obs%StoreObsType('inflow', .true., indx)
4595  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4596  !
4597  ! -- Store obs type and assign procedure pointer
4598  ! for from-mvr observation type.
4599  call this%obs%StoreObsType('from-mvr', .true., indx)
4600  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4601  !
4602  ! -- Store obs type and assign procedure pointer
4603  ! for rainfall observation type.
4604  call this%obs%StoreObsType('rainfall', .true., indx)
4605  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4606  !
4607  ! -- Store obs type and assign procedure pointer
4608  ! for runoff observation type.
4609  call this%obs%StoreObsType('runoff', .true., indx)
4610  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4611  !
4612  ! -- Store obs type and assign procedure pointer
4613  ! for lak observation type.
4614  call this%obs%StoreObsType('lak', .true., indx)
4615  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4616  !
4617  ! -- Store obs type and assign procedure pointer
4618  ! for evaporation observation type.
4619  call this%obs%StoreObsType('evaporation', .true., indx)
4620  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4621  !
4622  ! -- Store obs type and assign procedure pointer
4623  ! for withdrawal observation type.
4624  call this%obs%StoreObsType('withdrawal', .true., indx)
4625  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4626  !
4627  ! -- Store obs type and assign procedure pointer
4628  ! for ext-outflow observation type.
4629  call this%obs%StoreObsType('ext-outflow', .true., indx)
4630  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4631  !
4632  ! -- Store obs type and assign procedure pointer
4633  ! for to-mvr observation type.
4634  call this%obs%StoreObsType('to-mvr', .true., indx)
4635  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4636  !
4637  ! -- Store obs type and assign procedure pointer
4638  ! for storage observation type.
4639  call this%obs%StoreObsType('storage', .true., indx)
4640  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4641  !
4642  ! -- Store obs type and assign procedure pointer
4643  ! for constant observation type.
4644  call this%obs%StoreObsType('constant', .true., indx)
4645  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4646  !
4647  ! -- Store obs type and assign procedure pointer
4648  ! for outlet observation type.
4649  call this%obs%StoreObsType('outlet', .true., indx)
4650  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4651  !
4652  ! -- Store obs type and assign procedure pointer
4653  ! for volume observation type.
4654  call this%obs%StoreObsType('volume', .true., indx)
4655  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4656  !
4657  ! -- Store obs type and assign procedure pointer
4658  ! for surface-area observation type.
4659  call this%obs%StoreObsType('surface-area', .true., indx)
4660  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4661  !
4662  ! -- Store obs type and assign procedure pointer
4663  ! for wetted-area observation type.
4664  call this%obs%StoreObsType('wetted-area', .true., indx)
4665  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4666  !
4667  ! -- Store obs type and assign procedure pointer
4668  ! for conductance observation type.
4669  call this%obs%StoreObsType('conductance', .true., indx)
4670  this%obs%obsData(indx)%ProcessIdPtr => lak_process_obsid
4671  !
4672  ! -- Return
4673  return
4674  end subroutine lak_df_obs
4675 
4676  !> @brief Calculate observations this time step and call ObsType%SaveOneSimval
4677  !! for each LakType observation.
4678  !<
4679  subroutine lak_bd_obs(this)
4680  ! -- dummy
4681  class(laktype) :: this
4682  ! -- local
4683  integer(I4B) :: i
4684  integer(I4B) :: igwfnode
4685  integer(I4B) :: j
4686  integer(I4B) :: jj
4687  integer(I4B) :: n
4688  real(DP) :: hgwf
4689  real(DP) :: hlak
4690  real(DP) :: v
4691  real(DP) :: v2
4692  type(observetype), pointer :: obsrv => null()
4693  !
4694  ! Write simulated values for all LAK observations
4695  if (this%obs%npakobs > 0) then
4696  call this%obs%obs_bd_clear()
4697  do i = 1, this%obs%npakobs
4698  obsrv => this%obs%pakobs(i)%obsrv
4699  do j = 1, obsrv%indxbnds_count
4700  v = dnodata
4701  jj = obsrv%indxbnds(j)
4702  select case (obsrv%ObsTypeId)
4703  case ('STAGE')
4704  if (this%iboundpak(jj) /= 0) then
4705  v = this%xnewpak(jj)
4706  end if
4707  case ('EXT-INFLOW')
4708  if (this%iboundpak(jj) /= 0) then
4709  call this%lak_calculate_inflow(jj, v)
4710  end if
4711  case ('OUTLET-INFLOW')
4712  if (this%iboundpak(jj) /= 0) then
4713  call this%lak_calculate_outlet_inflow(jj, v)
4714  end if
4715  case ('INFLOW')
4716  if (this%iboundpak(jj) /= 0) then
4717  call this%lak_calculate_inflow(jj, v)
4718  call this%lak_calculate_outlet_inflow(jj, v2)
4719  v = v + v2
4720  end if
4721  case ('FROM-MVR')
4722  if (this%iboundpak(jj) /= 0) then
4723  if (this%imover == 1) then
4724  v = this%pakmvrobj%get_qfrommvr(jj)
4725  end if
4726  end if
4727  case ('RAINFALL')
4728  if (this%iboundpak(jj) /= 0) then
4729  v = this%precip(jj)
4730  end if
4731  case ('RUNOFF')
4732  if (this%iboundpak(jj) /= 0) then
4733  v = this%runoff(jj)
4734  end if
4735  case ('LAK')
4736  n = this%imap(jj)
4737  if (this%iboundpak(n) /= 0) then
4738  igwfnode = this%cellid(jj)
4739  hgwf = this%xnew(igwfnode)
4740  if (this%hcof(jj) /= dzero) then
4741  v = -(this%hcof(jj) * (this%xnewpak(n) - hgwf))
4742  else
4743  v = -this%rhs(jj)
4744  end if
4745  end if
4746  case ('EVAPORATION')
4747  if (this%iboundpak(jj) /= 0) then
4748  v = this%evap(jj)
4749  end if
4750  case ('WITHDRAWAL')
4751  if (this%iboundpak(jj) /= 0) then
4752  v = this%withr(jj)
4753  end if
4754  case ('EXT-OUTFLOW')
4755  n = this%lakein(jj)
4756  if (this%iboundpak(n) /= 0) then
4757  if (this%lakeout(jj) == 0) then
4758  v = this%simoutrate(jj)
4759  if (v < dzero) then
4760  if (this%imover == 1) then
4761  v = v + this%pakmvrobj%get_qtomvr(jj)
4762  end if
4763  end if
4764  end if
4765  end if
4766  case ('TO-MVR')
4767  n = this%lakein(jj)
4768  if (this%iboundpak(n) /= 0) then
4769  if (this%imover == 1) then
4770  v = this%pakmvrobj%get_qtomvr(jj)
4771  if (v > dzero) then
4772  v = -v
4773  end if
4774  end if
4775  end if
4776  case ('STORAGE')
4777  if (this%iboundpak(jj) /= 0) then
4778  v = this%qsto(jj)
4779  end if
4780  case ('CONSTANT')
4781  if (this%iboundpak(jj) /= 0) then
4782  v = this%chterm(jj)
4783  end if
4784  case ('OUTLET')
4785  n = this%lakein(jj)
4786  if (this%iboundpak(n) /= 0) then
4787  v = this%simoutrate(jj)
4788  end if
4789  case ('VOLUME')
4790  if (this%iboundpak(jj) /= 0) then
4791  call this%lak_calculate_vol(jj, this%xnewpak(jj), v)
4792  end if
4793  case ('SURFACE-AREA')
4794  if (this%iboundpak(jj) /= 0) then
4795  hlak = this%xnewpak(jj)
4796  call this%lak_calculate_sarea(jj, hlak, v)
4797  end if
4798  case ('WETTED-AREA')
4799  n = this%imap(jj)
4800  if (this%iboundpak(n) /= 0) then
4801  hlak = this%xnewpak(n)
4802  igwfnode = this%cellid(jj)
4803  hgwf = this%xnew(igwfnode)
4804  call this%lak_calculate_conn_warea(n, jj, hlak, hgwf, v)
4805  end if
4806  case ('CONDUCTANCE')
4807  n = this%imap(jj)
4808  if (this%iboundpak(n) /= 0) then
4809  hlak = this%xnewpak(n)
4810  igwfnode = this%cellid(jj)
4811  hgwf = this%xnew(igwfnode)
4812  call this%lak_calculate_conn_conductance(n, jj, hlak, hgwf, v)
4813  end if
4814  case default
4815  errmsg = 'Unrecognized observation type: '//trim(obsrv%ObsTypeId)
4816  call store_error(errmsg)
4817  end select
4818  call this%obs%SaveOneSimval(obsrv, v)
4819  end do
4820  end do
4821  !
4822  ! -- write summary of error messages
4823  if (count_errors() > 0) then
4824  call store_error_unit(this%inunit)
4825  end if
4826  end if
4827  !
4828  ! -- Return
4829  return
4830  end subroutine lak_bd_obs
4831 
4832  !> @brief Process each observation
4833  !!
4834  !! Only done the first stress period since boundaries are fixed for the
4835  !! simulation
4836  !<
4837  subroutine lak_rp_obs(this)
4838  use tdismodule, only: kper
4839  ! -- dummy
4840  class(laktype), intent(inout) :: this
4841  ! -- local
4842  integer(I4B) :: i
4843  integer(I4B) :: j
4844  integer(I4B) :: nn1
4845  integer(I4B) :: nn2
4846  integer(I4B) :: jj
4847  character(len=LENBOUNDNAME) :: bname
4848  logical(LGP) :: jfound
4849  class(observetype), pointer :: obsrv => null()
4850  ! -- formats
4851 10 format('Boundary "', a, '" for observation "', a, &
4852  '" is invalid in package "', a, '"')
4853  !
4854  ! -- process each package observation
4855  ! only done the first stress period since boundaries are fixed
4856  ! for the simulation
4857  if (kper == 1) then
4858  do i = 1, this%obs%npakobs
4859  obsrv => this%obs%pakobs(i)%obsrv
4860  !
4861  ! -- get node number 1
4862  nn1 = obsrv%NodeNumber
4863  if (nn1 == namedboundflag) then
4864  bname = obsrv%FeatureName
4865  if (bname /= '') then
4866  ! -- Observation lake is based on a boundary name.
4867  ! Iterate through all lakes to identify and store
4868  ! corresponding index in bound array.
4869  jfound = .false.
4870  if (obsrv%ObsTypeId == 'LAK' .or. &
4871  obsrv%ObsTypeId == 'CONDUCTANCE' .or. &
4872  obsrv%ObsTypeId == 'WETTED-AREA') then
4873  do j = 1, this%nlakes
4874  do jj = this%idxlakeconn(j), this%idxlakeconn(j + 1) - 1
4875  if (this%boundname(jj) == bname) then
4876  jfound = .true.
4877  call obsrv%AddObsIndex(jj)
4878  end if
4879  end do
4880  end do
4881  else if (obsrv%ObsTypeId == 'EXT-OUTFLOW' .or. &
4882  obsrv%ObsTypeId == 'TO-MVR' .or. &
4883  obsrv%ObsTypeId == 'OUTLET') then
4884  do j = 1, this%noutlets
4885  jj = this%lakein(j)
4886  if (this%lakename(jj) == bname) then
4887  jfound = .true.
4888  call obsrv%AddObsIndex(j)
4889  end if
4890  end do
4891  else
4892  do j = 1, this%nlakes
4893  if (this%lakename(j) == bname) then
4894  jfound = .true.
4895  call obsrv%AddObsIndex(j)
4896  end if
4897  end do
4898  end if
4899  if (.not. jfound) then
4900  write (errmsg, 10) &
4901  trim(bname), trim(obsrv%Name), trim(this%packName)
4902  call store_error(errmsg)
4903  end if
4904  end if
4905  else
4906  if (obsrv%indxbnds_count == 0) then
4907  if (obsrv%ObsTypeId == 'LAK' .or. &
4908  obsrv%ObsTypeId == 'CONDUCTANCE' .or. &
4909  obsrv%ObsTypeId == 'WETTED-AREA') then
4910  nn2 = obsrv%NodeNumber2
4911  j = this%idxlakeconn(nn1) + nn2 - 1
4912  call obsrv%AddObsIndex(j)
4913  else
4914  call obsrv%AddObsIndex(nn1)
4915  end if
4916  else
4917  errmsg = 'Programming error in lak_rp_obs'
4918  call store_error(errmsg)
4919  end if
4920  end if
4921  !
4922  ! -- catch non-cumulative observation assigned to observation defined
4923  ! by a boundname that is assigned to more than one element
4924  if (obsrv%ObsTypeId == 'STAGE') then
4925  if (obsrv%indxbnds_count > 1) then
4926  write (errmsg, '(a,3(1x,a))') &
4927  trim(adjustl(obsrv%ObsTypeId)), &
4928  'for observation', trim(adjustl(obsrv%Name)), &
4929  ' must be assigned to a lake with a unique boundname.'
4930  call store_error(errmsg)
4931  end if
4932  end if
4933  !
4934  ! -- check that index values are valid
4935  if (obsrv%ObsTypeId == 'TO-MVR' .or. &
4936  obsrv%ObsTypeId == 'EXT-OUTFLOW' .or. &
4937  obsrv%ObsTypeId == 'OUTLET') then
4938  do j = 1, obsrv%indxbnds_count
4939  nn1 = obsrv%indxbnds(j)
4940  if (nn1 < 1 .or. nn1 > this%noutlets) then
4941  write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
4942  trim(adjustl(obsrv%ObsTypeId)), &
4943  ' outlet must be > 0 and <=', this%noutlets, &
4944  '(specified value is ', nn1, ')'
4945  call store_error(errmsg)
4946  end if
4947  end do
4948  else if (obsrv%ObsTypeId == 'LAK' .or. &
4949  obsrv%ObsTypeId == 'CONDUCTANCE' .or. &
4950  obsrv%ObsTypeId == 'WETTED-AREA') then
4951  do j = 1, obsrv%indxbnds_count
4952  nn1 = obsrv%indxbnds(j)
4953  if (nn1 < 1 .or. nn1 > this%maxbound) then
4954  write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
4955  trim(adjustl(obsrv%ObsTypeId)), &
4956  'lake connection number must be > 0 and <=', this%maxbound, &
4957  '(specified value is ', nn1, ')'
4958  call store_error(errmsg)
4959  end if
4960  end do
4961  else
4962  do j = 1, obsrv%indxbnds_count
4963  nn1 = obsrv%indxbnds(j)
4964  if (nn1 < 1 .or. nn1 > this%nlakes) then
4965  write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
4966  trim(adjustl(obsrv%ObsTypeId)), &
4967  ' lake must be > 0 and <=', this%nlakes, &
4968  '(specified value is ', nn1, ')'
4969  call store_error(errmsg)
4970  end if
4971  end do
4972  end if
4973  end do
4974  !
4975  ! -- evaluate if there are any observation errors
4976  if (count_errors() > 0) then
4977  call store_error_unit(this%inunit)
4978  end if
4979  end if
4980  !
4981  ! -- Return
4982  return
4983  end subroutine lak_rp_obs
4984 
4985  !
4986  ! -- Procedures related to observations (NOT type-bound)
4987 
4988  !> @brief This procedure is pointed to by ObsDataType%ProcesssIdPtr. It
4989  !! processes the ID string of an observation definition for LAK package
4990  !! observations.
4991  !<
4992  subroutine lak_process_obsid(obsrv, dis, inunitobs, iout)
4993  ! -- dummy
4994  type(observetype), intent(inout) :: obsrv
4995  class(disbasetype), intent(in) :: dis
4996  integer(I4B), intent(in) :: inunitobs
4997  integer(I4B), intent(in) :: iout
4998  ! -- local
4999  integer(I4B) :: nn1, nn2
5000  integer(I4B) :: icol, istart, istop
5001  character(len=LINELENGTH) :: string
5002  character(len=LENBOUNDNAME) :: bndname
5003  !
5004  string = obsrv%IDstring
5005  ! -- Extract lake number from string and store it.
5006  ! If 1st item is not an integer(I4B), it should be a
5007  ! lake name--deal with it.
5008  icol = 1
5009  ! -- get lake number or boundary name
5010  call extract_idnum_or_bndname(string, icol, istart, istop, nn1, bndname)
5011  if (nn1 == namedboundflag) then
5012  obsrv%FeatureName = bndname
5013  else
5014  if (obsrv%ObsTypeId == 'LAK' .or. obsrv%ObsTypeId == 'CONDUCTANCE' .or. &
5015  obsrv%ObsTypeId == 'WETTED-AREA') then
5016  call extract_idnum_or_bndname(string, icol, istart, istop, nn2, bndname)
5017  if (len_trim(bndname) < 1 .and. nn2 < 0) then
5018  write (errmsg, '(a,1x,a,a,1x,a,1x,a)') &
5019  'For observation type', trim(adjustl(obsrv%ObsTypeId)), &
5020  ', ID given as an integer and not as boundname,', &
5021  'but ID2 (iconn) is missing. Either change ID to valid', &
5022  'boundname or supply valid entry for ID2.'
5023  call store_error(errmsg)
5024  end if
5025  if (nn2 == namedboundflag) then
5026  obsrv%FeatureName = bndname
5027  ! -- reset nn1
5028  nn1 = nn2
5029  else
5030  obsrv%NodeNumber2 = nn2
5031  end if
5032  end if
5033  end if
5034  ! -- store lake number (NodeNumber)
5035  obsrv%NodeNumber = nn1
5036  !
5037  ! -- Return
5038  return
5039  end subroutine lak_process_obsid
5040 
5041  !
5042  ! -- private LAK methods
5043  !
5044 
5045  !> @brief Accumulate constant head terms for budget
5046  !<
5047  subroutine lak_accumulate_chterm(this, ilak, rrate, chratin, chratout)
5048  ! -- dummy
5049  class(laktype) :: this
5050  integer(I4B), intent(in) :: ilak
5051  real(DP), intent(in) :: rrate
5052  real(DP), intent(inout) :: chratin
5053  real(DP), intent(inout) :: chratout
5054  ! -- locals
5055  real(DP) :: q
5056  !
5057  ! code
5058  if (this%iboundpak(ilak) < 0) then
5059  q = -rrate
5060  this%chterm(ilak) = this%chterm(ilak) + q
5061  !
5062  ! -- See if flow is into lake or out of lake.
5063  if (q < dzero) then
5064  !
5065  ! -- Flow is out of lake subtract rate from ratout.
5066  chratout = chratout - q
5067  else
5068  !
5069  ! -- Flow is into lake; add rate to ratin.
5070  chratin = chratin + q
5071  end if
5072  end if
5073  !
5074  ! -- Return
5075  return
5076  end subroutine lak_accumulate_chterm
5077 
5078  !> @brief Store the lake head and connection conductance in the bound array
5079  !<
5080  subroutine lak_bound_update(this)
5081  ! -- dummy
5082  class(laktype), intent(inout) :: this
5083  ! -- local
5084  integer(I4B) :: j, n, node
5085  real(DP) :: hlak, head, clak
5086  !
5087  ! -- Return if no lak lakes
5088  if (this%nbound == 0) return
5089  !
5090  ! -- Calculate hcof and rhs for each lak entry
5091  do n = 1, this%nlakes
5092  hlak = this%xnewpak(n)
5093  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5094  node = this%cellid(j)
5095  head = this%xnew(node)
5096  call this%lak_calculate_conn_conductance(n, j, hlak, head, clak)
5097  this%bound(1, j) = hlak
5098  this%bound(2, j) = clak
5099  end do
5100  end do
5101  !
5102  ! -- Return
5103  return
5104  end subroutine lak_bound_update
5105 
5106  !> @brief Solve for lake stage
5107  !<
5108  subroutine lak_solve(this, update)
5109  ! -- modules
5110  use tdismodule, only: delt
5111  ! -- dummy
5112  class(laktype), intent(inout) :: this
5113  logical(LGP), intent(in), optional :: update
5114  ! -- local
5115  logical(LGP) :: lupdate
5116  integer(I4B) :: i
5117  integer(I4B) :: j
5118  integer(I4B) :: n
5119  integer(I4B) :: iicnvg
5120  integer(I4B) :: iter
5121  integer(I4B) :: maxiter
5122  integer(I4B) :: ncnv
5123  integer(I4B) :: idry
5124  integer(I4B) :: idry1
5125  integer(I4B) :: igwfnode
5126  integer(I4B) :: ibflg
5127  integer(I4B) :: idhp
5128  real(DP) :: hlak
5129  real(DP) :: hlak0
5130  real(DP) :: v0
5131  real(DP) :: v1
5132  real(DP) :: head
5133  real(DP) :: ra
5134  real(DP) :: ro
5135  real(DP) :: qinf
5136  real(DP) :: ex
5137  real(DP) :: ev
5138  real(DP) :: outinf
5139  real(DP) :: qlakgw
5140  real(DP) :: qlakgw1
5141  real(DP) :: gwfhcof
5142  real(DP) :: gwfrhs
5143  real(DP) :: avail
5144  real(DP) :: resid
5145  real(DP) :: resid1
5146  real(DP) :: residb
5147  real(DP) :: wr
5148  real(DP) :: derv
5149  real(DP) :: dh
5150  real(DP) :: adh
5151  real(DP) :: adh0
5152  real(DP) :: delh
5153  real(DP) :: ts
5154  real(DP) :: area
5155  real(DP) :: qtolfact
5156  !
5157  ! -- set lupdate
5158  if (present(update)) then
5159  lupdate = update
5160  else
5161  lupdate = .true.
5162  end if
5163  !
5164  ! -- initialize
5165  avail = dzero
5166  delh = this%delh
5167  !
5168  ! -- initialize
5169  do n = 1, this%nlakes
5170  this%ncncvr(n) = 0
5171  this%surfin(n) = dzero
5172  this%surfout(n) = dzero
5173  this%surfout1(n) = dzero
5174  if (this%xnewpak(n) < this%lakebot(n)) then
5175  this%xnewpak(n) = this%lakebot(n)
5176  end if
5177  if (this%gwfiss /= 0) then
5178  this%xoldpak(n) = this%xnewpak(n)
5179  end if
5180  ! -- lake iteration items
5181  this%iseepc(n) = 0
5182  this%idhc(n) = 0
5183  this%en1(n) = this%lakebot(n)
5184  call this%lak_calculate_residual(n, this%en1(n), this%r1(n))
5185  this%en2(n) = this%laketop(n)
5186  call this%lak_calculate_residual(n, this%en2(n), this%r2(n))
5187  end do
5188  do n = 1, this%noutlets
5189  this%simoutrate(n) = dzero
5190  end do
5191  !
5192  ! -- sum up inflows from mover inflows
5193  do n = 1, this%nlakes
5194  call this%lak_calculate_outlet_inflow(n, this%surfin(n))
5195  end do
5196  !
5197  ! -- sum up overland runoff, inflows, and external flows into lake
5198  ! (includes maximum lake volume)
5199  do n = 1, this%nlakes
5200  hlak0 = this%xoldpak(n)
5201  hlak = this%xnewpak(n)
5202  call this%lak_calculate_runoff(n, ro)
5203  call this%lak_calculate_inflow(n, qinf)
5204  call this%lak_calculate_external(n, ex)
5205  call this%lak_calculate_vol(n, hlak0, v0)
5206  call this%lak_calculate_vol(n, hlak, v1)
5207  this%flwin(n) = this%surfin(n) + ro + qinf + ex + &
5208  max(v0, v1) / delt
5209  end do
5210  !
5211  ! -- sum up inflows from upstream outlets
5212  do n = 1, this%nlakes
5213  call this%lak_calculate_outlet_inflow(n, outinf)
5214  this%flwin(n) = this%flwin(n) + outinf
5215  end do
5216  !
5217  iicnvg = 0
5218  maxiter = this%maxlakit
5219  !
5220  ! -- outer loop
5221  converge: do iter = 1, maxiter
5222  ncnv = 0
5223  do n = 1, this%nlakes
5224  if (this%ncncvr(n) == 0) ncnv = 1
5225  end do
5226  if (iter == maxiter) ncnv = 0
5227  if (ncnv == 0) iicnvg = 1
5228  !
5229  ! -- initialize variables
5230  do n = 1, this%nlakes
5231  this%evap(n) = dzero
5232  this%precip(n) = dzero
5233  this%precip1(n) = dzero
5234  this%seep(n) = dzero
5235  this%seep1(n) = dzero
5236  this%evap(n) = dzero
5237  this%evap1(n) = dzero
5238  this%evapo(n) = dzero
5239  this%withr(n) = dzero
5240  this%withr1(n) = dzero
5241  this%flwiter(n) = this%flwin(n)
5242  this%flwiter1(n) = this%flwin(n)
5243  if (this%gwfiss /= 0) then
5244  this%flwiter(n) = dep20
5245  this%flwiter1(n) = dep20
5246  end if
5247  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5248  this%hcof(j) = dzero
5249  this%rhs(j) = dzero
5250  end do
5251  end do
5252  !
5253  estseep: do i = 1, 2
5254  lakseep: do n = 1, this%nlakes
5255  ! -- skip inactive lakes
5256  if (this%iboundpak(n) == 0) then
5257  cycle lakseep
5258  end if
5259  ! - set xoldpak to xnewpak if steady-state
5260  if (this%gwfiss /= 0) then
5261  this%xoldpak(n) = this%xnewpak(n)
5262  end if
5263  hlak = this%xnewpak(n)
5264  calcconnseep: do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5265  igwfnode = this%cellid(j)
5266  head = this%xnew(igwfnode)
5267  if (this%ncncvr(n) /= 2) then
5268  if (this%ibound(igwfnode) > 0) then
5269  call this%lak_estimate_conn_exchange(i, n, j, idry, hlak, &
5270  head, qlakgw, &
5271  this%flwiter(n), &
5272  gwfhcof, gwfrhs)
5273  call this%lak_estimate_conn_exchange(i, n, j, idry1, &
5274  hlak + delh, head, qlakgw1, &
5275  this%flwiter1(n))
5276  !
5277  ! -- add to gwf matrix
5278  if (ncnv == 0 .and. i == 2) then
5279  if (j == this%maxbound) then
5280  this%ncncvr(n) = 2
5281  end if
5282  if (idry /= 1) then
5283  this%hcof(j) = gwfhcof
5284  this%rhs(j) = gwfrhs
5285  else
5286  this%hcof(j) = dzero
5287  this%rhs(j) = qlakgw
5288  end if
5289  end if
5290  if (i == 2) then
5291  this%seep(n) = this%seep(n) + qlakgw
5292  this%seep1(n) = this%seep1(n) + qlakgw1
5293  end if
5294  end if
5295  end if
5296  !
5297  end do calcconnseep
5298  end do lakseep
5299  end do estseep
5300  !
5301  laklevel: do n = 1, this%nlakes
5302  ! -- skip inactive lakes
5303  if (this%iboundpak(n) == 0) then
5304  this%ncncvr(n) = 1
5305  cycle laklevel
5306  end if
5307  ibflg = 0
5308  hlak = this%xnewpak(n)
5309  if (iter < maxiter) then
5310  this%stageiter(n) = this%xnewpak(n)
5311  end if
5312  call this%lak_calculate_rainfall(n, hlak, ra)
5313  this%precip(n) = ra
5314  this%flwiter(n) = this%flwiter(n) + ra
5315  call this%lak_calculate_rainfall(n, hlak + delh, ra)
5316  this%precip1(n) = ra
5317  this%flwiter1(n) = this%flwiter1(n) + ra
5318  !
5319  ! -- limit withdrawals to lake inflows and lake storage
5320  call this%lak_calculate_withdrawal(n, this%flwiter(n), wr)
5321  this%withr(n) = wr
5322  call this%lak_calculate_withdrawal(n, this%flwiter1(n), wr)
5323  this%withr1(n) = wr
5324  !
5325  ! -- limit evaporation to lake inflows and lake storage
5326  call this%lak_calculate_evaporation(n, hlak, this%flwiter(n), ev)
5327  this%evap(n) = ev
5328  call this%lak_calculate_evaporation(n, hlak + delh, this%flwiter1(n), ev)
5329  this%evap1(n) = ev
5330  !
5331  ! -- no outlet flow if evaporation consumes all water
5332  call this%lak_calculate_outlet_outflow(n, hlak + delh, &
5333  this%flwiter1(n), &
5334  this%surfout1(n))
5335  call this%lak_calculate_outlet_outflow(n, hlak, this%flwiter(n), &
5336  this%surfout(n))
5337  !
5338  ! -- update the surface inflow values
5339  call this%lak_calculate_outlet_inflow(n, this%surfin(n))
5340  !
5341  !
5342  if (ncnv == 1) then
5343  if (this%iboundpak(n) > 0 .and. lupdate .eqv. .true.) then
5344  !
5345  ! -- recalculate flwin
5346  hlak0 = this%xoldpak(n)
5347  hlak = this%xnewpak(n)
5348  call this%lak_calculate_vol(n, hlak0, v0)
5349  call this%lak_calculate_vol(n, hlak, v1)
5350  call this%lak_calculate_runoff(n, ro)
5351  call this%lak_calculate_inflow(n, qinf)
5352  call this%lak_calculate_external(n, ex)
5353  this%flwin(n) = this%surfin(n) + ro + qinf + ex + &
5354  max(v0, v1) / delt
5355  !
5356  ! -- compute new lake stage using Newton's method
5357  resid = this%precip(n) + this%evap(n) + this%withr(n) + ro + &
5358  qinf + ex + this%surfin(n) + &
5359  this%surfout(n) + this%seep(n)
5360  resid1 = this%precip1(n) + this%evap1(n) + this%withr1(n) + ro + &
5361  qinf + ex + this%surfin(n) + &
5362  this%surfout1(n) + this%seep1(n)
5363  !
5364  ! -- add storage changes for transient stress periods
5365  hlak = this%xnewpak(n)
5366  if (this%gwfiss /= 1) then
5367  call this%lak_calculate_vol(n, hlak, v1)
5368  resid = resid + (v0 - v1) / delt
5369  call this%lak_calculate_vol(n, hlak + delh, v1)
5370  resid1 = resid1 + (v0 - v1) / delt
5371  end if
5372  !
5373  ! -- determine the derivative and the stage change
5374  if (abs(resid1 - resid) > dzero) then
5375  derv = (resid1 - resid) / delh
5376  dh = dzero
5377  if (abs(derv) > dprec) then
5378  dh = resid / derv
5379  end if
5380  else
5381  if (resid < dzero) then
5382  resid = dzero
5383  end if
5384  call this%lak_vol2stage(n, resid, dh)
5385  dh = hlak - dh
5386  this%ncncvr(n) = 1
5387  end if
5388  !
5389  ! -- determine if the updated stage is outside the endpoints
5390  ts = hlak - dh
5391  if (iter == 1) this%dh0(n) = dh
5392  adh = abs(dh)
5393  adh0 = abs(this%dh0(n))
5394  if ((ts >= this%en2(n)) .or. (ts < this%en1(n))) then
5395  ! -- use bisection if dh is increasing or updated stage is below the
5396  ! bottom of the lake
5397  if ((adh > adh0) .or. (ts - this%lakebot(n)) < dprec) then
5398  residb = resid
5399  call this%lak_bisection(n, ibflg, hlak, ts, dh, residb)
5400  end if
5401  end if
5402  !
5403  ! -- set seep0 on the first lake iteration
5404  if (iter == 1) then
5405  this%seep0(n) = this%seep(n)
5406  end if
5407  !
5408  ! -- check for slow convergence
5409  if (this%seep(n) * this%seep0(n) < dprec) then
5410  this%iseepc(n) = this%iseepc(n) + 1
5411  else
5412  this%iseepc(n) = 0
5413  end if
5414  ! -- determine of convergence is slow and oscillating
5415  idhp = 0
5416  if (dh * this%dh0(n) < dprec) idhp = 1
5417  ! -- determine if stage change is increasing
5418  adh = abs(dh)
5419  if (adh > adh0) idhp = 1
5420  ! -- increment idhc convergence flag
5421  if (idhp == 1) then
5422  this%idhc(n) = this%idhc(n) + 1
5423  end if
5424  !
5425  ! -- switch to bisection when the Newton-Raphson method oscillates
5426  ! or when convergence is slow
5427  if (ibflg == 1) then
5428  if (this%iseepc(n) > 7 .or. this%idhc(n) > 12) then
5429  call this%lak_bisection(n, ibflg, hlak, ts, dh, residb)
5430  end if
5431  end if
5432  else
5433  dh = dzero
5434  end if
5435  !
5436  ! -- update lake stage
5437  hlak = hlak - dh
5438  if (hlak < this%lakebot(n)) then
5439  hlak = this%lakebot(n)
5440  end if
5441  !
5442  ! -- calculate surface area
5443  call this%lak_calculate_sarea(n, hlak, area)
5444  !
5445  ! -- set the Q to length factor
5446  if (area > dzero) then
5447  qtolfact = delt / area
5448  else
5449  qtolfact = dzero
5450  end if
5451  !
5452  ! -- recalculate the residual
5453  call this%lak_calculate_residual(n, hlak, resid)
5454  !
5455  ! -- evaluate convergence
5456  !if (ABS(dh) < delh) then
5457  if (abs(dh) < delh .and. abs(resid) * qtolfact < this%dmaxchg) then
5458  this%ncncvr(n) = 1
5459  end if
5460  this%xnewpak(n) = hlak
5461  !
5462  ! -- save iterates for lake
5463  this%seep0(n) = this%seep(n)
5464  this%dh0(n) = dh
5465  end if
5466  end do laklevel
5467  !
5468  if (iicnvg == 1) exit converge
5469  !
5470  end do converge
5471  !
5472  ! -- Mover terms: store outflow after diversion loss
5473  ! as qformvr and reduce outflow (qd)
5474  ! by how much was actually sent to the mover
5475  if (this%imover == 1) then
5476  do n = 1, this%noutlets
5477  call this%pakmvrobj%accumulate_qformvr(n, -this%simoutrate(n))
5478  end do
5479  end if
5480  !
5481  ! -- Return
5482  return
5483  end subroutine lak_solve
5484 
5485  !> @ brief Lake package bisection method
5486  !!
5487  !! Use bisection method to find lake stage that reduces the residual
5488  !<
5489  subroutine lak_bisection(this, n, ibflg, hlak, temporary_stage, dh, residual)
5490  ! -- dummy
5491  class(laktype), intent(inout) :: this
5492  integer(I4B), intent(in) :: n !< lake number
5493  integer(I4B), intent(inout) :: ibflg !< bisection flag
5494  real(DP), intent(in) :: hlak !< lake stage
5495  real(DP), intent(inout) :: temporary_stage !< temporary lake stage
5496  real(DP), intent(inout) :: dh !< lake stage change
5497  real(DP), intent(inout) :: residual !< lake residual
5498  ! -- local
5499  integer(I4B) :: i
5500  real(DP) :: temporary_stage0
5501  real(DP) :: residuala
5502  real(DP) :: endpoint1
5503  real(DP) :: endpoint2
5504  ! -- code
5505  ibflg = 1
5506  temporary_stage0 = hlak
5507  endpoint1 = this%en1(n)
5508  endpoint2 = this%en2(n)
5509  call this%lak_calculate_residual(n, temporary_stage, residuala)
5510  if (hlak > endpoint1 .and. hlak < endpoint2) then
5511  endpoint2 = hlak
5512  end if
5513  do i = 1, this%maxlakit
5514  temporary_stage = dhalf * (endpoint1 + endpoint2)
5515  call this%lak_calculate_residual(n, temporary_stage, residual)
5516  if (abs(residual) == dzero .or. &
5517  abs(temporary_stage0 - temporary_stage) < this%dmaxchg) then
5518  exit
5519  end if
5520  call this%lak_calculate_residual(n, endpoint1, residuala)
5521  ! -- change end points
5522  ! -- root is between temporary_stage and endpoint2
5523  if (sign(done, residuala) == sign(done, residual)) then
5524  endpoint1 = temporary_stage
5525  ! -- root is between endpoint1 and temporary_stage
5526  else
5527  endpoint2 = temporary_stage
5528  end if
5529  temporary_stage0 = temporary_stage
5530  end do
5531  dh = hlak - temporary_stage
5532  !
5533  ! -- Return
5534  return
5535  end subroutine lak_bisection
5536 
5537  !> @brief Calculate the available volumetric rate for a lake given a passed
5538  !! stage
5539  !<
5540  subroutine lak_calculate_available(this, n, hlak, avail, &
5541  ra, ro, qinf, ex, headp)
5542  ! -- modules
5543  use tdismodule, only: delt
5544  ! -- dummy
5545  class(laktype), intent(inout) :: this
5546  integer(I4B), intent(in) :: n
5547  real(DP), intent(in) :: hlak
5548  real(DP), intent(inout) :: avail
5549  real(DP), intent(inout) :: ra
5550  real(DP), intent(inout) :: ro
5551  real(DP), intent(inout) :: qinf
5552  real(DP), intent(inout) :: ex
5553  real(DP), intent(in), optional :: headp
5554  ! -- local
5555  integer(I4B) :: j
5556  integer(I4B) :: idry
5557  integer(I4B) :: igwfnode
5558  real(DP) :: hp
5559  real(DP) :: head
5560  real(DP) :: qlakgw
5561  real(DP) :: v0
5562  !
5563  ! -- set hp
5564  if (present(headp)) then
5565  hp = headp
5566  else
5567  hp = dzero
5568  end if
5569  !
5570  ! -- initialize
5571  avail = dzero
5572  !
5573  ! -- calculate the aquifer sources to the lake
5574  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5575  igwfnode = this%cellid(j)
5576  if (this%ibound(igwfnode) == 0) cycle
5577  head = this%xnew(igwfnode) + hp
5578  call this%lak_estimate_conn_exchange(1, n, j, idry, hlak, head, qlakgw, &
5579  avail)
5580  end do
5581  !
5582  ! -- add rainfall
5583  call this%lak_calculate_rainfall(n, hlak, ra)
5584  avail = avail + ra
5585  !
5586  ! -- calculate runoff
5587  call this%lak_calculate_runoff(n, ro)
5588  avail = avail + ro
5589  !
5590  ! -- calculate inflow
5591  call this%lak_calculate_inflow(n, qinf)
5592  avail = avail + qinf
5593  !
5594  ! -- calculate external flow terms
5595  call this%lak_calculate_external(n, ex)
5596  avail = avail + ex
5597  !
5598  ! -- calculate volume available in storage
5599  call this%lak_calculate_vol(n, this%xoldpak(n), v0)
5600  avail = avail + v0 / delt
5601  !
5602  ! -- Return
5603  return
5604  end subroutine lak_calculate_available
5605 
5606  !> @brief Calculate the residual for a lake given a passed stage
5607  !<
5608  subroutine lak_calculate_residual(this, n, hlak, resid, headp)
5609  ! -- modules
5610  use tdismodule, only: delt
5611  ! -- dummy
5612  class(laktype), intent(inout) :: this
5613  integer(I4B), intent(in) :: n
5614  real(DP), intent(in) :: hlak
5615  real(DP), intent(inout) :: resid
5616  real(DP), intent(in), optional :: headp
5617  ! -- local
5618  integer(I4B) :: j
5619  integer(I4B) :: idry
5620  integer(I4B) :: igwfnode
5621  real(DP) :: hp
5622  real(DP) :: avail
5623  real(DP) :: head
5624  real(DP) :: ra
5625  real(DP) :: ro
5626  real(DP) :: qinf
5627  real(DP) :: ex
5628  real(DP) :: ev
5629  real(DP) :: wr
5630  real(DP) :: sout
5631  real(DP) :: sin
5632  real(DP) :: qlakgw
5633  real(DP) :: seep
5634  real(DP) :: hlak0
5635  real(DP) :: v0
5636  real(DP) :: v1
5637  !
5638  ! -- set hp
5639  if (present(headp)) then
5640  hp = headp
5641  else
5642  hp = dzero
5643  end if
5644  !
5645  ! -- initialize
5646  resid = dzero
5647  avail = dzero
5648  seep = dzero
5649  !
5650  ! -- calculate the available water
5651  call this%lak_calculate_available(n, hlak, avail, &
5652  ra, ro, qinf, ex, hp)
5653  !
5654  ! -- calculate groundwater seepage
5655  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5656  igwfnode = this%cellid(j)
5657  if (this%ibound(igwfnode) == 0) cycle
5658  head = this%xnew(igwfnode) + hp
5659  call this%lak_estimate_conn_exchange(2, n, j, idry, hlak, head, qlakgw, &
5660  avail)
5661  seep = seep + qlakgw
5662  end do
5663  !
5664  ! -- limit withdrawals to lake inflows and lake storage
5665  call this%lak_calculate_withdrawal(n, avail, wr)
5666  !
5667  ! -- limit evaporation to lake inflows and lake storage
5668  call this%lak_calculate_evaporation(n, hlak, avail, ev)
5669  !
5670  ! -- no outlet flow if evaporation consumes all water
5671  call this%lak_calculate_outlet_outflow(n, hlak, avail, sout)
5672  !
5673  ! -- update the surface inflow values
5674  call this%lak_calculate_outlet_inflow(n, sin)
5675  !
5676  ! -- calculate residual
5677  resid = ra + ev + wr + ro + qinf + ex + sin + sout + seep
5678  !
5679  ! -- include storage
5680  if (this%gwfiss /= 1) then
5681  hlak0 = this%xoldpak(n)
5682  call this%lak_calculate_vol(n, hlak0, v0)
5683  call this%lak_calculate_vol(n, hlak, v1)
5684  resid = resid + (v0 - v1) / delt
5685  end if
5686  !
5687  ! -- Return
5688  return
5689  end subroutine lak_calculate_residual
5690 
5691  !> @brief Set up the budget object that stores all the lake flows
5692  !<
5693  subroutine lak_setup_budobj(this)
5694  ! -- modules
5695  use constantsmodule, only: lenbudtxt
5696  ! -- dummy
5697  class(laktype) :: this
5698  ! -- local
5699  integer(I4B) :: nbudterm
5700  integer(I4B) :: nlen
5701  integer(I4B) :: j, n, n1, n2
5702  integer(I4B) :: maxlist, naux
5703  integer(I4B) :: idx
5704  real(DP) :: q
5705  character(len=LENBUDTXT) :: text
5706  character(len=LENBUDTXT), dimension(1) :: auxtxt
5707  !
5708  ! -- Determine the number of lake budget terms. These are fixed for
5709  ! the simulation and cannot change
5710  nbudterm = 9
5711  nlen = 0
5712  do n = 1, this%noutlets
5713  if (this%lakein(n) > 0 .and. this%lakeout(n) > 0) then
5714  nlen = nlen + 1
5715  end if
5716  end do
5717  if (nlen > 0) nbudterm = nbudterm + 1
5718  if (this%imover == 1) nbudterm = nbudterm + 2
5719  if (this%naux > 0) nbudterm = nbudterm + 1
5720  !
5721  ! -- set up budobj
5722  call budgetobject_cr(this%budobj, this%packName)
5723  call this%budobj%budgetobject_df(this%nlakes, nbudterm, 0, 0, &
5724  ibudcsv=this%ibudcsv)
5725  idx = 0
5726  !
5727  ! -- Go through and set up each budget term. nlen is the number
5728  ! of outlets that discharge into another lake
5729  if (nlen > 0) then
5730  text = ' FLOW-JA-FACE'
5731  idx = idx + 1
5732  maxlist = 2 * nlen
5733  naux = 0
5734  call this%budobj%budterm(idx)%initialize(text, &
5735  this%name_model, &
5736  this%packName, &
5737  this%name_model, &
5738  this%packName, &
5739  maxlist, .false., .false., &
5740  naux, ordered_id1=.false.)
5741  !
5742  ! -- store connectivity
5743  call this%budobj%budterm(idx)%reset(2 * nlen)
5744  q = dzero
5745  do n = 1, this%noutlets
5746  n1 = this%lakein(n)
5747  n2 = this%lakeout(n)
5748  if (n1 > 0 .and. n2 > 0) then
5749  call this%budobj%budterm(idx)%update_term(n1, n2, q)
5750  call this%budobj%budterm(idx)%update_term(n2, n1, -q)
5751  end if
5752  end do
5753  end if
5754  !
5755  ! --
5756  text = ' GWF'
5757  idx = idx + 1
5758  maxlist = this%maxbound
5759  naux = 1
5760  auxtxt(1) = ' FLOW-AREA'
5761  call this%budobj%budterm(idx)%initialize(text, &
5762  this%name_model, &
5763  this%packName, &
5764  this%name_model, &
5765  this%name_model, &
5766  maxlist, .false., .true., &
5767  naux, auxtxt)
5768  call this%budobj%budterm(idx)%reset(this%maxbound)
5769  q = dzero
5770  do n = 1, this%nlakes
5771  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5772  n2 = this%cellid(j)
5773  call this%budobj%budterm(idx)%update_term(n, n2, q)
5774  end do
5775  end do
5776  !
5777  ! --
5778  text = ' RAINFALL'
5779  idx = idx + 1
5780  maxlist = this%nlakes
5781  naux = 0
5782  call this%budobj%budterm(idx)%initialize(text, &
5783  this%name_model, &
5784  this%packName, &
5785  this%name_model, &
5786  this%packName, &
5787  maxlist, .false., .false., &
5788  naux)
5789  !
5790  ! --
5791  text = ' EVAPORATION'
5792  idx = idx + 1
5793  maxlist = this%nlakes
5794  naux = 0
5795  call this%budobj%budterm(idx)%initialize(text, &
5796  this%name_model, &
5797  this%packName, &
5798  this%name_model, &
5799  this%packName, &
5800  maxlist, .false., .false., &
5801  naux)
5802  !
5803  ! --
5804  text = ' RUNOFF'
5805  idx = idx + 1
5806  maxlist = this%nlakes
5807  naux = 0
5808  call this%budobj%budterm(idx)%initialize(text, &
5809  this%name_model, &
5810  this%packName, &
5811  this%name_model, &
5812  this%packName, &
5813  maxlist, .false., .false., &
5814  naux)
5815  !
5816  ! --
5817  text = ' EXT-INFLOW'
5818  idx = idx + 1
5819  maxlist = this%nlakes
5820  naux = 0
5821  call this%budobj%budterm(idx)%initialize(text, &
5822  this%name_model, &
5823  this%packName, &
5824  this%name_model, &
5825  this%packName, &
5826  maxlist, .false., .false., &
5827  naux)
5828  !
5829  ! --
5830  text = ' WITHDRAWAL'
5831  idx = idx + 1
5832  maxlist = this%nlakes
5833  naux = 0
5834  call this%budobj%budterm(idx)%initialize(text, &
5835  this%name_model, &
5836  this%packName, &
5837  this%name_model, &
5838  this%packName, &
5839  maxlist, .false., .false., &
5840  naux)
5841  !
5842  ! --
5843  text = ' EXT-OUTFLOW'
5844  idx = idx + 1
5845  maxlist = this%nlakes
5846  naux = 0
5847  call this%budobj%budterm(idx)%initialize(text, &
5848  this%name_model, &
5849  this%packName, &
5850  this%name_model, &
5851  this%packName, &
5852  maxlist, .false., .false., &
5853  naux)
5854  !
5855  ! --
5856  text = ' STORAGE'
5857  idx = idx + 1
5858  maxlist = this%nlakes
5859  naux = 1
5860  auxtxt(1) = ' VOLUME'
5861  call this%budobj%budterm(idx)%initialize(text, &
5862  this%name_model, &
5863  this%packName, &
5864  this%name_model, &
5865  this%packName, &
5866  maxlist, .false., .false., &
5867  naux, auxtxt)
5868  !
5869  ! --
5870  text = ' CONSTANT'
5871  idx = idx + 1
5872  maxlist = this%nlakes
5873  naux = 0
5874  call this%budobj%budterm(idx)%initialize(text, &
5875  this%name_model, &
5876  this%packName, &
5877  this%name_model, &
5878  this%packName, &
5879  maxlist, .false., .false., &
5880  naux)
5881  !
5882  ! --
5883  if (this%imover == 1) then
5884  !
5885  ! --
5886  text = ' FROM-MVR'
5887  idx = idx + 1
5888  maxlist = this%nlakes
5889  naux = 0
5890  call this%budobj%budterm(idx)%initialize(text, &
5891  this%name_model, &
5892  this%packName, &
5893  this%name_model, &
5894  this%packName, &
5895  maxlist, .false., .false., &
5896  naux)
5897  !
5898  ! --
5899  text = ' TO-MVR'
5900  idx = idx + 1
5901  maxlist = this%noutlets
5902  naux = 0
5903  call this%budobj%budterm(idx)%initialize(text, &
5904  this%name_model, &
5905  this%packName, &
5906  this%name_model, &
5907  this%packName, &
5908  maxlist, .false., .false., &
5909  naux, ordered_id1=.false.)
5910  !
5911  ! -- store to-mvr connection information
5912  call this%budobj%budterm(idx)%reset(this%noutlets)
5913  q = dzero
5914  do n = 1, this%noutlets
5915  n1 = this%lakein(n)
5916  call this%budobj%budterm(idx)%update_term(n1, n1, q)
5917  end do
5918  end if
5919  !
5920  ! --
5921  naux = this%naux
5922  if (naux > 0) then
5923  !
5924  ! --
5925  text = ' AUXILIARY'
5926  idx = idx + 1
5927  maxlist = this%nlakes
5928  call this%budobj%budterm(idx)%initialize(text, &
5929  this%name_model, &
5930  this%packName, &
5931  this%name_model, &
5932  this%packName, &
5933  maxlist, .false., .false., &
5934  naux, this%auxname)
5935  end if
5936  !
5937  ! -- if lake flow for each reach are written to the listing file
5938  if (this%iprflow /= 0) then
5939  call this%budobj%flowtable_df(this%iout)
5940  end if
5941  !
5942  ! -- Return
5943  return
5944  end subroutine lak_setup_budobj
5945 
5946  !> @brief Copy flow terms into this%budobj
5947  !<
5948  subroutine lak_fill_budobj(this)
5949  ! -- dummy
5950  class(laktype) :: this
5951  ! -- local
5952  integer(I4B) :: naux
5953  real(DP), dimension(:), allocatable :: auxvartmp
5954  !integer(I4B) :: i
5955  integer(I4B) :: j
5956  integer(I4B) :: n
5957  integer(I4B) :: n1
5958  integer(I4B) :: n2
5959  integer(I4B) :: ii
5960  integer(I4B) :: jj
5961  integer(I4B) :: idx
5962  integer(I4B) :: nlen
5963  real(DP) :: v, v1
5964  real(DP) :: q
5965  real(DP) :: lkstg, gwhead, wa
5966  !
5967  ! -- initialize counter
5968  idx = 0
5969 
5970  ! -- FLOW JA FACE
5971  nlen = 0
5972  do n = 1, this%noutlets
5973  if (this%lakein(n) > 0 .and. this%lakeout(n) > 0) then
5974  nlen = nlen + 1
5975  end if
5976  end do
5977  if (nlen > 0) then
5978  idx = idx + 1
5979  call this%budobj%budterm(idx)%reset(2 * nlen)
5980  do n = 1, this%noutlets
5981  n1 = this%lakein(n)
5982  n2 = this%lakeout(n)
5983  if (n1 > 0 .and. n2 > 0) then
5984  q = this%simoutrate(n)
5985  if (this%imover == 1) then
5986  q = q + this%pakmvrobj%get_qtomvr(n)
5987  end if
5988  call this%budobj%budterm(idx)%update_term(n1, n2, q)
5989  call this%budobj%budterm(idx)%update_term(n2, n1, -q)
5990  end if
5991  end do
5992  end if
5993  !
5994  ! -- GWF (LEAKAGE)
5995  idx = idx + 1
5996  call this%budobj%budterm(idx)%reset(this%maxbound)
5997  do n = 1, this%nlakes
5998  do j = this%idxlakeconn(n), this%idxlakeconn(n + 1) - 1
5999  n2 = this%cellid(j)
6000  q = this%qleak(j)
6001  lkstg = this%xnewpak(n)
6002  ! -- For the case when the lak stage is exactly equal
6003  ! to the lake bottom, the wetted area is not returned
6004  ! equal to 0.0
6005  gwhead = this%xnew(n2)
6006  call this%lak_calculate_conn_warea(n, j, lkstg, gwhead, wa)
6007  ! -- For thermal conduction between a lake and a gw cell,
6008  ! the shared wetted area should be reset to zero when the lake
6009  ! stage is below the cell bottom
6010  if (this%belev(j) > lkstg) wa = dzero
6011  this%qauxcbc(1) = wa
6012  call this%budobj%budterm(idx)%update_term(n, n2, q, this%qauxcbc)
6013  end do
6014  end do
6015  !
6016  ! -- RAIN
6017  idx = idx + 1
6018  call this%budobj%budterm(idx)%reset(this%nlakes)
6019  do n = 1, this%nlakes
6020  q = this%precip(n)
6021  call this%budobj%budterm(idx)%update_term(n, n, q)
6022  end do
6023  !
6024  ! -- EVAPORATION
6025  idx = idx + 1
6026  call this%budobj%budterm(idx)%reset(this%nlakes)
6027  do n = 1, this%nlakes
6028  q = this%evap(n)
6029  call this%budobj%budterm(idx)%update_term(n, n, q)
6030  end do
6031  !
6032  ! -- RUNOFF
6033  idx = idx + 1
6034  call this%budobj%budterm(idx)%reset(this%nlakes)
6035  do n = 1, this%nlakes
6036  q = this%runoff(n)
6037  call this%budobj%budterm(idx)%update_term(n, n, q)
6038  end do
6039  !
6040  ! -- INFLOW
6041  idx = idx + 1
6042  call this%budobj%budterm(idx)%reset(this%nlakes)
6043  do n = 1, this%nlakes
6044  q = this%inflow(n)
6045  call this%budobj%budterm(idx)%update_term(n, n, q)
6046  end do
6047  !
6048  ! -- WITHDRAWAL
6049  idx = idx + 1
6050  call this%budobj%budterm(idx)%reset(this%nlakes)
6051  do n = 1, this%nlakes
6052  q = this%withr(n)
6053  call this%budobj%budterm(idx)%update_term(n, n, q)
6054  end do
6055  !
6056  ! -- EXTERNAL OUTFLOW
6057  idx = idx + 1
6058  call this%budobj%budterm(idx)%reset(this%nlakes)
6059  do n = 1, this%nlakes
6060  call this%lak_get_external_outlet(n, q)
6061  ! subtract tomover from external outflow
6062  call this%lak_get_external_mover(n, v)
6063  q = q + v
6064  call this%budobj%budterm(idx)%update_term(n, n, q)
6065  end do
6066  !
6067  ! -- STORAGE
6068  idx = idx + 1
6069  call this%budobj%budterm(idx)%reset(this%nlakes)
6070  do n = 1, this%nlakes
6071  call this%lak_calculate_vol(n, this%xnewpak(n), v1)
6072  q = this%qsto(n)
6073  this%qauxcbc(1) = v1
6074  call this%budobj%budterm(idx)%update_term(n, n, q, this%qauxcbc)
6075  end do
6076  !
6077  ! -- CONSTANT FLOW
6078  idx = idx + 1
6079  call this%budobj%budterm(idx)%reset(this%nlakes)
6080  do n = 1, this%nlakes
6081  q = this%chterm(n)
6082  call this%budobj%budterm(idx)%update_term(n, n, q)
6083  end do
6084  !
6085  ! -- MOVER
6086  if (this%imover == 1) then
6087  !
6088  ! -- FROM MOVER
6089  idx = idx + 1
6090  call this%budobj%budterm(idx)%reset(this%nlakes)
6091  do n = 1, this%nlakes
6092  q = this%pakmvrobj%get_qfrommvr(n)
6093  call this%budobj%budterm(idx)%update_term(n, n, q)
6094  end do
6095  !
6096  ! -- TO MOVER
6097  idx = idx + 1
6098  call this%budobj%budterm(idx)%reset(this%noutlets)
6099  do n = 1, this%noutlets
6100  n1 = this%lakein(n)
6101  q = this%pakmvrobj%get_qtomvr(n)
6102  if (q > dzero) then
6103  q = -q
6104  end if
6105  call this%budobj%budterm(idx)%update_term(n1, n1, q)
6106  end do
6107  !
6108  end if
6109  !
6110  ! -- AUXILIARY VARIABLES
6111  naux = this%naux
6112  if (naux > 0) then
6113  idx = idx + 1
6114  allocate (auxvartmp(naux))
6115  call this%budobj%budterm(idx)%reset(this%nlakes)
6116  do n = 1, this%nlakes
6117  q = dzero
6118  do jj = 1, naux
6119  ii = n
6120  auxvartmp(jj) = this%lauxvar(jj, ii)
6121  end do
6122  call this%budobj%budterm(idx)%update_term(n, n, q, auxvartmp)
6123  end do
6124  deallocate (auxvartmp)
6125  end if
6126  !
6127  ! --Terms are filled, now accumulate them for this time step
6128  call this%budobj%accumulate_terms()
6129  !
6130  ! -- Return
6131  return
6132  end subroutine lak_fill_budobj
6133 
6134  !> @brief Set up the table object that is used to write the lak stage data
6135  !!
6136  !! The terms listed here must correspond in number and order to the ones
6137  !! written to the stage table in the lak_ot method
6138  !<
6139  subroutine lak_setup_tableobj(this)
6140  ! -- modules
6142  ! -- dummy
6143  class(laktype) :: this
6144  ! -- local
6145  integer(I4B) :: nterms
6146  character(len=LINELENGTH) :: title
6147  character(len=LINELENGTH) :: text
6148  !
6149  ! -- setup stage table
6150  if (this%iprhed > 0) then
6151  !
6152  ! -- Determine the number of lake stage terms. These are fixed for
6153  ! the simulation and cannot change. This includes FLOW-JA-FACE
6154  ! so they can be written to the binary budget files, but these internal
6155  ! flows are not included as part of the budget table.
6156  nterms = 5
6157  if (this%inamedbound == 1) then
6158  nterms = nterms + 1
6159  end if
6160  !
6161  ! -- set up table title
6162  title = trim(adjustl(this%text))//' PACKAGE ('// &
6163  trim(adjustl(this%packName))//') STAGES FOR EACH CONTROL VOLUME'
6164  !
6165  ! -- set up stage tableobj
6166  call table_cr(this%stagetab, this%packName, title)
6167  call this%stagetab%table_df(this%nlakes, nterms, this%iout, &
6168  transient=.true.)
6169  !
6170  ! -- Go through and set up table budget term
6171  if (this%inamedbound == 1) then
6172  text = 'NAME'
6173  call this%stagetab%initialize_column(text, 20, alignment=tableft)
6174  end if
6175  !
6176  ! -- lake number
6177  text = 'NUMBER'
6178  call this%stagetab%initialize_column(text, 10, alignment=tabcenter)
6179  !
6180  ! -- lake stage
6181  text = 'STAGE'
6182  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
6183  !
6184  ! -- lake surface area
6185  text = 'SURFACE AREA'
6186  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
6187  !
6188  ! -- lake wetted area
6189  text = 'WETTED AREA'
6190  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
6191  !
6192  ! -- lake volume
6193  text = 'VOLUME'
6194  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
6195  end if
6196  !
6197  ! -- Return
6198  return
6199  end subroutine lak_setup_tableobj
6200 
6201  !> @brief Activate addition of density terms
6202  !<
6203  subroutine lak_activate_density(this)
6204  ! -- dummy
6205  class(laktype), intent(inout) :: this
6206  ! -- local
6207  integer(I4B) :: i, j
6208  !
6209  ! -- Set idense and reallocate denseterms to be of size MAXBOUND
6210  this%idense = 1
6211  call mem_reallocate(this%denseterms, 3, this%MAXBOUND, 'DENSETERMS', &
6212  this%memoryPath)
6213  do i = 1, this%maxbound
6214  do j = 1, 3
6215  this%denseterms(j, i) = dzero
6216  end do
6217  end do
6218  write (this%iout, '(/1x,a)') 'DENSITY TERMS HAVE BEEN ACTIVATED FOR LAKE &
6219  &PACKAGE: '//trim(adjustl(this%packName))
6220  !
6221  ! -- Return
6222  return
6223  end subroutine lak_activate_density
6224 
6225  !> @brief Activate viscosity terms
6226  !!
6227  !! Method to activate addition of viscosity terms for a LAK package reach.
6228  !<
6229  subroutine lak_activate_viscosity(this)
6230  ! -- modules
6232  ! -- dummy variables
6233  class(laktype), intent(inout) :: this !< LakType object
6234  ! -- local variables
6235  integer(I4B) :: i
6236  integer(I4B) :: j
6237  !
6238  ! -- Set ivsc and reallocate viscratios to be of size MAXBOUND
6239  this%ivsc = 1
6240  call mem_reallocate(this%viscratios, 2, this%MAXBOUND, 'VISCRATIOS', &
6241  this%memoryPath)
6242  do i = 1, this%maxbound
6243  do j = 1, 2
6244  this%viscratios(j, i) = done
6245  end do
6246  end do
6247  write (this%iout, '(/1x,a)') 'VISCOSITY HAS BEEN ACTIVATED FOR LAK &
6248  &PACKAGE: '//trim(adjustl(this%packName))
6249  !
6250  ! -- Return
6251  return
6252  end subroutine lak_activate_viscosity
6253 
6254  !> @brief Calculate the groundwater-lake density exchange terms
6255  !!
6256  !! Arguments are as follows:
6257  !! iconn : lak-gwf connection number
6258  !! stage : lake stage
6259  !! head : gwf head
6260  !! cond : conductance
6261  !! botl : bottom elevation of this connection
6262  !! flow : calculated flow, updated here with density terms
6263  !! gwfhcof : gwf head coefficient, updated here with density terms
6264  !! gwfrhs : gwf right-hand-side value, updated here with density terms
6265  !!
6266  !! Member variable used here
6267  !! denseterms : shape (3, MAXBOUND), filled by buoyancy package
6268  !! col 1 is relative density of lake (denselak / denseref)
6269  !! col 2 is relative density of gwf cell (densegwf / denseref)
6270  !! col 3 is elevation of gwf cell
6271  !<
6272  subroutine lak_calculate_density_exchange(this, iconn, stage, head, cond, &
6273  botl, flow, gwfhcof, gwfrhs)
6274  ! -- dummy
6275  class(laktype), intent(inout) :: this
6276  integer(I4B), intent(in) :: iconn
6277  real(DP), intent(in) :: stage
6278  real(DP), intent(in) :: head
6279  real(DP), intent(in) :: cond
6280  real(DP), intent(in) :: botl
6281  real(DP), intent(inout) :: flow
6282  real(DP), intent(inout) :: gwfhcof
6283  real(DP), intent(inout) :: gwfrhs
6284  ! -- local
6285  real(DP) :: ss
6286  real(DP) :: hh
6287  real(DP) :: havg
6288  real(DP) :: rdenselak
6289  real(DP) :: rdensegwf
6290  real(DP) :: rdenseavg
6291  real(DP) :: elevlak
6292  real(DP) :: elevgwf
6293  real(DP) :: elevavg
6294  real(DP) :: d1
6295  real(DP) :: d2
6296  logical(LGP) :: stage_below_bot
6297  logical(LGP) :: head_below_bot
6298  !
6299  ! -- Set lak density to lak density or gwf density
6300  if (stage >= botl) then
6301  ss = stage
6302  stage_below_bot = .false.
6303  rdenselak = this%denseterms(1, iconn) ! lak rel density
6304  else
6305  ss = botl
6306  stage_below_bot = .true.
6307  rdenselak = this%denseterms(2, iconn) ! gwf rel density
6308  end if
6309  !
6310  ! -- set hh to head or botl
6311  if (head >= botl) then
6312  hh = head
6313  head_below_bot = .false.
6314  rdensegwf = this%denseterms(2, iconn) ! gwf rel density
6315  else
6316  hh = botl
6317  head_below_bot = .true.
6318  rdensegwf = this%denseterms(1, iconn) ! lak rel density
6319  end if
6320  !
6321  ! -- todo: hack because denseterms not updated in a cf calculation
6322  if (rdensegwf == dzero) return
6323  !
6324  ! -- Update flow
6325  if (stage_below_bot .and. head_below_bot) then
6326  !
6327  ! -- flow is zero, so no terms are updated
6328  !
6329  else
6330  !
6331  ! -- calculate average relative density
6332  rdenseavg = dhalf * (rdenselak + rdensegwf)
6333  !
6334  ! -- Add contribution of first density term:
6335  ! cond * (denseavg/denseref - 1) * (hgwf - hlak)
6336  d1 = cond * (rdenseavg - done)
6337  gwfhcof = gwfhcof - d1
6338  gwfrhs = gwfrhs - d1 * ss
6339  d1 = d1 * (hh - ss)
6340  flow = flow + d1
6341  !
6342  ! -- Add second density term if stage and head not below bottom
6343  if (.not. stage_below_bot .and. .not. head_below_bot) then
6344  !
6345  ! -- Add contribution of second density term:
6346  ! cond * (havg - elevavg) * (densegwf - denselak) / denseref
6347  elevgwf = this%denseterms(3, iconn)
6348  if (this%ictype(iconn) == 0 .or. this%ictype(iconn) == 3) then
6349  ! -- vertical or embedded vertical connection
6350  elevlak = botl
6351  else
6352  ! -- horizontal or embedded horizontal connection
6353  elevlak = elevgwf
6354  end if
6355  elevavg = dhalf * (elevlak + elevgwf)
6356  havg = dhalf * (hh + ss)
6357  d2 = cond * (havg - elevavg) * (rdensegwf - rdenselak)
6358  gwfrhs = gwfrhs + d2
6359  flow = flow + d2
6360  end if
6361  end if
6362  !
6363  ! -- Return
6364  return
6365  end subroutine lak_calculate_density_exchange
6366 
6367 end module lakmodule
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains the base boundary package.
subroutine, public budgetobject_cr(this, name)
Create a new budget object.
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 dhdry
real dry cell constant
Definition: Constants.f90:93
@ tabcenter
centered table column
Definition: Constants.f90:171
@ tabright
right justified table column
Definition: Constants.f90:172
@ tableft
left justified table column
Definition: Constants.f90:170
@ mnormal
normal output mode
Definition: Constants.f90:205
real(dp), parameter dtwothirds
real constant 2/3
Definition: Constants.f90:69
@ tabucstring
upper case string table data
Definition: Constants.f90:179
@ tabstring
string table data
Definition: Constants.f90:178
@ tabreal
real table data
Definition: Constants.f90:181
@ tabinteger
integer table data
Definition: Constants.f90:180
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:22
integer(i4b), parameter iwetlake
integer constant for a dry lake
Definition: Constants.f90:51
real(dp), parameter deight
real constant 8
Definition: Constants.f90:82
real(dp), parameter dfivethirds
real constant 5/3
Definition: Constants.f90:77
real(dp), parameter dp999
real constant 999/1000
Definition: Constants.f90:73
integer(i4b), parameter namedboundflag
named bound flag
Definition: Constants.f90:48
real(dp), parameter donethird
real constant 1/3
Definition: Constants.f90:66
real(dp), parameter dnodata
real no data constant
Definition: Constants.f90:94
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:92
real(dp), parameter dhundred
real constant 100
Definition: Constants.f90:85
integer(i4b), parameter lenpakloc
maximum length of a package location
Definition: Constants.f90:49
integer(i4b), parameter lentimeseriesname
maximum length of a time series name
Definition: Constants.f90:41
real(dp), parameter dep20
real constant 1e20
Definition: Constants.f90:90
real(dp), parameter dem1
real constant 1e-1
Definition: Constants.f90:102
integer(i4b), parameter maxadpit
maximum advanced package Newton-Raphson iterations
Definition: Constants.f90:52
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:67
integer(i4b), parameter lenftype
maximum length of a package type (DIS, WEL, OC, etc.)
Definition: Constants.f90:38
real(dp), parameter dgravity
real constant gravitational acceleration (m/(s s))
Definition: Constants.f90:131
real(dp), parameter dpi
real constant
Definition: Constants.f90:127
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:35
real(dp), parameter dem4
real constant 1e-4
Definition: Constants.f90:106
real(dp), parameter dem30
real constant 1e-30
Definition: Constants.f90:117
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:108
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:64
real(dp), parameter dcd
real constant weir coefficient in SI units
Definition: Constants.f90:132
real(dp), parameter dem5
real constant 1e-5
Definition: Constants.f90:107
real(dp), parameter dten
real constant 10
Definition: Constants.f90:83
real(dp), parameter dprec
real constant machine precision
Definition: Constants.f90:119
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:46
real(dp), parameter dp7
real constant 7/10
Definition: Constants.f90:70
real(dp), parameter dem9
real constant 1e-9
Definition: Constants.f90:111
real(dp), parameter dem2
real constant 1e-2
Definition: Constants.f90:104
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 dthree
real constant 3
Definition: Constants.f90:79
real(dp), parameter done
real constant 1
Definition: Constants.f90:75
integer(i4b) function, public get_node(ilay, irow, icol, nlay, nrow, ncol)
Get node number, given layer, row, and column indices for a structured grid. If any argument is inval...
Definition: GeomUtil.f90:81
subroutine, public extract_idnum_or_bndname(line, icol, istart, istop, idnum, bndname)
Starting at position icol, define string as line(istart:istop).
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public ulasav(buf, text, kstp, kper, pertim, totim, ncol, nrow, ilay, ichn)
Save 1 layer array on disk.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
subroutine, public urword(line, icol, istart, istop, ncode, n, r, iout, in)
Extract a word from a string.
This module defines variable data types.
Definition: kind.f90:8
subroutine lak_activate_density(this)
Activate addition of density terms.
Definition: gwf-lak.f90:6204
subroutine lak_cq(this, x, flowja, iadv)
Calculate flows.
Definition: gwf-lak.f90:4088
subroutine lak_read_outlets(this)
Read the lake outlets for this package.
Definition: gwf-lak.f90:1426
subroutine lak_vol2stage(this, ilak, vol, stage)
Determine the stage from a provided volume.
Definition: gwf-lak.f90:2847
subroutine lak_calculate_outlet_outflow(this, ilak, stage, avail, outoutf)
Calculate the outlet outflow from a lake.
Definition: gwf-lak.f90:2647
subroutine lak_read_lake_connections(this)
Read the lake connections for this package.
Definition: gwf-lak.f90:696
subroutine lak_calculate_sarea(this, ilak, stage, sarea)
Calculate the surface area of a lake at a given stage.
Definition: gwf-lak.f90:2019
subroutine lak_fn(this, rhs, ia, idxglo, matrix_sln)
Fill newton terms.
Definition: gwf-lak.f90:3727
subroutine lak_read_tables(this)
Read the lake tables for this package.
Definition: gwf-lak.f90:1012
subroutine lak_set_stressperiod(this, itemno)
Set a stress period attribute for lakweslls(itemno) using keywords.
Definition: gwf-lak.f90:2968
subroutine lak_ot_package_flows(this, icbcfl, ibudfl)
Output LAK package flow terms.
Definition: gwf-lak.f90:4193
subroutine lak_accumulate_chterm(this, ilak, rrate, chratin, chratout)
Accumulate constant head terms for budget.
Definition: gwf-lak.f90:5048
subroutine lak_process_obsid(obsrv, dis, inunitobs, iout)
This procedure is pointed to by ObsDataTypeProcesssIdPtr. It processes the ID string of an observatio...
Definition: gwf-lak.f90:4993
subroutine lak_get_external_mover(this, ilak, outoutf)
Get the mover outflow from a lake to an external boundary.
Definition: gwf-lak.f90:2776
subroutine lak_cf(this)
Formulate the HCOF and RHS terms.
Definition: gwf-lak.f90:3605
subroutine lak_calculate_density_exchange(this, iconn, stage, head, cond, botl, flow, gwfhcof, gwfrhs)
Calculate the groundwater-lake density exchange terms.
Definition: gwf-lak.f90:6274
subroutine lak_calculate_evaporation(this, ilak, stage, avail, ev)
Calculate the evaporation from a lake at a provided stage subject to an available volume.
Definition: gwf-lak.f90:2593
subroutine lak_read_lakes(this)
Read the dimensions for this package.
Definition: gwf-lak.f90:462
subroutine lak_setup_budobj(this)
Set up the budget object that stores all the lake flows.
Definition: gwf-lak.f90:5694
subroutine lak_calculate_external(this, ilak, ex)
Calculate the external flow terms to a lake.
Definition: gwf-lak.f90:2549
subroutine lak_calculate_warea(this, ilak, stage, warea, hin)
Calculate the wetted area of a lake at a given stage.
Definition: gwf-lak.f90:2064
subroutine lak_calculate_vol(this, ilak, stage, volume)
Calculate the volume of a lake at a given stage.
Definition: gwf-lak.f90:2149
subroutine lak_da(this)
Deallocate objects.
Definition: gwf-lak.f90:4330
subroutine lak_calculate_storagechange(this, ilak, stage, stage0, delt, dvr)
Calculate the storage change in a lake based on provided stages and a passed delt.
Definition: gwf-lak.f90:2469
subroutine lak_get_internal_outlet(this, ilak, outoutf)
Get the outlet from a lake to another lake.
Definition: gwf-lak.f90:2732
subroutine lak_calculate_conductance(this, ilak, stage, conductance)
Calculate the total conductance for a lake at a provided stage.
Definition: gwf-lak.f90:2205
subroutine laktables_to_vectors(this, laketables)
Copy the laketables structure data into flattened vectors that are stored in the memory manager.
Definition: gwf-lak.f90:1139
subroutine lak_calculate_residual(this, n, hlak, resid, headp)
Calculate the residual for a lake given a passed stage.
Definition: gwf-lak.f90:5609
subroutine lak_get_outlet_tomover(this, ilak, outoutf)
Get the outlet to mover from a lake.
Definition: gwf-lak.f90:2824
subroutine lak_allocate_arrays(this)
Allocate scalar members.
Definition: gwf-lak.f90:395
subroutine lak_calculate_available(this, n, hlak, avail, ra, ro, qinf, ex, headp)
Calculate the available volumetric rate for a lake given a passed stage.
Definition: gwf-lak.f90:5542
logical function lak_obs_supported(this)
Procedures related to observations (type-bound)
Definition: gwf-lak.f90:4559
subroutine lak_set_pointers(this, neq, ibound, xnew, xold, flowja)
Set pointers to model arrays and variables so that a package has access to these things.
Definition: gwf-lak.f90:4525
subroutine lak_calculate_inflow(this, ilak, qin)
Calculate specified inflow to a lake.
Definition: gwf-lak.f90:2534
character(len=lenpackagename) text
Definition: gwf-lak.f90:44
subroutine lak_ot_model_flows(this, icbcfl, ibudfl, icbcun, imap)
Write flows to binary file and/or print flows to budget.
Definition: gwf-lak.f90:4222
subroutine lak_rp_obs(this)
Process each observation.
Definition: gwf-lak.f90:4838
subroutine lak_calculate_conn_conductance(this, ilak, iconn, stage, head, cond)
Calculate the conductance for a lake connection at a provided stage and groundwater head.
Definition: gwf-lak.f90:2261
subroutine lak_calculate_exchange(this, ilak, stage, totflow)
Calculate the total groundwater-lake flow at a provided stage.
Definition: gwf-lak.f90:2330
subroutine lak_linear_interpolation(this, n, x, y, z, v)
Perform linear interpolation of two vectors.
Definition: gwf-lak.f90:1971
subroutine lak_setup_tableobj(this)
Set up the table object that is used to write the lak stage data.
Definition: gwf-lak.f90:6140
subroutine lak_ot_dv(this, idvsave, idvprint)
Save LAK-calculated values to binary file.
Definition: gwf-lak.f90:4238
subroutine lak_options(this, option, found)
Set options specific to LakType.
Definition: gwf-lak.f90:3211
subroutine lak_get_external_outlet(this, ilak, outoutf)
Get the outlet outflow from a lake to an external boundary.
Definition: gwf-lak.f90:2754
subroutine lak_calculate_rainfall(this, ilak, stage, ra)
Calculate the rainfall for a lake.
Definition: gwf-lak.f90:2494
subroutine lak_get_internal_inlet(this, ilak, outinf)
Get the outlet inflow to a lake from another lake.
Definition: gwf-lak.f90:2708
subroutine lak_cc(this, innertot, kiter, iend, icnvgmod, cpak, ipak, dpak)
Final convergence check for package.
Definition: gwf-lak.f90:3789
subroutine lak_rp(this)
Read and Prepare.
Definition: gwf-lak.f90:3396
subroutine lak_read_dimensions(this)
Read the dimensions for this package.
Definition: gwf-lak.f90:1611
subroutine lak_activate_viscosity(this)
Activate viscosity terms.
Definition: gwf-lak.f90:6230
subroutine lak_read_initial_attr(this)
Read the initial parameters for this package.
Definition: gwf-lak.f90:1698
integer(i4b) function lak_check_valid(this, itemno)
Determine if a valid lake or outlet number has been specified.
Definition: gwf-lak.f90:2931
subroutine lak_bisection(this, n, ibflg, hlak, temporary_stage, dh, residual)
@ brief Lake package bisection method
Definition: gwf-lak.f90:5490
subroutine lak_ad(this)
Add package connection to matrix.
Definition: gwf-lak.f90:3533
subroutine lak_solve(this, update)
Solve for lake stage.
Definition: gwf-lak.f90:5109
character(len=lenftype) ftype
Definition: gwf-lak.f90:43
subroutine lak_fc(this, rhs, ia, idxglo, matrix_sln)
Copy rhs and hcof into solution rhs and amat.
Definition: gwf-lak.f90:3689
subroutine lak_set_attribute_error(this, ilak, keyword, msg)
Issue a parameter error for lakweslls(ilak)
Definition: gwf-lak.f90:3187
subroutine lak_calculate_runoff(this, ilak, ro)
Calculate runoff to a lake.
Definition: gwf-lak.f90:2519
subroutine define_listlabel(this)
Define the list heading that is written to iout when PRINT_INPUT option is used.
Definition: gwf-lak.f90:4497
subroutine lak_read_table(this, ilak, filename, laketable)
Read the lake table for this package.
Definition: gwf-lak.f90:1190
subroutine lak_calculate_withdrawal(this, ilak, avail, wr)
Calculate the withdrawal from a lake subject to an available volume.
Definition: gwf-lak.f90:2568
subroutine lak_calculate_conn_warea(this, ilak, iconn, stage, head, wa)
Calculate the wetted area of a lake connection at a given stage.
Definition: gwf-lak.f90:2095
subroutine lak_df_obs(this)
Store observation type supported by LAK package. Overrides BndTypebnd_df_obs.
Definition: gwf-lak.f90:4572
subroutine lak_allocate_scalars(this)
Allocate scalar members.
Definition: gwf-lak.f90:332
subroutine lak_bound_update(this)
Store the lake head and connection conductance in the bound array.
Definition: gwf-lak.f90:5081
subroutine lak_calculate_cond_head(this, iconn, stage, head, vv)
Calculate the controlling lake stage or groundwater head used to calculate the conductance for a lake...
Definition: gwf-lak.f90:2229
subroutine lak_ot_bdsummary(this, kstp, kper, iout, ibudfl)
Write LAK budget to listing file.
Definition: gwf-lak.f90:4312
subroutine, public lak_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname)
Create a new LAK Package and point bndobj to the new package.
Definition: gwf-lak.f90:291
subroutine lak_bd_obs(this)
Calculate observations this time step and call ObsTypeSaveOneSimval for each LakType observation.
Definition: gwf-lak.f90:4680
subroutine lak_estimate_conn_exchange(this, iflag, ilak, iconn, idry, stage, head, flow, source, gwfhcof, gwfrhs)
Calculate the groundwater-lake flow at a provided stage and groundwater head.
Definition: gwf-lak.f90:2424
subroutine lak_fill_budobj(this)
Copy flow terms into thisbudobj.
Definition: gwf-lak.f90:5949
subroutine lak_get_internal_mover(this, ilak, outoutf)
Get the mover outflow from a lake to another lake.
Definition: gwf-lak.f90:2800
subroutine lak_calculate_outlet_inflow(this, ilak, outinf)
Calculate the outlet inflow to a lake.
Definition: gwf-lak.f90:2623
subroutine lak_calculate_conn_exchange(this, ilak, iconn, stage, head, flow, gwfhcof, gwfrhs)
Calculate the groundwater-lake flow at a provided stage and groundwater head.
Definition: gwf-lak.f90:2358
subroutine lak_ar(this)
Allocate and Read.
Definition: gwf-lak.f90:3370
pure logical function, public is_close(a, b, rtol, atol, symmetric)
Check if a real value is approximately equal to another.
Definition: MathUtil.f90:46
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains the derived types ObserveType and ObsDataType.
Definition: Observe.f90:15
This module contains the derived type ObsType.
Definition: Obs.f90:127
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_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 deprecation_warning(cblock, cvar, cver, endmsg, iunit)
Store deprecation warning message.
Definition: Sim.f90:259
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:168
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
integer(i4b) ifailedstepretry
current retry for this time step
character(len=maxcharlen) warnmsg
warning message string
real(dp) function squadraticsaturation(top, bot, x, eps)
@ brief sQuadraticSaturation
real(dp) function squadraticsaturationderivative(top, bot, x, eps)
@ brief Derivative of the quadratic saturation function
real(dp) function sqsaturationderivative(top, bot, x, c1, c2)
@ brief sQSaturationDerivative
real(dp) function sqsaturation(top, bot, x, c1, c2)
@ brief sQSaturation
subroutine, public table_cr(this, name, title)
Definition: Table.f90:85
real(dp), pointer, public pertim
time relative to start of stress period
Definition: tdis.f90:30
real(dp), pointer, public totim
time relative to start of simulation
Definition: tdis.f90:32
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
integer(i4b), pointer, public nper
number of stress period
Definition: tdis.f90:21
subroutine, public read_value_or_time_series_adv(textInput, ii, jj, bndElem, pkgName, auxOrBnd, tsManager, iprpak, varName)
Call this subroutine from advanced packages to define timeseries link for a variable (varName).
@ brief BndType