MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
TvBase.f90
Go to the documentation of this file.
1 !> @brief This module contains common time-varying property functionality
2 !!
3 !! This module contains methods implementing functionality common to both
4 !! time-varying hydraulic conductivity (TVK) and time-varying storage (TVS)
5 !! packages.
6 !!
7 !<
9  use basedismodule, only: disbasetype
10  use constantsmodule, only: maxcharlen, dzero
11  use geomutilmodule, only: get_node
12  use kindmodule, only: i4b, dp, lgp
15  use simvariablesmodule, only: errmsg
16  use stlvecintmodule, only: stlvecint
17  use tdismodule, only: kper, nper, kstp
19 
20  implicit none
21 
22  private
23 
24  public :: tvbasetype
25  public :: tvbase_da
26 
27  type, abstract, extends(numericalpackagetype) :: tvbasetype
28  logical(LGP) :: ts_active = .false. !< is timeseries active in package
29  integer(I4B), dimension(:, :), pointer, contiguous :: cellid => null() !< input cellids of time varying value
30  type(stlvecint) :: tracked_nodeu !< unreduced node numbers ever set, in first-set order, no duplicates
31  contains
32  procedure :: init
33  procedure :: ar
34  procedure :: rp
35  procedure :: ad
36  procedure :: da => tvbase_da
37  procedure, private :: tvbase_allocate_scalars
38  procedure, private :: sync_node_changes
39  procedure, private :: cellid_to_nodeu
40  procedure(ar_set_pointers), deferred :: ar_set_pointers
41  procedure :: source_options => tvbase_source_options
42  procedure :: source_package_options => tvbase_source_package_options
43  procedure(apply_row_changes), deferred :: apply_row_changes
44  procedure(set_changed_at), deferred :: set_changed_at
45  procedure(reset_change_flags), deferred :: reset_change_flags
46  procedure(validate_change), deferred :: validate_change
47  end type tvbasetype
48 
49  abstract interface
50 
51  !> @brief Announce package and set pointers to variables
52  !!
53  !! Deferred procedure called by the TvBaseType code to announce the
54  !! specific package version and set any required array and variable
55  !! pointers from other packages.
56  !<
57  subroutine ar_set_pointers(this)
58  ! -- modules
59  import tvbasetype
60  ! -- dummy
61  class(tvbasetype) :: this
62  end subroutine
63 
64  !> @brief Apply this node's current input value(s) to the model
65  !! property array(s).
66  !!
67  !! Called for every tracked node; each field's own DNODATA check
68  !! determines whether there is anything to do. node may be invalid
69  !! even when a field has a value at nodeu, so each live-field branch
70  !! must validate node itself before using it.
71  !<
72  subroutine apply_row_changes(this, nodeu, node)
73  ! -- modules
74  use kindmodule, only: i4b
75  import tvbasetype
76  ! -- dummy
77  class(tvbasetype) :: this
78  integer(I4B), intent(in) :: nodeu !< unreduced node number, indexes the permanent input arrays
79  integer(I4B), intent(in) :: node !< reduced node number; may be invalid, see above
80  end subroutine
81 
82  !> @brief Mark property changes as having occurred at (kper, kstp)
83  !!
84  !! Deferred procedure called by the TvBaseType code when a property value
85  !! change occurs at (kper, kstp).
86  !<
87  subroutine set_changed_at(this, kper, kstp)
88  ! -- modules
89  use kindmodule, only: i4b
90  import tvbasetype
91  ! -- dummy
92  class(tvbasetype) :: this
93  integer(I4B), intent(in) :: kper
94  integer(I4B), intent(in) :: kstp
95  end subroutine
96 
97  !> @brief Clear all per-node change flags
98  !!
99  !! Deferred procedure called by the TvBaseType code when a new time step
100  !! commences, indicating that any previously set per-node property value
101  !! change flags should be reset.
102  !<
103  subroutine reset_change_flags(this)
104  ! -- modules
105  import tvbasetype
106  ! -- dummy
107  class(tvbasetype) :: this
108  end subroutine
109 
110  !> @brief Check that a given property value is valid
111  !!
112  !! Deferred procedure called by each derived type's apply_row_changes
113  !! implementation after a property value change occurs. Performs any
114  !! required validity checks on the value of the given variable at the
115  !! given node. Perform any required updates to the property value if it
116  !! is valid, or log an error if not.
117  !<
118  subroutine validate_change(this, n, varName)
119  ! -- modules
120  use kindmodule, only: i4b
121  import tvbasetype
122  ! -- dummy
123  class(tvbasetype) :: this
124  integer(I4B), intent(in) :: n
125  character(len=*), intent(in) :: varName
126  end subroutine
127 
128  end interface
129 
130 contains
131 
132  !> @brief Initialize the TvBaseType object
133  !!
134  !! Allocate and initialize data members of the object.
135  !<
136  subroutine init(this, name_model, pakname, ftype, mempath, inunit, iout)
137  ! -- dummy
138  class(tvbasetype) :: this
139  character(len=*), intent(in) :: name_model
140  character(len=*), intent(in) :: pakname
141  character(len=*), intent(in) :: ftype
142  character(len=*), intent(in) :: mempath
143  integer(I4B), intent(in) :: inunit
144  integer(I4B), intent(in) :: iout
145  !
146  call this%set_names(1, name_model, pakname, ftype, mempath)
147  call this%tvbase_allocate_scalars()
148  this%inunit = inunit
149  this%iout = iout
150  end subroutine init
151 
152  !> @brief Allocate scalar variables
153  !!
154  !! Allocate scalar data members of the object.
155  !<
156  subroutine tvbase_allocate_scalars(this)
157  ! -- dummy
158  class(tvbasetype) :: this
159  !
160  ! -- Call standard NumericalPackageType allocate scalars
161  call this%NumericalPackageType%allocate_scalars()
162  end subroutine tvbase_allocate_scalars
163 
164  !> @brief Source common options from the input memory path.
165  !!
166  !! Source common options and call derived package routine to source
167  !! and log any package-specific options within the same block.
168  !<
169  subroutine tvbase_source_options(this)
170  ! -- modules
172  ! -- dummy
173  class(tvbasetype) :: this
174  ! -- locals
175  integer(I4B) :: isize
176  logical(LGP) :: found_print_input
177  !
178  write (this%iout, '(1x,a)') &
179  'PROCESSING '//trim(adjustl(this%packName))//' OPTIONS'
180  !
181  call mem_set_value(this%iprpak, 'PRINT_INPUT', this%input_mempath, &
182  found_print_input)
183  !
184  if (found_print_input) then
185  write (this%iout, '(4x,a)') 'TIME-VARYING INPUT WILL BE PRINTED.'
186  end if
187  !
188  call get_isize('TS6_FILENAME', this%input_mempath, isize)
189  if (isize > 0) this%ts_active = .true.
190  !
191  ! -- source package-specific options
192  call this%source_package_options()
193  !
194  write (this%iout, '(1x,a)') &
195  'END OF '//trim(adjustl(this%packName))//' OPTIONS'
196  end subroutine tvbase_source_options
197 
198  !> @brief Source package-specific options from the input memory path.
199  !!
200  !! Override in derived package to source and log package-specific options.
201  !! Default implementation is a no-op.
202  !<
204  ! -- dummy
205  class(tvbasetype) :: this
206  !
207  ! -- no package-specific options in the base class
208  end subroutine tvbase_source_package_options
209 
210  !> @brief Allocate and read static data for the package.
211  !<
212  subroutine ar(this, dis)
213  ! -- dummy
214  class(tvbasetype) :: this
215  class(disbasetype), pointer, intent(in) :: dis
216  !
217  this%dis => dis
218  call this%ar_set_pointers()
219  !
220  call this%source_options()
221  !
222  ! -- set input mempath pointers
223  call mem_setptr(this%cellid, 'CELLID', this%input_mempath)
224  call this%tracked_nodeu%init()
225  !
226  if (count_errors() > 0) then
227  call store_error_filename(this%input_fname)
228  end if
229  end subroutine ar
230 
231  !> @brief Read and prepare stress period data for the package.
232  !<
233  subroutine rp(this)
234  ! -- dummy
235  class(tvbasetype) :: this
236  ! -- local variables
237  integer(I4B), pointer :: iper, nbound
238  integer(I4B) :: n, nodeu, nodeu_count
239  !
240  ! -- check last loaded input period
241  call mem_setptr(iper, 'IPER', this%input_mempath)
242  if (iper /= kper) return
243  !
244  ! -- record every node newly addressed by this period's own rows in
245  ! -- tracked_nodeu, so sync_node_changes never has to scan the full
246  ! -- node space to find which nodes have a live tracked value
247  call mem_setptr(nbound, 'NBOUND', this%input_mempath)
248  if (nbound > 0) then
249  nodeu_count = product(this%dis%mshape)
250  do n = 1, nbound
251  nodeu = this%cellid_to_nodeu(n)
252  if (nodeu < 1 .or. nodeu > nodeu_count) then
253  write (errmsg, '(a,i0,a)') &
254  'CELLID at PERIOD row ', n, ' is not in the active model domain.'
255  call store_error(errmsg)
256  cycle
257  end if
258  call this%tracked_nodeu%push_back_unique(nodeu)
259  end do
260  end if
261  !
262  ! -- When timeseries are active, ad applies values at every time step
263  if (this%ts_active) return
264  !
265  call this%sync_node_changes()
266  end subroutine rp
267 
268  !> @brief Apply advanced values at each time step.
269  !<
270  subroutine ad(this)
271  ! -- dummy
272  class(tvbasetype) :: this
273  !
274  ! -- no-op when timeseries aren't active.
275  if (.not. this%ts_active) return
276  !
277  call this%sync_node_changes()
278  end subroutine ad
279 
280  !> @brief Sync every tracked node's current input value into the model
281  !! property array(s) it belongs to (e.g. NPF's K11).
282  !<
283  subroutine sync_node_changes(this)
284  ! -- dummy
285  class(tvbasetype) :: this
286  ! -- local variables
287  integer(I4B) :: i, nodeu, node
288  !
289  if (this%tracked_nodeu%size <= 0) return
290  !
291  call this%set_changed_at(kper, kstp)
292  call this%reset_change_flags()
293  !
294  do i = 1, this%tracked_nodeu%size
295  nodeu = this%tracked_nodeu%at(i)
296  node = this%dis%get_nodenumber(nodeu, 1)
297  call this%apply_row_changes(nodeu, node)
298  end do
299  !
300  if (count_errors() > 0) then
301  call store_error_filename(this%input_fname)
302  end if
303  end subroutine sync_node_changes
304 
305  !> @brief Return the unreduced node number for CELLID row n.
306  !<
307  function cellid_to_nodeu(this, n) result(nodeu)
308  ! -- dummy
309  class(tvbasetype) :: this
310  integer(I4B), intent(in) :: n !< row index in the period-data arrays
311  ! -- return
312  integer(I4B) :: nodeu
313  !
314  if (this%dis%ndim == 1) then
315  nodeu = this%cellid(1, n)
316  elseif (this%dis%ndim == 2) then
317  nodeu = get_node(this%cellid(1, n), 1, &
318  this%cellid(2, n), &
319  this%dis%mshape(1), 1, &
320  this%dis%mshape(2))
321  else
322  nodeu = get_node(this%cellid(1, n), &
323  this%cellid(2, n), &
324  this%cellid(3, n), &
325  this%dis%mshape(1), &
326  this%dis%mshape(2), &
327  this%dis%mshape(3))
328  end if
329  end function cellid_to_nodeu
330 
331  !> @brief Deallocate package memory
332  !!
333  !! Deallocate package scalars and arrays.
334  !<
335  subroutine tvbase_da(this)
336  ! -- dummy
337  class(tvbasetype) :: this
338  !
339  nullify (this%cellid)
340  call this%tracked_nodeu%destroy()
341  call this%NumericalPackageType%da()
342  end subroutine tvbase_da
343 
344 end module tvbasemodule
subroutine init()
Definition: GridSorting.f90:25
Apply this node's current input value(s) to the model property array(s).
Definition: TvBase.f90:72
Announce package and set pointers to variables.
Definition: TvBase.f90:57
Clear all per-node change flags.
Definition: TvBase.f90:103
Mark property changes as having occurred at (kper, kstp)
Definition: TvBase.f90:87
Check that a given property value is valid.
Definition: TvBase.f90:118
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:47
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:92
This module defines variable data types.
Definition: kind.f90:8
subroutine, public get_isize(name, mem_path, isize)
@ brief Get the number of elements for this variable
This module contains the base numerical package type.
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:204
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
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
integer(i4b), pointer, public nper
number of stress period
Definition: tdis.f90:24
This module contains common time-varying property functionality.
Definition: TvBase.f90:8
subroutine tvbase_source_options(this)
Source common options from the input memory path.
Definition: TvBase.f90:170
integer(i4b) function cellid_to_nodeu(this, n)
Return the unreduced node number for CELLID row n.
Definition: TvBase.f90:308
subroutine, public tvbase_da(this)
Deallocate package memory.
Definition: TvBase.f90:336
subroutine tvbase_allocate_scalars(this)
Allocate scalar variables.
Definition: TvBase.f90:157
subroutine rp(this)
Read and prepare stress period data for the package.
Definition: TvBase.f90:234
subroutine tvbase_source_package_options(this)
Source package-specific options from the input memory path.
Definition: TvBase.f90:204
subroutine sync_node_changes(this)
Sync every tracked node's current input value into the model property array(s) it belongs to (e....
Definition: TvBase.f90:284
subroutine ad(this)
Apply advanced values at each time step.
Definition: TvBase.f90:271
subroutine ar(this, dis)
Allocate and read static data for the package.
Definition: TvBase.f90:213