MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
TspSpc.f90
Go to the documentation of this file.
1 !> @brief This module contains the TspSpc Module
2 !!
3 !! This module contains the code for reading and storing a
4 !! generic input file of source and sink concentrations or
5 !! temperatures.
6 !!
7 !<
9 
10  use kindmodule, only: dp, lgp, i4b
14  use simvariablesmodule, only: errmsg
19  use basedismodule, only: disbasetype
20  use tdismodule, only: kper
21 
22  implicit none
23  private
24  public :: tspspctype
25 
26  character(len=LENFTYPE) :: ftype = 'SPC'
27 
28  !> @brief Derived type for managing SPC input
29  !!
30  !! This derived type reads pre-loaded values from the SPC input
31  !! memory path and provides concentrations or temperatures to the
32  !! SSM package for individual GWF stress packages.
33  !<
34  type :: tspspctype
35 
36  character(len=LENMODELNAME) :: name_model = '' !< the name of the model that contains this package
37  character(len=LENPACKAGENAME) :: packname = '' !< name of the package
38  character(len=LENPACKAGENAME) :: packnameflow = '' !< name of the corresponding flow package
39  character(len=LENVARNAME) :: depvarname = '' !< name of the dependent variable (CONCENTRATION or TEMPERATURE)
40  character(len=LENMEMPATH) :: memorypath = '' !< the location in the memory manager where the variables are stored
41  character(len=LENMEMPATH) :: input_mempath = '' !< input memory path for SPC data
42  character(len=LINELENGTH) :: input_fname = '' !< SPC input file name
43  integer(I4B), pointer :: id => null() !< id number for this spc package
44  integer(I4B), pointer :: iout => null() !< unit number for output
45  integer(I4B), pointer :: maxbound => null() !< length of dblvec
46  integer(I4B), pointer :: iprpak => null() !< flag for printing input
47  logical(LGP), pointer :: readasarrays => null() !< flag for reading concentrations as an array
48  logical(LGP) :: ts_active = .false. !< .true. if timeseries or time-array series are active
49  real(dp), dimension(:), pointer, contiguous :: dblvec => null() !< vector of floats read from file
50  class(disbasetype), pointer :: dis => null() !< model discretization object
51 
52  contains
53 
54  procedure :: initialize
55  procedure :: allocate_scalars
56  procedure :: allocate_arrays
57  procedure :: get_value
58  procedure :: apply_input_values
59  procedure :: spc_rp
60  procedure :: spc_ad
61  procedure :: spc_da
62  procedure :: check_flow_package
63 
64  end type tspspctype
65 
66 contains
67 
68  !> @brief Initialize the SPC type
69  !!
70  !! Initialize the SPC object using input context data.
71  !!
72  !<
73  subroutine initialize(this, dis, id, input_mempath, iout, name_model, &
74  packNameFlow, dvn, input_fname)
75  ! -- dummy variables
76  class(tspspctype) :: this !< TspSpcType
77  class(disbasetype), pointer, intent(in) :: dis !< discretization package
78  integer(I4B), intent(in) :: id !< id number for this spc package
79  character(len=*), intent(in) :: input_mempath !< input memory path
80  integer(I4B), intent(in) :: iout !< unit number for output
81  character(len=*), intent(in) :: name_model !< model name
82  character(len=*), intent(in) :: packNameFlow !< name of corresponding flow package
83  character(len=*), intent(in) :: dvn !< dependent variable name (CONCENTRATION or TEMPERATURE)
84  character(len=*), intent(in) :: input_fname !< SPC input file name
85  ! -- local
86  integer(I4B), pointer :: maxbound_ptr
87  integer(I4B) :: isize
88  logical(LGP) :: found_print_input
89  !
90  write (this%packName, '(a,i0)') 'SPC-', id
91  !
92  call this%allocate_scalars()
93  !
94  this%name_model = name_model
95  this%memoryPath = create_mem_path(this%name_model, this%packName)
96  this%input_mempath = input_mempath
97  this%input_fname = input_fname
98  this%id = id
99  this%iout = iout
100  this%packNameFlow = packnameflow
101  this%depvarname = dvn
102  this%dis => dis
103  !
104  ! -- READASARRAYS determine array or list based input
105  call get_isize('READASARRAYS', input_mempath, isize)
106  this%readasarrays = (isize > 0)
107  !
108  ! -- set maxbound
109  if (this%readasarrays) then
110  this%maxbound = dis%get_ncpl()
111  else
112  call mem_setptr(maxbound_ptr, 'MAXBOUND', input_mempath)
113  this%maxbound = maxbound_ptr
114  end if
115  !
116  call this%allocate_arrays()
117  !
118  ! -- read PRINT_INPUT flag from input context
119  call mem_set_value(this%iprpak, 'PRINT_INPUT', this%input_mempath, &
120  found_print_input)
121  if (found_print_input) then
122  write (this%iout, '(4x,a)') 'TIME-VARYING INPUT WILL BE PRINTED.'
123  end if
124  !
125  ! -- check for idm managed active timeseries
126  call get_isize('TS6_FILENAME', input_mempath, isize)
127  if (isize > 0) this%ts_active = .true.
128  call get_isize('TAS6_FILENAME', input_mempath, isize)
129  if (isize > 0) this%ts_active = .true.
130  !
131  write (this%iout, '(4x,a,a,a,a,a)') 'USING SPC INPUT FILE ', &
132  trim(input_fname), ' TO SET ', trim(dvn), &
133  'S FOR PACKAGE '//trim(packnameflow)
134  !
135  if (count_errors() > 0) then
136  call store_error_filename(this%input_fname)
137  end if
138  end subroutine initialize
139 
140  !> @brief Allocate package scalars
141  !<
142  subroutine allocate_scalars(this)
143  ! -- modules
145  ! -- dummy variables
146  class(tspspctype) :: this !< TspSpcType object
147  !
148  call mem_allocate(this%id, 'ID', this%memoryPath)
149  call mem_allocate(this%iout, 'IOUT', this%memoryPath)
150  call mem_allocate(this%maxbound, 'MAXBOUND', this%memoryPath)
151  call mem_allocate(this%iprpak, 'IPRPAK', this%memoryPath)
152  call mem_allocate(this%readasarrays, 'READASARRAYS', this%memoryPath)
153  !
154  this%id = 0
155  this%iout = 0
156  this%maxbound = 0
157  this%iprpak = 0
158  this%readasarrays = .false.
159  end subroutine allocate_scalars
160 
161  !> @brief Allocate package arrays
162  !<
163  subroutine allocate_arrays(this)
164  ! -- modules
166  ! -- dummy variables
167  class(tspspctype) :: this !< TspSpcType object
168  ! -- local
169  integer(I4B) :: i
170  !
171  call mem_allocate(this%dblvec, this%maxbound, 'DBLVEC', this%memoryPath)
172  !
173  do i = 1, this%maxbound
174  this%dblvec(i) = dzero
175  end do
176  end subroutine allocate_arrays
177 
178  !> @brief Get the data value from this package
179  !!
180  !! Get the floating point value from the dblvec array.
181  !!
182  !<
183  function get_value(this, ientry, nbound_flow) result(value)
184  class(tspspctype) :: this !< TspSpcType object
185  integer(I4B), intent(in) :: ientry !< index of the data to return
186  integer(I4B), intent(in) :: nbound_flow !< size of bound list in flow package
187  real(dp) :: value
188  integer(I4B) :: nu
189  if (this%readasarrays) then
190  ! -- Special handling for reduced grids and readasarrays.
191  ! -- If flow and transport are in the same simulation, ientry is a user
192  ! -- node number and corresponds to the correct position in dblvec.
193  ! -- If flow and transport are not in the same simulation, ientry is a
194  ! -- reduced node number, because the list of flows in the budget file
195  ! -- does not include idomain < 1 entries. In that case, ientry must be
196  ! -- converted to a user node number so that it corresponds to a user
197  ! -- array, which includes idomain < 1 values.
198  if (nbound_flow == this%maxbound) then
199  ! -- flow and transport are in the same simulation or there
200  ! -- are no idomain < 1 cells.
201  value = this%dblvec(ientry)
202  else
203  ! -- flow and transport are in separate simulations; nbound_flow
204  ! -- would equal ncpl if in the same simulation, but boundary cells
205  ! -- with idomain < 1 are excluded from the binary budget file.
206  nu = this%dis%get_nodeuser(ientry)
207  value = this%dblvec(nu)
208  end if
209  else
210  value = this%dblvec(ientry)
211  end if
212  end function get_value
213 
214  !> @brief Apply current input mempath values to dblvec
215  !!
216  !! For list-based SPC, iterates BNDNO/value rows. For array-based SPCA,
217  !! copies the depvarname array directly.
218  !!
219  !<
220  subroutine apply_input_values(this)
221  ! -- dummy
222  class(tspspctype), intent(inout) :: this !< TspSpcType object
223  ! -- local
224  integer(I4B), pointer :: nbound
225  integer(I4B), dimension(:), pointer, contiguous :: bndno_arr
226  real(DP), dimension(:), pointer, contiguous :: val_arr
227  integer(I4B) :: n
228  ! -- formats
229  character(len=*), parameter :: fmthdr = &
230  &"(1X,/1X,'INPUT VALUES FOR ',A,' PACKAGE (PACKAGE ',A,')')"
231  character(len=*), parameter :: fmtdvhdr = &
232  &"(5X,'NO.',5X,A)"
233  character(len=*), parameter :: fmtdvval = &
234  &"(5X,I6,2X,G12.5)"
235  !
236  if (this%readasarrays) then
237  ! -- array mode: copy depvarname array into dblvec
238  call mem_setptr(val_arr, trim(this%depvarname), this%input_mempath)
239  do n = 1, this%maxbound
240  this%dblvec(n) = val_arr(n)
241  end do
242  if (this%iprpak /= 0) then
243  write (this%iout, fmthdr) trim(this%depvarname), &
244  trim(this%packNameFlow)
245  write (this%iout, fmtdvhdr) trim(this%depvarname)
246  do n = 1, this%maxbound
247  write (this%iout, fmtdvval) n, this%dblvec(n)
248  end do
249  end if
250  else
251  ! -- list mode: apply BNDNO-indexed values; DNODATA entries are skipped
252  call mem_setptr(nbound, 'NBOUND', this%input_mempath)
253  call mem_setptr(bndno_arr, 'BNDNO', this%input_mempath)
254  call mem_setptr(val_arr, trim(this%depvarname), this%input_mempath)
255  do n = 1, nbound
256  if (val_arr(n) /= dnodata) then
257  this%dblvec(bndno_arr(n)) = val_arr(n)
258  end if
259  end do
260  if (this%iprpak /= 0) then
261  write (this%iout, fmthdr) trim(this%depvarname), &
262  trim(this%packNameFlow)
263  write (this%iout, fmtdvhdr) trim(this%depvarname)
264  do n = 1, this%maxbound
265  write (this%iout, fmtdvval) n, this%dblvec(n)
266  end do
267  end if
268  end if
269  end subroutine apply_input_values
270 
271  !> @brief Read and prepare stress period data
272  !!
273  !! Copies input period data into dblvec when new data
274  !! has been loaded for this stress period.
275  !!
276  !<
277  subroutine spc_rp(this, nbound_flowpack, budtxt)
278  ! -- dummy
279  class(tspspctype), intent(inout) :: this !< TspSpcType object
280  integer(I4B), intent(in) :: nbound_flowpack
281  character(len=*), intent(in) :: budtxt
282  ! -- local
283  integer(I4B), pointer :: iper
284  ! -- formats
285  character(len=*), parameter :: fmtlsp = &
286  &"(1X,/1X,'REUSING ',A,'S FROM LAST STRESS PERIOD')"
287  !
288  call mem_setptr(iper, 'IPER', this%input_mempath)
289  if (iper /= kper) then
290  write (this%iout, fmtlsp) trim(ftype)
291  return
292  end if
293  !
294  ! -- spc_ad applies each time step
295  if (this%ts_active) return
296  !
297  call this%apply_input_values()
298  call this%check_flow_package(nbound_flowpack, budtxt)
299  end subroutine spc_rp
300 
301  !> @brief Advance
302  !!
303  !! Apply advanced input values at each time step.
304  !!
305  !<
306  subroutine spc_ad(this, nbound_flowpack, budtxt)
307  ! -- dummy
308  class(tspspctype), intent(inout) :: this !< TspSpcType object
309  integer(I4B), intent(in) :: nbound_flowpack
310  character(len=*), intent(in) :: budtxt
311  !
312  ! -- no-op if timeseries inactive
313  if (.not. this%ts_active) return
314  !
315  call this%apply_input_values()
316  call this%check_flow_package(nbound_flowpack, budtxt)
317  end subroutine spc_ad
318 
319  !> @brief Deallocate variables
320  !<
321  subroutine spc_da(this)
322  ! -- modules
324  ! -- dummy variables
325  class(tspspctype) :: this !< TspSpcType object
326  !
327  nullify (this%dis)
328  call mem_deallocate(this%dblvec)
329  call mem_deallocate(this%id)
330  call mem_deallocate(this%iout)
331  call mem_deallocate(this%maxbound)
332  call mem_deallocate(this%iprpak)
333  call mem_deallocate(this%readasarrays)
334  end subroutine spc_da
335 
336  !> @brief Check flow package consistency
337  !!
338  !! Check that MAXBOUND is not less than nbound_flowpack and that
339  !! readasarrays is consistent with the flow package type.
340  !!
341  !<
342  subroutine check_flow_package(this, nbound_flowpack, budtxt)
343  ! -- dummy
344  class(tspspctype), intent(inout) :: this !< TspSpcType object
345  integer(I4B), intent(in) :: nbound_flowpack
346  character(len=*), intent(in) :: budtxt
347  !
348  ! -- Check and make sure MAXBOUND is not less than nbound_flowpack
349  if (this%maxbound < nbound_flowpack) then
350  write (errmsg, '(a,a,a,i0,a,i0,a)') &
351  'The SPC Package corresponding to flow package ', &
352  trim(this%packNameFlow), &
353  ' has MAXBOUND set less than the number of boundaries &
354  &active in this package. Found MAXBOUND equal ', &
355  this%maxbound, &
356  ' and number of flow boundaries (NBOUND) equal ', &
357  nbound_flowpack, &
358  '. Increase MAXBOUND in the SPC input file for this package.'
359  call store_error(errmsg)
360  call store_error_filename(this%input_fname)
361  end if
362  !
363  ! -- If budtxt is RCHA or EVTA, then readasarrays must be used, otherwise
364  ! readasarrays cannot be used
365  select case (trim(adjustl(budtxt)))
366  case ('RCHA')
367  if (.not. this%readasarrays) then
368  write (errmsg, '(a,a,a)') &
369  'Array-based recharge must be used with array-based stress package &
370  &concentrations. GWF Package ', trim(this%packNameFlow), ' is being &
371  &used with list-based SPC6 input. Use array-based SPC6 input instead.'
372  call store_error(errmsg)
373  call store_error_filename(this%input_fname)
374  end if
375  case ('EVTA')
376  if (.not. this%readasarrays) then
377  write (errmsg, '(a,a,a)') &
378  'Array-based evapotranspiration must be used with array-based stress &
379  &package concentrations. GWF Package ', trim(this%packNameFlow), &
380  &' is being used with list-based SPC6 input. Use array-based SPC6 &
381  &input instead.'
382  call store_error(errmsg)
383  call store_error_filename(this%input_fname)
384  end if
385  case default
386  if (this%readasarrays) then
387  write (errmsg, '(a,a,a)') &
388  'List-based packages must be used with list-based stress &
389  &package concentrations. GWF Package ', trim(this%packNameFlow), &
390  &' is being used with array-based SPC6 input. Use list-based SPC6 &
391  &input instead.'
392  call store_error(errmsg)
393  call store_error_filename(this%input_fname)
394  end if
395  end select
396  end subroutine check_flow_package
397 
398 end module tspspcmodule
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition: Constants.f90:22
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
real(dp), parameter dnodata
real no data constant
Definition: Constants.f90:95
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
integer(i4b), parameter lenftype
maximum length of a package type (DIS, WEL, OC, etc.)
Definition: Constants.f90:39
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
subroutine, public get_isize(name, mem_path, isize)
@ brief Get the number of elements for this variable
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:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
This module contains the TspSpc Module.
Definition: TspSpc.f90:8
subroutine spc_ad(this, nbound_flowpack, budtxt)
Advance.
Definition: TspSpc.f90:307
subroutine spc_da(this)
Deallocate variables.
Definition: TspSpc.f90:322
character(len=lenftype) ftype
Definition: TspSpc.f90:26
subroutine initialize(this, dis, id, input_mempath, iout, name_model, packNameFlow, dvn, input_fname)
Initialize the SPC type.
Definition: TspSpc.f90:75
subroutine check_flow_package(this, nbound_flowpack, budtxt)
Check flow package consistency.
Definition: TspSpc.f90:343
real(dp) function get_value(this, ientry, nbound_flow)
Get the data value from this package.
Definition: TspSpc.f90:184
subroutine allocate_scalars(this)
Allocate package scalars.
Definition: TspSpc.f90:143
subroutine apply_input_values(this)
Apply current input mempath values to dblvec.
Definition: TspSpc.f90:221
subroutine allocate_arrays(this)
Allocate package arrays.
Definition: TspSpc.f90:164
subroutine spc_rp(this, nbound_flowpack, budtxt)
Read and prepare stress period data.
Definition: TspSpc.f90:278
Derived type for managing SPC input.
Definition: TspSpc.f90:34