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