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