MODFLOW 6  version 6.7.0.dev3
USGS Modular Hydrologic Model
gwf-csub.f90
Go to the documentation of this file.
1 !> @brief This module contains the CSUB package methods
2 !!
3 !! This module contains the methods used to add the effects of elastic
4 !! skeletal storage, compaction, and subsidence on the groundwater flow
5 !! equation. The contribution of elastic skelatal, inelastic and elastic
6 !! interbed storage and water compressibility can be represented.
7 !!
8 !<
10  use kindmodule, only: i4b, dp, lgp
11  use constantsmodule, only: dprec, dzero, dem20, dem15, dem10, dem8, dem7, &
12  dem6, dem4, dp9, dhalf, dem1, done, dtwo, dthree, &
17  lenlistlabel, &
21  use mathutilmodule, only: is_close
22  use messagemodule, only: write_message
25  squadratic0sp, &
28  use observemodule, only: observetype
29  use obsmodule, only: obstype, obs_cr
30  use geomutilmodule, only: get_node
32  use basedismodule, only: disbasetype
36  use sortmodule, only: selectn
37  !
38  use tablemodule, only: tabletype, table_cr
39  !
42  !
43  implicit none
44  !
45  private
46  public :: csub_cr
47  public :: gwfcsubtype
48  !
49  character(len=LENBUDTXT), dimension(4) :: budtxt = & !< text labels for budget terms
50  [' CSUB-CGELASTIC', &
51  ' CSUB-ELASTIC', &
52  ' CSUB-INELASTIC', &
53  ' CSUB-WATERCOMP']
54  character(len=LENBUDTXT), dimension(6) :: comptxt = & !< text labels for compaction terms
55  ['CSUB-COMPACTION', &
56  ' CSUB-INELASTIC', &
57  ' CSUB-ELASTIC', &
58  ' CSUB-INTERBED', &
59  ' CSUB-COARSE', &
60  ' CSUB-ZDISPLACE']
61 
62  !
63  ! -- local parameter
64  real(dp), parameter :: dlog10es = 0.4342942_dp !< derivative of the log of effective stress
65  !
66  ! CSUB type
68  ! -- characters scalars
69  character(len=LENLISTLABEL), pointer :: listlabel => null() !< title of table written for RP
70  character(len=LENMEMPATH), pointer :: stomempath => null() !< memory path of storage package
71  ! -- character arrays
72  character(len=LENBOUNDNAME), dimension(:), &
73  pointer, contiguous :: boundname => null() !< vector of boundnames
74  character(len=LENAUXNAME), dimension(:), &
75  pointer, contiguous :: auxname => null() !< vector of auxname
76  ! -- logical scalars
77  logical(LGP), pointer :: lhead_based => null() !< logical variable indicating if head-based solution
78  ! -- integer scalars
79  integer(I4B), pointer :: istounit => null() !< unit number of storage package
80  integer(I4B), pointer :: istrainib => null() !< unit number of interbed strain output
81  integer(I4B), pointer :: istrainsk => null() !< unit number of coarse-grained strain output
82  integer(I4B), pointer :: ioutcomp => null() !< unit number for cell-by-cell compaction output
83  integer(I4B), pointer :: ioutcompi => null() !< unit number for cell-by-cell inelastic compaction output
84  integer(I4B), pointer :: ioutcompe => null() !< unit number for cell-by-cell elastic compaction output
85  integer(I4B), pointer :: ioutcompib => null() !< unit number for cell-by-cell interbed compaction output
86  integer(I4B), pointer :: ioutcomps => null() !< unit number for cell-by-cell coarse-grained compaction output
87  integer(I4B), pointer :: ioutzdisp => null() !< unit number for z-displacement output
88  integer(I4B), pointer :: ipakcsv => null() !< unit number for csv output
89  integer(I4B), pointer :: iupdatematprop => null() !< flag indicating if material properties will be updated
90  integer(I4B), pointer :: istoragec => null() !< flag indicating specific storage coefficient will be specified
91  integer(I4B), pointer :: icellf => null() !< flag indicating cell fractions will be specified
92  integer(I4B), pointer :: ispecified_pcs => null() !< flag indicating preconsolidation state is specified (not relative)
93  integer(I4B), pointer :: ispecified_dbh => null() !< flag indicating delay bed head is specified (not relative)
94  integer(I4B), pointer :: inamedbound => null() !< flag to read boundnames
95  integer(I4B), pointer :: iconvchk => null() !< flag indicating if a final convergence check will be made
96  integer(I4B), pointer :: naux => null() !< number of auxiliary variables
97  integer(I4B), pointer :: ninterbeds => null() !< number of interbeds
98  integer(I4B), pointer :: maxsig0 => null() !< maximum number of cells with specified sig0 values
99  integer(I4B), pointer :: nbound => null() !< number of boundaries for current stress period
100  integer(I4B), pointer :: iscloc => null() !< bound column to scale with SFAC
101  integer(I4B), pointer :: iauxmultcol => null() !< column to use as multiplier for column iscloc
102  integer(I4B), pointer :: ndelaycells => null() !< number of cells in delay interbeds
103  integer(I4B), pointer :: ndelaybeds => null() !< number of delay interbeds
104  integer(I4B), pointer :: initialized => null() !< flag indicating if the initial stresses have been initialized
105  integer(I4B), pointer :: ieslag => null() !< flag indicating if the effective stress is lagged
106  integer(I4B), pointer :: ipch => null() !< flag indicating if initial precosolidation value is a head
107  integer(I4B), pointer :: iupdatestress => null() !< flag indicating if the geostatic stress is active
108  ! -- real scalars
109  real(dp), pointer :: epsilon => null() !< epsilon for stress smoothing
110  real(dp), pointer :: cc_crit => null() !< convergence criteria for csub-gwf convergence check
111  real(dp), pointer :: gammaw => null() !< product of fluid density, and gravity
112  real(dp), pointer :: beta => null() !< water compressibility
113  real(dp), pointer :: brg => null() !< product of gammaw and water compressibility
114  real(dp), pointer :: satomega => null() !< newton-raphson saturation omega
115  ! -- integer pointer to storage package variables
116  integer(I4B), pointer :: gwfiss => null() !< pointer to model iss flag
117  integer(I4B), pointer :: gwfiss0 => null() !< iss flag for last stress period
118  ! -- integer arrays
119  integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound
120  integer(I4B), dimension(:), pointer, contiguous :: stoiconv => null() !< pointer to iconvert in storage
121  ! -- real arrays
122  real(dp), dimension(:), pointer, contiguous :: stoss => null() !< pointer to ss in storage
123  real(dp), dimension(:), pointer, contiguous :: buff => null() !< buff array
124  real(dp), dimension(:), pointer, contiguous :: buffusr => null() !< buffusr array
125  integer, dimension(:), pointer, contiguous :: nodelist => null() !< reduced node that the interbed is attached to
126  integer, dimension(:), pointer, contiguous :: unodelist => null() !< user node that the interbed is attached to
127  !
128  ! -- coarse-grained storage variables
129  real(dp), dimension(:), pointer, contiguous :: sgm => null() !< specific gravity moist sediments
130  real(dp), dimension(:), pointer, contiguous :: sgs => null() !< specific gravity saturated sediments
131  real(dp), dimension(:), pointer, contiguous :: cg_ske_cr => null() !< coarse-grained specified storage
132  real(dp), dimension(:), pointer, contiguous :: cg_gs => null() !< geostatic stress for a cell
133  real(dp), dimension(:), pointer, contiguous :: cg_es => null() !< coarse-grained (aquifer) effective stress
134  real(dp), dimension(:), pointer, contiguous :: cg_es0 => null() !< coarse-grained (aquifer) effective stress for the previous time step
135  real(dp), dimension(:), pointer, contiguous :: cg_pcs => null() !< coarse-grained (aquifer) preconsolidation stress
136  real(dp), dimension(:), pointer, contiguous :: cg_comp => null() !< coarse-grained (aquifer) incremental compaction
137  real(dp), dimension(:), pointer, contiguous :: cg_tcomp => null() !< coarse-grained (aquifer) total compaction
138  real(dp), dimension(:), pointer, contiguous :: cg_stor => null() !< coarse-grained (aquifer) storage
139  real(dp), dimension(:), pointer, contiguous :: cg_ske => null() !< coarse-grained (aquifer) elastic storage coefficient
140  real(dp), dimension(:), pointer, contiguous :: cg_sk => null() !< coarse-grained (aquifer) first storage coefficient
141  real(dp), dimension(:), pointer, contiguous :: cg_thickini => null() !< initial coarse-grained (aquifer) thickness
142  real(dp), dimension(:), pointer, contiguous :: cg_thetaini => null() !< initial coarse-grained (aquifer) porosity
143  real(dp), dimension(:), pointer, contiguous :: cg_thick => null() !< current coarse-grained (aquifer) thickness
144  real(dp), dimension(:), pointer, contiguous :: cg_thick0 => null() !< previous coarse-grained (aquifer) thickness
145  real(dp), dimension(:), pointer, contiguous :: cg_theta => null() !< current coarse-grained (aquifer) porosity
146  real(dp), dimension(:), pointer, contiguous :: cg_theta0 => null() !< previous coarse-grained (aquifer) porosity
147  !
148  ! -- cell storage variables
149  real(dp), dimension(:), pointer, contiguous :: cell_wcstor => null() !< cell water compressibility storage
150  real(dp), dimension(:), pointer, contiguous :: cell_thick => null() !< cell compressible material thickness
151  !
152  ! -- interbed variables
153  integer(I4B), dimension(:), pointer, contiguous :: idelay => null() !< delay interbed flag - 0 = nodelay, > 0 = delay
154  integer(I4B), dimension(:), pointer, contiguous :: ielastic => null() !< elastic interbed equation - 0 = inelastic and elastic, > 0 = elastic
155  integer(I4B), dimension(:), pointer, contiguous :: iconvert => null() !< convertible cell flag - 0 = elastic, > 0 = inelastic
156  real(dp), dimension(:), pointer, contiguous :: ci => null() !< compression index
157  real(dp), dimension(:), pointer, contiguous :: rci => null() !< recompression index
158  real(dp), dimension(:), pointer, contiguous :: pcs => null() !< preconsolidation stress
159  real(dp), dimension(:), pointer, contiguous :: rnb => null() !< interbed system material factor
160  real(dp), dimension(:), pointer, contiguous :: kv => null() !< vertical hydraulic conductivity of interbed
161  real(dp), dimension(:), pointer, contiguous :: h0 => null() !< initial head in interbed
162  real(dp), dimension(:), pointer, contiguous :: comp => null() !< interbed incremental compaction
163  real(dp), dimension(:), pointer, contiguous :: tcomp => null() !< total interbed compaction
164  real(dp), dimension(:), pointer, contiguous :: tcompi => null() !< total inelastic interbed compaction
165  real(dp), dimension(:), pointer, contiguous :: tcompe => null() !< total elastic interbed compaction
166  real(dp), dimension(:), pointer, contiguous :: storagee => null() !< elastic storage
167  real(dp), dimension(:), pointer, contiguous :: storagei => null() !< inelastic storage
168  real(dp), dimension(:), pointer, contiguous :: ske => null() !< elastic storage coefficient
169  real(dp), dimension(:), pointer, contiguous :: sk => null() !< first storage coefficient
170  real(dp), dimension(:), pointer, contiguous :: thickini => null() !< initial interbed thickness
171  real(dp), dimension(:), pointer, contiguous :: thetaini => null() !< initial interbed theta
172  real(dp), dimension(:), pointer, contiguous :: thick => null() !< current interbed thickness
173  real(dp), dimension(:), pointer, contiguous :: thick0 => null() !< previous interbed thickness
174  real(dp), dimension(:), pointer, contiguous :: theta => null() !< current interbed porosity
175  real(dp), dimension(:), pointer, contiguous :: theta0 => null() !< previous interbed porosity
176  real(dp), dimension(:, :), pointer, contiguous :: auxvar => null() !< auxiliary variable array
177  !
178  ! -- delay interbed
179  integer(I4B), dimension(:), pointer, contiguous :: idb_nconv_count => null() !< non-convertible count of interbeds with heads below delay cell top
180  integer(I4B), dimension(:, :), pointer, contiguous :: idbconvert => null() !0 = elastic, > 0 = inelastic
181  real(dp), dimension(:), pointer, contiguous :: dbdhmax => null() !< delay bed maximum head change
182  real(dp), dimension(:, :), pointer, contiguous :: dbz => null() !< delay bed cell z
183  real(dp), dimension(:, :), pointer, contiguous :: dbrelz => null() !< delay bed cell z relative to znode
184  real(dp), dimension(:, :), pointer, contiguous :: dbh => null() !< delay bed cell h
185  real(dp), dimension(:, :), pointer, contiguous :: dbh0 => null() !< delay bed cell previous h
186  real(dp), dimension(:, :), pointer, contiguous :: dbgeo => null() !< delay bed cell geostatic stress
187  real(dp), dimension(:, :), pointer, contiguous :: dbes => null() !< delay bed cell effective stress
188  real(dp), dimension(:, :), pointer, contiguous :: dbes0 => null() !< delay bed cell previous effective stress
189  real(dp), dimension(:, :), pointer, contiguous :: dbpcs => null() !< delay bed cell preconsolidation stress
190  real(dp), dimension(:), pointer, contiguous :: dbflowtop => null() !< delay bed flow through interbed top
191  real(dp), dimension(:), pointer, contiguous :: dbflowbot => null() !< delay bed flow through interbed bottom
192  real(dp), dimension(:, :), pointer, contiguous :: dbdzini => null() !< initial delay bed cell thickness
193  real(dp), dimension(:, :), pointer, contiguous :: dbthetaini => null() !< initial delay bed cell porosity
194  real(dp), dimension(:, :), pointer, contiguous :: dbdz => null() !< delay bed dz
195  real(dp), dimension(:, :), pointer, contiguous :: dbdz0 => null() !< delay bed previous dz
196  real(dp), dimension(:, :), pointer, contiguous :: dbtheta => null() !< delay bed cell porosity
197  real(dp), dimension(:, :), pointer, contiguous :: dbtheta0 => null() !< delay bed cell previous porosity
198  real(dp), dimension(:, :), pointer, contiguous :: dbcomp => null() !< delay bed incremental compaction
199  real(dp), dimension(:, :), pointer, contiguous :: dbtcomp => null() !< delay bed total interbed compaction
200  !
201  ! -- delay interbed solution arrays
202  real(dp), dimension(:), pointer, contiguous :: dbal => null() !< delay bed lower diagonal
203  real(dp), dimension(:), pointer, contiguous :: dbad => null() !< delay bed diagonal
204  real(dp), dimension(:), pointer, contiguous :: dbau => null() !< delay bed upper diagonal
205  real(dp), dimension(:), pointer, contiguous :: dbrhs => null() !< delay bed right hand side
206  real(dp), dimension(:), pointer, contiguous :: dbdh => null() !< delay bed dh
207  real(dp), dimension(:), pointer, contiguous :: dbaw => null() !< delay bed work vector
208  !
209  ! -- period data
210  integer(I4B), dimension(:), pointer, contiguous :: nodelistsig0 => null() !< vector of reduced node numbers
211  real(dp), dimension(:), pointer, contiguous :: sig0 => null() !< array of package specific boundary numbers
212  !
213  ! -- observation data
214  integer(I4B), pointer :: inobspkg => null() !< unit number for obs package
215  type(obstype), pointer :: obs => null() !< observation package
216  !
217  ! -- table objects
218  type(tabletype), pointer :: inputtab => null() !< table for input variables
219  type(tabletype), pointer :: outputtab => null() !< table for output variables
220  type(tabletype), pointer :: pakcsvtab => null() !< table for csv output
221 
222  contains
223  procedure :: define_listlabel
224  procedure :: source_options
225  procedure :: log_options
226  procedure :: csub_ar
227  procedure :: csub_da
228  procedure :: csub_rp
229  procedure :: csub_ad
230  procedure :: csub_fc
231  procedure :: csub_fn
232  procedure :: csub_cc
233  procedure :: csub_cq
234  procedure :: csub_bd
236  procedure :: csub_ot_dv
237  procedure :: csub_fp
238  procedure :: source_dimensions => csub_source_dimensions
239  procedure, private :: csub_allocate_scalars
240  procedure, private :: csub_allocate_arrays
241  procedure, private :: csub_source_griddata
242  procedure, private :: csub_source_packagedata
243  procedure, private :: csub_print_packagedata
244  !
245  ! -- helper methods
246  procedure, private :: csub_calc_void_ratio
247  procedure, private :: csub_calc_theta
248  procedure, private :: csub_calc_znode
249  procedure, private :: csub_calc_adjes
250  procedure, private :: csub_calc_sat
251  procedure, private :: csub_calc_sat_derivative
252  procedure, private :: csub_calc_sfacts
253  procedure, private :: csub_adj_matprop
254  procedure, private :: csub_calc_interbed_thickness
255  procedure, private :: csub_calc_delay_flow
256  !
257  ! -- stress methods
258  procedure, private :: csub_cg_calc_stress
259  procedure, private :: csub_cg_chk_stress
260  !
261  ! -- initial states
262  procedure, private :: csub_set_initial_state
263  !
264  ! -- coarse-grained coarse-grained methods
265  procedure, private :: csub_cg_update
266  procedure, private :: csub_cg_calc_comp
267  procedure, private :: csub_cg_calc_sske
268  procedure, private :: csub_cg_fc
269  procedure, private :: csub_cg_fn
270  procedure, private :: csub_cg_wcomp_fc
271  procedure, private :: csub_cg_wcomp_fn
272  !
273  ! -- interbed methods
274  procedure, private :: csub_interbed_fc
275  procedure, private :: csub_interbed_fn
276  !
277  ! -- no-delay interbed methods
278  procedure, private :: csub_nodelay_update
279  procedure, private :: csub_nodelay_fc
280  procedure, private :: csub_nodelay_wcomp_fc
281  procedure, private :: csub_nodelay_wcomp_fn
282  procedure, private :: csub_nodelay_calc_comp
283  !
284  ! -- delay interbed methods
285  procedure, private :: csub_delay_calc_sat
286  procedure, private :: csub_delay_calc_sat_derivative
287  procedure, private :: csub_delay_init_zcell
288  procedure, private :: csub_delay_calc_stress
289  procedure, private :: csub_delay_calc_ssksske
290  procedure, private :: csub_delay_calc_comp
291  procedure, private :: csub_delay_update
292  procedure, private :: csub_delay_calc_dstor
293  procedure, private :: csub_delay_calc_wcomp
294  procedure, private :: csub_delay_fc
295  procedure, private :: csub_delay_sln
296  procedure, private :: csub_delay_assemble
297  procedure, private :: csub_delay_assemble_fc
298  procedure, private :: csub_delay_assemble_fn
299  procedure, private :: csub_delay_head_check
300 
301  ! methods for tables
302  procedure, private :: csub_initialize_tables
303  !
304  ! -- methods for observations
305  procedure, public :: csub_obs_supported
306  procedure, public :: csub_df_obs
307  procedure, private :: csub_rp_obs
308  procedure, public :: csub_bd_obs
309  end type gwfcsubtype
310 
311 contains
312 
313  !> @ brief Create a new package object
314  !!
315  !! Create a new CSUB object
316  !!
317  !<
318  subroutine csub_cr(csubobj, name_model, mempath, istounit, stoPckName, inunit, &
319  iout)
320  ! -- dummy variables
321  type(gwfcsubtype), pointer :: csubobj !< pointer to default package type
322  character(len=*), intent(in) :: name_model !< model name
323  character(len=*), intent(in) :: mempath !< input context mem path
324  integer(I4B), intent(in) :: inunit !< unit number of csub input file
325  integer(I4B), intent(in) :: istounit !< unit number of storage package
326  character(len=*), intent(in) :: stopckname !< name of the storage package
327  integer(I4B), intent(in) :: iout !< unit number of lst output file
328  ! -- local variables
329  !
330  ! -- allocate the object and assign values to object variables
331  allocate (csubobj)
332 
333  ! -- create name and memory path
334  call csubobj%set_names(1, name_model, 'CSUB', 'CSUB', mempath)
335  !
336  ! -- Allocate scalars
337  call csubobj%csub_allocate_scalars()
338  !
339  ! -- Create memory path to variables from STO package
340  csubobj%stoMemPath = create_mem_path(name_model, stopckname)
341  !
342  ! -- Set variables
343  csubobj%istounit = istounit
344  csubobj%inunit = inunit
345  csubobj%iout = iout
346  end subroutine csub_cr
347 
348  !> @ brief Allocate and read method for package
349  !!
350  !! Method to allocate and read static data for the CSUB package.
351  !!
352  !<
353  subroutine csub_ar(this, dis, ibound)
354  ! -- modules
356  use constantsmodule, only: linelength
357  use kindmodule, only: i4b
358  ! -- dummy variables
359  class(gwfcsubtype), intent(inout) :: this
360  class(disbasetype), pointer, intent(in) :: dis !< model discretization
361  integer(I4B), dimension(:), pointer, contiguous :: ibound !< model ibound array
362  ! -- local variables
363  character(len=20) :: cellid
364  integer(I4B) :: idelay
365  integer(I4B) :: ib
366  integer(I4B) :: node
367  integer(I4B) :: istoerr
368  real(DP) :: top
369  real(DP) :: bot
370  real(DP) :: thick
371  real(DP) :: cg_ske_cr
372  real(DP) :: theta
373  real(DP) :: v
374  real(DP) :: vtot
375  ! -- format
376  character(len=*), parameter :: fmtcsub = &
377  "(1x,/1x,'CSUB -- COMPACTION PACKAGE, VERSION 1, 12/15/2019', &
378  &' INPUT READ FROM MEMPATH: ', A, /)"
379  !
380  ! --print a message identifying the csub package.
381  write (this%iout, fmtcsub) this%input_mempath
382  !
383  ! -- store pointers to arguments that were passed in
384  this%dis => dis
385  this%ibound => ibound
386  !
387  ! -- create obs package
388  call obs_cr(this%obs, this%inobspkg)
389  !
390  ! -- source csub options
391  call this%source_options()
392  !
393  ! -- source the csub dimensions
394  call this%source_dimensions()
395  !
396  ! - observation data
397  call this%obs%obs_ar()
398  !
399  ! -- terminate if errors dimensions block data
400  if (count_errors() > 0) then
401  call store_error_filename(this%input_fname)
402  end if
403 
404  ! -- Allocate arrays in
405  call this%csub_allocate_arrays()
406  !
407  ! -- source griddata
408  call this%csub_source_griddata()
409  !
410  ! -- evaluate the coarse-grained material properties and if
411  ! non-zero specific storage values are specified in the
412  ! STO package
413  istoerr = 0
414  do node = 1, this%dis%nodes
415  call this%dis%noder_to_string(node, cellid)
416  cg_ske_cr = this%cg_ske_cr(node)
417  theta = this%cg_thetaini(node)
418  !
419  ! -- coarse-grained storage error condition
420  if (cg_ske_cr < dzero) then
421  write (errmsg, '(a,g0,a,1x,a,1x,a,a)') &
422  'Coarse-grained material CG_SKE_CR (', cg_ske_cr, ') is less', &
423  'than zero in cell', trim(adjustl(cellid)), '.'
424  end if
425  !
426  ! -- storage (STO) package error condition
427  if (this%stoss(node) /= dzero) then
428  istoerr = 1
429  end if
430  !
431  ! -- porosity error condition
432  if (theta > done .or. theta < dzero) then
433  write (errmsg, '(a,g0,a,1x,a,1x,a,a)') &
434  'Coarse-grained material THETA (', theta, ') is less', &
435  'than zero or greater than 1 in cell', trim(adjustl(cellid)), '.'
436  end if
437  end do
438  !
439  ! -- write single message if storage (STO) package has non-zero specific
440  ! storage values
441  if (istoerr /= 0) then
442  write (errmsg, '(a,3(1x,a))') &
443  'Specific storage values in the storage (STO) package must', &
444  'be zero in all active cells when using the', &
445  trim(adjustl(this%packName)), &
446  'package.'
447  call store_error(errmsg)
448  end if
449  !
450  ! -- source interbed data
451  if (this%ninterbeds > 0) then
452  call this%csub_source_packagedata()
453  end if
454  !
455  ! setup package convergence tables
456  call this%csub_initialize_tables()
457  !
458  ! -- calculate the coarse-grained material thickness without the interbeds
459  do node = 1, this%dis%nodes
460  top = this%dis%top(node)
461  bot = this%dis%bot(node)
462  this%cg_thickini(node) = top - bot
463  this%cell_thick(node) = top - bot
464  end do
465  !
466  ! -- subtract the interbed thickness from aquifer thickness
467  do ib = 1, this%ninterbeds
468  node = this%nodelist(ib)
469  idelay = this%idelay(ib)
470  if (idelay == 0) then
471  v = this%thickini(ib)
472  else
473  v = this%rnb(ib) * this%thickini(ib)
474  end if
475  this%cg_thickini(node) = this%cg_thickini(node) - v
476  end do
477  !
478  ! -- evaluate if any cg_thick values are less than 0
479  do node = 1, this%dis%nodes
480  thick = this%cg_thickini(node)
481  if (thick < dzero) then
482  call this%dis%noder_to_string(node, cellid)
483  write (errmsg, '(a,g0,a,1x,a,a)') &
484  'Coarse grained material thickness is less than zero (', &
485  thick, ') in cell', trim(adjustl(cellid)), '. Interbed thicknesses:'
486 
487  vtot = dzero
488  do ib = 1, this%ninterbeds
489  if (node /= this%nodelist(ib)) then
490  cycle
491  end if
492  idelay = this%idelay(ib)
493  v = this%thickini(ib)
494  if (idelay /= 0) then
495  v = v * this%rnb(ib)
496  end if
497  vtot = vtot + v
498  write (errmsg, '(a,1x,a,i0,a,g0)') &
499  trim(adjustl(errmsg)), &
500  'icbno(', ib, ')=', v
501  end do
502  write (errmsg, '(a,a,g0,a)') &
503  trim(adjustl(errmsg)), &
504  '. Total interbed thickness=', vtot, '.'
505  call store_error(errmsg)
506  end if
507  end do
508  !
509  ! -- terminate if errors griddata, packagedata blocks, TDIS, or STO data
510  if (count_errors() > 0) then
511  call store_error_filename(this%input_fname)
512  end if
513  !
514  ! -- set current coarse-grained thickness (cg_thick) and
515  ! current coarse-grained porosity (cg_theta). Only needed
516  ! if updating material properties
517  if (this%iupdatematprop /= 0) then
518  do node = 1, this%dis%nodes
519  this%cg_thick(node) = this%cg_thickini(node)
520  this%cg_theta(node) = this%cg_thetaini(node)
521  end do
522  end if
523  end subroutine csub_ar
524 
525  !> @ brief Source options for package
526  !!
527  !! Source options for CSUB package.
528  !!
529  !<
530  subroutine source_options(this)
531  ! -- modules
535  use openspecmodule, only: access, form
539  ! -- dummy variables
540  class(gwfcsubtype), intent(inout) :: this
541  ! -- local variables
542  integer(I4B), pointer :: ibs
543  integer(I4B) :: inobs
544  character(len=LINELENGTH) :: csv_interbed, csv_coarse
545  character(len=LINELENGTH) :: cmp_fn, ecmp_fn, iecmp_fn, ibcmp_fn, cmpcoarse_fn
546  character(len=LINELENGTH) :: zdisp_fn, pkg_converge_fn
547  type(gwfcsubparamfoundtype) :: found
548  logical(LGP) :: warn_estress_lag = .false.
549 
550  ! -- allocate and initialize variables
551  allocate (ibs)
552  ibs = 0
553 
554  ! -- update defaults from input context
555  call mem_set_value(this%inamedbound, 'BOUNDNAMES', this%input_mempath, &
556  found%boundnames)
557  call mem_set_value(this%iprpak, 'PRINT_INPUT', this%input_mempath, &
558  found%print_input)
559  call mem_set_value(this%ipakcb, 'SAVE_FLOWS', this%input_mempath, &
560  found%save_flows)
561  call mem_set_value(this%gammaw, 'GAMMAW', this%input_mempath, found%gammaw)
562  call mem_set_value(this%beta, 'BETA', this%input_mempath, found%beta)
563  call mem_set_value(this%ipch, 'HEAD_BASED', this%input_mempath, &
564  found%head_based)
565  call mem_set_value(this%ipch, 'PRECON_HEAD', this%input_mempath, &
566  found%precon_head)
567  call mem_set_value(this%ndelaycells, 'NDELAYCELLS', this%input_mempath, &
568  found%ndelaycells)
569  call mem_set_value(this%istoragec, 'ICOMPRESS', this%input_mempath, &
570  found%icompress)
571  call mem_set_value(this%iupdatematprop, 'MATPROP', this%input_mempath, &
572  found%matprop)
573  call mem_set_value(this%icellf, 'CELL_FRACTION', this%input_mempath, &
574  found%cell_fraction)
575  call mem_set_value(ibs, 'INTERBED_STATE', this%input_mempath, &
576  found%interbed_state)
577  call mem_set_value(this%ispecified_pcs, 'PRECON_STRESS', this%input_mempath, &
578  found%precon_stress)
579  call mem_set_value(this%ispecified_dbh, 'DELAY_HEAD', this%input_mempath, &
580  found%delay_head)
581  call mem_set_value(this%ieslag, 'STRESS_LAG', this%input_mempath, &
582  found%stress_lag)
583  call mem_set_value(csv_interbed, 'INTERBEDSTRAINFN', this%input_mempath, &
584  found%interbedstrainfn)
585  call mem_set_value(csv_coarse, 'COARSESTRAINFN', this%input_mempath, &
586  found%coarsestrainfn)
587  call mem_set_value(cmp_fn, 'CMPFN', this%input_mempath, found%cmpfn)
588  call mem_set_value(ecmp_fn, 'ELASTICCMPFN', this%input_mempath, &
589  found%elasticcmpfn)
590  call mem_set_value(iecmp_fn, 'INELASTICCMPFN', this%input_mempath, &
591  found%inelasticcmpfn)
592  call mem_set_value(ibcmp_fn, 'INTERBEDCMPFN', this%input_mempath, &
593  found%interbedcmpfn)
594  call mem_set_value(cmpcoarse_fn, 'CMPCOARSEFN', this%input_mempath, &
595  found%cmpcoarsefn)
596  call mem_set_value(zdisp_fn, 'ZDISPFN', this%input_mempath, found%zdispfn)
597  call mem_set_value(pkg_converge_fn, 'PKGCONVERGEFN', this%input_mempath, &
598  found%pkgconvergefn)
599 
600  ! -- enforce 0 or 1 OBS6_FILENAME entries in option block
601  if (filein_fname(this%obs%inputFilename, 'OBS6_FILENAME', &
602  this%input_mempath, this%input_fname)) then
603  this%obs%active = .true.
604  inobs = getunit()
605  call openfile(inobs, this%iout, this%obs%inputFilename, 'OBS')
606  this%obs%inUnitObs = inobs
607  this%inobspkg = inobs
608  call this%obs%obs_df(this%iout, this%packName, this%filtyp, this%dis)
609  call this%csub_df_obs()
610  end if
611 
612  ! -- update input dependent internal state
613  if (found%save_flows) this%ipakcb = -1
614  if (found%head_based) then
615  this%lhead_based = .true.
616  if (this%ieslag /= 0) then
617  this%ieslag = 0
618  warn_estress_lag = .true.
619  end if
620  end if
621  if (found%icompress) this%istoragec = 0
622  if (found%interbed_state) then
623  this%ispecified_pcs = 1
624  this%ispecified_dbh = 1
625  end if
626  if (found%gammaw .or. found%beta) then
627  this%brg = this%gammaw * this%beta
628  end if
629 
630  ! fileout options
631  if (found%interbedstrainfn) then
632  this%istrainib = getunit()
633  call openfile(this%istrainib, this%iout, csv_interbed, 'CSV_OUTPUT', &
634  filstat_opt='REPLACE', mode_opt=mnormal)
635  end if
636  if (found%coarsestrainfn) then
637  this%istrainsk = getunit()
638  call openfile(this%istrainsk, this%iout, csv_coarse, 'CSV_OUTPUT', &
639  filstat_opt='REPLACE', mode_opt=mnormal)
640  end if
641  if (found%cmpfn) then
642  this%ioutcomp = getunit()
643  call openfile(this%ioutcomp, this%iout, cmp_fn, 'DATA(BINARY)', &
644  form, access, 'REPLACE', mode_opt=mnormal)
645  end if
646  if (found%elasticcmpfn) then
647  this%ioutcompe = getunit()
648  call openfile(this%ioutcompe, this%iout, ecmp_fn, &
649  'DATA(BINARY)', form, access, 'REPLACE', &
650  mode_opt=mnormal)
651  end if
652  if (found%inelasticcmpfn) then
653  this%ioutcompi = getunit()
654  call openfile(this%ioutcompi, this%iout, iecmp_fn, &
655  'DATA(BINARY)', form, access, 'REPLACE', &
656  mode_opt=mnormal)
657  end if
658  if (found%interbedcmpfn) then
659  this%ioutcompib = getunit()
660  call openfile(this%ioutcompib, this%iout, ibcmp_fn, &
661  'DATA(BINARY)', form, access, 'REPLACE', &
662  mode_opt=mnormal)
663  end if
664  if (found%cmpcoarsefn) then
665  this%ioutcomps = getunit()
666  call openfile(this%ioutcomps, this%iout, cmpcoarse_fn, &
667  'DATA(BINARY)', form, access, 'REPLACE', &
668  mode_opt=mnormal)
669  end if
670  if (found%zdispfn) then
671  this%ioutzdisp = getunit()
672  call openfile(this%ioutzdisp, this%iout, zdisp_fn, &
673  'DATA(BINARY)', form, access, 'REPLACE', &
674  mode_opt=mnormal)
675  end if
676  if (found%pkgconvergefn) then
677  this%ipakcsv = getunit()
678  call openfile(this%ipakcsv, this%iout, pkg_converge_fn, 'CSV', &
679  filstat_opt='REPLACE', mode_opt=mnormal)
680  end if
681 
682  ! -- log user options
683  call this%log_options(warn_estress_lag)
684 
685  ! -- cleanup
686  deallocate (ibs)
687  end subroutine source_options
688 
689  !> @ brief log options for package
690  !!
691  !! log options block for CSUB package.
692  !!
693  !<
694  subroutine log_options(this, warn_estress_lag)
695  ! -- modules
696  ! -- dummy variables
697  class(gwfcsubtype), intent(inout) :: this
698  logical(LGP), intent(in) :: warn_estress_lag
699  ! -- local variables
700  ! -- formats
701  character(len=*), parameter :: fmtts = &
702  &"(4x,'TIME-SERIES DATA WILL BE READ FROM FILE: ',a)"
703  character(len=*), parameter :: fmtflow = &
704  &"(4x,'FLOWS WILL BE SAVED TO FILE: ',a,/4x,'OPENED ON UNIT: ',I7)"
705  character(len=*), parameter :: fmtflow2 = &
706  &"(4x,'FLOWS WILL BE SAVED TO BUDGET FILE SPECIFIED IN OUTPUT CONTROL')"
707  character(len=*), parameter :: fmtssessv = &
708  &"(4x,'USING SSE AND SSV INSTEAD OF CR AND CC.')"
709  character(len=*), parameter :: fmtoffset = &
710  &"(4x,'INITIAL_STRESS TREATED AS AN OFFSET.')"
711  character(len=*), parameter :: fmtopt = &
712  &"(4x,A)"
713  character(len=*), parameter :: fmtopti = &
714  &"(4x,A,1X,I0)"
715  character(len=*), parameter :: fmtoptr = &
716  &"(4x,A,1X,G0)"
717  character(len=*), parameter :: fmtfileout = &
718  "(4x,'CSUB ',1x,a,1x,' WILL BE SAVED TO FILE: ',a,/4x,&
719  &'OPENED ON UNIT: ',I7)"
720  !
721  ! -- write messages for options
722  write (this%iout, '(//2(1X,A))') trim(adjustl(this%packName)), &
723  'PACKAGE SETTINGS'
724  write (this%iout, fmtopti) 'NUMBER OF DELAY CELLS =', &
725  this%ndelaycells
726  if (this%lhead_based .EQV. .true.) then
727  write (this%iout, '(4x,a)') &
728  'HEAD-BASED FORMULATION'
729  else
730  write (this%iout, '(4x,a)') &
731  'EFFECTIVE-STRESS FORMULATION'
732  end if
733  if (this%istoragec == 0) then
734  write (this%iout, '(4x,a,1(/,6x,a))') &
735  'COMPRESSION INDICES WILL BE SPECIFIED INSTEAD OF ELASTIC AND', &
736  'INELASTIC SPECIFIC STORAGE COEFFICIENTS'
737  else
738  write (this%iout, '(4x,a,1(/,6x,a))') &
739  'ELASTIC AND INELASTIC SPECIFIC STORAGE COEFFICIENTS WILL BE ', &
740  'SPECIFIED'
741  end if
742  if (this%iupdatematprop /= 1) then
743  write (this%iout, '(4x,a,1(/,6x,a))') &
744  'THICKNESS AND VOID RATIO WILL NOT BE ADJUSTED DURING THE', &
745  'SIMULATION'
746  else
747  write (this%iout, '(4x,a)') &
748  'THICKNESS AND VOID RATIO WILL BE ADJUSTED DURING THE SIMULATION'
749  end if
750  if (this%icellf /= 1) then
751  write (this%iout, '(4x,a)') &
752  'INTERBED THICKNESS WILL BE SPECIFIED AS A THICKNESS'
753  else
754  write (this%iout, '(4x,a,1(/,6x,a))') &
755  'INTERBED THICKNESS WILL BE SPECIFIED AS A AS A CELL FRACTION'
756  end if
757  if (this%ispecified_pcs /= 1) then
758  if (this%ipch /= 0) then
759  write (this%iout, '(4x,a,1(/,6x,a))') &
760  'PRECONSOLIDATION HEAD WILL BE SPECIFIED RELATIVE TO INITIAL', &
761  'STRESS CONDITIONS'
762  else
763  write (this%iout, '(4x,a,1(/,6x,a))') &
764  'PRECONSOLIDATION STRESS WILL BE SPECIFIED RELATIVE TO INITIAL', &
765  'STRESS CONDITIONS'
766  end if
767  else
768  if (this%ipch /= 0) then
769  write (this%iout, '(4x,a,1(/,6x,a))') &
770  'PRECONSOLIDATION HEAD WILL BE SPECIFIED AS ABSOLUTE VALUES', &
771  'INSTEAD OF RELATIVE TO INITIAL HEAD CONDITIONS'
772  else
773  write (this%iout, '(4x,a,1(/,6x,a))') &
774  'PRECONSOLIDATION STRESS WILL BE SPECIFIED AS ABSOLUTE VALUES', &
775  'INSTEAD OF RELATIVE TO INITIAL STRESS CONDITIONS'
776  end if
777  end if
778  if (this%ispecified_dbh /= 1) then
779  write (this%iout, '(4x,a,1(/,6x,a))') &
780  'DELAY INTERBED HEADS WILL BE SPECIFIED RELATIVE TO INITIAL ', &
781  'GWF HEADS'
782  else
783  write (this%iout, '(4x,a,1(/,6x,a))') &
784  'DELAY INTERBED HEADS WILL BE SPECIFIED AS ABSOLUTE VALUES INSTEAD', &
785  'OF RELATIVE TO INITIAL GWF HEADS'
786  end if
787  !
788  if (this%lhead_based .EQV. .false.) then
789  if (this%ieslag /= 0) then
790  write (this%iout, '(4x,a,1(/,6x,a))') &
791  'SPECIFIC STORAGE VALUES WILL BE CALCULATED USING THE EFFECTIVE', &
792  'STRESS FROM THE PREVIOUS TIME STEP'
793  else
794  write (this%iout, '(4x,a,1(/,6x,a))') &
795  'SPECIFIC STORAGE VALUES WILL BE CALCULATED USING THE CURRENT', &
796  'EFFECTIVE STRESS'
797  end if
798  else if (warn_estress_lag) then
799  write (this%iout, '(4x,a,2(/,6x,a))') &
800  'EFFECTIVE_STRESS_LAG HAS BEEN SPECIFIED BUT HAS NO EFFECT WHEN', &
801  'USING THE HEAD-BASED FORMULATION (HEAD_BASED HAS BEEN SPECIFIED', &
802  'IN THE OPTIONS BLOCK)'
803  end if
804  !
805  write (this%iout, fmtoptr) 'GAMMAW =', this%gammaw
806  write (this%iout, fmtoptr) 'BETA =', this%beta
807  write (this%iout, fmtoptr) 'GAMMAW * BETA =', this%brg
808  write (this%iout, '((1X,A))') 'END PACKAGE SETTINGS'
809  end subroutine log_options
810 
811  !> @ brief Source dimensions for package
812  !!
813  !! Read the number of interbeds and maximum number of cells with a specified
814  !! overlying geostatic stress.
815  !!
816  !<
817  subroutine csub_source_dimensions(this)
818  ! -- modules
821  ! -- dummy variables
822  class(gwfcsubtype), intent(inout) :: this
823  ! -- local variables
824  type(gwfcsubparamfoundtype) :: found
825 
826  ! -- initialize dimensions to -1
827  this%ninterbeds = -1
828 
829  ! -- update defaults from input context
830  call mem_set_value(this%ninterbeds, 'NINTERBEDS', this%input_mempath, &
831  found%ninterbeds)
832  call mem_set_value(this%maxsig0, 'MAXBOUND', this%input_mempath, &
833  found%maxbound)
834 
835  ! - log dimensions
836  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%packName))// &
837  ' DIMENSIONS'
838  write (this%iout, '(4x,a,i0)') 'NINTERBEDS = ', this%ninterbeds
839  write (this%iout, '(4x,a,i0)') 'MAXSIG0 = ', this%maxsig0
840  write (this%iout, '(1x,a)') &
841  'END OF '//trim(adjustl(this%packName))//' DIMENSIONS'
842 
843  ! -- verify dimensions were set correctly
844  if (.not. found%ninterbeds) then
845  write (errmsg, '(a)') &
846  'NINTERBEDS is a required dimension.'
847  call store_error(errmsg)
848  call store_error_filename(this%input_mempath)
849  end if
850 
851  ! -- Call define_listlabel to construct the list label that is written
852  ! when PRINT_INPUT option is used.
853  call this%define_listlabel()
854  end subroutine csub_source_dimensions
855 
856  !> @ brief Allocate scalars
857  !!
858  !! Allocate and initialize scalars for the CSUB package. The base model
859  !! allocate scalars method is also called.
860  !!
861  !<
862  subroutine csub_allocate_scalars(this)
863  ! -- modules
865  ! -- dummy variables
866  class(gwfcsubtype), intent(inout) :: this
867  !
868  ! -- call standard NumericalPackageType allocate scalars
869  call this%NumericalPackageType%allocate_scalars()
870  !
871  ! -- allocate character variables
872  call mem_allocate(this%listlabel, lenlistlabel, 'LISTLABEL', this%memoryPath)
873  call mem_allocate(this%stoMemPath, lenmempath, 'STONAME', this%memoryPath)
874  !
875  ! -- allocate the object and assign values to object variables
876  call mem_allocate(this%istounit, 'ISTOUNIT', this%memoryPath)
877  call mem_allocate(this%inobspkg, 'INOBSPKG', this%memoryPath)
878  call mem_allocate(this%ninterbeds, 'NINTERBEDS', this%memoryPath)
879  call mem_allocate(this%maxsig0, 'MAXSIG0', this%memoryPath)
880  call mem_allocate(this%nbound, 'NBOUND', this%memoryPath)
881  call mem_allocate(this%iscloc, 'ISCLOC', this%memoryPath)
882  call mem_allocate(this%iauxmultcol, 'IAUXMULTCOL', this%memoryPath)
883  call mem_allocate(this%ndelaycells, 'NDELAYCELLS', this%memoryPath)
884  call mem_allocate(this%ndelaybeds, 'NDELAYBEDS', this%memoryPath)
885  call mem_allocate(this%initialized, 'INITIALIZED', this%memoryPath)
886  call mem_allocate(this%ieslag, 'IESLAG', this%memoryPath)
887  call mem_allocate(this%ipch, 'IPCH', this%memoryPath)
888  call mem_allocate(this%lhead_based, 'LHEAD_BASED', this%memoryPath)
889  call mem_allocate(this%iupdatestress, 'IUPDATESTRESS', this%memoryPath)
890  call mem_allocate(this%ispecified_pcs, 'ISPECIFIED_PCS', this%memoryPath)
891  call mem_allocate(this%ispecified_dbh, 'ISPECIFIED_DBH', this%memoryPath)
892  call mem_allocate(this%inamedbound, 'INAMEDBOUND', this%memoryPath)
893  call mem_allocate(this%iconvchk, 'ICONVCHK', this%memoryPath)
894  call mem_allocate(this%naux, 'NAUX', this%memoryPath)
895  call mem_allocate(this%istoragec, 'ISTORAGEC', this%memoryPath)
896  call mem_allocate(this%istrainib, 'ISTRAINIB', this%memoryPath)
897  call mem_allocate(this%istrainsk, 'ISTRAINSK', this%memoryPath)
898  call mem_allocate(this%ioutcomp, 'IOUTCOMP', this%memoryPath)
899  call mem_allocate(this%ioutcompi, 'IOUTCOMPI', this%memoryPath)
900  call mem_allocate(this%ioutcompe, 'IOUTCOMPE', this%memoryPath)
901  call mem_allocate(this%ioutcompib, 'IOUTCOMPIB', this%memoryPath)
902  call mem_allocate(this%ioutcomps, 'IOUTCOMPS', this%memoryPath)
903  call mem_allocate(this%ioutzdisp, 'IOUTZDISP', this%memoryPath)
904  call mem_allocate(this%ipakcsv, 'IPAKCSV', this%memoryPath)
905  call mem_allocate(this%iupdatematprop, 'IUPDATEMATPROP', this%memoryPath)
906  call mem_allocate(this%epsilon, 'EPSILON', this%memoryPath)
907  call mem_allocate(this%cc_crit, 'CC_CRIT', this%memoryPath)
908  call mem_allocate(this%gammaw, 'GAMMAW', this%memoryPath)
909  call mem_allocate(this%beta, 'BETA', this%memoryPath)
910  call mem_allocate(this%brg, 'BRG', this%memoryPath)
911  call mem_allocate(this%satomega, 'SATOMEGA', this%memoryPath)
912  call mem_allocate(this%icellf, 'ICELLF', this%memoryPath)
913  call mem_allocate(this%gwfiss0, 'GWFISS0', this%memoryPath)
914  !
915  ! -- allocate text strings
916  call mem_allocate(this%auxname, lenauxname, 0, 'AUXNAME', this%memoryPath)
917  !
918  ! -- initialize values
919  this%istounit = 0
920  this%inobspkg = 0
921  this%ninterbeds = 0
922  this%maxsig0 = 0
923  this%nbound = 0
924  this%iscloc = 0
925  this%iauxmultcol = 0
926  this%ndelaycells = 19
927  this%ndelaybeds = 0
928  this%initialized = 0
929  this%ieslag = 0
930  this%ipch = 0
931  this%lhead_based = .false.
932  this%iupdatestress = 1
933  this%ispecified_pcs = 0
934  this%ispecified_dbh = 0
935  this%inamedbound = 0
936  this%iconvchk = 1
937  this%naux = 0
938  this%istoragec = 1
939  this%istrainib = 0
940  this%istrainsk = 0
941  this%ioutcomp = 0
942  this%ioutcompi = 0
943  this%ioutcompe = 0
944  this%ioutcompib = 0
945  this%ioutcomps = 0
946  this%ioutzdisp = 0
947  this%ipakcsv = 0
948  this%iupdatematprop = 0
949  this%epsilon = dzero
950  this%cc_crit = dem7
951  this%gammaw = dgravity * 1000._dp
952  this%beta = 4.6512e-10_dp
953  this%brg = this%gammaw * this%beta
954  !
955  ! -- set omega value used for saturation calculations
956  if (this%inewton /= 0) then
957  this%satomega = dem6
958  this%epsilon = dhalf * dem6
959  else
960  this%satomega = dzero
961  end if
962  this%icellf = 0
963  this%ninterbeds = 0
964  this%gwfiss0 = 0
965  end subroutine csub_allocate_scalars
966 
967  !> @ brief Allocate package arrays
968  !!
969  !! Allocate and initialize CSUB package arrays.
970  !!
971  !<
972  subroutine csub_allocate_arrays(this)
973  ! -- modules
975  ! -- dummy variables
976  class(gwfcsubtype), intent(inout) :: this
977  ! -- local variables
978  integer(I4B) :: j
979  integer(I4B) :: n
980  integer(I4B) :: iblen
981  integer(I4B) :: naux
982  !
983  ! -- grid based data
984  if (this%ioutcomp == 0 .and. this%ioutcompi == 0 .and. &
985  this%ioutcompe == 0 .and. this%ioutcompib == 0 .and. &
986  this%ioutcomps == 0 .and. this%ioutzdisp == 0) then
987  call mem_allocate(this%buff, 1, 'BUFF', trim(this%memoryPath))
988  else
989  call mem_allocate(this%buff, this%dis%nodes, 'BUFF', trim(this%memoryPath))
990  end if
991  if (this%ioutcomp == 0 .and. this%ioutzdisp == 0) then
992  call mem_allocate(this%buffusr, 1, 'BUFFUSR', trim(this%memoryPath))
993  else
994  call mem_allocate(this%buffusr, this%dis%nodesuser, 'BUFFUSR', &
995  trim(this%memoryPath))
996  end if
997  call mem_allocate(this%sgm, this%dis%nodes, 'SGM', trim(this%memoryPath))
998  call mem_allocate(this%sgs, this%dis%nodes, 'SGS', trim(this%memoryPath))
999  call mem_allocate(this%cg_ske_cr, this%dis%nodes, 'CG_SKE_CR', &
1000  trim(this%memoryPath))
1001  call mem_allocate(this%cg_es, this%dis%nodes, 'CG_ES', &
1002  trim(this%memoryPath))
1003  call mem_allocate(this%cg_es0, this%dis%nodes, 'CG_ES0', &
1004  trim(this%memoryPath))
1005  call mem_allocate(this%cg_pcs, this%dis%nodes, 'CG_PCS', &
1006  trim(this%memoryPath))
1007  call mem_allocate(this%cg_comp, this%dis%nodes, 'CG_COMP', &
1008  trim(this%memoryPath))
1009  call mem_allocate(this%cg_tcomp, this%dis%nodes, 'CG_TCOMP', &
1010  trim(this%memoryPath))
1011  call mem_allocate(this%cg_stor, this%dis%nodes, 'CG_STOR', &
1012  trim(this%memoryPath))
1013  call mem_allocate(this%cg_ske, this%dis%nodes, 'CG_SKE', &
1014  trim(this%memoryPath))
1015  call mem_allocate(this%cg_sk, this%dis%nodes, 'CG_SK', &
1016  trim(this%memoryPath))
1017  call mem_allocate(this%cg_thickini, this%dis%nodes, 'CG_THICKINI', &
1018  trim(this%memoryPath))
1019  call mem_allocate(this%cg_thetaini, this%dis%nodes, 'CG_THETAINI', &
1020  trim(this%memoryPath))
1021  if (this%iupdatematprop == 0) then
1022  call mem_setptr(this%cg_thick, 'CG_THICKINI', trim(this%memoryPath))
1023  call mem_setptr(this%cg_thick0, 'CG_THICKINI', trim(this%memoryPath))
1024  call mem_setptr(this%cg_theta, 'CG_THETAINI', trim(this%memoryPath))
1025  call mem_setptr(this%cg_theta0, 'CG_THETAINI', trim(this%memoryPath))
1026  else
1027  call mem_allocate(this%cg_thick, this%dis%nodes, 'CG_THICK', &
1028  trim(this%memoryPath))
1029  call mem_allocate(this%cg_thick0, this%dis%nodes, 'CG_THICK0', &
1030  trim(this%memoryPath))
1031  call mem_allocate(this%cg_theta, this%dis%nodes, 'CG_THETA', &
1032  trim(this%memoryPath))
1033  call mem_allocate(this%cg_theta0, this%dis%nodes, 'CG_THETA0', &
1034  trim(this%memoryPath))
1035  end if
1036  !
1037  ! -- cell storage data
1038  call mem_allocate(this%cell_wcstor, this%dis%nodes, 'CELL_WCSTOR', &
1039  trim(this%memoryPath))
1040  call mem_allocate(this%cell_thick, this%dis%nodes, 'CELL_THICK', &
1041  trim(this%memoryPath))
1042  !
1043  ! -- interbed data
1044  iblen = 1
1045  if (this%ninterbeds > 0) then
1046  iblen = this%ninterbeds
1047  end if
1048  naux = 1
1049  if (this%naux > 0) then
1050  naux = this%naux
1051  end if
1052  call mem_allocate(this%auxvar, naux, iblen, 'AUXVAR', this%memoryPath)
1053  do n = 1, iblen
1054  do j = 1, naux
1055  this%auxvar(j, n) = dzero
1056  end do
1057  end do
1058  call mem_allocate(this%unodelist, iblen, 'UNODELIST', trim(this%memoryPath))
1059  call mem_allocate(this%nodelist, iblen, 'NODELIST', trim(this%memoryPath))
1060  call mem_allocate(this%cg_gs, this%dis%nodes, 'CG_GS', trim(this%memoryPath))
1061  call mem_allocate(this%pcs, iblen, 'PCS', trim(this%memoryPath))
1062  call mem_allocate(this%rnb, iblen, 'RNB', trim(this%memoryPath))
1063  call mem_allocate(this%kv, iblen, 'KV', trim(this%memoryPath))
1064  call mem_allocate(this%h0, iblen, 'H0', trim(this%memoryPath))
1065  call mem_allocate(this%ci, iblen, 'CI', trim(this%memoryPath))
1066  call mem_allocate(this%rci, iblen, 'RCI', trim(this%memoryPath))
1067  call mem_allocate(this%idelay, iblen, 'IDELAY', trim(this%memoryPath))
1068  call mem_allocate(this%ielastic, iblen, 'IELASTIC', trim(this%memoryPath))
1069  call mem_allocate(this%iconvert, iblen, 'ICONVERT', trim(this%memoryPath))
1070  call mem_allocate(this%comp, iblen, 'COMP', trim(this%memoryPath))
1071  call mem_allocate(this%tcomp, iblen, 'TCOMP', trim(this%memoryPath))
1072  call mem_allocate(this%tcompi, iblen, 'TCOMPI', trim(this%memoryPath))
1073  call mem_allocate(this%tcompe, iblen, 'TCOMPE', trim(this%memoryPath))
1074  call mem_allocate(this%storagee, iblen, 'STORAGEE', trim(this%memoryPath))
1075  call mem_allocate(this%storagei, iblen, 'STORAGEI', trim(this%memoryPath))
1076  call mem_allocate(this%ske, iblen, 'SKE', trim(this%memoryPath))
1077  call mem_allocate(this%sk, iblen, 'SK', trim(this%memoryPath))
1078  call mem_allocate(this%thickini, iblen, 'THICKINI', trim(this%memoryPath))
1079  call mem_allocate(this%thetaini, iblen, 'THETAINI', trim(this%memoryPath))
1080  if (this%iupdatematprop == 0) then
1081  call mem_setptr(this%thick, 'THICKINI', trim(this%memoryPath))
1082  call mem_setptr(this%thick0, 'THICKINI', trim(this%memoryPath))
1083  call mem_setptr(this%theta, 'THETAINI', trim(this%memoryPath))
1084  call mem_setptr(this%theta0, 'THETAINI', trim(this%memoryPath))
1085  else
1086  call mem_allocate(this%thick, iblen, 'THICK', trim(this%memoryPath))
1087  call mem_allocate(this%thick0, iblen, 'THICK0', trim(this%memoryPath))
1088  call mem_allocate(this%theta, iblen, 'THETA', trim(this%memoryPath))
1089  call mem_allocate(this%theta0, iblen, 'THETA0', trim(this%memoryPath))
1090  end if
1091  !
1092  ! -- delay bed storage - allocated in csub_source_packagedata
1093  ! after number of delay beds is defined
1094  !
1095  ! -- allocate boundname
1096  if (this%inamedbound /= 0) then
1097  call mem_allocate(this%boundname, lenboundname, this%ninterbeds, &
1098  'BOUNDNAME', trim(this%memoryPath))
1099  else
1100  call mem_allocate(this%boundname, lenboundname, 1, &
1101  'BOUNDNAME', trim(this%memoryPath))
1102 
1103  end if
1104  !
1105  ! -- allocate the nodelist and bound arrays
1106  call mem_allocate(this%nodelistsig0, this%maxsig0, 'NODELISTSIG0', &
1107  this%memoryPath)
1108 
1109  ! -- set sig0 input context pointer
1110  call mem_setptr(this%sig0, 'SIG0', this%input_mempath)
1111  call mem_checkin(this%sig0, 'SIG0', this%memoryPath, &
1112  'SIG0', this%input_mempath)
1113  !
1114  ! -- set pointers to gwf variables
1115  call mem_setptr(this%gwfiss, 'ISS', trim(this%name_model))
1116  !
1117  ! -- set pointers to variables in the storage package
1118  call mem_setptr(this%stoiconv, 'ICONVERT', this%stoMemPath)
1119  call mem_setptr(this%stoss, 'SS', this%stoMemPath)
1120  !
1121  ! -- initialize variables that are not specified by user
1122  do n = 1, this%dis%nodes
1123  this%cg_gs(n) = dzero
1124  this%cg_es(n) = dzero
1125  this%cg_comp(n) = dzero
1126  this%cg_tcomp(n) = dzero
1127  this%cell_wcstor(n) = dzero
1128  end do
1129  do n = 1, this%ninterbeds
1130  this%theta(n) = dzero
1131  this%tcomp(n) = dzero
1132  this%tcompi(n) = dzero
1133  this%tcompe(n) = dzero
1134  end do
1135  do n = 1, this%maxsig0
1136  this%nodelistsig0(n) = 0
1137  end do
1138  end subroutine csub_allocate_arrays
1139 
1140  !> @ brief Source griddata for package
1141  !<
1142  subroutine csub_source_griddata(this)
1143  ! -- modules
1146  ! -- dummy variables
1147  class(gwfcsubtype), intent(inout) :: this
1148  ! -- locals
1149  integer(I4B) :: node
1150  type(gwfcsubparamfoundtype) :: found
1151  integer(I4B), dimension(:), pointer, contiguous :: map
1152 
1153  ! -- set map to convert user input data into reduced data
1154  map => null()
1155  if (this%dis%nodes < this%dis%nodesuser) map => this%dis%nodeuser
1156 
1157  ! -- update defaults from input context
1158  call mem_set_value(this%cg_ske_cr, 'CG_SKE_CR', this%input_mempath, &
1159  map, found%cg_ske_cr)
1160  call mem_set_value(this%cg_thetaini, 'CG_THETA', this%input_mempath, &
1161  map, found%cg_theta)
1162  call mem_set_value(this%sgm, 'SGM', this%input_mempath, map, found%sgm)
1163  call mem_set_value(this%sgs, 'SGS', this%input_mempath, map, found%sgs)
1164 
1165  ! -- cg_ske and cg_theta are required input params
1166  if (.not. found%cg_ske_cr) then
1167  call store_error('CG_SKE GRIDDATA must be specified.')
1168  call store_error_filename(this%input_fname)
1169  end if
1170  if (.not. found%cg_theta) then
1171  call store_error('CG_THETA GRIDDATA must be specified.')
1172  call store_error_filename(this%input_fname)
1173  end if
1174 
1175  ! -- if sgm and sgs have not been specified assign default values
1176  if (.not. found%sgm) then
1177  do node = 1, this%dis%nodes
1178  this%sgm(node) = 1.7d0
1179  end do
1180  end if
1181  if (.not. found%sgs) then
1182  do node = 1, this%dis%nodes
1183  this%sgs(node) = 2.0d0
1184  end do
1185  end if
1186  end subroutine csub_source_griddata
1187 
1188  !> @ brief source packagedata for package
1189  !!
1190  !! Read delay and no-delay interbed input data for the CSUB package. Method
1191  !! also validates interbed input data.
1192  !!
1193  !<
1194  subroutine csub_source_packagedata(this)
1195  ! -- modules
1199  ! -- dummy variables
1200  class(gwfcsubtype), intent(inout) :: this
1201  integer(I4B), dimension(:), pointer, contiguous :: icsubno
1202  integer(I4B), dimension(:, :), pointer, contiguous :: cellid_pkgdata
1203  integer(I4B), dimension(:), pointer :: cellid
1204  type(characterstringtype), dimension(:), pointer, &
1205  contiguous :: cdelay
1206  type(characterstringtype), dimension(:), pointer, &
1207  contiguous :: boundname
1208  real(DP), dimension(:), pointer, contiguous :: pcs, thick_frac, rnb
1209  real(DP), dimension(:), pointer, contiguous :: ssv_cc, sse_cr, theta, kv, h0
1210  character(len=LINELENGTH) :: cdelaystr
1211  character(len=LENBOUNDNAME) :: bndname
1212  character(len=20) :: cellidstr
1213  real(DP) :: top, botm, baq, q, thick, rval
1214  integer(I4B) :: idelay, ndelaybeds, csubno
1215  integer(I4B) :: ib, n, nodeu, noder
1216 
1217  ! -- set input context pointers
1218  call mem_setptr(icsubno, 'ICSUBNO', this%input_mempath)
1219  call mem_setptr(cellid_pkgdata, 'CELLID_PKGDATA', this%input_mempath)
1220  call mem_setptr(cdelay, 'CDELAY', this%input_mempath)
1221  call mem_setptr(pcs, 'PCS0', this%input_mempath)
1222  call mem_setptr(thick_frac, 'THICK_FRAC', this%input_mempath)
1223  call mem_setptr(rnb, 'RNB', this%input_mempath)
1224  call mem_setptr(ssv_cc, 'SSV_CC', this%input_mempath)
1225  call mem_setptr(sse_cr, 'SSE_CR', this%input_mempath)
1226  call mem_setptr(theta, 'THETA', this%input_mempath)
1227  call mem_setptr(kv, 'KV', this%input_mempath)
1228  call mem_setptr(h0, 'H0', this%input_mempath)
1229  call mem_setptr(boundname, 'BOUNDNAME', this%input_mempath)
1230 
1231  ! initialize ndelaybeds
1232  ndelaybeds = 0
1233 
1234  ! -- update state
1235  do n = 1, size(icsubno)
1236 
1237  ! -- set cubno
1238  csubno = icsubno(n)
1239 
1240  ! -- check csubno
1241  if (csubno < 1 .or. csubno > this%ninterbeds) then
1242  write (errmsg, '(a,1x,i0,2(1x,a),1x,i0,a)') &
1243  'Interbed number (', csubno, ') must be greater than 0 and ', &
1244  'less than or equal to', this%ninterbeds, '.'
1245  call store_error(errmsg)
1246  cycle
1247  end if
1248 
1249  ! -- set cellid
1250  cellid => cellid_pkgdata(:, n)
1251 
1252  ! -- set node user
1253  if (this%dis%ndim == 1) then
1254  nodeu = cellid(1)
1255  elseif (this%dis%ndim == 2) then
1256  nodeu = get_node(cellid(1), 1, cellid(2), &
1257  this%dis%mshape(1), 1, &
1258  this%dis%mshape(2))
1259  else
1260  nodeu = get_node(cellid(1), cellid(2), cellid(3), &
1261  this%dis%mshape(1), &
1262  this%dis%mshape(2), &
1263  this%dis%mshape(3))
1264  end if
1265 
1266  ! -- set node reduced
1267  noder = this%dis%get_nodenumber(nodeu, 1)
1268  if (noder <= 0) then
1269  call this%dis%nodeu_to_string(nodeu, cellidstr)
1270  write (errmsg, '(a)') &
1271  'CSUB configured for inactive cell: '// &
1272  trim(adjustl(cellidstr))//'.'
1273  call store_error(errmsg)
1274  cycle
1275  end if
1276 
1277  ! -- update nodelists
1278  this%nodelist(csubno) = noder
1279  this%unodelist(csubno) = nodeu
1280 
1281  ! -- set top, botm, baq
1282  top = this%dis%top(noder)
1283  botm = this%dis%bot(noder)
1284  baq = top - botm
1285 
1286  ! -- set cdelay
1287  cdelaystr = cdelay(n)
1288  select case (cdelaystr)
1289  case ('NODELAY')
1290  idelay = 0
1291  case ('DELAY')
1292  ndelaybeds = ndelaybeds + 1
1293  idelay = ndelaybeds
1294  case default
1295  write (errmsg, '(a,1x,a,1x,i0,1x,a)') &
1296  'Invalid CDELAY ', trim(adjustl(cdelaystr)), &
1297  'for packagedata entry', csubno, '.'
1298  call store_error(errmsg)
1299  cycle
1300  end select
1301  this%idelay(csubno) = idelay
1302 
1303  ! -- set initial preconsolidation stress
1304  this%pcs(csubno) = pcs(n)
1305 
1306  ! -- set thickness
1307  if (this%icellf == 0) then
1308  if (thick_frac(n) < dzero .or. thick_frac(n) > baq) then
1309  write (errmsg, '(a,g0,2(a,1x),g0,1x,a,1x,i0,a)') &
1310  'THICK (', thick_frac(n), ') MUST BE greater than or equal to 0 ', &
1311  'and less than or equal to than', baq, &
1312  'for packagedata entry', csubno, '.'
1313  call store_error(errmsg)
1314  end if
1315  thick = thick_frac(n)
1316  else
1317  if (thick_frac(n) < dzero .or. thick_frac(n) > done) then
1318  write (errmsg, '(a,1x,a,1x,i0,a)') &
1319  'FRAC MUST BE greater than 0 and less than or equal to 1', &
1320  'for packagedata entry', csubno, '.'
1321  call store_error(errmsg)
1322  end if
1323  thick = thick_frac(n) * baq
1324  end if
1325  this%thickini(csubno) = thick
1326  if (this%iupdatematprop /= 0) then
1327  this%thick(csubno) = thick
1328  end if
1329 
1330  ! -- set rnb
1331  if (idelay > 0) then
1332  if (rnb(n) < done) then
1333  write (errmsg, '(a,g0,a,1x,a,1x,i0,a)') &
1334  'RNB (', rnb(n), ') must be greater than or equal to 1', &
1335  'for packagedata entry', csubno, '.'
1336  call store_error(errmsg)
1337  end if
1338  this%rnb(csubno) = rnb(n)
1339  else
1340  this%rnb(csubno) = done
1341  end if
1342 
1343  ! -- set skv or ci
1344  if (ssv_cc(n) < dzero) then
1345  write (errmsg, '(2(a,1x),i0,a)') &
1346  '(SKV,CI) must be greater than or equal to 0', &
1347  'for packagedata entry', csubno, '.'
1348  call store_error(errmsg)
1349  end if
1350  this%ci(csubno) = ssv_cc(n)
1351 
1352  ! -- set ske or rci
1353  if (sse_cr(n) < dzero) then
1354  write (errmsg, '(2(a,1x),i0,a)') &
1355  '(SKE,RCI) must be greater than or equal to 0', &
1356  'for packagedata entry', csubno, '.'
1357  call store_error(errmsg)
1358  end if
1359  this%rci(csubno) = sse_cr(n)
1360 
1361  ! -- set ielastic
1362  if (this%ci(csubno) == this%rci(csubno)) then
1363  this%ielastic(csubno) = 1
1364  else
1365  this%ielastic(csubno) = 0
1366  end if
1367 
1368  ! -- set porosity
1369  if (theta(n) <= dzero .or. theta(n) > done) then
1370  write (errmsg, '(a,1x,a,1x,i0,a)') &
1371  'THETA must be greater than 0 and less than or equal to 1', &
1372  'for packagedata entry', csubno, '.'
1373  call store_error(errmsg)
1374  end if
1375  this%thetaini(csubno) = theta(n)
1376  if (this%iupdatematprop /= 0) then
1377  this%theta(csubno) = theta(n)
1378  end if
1379 
1380  ! -- set kv
1381  if (idelay > 0) then
1382  if (kv(n) <= 0.0) then
1383  write (errmsg, '(a,1x,i0,a)') &
1384  'KV must be greater than 0 for packagedata entry', csubno, '.'
1385  call store_error(errmsg)
1386  end if
1387  end if
1388  this%kv(csubno) = kv(n)
1389 
1390  ! -- set h0
1391  this%h0(csubno) = h0(n)
1392 
1393  ! -- set bound name
1394  if (this%inamedbound /= 0) then
1395  bndname = boundname(n)
1396  if (len_trim(bndname) < 1) then
1397  write (errmsg, '(a,1x,i0,a)') &
1398  'BOUNDNAME must be specified for packagedata entry', csubno, '.'
1399  call store_error(errmsg)
1400  end if
1401  this%boundname(csubno) = bndname
1402  end if
1403  end do
1404 
1405  !
1406  ! -- set the number of delay interbeds
1407  this%ndelaybeds = ndelaybeds
1408  !
1409  ! -- process delay interbeds
1410  if (ndelaybeds > 0) then
1411  !
1412  ! -- reallocate and initialize delay interbed arrays
1413  call mem_allocate(this%idb_nconv_count, 2, &
1414  'IDB_NCONV_COUNT', trim(this%memoryPath))
1415  call mem_allocate(this%idbconvert, this%ndelaycells, ndelaybeds, &
1416  'IDBCONVERT', trim(this%memoryPath))
1417  call mem_allocate(this%dbdhmax, ndelaybeds, &
1418  'DBDHMAX', trim(this%memoryPath))
1419  call mem_allocate(this%dbz, this%ndelaycells, ndelaybeds, &
1420  'DBZ', trim(this%memoryPath))
1421  call mem_allocate(this%dbrelz, this%ndelaycells, ndelaybeds, &
1422  'DBRELZ', trim(this%memoryPath))
1423  call mem_allocate(this%dbh, this%ndelaycells, ndelaybeds, &
1424  'DBH', trim(this%memoryPath))
1425  call mem_allocate(this%dbh0, this%ndelaycells, ndelaybeds, &
1426  'DBH0', trim(this%memoryPath))
1427  call mem_allocate(this%dbgeo, this%ndelaycells, ndelaybeds, &
1428  'DBGEO', trim(this%memoryPath))
1429  call mem_allocate(this%dbes, this%ndelaycells, ndelaybeds, &
1430  'DBES', trim(this%memoryPath))
1431  call mem_allocate(this%dbes0, this%ndelaycells, ndelaybeds, &
1432  'DBES0', trim(this%memoryPath))
1433  call mem_allocate(this%dbpcs, this%ndelaycells, ndelaybeds, &
1434  'DBPCS', trim(this%memoryPath))
1435  call mem_allocate(this%dbflowtop, ndelaybeds, &
1436  'DBFLOWTOP', trim(this%memoryPath))
1437  call mem_allocate(this%dbflowbot, ndelaybeds, &
1438  'DBFLOWBOT', trim(this%memoryPath))
1439  call mem_allocate(this%dbdzini, this%ndelaycells, ndelaybeds, &
1440  'DBDZINI', trim(this%memoryPath))
1441  call mem_allocate(this%dbthetaini, this%ndelaycells, ndelaybeds, &
1442  'DBTHETAINI', trim(this%memoryPath))
1443  call mem_allocate(this%dbcomp, this%ndelaycells, ndelaybeds, &
1444  'DBCOMP', trim(this%memoryPath))
1445  call mem_allocate(this%dbtcomp, this%ndelaycells, ndelaybeds, &
1446  'DBTCOMP', trim(this%memoryPath))
1447  !
1448  ! -- allocate delay bed arrays
1449  if (this%iupdatematprop == 0) then
1450  call mem_setptr(this%dbdz, 'DBDZINI', trim(this%memoryPath))
1451  call mem_setptr(this%dbdz0, 'DBDZINI', trim(this%memoryPath))
1452  call mem_setptr(this%dbtheta, 'DBTHETAINI', trim(this%memoryPath))
1453  call mem_setptr(this%dbtheta0, 'DBTHETAINI', trim(this%memoryPath))
1454  else
1455  call mem_allocate(this%dbdz, this%ndelaycells, ndelaybeds, &
1456  'DBDZ', trim(this%memoryPath))
1457  call mem_allocate(this%dbdz0, this%ndelaycells, ndelaybeds, &
1458  'DBDZ0', trim(this%memoryPath))
1459  call mem_allocate(this%dbtheta, this%ndelaycells, ndelaybeds, &
1460  'DBTHETA', trim(this%memoryPath))
1461  call mem_allocate(this%dbtheta0, this%ndelaycells, ndelaybeds, &
1462  'DBTHETA0', trim(this%memoryPath))
1463  end if
1464  !
1465  ! -- allocate delay interbed solution arrays
1466  call mem_allocate(this%dbal, this%ndelaycells, &
1467  'DBAL', trim(this%memoryPath))
1468  call mem_allocate(this%dbad, this%ndelaycells, &
1469  'DBAD', trim(this%memoryPath))
1470  call mem_allocate(this%dbau, this%ndelaycells, &
1471  'DBAU', trim(this%memoryPath))
1472  call mem_allocate(this%dbrhs, this%ndelaycells, &
1473  'DBRHS', trim(this%memoryPath))
1474  call mem_allocate(this%dbdh, this%ndelaycells, &
1475  'DBDH', trim(this%memoryPath))
1476  call mem_allocate(this%dbaw, this%ndelaycells, &
1477  'DBAW', trim(this%memoryPath))
1478  !
1479  ! -- initialize delay bed counters
1480  do n = 1, 2
1481  this%idb_nconv_count(n) = 0
1482  end do
1483  !
1484  ! -- initialize delay bed storage
1485  do ib = 1, this%ninterbeds
1486  idelay = this%idelay(ib)
1487  if (idelay == 0) then
1488  cycle
1489  end if
1490  !
1491  ! -- initialize delay interbed variables
1492  do n = 1, this%ndelaycells
1493  rval = this%thickini(ib) / real(this%ndelaycells, dp)
1494  this%dbdzini(n, idelay) = rval
1495  this%dbh(n, idelay) = this%h0(ib)
1496  this%dbh0(n, idelay) = this%h0(ib)
1497  this%dbthetaini(n, idelay) = this%thetaini(ib)
1498  this%dbgeo(n, idelay) = dzero
1499  this%dbes(n, idelay) = dzero
1500  this%dbes0(n, idelay) = dzero
1501  this%dbpcs(n, idelay) = this%pcs(ib)
1502  this%dbcomp(n, idelay) = dzero
1503  this%dbtcomp(n, idelay) = dzero
1504  if (this%iupdatematprop /= 0) then
1505  this%dbdz(n, idelay) = this%dbdzini(n, idelay)
1506  this%dbdz0(n, idelay) = this%dbdzini(n, idelay)
1507  this%dbtheta(n, idelay) = this%theta(ib)
1508  this%dbtheta0(n, idelay) = this%theta(ib)
1509  end if
1510  end do
1511  !
1512  ! -- initialize elevation of delay bed cells
1513  call this%csub_delay_init_zcell(ib)
1514  end do
1515  !
1516  ! -- initialize delay bed solution arrays
1517  do n = 1, this%ndelaycells
1518  this%dbal(n) = dzero
1519  this%dbad(n) = dzero
1520  this%dbau(n) = dzero
1521  this%dbrhs(n) = dzero
1522  this%dbdh(n) = dzero
1523  this%dbaw(n) = dzero
1524  end do
1525  end if
1526  !
1527  ! -- check that ndelaycells is odd when using
1528  ! the effective stress formulation
1529  if (ndelaybeds > 0) then
1530  q = mod(real(this%ndelaycells, dp), dtwo)
1531  if (q == dzero) then
1532  write (errmsg, '(a,i0,a,1x,a)') &
1533  'NDELAYCELLS (', this%ndelaycells, ') must be an', &
1534  'odd number when using the effective stress formulation.'
1535  call store_error(errmsg)
1536  end if
1537  end if
1538 
1539  if (this%iprpak /= 0) then
1540  call this%csub_print_packagedata()
1541  end if
1542 
1543  ! -- terminate if errors encountered
1544  if (count_errors() > 0) then
1545  call store_error_filename(this%input_fname)
1546  end if
1547  end subroutine csub_source_packagedata
1548 
1549  !> @ brief Print packagedata
1550  !<
1551  subroutine csub_print_packagedata(this)
1552  class(gwfcsubtype) :: this
1553  ! local
1554  character(len=LINELENGTH) :: title
1555  character(len=LINELENGTH) :: tag
1556  character(len=10) :: ctype
1557  character(len=20) :: cellid
1558  integer(I4B) :: ntabrows
1559  integer(I4B) :: ntabcols
1560  integer(I4B) :: ib
1561  integer(I4b) :: idelay
1562  integer(I4B) :: node
1563 
1564  ! set title
1565  title = 'CSUB'//' PACKAGE ('// &
1566  trim(adjustl(this%packName))//') INTERBED DATA'
1567  !
1568  ! determine the number of columns and rows
1569  ntabrows = this%ninterbeds
1570  ntabcols = 13
1571  if (this%inamedbound /= 0) then
1572  ntabcols = ntabcols + 1
1573  end if
1574 
1575  ! setup table
1576  call table_cr(this%inputtab, this%packName, title)
1577  call this%inputtab%table_df(ntabrows, ntabcols, this%iout)
1578  !
1579  ! add columns
1580  !<icsubno> <cellid> <cdelay> <pcs0> <thick_frac> <rnb> <ssv_cc> <sse_cr> <theta> <kv> <h0> [<boundname>]
1581 
1582  tag = 'INTERBED NUMBER'
1583  call this%inputtab%initialize_column(tag, 10, alignment=tabcenter)
1584  tag = 'CELLID'
1585  call this%inputtab%initialize_column(tag, 20, alignment=tableft)
1586  tag = 'INTERBED TYPE'
1587  call this%inputtab%initialize_column(tag, 10, alignment=tabcenter)
1588  tag = 'PCS0'
1589  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1590  tag = 'THICK_FRAC'
1591  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1592  tag = 'RNB'
1593  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1594  tag = 'INTERBED THICKNESS'
1595  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1596  tag = 'CELL THICKNESS'
1597  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1598  tag = 'SSV_CV'
1599  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1600  tag = 'SSE_CR'
1601  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1602  tag = 'THETA'
1603  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1604  tag = 'KV'
1605  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1606  tag = 'H0'
1607  call this%inputtab%initialize_column(tag, 12, alignment=tabcenter)
1608  if (this%inamedbound /= 0) then
1609  tag = 'BOUNDNAME'
1610  call this%inputtab%initialize_column(tag, 40, alignment=tableft)
1611  end if
1612 
1613  do ib = 1, this%ninterbeds
1614  idelay = this%idelay(ib)
1615  node = this%nodelist(ib)
1616  call this%dis%noder_to_string(node, cellid)
1617  if (idelay == 0) then
1618  ctype = 'nodelay'
1619  else
1620  ctype = 'delay'
1621  end if
1622 
1623  ! fill table line
1624  call this%inputtab%add_term(ib)
1625  call this%inputtab%add_term(cellid)
1626  call this%inputtab%add_term(ctype)
1627  call this%inputtab%add_term(this%pcs(ib))
1628  call this%inputtab%add_term(this%thickini(ib))
1629  call this%inputtab%add_term(this%rnb(ib))
1630  call this%inputtab%add_term(this%thickini(ib) * this%rnb(ib))
1631  call this%inputtab%add_term(this%dis%top(node) - this%dis%bot(node))
1632  call this%inputtab%add_term(this%ci(ib))
1633  call this%inputtab%add_term(this%rci(ib))
1634  call this%inputtab%add_term(this%theta(ib))
1635  if (idelay == 0) then
1636  call this%inputtab%add_term("--")
1637  call this%inputtab%add_term("--")
1638  else
1639  call this%inputtab%add_term(this%kv(ib))
1640  call this%inputtab%add_term(this%h0(ib))
1641  end if
1642  if (this%inamedbound /= 0) then
1643  call this%inputtab%add_term(this%boundname(ib))
1644  end if
1645  end do
1646 
1647  end subroutine csub_print_packagedata
1648 
1649  !> @ brief Final processing for package
1650  !!
1651  !! Final processing for the CSUB package. This method generates the final
1652  !! strain tables that are output so that the user can evaluate if calculated
1653  !! strain rates in coarse-grained sediments and interbeds exceed 1 percent.
1654  !!
1655  !<
1656  subroutine csub_fp(this)
1657  ! -- dummy variables
1658  class(gwfcsubtype) :: this
1659  ! -- local variables
1660  character(len=LINELENGTH) :: title
1661  character(len=LINELENGTH) :: tag
1662  character(len=LINELENGTH) :: msg
1663  character(len=10) :: ctype
1664  character(len=20) :: cellid
1665  character(len=10) :: cflag
1666  integer(I4B) :: i
1667  integer(I4B) :: ib
1668  integer(I4B) :: i0
1669  integer(I4B) :: i1
1670  integer(I4B) :: node
1671  integer(I4B) :: nn
1672  integer(I4B) :: idelay
1673  integer(I4B) :: iexceed
1674  integer(I4B), parameter :: ncells = 20
1675  integer(I4B) :: nlen
1676  integer(I4B) :: ntabrows
1677  integer(I4B) :: ntabcols
1678  integer(I4B) :: ipos
1679  real(DP) :: b0
1680  real(DP) :: b1
1681  real(DP) :: strain
1682  real(DP) :: pctcomp
1683  integer(I4B), dimension(:), allocatable :: imap_sel
1684  integer(I4B), dimension(:), allocatable :: locs
1685  real(DP), dimension(:), allocatable :: pctcomp_arr
1686  !
1687  ! -- initialize locs
1688  allocate (locs(this%dis%ndim))
1689  !
1690  ! -- calculate and report strain for interbeds
1691  if (this%ninterbeds > 0) then
1692  nlen = min(ncells, this%ninterbeds)
1693  allocate (imap_sel(nlen))
1694  allocate (pctcomp_arr(this%ninterbeds))
1695  iexceed = 0
1696  do ib = 1, this%ninterbeds
1697  idelay = this%idelay(ib)
1698  b0 = this%thickini(ib)
1699  strain = this%tcomp(ib) / b0
1700  pctcomp = dhundred * strain
1701  pctcomp_arr(ib) = pctcomp
1702  if (pctcomp >= done) then
1703  iexceed = iexceed + 1
1704  end if
1705  end do
1706  call selectn(imap_sel, pctcomp_arr, reverse=.true.)
1707  !
1708  ! -- summary interbed strain table
1709  i0 = max(1, this%ninterbeds - ncells + 1)
1710  i1 = this%ninterbeds
1711  msg = ''
1712  if (iexceed /= 0) then
1713  write (msg, '(1x,a,1x,i0,1x,a,1x,i0,1x,a)') &
1714  'LARGEST', (i1 - i0 + 1), 'OF', this%ninterbeds, &
1715  'INTERBED STRAIN VALUES SHOWN'
1716  call write_message(msg, this%iout, skipbefore=1)
1717  !
1718  ! -- interbed strain data
1719  ! -- set title
1720  title = trim(adjustl(this%packName))//' PACKAGE INTERBED STRAIN SUMMARY'
1721  !
1722  ! -- determine the number of columns and rows
1723  ntabrows = nlen
1724  ntabcols = 9
1725  !
1726  ! -- setup table
1727  call table_cr(this%outputtab, this%packName, title)
1728  call this%outputtab%table_df(ntabrows, ntabcols, this%iout)
1729  !
1730  ! add columns
1731  tag = 'INTERBED NUMBER'
1732  call this%outputtab%initialize_column(tag, 10, alignment=tabcenter)
1733  tag = 'INTERBED TYPE'
1734  call this%outputtab%initialize_column(tag, 10, alignment=tabcenter)
1735  tag = 'CELLID'
1736  call this%outputtab%initialize_column(tag, 20, alignment=tableft)
1737  tag = 'INITIAL THICKNESS'
1738  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1739  tag = 'FINAL THICKNESS'
1740  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1741  tag = 'TOTAL COMPACTION'
1742  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1743  tag = 'FINAL STRAIN'
1744  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1745  tag = 'PERCENT COMPACTION'
1746  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1747  tag = 'FLAG'
1748  call this%outputtab%initialize_column(tag, 10, alignment=tabcenter)
1749  !
1750  ! -- write data
1751  do i = 1, nlen
1752  ib = imap_sel(i)
1753  idelay = this%idelay(ib)
1754  b0 = this%thickini(ib)
1755  b1 = this%csub_calc_interbed_thickness(ib)
1756  if (idelay == 0) then
1757  ctype = 'no-delay'
1758  else
1759  ctype = 'delay'
1760  b0 = b0 * this%rnb(ib)
1761  end if
1762  strain = this%tcomp(ib) / b0
1763  pctcomp = dhundred * strain
1764  if (pctcomp >= 5.0_dp) then
1765  cflag = '**>=5%'
1766  else if (pctcomp >= done) then
1767  cflag = '*>=1%'
1768  else
1769  cflag = ''
1770  end if
1771  node = this%nodelist(ib)
1772  call this%dis%noder_to_string(node, cellid)
1773  !
1774  ! -- fill table line
1775  call this%outputtab%add_term(ib)
1776  call this%outputtab%add_term(ctype)
1777  call this%outputtab%add_term(cellid)
1778  call this%outputtab%add_term(b0)
1779  call this%outputtab%add_term(b1)
1780  call this%outputtab%add_term(this%tcomp(ib))
1781  call this%outputtab%add_term(strain)
1782  call this%outputtab%add_term(pctcomp)
1783  call this%outputtab%add_term(cflag)
1784  end do
1785  write (this%iout, '(/1X,A,1X,I0,1X,A,1X,I0,1X,A,/1X,A,/1X,A)') &
1786  'PERCENT COMPACTION IS GREATER THAN OR EQUAL TO 1 PERCENT IN', &
1787  iexceed, 'OF', this%ninterbeds, 'INTERBED(S).', &
1788  'USE THE STRAIN_CSV_INTERBED OPTION TO OUTPUT A CSV '// &
1789  'FILE WITH PERCENT COMPACTION ', 'VALUES FOR ALL INTERBEDS.'
1790  else
1791  msg = 'PERCENT COMPACTION WAS LESS THAN 1 PERCENT IN ALL INTERBEDS'
1792  write (this%iout, '(/1X,A)') trim(adjustl(msg))
1793  end if
1794  !
1795  ! -- write csv file
1796  if (this%istrainib /= 0) then
1797  !
1798  ! -- determine the number of columns and rows
1799  ntabrows = this%ninterbeds
1800  ntabcols = 7
1801  if (this%dis%ndim > 1) then
1802  ntabcols = ntabcols + 1
1803  end if
1804  ntabcols = ntabcols + this%dis%ndim
1805  !
1806  ! -- setup table
1807  call table_cr(this%outputtab, this%packName, '')
1808  call this%outputtab%table_df(ntabrows, ntabcols, this%istrainib, &
1809  lineseparator=.false., separator=',')
1810  !
1811  ! add columns
1812  tag = 'INTERBED_NUMBER'
1813  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1814  tag = 'INTERBED_TYPE'
1815  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1816  tag = 'NODE'
1817  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1818  if (this%dis%ndim == 2) then
1819  tag = 'LAYER'
1820  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1821  tag = 'ICELL2D'
1822  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1823  else
1824  tag = 'LAYER'
1825  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1826  tag = 'ROW'
1827  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1828  tag = 'COLUMN'
1829  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1830  end if
1831  tag = 'INITIAL_THICKNESS'
1832  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1833  tag = 'FINAL_THICKNESS'
1834  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1835  tag = 'TOTAL_COMPACTION'
1836  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1837  tag = 'TOTAL_STRAIN'
1838  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1839  tag = 'PERCENT_COMPACTION'
1840  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
1841  !
1842  ! -- write data
1843  do ib = 1, this%ninterbeds
1844  idelay = this%idelay(ib)
1845  b0 = this%thickini(ib)
1846  b1 = this%csub_calc_interbed_thickness(ib)
1847  if (idelay == 0) then
1848  ctype = 'no-delay'
1849  else
1850  ctype = 'delay'
1851  b0 = b0 * this%rnb(ib)
1852  end if
1853  strain = this%tcomp(ib) / b0
1854  pctcomp = dhundred * strain
1855  node = this%nodelist(ib)
1856  call this%dis%noder_to_array(node, locs)
1857  !
1858  ! -- fill table line
1859  call this%outputtab%add_term(ib)
1860  call this%outputtab%add_term(ctype)
1861  if (this%dis%ndim > 1) then
1862  call this%outputtab%add_term(this%dis%get_nodeuser(node))
1863  end if
1864  do ipos = 1, this%dis%ndim
1865  call this%outputtab%add_term(locs(ipos))
1866  end do
1867  call this%outputtab%add_term(b0)
1868  call this%outputtab%add_term(b1)
1869  call this%outputtab%add_term(this%tcomp(ib))
1870  call this%outputtab%add_term(strain)
1871  call this%outputtab%add_term(pctcomp)
1872  end do
1873  end if
1874  !
1875  ! -- deallocate temporary storage
1876  deallocate (imap_sel)
1877  deallocate (pctcomp_arr)
1878  end if
1879  !
1880  ! -- calculate and report strain for coarse-grained materials
1881  nlen = min(ncells, this%dis%nodes)
1882  allocate (imap_sel(nlen))
1883  allocate (pctcomp_arr(this%dis%nodes))
1884  iexceed = 0
1885  do node = 1, this%dis%nodes
1886  strain = dzero
1887  if (this%cg_thickini(node) > dzero) then
1888  strain = this%cg_tcomp(node) / this%cg_thickini(node)
1889  end if
1890  pctcomp = dhundred * strain
1891  pctcomp_arr(node) = pctcomp
1892  if (pctcomp >= done) then
1893  iexceed = iexceed + 1
1894  end if
1895  end do
1896  call selectn(imap_sel, pctcomp_arr, reverse=.true.)
1897  !
1898  ! -- summary coarse-grained strain table
1899  i0 = max(1, this%dis%nodes - ncells + 1)
1900  i1 = this%dis%nodes
1901  msg = ''
1902  if (iexceed /= 0) then
1903  write (msg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1904  'LARGEST ', (i1 - i0 + 1), 'OF', this%dis%nodes, &
1905  'CELL COARSE-GRAINED VALUES SHOWN'
1906  call write_message(msg, this%iout, skipbefore=1)
1907  !
1908  ! -- set title
1909  title = trim(adjustl(this%packName))// &
1910  ' PACKAGE COARSE-GRAINED STRAIN SUMMARY'
1911  !
1912  ! -- determine the number of columns and rows
1913  ntabrows = nlen
1914  ntabcols = 7
1915  !
1916  ! -- setup table
1917  call table_cr(this%outputtab, this%packName, title)
1918  call this%outputtab%table_df(ntabrows, ntabcols, this%iout)
1919  !
1920  ! add columns
1921  tag = 'CELLID'
1922  call this%outputtab%initialize_column(tag, 20, alignment=tableft)
1923  tag = 'INITIAL THICKNESS'
1924  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1925  tag = 'FINAL THICKNESS'
1926  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1927  tag = 'TOTAL COMPACTION'
1928  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1929  tag = 'FINAL STRAIN'
1930  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1931  tag = 'PERCENT COMPACTION'
1932  call this%outputtab%initialize_column(tag, 12, alignment=tabcenter)
1933  tag = 'FLAG'
1934  call this%outputtab%initialize_column(tag, 10, alignment=tabcenter)
1935  ! -- write data
1936  do nn = 1, nlen
1937  node = imap_sel(nn)
1938  if (this%cg_thickini(node) > dzero) then
1939  strain = this%cg_tcomp(node) / this%cg_thickini(node)
1940  else
1941  strain = dzero
1942  end if
1943  pctcomp = dhundred * strain
1944  if (pctcomp >= 5.0_dp) then
1945  cflag = '**>=5%'
1946  else if (pctcomp >= done) then
1947  cflag = '*>=1%'
1948  else
1949  cflag = ''
1950  end if
1951  call this%dis%noder_to_string(node, cellid)
1952  !
1953  ! -- fill table line
1954  call this%outputtab%add_term(cellid)
1955  call this%outputtab%add_term(this%cg_thickini(node))
1956  call this%outputtab%add_term(this%cg_thick(node))
1957  call this%outputtab%add_term(this%cg_tcomp(node))
1958  call this%outputtab%add_term(strain)
1959  call this%outputtab%add_term(pctcomp)
1960  call this%outputtab%add_term(cflag)
1961  end do
1962  write (this%iout, '(/1X,A,1X,I0,1X,A,1X,I0,1X,A,/1X,A,/1X,A)') &
1963  'COARSE-GRAINED STORAGE PERCENT COMPACTION IS GREATER THAN OR '// &
1964  'EQUAL TO 1 PERCENT IN', iexceed, 'OF', this%dis%nodes, 'CELL(S).', &
1965  'USE THE STRAIN_CSV_COARSE OPTION TO OUTPUT A CSV '// &
1966  'FILE WITH PERCENT COMPACTION ', 'VALUES FOR ALL CELLS.'
1967  else
1968  msg = 'COARSE-GRAINED STORAGE PERCENT COMPACTION WAS LESS THAN '// &
1969  '1 PERCENT IN ALL CELLS '
1970  write (this%iout, '(/1X,A)') trim(adjustl(msg))
1971  end if
1972  !
1973  ! -- write csv file
1974  if (this%istrainsk /= 0) then
1975  !
1976  ! -- determine the number of columns and rows
1977  ntabrows = this%dis%nodes
1978  ntabcols = 5
1979  if (this%dis%ndim > 1) then
1980  ntabcols = ntabcols + 1
1981  end if
1982  ntabcols = ntabcols + this%dis%ndim
1983  !
1984  ! -- setup table
1985  call table_cr(this%outputtab, this%packName, '')
1986  call this%outputtab%table_df(ntabrows, ntabcols, this%istrainsk, &
1987  lineseparator=.false., separator=',')
1988  !
1989  ! add columns
1990  tag = 'NODE'
1991  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1992  if (this%dis%ndim == 2) then
1993  tag = 'LAYER'
1994  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1995  tag = 'ICELL2D'
1996  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
1997  else
1998  tag = 'LAYER'
1999  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
2000  tag = 'ROW'
2001  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
2002  tag = 'COLUMN'
2003  call this%outputtab%initialize_column(tag, 10, alignment=tabright)
2004  end if
2005  tag = 'INITIAL_THICKNESS'
2006  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
2007  tag = 'FINAL_THICKNESS'
2008  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
2009  tag = 'TOTAL_COMPACTION'
2010  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
2011  tag = 'TOTAL_STRAIN'
2012  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
2013  tag = 'PERCENT_COMPACTION'
2014  call this%outputtab%initialize_column(tag, 20, alignment=tabright)
2015  !
2016  ! -- write data
2017  do node = 1, this%dis%nodes
2018  if (this%cg_thickini(node) > dzero) then
2019  strain = this%cg_tcomp(node) / this%cg_thickini(node)
2020  else
2021  strain = dzero
2022  end if
2023  pctcomp = dhundred * strain
2024  call this%dis%noder_to_array(node, locs)
2025  !
2026  ! -- fill table line
2027  if (this%dis%ndim > 1) then
2028  call this%outputtab%add_term(this%dis%get_nodeuser(node))
2029  end if
2030  do ipos = 1, this%dis%ndim
2031  call this%outputtab%add_term(locs(ipos))
2032  end do
2033  call this%outputtab%add_term(this%cg_thickini(node))
2034  call this%outputtab%add_term(this%cg_thick(node))
2035  call this%outputtab%add_term(this%cg_tcomp(node))
2036  call this%outputtab%add_term(strain)
2037  call this%outputtab%add_term(pctcomp)
2038  end do
2039  end if
2040  !
2041  ! -- write a warning message for delay interbeds in non-convertible gwf
2042  ! cells that violate minimum head assumptions
2043  if (this%ndelaybeds > 0) then
2044  if (this%idb_nconv_count(2) > 0) then
2045  write (warnmsg, '(a,1x,a,1x,i0,1x,a,1x,a)') &
2046  'Delay interbed cell heads were less than the top of the interbed', &
2047  'cell in', this%idb_nconv_count(2), 'interbed cells in ', &
2048  'non-convertible GWF cells for at least one time step during '// &
2049  'the simulation.'
2050  call store_warning(warnmsg)
2051  end if
2052  end if
2053  !
2054  ! -- deallocate temporary storage
2055  deallocate (imap_sel)
2056  deallocate (locs)
2057  deallocate (pctcomp_arr)
2058  end subroutine csub_fp
2059 
2060  !> @ brief Deallocate package memory
2061  !!
2062  !! Deallocate CSUB package scalars and arrays.
2063  !!
2064  !<
2065  subroutine csub_da(this)
2066  ! -- modules
2068  ! -- dummy variables
2069  class(gwfcsubtype) :: this
2070  !
2071  ! -- Deallocate arrays if package is active
2072  if (this%inunit > 0) then
2073  call mem_deallocate(this%unodelist)
2074  call mem_deallocate(this%nodelist)
2075  call mem_deallocate(this%idelay)
2076  call mem_deallocate(this%ielastic)
2077  call mem_deallocate(this%iconvert)
2078  !
2079  ! -- grid-based storage data
2080  call mem_deallocate(this%buff)
2081  call mem_deallocate(this%buffusr)
2082  call mem_deallocate(this%sgm)
2083  call mem_deallocate(this%sgs)
2084  call mem_deallocate(this%cg_ske_cr)
2085  call mem_deallocate(this%cg_gs)
2086  call mem_deallocate(this%cg_es)
2087  call mem_deallocate(this%cg_es0)
2088  call mem_deallocate(this%cg_pcs)
2089  call mem_deallocate(this%cg_comp)
2090  call mem_deallocate(this%cg_tcomp)
2091  call mem_deallocate(this%cg_stor)
2092  call mem_deallocate(this%cg_ske)
2093  call mem_deallocate(this%cg_sk)
2094  if (this%iupdatematprop == 0) then
2095  nullify (this%cg_thick)
2096  nullify (this%cg_thick0)
2097  nullify (this%cg_theta)
2098  nullify (this%cg_theta0)
2099  else
2100  call mem_deallocate(this%cg_thick)
2101  call mem_deallocate(this%cg_thick0)
2102  call mem_deallocate(this%cg_theta)
2103  call mem_deallocate(this%cg_theta0)
2104  end if
2105  call mem_deallocate(this%cg_thickini)
2106  call mem_deallocate(this%cg_thetaini)
2107  !
2108  ! -- cell storage
2109  call mem_deallocate(this%cell_wcstor)
2110  call mem_deallocate(this%cell_thick)
2111  !
2112  ! -- interbed storage
2113  call mem_deallocate(this%boundname, 'BOUNDNAME', this%memoryPath)
2114  call mem_deallocate(this%auxname, 'AUXNAME', this%memoryPath)
2115  call mem_deallocate(this%auxvar)
2116  call mem_deallocate(this%ci)
2117  call mem_deallocate(this%rci)
2118  call mem_deallocate(this%pcs)
2119  call mem_deallocate(this%rnb)
2120  call mem_deallocate(this%kv)
2121  call mem_deallocate(this%h0)
2122  call mem_deallocate(this%comp)
2123  call mem_deallocate(this%tcomp)
2124  call mem_deallocate(this%tcompi)
2125  call mem_deallocate(this%tcompe)
2126  call mem_deallocate(this%storagee)
2127  call mem_deallocate(this%storagei)
2128  call mem_deallocate(this%ske)
2129  call mem_deallocate(this%sk)
2130  if (this%iupdatematprop == 0) then
2131  nullify (this%thick)
2132  nullify (this%thick0)
2133  nullify (this%theta)
2134  nullify (this%theta0)
2135  else
2136  call mem_deallocate(this%thick)
2137  call mem_deallocate(this%thick0)
2138  call mem_deallocate(this%theta)
2139  call mem_deallocate(this%theta0)
2140  end if
2141  call mem_deallocate(this%thickini)
2142  call mem_deallocate(this%thetaini)
2143  !
2144  ! -- delay bed storage
2145  if (this%ndelaybeds > 0) then
2146  if (this%iupdatematprop == 0) then
2147  nullify (this%dbdz)
2148  nullify (this%dbdz0)
2149  nullify (this%dbtheta)
2150  nullify (this%dbtheta0)
2151  else
2152  call mem_deallocate(this%dbdz)
2153  call mem_deallocate(this%dbdz0)
2154  call mem_deallocate(this%dbtheta)
2155  call mem_deallocate(this%dbtheta0)
2156  end if
2157  call mem_deallocate(this%idb_nconv_count)
2158  call mem_deallocate(this%idbconvert)
2159  call mem_deallocate(this%dbdhmax)
2160  call mem_deallocate(this%dbz)
2161  call mem_deallocate(this%dbrelz)
2162  call mem_deallocate(this%dbh)
2163  call mem_deallocate(this%dbh0)
2164  call mem_deallocate(this%dbgeo)
2165  call mem_deallocate(this%dbes)
2166  call mem_deallocate(this%dbes0)
2167  call mem_deallocate(this%dbpcs)
2168  call mem_deallocate(this%dbflowtop)
2169  call mem_deallocate(this%dbflowbot)
2170  call mem_deallocate(this%dbdzini)
2171  call mem_deallocate(this%dbthetaini)
2172  call mem_deallocate(this%dbcomp)
2173  call mem_deallocate(this%dbtcomp)
2174  !
2175  ! -- delay interbed solution arrays
2176  call mem_deallocate(this%dbal)
2177  call mem_deallocate(this%dbad)
2178  call mem_deallocate(this%dbau)
2179  call mem_deallocate(this%dbrhs)
2180  call mem_deallocate(this%dbdh)
2181  call mem_deallocate(this%dbaw)
2182  end if
2183  !
2184  ! -- period data
2185  call mem_deallocate(this%nodelistsig0)
2186  call mem_deallocate(this%sig0, 'SIG0', this%memoryPath)
2187  !
2188  ! -- pointers to gwf variables
2189  nullify (this%gwfiss)
2190  !
2191  ! -- pointers to storage variables
2192  nullify (this%stoiconv)
2193  nullify (this%stoss)
2194  !
2195  ! -- input table
2196  if (this%iprpak > 0) then
2197  call this%inputtab%table_da()
2198  deallocate (this%inputtab)
2199  nullify (this%inputtab)
2200  end if
2201  !
2202  ! -- output table
2203  if (associated(this%outputtab)) then
2204  call this%outputtab%table_da()
2205  deallocate (this%outputtab)
2206  nullify (this%outputtab)
2207  end if
2208  end if
2209  !
2210  ! -- package csv table
2211  if (this%ipakcsv > 0) then
2212  call this%pakcsvtab%table_da()
2213  deallocate (this%pakcsvtab)
2214  nullify (this%pakcsvtab)
2215  end if
2216  !
2217  ! -- deallocate character variables
2218  call mem_deallocate(this%listlabel, 'LISTLABEL', this%memoryPath)
2219  call mem_deallocate(this%stoMemPath, 'STONAME', this%memoryPath)
2220  !
2221  ! -- deallocate scalars
2222  call mem_deallocate(this%istounit)
2223  call mem_deallocate(this%inobspkg)
2224  call mem_deallocate(this%ninterbeds)
2225  call mem_deallocate(this%maxsig0)
2226  call mem_deallocate(this%nbound)
2227  call mem_deallocate(this%iscloc)
2228  call mem_deallocate(this%iauxmultcol)
2229  call mem_deallocate(this%ndelaycells)
2230  call mem_deallocate(this%ndelaybeds)
2231  call mem_deallocate(this%initialized)
2232  call mem_deallocate(this%ieslag)
2233  call mem_deallocate(this%ipch)
2234  call mem_deallocate(this%lhead_based)
2235  call mem_deallocate(this%iupdatestress)
2236  call mem_deallocate(this%ispecified_pcs)
2237  call mem_deallocate(this%ispecified_dbh)
2238  call mem_deallocate(this%inamedbound)
2239  call mem_deallocate(this%iconvchk)
2240  call mem_deallocate(this%naux)
2241  call mem_deallocate(this%istoragec)
2242  call mem_deallocate(this%istrainib)
2243  call mem_deallocate(this%istrainsk)
2244  call mem_deallocate(this%ioutcomp)
2245  call mem_deallocate(this%ioutcompi)
2246  call mem_deallocate(this%ioutcompe)
2247  call mem_deallocate(this%ioutcompib)
2248  call mem_deallocate(this%ioutcomps)
2249  call mem_deallocate(this%ioutzdisp)
2250  call mem_deallocate(this%ipakcsv)
2251  call mem_deallocate(this%iupdatematprop)
2252  call mem_deallocate(this%epsilon)
2253  call mem_deallocate(this%cc_crit)
2254  call mem_deallocate(this%gammaw)
2255  call mem_deallocate(this%beta)
2256  call mem_deallocate(this%brg)
2257  call mem_deallocate(this%satomega)
2258  call mem_deallocate(this%icellf)
2259  call mem_deallocate(this%gwfiss0)
2260  !
2261  ! -- deallocate methods on objects
2262  if (this%inunit > 0) then
2263  call this%obs%obs_da()
2264  !
2265  ! -- deallocate and nullify observations
2266  deallocate (this%obs)
2267  nullify (this%obs)
2268  end if
2269 
2270  !
2271  ! -- deallocate parent
2272  call this%NumericalPackageType%da()
2273  end subroutine csub_da
2274 
2275  !> @ brief Read and prepare stress period data for package
2276  !!
2277  !! Method reads and prepares stress period data for the CSUB package.
2278  !! The overlying geostatic stress (sig0) is the only stress period data
2279  !! read by the CSUB package.
2280  !!
2281  !<
2282  subroutine csub_rp(this)
2283  ! -- modules
2284  use tdismodule, only: kper
2285  use constantsmodule, only: linelength
2286  use memorymanagermodule, only: mem_setptr
2288  ! -- dummy variables
2289  class(gwfcsubtype), intent(inout) :: this
2290  ! -- local variables
2291  integer(I4B), dimension(:, :), pointer, contiguous :: cellids
2292  integer(I4B), dimension(:), pointer, contiguous :: cellid
2293  integer(I4B), pointer :: iper
2294  integer(I4B) :: n, nodeu, noder
2295  character(len=LINELENGTH) :: title, text
2296  character(len=20) :: cellstr
2297  logical(LGP) :: found
2298  ! -- formats
2299  character(len=*), parameter :: fmtlsp = &
2300  &"(1X,/1X,'REUSING ',a,'S FROM LAST STRESS PERIOD')"
2301 
2302  call mem_setptr(iper, 'IPER', this%input_mempath)
2303  if (iper /= kper) then
2304  write (this%iout, fmtlsp) trim(this%filtyp)
2305  call this%csub_rp_obs()
2306  return
2307  end if
2308 
2309  call mem_setptr(cellids, 'CELLID', this%input_mempath)
2310  call mem_set_value(this%nbound, 'NBOUND', this%input_mempath, &
2311  found)
2312 
2313  ! -- setup table for period data
2314  if (this%iprpak /= 0) then
2315  ! -- reset the input table object
2316  title = 'CSUB'//' PACKAGE ('// &
2317  trim(adjustl(this%packName))//') DATA FOR PERIOD'
2318  write (title, '(a,1x,i6)') trim(adjustl(title)), kper
2319  call table_cr(this%inputtab, this%packName, title)
2320  call this%inputtab%table_df(1, 2, this%iout, finalize=.false.)
2321  text = 'CELLID'
2322  call this%inputtab%initialize_column(text, 20)
2323  text = 'SIG0'
2324  call this%inputtab%initialize_column(text, 15, alignment=tableft)
2325  end if
2326 
2327  ! -- update nodelist
2328  do n = 1, this%nbound
2329 
2330  ! -- set cellid
2331  cellid => cellids(:, n)
2332 
2333  ! -- set user node number
2334  if (this%dis%ndim == 1) then
2335  nodeu = cellid(1)
2336  elseif (this%dis%ndim == 2) then
2337  nodeu = get_node(cellid(1), 1, cellid(2), &
2338  this%dis%mshape(1), 1, &
2339  this%dis%mshape(2))
2340  else
2341  nodeu = get_node(cellid(1), cellid(2), cellid(3), &
2342  this%dis%mshape(1), &
2343  this%dis%mshape(2), &
2344  this%dis%mshape(3))
2345  end if
2346 
2347  ! -- set noder
2348  noder = this%dis%get_nodenumber(nodeu, 1)
2349  if (noder <= 0) then
2350  cycle
2351  end if
2352 
2353  this%nodelistsig0(n) = noder
2354 
2355  ! -- write line to table
2356  if (this%iprpak /= 0) then
2357  call this%dis%noder_to_string(noder, cellstr)
2358  call this%inputtab%add_term(cellstr)
2359  call this%inputtab%add_term(this%sig0(n))
2360  end if
2361  end do
2362  !
2363  ! -- terminate if errors encountered
2364  if (count_errors() > 0) then
2365  call store_error_filename(this%input_fname)
2366  end if
2367  !
2368  ! -- finalize the table
2369  if (this%iprpak /= 0) then
2370  call this%inputtab%finalize_table()
2371  end if
2372  !
2373  ! -- read observations
2374  call this%csub_rp_obs()
2375  end subroutine csub_rp
2376 
2377  !> @ brief Advance the package
2378  !!
2379  !! Advance data in the CSUB package. The method sets data for the previous
2380  !! time step to the current value for the data (e.g., HOLD = HNEW). The
2381  !! method also calls the method to initialize the initial stress conditions
2382  !! if this is the first transient stress period.
2383  !!
2384  !<
2385  subroutine csub_ad(this, nodes, hnew)
2386  ! -- modules
2387  use tdismodule, only: nper, kper
2388  ! -- dummy variables
2389  class(gwfcsubtype) :: this
2390  integer(I4B), intent(in) :: nodes !< number of active model nodes
2391  real(DP), dimension(nodes), intent(in) :: hnew !< current head
2392  ! -- local variables
2393  integer(I4B) :: ib
2394  integer(I4B) :: n
2395  integer(I4B) :: idelay
2396  integer(I4B) :: node
2397  real(DP) :: h
2398  real(DP) :: es
2399  real(DP) :: pcs
2400  !
2401  ! -- evaluate if steady-state stress periods are specified for more
2402  ! than the first and last stress period if interbeds are simulated
2403  if (this%ninterbeds > 0) then
2404  if (kper > 1 .and. kper < nper) then
2405  if (this%gwfiss /= 0) then
2406  write (errmsg, '(a,i0,a,1x,a,1x,a,1x,i0,1x,a)') &
2407  'Only the first and last (', nper, ')', &
2408  'stress period can be steady if interbeds are simulated.', &
2409  'Stress period', kper, 'has been defined to be steady state.'
2410  call store_error(errmsg, terminate=.true.)
2411  end if
2412  end if
2413  end if
2414  !
2415  ! -- set initial states
2416  if (this%initialized == 0) then
2417  if (this%gwfiss == 0) then
2418  call this%csub_set_initial_state(nodes, hnew)
2419  end if
2420  end if
2421  !
2422  ! -- update state variables
2423  !
2424  ! -- coarse-grained materials
2425  do node = 1, nodes
2426  this%cg_comp(node) = dzero
2427  this%cg_es0(node) = this%cg_es(node)
2428  if (this%iupdatematprop /= 0) then
2429  this%cg_thick0(node) = this%cg_thick(node)
2430  this%cg_theta0(node) = this%cg_theta(node)
2431  end if
2432  end do
2433  !
2434  ! -- interbeds
2435  do ib = 1, this%ninterbeds
2436  idelay = this%idelay(ib)
2437  !
2438  ! -- update common terms for no-delay and delay interbeds
2439  this%comp(ib) = dzero
2440  node = this%nodelist(ib)
2441  if (this%initialized /= 0) then
2442  es = this%cg_es(node)
2443  pcs = this%pcs(ib)
2444  if (es > pcs) then
2445  this%pcs(ib) = es
2446  end if
2447  end if
2448  if (this%iupdatematprop /= 0) then
2449  this%thick0(ib) = this%thick(ib)
2450  this%theta0(ib) = this%theta(ib)
2451  end if
2452  !
2453  ! -- update delay interbed terms
2454  if (idelay /= 0) then
2455  !
2456  ! -- update state if previous period was steady state
2457  if (kper > 1) then
2458  if (this%gwfiss0 /= 0) then
2459  node = this%nodelist(ib)
2460  h = hnew(node)
2461  do n = 1, this%ndelaycells
2462  this%dbh(n, idelay) = h
2463  end do
2464  end if
2465  end if
2466  !
2467  ! -- update preconsolidation stress, stresses, head, dbdz0, and theta0
2468  do n = 1, this%ndelaycells
2469  ! update preconsolidation stress
2470  if (this%initialized /= 0) then
2471  if (this%dbes(n, idelay) > this%dbpcs(n, idelay)) then
2472  this%dbpcs(n, idelay) = this%dbes(n, idelay)
2473  end if
2474  end if
2475  this%dbh0(n, idelay) = this%dbh(n, idelay)
2476  this%dbes0(n, idelay) = this%dbes(n, idelay)
2477  if (this%iupdatematprop /= 0) then
2478  this%dbdz0(n, idelay) = this%dbdz(n, idelay)
2479  this%dbtheta0(n, idelay) = this%dbtheta(n, idelay)
2480  end if
2481  end do
2482  end if
2483  end do
2484  !
2485  ! -- set gwfiss0
2486  this%gwfiss0 = this%gwfiss
2487  !
2488  ! -- For each observation, push simulated value and corresponding
2489  ! simulation time from "current" to "preceding" and reset
2490  ! "current" value.
2491  call this%obs%obs_ad()
2492  end subroutine csub_ad
2493 
2494  !> @ brief Fill A and r for the package
2495  !!
2496  !! Fill the coefficient matrix and right-hand side with the CSUB package terms.
2497  !!
2498  !<
2499  subroutine csub_fc(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
2500  ! -- modules
2501  use tdismodule, only: delt
2502  ! -- dummy variables
2503  class(gwfcsubtype) :: this
2504  integer(I4B), intent(in) :: kiter !< outer iteration numbed
2505  real(DP), intent(in), dimension(:) :: hold !< previous heads
2506  real(DP), intent(in), dimension(:) :: hnew !< current heads
2507  class(matrixbasetype), pointer :: matrix_sln !< A matrix
2508  integer(I4B), intent(in), dimension(:) :: idxglo !< global index model to solution
2509  real(DP), intent(inout), dimension(:) :: rhs !< right-hand side
2510  ! -- local variables
2511  integer(I4B) :: ib
2512  integer(I4B) :: node
2513  integer(I4B) :: idiag
2514  integer(I4B) :: idelay
2515  real(DP) :: tled
2516  real(DP) :: area
2517  real(DP) :: hcof
2518  real(DP) :: rhsterm
2519  real(DP) :: comp
2520  !
2521  ! -- update geostatic load calculation
2522  call this%csub_cg_calc_stress(this%dis%nodes, hnew)
2523  !
2524  ! -- formulate csub terms
2525  if (this%gwfiss == 0) then
2526  !
2527  ! -- initialize tled
2528  tled = done / delt
2529  !
2530  ! -- coarse-grained storage
2531  do node = 1, this%dis%nodes
2532  idiag = this%dis%con%ia(node)
2533  area = this%dis%get_area(node)
2534  !
2535  ! -- skip inactive cells
2536  if (this%ibound(node) < 1) cycle
2537  !
2538  ! -- update coarse-grained material properties
2539  if (this%iupdatematprop /= 0) then
2540  if (this%ieslag == 0) then
2541  !
2542  ! -- calculate compaction
2543  call this%csub_cg_calc_comp(node, hnew(node), hold(node), comp)
2544  this%cg_comp(node) = comp
2545  !
2546  ! -- update coarse-grained thickness and void ratio
2547  call this%csub_cg_update(node)
2548  end if
2549  end if
2550  !
2551  ! -- calculate coarse-grained storage terms
2552  call this%csub_cg_fc(node, tled, area, hnew(node), hold(node), &
2553  hcof, rhsterm)
2554  !
2555  ! -- add coarse-grained storage terms to amat and rhs for coarse-grained storage
2556  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2557  rhs(node) = rhs(node) + rhsterm
2558  !
2559  ! -- calculate coarse-grained water compressibility
2560  ! storage terms
2561  if (this%brg /= dzero) then
2562  call this%csub_cg_wcomp_fc(node, tled, area, hnew(node), hold(node), &
2563  hcof, rhsterm)
2564  !
2565  ! -- add water compression storage terms to amat and rhs for
2566  ! coarse-grained storage
2567  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2568  rhs(node) = rhs(node) + rhsterm
2569  end if
2570  end do
2571  !
2572  ! -- interbed storage
2573  if (this%ninterbeds /= 0) then
2574  !
2575  ! -- calculate the contribution of interbeds to the
2576  ! groundwater flow equation
2577  do ib = 1, this%ninterbeds
2578  node = this%nodelist(ib)
2579  idelay = this%idelay(ib)
2580  idiag = this%dis%con%ia(node)
2581  area = this%dis%get_area(node)
2582  call this%csub_interbed_fc(ib, node, area, hnew(node), hold(node), &
2583  hcof, rhsterm)
2584  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2585  rhs(node) = rhs(node) + rhsterm
2586  !
2587  ! -- calculate interbed water compressibility terms
2588  if (.not. is_close(this%brg, dzero) .and. idelay == 0) then
2589  call this%csub_nodelay_wcomp_fc(ib, node, tled, area, &
2590  hnew(node), hold(node), &
2591  hcof, rhsterm)
2592  !
2593  ! -- add water compression storage terms to amat and rhs for interbed
2594  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2595  rhs(node) = rhs(node) + rhsterm
2596  end if
2597  end do
2598  end if
2599  end if
2600  !
2601  ! -- terminate if errors encountered when updating material properties
2602  if (count_errors() > 0) then
2603  call store_error_filename(this%input_fname)
2604  end if
2605  end subroutine csub_fc
2606 
2607  !> @ brief Fill Newton-Raphson terms in A and r for the package
2608  !!
2609  !! Fill the coefficient matrix and right-hand side with CSUB package
2610  !! with Newton-Raphson terms.
2611  !!
2612  !! @param[in,out] amat A matrix
2613  !! @param[in,out] rhs right-hand side
2614  !!
2615  !<
2616  subroutine csub_fn(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
2617  ! -- modules
2618  use tdismodule, only: delt
2619  ! -- dummy variables
2620  class(gwfcsubtype) :: this
2621  integer(I4B), intent(in) :: kiter !< outer iteration number
2622  real(DP), intent(in), dimension(:) :: hold !< previous heads
2623  real(DP), intent(in), dimension(:) :: hnew !< current heads
2624  class(matrixbasetype), pointer :: matrix_sln !< A matrix
2625  integer(I4B), intent(in), dimension(:) :: idxglo !< global index model to solution
2626  real(DP), intent(inout), dimension(:) :: rhs !< right-hand side
2627  ! -- local variables
2628  integer(I4B) :: idelay
2629  integer(I4B) :: node
2630  integer(I4B) :: idiag
2631  integer(I4B) :: ib
2632  real(DP) :: tled
2633  real(DP) :: area
2634  real(DP) :: hcof
2635  real(DP) :: rhsterm
2636  !
2637  ! -- formulate csub terms
2638  if (this%gwfiss == 0) then
2639  tled = done / delt
2640  !
2641  ! -- coarse-grained storage
2642  do node = 1, this%dis%nodes
2643  idiag = this%dis%con%ia(node)
2644  area = this%dis%get_area(node)
2645  !
2646  ! -- skip inactive cells
2647  if (this%ibound(node) < 1) cycle
2648  !
2649  ! -- calculate coarse-grained storage newton terms
2650  call this%csub_cg_fn(node, tled, area, &
2651  hnew(node), hcof, rhsterm)
2652  !
2653  ! -- add coarse-grained storage newton terms to amat and rhs for
2654  ! coarse-grained storage
2655  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2656  rhs(node) = rhs(node) + rhsterm
2657  !
2658  ! -- calculate coarse-grained water compressibility storage
2659  ! newton terms
2660  if (this%brg /= dzero) then
2661  call this%csub_cg_wcomp_fn(node, tled, area, hnew(node), hold(node), &
2662  hcof, rhsterm)
2663  !
2664  ! -- add water compression storage newton terms to amat and rhs for
2665  ! coarse-grained storage
2666  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2667  rhs(node) = rhs(node) + rhsterm
2668  end if
2669  end do
2670  !
2671  ! -- interbed storage
2672  if (this%ninterbeds /= 0) then
2673  !
2674  ! -- calculate the interbed newton terms for the
2675  ! groundwater flow equation
2676  do ib = 1, this%ninterbeds
2677  idelay = this%idelay(ib)
2678  node = this%nodelist(ib)
2679  !
2680  ! -- skip inactive cells
2681  if (this%ibound(node) < 1) cycle
2682  !
2683  ! -- calculate interbed newton terms
2684  idiag = this%dis%con%ia(node)
2685  area = this%dis%get_area(node)
2686  call this%csub_interbed_fn(ib, node, hnew(node), hold(node), &
2687  hcof, rhsterm)
2688  !
2689  ! -- add interbed newton terms to amat and rhs
2690  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2691  rhs(node) = rhs(node) + rhsterm
2692  !
2693  ! -- calculate interbed water compressibility terms
2694  if (this%brg /= dzero .and. idelay == 0) then
2695  call this%csub_nodelay_wcomp_fn(ib, node, tled, area, &
2696  hnew(node), hold(node), &
2697  hcof, rhsterm)
2698  !
2699  ! -- add interbed water compression newton terms to amat and rhs
2700  call matrix_sln%add_value_pos(idxglo(idiag), hcof)
2701  rhs(node) = rhs(node) + rhsterm
2702  end if
2703  end do
2704  end if
2705  end if
2706  end subroutine csub_fn
2707 
2708  !> @ brief Initialize optional tables
2709  !!
2710  !! Subroutine to initialize optional tables. Tables include:
2711  !! o delay interbeds convergence tables
2712  !!
2713  !<
2714  subroutine csub_initialize_tables(this)
2715  class(gwfcsubtype) :: this
2716 
2717  character(len=LINELENGTH) :: tag
2718  integer(I4B) :: ntabrows
2719  integer(I4B) :: ntabcols
2720 
2721  if (this%ipakcsv > 0) then
2722  if (this%ndelaybeds < 1) then
2723  write (warnmsg, '(a,1x,3a)') &
2724  'Package convergence data is requested but delay interbeds', &
2725  'are not included in package (', &
2726  trim(adjustl(this%packName)), ').'
2727  call store_warning(warnmsg)
2728  end if
2729 
2730  ntabrows = 1
2731  ntabcols = 9
2732 
2733  ! setup table
2734  call table_cr(this%pakcsvtab, this%packName, '')
2735  call this%pakcsvtab%table_df(ntabrows, ntabcols, this%ipakcsv, &
2736  lineseparator=.false., separator=',', &
2737  finalize=.false.)
2738 
2739  ! add columns to package csv
2740  tag = 'total_inner_iterations'
2741  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2742  tag = 'totim'
2743  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2744  tag = 'kper'
2745  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2746  tag = 'kstp'
2747  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2748  tag = 'nouter'
2749  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2750  tag = 'dvmax'
2751  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2752  tag = 'dvmax_loc'
2753  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2754  tag = 'dstoragemax'
2755  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2756  tag = 'dstoragemax_loc'
2757  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2758  end if
2759 
2760  end subroutine csub_initialize_tables
2761 
2762  !> @ brief Final convergence check
2763  !!
2764  !! Final convergence check for the CSUB package. The final convergence
2765  !! check is only required when the simulation includes delay interbeds.
2766  !! The final convergence check compares the sum of water contributed
2767  !! by storage and water compressibility in the delay bed to the fluid
2768  !! exchange between the delay interbed and the gwf cell.
2769  !!
2770  !! @param[in,out] cpak string location of the maximum change in csub package
2771  !! @param[in,out] ipak node with the maximum change in csub package
2772  !! @param[in,out] dpak maximum change in csub package
2773  !!
2774  !<
2775  subroutine csub_cc(this, innertot, kiter, iend, icnvgmod, nodes, &
2776  hnew, hold, cpak, ipak, dpak)
2777  ! -- modules
2778  use tdismodule, only: totim, kstp, kper, delt
2779  ! -- dummy variables
2780  class(gwfcsubtype) :: this
2781  integer(I4B), intent(in) :: innertot !< total number of inner iterations
2782  integer(I4B), intent(in) :: kiter !< outer iteration number
2783  integer(I4B), intent(in) :: iend !< flag indicating if it is the last iteration
2784  integer(I4B), intent(in) :: icnvgmod !< flag indicating if the solution is considered converged
2785  integer(I4B), intent(in) :: nodes !< number of active nodes
2786  real(DP), dimension(nodes), intent(in) :: hnew !< current gwf head
2787  real(DP), dimension(nodes), intent(in) :: hold !< gwf for previous time step
2788  character(len=LENPAKLOC), intent(inout) :: cpak !< string location of the maximum change in csub package
2789  integer(I4B), intent(inout) :: ipak !< node with the maximum change in csub package
2790  real(DP), intent(inout) :: dpak !< maximum change in csub package
2791  ! local variables
2792  character(len=LENPAKLOC) :: cloc
2793  integer(I4B) :: icheck
2794  integer(I4B) :: ipakfail
2795  integer(I4B) :: ib
2796  integer(I4B) :: node
2797  integer(I4B) :: idelay
2798  integer(I4B) :: locdhmax
2799  integer(I4B) :: locrmax
2800  integer(I4B) :: ifirst
2801  real(DP) :: dhmax
2802  real(DP) :: rmax
2803  real(DP) :: dh
2804  real(DP) :: area
2805  real(DP) :: hcell
2806  real(DP) :: hcellold
2807  real(DP) :: snnew
2808  real(DP) :: snold
2809  real(DP) :: stoe
2810  real(DP) :: stoi
2811  real(DP) :: dwc
2812  real(DP) :: tled
2813  real(DP) :: hcof
2814  real(DP) :: rhs
2815  real(DP) :: v1
2816  real(DP) :: v2
2817  real(DP) :: df
2818  !
2819  ! -- initialize local variables
2820  icheck = this%iconvchk
2821  ipakfail = 0
2822  locdhmax = 0
2823  locrmax = 0
2824  ifirst = 1
2825  dhmax = dzero
2826  rmax = dzero
2827  !
2828  ! -- additional checks to see if convergence needs to be checked
2829  ! -- no convergence check for steady-state stress periods
2830  if (this%gwfiss /= 0) then
2831  icheck = 0
2832  else
2833  if (icnvgmod == 0) then
2834  icheck = 0
2835  end if
2836  end if
2837  !
2838  ! -- perform package convergence check
2839  if (icheck /= 0) then
2840  if (delt > dzero) then
2841  tled = done / delt
2842  else
2843  tled = dzero
2844  end if
2845  final_check: do ib = 1, this%ninterbeds
2846  idelay = this%idelay(ib)
2847  node = this%nodelist(ib)
2848  !
2849  ! -- skip nodelay interbeds
2850  if (idelay == 0) cycle
2851  !
2852  ! -- skip inactive cells
2853  if (this%ibound(node) < 1) cycle
2854  !
2855  ! -- evaluate the maximum head change in the interbed
2856  dh = this%dbdhmax(idelay)
2857  !
2858  ! -- evaluate difference between storage changes
2859  ! in the interbed and exchange between the interbed
2860  ! and the gwf cell
2861  area = this%dis%get_area(node)
2862  hcell = hnew(node)
2863  hcellold = hold(node)
2864  !
2865  ! -- calculate cell saturation
2866  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
2867  !
2868  ! -- calculate the change in storage
2869  call this%csub_delay_calc_dstor(ib, hcell, stoe, stoi)
2870  v1 = (stoe + stoi) * area * this%rnb(ib) * tled
2871  !
2872  ! -- add water compressibility to storage term
2873  call this%csub_delay_calc_wcomp(ib, dwc)
2874  v1 = v1 + dwc * area * this%rnb(ib)
2875  !
2876  ! -- calculate the flow between the interbed and the cell
2877  call this%csub_delay_fc(ib, hcof, rhs)
2878  v2 = (-hcof * hcell - rhs) * area * this%rnb(ib)
2879  !
2880  ! -- calculate the difference between the interbed change in
2881  ! storage and the flow between the interbed and the cell
2882  df = v2 - v1
2883  !
2884  ! -- normalize by cell area and convert to a depth
2885  df = df * delt / area
2886  !
2887  ! -- evaluate magnitude of differences
2888  if (ifirst == 1) then
2889  ifirst = 0
2890  locdhmax = ib
2891  dhmax = dh
2892  locrmax = ib
2893  rmax = df
2894  else
2895  if (abs(dh) > abs(dhmax)) then
2896  locdhmax = ib
2897  dhmax = dh
2898  end if
2899  if (abs(df) > abs(rmax)) then
2900  locrmax = ib
2901  rmax = df
2902  end if
2903  end if
2904  end do final_check
2905  !
2906  ! -- set dpak and cpak
2907  ! -- update head error
2908  if (abs(dhmax) > abs(dpak)) then
2909  ipak = locdhmax
2910  dpak = dhmax
2911  write (cloc, "(a,'-',a)") trim(this%packName), 'head'
2912  cpak = cloc
2913  end if
2914  !
2915  ! -- update storage error
2916  if (abs(rmax) > abs(dpak)) then
2917  ipak = locrmax
2918  dpak = rmax
2919  write (cloc, "(a,'-',a)") trim(this%packName), 'storage'
2920  cpak = cloc
2921  end if
2922  !
2923  ! -- write convergence data to package csv
2924  if (this%ipakcsv /= 0) then
2925  !
2926  ! -- write the data
2927  call this%pakcsvtab%add_term(innertot)
2928  call this%pakcsvtab%add_term(totim)
2929  call this%pakcsvtab%add_term(kper)
2930  call this%pakcsvtab%add_term(kstp)
2931  call this%pakcsvtab%add_term(kiter)
2932  if (this%ndelaybeds > 0) then
2933  call this%pakcsvtab%add_term(dhmax)
2934  call this%pakcsvtab%add_term(locdhmax)
2935  call this%pakcsvtab%add_term(rmax)
2936  call this%pakcsvtab%add_term(locrmax)
2937  else
2938  call this%pakcsvtab%add_term('--')
2939  call this%pakcsvtab%add_term('--')
2940  call this%pakcsvtab%add_term('--')
2941  call this%pakcsvtab%add_term('--')
2942  end if
2943  !
2944  ! -- finalize the package csv
2945  if (iend == 1) then
2946  call this%pakcsvtab%finalize_table()
2947  end if
2948  end if
2949  end if
2950  end subroutine csub_cc
2951 
2952  !> @ brief Calculate flows for package
2953  !!
2954  !! Flow calculation for the CSUB package components. Components include
2955  !! coarse-grained storage, delay and no-delay interbeds, and water
2956  !! compressibility.
2957  !!
2958  !! @param[in,out] model_budget model budget object
2959  !!
2960  !<
2961  subroutine csub_cq(this, nodes, hnew, hold, isuppress_output, flowja)
2962  ! -- modules
2963  use tdismodule, only: delt
2964  use constantsmodule, only: lenboundname, dzero, done
2965  ! -- dummy variables
2966  class(gwfcsubtype) :: this
2967  integer(I4B), intent(in) :: nodes !< number of active model nodes
2968  real(DP), intent(in), dimension(nodes) :: hnew !< current head
2969  real(DP), intent(in), dimension(nodes) :: hold !< head for the previous time step
2970  integer(I4B), intent(in) :: isuppress_output !< flag indicating if budget output should be suppressed
2971  real(DP), dimension(:), contiguous, intent(inout) :: flowja
2972  ! -- local variables
2973  integer(I4B) :: ib
2974  integer(I4B) :: idelay
2975  integer(I4B) :: ielastic
2976  integer(I4B) :: iconvert
2977  integer(I4B) :: node
2978  integer(I4B) :: nn
2979  integer(I4B) :: n
2980  integer(I4B) :: idiag
2981  real(DP) :: es
2982  real(DP) :: pcs
2983  real(DP) :: rho1
2984  real(DP) :: rho2
2985  real(DP) :: tled
2986  real(DP) :: tledm
2987  real(DP) :: es0
2988  real(DP) :: rrate
2989  real(DP) :: ratein
2990  real(DP) :: rateout
2991  real(DP) :: comp
2992  real(DP) :: compi
2993  real(DP) :: compe
2994  real(DP) :: area
2995  real(DP) :: h
2996  real(DP) :: h0
2997  real(DP) :: snnew
2998  real(DP) :: snold
2999  real(DP) :: hcof
3000  real(DP) :: rhs
3001  real(DP) :: stoe
3002  real(DP) :: stoi
3003  real(DP) :: b
3004  real(DP) :: q
3005  real(DP) :: rratewc
3006  ! -- for observations
3007  integer(I4B) :: iprobslocal
3008  ! -- formats
3009  !
3010  ! -- Suppress saving of simulated values; they
3011  ! will be saved at end of this procedure.
3012  iprobslocal = 0
3013  ratein = dzero
3014  rateout = dzero
3015  !
3016  ! -- coarse-grained coarse-grained storage
3017  do node = 1, this%dis%nodes
3018  idiag = this%dis%con%ia(node)
3019  area = this%dis%get_area(node)
3020  comp = dzero
3021  rrate = dzero
3022  rratewc = dzero
3023  if (this%gwfiss == 0) then
3024  if (delt > dzero) then
3025  tled = done / delt
3026  else
3027  tled = dzero
3028  end if
3029  if (this%ibound(node) > 0 .and. this%cg_thickini(node) > dzero) then
3030  !
3031  ! -- calculate coarse-grained storage terms
3032  call this%csub_cg_fc(node, tled, area, hnew(node), hold(node), &
3033  hcof, rhs)
3034  rrate = hcof * hnew(node) - rhs
3035  !
3036  ! -- calculate compaction
3037  call this%csub_cg_calc_comp(node, hnew(node), hold(node), comp)
3038  !
3039  ! -- calculate coarse-grained water compressibility storage terms
3040  call this%csub_cg_wcomp_fc(node, tled, area, hnew(node), hold(node), &
3041  hcof, rhs)
3042  rratewc = hcof * hnew(node) - rhs
3043  end if
3044  end if
3045  !
3046  ! -- update coarse-grained storage and water
3047  ! compression variables
3048  this%cg_stor(node) = rrate
3049  this%cell_wcstor(node) = rratewc
3050  this%cell_thick(node) = this%cg_thick(node)
3051  !
3052  ! -- update incremental coarse-grained compaction
3053  this%cg_comp(node) = comp
3054  !
3055  !
3056  ! -- update states if required
3057  if (isuppress_output == 0) then
3058  !
3059  ! -- calculate strain and change in coarse-grained void ratio and thickness
3060  ! todo: consider moving error check in csub_cg_update to ot()
3061  if (this%iupdatematprop /= 0) then
3062  call this%csub_cg_update(node)
3063  end if
3064  !
3065  ! -- update total compaction
3066  this%cg_tcomp(node) = this%cg_tcomp(node) + comp
3067  end if
3068  !
3069  ! -- update flowja
3070  flowja(idiag) = flowja(idiag) + rrate
3071  flowja(idiag) = flowja(idiag) + rratewc
3072  end do
3073  !
3074  ! -- interbed storage
3075  !
3076  ! -- reset delay bed counters for the current time step
3077  if (this%ndelaybeds > 0) then
3078  this%idb_nconv_count(1) = 0
3079  end if
3080  !
3081  ! -- initialize tled
3082  tled = done
3083  !
3084  ! -- calculate budget terms for each interbed
3085  do ib = 1, this%ninterbeds
3086  rratewc = dzero
3087  idelay = this%idelay(ib)
3088  ielastic = this%ielastic(ib)
3089  !
3090  ! -- calculate interbed thickness
3091  ! -- no delay interbeds
3092  if (idelay == 0) then
3093  b = this%thick(ib)
3094  ! -- delay interbeds
3095  else
3096  b = this%thick(ib) * this%rnb(ib)
3097  end if
3098  !
3099  ! -- set variables required for no-delay and delay interbeds
3100  node = this%nodelist(ib)
3101  idiag = this%dis%con%ia(node)
3102  area = this%dis%get_area(node)
3103  !
3104  ! -- add interbed thickness to cell thickness
3105  this%cell_thick(node) = this%cell_thick(node) + b
3106  !
3107  ! -- update budget terms if transient stress period
3108  if (this%gwfiss == 0) then
3109  if (delt > dzero) then
3110  tledm = done / delt
3111  else
3112  tledm = dzero
3113  end if
3114  !
3115  ! -- skip inactive and constant head cells
3116  if (this%ibound(node) < 1) cycle
3117  !
3118  ! -- no delay interbeds
3119  if (idelay == 0) then
3120  iconvert = this%iconvert(ib)
3121  stoi = dzero
3122  !
3123  ! -- calculate compaction
3124  call this%csub_nodelay_calc_comp(ib, hnew(node), hold(node), comp, &
3125  rho1, rho2)
3126  !
3127  ! -- interbed stresses
3128  es = this%cg_es(node)
3129  pcs = this%pcs(ib)
3130  es0 = this%cg_es0(node)
3131  !
3132  ! -- calculate inelastic and elastic compaction
3133  if (ielastic > 0 .or. iconvert == 0) then
3134  stoe = comp
3135  else
3136  stoi = -pcs * rho2 + (rho2 * es)
3137  stoe = pcs * rho1 - (rho1 * es0)
3138  end if
3139  compe = stoe
3140  compi = stoi
3141  stoe = stoe * area
3142  stoi = stoi * area
3143  this%storagee(ib) = stoe * tledm
3144  this%storagei(ib) = stoi * tledm
3145  !
3146  ! -- update compaction
3147  this%comp(ib) = comp
3148  !
3149  ! -- update states if required
3150  if (isuppress_output == 0) then
3151  !
3152  ! -- calculate strain and change in interbed void ratio and thickness
3153  if (this%iupdatematprop /= 0) then
3154  call this%csub_nodelay_update(ib)
3155  end if
3156  !
3157  ! -- update total compaction
3158  this%tcomp(ib) = this%tcomp(ib) + comp
3159  this%tcompe(ib) = this%tcompe(ib) + compe
3160  this%tcompi(ib) = this%tcompi(ib) + compi
3161  end if
3162  !
3163  ! -- delay interbeds
3164  else
3165  h = hnew(node)
3166  h0 = hold(node)
3167  !
3168  ! -- calculate cell saturation
3169  call this%csub_calc_sat(node, h, h0, snnew, snold)
3170  !
3171  ! -- calculate inelastic and elastic storage contributions
3172  call this%csub_delay_calc_dstor(ib, h, stoe, stoi)
3173  this%storagee(ib) = stoe * area * this%rnb(ib) * tledm
3174  this%storagei(ib) = stoi * area * this%rnb(ib) * tledm
3175  !
3176  ! -- calculate flow across the top and bottom of the delay interbed
3177  q = this%csub_calc_delay_flow(ib, 1, h) * area * this%rnb(ib)
3178  this%dbflowtop(idelay) = q
3179  nn = this%ndelaycells
3180  q = this%csub_calc_delay_flow(ib, nn, h) * area * this%rnb(ib)
3181  this%dbflowbot(idelay) = q
3182  !
3183  ! -- update states if required
3184  if (isuppress_output == 0) then
3185  !
3186  ! -- calculate sum of compaction in delay interbed
3187  call this%csub_delay_calc_comp(ib, h, h0, comp, compi, compe)
3188  !
3189  ! - calculate strain and change in interbed void ratio and thickness
3190  ! todo: consider moving error check in csub_delay_update to ot()
3191  if (this%iupdatematprop /= 0) then
3192  call this%csub_delay_update(ib)
3193  end if
3194  !
3195  ! -- update total compaction for interbed
3196  this%tcomp(ib) = this%tcomp(ib) + comp
3197  this%tcompi(ib) = this%tcompi(ib) + compi
3198  this%tcompe(ib) = this%tcompe(ib) + compe
3199  !
3200  ! -- update total compaction for each delay bed cell
3201  do n = 1, this%ndelaycells
3202  this%dbtcomp(n, idelay) = this%dbtcomp(n, idelay) + &
3203  this%dbcomp(n, idelay)
3204  end do
3205  !
3206  ! -- check delay bed heads relative to the top and bottom of each
3207  ! delay bed cell for convertible and non-convertible gwf cells
3208  call this%csub_delay_head_check(ib)
3209  end if
3210  end if
3211  !
3212  ! -- interbed water compressibility
3213  !
3214  ! -- no-delay interbed
3215  if (idelay == 0) then
3216  call this%csub_nodelay_wcomp_fc(ib, node, tledm, area, &
3217  hnew(node), hold(node), hcof, rhs)
3218  rratewc = hcof * hnew(node) - rhs
3219  !
3220  ! -- delay interbed
3221  else
3222  call this%csub_delay_calc_wcomp(ib, q)
3223  rratewc = q * area * this%rnb(ib)
3224  end if
3225  this%cell_wcstor(node) = this%cell_wcstor(node) + rratewc
3226  !
3227  ! -- flowja
3228  flowja(idiag) = flowja(idiag) + rratewc
3229  else
3230  this%storagee(ib) = dzero
3231  this%storagei(ib) = dzero
3232  if (idelay /= 0) then
3233  this%dbflowtop(idelay) = dzero
3234  this%dbflowbot(idelay) = dzero
3235  end if
3236  end if
3237  !
3238  ! -- flowja
3239  flowja(idiag) = flowja(idiag) + this%storagee(ib)
3240  flowja(idiag) = flowja(idiag) + this%storagei(ib)
3241  end do
3242  !
3243  ! -- terminate if errors encountered when updating material properties
3244  if (this%iupdatematprop /= 0) then
3245  if (count_errors() > 0) then
3246  call store_error_filename(this%input_fname)
3247  end if
3248  end if
3249  end subroutine csub_cq
3250 
3251  !> @ brief Model budget calculation for package
3252  !!
3253  !! Budget calculation for the CSUB package components. Components include
3254  !! coarse-grained storage, delay and no-delay interbeds, and water
3255  !! compressibility.
3256  !!
3257  !! @param[in,out] model_budget model budget object
3258  !!
3259  !<
3260  subroutine csub_bd(this, isuppress_output, model_budget)
3261  ! -- modules
3262  use tdismodule, only: delt
3263  use constantsmodule, only: lenboundname, dzero, done
3265  ! -- dummy variables
3266  class(gwfcsubtype) :: this
3267  integer(I4B), intent(in) :: isuppress_output
3268  type(budgettype), intent(inout) :: model_budget !< model budget object
3269  ! -- local
3270  real(DP) :: rin
3271  real(DP) :: rout
3272  !
3273  ! -- interbed elastic storage (this%cg_stor)
3274  call rate_accumulator(this%cg_stor, rin, rout)
3275  call model_budget%addentry(rin, rout, delt, budtxt(1), &
3276  isuppress_output, ' CSUB')
3277  if (this%ninterbeds > 0) then
3278  !
3279  ! -- interbed elastic storage (this%storagee)
3280  call rate_accumulator(this%storagee, rin, rout)
3281  call model_budget%addentry(rin, rout, delt, budtxt(2), &
3282  isuppress_output, ' CSUB')
3283  !
3284  ! -- interbed elastic storage (this%storagei)
3285  call rate_accumulator(this%storagei, rin, rout)
3286  call model_budget%addentry(rin, rout, delt, budtxt(3), &
3287  isuppress_output, ' CSUB')
3288  end if
3289  call rate_accumulator(this%cell_wcstor, rin, rout)
3290  call model_budget%addentry(rin, rout, delt, budtxt(4), &
3291  isuppress_output, ' CSUB')
3292  return
3293  end subroutine csub_bd
3294 
3295 !> @ brief Save model flows for package
3296 !!
3297 !! Save cell-by-cell budget terms for the CSUB package.
3298 !!
3299 !<
3300  subroutine csub_save_model_flows(this, icbcfl, icbcun)
3301  ! -- dummy variables
3302  class(gwfcsubtype) :: this
3303  integer(I4B), intent(in) :: icbcfl !< flag to output budget data
3304  integer(I4B), intent(in) :: icbcun !< unit number for cell-by-cell file
3305  ! -- local variables
3306  character(len=1) :: cdatafmp = ' '
3307  character(len=1) :: editdesc = ' '
3308  integer(I4B) :: ibinun
3309  integer(I4B) :: iprint
3310  integer(I4B) :: nvaluesp
3311  integer(I4B) :: nwidthp
3312  integer(I4B) :: ib
3313  integer(I4B) :: node
3314  integer(I4B) :: naux
3315  real(DP) :: dinact
3316  real(DP) :: Q
3317  ! -- formats
3318  !
3319  ! -- Set unit number for binary output
3320  if (this%ipakcb < 0) then
3321  ibinun = icbcun
3322  elseif (this%ipakcb == 0) then
3323  ibinun = 0
3324  else
3325  ibinun = this%ipakcb
3326  end if
3327  if (icbcfl == 0) ibinun = 0
3328  !
3329  ! -- Record the storage rates if requested
3330  if (ibinun /= 0) then
3331  iprint = 0
3332  dinact = dzero
3333  !
3334  ! -- coarse-grained storage (sske)
3335  call this%dis%record_array(this%cg_stor, this%iout, iprint, -ibinun, &
3336  budtxt(1), cdatafmp, nvaluesp, &
3337  nwidthp, editdesc, dinact)
3338  if (this%ninterbeds > 0) then
3339  naux = 0
3340  !
3341  ! -- interbed elastic storage
3342  call this%dis%record_srcdst_list_header(budtxt(2), &
3343  this%name_model, &
3344  this%name_model, &
3345  this%name_model, &
3346  this%packName, &
3347  naux, &
3348  this%auxname, &
3349  ibinun, &
3350  this%ninterbeds, &
3351  this%iout)
3352  do ib = 1, this%ninterbeds
3353  q = this%storagee(ib)
3354  node = this%nodelist(ib)
3355  call this%dis%record_mf6_list_entry(ibinun, node, node, q, naux, &
3356  this%auxvar(:, ib))
3357  end do
3358  !
3359  ! -- interbed inelastic storage
3360  call this%dis%record_srcdst_list_header(budtxt(3), &
3361  this%name_model, &
3362  this%name_model, &
3363  this%name_model, &
3364  this%packName, &
3365  naux, &
3366  this%auxname, &
3367  ibinun, &
3368  this%ninterbeds, &
3369  this%iout)
3370  do ib = 1, this%ninterbeds
3371  q = this%storagei(ib)
3372  node = this%nodelist(ib)
3373  call this%dis%record_mf6_list_entry(ibinun, node, node, q, naux, &
3374  this%auxvar(:, ib))
3375  end do
3376  end if
3377  !
3378  ! -- water compressibility
3379  call this%dis%record_array(this%cell_wcstor, this%iout, iprint, -ibinun, &
3380  budtxt(4), cdatafmp, nvaluesp, &
3381  nwidthp, editdesc, dinact)
3382  end if
3383  end subroutine csub_save_model_flows
3384 
3385 !> @ brief Save and print dependent values for package
3386 !!
3387 !! Method saves cell-by-cell compaction and z-displacement terms. The method
3388 !! also calls the method to process observation output.
3389 !!
3390 !<
3391  subroutine csub_ot_dv(this, idvfl, idvprint)
3392  ! -- dummy variables
3393  class(gwfcsubtype) :: this
3394  integer(I4B), intent(in) :: idvfl !< flag to save dependent variable data
3395  integer(I4B), intent(in) :: idvprint !< flag to print dependent variable data
3396  ! -- local variables
3397  character(len=1) :: cdatafmp = ' '
3398  character(len=1) :: editdesc = ' '
3399  integer(I4B) :: ibinun
3400  integer(I4B) :: iprint
3401  integer(I4B) :: nvaluesp
3402  integer(I4B) :: nwidthp
3403  integer(I4B) :: ib
3404  integer(I4B) :: node
3405  integer(I4B) :: nodem
3406  integer(I4B) :: nodeu
3407  integer(I4B) :: i
3408  integer(I4B) :: ii
3409  integer(I4B) :: idx_conn
3410  integer(I4B) :: k
3411  integer(I4B) :: ncpl
3412  integer(I4B) :: nlay
3413  integer(I4B) :: ihc
3414  real(DP) :: dinact
3415  real(DP) :: va_scale
3416  ! -- formats
3417  character(len=*), parameter :: fmtnconv = &
3418  "(/4x, 'DELAY INTERBED CELL HEADS IN ', i0, ' INTERBEDS IN', &
3419  &' NON-CONVERTIBLE GWF CELLS WERE LESS THAN THE TOP OF THE INTERBED CELL')"
3420  !
3421  ! -- Save compaction results
3422  !
3423  ! -- Set unit number for binary compaction and z-displacement output
3424  if (this%ioutcomp /= 0 .or. this%ioutzdisp /= 0) then
3425  ibinun = 1
3426  else
3427  ibinun = 0
3428  end if
3429  if (idvfl == 0) ibinun = 0
3430  !
3431  ! -- save compaction results
3432  if (ibinun /= 0) then
3433  iprint = 0
3434  dinact = dhnoflo
3435  !
3436  ! -- fill buff with total compaction
3437  do node = 1, this%dis%nodes
3438  this%buff(node) = this%cg_tcomp(node)
3439  end do
3440  do ib = 1, this%ninterbeds
3441  node = this%nodelist(ib)
3442  this%buff(node) = this%buff(node) + this%tcomp(ib)
3443  end do
3444  !
3445  ! -- write compaction data to binary file
3446  if (this%ioutcomp /= 0) then
3447  ibinun = this%ioutcomp
3448  call this%dis%record_array(this%buff, this%iout, iprint, ibinun, &
3449  comptxt(1), cdatafmp, nvaluesp, &
3450  nwidthp, editdesc, dinact)
3451  end if
3452  !
3453  ! -- calculate z-displacement (subsidence) and write data to binary file
3454  if (this%ioutzdisp /= 0) then
3455  ibinun = this%ioutzdisp
3456  !
3457  ! -- initialize buffusr
3458  do nodeu = 1, this%dis%nodesuser
3459  this%buffusr(nodeu) = dzero
3460  end do
3461  !
3462  ! -- fill buffusr with buff
3463  do node = 1, this%dis%nodes
3464  nodeu = this%dis%get_nodeuser(node)
3465  this%buffusr(nodeu) = this%buff(node)
3466  end do
3467  !
3468  ! -- calculate z-displacement
3469  ncpl = this%dis%get_ncpl()
3470  !
3471  ! -- disu
3472  if (this%dis%ndim == 1) then
3473  do node = this%dis%nodes, 1, -1
3474  do ii = this%dis%con%ia(node) + 1, this%dis%con%ia(node + 1) - 1
3475  !
3476  ! -- Set the m cell number
3477  nodem = this%dis%con%ja(ii)
3478  idx_conn = this%dis%con%jas(ii)
3479  !
3480  ! -- vertical connection
3481  ihc = this%dis%con%ihc(idx_conn)
3482  if (ihc == 0) then
3483  !
3484  ! -- node has an underlying cell
3485  if (node < nodem) then
3486  va_scale = this%dis%get_area_factor(node, idx_conn)
3487  this%buffusr(node) = this%buffusr(node) + &
3488  va_scale * this%buffusr(nodem)
3489  end if
3490  end if
3491  end do
3492  end do
3493  ! -- disv or dis
3494  else
3495  nlay = this%dis%nodesuser / ncpl
3496  do k = nlay - 1, 1, -1
3497  do i = 1, ncpl
3498  node = (k - 1) * ncpl + i
3499  nodem = k * ncpl + i
3500  this%buffusr(node) = this%buffusr(node) + this%buffusr(nodem)
3501  end do
3502  end do
3503  end if
3504  !
3505  ! -- fill buff with data from buffusr
3506  do nodeu = 1, this%dis%nodesuser
3507  node = this%dis%get_nodenumber_idx1(nodeu, 1)
3508  if (node > 0) then
3509  this%buff(node) = this%buffusr(nodeu)
3510  end if
3511  end do
3512  !
3513  ! -- write z-displacement
3514  call this%dis%record_array(this%buff, this%iout, iprint, ibinun, &
3515  comptxt(6), cdatafmp, nvaluesp, &
3516  nwidthp, editdesc, dinact)
3517 
3518  end if
3519  end if
3520  !
3521  ! -- Set unit number for binary inelastic interbed compaction
3522  if (this%ioutcompi /= 0) then
3523  ibinun = this%ioutcompi
3524  else
3525  ibinun = 0
3526  end if
3527  if (idvfl == 0) ibinun = 0
3528  !
3529  ! -- save inelastic interbed compaction results
3530  if (ibinun /= 0) then
3531  iprint = 0
3532  dinact = dhnoflo
3533  !
3534  ! -- fill buff with inelastic interbed compaction
3535  do node = 1, this%dis%nodes
3536  this%buff(node) = dzero
3537  end do
3538  do ib = 1, this%ninterbeds
3539  node = this%nodelist(ib)
3540  this%buff(node) = this%buff(node) + this%tcompi(ib)
3541  end do
3542  !
3543  ! -- write inelastic interbed compaction data to binary file
3544  call this%dis%record_array(this%buff, this%iout, iprint, ibinun, &
3545  comptxt(2), cdatafmp, nvaluesp, &
3546  nwidthp, editdesc, dinact)
3547  end if
3548  !
3549  ! -- Set unit number for binary elastic interbed compaction
3550  if (this%ioutcompe /= 0) then
3551  ibinun = this%ioutcompe
3552  else
3553  ibinun = 0
3554  end if
3555  if (idvfl == 0) ibinun = 0
3556  !
3557  ! -- save elastic interbed compaction results
3558  if (ibinun /= 0) then
3559  iprint = 0
3560  dinact = dhnoflo
3561  !
3562  ! -- fill buff with elastic interbed compaction
3563  do node = 1, this%dis%nodes
3564  this%buff(node) = dzero
3565  end do
3566  do ib = 1, this%ninterbeds
3567  node = this%nodelist(ib)
3568  this%buff(node) = this%buff(node) + this%tcompe(ib)
3569  end do
3570  !
3571  ! -- write elastic interbed compaction data to binary file
3572  call this%dis%record_array(this%buff, this%iout, iprint, ibinun, &
3573  comptxt(3), cdatafmp, nvaluesp, &
3574  nwidthp, editdesc, dinact)
3575  end if
3576  !
3577  ! -- Set unit number for binary interbed compaction
3578  if (this%ioutcompib /= 0) then
3579  ibinun = this%ioutcompib
3580  else
3581  ibinun = 0
3582  end if
3583  if (idvfl == 0) ibinun = 0
3584  !
3585  ! -- save interbed compaction results
3586  if (ibinun /= 0) then
3587  iprint = 0
3588  dinact = dhnoflo
3589  !
3590  ! -- fill buff with interbed compaction
3591  do node = 1, this%dis%nodes
3592  this%buff(node) = dzero
3593  end do
3594  do ib = 1, this%ninterbeds
3595  node = this%nodelist(ib)
3596  this%buff(node) = this%buff(node) + this%tcompe(ib) + this%tcompi(ib)
3597  end do
3598  !
3599  ! -- write interbed compaction data to binary file
3600  call this%dis%record_array(this%buff, this%iout, iprint, ibinun, &
3601  comptxt(4), cdatafmp, nvaluesp, &
3602  nwidthp, editdesc, dinact)
3603  end if
3604  !
3605  ! -- Set unit number for binary coarse-grained compaction
3606  if (this%ioutcomps /= 0) then
3607  ibinun = this%ioutcomps
3608  else
3609  ibinun = 0
3610  end if
3611  if (idvfl == 0) ibinun = 0
3612  !
3613  ! -- save coarse-grained compaction results
3614  if (ibinun /= 0) then
3615  iprint = 0
3616  dinact = dhnoflo
3617  !
3618  ! -- fill buff with coarse-grained compaction
3619  do node = 1, this%dis%nodes
3620  this%buff(node) = this%cg_tcomp(node)
3621  end do
3622  !
3623  ! -- write coarse-grained compaction data to binary file
3624  call this%dis%record_array(this%buff, this%iout, iprint, ibinun, &
3625  comptxt(5), cdatafmp, nvaluesp, &
3626  nwidthp, editdesc, dinact)
3627  end if
3628  !
3629  ! -- check that final effective stress values for the time step
3630  ! are greater than zero
3631  if (this%gwfiss == 0) then
3632  call this%csub_cg_chk_stress()
3633  end if
3634  !
3635  ! -- update maximum count of delay interbeds that violate
3636  ! basic head assumptions for delay beds and write a message
3637  ! for delay interbeds in non-convertible gwf cells that
3638  ! violate these head assumptions
3639  if (this%ndelaybeds > 0) then
3640  if (this%idb_nconv_count(1) > this%idb_nconv_count(2)) then
3641  this%idb_nconv_count(2) = this%idb_nconv_count(1)
3642  end if
3643  if (this%idb_nconv_count(1) > 0) then
3644  write (this%iout, fmtnconv) this%idb_nconv_count(1)
3645  end if
3646  end if
3647  end subroutine csub_ot_dv
3648 
3649  !> @ brief Calculate the stress for model cells
3650  !!
3651  !! Method calculates the geostatic stress, pressure head, and effective
3652  !! stress at the bottom of each cell. The method also applies the overlying
3653  !! geostatic stress (sig0) not represented in the model.
3654  !!
3655  !<
3656  subroutine csub_cg_calc_stress(this, nodes, hnew)
3657  ! -- dummy variables
3658  class(gwfcsubtype) :: this
3659  integer(I4B), intent(in) :: nodes !< number of active model nodes
3660  real(DP), dimension(nodes), intent(in) :: hnew !< current head
3661  ! -- local variables
3662  integer(I4B) :: node
3663  integer(I4B) :: ii
3664  integer(I4B) :: nn
3665  integer(I4B) :: m
3666  integer(I4B) :: idx_conn
3667  real(DP) :: gs
3668  real(DP) :: top
3669  real(DP) :: bot
3670  real(DP) :: thick
3671  real(DP) :: va_scale
3672  real(DP) :: hcell
3673  real(DP) :: hbar
3674  real(DP) :: gs_conn
3675  real(DP) :: es
3676  real(DP) :: phead
3677  real(DP) :: sadd
3678  !
3679  ! -- calculate geostatic stress if necessary
3680  if (this%iupdatestress /= 0) then
3681  do node = 1, this%dis%nodes
3682  !
3683  ! -- calculate geostatic stress for this node
3684  ! this represents the geostatic stress component
3685  ! for the cell
3686  top = this%dis%top(node)
3687  bot = this%dis%bot(node)
3688  thick = top - bot
3689  !
3690  ! -- calculate cell contribution to geostatic stress
3691  if (this%ibound(node) /= 0) then
3692  hcell = hnew(node)
3693  else
3694  hcell = bot
3695  end if
3696  !
3697  ! -- calculate corrected head (hbar)
3698  hbar = squadratic0sp(hcell, bot, this%satomega)
3699  !
3700  ! -- geostatic stress calculation
3701  if (hcell < top) then
3702  gs = (top - hbar) * this%sgm(node) + (hbar - bot) * this%sgs(node)
3703  else
3704  gs = thick * this%sgs(node)
3705  end if
3706  !
3707  ! -- cell contribution to geostatic stress
3708  this%cg_gs(node) = gs
3709  end do
3710  !
3711  ! -- add user specified overlying geostatic stress
3712  do nn = 1, this%nbound
3713  node = this%nodelistsig0(nn)
3714  sadd = this%sig0(nn)
3715  this%cg_gs(node) = this%cg_gs(node) + sadd
3716  end do
3717  !
3718  ! -- calculate geostatic stress above cell
3719  do node = 1, this%dis%nodes
3720  !
3721  ! -- geostatic stress of cell
3722  gs = this%cg_gs(node)
3723  !
3724  ! -- Add geostatic stress of overlying cells (ihc=0)
3725  ! m < node = m is vertically above node
3726  do ii = this%dis%con%ia(node) + 1, this%dis%con%ia(node + 1) - 1
3727  !
3728  ! -- Set the m cell number
3729  m = this%dis%con%ja(ii)
3730  idx_conn = this%dis%con%jas(ii)
3731  !
3732  ! -- vertical connection
3733  if (this%dis%con%ihc(idx_conn) == 0) then
3734  !
3735  ! -- node has an overlying cell
3736  if (m < node) then
3737  !
3738  ! -- dis and disv discretization
3739  if (this%dis%ndim /= 1) then
3740  gs = gs + this%cg_gs(m)
3741  !
3742  ! -- disu discretization
3743  else
3744  va_scale = this%dis%get_area_factor(node, idx_conn)
3745  gs_conn = this%cg_gs(m)
3746  gs = gs + (gs_conn * va_scale)
3747  end if
3748  end if
3749  end if
3750  end do
3751  !
3752  ! -- geostatic stress for cell with geostatic stress
3753  ! of overlying cells
3754  this%cg_gs(node) = gs
3755  end do
3756  end if
3757  !
3758  ! -- save effective stress from the last iteration and
3759  ! calculate the new effective stress for a cell
3760  do node = 1, this%dis%nodes
3761  top = this%dis%top(node)
3762  bot = this%dis%bot(node)
3763  if (this%ibound(node) /= 0) then
3764  hcell = hnew(node)
3765  else
3766  hcell = bot
3767  end if
3768  !
3769  ! -- calculate corrected head (hbar)
3770  hbar = squadratic0sp(hcell, bot, this%satomega)
3771  !
3772  ! -- calculate pressure head
3773  phead = hbar - bot
3774  !
3775  ! -- calculate effective stress
3776  es = this%cg_gs(node) - phead
3777  this%cg_es(node) = es
3778  end do
3779  end subroutine csub_cg_calc_stress
3780 
3781  !> @ brief Check effective stress values
3782  !!
3783  !! Method checks calculated effective stress values to ensure that
3784  !! effective stress values are positive. An error condition and message are
3785  !! issued if calculated effective stress values are less than a small positive
3786  !! value (DEM6).
3787  !!
3788  !<
3789  subroutine csub_cg_chk_stress(this)
3790  ! -- dummy variables
3791  class(gwfcsubtype) :: this
3792  ! -- local variables
3793  character(len=20) :: cellid
3794  integer(I4B) :: ierr
3795  integer(I4B) :: node
3796  real(DP) :: gs
3797  real(DP) :: bot
3798  real(DP) :: hcell
3799  real(DP) :: es
3800  real(DP) :: phead
3801  !
3802  ! -- initialize variables
3803  ierr = 0
3804  !
3805  ! -- check geostatic stress if necessary
3806  !
3807  ! -- save effective stress from the last iteration and
3808  ! calculate the new effective stress for a cell
3809  do node = 1, this%dis%nodes
3810  if (this%ibound(node) < 1) cycle
3811  bot = this%dis%bot(node)
3812  gs = this%cg_gs(node)
3813  es = this%cg_es(node)
3814  phead = dzero
3815  if (this%ibound(node) /= 0) then
3816  phead = gs - es
3817  end if
3818  hcell = phead + bot
3819  if (this%lhead_based .EQV. .false.) then
3820  if (es < dem6) then
3821  ierr = ierr + 1
3822  call this%dis%noder_to_string(node, cellid)
3823  write (errmsg, '(a,g0,a,1x,a,1x,a,4(g0,a))') &
3824  'Small to negative effective stress (', es, ') in cell', &
3825  trim(adjustl(cellid)), '. (', es, ' = ', this%cg_gs(node), &
3826  ' - (', hcell, ' - ', bot, ').'
3827  call store_error(errmsg)
3828  end if
3829  end if
3830  end do
3831  !
3832  ! -- write a summary error message
3833  if (ierr > 0) then
3834  write (errmsg, '(a,1x,i0,3(1x,a))') &
3835  'Solution: small to negative effective stress values in', ierr, &
3836  'cells can be eliminated by increasing storage values and/or ', &
3837  'adding/modifying stress boundaries to prevent water-levels from', &
3838  'exceeding the top of the model.'
3839  call store_error(errmsg)
3840  call store_error_filename(this%input_fname)
3841  end if
3842  end subroutine csub_cg_chk_stress
3843 
3844  !> @ brief Update no-delay material properties
3845  !!
3846  !! Method updates no-delay material properties based on the current
3847  !! compaction value.
3848  !!
3849  !<
3850  subroutine csub_nodelay_update(this, i)
3851  ! -- dummy variables
3852  class(gwfcsubtype), intent(inout) :: this
3853  integer(I4B), intent(in) :: i
3854  ! -- local variables
3855  real(DP) :: comp
3856  real(DP) :: thick
3857  real(DP) :: theta
3858  !
3859  ! -- update thickness and theta
3860  comp = this%tcomp(i) + this%comp(i)
3861  if (abs(comp) > dzero) then
3862  thick = this%thickini(i)
3863  theta = this%thetaini(i)
3864  call this%csub_adj_matprop(comp, thick, theta)
3865  if (thick <= dzero) then
3866  write (errmsg, '(a,1x,i0,1x,a,g0,a)') &
3867  'Adjusted thickness for no-delay interbed', i, &
3868  'is less than or equal to 0 (', thick, ').'
3869  call store_error(errmsg)
3870  end if
3871  if (theta <= dzero) then
3872  write (errmsg, '(a,1x,i0,1x,a,g0,a)') &
3873  'Adjusted theta for no-delay interbed', i, &
3874  'is less than or equal to 0 (', theta, ').'
3875  call store_error(errmsg)
3876  end if
3877  this%thick(i) = thick
3878  this%theta(i) = theta
3879  end if
3880  end subroutine csub_nodelay_update
3881 
3882  !> @ brief Calculate no-delay interbed storage coefficients
3883  !!
3884  !! Method calculates the skeletal storage coefficients for a no-delay
3885  !! interbed. The method also calculates the contribution of the
3886  !! no-delay interbed to the right-hand side of the groundwater flow
3887  !! equation for the cell.
3888  !!
3889  !! @param[in,out] rho1 no-delay storage value using Sske
3890  !! @param[in,out] rho2 no-delay storage value using Ssk
3891  !! @param[in,out] rhs no-delay right-hand side contribution
3892  !!
3893  !<
3894  subroutine csub_nodelay_fc(this, ib, hcell, hcellold, rho1, rho2, rhs, &
3895  argtled)
3896  ! -- modules
3897  use tdismodule, only: delt
3898  ! -- dummy variables
3899  class(gwfcsubtype) :: this
3900  integer(I4B), intent(in) :: ib !< interbed number
3901  real(DP), intent(in) :: hcell !< current head in the cell
3902  real(DP), intent(in) :: hcellold !< previous head in the cell
3903  real(DP), intent(inout) :: rho1 !< current storage coefficient value using Sske
3904  real(DP), intent(inout) :: rho2 !< current storage coefficient value based on Ssk
3905  real(DP), intent(inout) :: rhs !< no-delay interbed contribution to the right-hand side
3906  real(DP), intent(in), optional :: argtled !< optional reciprocal of the time step length
3907  ! -- local variables
3908  integer(I4B) :: node
3909  real(DP) :: tled
3910  real(DP) :: top
3911  real(DP) :: bot
3912  real(DP) :: thick
3913  real(DP) :: hbar
3914  real(DP) :: znode
3915  real(DP) :: snold
3916  real(DP) :: snnew
3917  real(DP) :: sto_fac
3918  real(DP) :: sto_fac0
3919  real(DP) :: area
3920  real(DP) :: theta
3921  real(DP) :: es
3922  real(DP) :: es0
3923  real(DP) :: f
3924  real(DP) :: f0
3925  real(DP) :: rcorr
3926  !
3927  ! -- process optional variables
3928  if (present(argtled)) then
3929  tled = argtled
3930  else
3931  tled = done / delt
3932  end if
3933  node = this%nodelist(ib)
3934  area = this%dis%get_area(node)
3935  bot = this%dis%bot(node)
3936  top = this%dis%top(node)
3937  thick = this%thickini(ib)
3938  !
3939  ! -- calculate corrected head (hbar)
3940  hbar = squadratic0sp(hcell, bot, this%satomega)
3941  !
3942  ! -- set iconvert
3943  this%iconvert(ib) = 0
3944  !
3945  ! -- aquifer saturation
3946  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
3947  if (this%lhead_based .EQV. .true.) then
3948  f = done
3949  f0 = done
3950  else
3951  znode = this%csub_calc_znode(top, bot, hbar)
3952  es = this%cg_es(node)
3953  es0 = this%cg_es0(node)
3954  theta = this%thetaini(ib)
3955  !
3956  ! -- calculate the compression index factors for the delay
3957  ! node relative to the center of the cell based on the
3958  ! current and previous head
3959  call this%csub_calc_sfacts(node, bot, znode, theta, es, es0, f)
3960  end if
3961  sto_fac = tled * snnew * thick * f
3962  sto_fac0 = tled * snold * thick * f
3963  !
3964  ! -- calculate rho1 and rho2
3965  rho1 = this%rci(ib) * sto_fac0
3966  rho2 = this%rci(ib) * sto_fac
3967  if (this%cg_es(node) > this%pcs(ib)) then
3968  this%iconvert(ib) = 1
3969  rho2 = this%ci(ib) * sto_fac
3970  end if
3971  !
3972  ! -- calculate correction term
3973  rcorr = rho2 * (hcell - hbar)
3974  !
3975  ! -- fill right-hand side
3976  if (this%ielastic(ib) /= 0) then
3977  rhs = rho1 * this%cg_es0(node) - &
3978  rho2 * (this%cg_gs(node) + bot) - &
3979  rcorr
3980  else
3981  rhs = -rho2 * (this%cg_gs(node) + bot) + &
3982  (this%pcs(ib) * (rho2 - rho1)) + &
3983  (rho1 * this%cg_es0(node)) - &
3984  rcorr
3985  end if
3986  !
3987  ! -- save ske and sk
3988  this%ske(ib) = rho1
3989  this%sk(ib) = rho2
3990  end subroutine csub_nodelay_fc
3991 
3992  !> @ brief Calculate no-delay interbed compaction
3993  !!
3994  !! Method calculates the compaction for a no-delay interbed. The method
3995  !! also calculates the storage coefficients for the no-delay interbed.
3996  !!
3997  !! @param[in,out] comp no-delay compaction
3998  !! @param[in,out] rho1 no-delay storage value using Sske
3999  !! @param[in,out] rho2 no-delay storage value using Ssk
4000  !!
4001  !<
4002  subroutine csub_nodelay_calc_comp(this, ib, hcell, hcellold, comp, rho1, rho2)
4003  ! -- dummy variables
4004  class(gwfcsubtype) :: this
4005  integer(I4B), intent(in) :: ib !< interbed number
4006  real(DP), intent(in) :: hcell !< current head for the cell
4007  real(DP), intent(in) :: hcellold !< previous head for the cell
4008  real(DP), intent(inout) :: comp !< no-delay interbed compaction
4009  real(DP), intent(inout) :: rho1 !< current storage coefficient based on Sske
4010  real(DP), intent(inout) :: rho2 !< current storage coefficient based on Ssk
4011  ! -- local variables
4012  integer(I4B) :: node
4013  real(DP) :: es
4014  real(DP) :: es0
4015  real(DP) :: pcs
4016  real(DP) :: tled
4017  real(DP) :: rhs
4018  !
4019  ! -- initialize variables
4020  node = this%nodelist(ib)
4021  tled = done
4022  es = this%cg_es(node)
4023  es0 = this%cg_es0(node)
4024  pcs = this%pcs(ib)
4025  !
4026  ! -- calculate no-delay interbed rho1 and rho2
4027  call this%csub_nodelay_fc(ib, hcell, hcellold, rho1, rho2, rhs, argtled=tled)
4028  !
4029  ! -- calculate no-delay interbed compaction
4030  if (this%ielastic(ib) /= 0) then
4031  comp = rho2 * es - rho1 * es0
4032  else
4033  comp = -pcs * (rho2 - rho1) - (rho1 * es0) + (rho2 * es)
4034  end if
4035  end subroutine csub_nodelay_calc_comp
4036 
4037  !> @ brief Set initial states for the package
4038  !!
4039  !! Method sets the initial states for coarse-grained materials and fine-
4040  !! grained sediments in the interbeds.
4041  !!
4042  !<
4043  subroutine csub_set_initial_state(this, nodes, hnew)
4044  ! -- dummy variables
4045  class(gwfcsubtype) :: this
4046  ! -- dummy variables
4047  integer(I4B), intent(in) :: nodes !< number of active model nodes
4048  real(DP), dimension(nodes), intent(in) :: hnew !< current heads
4049  ! -- local variables
4050  character(len=LINELENGTH) :: title
4051  character(len=LINELENGTH) :: tag
4052  character(len=20) :: cellid
4053  integer(I4B) :: ib
4054  integer(I4B) :: node
4055  integer(I4B) :: n
4056  integer(I4B) :: idelay
4057  integer(I4B) :: ntabrows
4058  integer(I4B) :: ntabcols
4059  real(DP) :: pcs0
4060  real(DP) :: pcs
4061  real(DP) :: fact
4062  real(DP) :: top
4063  real(DP) :: bot
4064  real(DP) :: void_ratio
4065  real(DP) :: es
4066  real(DP) :: znode
4067  real(DP) :: hcell
4068  real(DP) :: hbar
4069  real(DP) :: dzhalf
4070  real(DP) :: zbot
4071  real(DP) :: dbpcs
4072  !
4073  ! -- update geostatic load calculation
4074  call this%csub_cg_calc_stress(nodes, hnew)
4075  !
4076  ! -- initialize coarse-grained material effective stress
4077  ! for the previous time step and the previous iteration
4078  do node = 1, nodes
4079  this%cg_es0(node) = this%cg_es(node)
4080  end do
4081  !
4082  ! -- initialize interbed initial states
4083  do ib = 1, this%ninterbeds
4084  idelay = this%idelay(ib)
4085  node = this%nodelist(ib)
4086  top = this%dis%top(node)
4087  bot = this%dis%bot(node)
4088  hcell = hnew(node)
4089  pcs = this%pcs(ib)
4090  pcs0 = pcs
4091  if (this%ispecified_pcs == 0) then
4092  ! relative pcs...subtract head (u) from sigma'
4093  if (this%ipch /= 0) then
4094  pcs = this%cg_es(node) - pcs0
4095  else
4096  pcs = this%cg_es(node) + pcs0
4097  end if
4098  else
4099  ! specified pcs...subtract head (u) from sigma
4100  if (this%ipch /= 0) then
4101  pcs = this%cg_gs(node) - (pcs0 - bot)
4102  end if
4103  if (pcs < this%cg_es(node)) then
4104  pcs = this%cg_es(node)
4105  end if
4106  end if
4107  this%pcs(ib) = pcs
4108  !
4109  ! -- delay bed initial states
4110  if (idelay /= 0) then
4111  dzhalf = dhalf * this%dbdzini(1, idelay)
4112  !
4113  ! -- fill delay bed head with aquifer head or offset from aquifer head
4114  ! heads need to be filled first since used to calculate
4115  ! the effective stress for each delay bed
4116  do n = 1, this%ndelaycells
4117  if (this%ispecified_dbh == 0) then
4118  this%dbh(n, idelay) = hcell + this%dbh(n, idelay)
4119  else
4120  this%dbh(n, idelay) = hcell
4121  end if
4122  this%dbh0(n, idelay) = this%dbh(n, idelay)
4123  end do
4124  !
4125  ! -- fill delay bed effective stress
4126  call this%csub_delay_calc_stress(ib, hcell)
4127  !
4128  ! -- fill delay bed pcs
4129  pcs = this%pcs(ib)
4130  do n = 1, this%ndelaycells
4131  zbot = this%dbz(n, idelay) - dzhalf
4132  ! -- adjust pcs to bottom of each delay bed cell
4133  ! not using csub_calc_adjes() since smoothing not required
4134  dbpcs = pcs - (zbot - bot) * (this%sgs(node) - done)
4135  this%dbpcs(n, idelay) = dbpcs
4136  !
4137  ! -- initialize effective stress for previous time step
4138  this%dbes0(n, idelay) = this%dbes(n, idelay)
4139  end do
4140  end if
4141  end do
4142  !
4143  ! -- scale coarse-grained materials cr
4144  do node = 1, nodes
4145  top = this%dis%top(node)
4146  bot = this%dis%bot(node)
4147  !
4148  ! -- user-specified specific storage
4149  if (this%istoragec == 1) then
4150  !
4151  ! -- retain specific storage values since they are constant
4152  if (this%lhead_based .EQV. .true.) then
4153  fact = done
4154  !
4155  ! -- convert specific storage values since they are simulated to
4156  ! be a function of the average effective stress
4157  else
4158  void_ratio = this%csub_calc_void_ratio(this%cg_theta(node))
4159  es = this%cg_es(node)
4160  hcell = hnew(node)
4161  !
4162  ! -- calculate corrected head (hbar)
4163  hbar = squadratic0sp(hcell, bot, this%satomega)
4164  !
4165  ! -- calculate znode and factor
4166  znode = this%csub_calc_znode(top, bot, hbar)
4167  fact = this%csub_calc_adjes(node, es, bot, znode)
4168  fact = fact * (done + void_ratio)
4169  end if
4170  !
4171  ! -- user-specified compression indices - multiply by dlog10es
4172  else
4173  fact = dlog10es
4174  end if
4175  this%cg_ske_cr(node) = this%cg_ske_cr(node) * fact
4176  !
4177  ! -- write error message if negative compression indices
4178  if (fact <= dzero) then
4179  call this%dis%noder_to_string(node, cellid)
4180  write (errmsg, '(a,1x,a,a)') &
4181  'Negative recompression index calculated for cell', &
4182  trim(adjustl(cellid)), '.'
4183  call store_error(errmsg)
4184  end if
4185  end do
4186  !
4187  ! -- scale interbed cc and cr
4188  do ib = 1, this%ninterbeds
4189  idelay = this%idelay(ib)
4190  node = this%nodelist(ib)
4191  top = this%dis%top(node)
4192  bot = this%dis%bot(node)
4193  !
4194  ! -- user-specified specific storage
4195  if (this%istoragec == 1) then
4196  !
4197  ! -- retain specific storage values since they are constant
4198  if (this%lhead_based .EQV. .true.) then
4199  fact = done
4200  !
4201  ! -- convert specific storage values since they are simulated to
4202  ! be a function of the average effective stress
4203  else
4204  void_ratio = this%csub_calc_void_ratio(this%theta(ib))
4205  es = this%cg_es(node)
4206  hcell = hnew(node)
4207  !
4208  ! -- calculate corrected head (hbar)
4209  hbar = squadratic0sp(hcell, bot, this%satomega)
4210  !
4211  ! -- calculate zone and factor
4212  znode = this%csub_calc_znode(top, bot, hbar)
4213  fact = this%csub_calc_adjes(node, es, bot, znode)
4214  fact = fact * (done + void_ratio)
4215  end if
4216  !
4217  ! -- user-specified compression indices - multiply by dlog10es
4218  else
4219  fact = dlog10es
4220  end if
4221  this%ci(ib) = this%ci(ib) * fact
4222  this%rci(ib) = this%rci(ib) * fact
4223  !
4224  ! -- write error message if negative compression indices
4225  if (fact <= dzero) then
4226  call this%dis%noder_to_string(node, cellid)
4227  write (errmsg, '(a,1x,i0,2(1x,a),a)') &
4228  'Negative compression indices calculated for interbed', ib, &
4229  'in cell', trim(adjustl(cellid)), '.'
4230  call store_error(errmsg)
4231  end if
4232  end do
4233  !
4234  ! -- write current stress and initial preconsolidation stress
4235  if (this%iprpak == 1) then
4236  ! -- set title
4237  title = trim(adjustl(this%packName))// &
4238  ' PACKAGE CALCULATED INITIAL INTERBED STRESSES AT THE CELL BOTTOM'
4239  !
4240  ! -- determine the number of columns and rows
4241  ntabrows = this%ninterbeds
4242  ntabcols = 5
4243  if (this%inamedbound /= 0) then
4244  ntabcols = ntabcols + 1
4245  end if
4246  !
4247  ! -- setup table
4248  call table_cr(this%inputtab, this%packName, title)
4249  call this%inputtab%table_df(ntabrows, ntabcols, this%iout)
4250  !
4251  ! add columns
4252  tag = 'INTERBED NUMBER'
4253  call this%inputtab%initialize_column(tag, 10, alignment=tableft)
4254  tag = 'CELLID'
4255  call this%inputtab%initialize_column(tag, 20)
4256  tag = 'GEOSTATIC STRESS'
4257  call this%inputtab%initialize_column(tag, 16)
4258  tag = 'EFFECTIVE STRESS'
4259  call this%inputtab%initialize_column(tag, 16)
4260  tag = 'PRECONSOLIDATION STRESS'
4261  call this%inputtab%initialize_column(tag, 16)
4262  if (this%inamedbound /= 0) then
4263  tag = 'BOUNDNAME'
4264  call this%inputtab%initialize_column(tag, lenboundname, &
4265  alignment=tableft)
4266  end if
4267  !
4268  ! -- write the data
4269  do ib = 1, this%ninterbeds
4270  node = this%nodelist(ib)
4271  call this%dis%noder_to_string(node, cellid)
4272  !
4273  ! -- write the columns
4274  call this%inputtab%add_term(ib)
4275  call this%inputtab%add_term(cellid)
4276  call this%inputtab%add_term(this%cg_gs(node))
4277  call this%inputtab%add_term(this%cg_es(node))
4278  call this%inputtab%add_term(this%pcs(ib))
4279  if (this%inamedbound /= 0) then
4280  call this%inputtab%add_term(this%boundname(ib))
4281  end if
4282  end do
4283  !
4284  ! -- write effective stress and preconsolidation stress
4285  ! for delay beds
4286  ! -- set title
4287  title = trim(adjustl(this%packName))// &
4288  ' PACKAGE CALCULATED INITIAL DELAY INTERBED STRESSES'
4289  !
4290  ! -- determine the number of columns and rows
4291  ntabrows = 0
4292  do ib = 1, this%ninterbeds
4293  idelay = this%idelay(ib)
4294  if (idelay /= 0) then
4295  ntabrows = ntabrows + this%ndelaycells
4296  end if
4297  end do
4298  ntabcols = 6
4299  if (this%inamedbound /= 0) then
4300  ntabcols = ntabcols + 1
4301  end if
4302  !
4303  ! -- setup table
4304  call table_cr(this%inputtab, this%packName, title)
4305  call this%inputtab%table_df(ntabrows, ntabcols, this%iout)
4306  !
4307  ! add columns
4308  tag = 'INTERBED NUMBER'
4309  call this%inputtab%initialize_column(tag, 10, alignment=tableft)
4310  tag = 'CELLID'
4311  call this%inputtab%initialize_column(tag, 20)
4312  tag = 'DELAY CELL'
4313  call this%inputtab%initialize_column(tag, 10, alignment=tableft)
4314  tag = 'GEOSTATIC STRESS'
4315  call this%inputtab%initialize_column(tag, 16)
4316  tag = 'EFFECTIVE STRESS'
4317  call this%inputtab%initialize_column(tag, 16)
4318  tag = 'PRECONSOLIDATION STRESS'
4319  call this%inputtab%initialize_column(tag, 16)
4320  if (this%inamedbound /= 0) then
4321  tag = 'BOUNDNAME'
4322  call this%inputtab%initialize_column(tag, lenboundname, &
4323  alignment=tableft)
4324  end if
4325  !
4326  ! -- write the data
4327  do ib = 1, this%ninterbeds
4328  idelay = this%idelay(ib)
4329  if (idelay /= 0) then
4330  node = this%nodelist(ib)
4331  call this%dis%noder_to_string(node, cellid)
4332  !
4333  ! -- write the columns
4334  do n = 1, this%ndelaycells
4335  if (n == 1) then
4336  call this%inputtab%add_term(ib)
4337  call this%inputtab%add_term(cellid)
4338  else
4339  call this%inputtab%add_term(' ')
4340  call this%inputtab%add_term(' ')
4341  end if
4342  call this%inputtab%add_term(n)
4343  call this%inputtab%add_term(this%dbgeo(n, idelay))
4344  call this%inputtab%add_term(this%dbes(n, idelay))
4345  call this%inputtab%add_term(this%dbpcs(n, idelay))
4346  if (this%inamedbound /= 0) then
4347  if (n == 1) then
4348  call this%inputtab%add_term(this%boundname(ib))
4349  else
4350  call this%inputtab%add_term(' ')
4351  end if
4352  end if
4353  end do
4354  end if
4355  end do
4356  !
4357  ! -- write calculated compression indices
4358  if (this%istoragec == 1) then
4359  if (this%lhead_based .EQV. .false.) then
4360  ! -- set title
4361  title = trim(adjustl(this%packName))// &
4362  ' PACKAGE COMPRESSION INDICES'
4363  !
4364  ! -- determine the number of columns and rows
4365  ntabrows = this%ninterbeds
4366  ntabcols = 4
4367  if (this%inamedbound /= 0) then
4368  ntabcols = ntabcols + 1
4369  end if
4370  !
4371  ! -- setup table
4372  call table_cr(this%inputtab, this%packName, title)
4373  call this%inputtab%table_df(ntabrows, ntabcols, this%iout)
4374  !
4375  ! add columns
4376  tag = 'INTERBED NUMBER'
4377  call this%inputtab%initialize_column(tag, 10, alignment=tableft)
4378  tag = 'CELLID'
4379  call this%inputtab%initialize_column(tag, 20)
4380  tag = 'CC'
4381  call this%inputtab%initialize_column(tag, 16)
4382  tag = 'CR'
4383  call this%inputtab%initialize_column(tag, 16)
4384  if (this%inamedbound /= 0) then
4385  tag = 'BOUNDNAME'
4386  call this%inputtab%initialize_column(tag, lenboundname, &
4387  alignment=tableft)
4388  end if
4389  !
4390  ! -- write the data
4391  do ib = 1, this%ninterbeds
4392  fact = done / dlog10es
4393  node = this%nodelist(ib)
4394  call this%dis%noder_to_string(node, cellid)
4395  !
4396  ! -- write the columns
4397  call this%inputtab%add_term(ib)
4398  call this%inputtab%add_term(cellid)
4399  call this%inputtab%add_term(this%ci(ib) * fact)
4400  call this%inputtab%add_term(this%rci(ib) * fact)
4401  if (this%inamedbound /= 0) then
4402  call this%inputtab%add_term(this%boundname(ib))
4403  end if
4404  end do
4405  end if
4406  end if
4407  end if
4408  !
4409  ! -- terminate if any initialization errors have been detected
4410  if (count_errors() > 0) then
4411  call store_error_filename(this%input_fname)
4412  end if
4413  !
4414  ! -- set initialized
4415  this%initialized = 1
4416  !
4417  ! -- set flag to retain initial stresses for entire simulation
4418  if (this%lhead_based .EQV. .true.) then
4419  this%iupdatestress = 0
4420  end if
4421  end subroutine csub_set_initial_state
4422 
4423  !> @ brief Formulate the coefficients for coarse-grained materials
4424  !!
4425  !! Method formulates the coefficient matrix and right-hand side terms
4426  !! for coarse grained materials in a cell.
4427  !!
4428  !! @param[in,out] hcof coarse-grained A matrix entry
4429  !! @param[in,out] rhs coarse-grained right-hand side entry
4430  !!
4431  !<
4432  subroutine csub_cg_fc(this, node, tled, area, hcell, hcellold, hcof, rhs)
4433  ! -- dummy variables
4434  class(gwfcsubtype) :: this
4435  integer(I4B), intent(in) :: node !< cell node number
4436  real(DP), intent(in) :: tled !< recripicol of the time step length
4437  real(DP), intent(in) :: area !< horizontal cell area
4438  real(DP), intent(in) :: hcell !< current head
4439  real(DP), intent(in) :: hcellold !< previous head
4440  real(DP), intent(inout) :: hcof !< coarse-grained A matrix entry
4441  real(DP), intent(inout) :: rhs !< coarse-grained right-hand side entry
4442  ! -- local variables
4443  real(DP) :: top
4444  real(DP) :: bot
4445  real(DP) :: tthk
4446  real(DP) :: snold
4447  real(DP) :: snnew
4448  real(DP) :: hbar
4449  real(DP) :: sske
4450  real(DP) :: rho1
4451  !
4452  ! -- initialize variables
4453  rhs = dzero
4454  hcof = dzero
4455  !
4456  ! -- aquifer elevations and thickness
4457  top = this%dis%top(node)
4458  bot = this%dis%bot(node)
4459  tthk = this%cg_thickini(node)
4460  !
4461  ! -- calculate hcof and rhs terms if coarse-grained materials present
4462  if (tthk > dzero) then
4463  !
4464  ! -- calculate aquifer saturation
4465  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
4466  !
4467  ! -- calculate corrected head (hbar)
4468  hbar = squadratic0sp(hcell, bot, this%satomega)
4469  !
4470  ! -- storage coefficients
4471  call this%csub_cg_calc_sske(node, sske, hcell)
4472  rho1 = sske * area * tthk * tled
4473  !
4474  ! -- update sk and ske
4475  this%cg_ske(node) = sske * tthk * snold
4476  this%cg_sk(node) = sske * tthk * snnew
4477  !
4478  ! -- calculate hcof and rhs term
4479  hcof = -rho1 * snnew
4480  rhs = rho1 * snold * this%cg_es0(node) - &
4481  rho1 * snnew * (this%cg_gs(node) + bot)
4482  !
4483  ! -- calculate and apply the flow correction term
4484  rhs = rhs - rho1 * snnew * (hcell - hbar)
4485  end if
4486  end subroutine csub_cg_fc
4487 
4488  !> @ brief Formulate coarse-grained Newton-Raphson terms
4489  !!
4490  !! Method formulates the coefficient matrix and right-hand side terms
4491  !! for coarse grained materials in a cell when using the Newton-Raphson
4492  !! formulation.
4493  !!
4494  !! @param[in,out] hcof coarse-grained A matrix entry
4495  !! @param[in,out] rhs coarse-grained right-hand side entry
4496  !!
4497  !<
4498  subroutine csub_cg_fn(this, node, tled, area, hcell, hcof, rhs)
4499  ! -- dummy variables
4500  class(gwfcsubtype) :: this
4501  integer(I4B), intent(in) :: node !< node number
4502  real(DP), intent(in) :: tled !< reciprocal of the time step length
4503  real(DP), intent(in) :: area !< horizontal cell area
4504  real(DP), intent(in) :: hcell !< current head in cell
4505  real(DP), intent(inout) :: hcof !< coarse-grained A matrix entry
4506  real(DP), intent(inout) :: rhs !< coarse-grained right-hand side entry
4507  ! -- local variables
4508  real(DP) :: top
4509  real(DP) :: bot
4510  real(DP) :: tthk
4511  real(DP) :: snnew
4512  real(DP) :: snold
4513  real(DP) :: satderv
4514  real(DP) :: hbar
4515  real(DP) :: hbarderv
4516  real(DP) :: sske
4517  real(DP) :: rho1
4518  !
4519  ! -- initialize variables
4520  rhs = dzero
4521  hcof = dzero
4522  !
4523  ! -- aquifer elevations and thickness
4524  top = this%dis%top(node)
4525  bot = this%dis%bot(node)
4526  tthk = this%cg_thickini(node)
4527  !
4528  ! -- calculate newton terms if coarse-grained materials present
4529  if (tthk > dzero) then
4530  !
4531  ! -- calculate aquifer saturation - only need snnew
4532  call this%csub_calc_sat(node, hcell, top, snnew, snold)
4533  !
4534  ! -- calculate saturation derivative
4535  satderv = this%csub_calc_sat_derivative(node, hcell)
4536  !
4537  ! -- calculate corrected head (hbar)
4538  hbar = squadratic0sp(hcell, bot, this%satomega)
4539  !
4540  ! -- calculate the derivative of the hbar functions
4541  hbarderv = squadratic0spderivative(hcell, bot, this%satomega)
4542  !
4543  ! -- storage coefficients
4544  call this%csub_cg_calc_sske(node, sske, hcell)
4545  rho1 = sske * area * tthk * tled
4546  !
4547  ! -- calculate hcof term
4548  hcof = rho1 * snnew * (done - hbarderv) + &
4549  rho1 * (this%cg_gs(node) - hbar + bot) * satderv
4550  !
4551  ! -- Add additional term if using lagged effective stress
4552  if (this%ieslag /= 0) then
4553  hcof = hcof - rho1 * this%cg_es0(node) * satderv
4554  end if
4555  !
4556  ! -- calculate rhs term
4557  rhs = hcof * hcell
4558  end if
4559  end subroutine csub_cg_fn
4560 
4561  !> @ brief Formulate the coefficients for a interbed
4562  !!
4563  !! Method formulates the coefficient matrix and right-hand side terms
4564  !! for a interbed in a cell.
4565  !!
4566  !! @param[in,out] hcof interbed A matrix entry
4567  !! @param[in,out] rhs interbed right-hand side entry
4568  !!
4569  !<
4570  subroutine csub_interbed_fc(this, ib, node, area, hcell, hcellold, hcof, rhs)
4571  ! -- dummy variables
4572  class(gwfcsubtype) :: this
4573  integer(I4B), intent(in) :: ib !< interbed number
4574  integer(I4B), intent(in) :: node !< cell node number
4575  real(DP), intent(in) :: area !< horizontal cell area
4576  real(DP), intent(in) :: hcell !< current head in cell
4577  real(DP), intent(in) :: hcellold !< previous head in cell
4578  real(DP), intent(inout) :: hcof !< interbed A matrix entry
4579  real(DP), intent(inout) :: rhs !< interbed right-hand side
4580  ! -- local variables
4581  real(DP) :: snnew
4582  real(DP) :: snold
4583  real(DP) :: comp
4584  real(DP) :: compi
4585  real(DP) :: compe
4586  real(DP) :: rho1
4587  real(DP) :: rho2
4588  real(DP) :: f
4589  !
4590  ! -- initialize variables
4591  rhs = dzero
4592  hcof = dzero
4593  comp = dzero
4594  compi = dzero
4595  compe = dzero
4596  !
4597  ! -- skip inactive and constant head cells
4598  if (this%ibound(node) > 0) then
4599  if (this%idelay(ib) == 0) then
4600  !
4601  ! -- update material properties
4602  if (this%iupdatematprop /= 0) then
4603  if (this%ieslag == 0) then
4604  !
4605  ! -- calculate compaction
4606  call this%csub_nodelay_calc_comp(ib, hcell, hcellold, comp, &
4607  rho1, rho2)
4608  this%comp(ib) = comp
4609  !
4610  ! -- update thickness and void ratio
4611  call this%csub_nodelay_update(ib)
4612  end if
4613  end if
4614  !
4615  ! -- calculate no-delay interbed rho1 and rho2
4616  call this%csub_nodelay_fc(ib, hcell, hcellold, rho1, hcof, rhs)
4617  f = area
4618  else
4619  !
4620  ! -- calculate cell saturation
4621  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
4622  !
4623  ! -- update material properties
4624  if (this%iupdatematprop /= 0) then
4625  if (this%ieslag == 0) then
4626  !
4627  ! -- calculate compaction
4628  call this%csub_delay_calc_comp(ib, hcell, hcellold, &
4629  comp, compi, compe)
4630  this%comp(ib) = comp
4631  !
4632  ! -- update thickness and void ratio
4633  call this%csub_delay_update(ib)
4634  end if
4635  end if
4636  !
4637  ! -- calculate delay interbed hcof and rhs
4638  call this%csub_delay_sln(ib, hcell)
4639  call this%csub_delay_fc(ib, hcof, rhs)
4640  f = area * this%rnb(ib)
4641  end if
4642  rhs = rhs * f
4643  hcof = -hcof * f
4644  end if
4645  end subroutine csub_interbed_fc
4646 
4647  !> @ brief Formulate the coefficients for a interbed
4648  !!
4649  !! Method formulates the Newton-Raphson formulation coefficient matrix and
4650  !! right-hand side terms for a interbed in a cell.
4651  !!
4652  !! @param[in,out] hcof interbed A matrix entry
4653  !! @param[in,out] rhs interbed right-hand side entry
4654  !!
4655  !<
4656  subroutine csub_interbed_fn(this, ib, node, hcell, hcellold, hcof, rhs)
4657  ! -- modules
4658  use tdismodule, only: delt
4659  ! -- dummy variables
4660  class(gwfcsubtype) :: this
4661  integer(I4B), intent(in) :: ib !< interbed number
4662  integer(I4B), intent(in) :: node !< cell node number
4663  real(DP), intent(in) :: hcell !< current head in a cell
4664  real(DP), intent(in) :: hcellold !< previous head in a cell
4665  real(DP), intent(inout) :: hcof !< interbed A matrix entry
4666  real(DP), intent(inout) :: rhs !< interbed right-hand side entry
4667  ! -- local variables
4668  integer(I4B) :: idelay
4669  real(DP) :: hcofn
4670  real(DP) :: rhsn
4671  real(DP) :: top
4672  real(DP) :: bot
4673  real(DP) :: tled
4674  real(DP) :: tthk
4675  real(DP) :: snnew
4676  real(DP) :: snold
4677  real(DP) :: f
4678  real(DP) :: satderv
4679  real(DP) :: hbar
4680  real(DP) :: hbarderv
4681  real(DP) :: rho1
4682  real(DP) :: rho2
4683  !
4684  ! -- initialize variables
4685  rhs = dzero
4686  hcof = dzero
4687  rhsn = dzero
4688  hcofn = dzero
4689  satderv = dzero
4690  idelay = this%idelay(ib)
4691  top = this%dis%top(node)
4692  bot = this%dis%bot(node)
4693  !
4694  ! -- skip inactive and constant head cells
4695  if (this%ibound(node) > 0) then
4696  tled = done / delt
4697  tthk = this%thickini(ib)
4698  !
4699  ! -- calculate cell saturation
4700  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
4701  !
4702  ! -- no-delay interbeds
4703  if (idelay == 0) then
4704  !
4705  ! -- initialize factor
4706  f = done
4707  !
4708  ! -- calculate the saturation derivative
4709  satderv = this%csub_calc_sat_derivative(node, hcell)
4710  !
4711  ! -- calculate corrected head (hbar)
4712  hbar = squadratic0sp(hcell, bot, this%satomega)
4713  !
4714  ! -- calculate the derivative of the hbar functions
4715  hbarderv = squadratic0spderivative(hcell, bot, this%satomega)
4716  !
4717  ! -- calculate storage coefficient
4718  call this%csub_nodelay_fc(ib, hcell, hcellold, rho1, rho2, rhsn)
4719  !
4720  ! -- calculate hcofn term
4721  hcofn = rho2 * (done - hbarderv) * snnew + &
4722  rho2 * (this%cg_gs(node) - hbar + bot) * satderv
4723  if (this%ielastic(ib) == 0) then
4724  hcofn = hcofn - rho2 * this%pcs(ib) * satderv
4725  end if
4726  !
4727  ! -- Add additional term if using lagged effective stress
4728  if (this%ieslag /= 0) then
4729  if (this%ielastic(ib) /= 0) then
4730  hcofn = hcofn - rho1 * this%cg_es0(node) * satderv
4731  else
4732  hcofn = hcofn - rho1 * (this%pcs(ib) - this%cg_es0(node)) * satderv
4733  end if
4734  end if
4735  end if
4736  end if
4737  end subroutine csub_interbed_fn
4738 
4739  !> @ brief Calculate Sske for a cell
4740  !!
4741  !! Method calculates Sske for coarse-grained materials in a cell.
4742  !!
4743  !! @param[in,out] sske coarse-grained Sske
4744  !!
4745  !<
4746  subroutine csub_cg_calc_sske(this, n, sske, hcell)
4747  ! -- dummy variables
4748  class(gwfcsubtype), intent(inout) :: this
4749  integer(I4B), intent(in) :: n !< cell node number
4750  real(DP), intent(inout) :: sske !< coarse grained Sske
4751  real(DP), intent(in) :: hcell !< current head in cell
4752  ! -- local variables
4753  real(DP) :: top
4754  real(DP) :: bot
4755  real(DP) :: hbar
4756  real(DP) :: znode
4757  real(DP) :: es
4758  real(DP) :: es0
4759  real(DP) :: theta
4760  real(DP) :: f
4761  real(DP) :: f0
4762  !
4763  ! -- initialize variables
4764  sske = dzero
4765  !
4766  ! -- calculate factor for the head-based case
4767  if (this%lhead_based .EQV. .true.) then
4768  f = done
4769  f0 = done
4770  !
4771  ! -- calculate factor for the effective stress case
4772  else
4773  top = this%dis%top(n)
4774  bot = this%dis%bot(n)
4775  !
4776  ! -- calculate corrected head (hbar)
4777  hbar = squadratic0sp(hcell, bot, this%satomega)
4778  !
4779  ! -- calculate znode
4780  znode = this%csub_calc_znode(top, bot, hbar)
4781  !
4782  ! -- calculate effective stress and theta
4783  es = this%cg_es(n)
4784  es0 = this%cg_es0(n)
4785  theta = this%cg_thetaini(n)
4786  !
4787  ! -- calculate the compression index factors for the delay
4788  ! node relative to the center of the cell based on the
4789  ! current and previous head
4790  call this%csub_calc_sfacts(n, bot, znode, theta, es, es0, f)
4791  end if
4792  sske = f * this%cg_ske_cr(n)
4793  end subroutine csub_cg_calc_sske
4794 
4795  !> @ brief Calculate coarse-grained compaction in a cell
4796  !!
4797  !! Method calculates coarse-grained compaction in a cell.
4798  !!
4799  !! @param[in,out] comp coarse-grained compaction
4800  !!
4801  !<
4802  subroutine csub_cg_calc_comp(this, node, hcell, hcellold, comp)
4803  ! -- dummy variables
4804  class(gwfcsubtype) :: this
4805  integer(I4B), intent(in) :: node !< cell node number
4806  real(DP), intent(in) :: hcell !< current head in cell
4807  real(DP), intent(in) :: hcellold !< previous head in cell
4808  real(DP), intent(inout) :: comp !< coarse-grained compaction
4809  ! -- local variables
4810  real(DP) :: area
4811  real(DP) :: tled
4812  real(DP) :: hcof
4813  real(DP) :: rhs
4814  !
4815  ! -- initialize variables
4816  area = done
4817  tled = done
4818  !
4819  ! -- calculate terms
4820  call this%csub_cg_fc(node, tled, area, hcell, hcellold, hcof, rhs)
4821  !
4822  ! - calculate compaction
4823  comp = hcof * hcell - rhs
4824  end subroutine csub_cg_calc_comp
4825 
4826  !> @ brief Update coarse-grained material properties
4827  !!
4828  !! Method updates coarse-grained material properties in a cell.
4829  !!
4830  !<
4831  subroutine csub_cg_update(this, node)
4832  ! -- dummy variables
4833  class(gwfcsubtype), intent(inout) :: this
4834  integer(I4B), intent(in) :: node !< cell node number
4835  ! -- local variables
4836  character(len=20) :: cellid
4837  real(DP) :: comp
4838  real(DP) :: thick
4839  real(DP) :: theta
4840  !
4841  ! -- update thickness and theta
4842  comp = this%cg_tcomp(node) + this%cg_comp(node)
4843  call this%dis%noder_to_string(node, cellid)
4844  if (abs(comp) > dzero) then
4845  thick = this%cg_thickini(node)
4846  theta = this%cg_thetaini(node)
4847  call this%csub_adj_matprop(comp, thick, theta)
4848  if (thick <= dzero) then
4849  write (errmsg, '(a,1x,a,1x,a,g0,a)') &
4850  'Adjusted thickness for cell', trim(adjustl(cellid)), &
4851  'is less than or equal to 0 (', thick, ').'
4852  call store_error(errmsg)
4853  end if
4854  if (theta <= dzero) then
4855  write (errmsg, '(a,1x,a,1x,a,g0,a)') &
4856  'Adjusted theta for cell', trim(adjustl(cellid)), &
4857  'is less than or equal to 0 (', theta, ').'
4858  call store_error(errmsg)
4859  end if
4860  this%cg_thick(node) = thick
4861  this%cg_theta(node) = theta
4862  end if
4863  end subroutine csub_cg_update
4864 
4865  !> @ brief Formulate coarse-grained water compressibility coefficients
4866  !!
4867  !! Method formulates the standard formulation coefficient matrix and
4868  !! right-hand side terms for water compressibility in coarse-grained
4869  !! sediments.
4870  !!
4871  !! @param[in,out] hcof coarse-grained A matrix entry
4872  !! @param[in,out] rhs coarse-grained right-hand side entry
4873  !!
4874  !<
4875  subroutine csub_cg_wcomp_fc(this, node, tled, area, hcell, hcellold, &
4876  hcof, rhs)
4877  ! -- dummy variables
4878  class(gwfcsubtype), intent(inout) :: this
4879  integer(I4B), intent(in) :: node !< cell node number
4880  real(DP), intent(in) :: tled !< reciprocal of the time step length
4881  real(DP), intent(in) :: area !< horizontal cell area
4882  real(DP), intent(in) :: hcell !< current head in cell
4883  real(DP), intent(in) :: hcellold !< previous head in cell
4884  real(DP), intent(inout) :: hcof !< coarse-grained A matrix entry
4885  real(DP), intent(inout) :: rhs !< coarse-grained right-hand side entry
4886  ! -- local variables
4887  real(DP) :: top
4888  real(DP) :: bot
4889  real(DP) :: tthk
4890  real(DP) :: tthk0
4891  real(DP) :: snold
4892  real(DP) :: snnew
4893  real(DP) :: wc
4894  real(DP) :: wc0
4895  !
4896  ! -- initialize variables
4897  rhs = dzero
4898  hcof = dzero
4899  !
4900  ! -- aquifer elevations and thickness
4901  top = this%dis%top(node)
4902  bot = this%dis%bot(node)
4903  tthk = this%cg_thick(node)
4904  tthk0 = this%cg_thick0(node)
4905  !
4906  ! -- aquifer saturation
4907  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
4908  !
4909  ! -- storage coefficients
4910  wc0 = this%brg * area * tthk0 * this%cg_theta0(node) * tled
4911  wc = this%brg * area * tthk * this%cg_theta(node) * tled
4912  !
4913  ! -- calculate hcof term
4914  hcof = -wc * snnew
4915  !
4916  ! -- calculate rhs term
4917  rhs = -wc0 * snold * hcellold
4918  end subroutine csub_cg_wcomp_fc
4919 
4920  !> @ brief Formulate coarse-grained water compressibility coefficients
4921  !!
4922  !! Method formulates the Newton-Raphson formulation coefficient matrix and
4923  !! right-hand side terms for water compressibility in coarse-grained
4924  !! sediments.
4925  !!
4926  !! @param[in,out] hcof coarse-grained A matrix entry
4927  !! @param[in,out] rhs coarse-grained right-hand side entry
4928  !!
4929  !<
4930  subroutine csub_cg_wcomp_fn(this, node, tled, area, hcell, hcellold, hcof, rhs)
4931  ! -- dummy variables
4932  class(gwfcsubtype), intent(inout) :: this
4933  integer(I4B), intent(in) :: node !< cell node number
4934  real(DP), intent(in) :: tled !< reciprocal of the time step length
4935  real(DP), intent(in) :: area !< horizontal cell area
4936  real(DP), intent(in) :: hcell !< current head in cell
4937  real(DP), intent(in) :: hcellold !< previous head in cell
4938  real(DP), intent(inout) :: hcof !< coarse-grained A matrix entry
4939  real(DP), intent(inout) :: rhs !< coarse-grained right-hand side entry
4940  ! -- local variables
4941  real(DP) :: top
4942  real(DP) :: bot
4943  real(DP) :: tthk
4944  real(DP) :: tthk0
4945  real(DP) :: satderv
4946  real(DP) :: f
4947  real(DP) :: wc
4948  real(DP) :: wc0
4949  !
4950  ! -- initialize variables
4951  rhs = dzero
4952  hcof = dzero
4953  !
4954  ! -- aquifer elevations and thickness
4955  top = this%dis%top(node)
4956  bot = this%dis%bot(node)
4957  tthk = this%cg_thick(node)
4958  !
4959  ! -- calculate saturation derivative
4960  satderv = this%csub_calc_sat_derivative(node, hcell)
4961  !
4962  ! -- calculate water compressibility factor
4963  f = this%brg * area * tled
4964  !
4965  ! -- water compressibility coefficient
4966  wc = f * tthk * this%cg_theta(node)
4967  !
4968  ! -- calculate hcof term
4969  hcof = -wc * hcell * satderv
4970  !
4971  ! -- Add additional term if using lagged effective stress
4972  if (this%ieslag /= 0) then
4973  tthk0 = this%cg_thick0(node)
4974  wc0 = f * tthk0 * this%cg_theta0(node)
4975  hcof = hcof + wc * hcellold * satderv
4976  end if
4977  !
4978  ! -- calculate rhs term
4979  rhs = hcof * hcell
4980  end subroutine csub_cg_wcomp_fn
4981 
4982  !> @ brief Formulate no-delay interbed water compressibility coefficients
4983  !!
4984  !! Method formulates the standard formulation coefficient matrix and
4985  !! right-hand side terms for water compressibility in no-delay
4986  !! interbeds.
4987  !!
4988  !! @param[in,out] hcof no-delay A matrix entry
4989  !! @param[in,out] rhs no-delay right-hand side entry
4990  !!
4991  !<
4992  subroutine csub_nodelay_wcomp_fc(this, ib, node, tled, area, &
4993  hcell, hcellold, hcof, rhs)
4994  ! -- dummy variables
4995  class(gwfcsubtype), intent(inout) :: this
4996  integer(I4B), intent(in) :: ib !< interbed number
4997  integer(I4B), intent(in) :: node !< cell node number
4998  real(DP), intent(in) :: tled !< reciprocal of time step length
4999  real(DP), intent(in) :: area !< horizontal cell area
5000  real(DP), intent(in) :: hcell !< current head in cell
5001  real(DP), intent(in) :: hcellold !< previous head in cell
5002  real(DP), intent(inout) :: hcof !< no-delay A matrix entry
5003  real(DP), intent(inout) :: rhs !< no-delay right-hand side entry
5004  ! -- local variables
5005  real(DP) :: top
5006  real(DP) :: bot
5007  real(DP) :: snold
5008  real(DP) :: snnew
5009  real(DP) :: f
5010  real(DP) :: wc
5011  real(DP) :: wc0
5012  !
5013  ! -- initialize variables
5014  rhs = dzero
5015  hcof = dzero
5016  !
5017  ! -- aquifer elevations and thickness
5018  top = this%dis%top(node)
5019  bot = this%dis%bot(node)
5020  !
5021  ! -- calculate cell saturation
5022  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
5023  !
5024  !
5025  f = this%brg * area * tled
5026  wc0 = f * this%theta0(ib) * this%thick0(ib)
5027  wc = f * this%theta(ib) * this%thick(ib)
5028  hcof = -wc * snnew
5029  rhs = -wc0 * snold * hcellold
5030  end subroutine csub_nodelay_wcomp_fc
5031 
5032  !> @ brief Formulate no-delay interbed water compressibility coefficients
5033  !!
5034  !! Method formulates the Newton-Raphson formulation coefficient matrix and
5035  !! right-hand side terms for water compressibility in no-delay
5036  !! interbeds.
5037  !!
5038  !! @param[in,out] hcof no-delay A matrix entry
5039  !! @param[in,out] rhs no-delay right-hand side entry
5040  !!
5041  !<
5042  subroutine csub_nodelay_wcomp_fn(this, ib, node, tled, area, &
5043  hcell, hcellold, hcof, rhs)
5044  ! -- dummy variables
5045  class(gwfcsubtype), intent(inout) :: this
5046  integer(I4B), intent(in) :: ib !< interbed number
5047  integer(I4B), intent(in) :: node !< cell node number
5048  real(DP), intent(in) :: tled !< reciprocal of time step length
5049  real(DP), intent(in) :: area !< horizontal cell area
5050  real(DP), intent(in) :: hcell !< current head in cell
5051  real(DP), intent(in) :: hcellold !< previous head in cell
5052  real(DP), intent(inout) :: hcof !< no-delay A matrix entry
5053  real(DP), intent(inout) :: rhs !< no-delay right-hand side entry
5054  ! -- local variables
5055  real(DP) :: top
5056  real(DP) :: bot
5057  real(DP) :: f
5058  real(DP) :: wc
5059  real(DP) :: wc0
5060  real(DP) :: satderv
5061  !
5062  ! -- initialize variables
5063  rhs = dzero
5064  hcof = dzero
5065  !
5066  ! -- aquifer elevations and thickness
5067  top = this%dis%top(node)
5068  bot = this%dis%bot(node)
5069  !
5070  !
5071  f = this%brg * area * tled
5072  !
5073  ! -- calculate saturation derivative
5074  satderv = this%csub_calc_sat_derivative(node, hcell)
5075  !
5076  ! -- calculate the current water compressibility factor
5077  wc = f * this%theta(ib) * this%thick(ib)
5078  !
5079  ! -- calculate derivative term
5080  hcof = -wc * hcell * satderv
5081  !
5082  ! -- Add additional term if using lagged effective stress
5083  if (this%ieslag /= 0) then
5084  wc0 = f * this%theta0(ib) * this%thick0(ib)
5085  hcof = hcof + wc0 * hcellold * satderv
5086  end if
5087  !
5088  ! -- set rhs
5089  rhs = hcof * hcell
5090  end subroutine csub_nodelay_wcomp_fn
5091 
5092  !> @brief Calculate the void ratio
5093  !!
5094  !! Function to calculate the void ratio from the porosity.
5095  !!
5096  !! @return void void ratio
5097  !<
5098  function csub_calc_void_ratio(this, theta) result(void_ratio)
5099  ! -- dummy variables
5100  class(gwfcsubtype), intent(inout) :: this
5101  real(dp), intent(in) :: theta !< porosity
5102  ! -- local variables
5103  real(dp) :: void_ratio
5104  ! -- calculate void ratio
5105  void_ratio = theta / (done - theta)
5106  end function csub_calc_void_ratio
5107 
5108  !> @brief Calculate the porosity
5109  !!
5110  !! Function to calculate the porosity from the void ratio.
5111  !!
5112  !! @return theta porosity
5113  !<
5114  function csub_calc_theta(this, void_ratio) result(theta)
5115  ! -- dummy variables
5116  class(gwfcsubtype), intent(inout) :: this
5117  real(dp), intent(in) :: void_ratio
5118  ! -- local variables
5119  real(dp) :: theta
5120  !
5121  ! -- calculate theta
5122  theta = void_ratio / (done + void_ratio)
5123  end function csub_calc_theta
5124 
5125  !> @brief Calculate the interbed thickness
5126  !!
5127  !! Function to calculate the interbed thickness.
5128  !!
5129  !! @return thick interbed thickness
5130  !<
5131  function csub_calc_interbed_thickness(this, ib) result(thick)
5132  ! -- dummy variables
5133  class(gwfcsubtype), intent(inout) :: this
5134  integer(I4B), intent(in) :: ib !< interbed number
5135  ! -- local variables
5136  integer(I4B) :: idelay
5137  real(dp) :: thick
5138  !
5139  ! -- calculate interbed thickness
5140  idelay = this%idelay(ib)
5141  thick = this%thick(ib)
5142  if (idelay /= 0) then
5143  thick = thick * this%rnb(ib)
5144  end if
5145  end function csub_calc_interbed_thickness
5146 
5147  !> @brief Calculate the cell node
5148  !!
5149  !! Function to calculate elevation of the node between the specified corrected
5150  !! elevation zbar and the bottom elevation. If zbar is greater than the top
5151  !! elevation, the node elevation is halfway between the top and bottom
5152  !! elevations. The corrected elevation (zbar) is always greater than or
5153  !! equal to bottom.
5154  !!
5155  !! @return znode node elevation
5156  !<
5157  function csub_calc_znode(this, top, bottom, zbar) result(znode)
5158  ! -- dummy variables
5159  class(gwfcsubtype), intent(inout) :: this
5160  real(dp), intent(in) :: top !< top of cell
5161  real(dp), intent(in) :: bottom !< bottom of cell
5162  real(dp), intent(in) :: zbar !< corrected elevation
5163  ! -- local variables
5164  real(dp) :: znode
5165  real(dp) :: v
5166  !
5167  ! -- calculate the node elevation
5168  if (zbar > top) then
5169  v = top
5170  else
5171  v = zbar
5172  end if
5173  znode = dhalf * (v + bottom)
5174  end function csub_calc_znode
5175 
5176  !> @brief Calculate the effective stress at elevation z
5177  !!
5178  !! Function to calculate the effective stress at specified elevation z
5179  !! using the provided effective stress (es0) calculated at elevation
5180  !! z0 (which is <= z)
5181  !!
5182  !! @return es node elevation
5183  !<
5184  function csub_calc_adjes(this, node, es0, z0, z) result(es)
5185  ! -- dummy variables
5186  class(gwfcsubtype), intent(inout) :: this
5187  integer(I4B), intent(in) :: node !< cell node number
5188  real(dp), intent(in) :: es0 !< effective stress at elevation z0
5189  real(dp), intent(in) :: z0 !< elevation effective stress is calculate at
5190  real(dp), intent(in) :: z !< elevation to calculate effective stress at
5191  ! -- local variables
5192  real(dp) :: es
5193  !
5194  ! -- adjust effective stress to vertical node position
5195  es = es0 - (z - z0) * (this%sgs(node) - done)
5196  end function csub_calc_adjes
5197 
5198  !> @brief Check delay interbed head
5199  !!
5200  !! Method to determine if the delay interbed head in any delay cell
5201  !! in a non-convertible gwf cell is less than the top of each delay
5202  !! interbed cell.
5203  !!
5204  !<
5205  subroutine csub_delay_head_check(this, ib)
5206  ! -- dummy variables
5207  class(gwfcsubtype), intent(inout) :: this
5208  integer(I4B), intent(in) :: ib !< interbed number
5209  ! -- local variables
5210  integer(I4B) :: iviolate
5211  integer(I4B) :: idelay
5212  integer(I4B) :: node
5213  integer(I4B) :: n
5214  real(DP) :: z
5215  real(DP) :: h
5216  real(DP) :: dzhalf
5217  real(DP) :: ztop
5218  !
5219  ! -- initialize variables
5220  iviolate = 0
5221  idelay = this%idelay(ib)
5222  node = this%nodelist(ib)
5223  !
5224  ! -- evaluate every delay cell
5225  idelaycells: do n = 1, this%ndelaycells
5226  z = this%dbz(n, idelay)
5227  h = this%dbh(n, idelay)
5228  dzhalf = dhalf * this%dbdzini(1, idelay)
5229  !
5230  ! -- non-convertible cell
5231  if (this%stoiconv(node) == 0) then
5232  ztop = z + dzhalf
5233  if (h < ztop) then
5234  this%idb_nconv_count(1) = this%idb_nconv_count(1) + 1
5235  iviolate = 1
5236  end if
5237  end if
5238  !
5239  ! -- terminate the loop
5240  if (iviolate > 0) then
5241  exit idelaycells
5242  end if
5243  end do idelaycells
5244  end subroutine csub_delay_head_check
5245 
5246  !> @brief Calculate cell saturation
5247  !!
5248  !! Method to calculate the cell saturation for the current and
5249  !! previous time step.
5250  !!
5251  !! @param[in,out] snnew current saturation
5252  !! @param[in,out] snold previous saturation
5253  !!
5254  !<
5255  subroutine csub_calc_sat(this, node, hcell, hcellold, snnew, snold)
5256  ! -- dummy variables
5257  class(gwfcsubtype), intent(inout) :: this
5258  integer(I4B), intent(in) :: node !< cell node number
5259  real(DP), intent(in) :: hcell !< current head
5260  real(DP), intent(in) :: hcellold !< previous head
5261  real(DP), intent(inout) :: snnew !< current saturation
5262  real(DP), intent(inout) :: snold !< previous saturation
5263  ! -- local variables
5264  real(DP) :: top
5265  real(DP) :: bot
5266  !
5267  ! -- calculate cell saturation
5268  if (this%stoiconv(node) /= 0) then
5269  top = this%dis%top(node)
5270  bot = this%dis%bot(node)
5271  snnew = squadraticsaturation(top, bot, hcell, this%satomega)
5272  snold = squadraticsaturation(top, bot, hcellold, this%satomega)
5273  else
5274  snnew = done
5275  snold = done
5276  end if
5277  if (this%ieslag /= 0) then
5278  snold = snnew
5279  end if
5280  end subroutine csub_calc_sat
5281 
5282  !> @brief Calculate the saturation derivative
5283  !!
5284  !! Function to calculate the derivative of the saturation with
5285  !! respect to the current head.
5286  !!
5287  !! @return satderv derivative of saturation
5288  !<
5289  function csub_calc_sat_derivative(this, node, hcell) result(satderv)
5290  ! -- dummy variables
5291  class(gwfcsubtype), intent(inout) :: this
5292  integer(I4B), intent(in) :: node !< cell node number
5293  real(dp), intent(in) :: hcell !< current head
5294  ! -- local variables
5295  real(dp) :: satderv
5296  real(dp) :: top
5297  real(dp) :: bot
5298 
5299  if (this%stoiconv(node) /= 0) then
5300  top = this%dis%top(node)
5301  bot = this%dis%bot(node)
5302  satderv = squadraticsaturationderivative(top, bot, hcell, this%satomega)
5303  else
5304  satderv = dzero
5305  end if
5306  end function csub_calc_sat_derivative
5307 
5308  !> @brief Calculate specific storage coefficient factor
5309  !!
5310  !! Method to calculate the factor that is used to calculate skeletal
5311  !! specific storage coefficients. Can be used for coarse-grained
5312  !! materials and interbeds.
5313  !!
5314  !! @param[in,out] fact skeletal storage coefficient factor
5315  !!
5316  !<
5317  subroutine csub_calc_sfacts(this, node, bot, znode, theta, es, es0, fact)
5318  ! -- dummy variables
5319  class(gwfcsubtype), intent(inout) :: this
5320  integer(I4B), intent(in) :: node !< cell node number
5321  real(DP), intent(in) :: bot !
5322  real(DP), intent(in) :: znode
5323  real(DP), intent(in) :: theta !< porosity
5324  real(DP), intent(in) :: es !< current effective stress
5325  real(DP), intent(in) :: es0 !< previous effective stress
5326  real(DP), intent(inout) :: fact !< skeletal storage coefficient factor (1/((1+void_ratio)*bar(es)))
5327  ! -- local variables
5328  real(DP) :: esv
5329  real(DP) :: void_ratio
5330  real(DP) :: denom
5331  !
5332  ! -- initialize variables
5333  fact = dzero
5334  if (this%ieslag /= 0) then
5335  esv = es0
5336  else
5337  esv = es
5338  end if
5339  !
5340  ! -- calculate storage factors for the effective stress case
5341  void_ratio = this%csub_calc_void_ratio(theta)
5342  denom = this%csub_calc_adjes(node, esv, bot, znode)
5343  denom = denom * (done + void_ratio)
5344  if (denom /= dzero) then
5345  fact = done / denom
5346  end if
5347  end subroutine csub_calc_sfacts
5348 
5349  !> @brief Calculate new material properties
5350  !!
5351  !! Method to calculate the current thickness and porosity.
5352  !!
5353  !! @param[in,out] thick initial and current thickness
5354  !! @param[in,out] theta initial and current porosity
5355  !!
5356  !<
5357  subroutine csub_adj_matprop(this, comp, thick, theta)
5358  ! -- dummy variables
5359  class(gwfcsubtype), intent(inout) :: this
5360  real(DP), intent(in) :: comp !< compaction
5361  real(DP), intent(inout) :: thick !< thickness
5362  real(DP), intent(inout) :: theta !< porosity
5363  ! -- local variables
5364  real(DP) :: strain
5365  real(DP) :: void_ratio
5366  !
5367  ! -- initialize variables
5368  strain = dzero
5369  void_ratio = this%csub_calc_void_ratio(theta)
5370  !
5371  ! -- calculate strain
5372  if (thick > dzero) strain = -comp / thick
5373  !
5374  ! -- update void ratio, theta, and thickness
5375  void_ratio = void_ratio + strain * (done + void_ratio)
5376  theta = this%csub_calc_theta(void_ratio)
5377  thick = thick - comp
5378  end subroutine csub_adj_matprop
5379 
5380  !> @brief Solve delay interbed continuity equation
5381  !!
5382  !! Method to calculate solve the delay interbed continuity equation for a
5383  !! delay interbed. The method encapsulates the non-linear loop and calls the
5384  !! linear solution.
5385  !!
5386  !<
5387  subroutine csub_delay_sln(this, ib, hcell, update)
5388  ! -- dummy variables
5389  class(gwfcsubtype), intent(inout) :: this
5390  integer(I4B), intent(in) :: ib !< interbed number
5391  real(DP), intent(in) :: hcell !< current head in a cell
5392  logical(LGP), intent(in), optional :: update !< optional logical variable indicating
5393  !! if the maximum head change variable
5394  !! in a delay bed should be updated
5395  ! -- local variables
5396  logical(LGP) :: lupdate
5397  integer(I4B) :: n
5398  integer(I4B) :: icnvg
5399  integer(I4B) :: iter
5400  integer(I4B) :: idelay
5401  real(DP) :: dh
5402  real(DP) :: dhmax
5403  real(DP) :: dhmax0
5404  real(DP), parameter :: dclose = dhundred * dprec
5405  !
5406  ! -- initialize variables
5407  if (present(update)) then
5408  lupdate = update
5409  else
5410  lupdate = .true.
5411  end if
5412  !
5413  ! -- calculate geostatic and effective stress for each delay bed cell
5414  call this%csub_delay_calc_stress(ib, hcell)
5415  !
5416  ! -- terminate if the aquifer head is below the top of delay interbeds
5417  if (count_errors() > 0) then
5418  call store_error_filename(this%input_fname)
5419  end if
5420  !
5421  ! -- solve for delay bed heads
5422  if (this%thickini(ib) > dzero) then
5423  icnvg = 0
5424  iter = 0
5425  idelay = this%idelay(ib)
5426  do
5427  iter = iter + 1
5428  !
5429  ! -- assemble coefficients
5430  call this%csub_delay_assemble(ib, hcell)
5431  !
5432  ! -- solve for head change in delay interbed cells
5433  call ims_misc_thomas(this%ndelaycells, &
5434  this%dbal, this%dbad, this%dbau, &
5435  this%dbrhs, this%dbdh, this%dbaw)
5436  !
5437  ! -- calculate maximum head change and update delay bed heads
5438  dhmax = dzero
5439  do n = 1, this%ndelaycells
5440  dh = this%dbdh(n) - this%dbh(n, idelay)
5441  if (abs(dh) > abs(dhmax)) then
5442  dhmax = dh
5443  if (lupdate) then
5444  this%dbdhmax(idelay) = dhmax
5445  end if
5446  end if
5447  ! -- update delay bed heads
5448  this%dbh(n, idelay) = this%dbdh(n)
5449  end do
5450  !
5451  ! -- update delay bed stresses
5452  call this%csub_delay_calc_stress(ib, hcell)
5453  !
5454  ! -- check delay bed convergence
5455  if (abs(dhmax) < dclose) then
5456  icnvg = 1
5457  else if (iter /= 1) then
5458  if (abs(dhmax) - abs(dhmax0) < dprec) then
5459  icnvg = 1
5460  end if
5461  end if
5462  if (icnvg == 1) then
5463  exit
5464  end if
5465  dhmax0 = dhmax
5466  end do
5467  end if
5468  end subroutine csub_delay_sln
5469 
5470  !> @brief Calculate delay interbed znode and z relative to interbed center
5471  !!
5472  !! Method to calculate the initial center of each delay interbed cell,
5473  !! assuming the delay bed head is equal to the top of the delay interbed.
5474  !! The method also calculates the distance of the center of each delay
5475  !! bed cell from the center of the delay interbed (z_offset) that is used
5476  !! to calculate average skeletal specific storage values for a delay interbed
5477  !! centered on the center of the saturated thickness for a cell.
5478  !!
5479  !<
5480  subroutine csub_delay_init_zcell(this, ib)
5481  ! -- dummy variables
5482  class(gwfcsubtype), intent(inout) :: this
5483  integer(I4B), intent(in) :: ib !< interbed number
5484  ! -- local variables
5485  integer(I4B) :: n
5486  integer(I4B) :: node
5487  integer(I4B) :: idelay
5488  real(DP) :: bot
5489  real(DP) :: top
5490  real(DP) :: hbar
5491  real(DP) :: znode
5492  real(DP) :: dzz
5493  real(DP) :: z
5494  real(DP) :: zr
5495  real(DP) :: b
5496  real(DP) :: dz
5497  !
5498  ! -- initialize variables
5499  idelay = this%idelay(ib)
5500  node = this%nodelist(ib)
5501  b = this%thickini(ib)
5502  bot = this%dis%bot(node)
5503  top = bot + b
5504  hbar = top
5505  !
5506  ! -- calculate znode based on assumption that the delay bed bottom
5507  ! is equal to the cell bottom
5508  znode = this%csub_calc_znode(top, bot, hbar)
5509  dz = dhalf * this%dbdzini(1, idelay)
5510  dzz = dhalf * b
5511  z = znode + dzz
5512  zr = dzz
5513  !
5514  ! -- calculate z and z relative to znode for each delay
5515  ! interbed node
5516  do n = 1, this%ndelaycells
5517  ! z of node relative to bottom of cell
5518  z = z - dz
5519  this%dbz(n, idelay) = z
5520  z = z - dz
5521  ! z relative to znode
5522  zr = zr - dz
5523  if (abs(zr) < dz) then
5524  zr = dzero
5525  end if
5526  this%dbrelz(n, idelay) = zr
5527  zr = zr - dz
5528  end do
5529  end subroutine csub_delay_init_zcell
5530 
5531  !> @brief Calculate delay interbed stress values
5532  !!
5533  !! Method to calculate the geostatic and effective stress in delay interbed
5534  !! cells using the passed the current head value in a cell.
5535  !!
5536  !<
5537  subroutine csub_delay_calc_stress(this, ib, hcell)
5538  ! -- dummy variables
5539  class(gwfcsubtype), intent(inout) :: this
5540  integer(I4B), intent(in) :: ib !< interbed number
5541  real(DP), intent(in) :: hcell !< current head in a cell
5542  ! -- local variables
5543  integer(I4B) :: n
5544  integer(I4B) :: idelay
5545  integer(I4B) :: node
5546  real(DP) :: sigma
5547  real(DP) :: topaq
5548  real(DP) :: botaq
5549  real(DP) :: dzhalf
5550  real(DP) :: sadd
5551  real(DP) :: sgm
5552  real(DP) :: sgs
5553  real(DP) :: h
5554  real(DP) :: hbar
5555  real(DP) :: z
5556  real(DP) :: top
5557  real(DP) :: bot
5558  real(DP) :: phead
5559  !
5560  ! -- initialize variables
5561  idelay = this%idelay(ib)
5562  node = this%nodelist(ib)
5563  sigma = this%cg_gs(node)
5564  topaq = this%dis%top(node)
5565  botaq = this%dis%bot(node)
5566  dzhalf = dhalf * this%dbdzini(1, idelay)
5567  top = this%dbz(1, idelay) + dzhalf
5568  !
5569  ! -- calculate corrected head (hbar)
5570  hbar = squadratic0sp(hcell, botaq, this%satomega)
5571  !
5572  ! -- calculate the geostatic load in the cell at the top of the interbed.
5573  sgm = this%sgm(node)
5574  sgs = this%sgs(node)
5575  if (hcell < top) then
5576  sadd = ((top - hbar) * sgm) + ((hbar - botaq) * sgs)
5577  else
5578  sadd = (top - botaq) * sgs
5579  end if
5580  sigma = sigma - sadd
5581  !
5582  ! -- calculate geostatic and effective stress for each interbed node.
5583  do n = 1, this%ndelaycells
5584  h = this%dbh(n, idelay)
5585  !
5586  ! -- geostatic calculated at the bottom of the delay cell
5587  z = this%dbz(n, idelay)
5588  top = z + dzhalf
5589  bot = z - dzhalf
5590  !
5591  ! -- calculate corrected head (hbar)
5592  hbar = squadratic0sp(h, bot, this%satomega)
5593  !
5594  ! -- geostatic stress calculation
5595  if (h < top) then
5596  sadd = ((top - hbar) * sgm) + ((hbar - bot) * sgs)
5597  else
5598  sadd = (top - bot) * sgs
5599  end if
5600  sigma = sigma + sadd
5601  phead = hbar - bot
5602  this%dbgeo(n, idelay) = sigma
5603  this%dbes(n, idelay) = sigma - phead
5604  end do
5605  end subroutine csub_delay_calc_stress
5606 
5607  !> @brief Calculate delay interbed cell storage coefficients
5608  !!
5609  !! Method to calculate the ssk and sske value for a node in a delay
5610  !! interbed cell.
5611  !!
5612  !! @param[in,out] ssk skeletal specific storage value dependent on the
5613  !! preconsolidation stress
5614  !! @param[in,out] sske elastic skeletal specific storage value
5615  !!
5616  !<
5617  subroutine csub_delay_calc_ssksske(this, ib, n, hcell, ssk, sske)
5618  ! -- dummy variables
5619  class(gwfcsubtype), intent(inout) :: this
5620  integer(I4B), intent(in) :: ib !< interbed number
5621  integer(I4B), intent(in) :: n !< delay interbed cell number
5622  real(DP), intent(in) :: hcell !< current head in a cell
5623  real(DP), intent(inout) :: ssk !< delay interbed skeletal specific storage
5624  real(DP), intent(inout) :: sske !< delay interbed elastic skeletal specific storage
5625  ! -- local variables
5626  integer(I4B) :: idelay
5627  integer(I4B) :: ielastic
5628  integer(I4B) :: node
5629  real(DP) :: topcell
5630  real(DP) :: botcell
5631  real(DP) :: hbarcell
5632  real(DP) :: zcell
5633  real(DP) :: zcenter
5634  real(DP) :: dzhalf
5635  real(DP) :: top
5636  real(DP) :: bot
5637  real(DP) :: h
5638  real(DP) :: hbar
5639  real(DP) :: znode
5640  real(DP) :: zbot
5641  real(DP) :: es
5642  real(DP) :: es0
5643  real(DP) :: theta
5644  real(DP) :: f
5645  real(DP) :: f0
5646  !
5647  ! -- initialize variables
5648  sske = dzero
5649  ssk = dzero
5650  idelay = this%idelay(ib)
5651  ielastic = this%ielastic(ib)
5652  !
5653  ! -- calculate factor for the head-based case
5654  if (this%lhead_based .EQV. .true.) then
5655  f = done
5656  f0 = f
5657  !
5658  ! -- calculate factor for the effective stress case
5659  else
5660  node = this%nodelist(ib)
5661  theta = this%dbthetaini(n, idelay)
5662  !
5663  ! -- set top and bottom of layer
5664  topcell = this%dis%top(node)
5665  botcell = this%dis%bot(node)
5666  !
5667  ! -- calculate corrected head for the cell (hbarcell)
5668  hbarcell = squadratic0sp(hcell, botcell, this%satomega)
5669  !
5670  ! -- set location of delay node relative to the center
5671  ! of the cell based on current head
5672  zcell = this%csub_calc_znode(topcell, botcell, hbarcell)
5673  !
5674  ! -- set variables for delay interbed zcell calculations
5675  zcenter = zcell + this%dbrelz(n, idelay)
5676  dzhalf = dhalf * this%dbdzini(1, idelay)
5677  top = zcenter + dzhalf
5678  bot = zcenter - dzhalf
5679  h = this%dbh(n, idelay)
5680  !
5681  ! -- calculate corrected head for the delay interbed cell (hbar)
5682  hbar = squadratic0sp(h, bot, this%satomega)
5683  !
5684  ! -- calculate the center of the saturated portion of the
5685  ! delay interbed cell
5686  znode = this%csub_calc_znode(top, bot, hbar)
5687  !
5688  ! -- set reference point for bottom of delay interbed cell that is used to
5689  ! scale the effective stress at the bottom of the delay interbed cell
5690  zbot = this%dbz(n, idelay) - dzhalf
5691  !
5692  ! -- set the effective stress
5693  es = this%dbes(n, idelay)
5694  es0 = this%dbes0(n, idelay)
5695  !
5696  ! -- calculate the compression index factors for the delay
5697  ! node relative to the center of the cell based on the
5698  ! current and previous head
5699  call this%csub_calc_sfacts(node, zbot, znode, theta, es, es0, f)
5700  end if
5701  this%idbconvert(n, idelay) = 0
5702  sske = f * this%rci(ib)
5703  ssk = f * this%rci(ib)
5704  if (ielastic == 0) then
5705  if (this%dbes(n, idelay) > this%dbpcs(n, idelay)) then
5706  this%idbconvert(n, idelay) = 1
5707  ssk = f * this%ci(ib)
5708  end if
5709  end if
5710  end subroutine csub_delay_calc_ssksske
5711 
5712  !> @brief Assemble delay interbed coefficients
5713  !!
5714  !! Method to assemble matrix and right-hand side coefficients for a delay
5715  !! interbed. The method calls the appropriate standard or Newton-Raphson
5716  !! assembly routines and fills all of the entries for a delay interbed.
5717  !!
5718  !<
5719  subroutine csub_delay_assemble(this, ib, hcell)
5720  ! -- dummy variables
5721  class(gwfcsubtype), intent(inout) :: this
5722  integer(I4B), intent(in) :: ib !< interbed number
5723  real(DP), intent(in) :: hcell !< current head in a cell
5724  ! -- local variables
5725  integer(I4B) :: n
5726  real(DP) :: aii
5727  real(DP) :: au
5728  real(DP) :: al
5729  real(DP) :: r
5730  !
5731  ! -- calculate matrix terms for each delay bed cell
5732  do n = 1, this%ndelaycells
5733  !
5734  ! -- assemble terms
5735  if (this%inewton == 0) then
5736  call this%csub_delay_assemble_fc(ib, n, hcell, aii, au, al, r)
5737  else
5738  call this%csub_delay_assemble_fn(ib, n, hcell, aii, au, al, r)
5739  end if
5740  !
5741  ! -- add terms
5742  this%dbal(n) = al
5743  this%dbau(n) = au
5744  this%dbad(n) = aii
5745  this%dbrhs(n) = r
5746  end do
5747  end subroutine csub_delay_assemble
5748 
5749  !> @brief Assemble delay interbed standard formulation coefficients
5750  !!
5751  !! Method to assemble standard formulation matrix and right-hand side
5752  !! coefficients for a delay interbed.
5753  !!
5754  !<
5755  subroutine csub_delay_assemble_fc(this, ib, n, hcell, aii, au, al, r)
5756  ! -- modules
5757  use tdismodule, only: delt
5758  ! -- dummy variables
5759  class(gwfcsubtype), intent(inout) :: this
5760  integer(I4B), intent(in) :: ib !< interbed number
5761  integer(I4B), intent(in) :: n !< delay interbed cell number
5762  real(DP), intent(in) :: hcell !< current head in a cell
5763  real(DP), intent(inout) :: aii !< diagonal in the A matrix
5764  real(DP), intent(inout) :: au !< upper term in the A matrix
5765  real(DP), intent(inout) :: al !< lower term in the A matrix
5766  real(DP), intent(inout) :: r !< right-hand side term
5767  ! -- local variables
5768  integer(I4B) :: node
5769  integer(I4B) :: idelay
5770  integer(I4B) :: ielastic
5771  real(DP) :: dzini
5772  real(DP) :: dzhalf
5773  real(DP) :: c
5774  real(DP) :: c2
5775  real(DP) :: c3
5776  real(DP) :: tled
5777  real(DP) :: wcf
5778  real(DP) :: smult
5779  real(DP) :: sske
5780  real(DP) :: ssk
5781  real(DP) :: z
5782  real(DP) :: ztop
5783  real(DP) :: zbot
5784  real(DP) :: dz
5785  real(DP) :: dz0
5786  real(DP) :: theta
5787  real(DP) :: theta0
5788  real(DP) :: dsn
5789  real(DP) :: dsn0
5790  real(DP) :: gs
5791  real(DP) :: es0
5792  real(DP) :: pcs
5793  real(DP) :: wc
5794  real(DP) :: wc0
5795  real(DP) :: h
5796  real(DP) :: h0
5797  real(DP) :: hbar
5798  !
5799  ! -- initialize accumulators
5800  aii = dzero
5801  au = dzero
5802  al = dzero
5803  r = dzero
5804  !
5805  ! -- initialize local variables
5806  idelay = this%idelay(ib)
5807  ielastic = this%ielastic(ib)
5808  node = this%nodelist(ib)
5809  dzini = this%dbdzini(1, idelay)
5810  dzhalf = dhalf * dzini
5811  tled = done / delt
5812  c = this%kv(ib) / dzini
5813  c2 = dtwo * c
5814  c3 = dthree * c
5815  !
5816  ! -- add qdb terms
5817  aii = aii - c2
5818  !
5819  ! -- top or bottom cell
5820  if (n == 1 .or. n == this%ndelaycells) then
5821  aii = aii - c
5822  r = r - c2 * hcell
5823  end if
5824  !
5825  ! -- lower qdb term
5826  if (n > 1) then
5827  al = c
5828  end if
5829  !
5830  ! -- upper qdb term
5831  if (n < this%ndelaycells) then
5832  au = c
5833  end if
5834  !
5835  ! -- current and previous delay cell states
5836  z = this%dbz(n, idelay)
5837  ztop = z + dzhalf
5838  zbot = z - dzhalf
5839  h = this%dbh(n, idelay)
5840  h0 = this%dbh0(n, idelay)
5841  dz = this%dbdz(n, idelay)
5842  dz0 = this%dbdz0(n, idelay)
5843  theta = this%dbtheta(n, idelay)
5844  theta0 = this%dbtheta0(n, idelay)
5845  !
5846  ! -- calculate corrected head (hbar)
5847  hbar = squadratic0sp(h, zbot, this%satomega)
5848  !
5849  ! -- calculate saturation
5850  call this%csub_delay_calc_sat(node, idelay, n, h, h0, dsn, dsn0)
5851  !
5852  ! -- calculate ssk and sske
5853  call this%csub_delay_calc_ssksske(ib, n, hcell, ssk, sske)
5854  !
5855  ! -- calculate and add storage terms
5856  smult = dzini * tled
5857  gs = this%dbgeo(n, idelay)
5858  es0 = this%dbes0(n, idelay)
5859  pcs = this%dbpcs(n, idelay)
5860  aii = aii - smult * dsn * ssk
5861  if (ielastic /= 0) then
5862  r = r - smult * &
5863  (dsn * ssk * (gs + zbot) - dsn0 * sske * es0)
5864  else
5865  r = r - smult * &
5866  (dsn * ssk * (gs + zbot - pcs) + dsn0 * sske * (pcs - es0))
5867  end if
5868  !
5869  ! -- add storage correction term
5870  r = r + smult * dsn * ssk * (h - hbar)
5871  !
5872  ! -- add water compressibility terms
5873  wcf = this%brg * tled
5874  wc = dz * wcf * theta
5875  wc0 = dz0 * wcf * theta0
5876  aii = aii - dsn * wc
5877  r = r - dsn0 * wc0 * h0
5878  end subroutine csub_delay_assemble_fc
5879 
5880  !> @brief Assemble delay interbed Newton-Raphson formulation coefficients
5881  !!
5882  !! Method to assemble Newton-Raphson formulation matrix and right-hand side
5883  !! coefficients for a delay interbed.
5884  !!
5885  !<
5886  subroutine csub_delay_assemble_fn(this, ib, n, hcell, aii, au, al, r)
5887  ! -- modules
5888  use tdismodule, only: delt
5889  ! -- dummy variables
5890  class(gwfcsubtype), intent(inout) :: this
5891  integer(I4B), intent(in) :: ib !< interbed number
5892  integer(I4B), intent(in) :: n !< delay interbed cell number
5893  real(DP), intent(in) :: hcell !< current head in a cell
5894  real(DP), intent(inout) :: aii !< diagonal in the A matrix
5895  real(DP), intent(inout) :: au !< upper term in the A matrix
5896  real(DP), intent(inout) :: al !< lower term in the A matrix
5897  real(DP), intent(inout) :: r !< right-hand side term
5898  ! -- local variables
5899  integer(I4B) :: node
5900  integer(I4B) :: idelay
5901  integer(I4B) :: ielastic
5902  real(DP) :: dzini
5903  real(DP) :: dzhalf
5904  real(DP) :: c
5905  real(DP) :: c2
5906  real(DP) :: c3
5907  real(DP) :: tled
5908  real(DP) :: wcf
5909  real(DP) :: smult
5910  real(DP) :: sske
5911  real(DP) :: ssk
5912  real(DP) :: z
5913  real(DP) :: ztop
5914  real(DP) :: zbot
5915  real(DP) :: dz
5916  real(DP) :: dz0
5917  real(DP) :: theta
5918  real(DP) :: theta0
5919  real(DP) :: dsn
5920  real(DP) :: dsn0
5921  real(DP) :: dsnderv
5922  real(DP) :: wc
5923  real(DP) :: wc0
5924  real(DP) :: h
5925  real(DP) :: h0
5926  real(DP) :: hbar
5927  real(DP) :: hbarderv
5928  real(DP) :: gs
5929  real(DP) :: es0
5930  real(DP) :: pcs
5931  real(DP) :: qsto
5932  real(DP) :: stoderv
5933  real(DP) :: qwc
5934  real(DP) :: wcderv
5935  !
5936  ! -- initialize accumulators
5937  aii = dzero
5938  au = dzero
5939  al = dzero
5940  r = dzero
5941  !
5942  ! -- initialize local variables
5943  idelay = this%idelay(ib)
5944  ielastic = this%ielastic(ib)
5945  node = this%nodelist(ib)
5946  dzini = this%dbdzini(1, idelay)
5947  dzhalf = dhalf * dzini
5948  tled = done / delt
5949  c = this%kv(ib) / dzini
5950  c2 = dtwo * c
5951  c3 = dthree * c
5952  !
5953  ! -- add qdb terms
5954  aii = aii - c2
5955  !
5956  ! -- top or bottom cell
5957  if (n == 1 .or. n == this%ndelaycells) then
5958  aii = aii - c
5959  r = r - c2 * hcell
5960  end if
5961  !
5962  ! -- lower qdb term
5963  if (n > 1) then
5964  al = c
5965  end if
5966  !
5967  ! -- upper qdb term
5968  if (n < this%ndelaycells) then
5969  au = c
5970  end if
5971  !
5972  ! -- current and previous delay cell states
5973  z = this%dbz(n, idelay)
5974  ztop = z + dzhalf
5975  zbot = z - dzhalf
5976  h = this%dbh(n, idelay)
5977  h0 = this%dbh0(n, idelay)
5978  dz = this%dbdz(n, idelay)
5979  dz0 = this%dbdz0(n, idelay)
5980  theta = this%dbtheta(n, idelay)
5981  theta0 = this%dbtheta0(n, idelay)
5982  !
5983  ! -- calculate corrected head (hbar)
5984  hbar = squadratic0sp(h, zbot, this%satomega)
5985  !
5986  ! -- calculate the derivative of the hbar functions
5987  hbarderv = squadratic0spderivative(h, zbot, this%satomega)
5988  !
5989  ! -- calculate saturation
5990  call this%csub_delay_calc_sat(node, idelay, n, h, h0, dsn, dsn0)
5991  !
5992  ! -- calculate the derivative of the saturation
5993  dsnderv = this%csub_delay_calc_sat_derivative(node, idelay, n, hcell)
5994  !
5995  ! -- calculate ssk and sske
5996  call this%csub_delay_calc_ssksske(ib, n, hcell, ssk, sske)
5997  !
5998  ! -- calculate storage terms
5999  smult = dzini * tled
6000  gs = this%dbgeo(n, idelay)
6001  es0 = this%dbes0(n, idelay)
6002  pcs = this%dbpcs(n, idelay)
6003  if (ielastic /= 0) then
6004  qsto = smult * (dsn * ssk * (gs - hbar + zbot) - dsn0 * sske * es0)
6005  stoderv = -smult * dsn * ssk * hbarderv + &
6006  smult * ssk * (gs - hbar + zbot) * dsnderv
6007  else
6008  qsto = smult * (dsn * ssk * (gs - hbar + zbot - pcs) + &
6009  dsn0 * sske * (pcs - es0))
6010  stoderv = -smult * dsn * ssk * hbarderv + &
6011  smult * ssk * (gs - hbar + zbot - pcs) * dsnderv
6012  end if
6013  !
6014  ! -- Add additional term if using lagged effective stress
6015  if (this%ieslag /= 0) then
6016  if (ielastic /= 0) then
6017  stoderv = stoderv - smult * sske * es0 * dsnderv
6018  else
6019  stoderv = stoderv + smult * sske * (pcs - es0) * dsnderv
6020  end if
6021  end if
6022  !
6023  ! -- add newton-raphson storage terms
6024  aii = aii + stoderv
6025  r = r - qsto + stoderv * h
6026  !
6027  ! -- add water compressibility terms
6028  wcf = this%brg * tled
6029  wc = dz * wcf * theta
6030  wc0 = dz0 * wcf * theta0
6031  qwc = dsn0 * wc0 * h0 - dsn * wc * h
6032  wcderv = -dsn * wc - wc * h * dsnderv
6033  !
6034  ! -- Add additional term if using lagged effective stress
6035  if (this%ieslag /= 0) then
6036  wcderv = wcderv + wc0 * h0 * dsnderv
6037  end if
6038  !
6039  ! -- add newton-raphson water compressibility terms
6040  aii = aii + wcderv
6041  r = r - qwc + wcderv * h
6042  end subroutine csub_delay_assemble_fn
6043 
6044  !> @brief Calculate delay interbed saturation
6045  !!
6046  !! Method to calculate the saturation in a delay interbed cell.
6047  !!
6048  !! @param[in,out] snnew current saturation in delay interbed cell n
6049  !! @param[in,out] snold previous saturation in delay interbed cell n
6050  !!
6051  !<
6052  subroutine csub_delay_calc_sat(this, node, idelay, n, hcell, hcellold, &
6053  snnew, snold)
6054  ! -- dummy variables
6055  class(gwfcsubtype), intent(inout) :: this
6056  integer(I4B), intent(in) :: node !< cell node number
6057  integer(I4B), intent(in) :: idelay !< delay interbed number
6058  integer(I4B), intent(in) :: n !< delay interbed cell number
6059  real(DP), intent(in) :: hcell !< current head in delay interbed cell n
6060  real(DP), intent(in) :: hcellold !< previous head in delay interbed cell n
6061  real(DP), intent(inout) :: snnew !< current saturation in delay interbed cell n
6062  real(DP), intent(inout) :: snold !< previous saturation in delay interbed cell n
6063  ! -- local variables
6064  real(DP) :: dzhalf
6065  real(DP) :: top
6066  real(DP) :: bot
6067  !
6068  ! -- calculate delay interbed cell saturation
6069  if (this%stoiconv(node) /= 0) then
6070  dzhalf = dhalf * this%dbdzini(n, idelay)
6071  top = this%dbz(n, idelay) + dzhalf
6072  bot = this%dbz(n, idelay) - dzhalf
6073  snnew = squadraticsaturation(top, bot, hcell, this%satomega)
6074  snold = squadraticsaturation(top, bot, hcellold, this%satomega)
6075  else
6076  snnew = done
6077  snold = done
6078  end if
6079  if (this%ieslag /= 0) then
6080  snold = snnew
6081  end if
6082  end subroutine csub_delay_calc_sat
6083 
6084  !> @brief Calculate the delay interbed cell saturation derivative
6085  !!
6086  !! Function to calculate the derivative of the saturation with
6087  !! respect to the current head in delay interbed cell n.
6088  !!
6089  !! @return satderv derivative of saturation
6090  !<
6091  function csub_delay_calc_sat_derivative(this, node, idelay, n, hcell) &
6092  result(satderv)
6093  ! -- dummy variables
6094  class(gwfcsubtype), intent(inout) :: this
6095  integer(I4B), intent(in) :: node !< cell node number
6096  integer(I4B), intent(in) :: idelay !< delay interbed number
6097  integer(I4B), intent(in) :: n !< delay interbed cell number
6098  real(dp), intent(in) :: hcell !< current head in delay interbed cell n
6099  ! -- local variables
6100  real(dp) :: satderv
6101  real(dp) :: dzhalf
6102  real(dp) :: top
6103  real(dp) :: bot
6104 
6105  if (this%stoiconv(node) /= 0) then
6106  dzhalf = dhalf * this%dbdzini(n, idelay)
6107  top = this%dbz(n, idelay) + dzhalf
6108  bot = this%dbz(n, idelay) - dzhalf
6109  satderv = squadraticsaturationderivative(top, bot, hcell, this%satomega)
6110  else
6111  satderv = dzero
6112  end if
6113  end function csub_delay_calc_sat_derivative
6114 
6115  !> @brief Calculate delay interbed storage change
6116  !!
6117  !! Method to calculate the storage change in a delay interbed.
6118  !!
6119  !! @param[in,out] stoe current elastic storage change in delay interbed
6120  !! @param[in,out] stoi current inelastic storage changes in delay interbed
6121  !!
6122  !<
6123  subroutine csub_delay_calc_dstor(this, ib, hcell, stoe, stoi)
6124  ! -- dummy variables
6125  class(gwfcsubtype), intent(inout) :: this
6126  integer(I4B), intent(in) :: ib !< interbed number
6127  real(DP), intent(in) :: hcell !< current head in cell
6128  real(DP), intent(inout) :: stoe !< elastic storage change
6129  real(DP), intent(inout) :: stoi !< inelastic storage change
6130  ! -- local variables
6131  integer(I4B) :: idelay
6132  integer(I4B) :: ielastic
6133  integer(I4B) :: node
6134  integer(I4B) :: n
6135  real(DP) :: sske
6136  real(DP) :: ssk
6137  real(DP) :: fmult
6138  real(DP) :: v1
6139  real(DP) :: v2
6140  real(DP) :: ske
6141  real(DP) :: sk
6142  real(DP) :: z
6143  real(DP) :: zbot
6144  real(DP) :: h
6145  real(DP) :: h0
6146  real(DP) :: dsn
6147  real(DP) :: dsn0
6148  real(DP) :: hbar
6149  real(DP) :: dzhalf
6150  !
6151  ! -- initialize variables
6152  idelay = this%idelay(ib)
6153  ielastic = this%ielastic(ib)
6154  node = this%nodelist(ib)
6155  stoe = dzero
6156  stoi = dzero
6157  ske = dzero
6158  sk = dzero
6159  !
6160  !
6161  if (this%thickini(ib) > dzero) then
6162  fmult = this%dbdzini(1, idelay)
6163  dzhalf = dhalf * this%dbdzini(1, idelay)
6164  do n = 1, this%ndelaycells
6165  call this%csub_delay_calc_ssksske(ib, n, hcell, ssk, sske)
6166  z = this%dbz(n, idelay)
6167  zbot = z - dzhalf
6168  h = this%dbh(n, idelay)
6169  h0 = this%dbh0(n, idelay)
6170  call this%csub_delay_calc_sat(node, idelay, n, h, h0, dsn, dsn0)
6171  hbar = squadratic0sp(h, zbot, this%satomega)
6172  if (ielastic /= 0) then
6173  v1 = dsn * ssk * (this%dbgeo(n, idelay) - hbar + zbot) - &
6174  dsn0 * sske * this%dbes0(n, idelay)
6175  v2 = dzero
6176  else
6177  v1 = dsn * ssk * (this%dbgeo(n, idelay) - hbar + zbot - &
6178  this%dbpcs(n, idelay))
6179  v2 = dsn0 * sske * (this%dbpcs(n, idelay) - this%dbes0(n, idelay))
6180  end if
6181  !
6182  ! -- calculate inelastic and elastic storage components
6183  if (this%idbconvert(n, idelay) /= 0) then
6184  stoi = stoi + v1 * fmult
6185  stoe = stoe + v2 * fmult
6186  else
6187  stoe = stoe + (v1 + v2) * fmult
6188  end if
6189  !
6190  ! calculate inelastic and elastic storativity
6191  ske = ske + sske * fmult
6192  sk = sk + ssk * fmult
6193  end do
6194  end if
6195  !
6196  ! -- save ske and sk
6197  this%ske(ib) = ske
6198  this%sk(ib) = sk
6199  end subroutine csub_delay_calc_dstor
6200 
6201  !> @brief Calculate delay interbed water compressibility
6202  !!
6203  !! Method to calculate the change in water compressibility in a delay interbed.
6204  !!
6205  !! @param[in,out] dwc current water compressibility change in delay interbed
6206  !!
6207  !<
6208  subroutine csub_delay_calc_wcomp(this, ib, dwc)
6209  ! -- modules
6210  use tdismodule, only: delt
6211  ! -- dummy variables
6212  class(gwfcsubtype), intent(inout) :: this
6213  integer(I4B), intent(in) :: ib !< interbed number
6214  real(DP), intent(inout) :: dwc !< water compressibility change
6215  ! -- local variables
6216  integer(I4B) :: idelay
6217  integer(I4B) :: node
6218  integer(I4B) :: n
6219  real(DP) :: tled
6220  real(DP) :: h
6221  real(DP) :: h0
6222  real(DP) :: dz
6223  real(DP) :: dz0
6224  real(DP) :: dsn
6225  real(DP) :: dsn0
6226  real(DP) :: wc
6227  real(DP) :: wc0
6228  real(DP) :: v
6229  !
6230  ! -- initialize variables
6231  dwc = dzero
6232  !
6233  !
6234  if (this%thickini(ib) > dzero) then
6235  idelay = this%idelay(ib)
6236  node = this%nodelist(ib)
6237  tled = done / delt
6238  do n = 1, this%ndelaycells
6239  h = this%dbh(n, idelay)
6240  h0 = this%dbh0(n, idelay)
6241  dz = this%dbdz(n, idelay)
6242  dz0 = this%dbdz0(n, idelay)
6243  call this%csub_delay_calc_sat(node, idelay, n, h, h0, dsn, dsn0)
6244  wc = dz * this%brg * this%dbtheta(n, idelay)
6245  wc0 = dz0 * this%brg * this%dbtheta0(n, idelay)
6246  v = dsn0 * wc0 * h0 - dsn * wc * h
6247  dwc = dwc + v * tled
6248  end do
6249  end if
6250  end subroutine csub_delay_calc_wcomp
6251 
6252  !> @brief Calculate delay interbed compaction
6253  !!
6254  !! Method to calculate the compaction in a delay interbed.
6255  !!
6256  !! @param[in,out] comp compaction in delay interbed
6257  !! @param[in,out] compi inelastic compaction in delay interbed
6258  !! @param[in,out] compe elastic compaction in delay interbed
6259  !!
6260  !<
6261  subroutine csub_delay_calc_comp(this, ib, hcell, hcellold, comp, compi, compe)
6262  ! -- dummy variables
6263  class(gwfcsubtype), intent(inout) :: this
6264  integer(I4B), intent(in) :: ib !< interbed number
6265  real(DP), intent(in) :: hcell !< current head in cell
6266  real(DP), intent(in) :: hcellold !< previous head in cell
6267  real(DP), intent(inout) :: comp !< compaction in delay interbed
6268  real(DP), intent(inout) :: compi !< inelastic compaction in delay interbed
6269  real(DP), intent(inout) :: compe !< elastic compaction in delay interbed
6270  ! -- local variables
6271  integer(I4B) :: idelay
6272  integer(I4B) :: ielastic
6273  integer(I4B) :: node
6274  integer(I4B) :: n
6275  real(DP) :: snnew
6276  real(DP) :: snold
6277  real(DP) :: sske
6278  real(DP) :: ssk
6279  real(DP) :: fmult
6280  real(DP) :: h
6281  real(DP) :: h0
6282  real(DP) :: dsn
6283  real(DP) :: dsn0
6284  real(DP) :: v
6285  real(DP) :: v1
6286  real(DP) :: v2
6287  !
6288  ! -- initialize variables
6289  idelay = this%idelay(ib)
6290  ielastic = this%ielastic(ib)
6291  node = this%nodelist(ib)
6292  comp = dzero
6293  compi = dzero
6294  compe = dzero
6295  !
6296  ! -- calculate cell saturation
6297  call this%csub_calc_sat(node, hcell, hcellold, snnew, snold)
6298  !
6299  ! -- calculate compaction
6300  if (this%thickini(ib) > dzero) then
6301  fmult = this%dbdzini(1, idelay)
6302  do n = 1, this%ndelaycells
6303  h = this%dbh(n, idelay)
6304  h0 = this%dbh0(n, idelay)
6305  call this%csub_delay_calc_sat(node, idelay, n, h, h0, dsn, dsn0)
6306  call this%csub_delay_calc_ssksske(ib, n, hcell, ssk, sske)
6307  if (ielastic /= 0) then
6308  v1 = dsn * ssk * this%dbes(n, idelay) - sske * this%dbes0(n, idelay)
6309  v2 = dzero
6310  else
6311  v1 = dsn * ssk * (this%dbes(n, idelay) - this%dbpcs(n, idelay))
6312  v2 = dsn0 * sske * (this%dbpcs(n, idelay) - this%dbes0(n, idelay))
6313  end if
6314  v = (v1 + v2) * fmult
6315  comp = comp + v
6316  !
6317  ! -- save compaction data
6318  this%dbcomp(n, idelay) = v * snnew
6319  !
6320  ! -- calculate inelastic and elastic storage components
6321  if (this%idbconvert(n, idelay) /= 0) then
6322  compi = compi + v1 * fmult
6323  compe = compe + v2 * fmult
6324  else
6325  compe = compe + (v1 + v2) * fmult
6326  end if
6327  end do
6328  end if
6329  !
6330  ! -- fill compaction
6331  comp = comp * this%rnb(ib)
6332  compi = compi * this%rnb(ib)
6333  compe = compe * this%rnb(ib)
6334  end subroutine csub_delay_calc_comp
6335 
6336  !> @brief Update delay interbed material properties
6337  !!
6338  !! Method to update the thickness and porosity of each delay interbed cell.
6339  !!
6340  !<
6341  subroutine csub_delay_update(this, ib)
6342  ! -- dummy variables
6343  class(gwfcsubtype), intent(inout) :: this
6344  integer(I4B), intent(in) :: ib !< interbed number
6345  ! -- local variables
6346  integer(I4B) :: idelay
6347  integer(I4B) :: n
6348  real(DP) :: comp
6349  real(DP) :: thick
6350  real(DP) :: theta
6351  real(DP) :: tthick
6352  real(DP) :: wtheta
6353  !
6354  ! -- initialize variables
6355  idelay = this%idelay(ib)
6356  comp = dzero
6357  tthick = dzero
6358  wtheta = dzero
6359  !
6360  !
6361  do n = 1, this%ndelaycells
6362  !
6363  ! -- initialize compaction for delay cell
6364  comp = this%dbtcomp(n, idelay) + this%dbcomp(n, idelay)
6365  !
6366  ! -- scale compaction by rnb to get the compaction for
6367  ! the interbed system (as opposed to the full system)
6368  comp = comp / this%rnb(ib)
6369  !
6370  ! -- update thickness and theta
6371  if (abs(comp) > dzero) then
6372  thick = this%dbdzini(n, idelay)
6373  theta = this%dbthetaini(n, idelay)
6374  call this%csub_adj_matprop(comp, thick, theta)
6375  if (thick <= dzero) then
6376  write (errmsg, '(2(a,i0),a,g0,a)') &
6377  'Adjusted thickness for delay interbed (', ib, &
6378  ') cell (', n, ') is less than or equal to 0 (', thick, ').'
6379  call store_error(errmsg)
6380  end if
6381  if (theta <= dzero) then
6382  write (errmsg, '(2(a,i0),a,g0,a)') &
6383  'Adjusted theta for delay interbed (', ib, &
6384  ') cell (', n, 'is less than or equal to 0 (', theta, ').'
6385  call store_error(errmsg)
6386  end if
6387  this%dbdz(n, idelay) = thick
6388  this%dbtheta(n, idelay) = theta
6389  tthick = tthick + thick
6390  wtheta = wtheta + thick * theta
6391  else
6392  thick = this%dbdz(n, idelay)
6393  theta = this%dbtheta(n, idelay)
6394  tthick = tthick + thick
6395  wtheta = wtheta + thick * theta
6396  end if
6397  end do
6398  !
6399  ! -- calculate thickness weighted theta and save thickness and weighted
6400  ! theta values for delay interbed
6401  if (tthick > dzero) then
6402  wtheta = wtheta / tthick
6403  else
6404  tthick = dzero
6405  wtheta = dzero
6406  end if
6407  this%thick(ib) = tthick
6408  this%theta(ib) = wtheta
6409  end subroutine csub_delay_update
6410 
6411  !> @brief Calculate delay interbed contribution to the cell
6412  !!
6413  !! Method to calculate the coefficients to calculate the delay interbed
6414  !! contribution to a cell. The product of hcof* h - rhs equals the
6415  !! delay contribution to the cell
6416  !!
6417  !! @param[in,out] hcof coefficient dependent on current head
6418  !! @param[in,out] rhs right-hand side contributions
6419  !!
6420  !<
6421  subroutine csub_delay_fc(this, ib, hcof, rhs)
6422  ! -- dummy variables
6423  class(gwfcsubtype), intent(inout) :: this
6424  integer(I4B), intent(in) :: ib !< interbed number
6425  real(DP), intent(inout) :: hcof !< head dependent coefficient
6426  real(DP), intent(inout) :: rhs !< right-hand side
6427  ! -- local variables
6428  integer(I4B) :: idelay
6429  real(DP) :: c1
6430  real(DP) :: c2
6431  !
6432  ! -- initialize variables
6433  idelay = this%idelay(ib)
6434  hcof = dzero
6435  rhs = dzero
6436  if (this%thickini(ib) > dzero) then
6437  ! -- calculate terms for gwf matrix
6438  c1 = dtwo * this%kv(ib) / this%dbdzini(1, idelay)
6439  rhs = -c1 * this%dbh(1, idelay)
6440  c2 = dtwo * &
6441  this%kv(ib) / this%dbdzini(this%ndelaycells, idelay)
6442  rhs = rhs - c2 * this%dbh(this%ndelaycells, idelay)
6443  hcof = c1 + c2
6444  end if
6445  end subroutine csub_delay_fc
6446 
6447  !> @brief Calculate the flow from delay interbed top or bottom
6448  !!
6449  !! Function to calculate the flow from across the top or bottom of
6450  !! a delay interbed.
6451  !!
6452  !! @return q flow across the top or bottom of a delay interbed
6453  !<
6454  function csub_calc_delay_flow(this, ib, n, hcell) result(q)
6455  ! -- dummy variables
6456  class(gwfcsubtype), intent(inout) :: this
6457  integer(I4B), intent(in) :: ib !< interbed number
6458  integer(I4B), intent(in) :: n !< delay interbed cell
6459  real(dp), intent(in) :: hcell !< current head in cell
6460  ! -- local variables
6461  integer(I4B) :: idelay
6462  real(dp) :: q
6463  real(dp) :: c
6464  !
6465  ! -- calculate flow between delay interbed and GWF
6466  idelay = this%idelay(ib)
6467  c = dtwo * this%kv(ib) / this%dbdzini(n, idelay)
6468  q = c * (hcell - this%dbh(n, idelay))
6469  end function csub_calc_delay_flow
6470 
6471  !
6472  ! -- Procedures related to observations (type-bound)
6473 
6474  !> @brief Determine if observations are supported.
6475  !!
6476  !! Function to determine if observations are supported by the CSUB package.
6477  !! Observations are supported by the CSUB package.
6478  !!
6479  !<
6480  logical function csub_obs_supported(this)
6481  ! -- dummy variables
6482  class(gwfcsubtype) :: this
6483  !
6484  ! -- initialize variables
6485  csub_obs_supported = .true.
6486  end function csub_obs_supported
6487 
6488  !> @brief Define the observation types available in the package
6489  !!
6490  !! Method to define the observation types available in the CSUB package.
6491  !!
6492  !<
6493  subroutine csub_df_obs(this)
6494  ! -- dummy variables
6495  class(gwfcsubtype) :: this
6496  ! -- local variables
6497  integer(I4B) :: indx
6498  !
6499  ! -- Store obs type and assign procedure pointer
6500  ! for csub observation type.
6501  call this%obs%StoreObsType('csub', .true., indx)
6502  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6503  !
6504  ! -- Store obs type and assign procedure pointer
6505  ! for inelastic-csub observation type.
6506  call this%obs%StoreObsType('inelastic-csub', .true., indx)
6507  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6508  !
6509  ! -- Store obs type and assign procedure pointer
6510  ! for elastic-csub observation type.
6511  call this%obs%StoreObsType('elastic-csub', .true., indx)
6512  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6513  !
6514  ! -- Store obs type and assign procedure pointer
6515  ! for coarse-csub observation type.
6516  call this%obs%StoreObsType('coarse-csub', .false., indx)
6517  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6518  !
6519  ! -- Store obs type and assign procedure pointer
6520  ! for csub-cell observation type.
6521  call this%obs%StoreObsType('csub-cell', .true., indx)
6522  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6523  !
6524  ! -- Store obs type and assign procedure pointer
6525  ! for watercomp-csub observation type.
6526  call this%obs%StoreObsType('wcomp-csub-cell', .false., indx)
6527  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6528  !
6529  ! -- Store obs type and assign procedure pointer
6530  ! for interbed ske observation type.
6531  call this%obs%StoreObsType('ske', .true., indx)
6532  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6533  !
6534  ! -- Store obs type and assign procedure pointer
6535  ! for interbed sk observation type.
6536  call this%obs%StoreObsType('sk', .true., indx)
6537  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6538  !
6539  ! -- Store obs type and assign procedure pointer
6540  ! for ske-cell observation type.
6541  call this%obs%StoreObsType('ske-cell', .true., indx)
6542  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6543  !
6544  ! -- Store obs type and assign procedure pointer
6545  ! for sk-cell observation type.
6546  call this%obs%StoreObsType('sk-cell', .true., indx)
6547  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6548  !
6549  ! -- Store obs type and assign procedure pointer
6550  ! for geostatic-stress-cell observation type.
6551  call this%obs%StoreObsType('gstress-cell', .false., indx)
6552  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6553  !
6554  ! -- Store obs type and assign procedure pointer
6555  ! for effective-stress-cell observation type.
6556  call this%obs%StoreObsType('estress-cell', .false., indx)
6557  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6558  !
6559  ! -- Store obs type and assign procedure pointer
6560  ! for total-compaction observation type.
6561  call this%obs%StoreObsType('interbed-compaction', .true., indx)
6562  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6563  !
6564  ! -- Store obs type and assign procedure pointer
6565  ! for inelastic-compaction observation type.
6566  call this%obs%StoreObsType('inelastic-compaction', .true., indx)
6567  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6568  !
6569  ! -- Store obs type and assign procedure pointer
6570  ! for inelastic-compaction observation type.
6571  call this%obs%StoreObsType('elastic-compaction', .true., indx)
6572  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6573  !
6574  ! -- Store obs type and assign procedure pointer
6575  ! for coarse-compaction observation type.
6576  call this%obs%StoreObsType('coarse-compaction', .false., indx)
6577  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6578  !
6579  ! -- Store obs type and assign procedure pointer
6580  ! for inelastic-compaction-cell observation type.
6581  call this%obs%StoreObsType('inelastic-compaction-cell', .true., indx)
6582  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6583  !
6584  ! -- Store obs type and assign procedure pointer
6585  ! for elastic-compaction-cell observation type.
6586  call this%obs%StoreObsType('elastic-compaction-cell', .true., indx)
6587  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6588  !
6589  ! -- Store obs type and assign procedure pointer
6590  ! for compaction-cell observation type.
6591  call this%obs%StoreObsType('compaction-cell', .true., indx)
6592  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6593  !
6594  ! -- Store obs type and assign procedure pointer
6595  ! for interbed thickness observation type.
6596  call this%obs%StoreObsType('thickness', .true., indx)
6597  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6598  !
6599  ! -- Store obs type and assign procedure pointer
6600  ! for coarse-thickness observation type.
6601  call this%obs%StoreObsType('coarse-thickness', .false., indx)
6602  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6603  !
6604  ! -- Store obs type and assign procedure pointer
6605  ! for thickness-cell observation type.
6606  call this%obs%StoreObsType('thickness-cell', .false., indx)
6607  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6608  !
6609  ! -- Store obs type and assign procedure pointer
6610  ! for interbed theta observation type.
6611  call this%obs%StoreObsType('theta', .true., indx)
6612  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6613  !
6614  ! -- Store obs type and assign procedure pointer
6615  ! for coarse-theta observation type.
6616  call this%obs%StoreObsType('coarse-theta', .false., indx)
6617  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6618  !
6619  ! -- Store obs type and assign procedure pointer
6620  ! for theta-cell observation type.
6621  call this%obs%StoreObsType('theta-cell', .true., indx)
6622  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6623  !
6624  ! -- Store obs type and assign procedure pointer
6625  ! for preconstress-cell observation type.
6626  call this%obs%StoreObsType('preconstress-cell', .false., indx)
6627  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6628  !
6629  ! -- Store obs type and assign procedure pointer
6630  ! for interbed-compaction-pct observation type.
6631  call this%obs%StoreObsType('interbed-compaction-pct', .false., indx)
6632  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6633  !
6634  ! -- Store obs type and assign procedure pointer
6635  ! for delay-preconstress observation type.
6636  call this%obs%StoreObsType('delay-preconstress', .false., indx)
6637  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6638  !
6639  ! -- Store obs type and assign procedure pointer
6640  ! for delay-head observation type.
6641  call this%obs%StoreObsType('delay-head', .false., indx)
6642  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6643  !
6644  ! -- Store obs type and assign procedure pointer
6645  ! for delay-gstress observation type.
6646  call this%obs%StoreObsType('delay-gstress', .false., indx)
6647  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6648  !
6649  ! -- Store obs type and assign procedure pointer
6650  ! for delay-estress observation type.
6651  call this%obs%StoreObsType('delay-estress', .false., indx)
6652  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6653  !
6654  ! -- Store obs type and assign procedure pointer
6655  ! for delay-compaction observation type.
6656  call this%obs%StoreObsType('delay-compaction', .false., indx)
6657  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6658  !
6659  ! -- Store obs type and assign procedure pointer
6660  ! for delay-thickness observation type.
6661  call this%obs%StoreObsType('delay-thickness', .false., indx)
6662  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6663  !
6664  ! -- Store obs type and assign procedure pointer
6665  ! for delay-theta observation type.
6666  call this%obs%StoreObsType('delay-theta', .false., indx)
6667  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6668  !
6669  ! -- Store obs type and assign procedure pointer
6670  ! for delay-flowtop observation type.
6671  call this%obs%StoreObsType('delay-flowtop', .true., indx)
6672  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6673  !
6674  ! -- Store obs type and assign procedure pointer
6675  ! for delay-flowbot observation type.
6676  call this%obs%StoreObsType('delay-flowbot', .true., indx)
6677  this%obs%obsData(indx)%ProcessIdPtr => csub_process_obsid
6678  end subroutine csub_df_obs
6679 
6680  !> @brief Set the observations for this time step
6681  !!
6682  !! Method to set the CSUB package observations for this time step.
6683  !!
6684  !<
6685  subroutine csub_bd_obs(this)
6686  ! -- dummy variables
6687  class(gwfcsubtype), intent(inout) :: this
6688  ! -- local variables
6689  type(observetype), pointer :: obsrv => null()
6690  integer(I4B) :: i
6691  integer(I4B) :: j
6692  integer(I4B) :: n
6693  integer(I4B) :: idelay
6694  integer(I4B) :: ncol
6695  integer(I4B) :: node
6696  real(DP) :: v
6697  real(DP) :: r
6698  real(DP) :: f
6699  real(DP) :: b0
6700  !
6701  ! -- Fill simulated values for all csub observations
6702  if (this%obs%npakobs > 0) then
6703  call this%obs%obs_bd_clear()
6704  do i = 1, this%obs%npakobs
6705  obsrv => this%obs%pakobs(i)%obsrv
6706  if (obsrv%BndFound) then
6707  if (obsrv%ObsTypeId == 'SKE' .or. &
6708  obsrv%ObsTypeId == 'SK' .or. &
6709  obsrv%ObsTypeId == 'SKE-CELL' .or. &
6710  obsrv%ObsTypeId == 'SK-CELL' .or. &
6711  obsrv%ObsTypeId == 'DELAY-HEAD' .or. &
6712  obsrv%ObsTypeId == 'DELAY-PRECONSTRESS' .or. &
6713  obsrv%ObsTypeId == 'DELAY-GSTRESS' .or. &
6714  obsrv%ObsTypeId == 'DELAY-ESTRESS' .or. &
6715  obsrv%ObsTypeId == 'PRECONSTRESS-CELL') then
6716  if (this%gwfiss /= 0) then
6717  call this%obs%SaveOneSimval(obsrv, dnodata)
6718  else
6719  v = dzero
6720  do j = 1, obsrv%indxbnds_count
6721  n = obsrv%indxbnds(j)
6722  select case (obsrv%ObsTypeId)
6723  case ('SKE')
6724  v = this%ske(n)
6725  case ('SK')
6726  v = this%sk(n)
6727  case ('SKE-CELL')
6728  !
6729  ! -- add the coarse component
6730  if (j == 1) then
6731  v = this%cg_ske(n)
6732  else
6733  v = this%ske(n)
6734  end if
6735  case ('SK-CELL')
6736  !
6737  ! -- add the coarse component
6738  if (j == 1) then
6739  v = this%cg_sk(n)
6740  else
6741  v = this%sk(n)
6742  end if
6743  case ('DELAY-HEAD', 'DELAY-PRECONSTRESS', &
6744  'DELAY-GSTRESS', 'DELAY-ESTRESS')
6745  if (n > this%ndelaycells) then
6746  r = real(n - 1, dp) / real(this%ndelaycells, dp)
6747  idelay = int(floor(r)) + 1
6748  ncol = n - int(floor(r)) * this%ndelaycells
6749  else
6750  idelay = 1
6751  ncol = n
6752  end if
6753  select case (obsrv%ObsTypeId)
6754  case ('DELAY-HEAD')
6755  v = this%dbh(ncol, idelay)
6756  case ('DELAY-PRECONSTRESS')
6757  v = this%dbpcs(ncol, idelay)
6758  case ('DELAY-GSTRESS')
6759  v = this%dbgeo(ncol, idelay)
6760  case ('DELAY-ESTRESS')
6761  v = this%dbes(ncol, idelay)
6762  end select
6763  case ('PRECONSTRESS-CELL')
6764  v = this%pcs(n)
6765  case default
6766  errmsg = "Unrecognized observation type '"// &
6767  trim(obsrv%ObsTypeId)//"'."
6768  call store_error(errmsg)
6769  end select
6770  call this%obs%SaveOneSimval(obsrv, v)
6771  end do
6772  end if
6773  else
6774  v = dzero
6775  do j = 1, obsrv%indxbnds_count
6776  n = obsrv%indxbnds(j)
6777  select case (obsrv%ObsTypeId)
6778  case ('CSUB')
6779  v = this%storagee(n) + this%storagei(n)
6780  case ('INELASTIC-CSUB')
6781  v = this%storagei(n)
6782  case ('ELASTIC-CSUB')
6783  v = this%storagee(n)
6784  case ('COARSE-CSUB')
6785  v = this%cg_stor(n)
6786  case ('WCOMP-CSUB-CELL')
6787  v = this%cell_wcstor(n)
6788  case ('CSUB-CELL')
6789  !
6790  ! -- add the coarse component
6791  if (j == 1) then
6792  v = this%cg_stor(n)
6793  else
6794  v = this%storagee(n) + this%storagei(n)
6795  end if
6796  case ('THETA')
6797  v = this%theta(n)
6798  case ('COARSE-THETA')
6799  v = this%cg_theta(n)
6800  case ('THETA-CELL')
6801  !
6802  ! -- add the coarse component
6803  if (j == 1) then
6804  f = this%cg_thick(n) / this%cell_thick(n)
6805  v = f * this%cg_theta(n)
6806  else
6807  node = this%nodelist(n)
6808  f = this%csub_calc_interbed_thickness(n) / this%cell_thick(node)
6809  v = f * this%theta(n)
6810  end if
6811  case ('GSTRESS-CELL')
6812  v = this%cg_gs(n)
6813  case ('ESTRESS-CELL')
6814  v = this%cg_es(n)
6815  case ('INTERBED-COMPACTION')
6816  v = this%tcomp(n)
6817  case ('INTERBED-COMPACTION-PCT')
6818  b0 = this%thickini(n)
6819  if (this%idelay(n) /= 0) then
6820  b0 = b0 * this%rnb(n)
6821  end if
6822  v = dhundred * this%tcomp(n) / b0
6823  case ('INELASTIC-COMPACTION')
6824  v = this%tcompi(n)
6825  case ('ELASTIC-COMPACTION')
6826  v = this%tcompe(n)
6827  case ('COARSE-COMPACTION')
6828  v = this%cg_tcomp(n)
6829  case ('INELASTIC-COMPACTION-CELL')
6830  !
6831  ! -- no coarse inelastic component
6832  if (j > 1) then
6833  v = this%tcompi(n)
6834  end if
6835  case ('ELASTIC-COMPACTION-CELL')
6836  !
6837  ! -- add the coarse component
6838  if (j == 1) then
6839  v = this%cg_tcomp(n)
6840  else
6841  v = this%tcompe(n)
6842  end if
6843  case ('COMPACTION-CELL')
6844  !
6845  ! -- add the coarse component
6846  if (j == 1) then
6847  v = this%cg_tcomp(n)
6848  else
6849  v = this%tcomp(n)
6850  end if
6851  case ('THICKNESS')
6852  idelay = this%idelay(n)
6853  v = this%thick(n)
6854  if (idelay /= 0) then
6855  v = v * this%rnb(n)
6856  end if
6857  case ('COARSE-THICKNESS')
6858  v = this%cg_thick(n)
6859  case ('THICKNESS-CELL')
6860  v = this%cell_thick(n)
6861  case ('DELAY-COMPACTION', 'DELAY-THICKNESS', &
6862  'DELAY-THETA')
6863  if (n > this%ndelaycells) then
6864  r = real(n, dp) / real(this%ndelaycells, dp)
6865  idelay = int(floor(r)) + 1
6866  ncol = mod(n, this%ndelaycells)
6867  else
6868  idelay = 1
6869  ncol = n
6870  end if
6871  select case (obsrv%ObsTypeId)
6872  case ('DELAY-COMPACTION')
6873  v = this%dbtcomp(ncol, idelay)
6874  case ('DELAY-THICKNESS')
6875  v = this%dbdz(ncol, idelay)
6876  case ('DELAY-THETA')
6877  v = this%dbtheta(ncol, idelay)
6878  end select
6879  case ('DELAY-FLOWTOP')
6880  idelay = this%idelay(n)
6881  v = this%dbflowtop(idelay)
6882  case ('DELAY-FLOWBOT')
6883  idelay = this%idelay(n)
6884  v = this%dbflowbot(idelay)
6885  case default
6886  errmsg = "Unrecognized observation type: '"// &
6887  trim(obsrv%ObsTypeId)//"'."
6888  call store_error(errmsg)
6889  end select
6890  call this%obs%SaveOneSimval(obsrv, v)
6891  end do
6892  end if
6893  else
6894  call this%obs%SaveOneSimval(obsrv, dnodata)
6895  end if
6896  end do
6897  !
6898  ! -- write summary of package error messages
6899  if (count_errors() > 0) then
6900  call store_error_filename(this%input_fname)
6901  end if
6902  end if
6903  end subroutine csub_bd_obs
6904 
6905  !> @brief Read and prepare the observations
6906  !!
6907  !! Method to read and prepare the observations for the CSUB package.
6908  !!
6909  !<
6910  subroutine csub_rp_obs(this)
6911  ! -- modules
6912  use tdismodule, only: kper
6913  ! -- dummy variables
6914  class(gwfcsubtype), intent(inout) :: this
6915  ! -- local variables
6916  class(observetype), pointer :: obsrv => null()
6917  character(len=LENBOUNDNAME) :: bname
6918  integer(I4B) :: i
6919  integer(I4B) :: j
6920  integer(I4B) :: n
6921  integer(I4B) :: n2
6922  integer(I4B) :: idelay
6923  !
6924  ! -- return if observations are not supported
6925  if (.not. this%csub_obs_supported()) then
6926  return
6927  end if
6928  !
6929  ! -- process each package observation
6930  ! only done the first stress period since boundaries are fixed
6931  ! for the simulation
6932  if (kper == 1) then
6933  do i = 1, this%obs%npakobs
6934  obsrv => this%obs%pakobs(i)%obsrv
6935  !
6936  ! -- initialize BndFound to .false.
6937  obsrv%BndFound = .false.
6938  !
6939  bname = obsrv%FeatureName
6940  if (bname /= '') then
6941  !
6942  ! -- Observation location(s) is(are) based on a boundary name.
6943  ! Iterate through all boundaries to identify and store
6944  ! corresponding index(indices) in bound array.
6945  do j = 1, this%ninterbeds
6946  if (this%boundname(j) == bname) then
6947  obsrv%BndFound = .true.
6948  obsrv%CurrentTimeStepEndValue = dzero
6949  call obsrv%AddObsIndex(j)
6950  end if
6951  end do
6952  !
6953  ! -- one value per cell
6954  else if (obsrv%ObsTypeId == 'GSTRESS-CELL' .or. &
6955  obsrv%ObsTypeId == 'ESTRESS-CELL' .or. &
6956  obsrv%ObsTypeId == 'THICKNESS-CELL' .or. &
6957  obsrv%ObsTypeId == 'COARSE-CSUB' .or. &
6958  obsrv%ObsTypeId == 'WCOMP-CSUB-CELL' .or. &
6959  obsrv%ObsTypeId == 'COARSE-COMPACTION' .or. &
6960  obsrv%ObsTypeId == 'COARSE-THETA' .or. &
6961  obsrv%ObsTypeId == 'COARSE-THICKNESS') then
6962  obsrv%BndFound = .true.
6963  obsrv%CurrentTimeStepEndValue = dzero
6964  call obsrv%AddObsIndex(obsrv%NodeNumber)
6965  else if (obsrv%ObsTypeId == 'DELAY-PRECONSTRESS' .or. &
6966  obsrv%ObsTypeId == 'DELAY-HEAD' .or. &
6967  obsrv%ObsTypeId == 'DELAY-GSTRESS' .or. &
6968  obsrv%ObsTypeId == 'DELAY-ESTRESS' .or. &
6969  obsrv%ObsTypeId == 'DELAY-COMPACTION' .or. &
6970  obsrv%ObsTypeId == 'DELAY-THICKNESS' .or. &
6971  obsrv%ObsTypeId == 'DELAY-THETA') then
6972  if (this%ninterbeds > 0) then
6973  n = obsrv%NodeNumber
6974  idelay = this%idelay(n)
6975  if (idelay /= 0) then
6976  j = (idelay - 1) * this%ndelaycells + 1
6977  n2 = obsrv%NodeNumber2
6978  if (n2 < 1 .or. n2 > this%ndelaycells) then
6979  write (errmsg, '(a,2(1x,a),1x,i0,1x,a,i0,a)') &
6980  trim(adjustl(obsrv%ObsTypeId)), 'interbed cell must be ', &
6981  'greater than 0 and less than or equal to', this%ndelaycells, &
6982  '(specified value is ', n2, ').'
6983  call store_error(errmsg)
6984  else
6985  j = (idelay - 1) * this%ndelaycells + n2
6986  end if
6987  obsrv%BndFound = .true.
6988  call obsrv%AddObsIndex(j)
6989  end if
6990  end if
6991  !
6992  ! -- interbed value
6993  else if (obsrv%ObsTypeId == 'CSUB' .or. &
6994  obsrv%ObsTypeId == 'INELASTIC-CSUB' .or. &
6995  obsrv%ObsTypeId == 'ELASTIC-CSUB' .or. &
6996  obsrv%ObsTypeId == 'SK' .or. &
6997  obsrv%ObsTypeId == 'SKE' .or. &
6998  obsrv%ObsTypeId == 'THICKNESS' .or. &
6999  obsrv%ObsTypeId == 'THETA' .or. &
7000  obsrv%ObsTypeId == 'INTERBED-COMPACTION' .or. &
7001  obsrv%ObsTypeId == 'INELASTIC-COMPACTION' .or. &
7002  obsrv%ObsTypeId == 'ELASTIC-COMPACTION' .or. &
7003  obsrv%ObsTypeId == 'INTERBED-COMPACTION-PCT') then
7004  if (this%ninterbeds > 0) then
7005  j = obsrv%NodeNumber
7006  if (j < 1 .or. j > this%ninterbeds) then
7007  write (errmsg, '(a,2(1x,a),1x,i0,1x,a,i0,a)') &
7008  trim(adjustl(obsrv%ObsTypeId)), 'interbed cell must be greater', &
7009  'than 0 and less than or equal to', this%ninterbeds, &
7010  '(specified value is ', j, ').'
7011  call store_error(errmsg)
7012  else
7013  obsrv%BndFound = .true.
7014  obsrv%CurrentTimeStepEndValue = dzero
7015  call obsrv%AddObsIndex(j)
7016  end if
7017  end if
7018  else if (obsrv%ObsTypeId == 'DELAY-FLOWTOP' .or. &
7019  obsrv%ObsTypeId == 'DELAY-FLOWBOT') then
7020  if (this%ninterbeds > 0) then
7021  j = obsrv%NodeNumber
7022  if (j < 1 .or. j > this%ninterbeds) then
7023  write (errmsg, '(a,2(1x,a),1x,i0,1x,a,i0,a)') &
7024  trim(adjustl(obsrv%ObsTypeId)), &
7025  'interbed cell must be greater ', &
7026  'than 0 and less than or equal to', this%ninterbeds, &
7027  '(specified value is ', j, ').'
7028  call store_error(errmsg)
7029  end if
7030  idelay = this%idelay(j)
7031  if (idelay /= 0) then
7032  obsrv%BndFound = .true.
7033  obsrv%CurrentTimeStepEndValue = dzero
7034  call obsrv%AddObsIndex(j)
7035  end if
7036  end if
7037  else
7038  !
7039  ! -- Accumulate values in a single cell
7040  ! -- Observation location is a single node number
7041  ! -- save node number in first position
7042  if (obsrv%ObsTypeId == 'CSUB-CELL' .or. &
7043  obsrv%ObsTypeId == 'SKE-CELL' .or. &
7044  obsrv%ObsTypeId == 'SK-CELL' .or. &
7045  obsrv%ObsTypeId == 'THETA-CELL' .or. &
7046  obsrv%ObsTypeId == 'INELASTIC-COMPACTION-CELL' .or. &
7047  obsrv%ObsTypeId == 'ELASTIC-COMPACTION-CELL' .or. &
7048  obsrv%ObsTypeId == 'COMPACTION-CELL') then
7049  if (.NOT. obsrv%BndFound) then
7050  obsrv%BndFound = .true.
7051  obsrv%CurrentTimeStepEndValue = dzero
7052  call obsrv%AddObsIndex(obsrv%NodeNumber)
7053  end if
7054  end if
7055  jloop: do j = 1, this%ninterbeds
7056  if (this%nodelist(j) == obsrv%NodeNumber) then
7057  obsrv%BndFound = .true.
7058  obsrv%CurrentTimeStepEndValue = dzero
7059  call obsrv%AddObsIndex(j)
7060  end if
7061  end do jloop
7062  end if
7063  end do
7064  !
7065  ! -- evaluate if there are any observation errors
7066  if (count_errors() > 0) then
7067  call store_error_filename(this%input_fname)
7068  end if
7069  end if
7070  end subroutine csub_rp_obs
7071 
7072  !
7073  ! -- Procedures related to observations (NOT type-bound)
7074 
7075  !> @brief Process the observation IDs for the package
7076  !!
7077  !! Method to process the observation IDs for the CSUB package. This
7078  !! procedure is pointed to by ObsDataType%ProcesssIdPtr. It processes the
7079  !! ID string of an observation definition for csub-package observations.
7080  !!
7081  !<
7082  subroutine csub_process_obsid(obsrv, dis, inunitobs, iout)
7083  ! -- dummy variables
7084  type(observetype), intent(inout) :: obsrv !< observation type
7085  class(disbasetype), intent(in) :: dis !< pointer to the model discretization
7086  integer(I4B), intent(in) :: inunitobs !< unit number of the observation file
7087  integer(I4B), intent(in) :: iout !< unit number to the model listing file
7088  ! -- local variables
7089  integer(I4B) :: nn1
7090  integer(I4B) :: nn2
7091  integer(I4B) :: icol, istart, istop
7092  character(len=LINELENGTH) :: string
7093  character(len=LENBOUNDNAME) :: bndname
7094  logical(LGP) :: flag_string
7095  logical(LGP) :: flag_idcellno
7096  logical(LGP) :: flag_error
7097  !
7098  ! -- initialize variables
7099  string = obsrv%IDstring
7100  flag_string = .true.
7101  flag_idcellno = .false.
7102  flag_error = .false.
7103  if (obsrv%ObsTypeId(1:5) == "DELAY" .AND. &
7104  obsrv%ObsTypeId(1:10) /= "DELAY-FLOW") then
7105  flag_idcellno = .true.
7106  end if
7107  !
7108  ! -- Extract reach number from string and store it.
7109  ! If 1st item is not an integer(I4B), it should be a
7110  ! boundary name--deal with it.
7111  icol = 1
7112  !
7113  ! -- get icsubno number or boundary name
7114  if (obsrv%ObsTypeId == 'CSUB' .or. &
7115  obsrv%ObsTypeId == 'INELASTIC-CSUB' .or. &
7116  obsrv%ObsTypeId == 'ELASTIC-CSUB' .or. &
7117  obsrv%ObsTypeId == 'SK' .or. &
7118  obsrv%ObsTypeId == 'SKE' .or. &
7119  obsrv%ObsTypeId == 'THETA' .or. &
7120  obsrv%ObsTypeId == 'THICKNESS' .or. &
7121  obsrv%ObsTypeId == 'INTERBED-COMPACTION' .or. &
7122  obsrv%ObsTypeId == 'INTERBED-COMPACTION-PCT' .or. &
7123  obsrv%ObsTypeId == 'INELASTIC-COMPACTION' .or. &
7124  obsrv%ObsTypeId == 'ELASTIC-COMPACTION' .or. &
7125  obsrv%ObsTypeId == 'DELAY-HEAD' .or. &
7126  obsrv%ObsTypeId == 'DELAY-GSTRESS' .or. &
7127  obsrv%ObsTypeId == 'DELAY-ESTRESS' .or. &
7128  obsrv%ObsTypeId == 'DELAY-PRECONSTRESS' .or. &
7129  obsrv%ObsTypeId == 'DELAY-COMPACTION' .or. &
7130  obsrv%ObsTypeId == 'DELAY-THICKNESS' .or. &
7131  obsrv%ObsTypeId == 'DELAY-THETA' .or. &
7132  obsrv%ObsTypeId == 'DELAY-FLOWTOP' .or. &
7133  obsrv%ObsTypeId == 'DELAY-FLOWBOT') then
7134  call extract_idnum_or_bndname(string, icol, istart, istop, nn1, bndname)
7135  ! read cellid
7136  else
7137  nn1 = dis%noder_from_string(icol, istart, istop, inunitobs, &
7138  iout, string, flag_string)
7139  end if
7140  ! boundnames are not allowed for these observation types
7141  if (obsrv%ObsTypeId == 'SK' .or. &
7142  obsrv%ObsTypeId == 'SKE' .or. &
7143  obsrv%ObsTypeId == 'THETA' .or. &
7144  obsrv%ObsTypeId == 'THICKNESS' .or. &
7145  obsrv%ObsTypeId == 'INTERBED-COMPACTION' .or. &
7146  obsrv%ObsTypeId == 'INELASTIC-COMPACTION' .or. &
7147  obsrv%ObsTypeId == 'ELASTIC-COMPACTION' .or. &
7148  obsrv%ObsTypeId == 'DELAY-HEAD' .or. &
7149  obsrv%ObsTypeId == 'DELAY-GSTRESS' .or. &
7150  obsrv%ObsTypeId == 'DELAY-ESTRESS' .or. &
7151  obsrv%ObsTypeId == 'DELAY-PRECONSTRESS' .or. &
7152  obsrv%ObsTypeId == 'DELAY-COMPACTION' .or. &
7153  obsrv%ObsTypeId == 'DELAY-THICKNESS' .or. &
7154  obsrv%ObsTypeId == 'DELAY-THETA') then
7155  if (nn1 == namedboundflag) then
7156  write (errmsg, '(5a)') &
7157  "BOUNDNAME ('", trim(adjustl(bndname)), &
7158  "') not allowed for CSUB observation type '", &
7159  trim(adjustl(obsrv%ObsTypeId)), "'."
7160  call store_error(errmsg)
7161  flag_error = .true.
7162  end if
7163  ! boundnames are allowed for these observation types
7164  else if (obsrv%ObsTypeId == 'CSUB' .or. &
7165  obsrv%ObsTypeId == 'INELASTIC-CSUB' .or. &
7166  obsrv%ObsTypeId == 'ELASTIC-CSUB' .or. &
7167  ! obsrv%ObsTypeId == 'INTERBED-COMPACTION' .or. &
7168  ! obsrv%ObsTypeId == 'INELASTIC-COMPACTION' .or. &
7169  ! obsrv%ObsTypeId == 'ELASTIC-COMPACTION' .or. &
7170  obsrv%ObsTypeId == 'DELAY-FLOWTOP' .or. &
7171  obsrv%ObsTypeId == 'DELAY-FLOWBOT') then
7172  if (nn1 == namedboundflag) then
7173  obsrv%FeatureName = bndname
7174  end if
7175  end if
7176  ! read idcellno for delay observations
7177  if (flag_idcellno .EQV. .true. .AND. flag_error .EQV. .false.) then
7178  if (nn1 /= namedboundflag) then
7179  call extract_idnum_or_bndname(string, icol, istart, istop, nn2, bndname)
7180  if (nn2 == namedboundflag) then
7181  write (errmsg, '(5a)') &
7182  "BOUNDNAME ('", trim(adjustl(bndname)), &
7183  "') not allowed for CSUB observation type '", &
7184  trim(adjustl(obsrv%ObsTypeId)), "' idcellno."
7185  call store_error(errmsg)
7186  else
7187  obsrv%NodeNumber2 = nn2
7188  end if
7189  end if
7190  end if
7191  !
7192  ! -- store reach number (NodeNumber)
7193  obsrv%NodeNumber = nn1
7194  end subroutine csub_process_obsid
7195 
7196  !> @ brief Define the list label for the package
7197  !!
7198  !! Method defined the list label for the CSUB package. The list label is
7199  !! the heading that is written to iout when PRINT_INPUT option is used.
7200  !!
7201  !<
7202  subroutine define_listlabel(this)
7203  ! -- dummy variables
7204  class(gwfcsubtype), intent(inout) :: this
7205  !
7206  ! -- create the header list label
7207  this%listlabel = trim(this%filtyp)//' NO.'
7208  if (this%dis%ndim == 3) then
7209  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
7210  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
7211  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
7212  elseif (this%dis%ndim == 2) then
7213  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
7214  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
7215  else
7216  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
7217  end if
7218  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'SIG0'
7219  if (this%inamedbound == 1) then
7220  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
7221  end if
7222  end subroutine define_listlabel
7223 
7224 end module gwfcsubmodule
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
Definition: Budget.f90:632
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
@ tabcenter
centered table column
Definition: Constants.f90:172
@ tabright
right justified table column
Definition: Constants.f90:173
@ tableft
left justified table column
Definition: Constants.f90:171
@ mnormal
normal output mode
Definition: Constants.f90:206
real(dp), parameter dem20
real constant 1e-20
Definition: Constants.f90:117
@ tabucstring
upper case string table data
Definition: Constants.f90:180
@ tabstring
string table data
Definition: Constants.f90:179
@ tabreal
real table data
Definition: Constants.f90:182
@ tabinteger
integer table data
Definition: Constants.f90:181
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
real(dp), parameter dp9
real constant 9/10
Definition: Constants.f90:72
real(dp), parameter dem10
real constant 1e-10
Definition: Constants.f90:113
real(dp), parameter dem7
real constant 1e-7
Definition: Constants.f90:110
real(dp), parameter dem8
real constant 1e-8
Definition: Constants.f90:111
integer(i4b), parameter namedboundflag
named bound flag
Definition: Constants.f90:49
real(dp), parameter dnodata
real no data constant
Definition: Constants.f90:95
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:93
integer(i4b), parameter lenlistlabel
maximum length of a llist label
Definition: Constants.f90:46
real(dp), parameter dhundred
real constant 100
Definition: Constants.f90:86
integer(i4b), parameter lenpakloc
maximum length of a package location
Definition: Constants.f90:50
real(dp), parameter dem1
real constant 1e-1
Definition: Constants.f90:103
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
integer(i4b), parameter lenftype
maximum length of a package type (DIS, WEL, OC, etc.)
Definition: Constants.f90:39
real(dp), parameter dgravity
real constant gravitational acceleration (m/(s s))
Definition: Constants.f90:132
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition: Constants.f90:35
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:36
real(dp), parameter dem4
real constant 1e-4
Definition: Constants.f90:107
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
real(dp), parameter dten
real constant 10
Definition: Constants.f90:84
real(dp), parameter dprec
real constant machine precision
Definition: Constants.f90:120
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:47
real(dp), parameter dem15
real constant 1e-15
Definition: Constants.f90:116
real(dp), parameter dtwo
real constant 2
Definition: Constants.f90:79
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter dthree
real constant 3
Definition: Constants.f90:80
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
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:83
This module contains the CSUB package methods.
Definition: gwf-csub.f90:9
subroutine csub_nodelay_wcomp_fn(this, ib, node, tled, area, hcell, hcellold, hcof, rhs)
@ brief Formulate no-delay interbed water compressibility coefficients
Definition: gwf-csub.f90:5044
real(dp) function csub_calc_delay_flow(this, ib, n, hcell)
Calculate the flow from delay interbed top or bottom.
Definition: gwf-csub.f90:6455
subroutine csub_source_dimensions(this)
@ brief Source dimensions for package
Definition: gwf-csub.f90:818
subroutine csub_cg_wcomp_fc(this, node, tled, area, hcell, hcellold, hcof, rhs)
@ brief Formulate coarse-grained water compressibility coefficients
Definition: gwf-csub.f90:4877
subroutine, public csub_cr(csubobj, name_model, mempath, istounit, stoPckName, inunit, iout)
@ brief Create a new package object
Definition: gwf-csub.f90:320
subroutine csub_calc_sfacts(this, node, bot, znode, theta, es, es0, fact)
Calculate specific storage coefficient factor.
Definition: gwf-csub.f90:5318
subroutine csub_delay_assemble_fn(this, ib, n, hcell, aii, au, al, r)
Assemble delay interbed Newton-Raphson formulation coefficients.
Definition: gwf-csub.f90:5887
subroutine csub_ar(this, dis, ibound)
@ brief Allocate and read method for package
Definition: gwf-csub.f90:354
subroutine csub_initialize_tables(this)
@ brief Initialize optional tables
Definition: gwf-csub.f90:2715
subroutine csub_nodelay_wcomp_fc(this, ib, node, tled, area, hcell, hcellold, hcof, rhs)
@ brief Formulate no-delay interbed water compressibility coefficients
Definition: gwf-csub.f90:4994
real(dp) function csub_calc_sat_derivative(this, node, hcell)
Calculate the saturation derivative.
Definition: gwf-csub.f90:5290
character(len=lenbudtxt), dimension(4) budtxt
Definition: gwf-csub.f90:49
subroutine csub_cg_calc_comp(this, node, hcell, hcellold, comp)
@ brief Calculate coarse-grained compaction in a cell
Definition: gwf-csub.f90:4803
real(dp) function csub_calc_adjes(this, node, es0, z0, z)
Calculate the effective stress at elevation z.
Definition: gwf-csub.f90:5185
subroutine csub_cg_wcomp_fn(this, node, tled, area, hcell, hcellold, hcof, rhs)
@ brief Formulate coarse-grained water compressibility coefficients
Definition: gwf-csub.f90:4931
subroutine csub_interbed_fc(this, ib, node, area, hcell, hcellold, hcof, rhs)
@ brief Formulate the coefficients for a interbed
Definition: gwf-csub.f90:4571
subroutine csub_delay_fc(this, ib, hcof, rhs)
Calculate delay interbed contribution to the cell.
Definition: gwf-csub.f90:6422
subroutine csub_delay_update(this, ib)
Update delay interbed material properties.
Definition: gwf-csub.f90:6342
subroutine csub_delay_init_zcell(this, ib)
Calculate delay interbed znode and z relative to interbed center.
Definition: gwf-csub.f90:5481
subroutine csub_nodelay_update(this, i)
@ brief Update no-delay material properties
Definition: gwf-csub.f90:3851
subroutine csub_source_packagedata(this)
@ brief source packagedata for package
Definition: gwf-csub.f90:1195
subroutine csub_allocate_arrays(this)
@ brief Allocate package arrays
Definition: gwf-csub.f90:973
subroutine csub_delay_calc_ssksske(this, ib, n, hcell, ssk, sske)
Calculate delay interbed cell storage coefficients.
Definition: gwf-csub.f90:5618
subroutine csub_adj_matprop(this, comp, thick, theta)
Calculate new material properties.
Definition: gwf-csub.f90:5358
subroutine log_options(this, warn_estress_lag)
@ brief log options for package
Definition: gwf-csub.f90:695
subroutine csub_cg_calc_sske(this, n, sske, hcell)
@ brief Calculate Sske for a cell
Definition: gwf-csub.f90:4747
real(dp) function csub_calc_void_ratio(this, theta)
Calculate the void ratio.
Definition: gwf-csub.f90:5099
subroutine csub_fc(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
@ brief Fill A and r for the package
Definition: gwf-csub.f90:2500
subroutine csub_calc_sat(this, node, hcell, hcellold, snnew, snold)
Calculate cell saturation.
Definition: gwf-csub.f90:5256
real(dp) function csub_calc_theta(this, void_ratio)
Calculate the porosity.
Definition: gwf-csub.f90:5115
subroutine csub_cc(this, innertot, kiter, iend, icnvgmod, nodes, hnew, hold, cpak, ipak, dpak)
@ brief Final convergence check
Definition: gwf-csub.f90:2777
subroutine csub_delay_calc_wcomp(this, ib, dwc)
Calculate delay interbed water compressibility.
Definition: gwf-csub.f90:6209
subroutine csub_delay_calc_sat(this, node, idelay, n, hcell, hcellold, snnew, snold)
Calculate delay interbed saturation.
Definition: gwf-csub.f90:6054
subroutine csub_source_griddata(this)
@ brief Source griddata for package
Definition: gwf-csub.f90:1143
real(dp) function csub_calc_znode(this, top, bottom, zbar)
Calculate the cell node.
Definition: gwf-csub.f90:5158
subroutine csub_delay_calc_comp(this, ib, hcell, hcellold, comp, compi, compe)
Calculate delay interbed compaction.
Definition: gwf-csub.f90:6262
subroutine csub_delay_calc_stress(this, ib, hcell)
Calculate delay interbed stress values.
Definition: gwf-csub.f90:5538
subroutine source_options(this)
@ brief Source options for package
Definition: gwf-csub.f90:531
subroutine csub_nodelay_calc_comp(this, ib, hcell, hcellold, comp, rho1, rho2)
@ brief Calculate no-delay interbed compaction
Definition: gwf-csub.f90:4003
subroutine csub_set_initial_state(this, nodes, hnew)
@ brief Set initial states for the package
Definition: gwf-csub.f90:4044
subroutine csub_cg_calc_stress(this, nodes, hnew)
@ brief Calculate the stress for model cells
Definition: gwf-csub.f90:3657
real(dp) function csub_calc_interbed_thickness(this, ib)
Calculate the interbed thickness.
Definition: gwf-csub.f90:5132
real(dp), parameter dlog10es
derivative of the log of effective stress
Definition: gwf-csub.f90:64
subroutine csub_delay_assemble_fc(this, ib, n, hcell, aii, au, al, r)
Assemble delay interbed standard formulation coefficients.
Definition: gwf-csub.f90:5756
subroutine csub_interbed_fn(this, ib, node, hcell, hcellold, hcof, rhs)
@ brief Formulate the coefficients for a interbed
Definition: gwf-csub.f90:4657
subroutine csub_print_packagedata(this)
@ brief Print packagedata
Definition: gwf-csub.f90:1552
subroutine csub_rp_obs(this)
Read and prepare the observations.
Definition: gwf-csub.f90:6911
subroutine csub_rp(this)
@ brief Read and prepare stress period data for package
Definition: gwf-csub.f90:2283
subroutine csub_nodelay_fc(this, ib, hcell, hcellold, rho1, rho2, rhs, argtled)
@ brief Calculate no-delay interbed storage coefficients
Definition: gwf-csub.f90:3896
subroutine csub_ad(this, nodes, hnew)
@ brief Advance the package
Definition: gwf-csub.f90:2386
subroutine csub_bd_obs(this)
Set the observations for this time step.
Definition: gwf-csub.f90:6686
subroutine csub_cg_update(this, node)
@ brief Update coarse-grained material properties
Definition: gwf-csub.f90:4832
subroutine csub_delay_assemble(this, ib, hcell)
Assemble delay interbed coefficients.
Definition: gwf-csub.f90:5720
subroutine csub_bd(this, isuppress_output, model_budget)
@ brief Model budget calculation for package
Definition: gwf-csub.f90:3261
subroutine define_listlabel(this)
@ brief Define the list label for the package
Definition: gwf-csub.f90:7203
subroutine csub_ot_dv(this, idvfl, idvprint)
@ brief Save and print dependent values for package
Definition: gwf-csub.f90:3392
real(dp) function csub_delay_calc_sat_derivative(this, node, idelay, n, hcell)
Calculate the delay interbed cell saturation derivative.
Definition: gwf-csub.f90:6093
subroutine csub_da(this)
@ brief Deallocate package memory
Definition: gwf-csub.f90:2066
subroutine csub_save_model_flows(this, icbcfl, icbcun)
@ brief Save model flows for package
Definition: gwf-csub.f90:3301
subroutine csub_cg_fn(this, node, tled, area, hcell, hcof, rhs)
@ brief Formulate coarse-grained Newton-Raphson terms
Definition: gwf-csub.f90:4499
subroutine csub_delay_head_check(this, ib)
Check delay interbed head.
Definition: gwf-csub.f90:5206
subroutine csub_delay_sln(this, ib, hcell, update)
Solve delay interbed continuity equation.
Definition: gwf-csub.f90:5388
subroutine csub_fp(this)
@ brief Final processing for package
Definition: gwf-csub.f90:1657
subroutine csub_process_obsid(obsrv, dis, inunitobs, iout)
Process the observation IDs for the package.
Definition: gwf-csub.f90:7083
subroutine csub_fn(this, kiter, hold, hnew, matrix_sln, idxglo, rhs)
@ brief Fill Newton-Raphson terms in A and r for the package
Definition: gwf-csub.f90:2617
logical function csub_obs_supported(this)
Determine if observations are supported.
Definition: gwf-csub.f90:6481
character(len=lenbudtxt), dimension(6) comptxt
Definition: gwf-csub.f90:54
subroutine csub_delay_calc_dstor(this, ib, hcell, stoe, stoi)
Calculate delay interbed storage change.
Definition: gwf-csub.f90:6124
subroutine csub_cg_chk_stress(this)
@ brief Check effective stress values
Definition: gwf-csub.f90:3790
subroutine csub_cg_fc(this, node, tled, area, hcell, hcellold, hcof, rhs)
@ brief Formulate the coefficients for coarse-grained materials
Definition: gwf-csub.f90:4433
subroutine csub_cq(this, nodes, hnew, hold, isuppress_output, flowja)
@ brief Calculate flows for package
Definition: gwf-csub.f90:2962
subroutine csub_allocate_scalars(this)
@ brief Allocate scalars
Definition: gwf-csub.f90:863
subroutine csub_df_obs(this)
Define the observation types available in the package.
Definition: gwf-csub.f90:6494
subroutine, public ims_misc_thomas(n, tl, td, tu, b, x, w)
Tridiagonal solve using the Thomas algorithm.
subroutine, public urdaux(naux, inunit, iout, lloc, istart, istop, auxname, line, text)
Read auxiliary variables from an input line.
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 openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
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
Store and issue logging messages to output units.
Definition: Message.f90:2
subroutine, public write_message(text, iunit, fmt, skipbefore, skipafter, advance)
Write a message to an output unit.
Definition: Message.f90:210
This module contains the base numerical package type.
This module contains the derived types ObserveType and ObsDataType.
Definition: Observe.f90:15
This module contains the derived type ObsType.
Definition: Obs.f90:127
subroutine, public obs_cr(obs, inobs)
@ brief Create a new ObsType object
Definition: Obs.f90:225
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:236
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
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 squadratic0spderivative(x, xi, tomega)
@ brief sQuadratic0spDerivative
real(dp) function squadratic0sp(x, xi, tomega)
@ brief sQuadratic0sp
subroutine, public selectn(indx, v, reverse)
Definition: sort.f90:384
This module contains the SourceCommonModule.
Definition: SourceCommon.f90:7
logical(lgp) function, public filein_fname(filename, tagname, input_mempath, input_fname)
enforce and set a single input filename provided via FILEIN keyword
subroutine, public table_cr(this, name, title)
Definition: Table.f90:87
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
Derived type for the Budget object.
Definition: Budget.f90:39
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23