MODFLOW 6  version 6.9.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  if (this%readasarrays) then
172  call mem_allocate(this%dblvec, this%maxbound, 'DBLVEC', this%memoryPath)
173  do i = 1, this%maxbound
174  this%dblvec(i) = dzero
175  end do
176  else
177  ! list mode: alias into the loader's permanent, BNDNO-indexed array
178  ! (allocated and DZERO-initialized by the loader)
179  call mem_setptr(this%dblvec, trim(this%depvarname), this%input_mempath)
180  end if
181  end subroutine allocate_arrays
182 
183  !> @brief Get the data value from this package
184  !!
185  !! Get the floating point value from the dblvec array.
186  !!
187  !<
188  function get_value(this, ientry, nbound_flow) result(value)
189  class(tspspctype) :: this !< TspSpcType object
190  integer(I4B), intent(in) :: ientry !< index of the data to return
191  integer(I4B), intent(in) :: nbound_flow !< size of bound list in flow package
192  real(dp) :: value
193  integer(I4B) :: nu
194  if (this%readasarrays) then
195  ! -- Special handling for reduced grids and readasarrays.
196  ! -- If flow and transport are in the same simulation, ientry is a user
197  ! -- node number and corresponds to the correct position in dblvec.
198  ! -- If flow and transport are not in the same simulation, ientry is a
199  ! -- reduced node number, because the list of flows in the budget file
200  ! -- does not include idomain < 1 entries. In that case, ientry must be
201  ! -- converted to a user node number so that it corresponds to a user
202  ! -- array, which includes idomain < 1 values.
203  if (nbound_flow == this%maxbound) then
204  ! -- flow and transport are in the same simulation or there
205  ! -- are no idomain < 1 cells.
206  value = this%dblvec(ientry)
207  else
208  ! -- flow and transport are in separate simulations; nbound_flow
209  ! -- would equal ncpl if in the same simulation, but boundary cells
210  ! -- with idomain < 1 are excluded from the binary budget file.
211  nu = this%dis%get_nodeuser(ientry)
212  value = this%dblvec(nu)
213  end if
214  else
215  value = this%dblvec(ientry)
216  end if
217  end function get_value
218 
219  !> @brief Apply current input mempath values to dblvec, then echo them
220  !!
221  !! Array mode copies the depvarname array into dblvec. List mode's
222  !! dblvec is already a permanent, BNDNO-indexed alias into the input
223  !! context, so there is nothing to copy.
224  !<
225  subroutine apply_input_values(this)
226  ! -- dummy
227  class(tspspctype), intent(inout) :: this !< TspSpcType object
228  ! -- local
229  real(DP), dimension(:), pointer, contiguous :: val_arr
230  integer(I4B) :: n
231  ! -- formats
232  character(len=*), parameter :: fmthdr = &
233  &"(1X,/1X,'INPUT VALUES FOR ',A,' PACKAGE (PACKAGE ',A,')')"
234  character(len=*), parameter :: fmtdvhdr = &
235  &"(5X,'NO.',5X,A)"
236  character(len=*), parameter :: fmtdvval = &
237  &"(5X,I6,2X,G12.5)"
238  !
239  if (this%readasarrays) then
240  call mem_setptr(val_arr, trim(this%depvarname), this%input_mempath)
241  do n = 1, this%maxbound
242  this%dblvec(n) = val_arr(n)
243  end do
244  end if
245  if (this%iprpak /= 0) then
246  write (this%iout, fmthdr) trim(this%depvarname), &
247  trim(this%packNameFlow)
248  write (this%iout, fmtdvhdr) trim(this%depvarname)
249  do n = 1, this%maxbound
250  write (this%iout, fmtdvval) n, this%dblvec(n)
251  end do
252  end if
253  end subroutine apply_input_values
254 
255  !> @brief Read and prepare stress period data
256  !!
257  !! Copies input period data into dblvec when new data
258  !! has been loaded for this stress period.
259  !!
260  !<
261  subroutine spc_rp(this, nbound_flowpack, budtxt)
262  ! -- dummy
263  class(tspspctype), intent(inout) :: this !< TspSpcType object
264  integer(I4B), intent(in) :: nbound_flowpack
265  character(len=*), intent(in) :: budtxt
266  ! -- local
267  integer(I4B), pointer :: iper
268  ! -- formats
269  character(len=*), parameter :: fmtlsp = &
270  &"(1X,/1X,'REUSING ',A,'S FROM LAST STRESS PERIOD')"
271  !
272  call mem_setptr(iper, 'IPER', this%input_mempath)
273  if (iper /= kper) then
274  write (this%iout, fmtlsp) trim(ftype)
275  return
276  end if
277  !
278  ! -- spc_ad applies each time step
279  if (this%ts_active) return
280  !
281  call this%apply_input_values()
282  call this%check_flow_package(nbound_flowpack, budtxt)
283  end subroutine spc_rp
284 
285  !> @brief Advance
286  !!
287  !! Apply advanced input values at each time step.
288  !!
289  !<
290  subroutine spc_ad(this, nbound_flowpack, budtxt)
291  ! -- dummy
292  class(tspspctype), intent(inout) :: this !< TspSpcType object
293  integer(I4B), intent(in) :: nbound_flowpack
294  character(len=*), intent(in) :: budtxt
295  !
296  ! -- no-op if timeseries inactive
297  if (.not. this%ts_active) return
298  !
299  call this%apply_input_values()
300  call this%check_flow_package(nbound_flowpack, budtxt)
301  end subroutine spc_ad
302 
303  !> @brief Deallocate variables
304  !<
305  subroutine spc_da(this)
306  ! -- modules
308  ! -- dummy variables
309  class(tspspctype) :: this !< TspSpcType object
310  !
311  nullify (this%dis)
312  if (this%readasarrays) then
313  call mem_deallocate(this%dblvec)
314  else
315  nullify (this%dblvec) ! input-context-owned alias, not package-allocated
316  end if
317  call mem_deallocate(this%id)
318  call mem_deallocate(this%iout)
319  call mem_deallocate(this%maxbound)
320  call mem_deallocate(this%iprpak)
321  call mem_deallocate(this%readasarrays)
322  end subroutine spc_da
323 
324  !> @brief Check flow package consistency
325  !!
326  !! Check that MAXBOUND is not less than nbound_flowpack and that
327  !! readasarrays is consistent with the flow package type.
328  !!
329  !<
330  subroutine check_flow_package(this, nbound_flowpack, budtxt)
331  ! -- dummy
332  class(tspspctype), intent(inout) :: this !< TspSpcType object
333  integer(I4B), intent(in) :: nbound_flowpack
334  character(len=*), intent(in) :: budtxt
335  !
336  ! -- Check and make sure MAXBOUND is not less than nbound_flowpack
337  if (this%maxbound < nbound_flowpack) then
338  write (errmsg, '(a,a,a,i0,a,i0,a)') &
339  'The SPC Package corresponding to flow package ', &
340  trim(this%packNameFlow), &
341  ' has MAXBOUND set less than the number of boundaries &
342  &active in this package. Found MAXBOUND equal ', &
343  this%maxbound, &
344  ' and number of flow boundaries (NBOUND) equal ', &
345  nbound_flowpack, &
346  '. Increase MAXBOUND in the SPC input file for this package.'
347  call store_error(errmsg)
348  call store_error_filename(this%input_fname)
349  end if
350  !
351  ! -- If budtxt is RCHA or EVTA, then readasarrays must be used, otherwise
352  ! readasarrays cannot be used
353  select case (trim(adjustl(budtxt)))
354  case ('RCHA')
355  if (.not. this%readasarrays) then
356  write (errmsg, '(a,a,a)') &
357  'Array-based recharge must be used with array-based stress package &
358  &concentrations. GWF Package ', trim(this%packNameFlow), ' is being &
359  &used with list-based SPC6 input. Use array-based SPC6 input instead.'
360  call store_error(errmsg)
361  call store_error_filename(this%input_fname)
362  end if
363  case ('EVTA')
364  if (.not. this%readasarrays) then
365  write (errmsg, '(a,a,a)') &
366  'Array-based evapotranspiration must be used with array-based stress &
367  &package concentrations. GWF Package ', trim(this%packNameFlow), &
368  &' is being used with list-based SPC6 input. Use array-based SPC6 &
369  &input instead.'
370  call store_error(errmsg)
371  call store_error_filename(this%input_fname)
372  end if
373  case default
374  if (this%readasarrays) then
375  write (errmsg, '(a,a,a)') &
376  'List-based packages must be used with list-based stress &
377  &package concentrations. GWF Package ', trim(this%packNameFlow), &
378  &' is being used with array-based SPC6 input. Use list-based SPC6 &
379  &input instead.'
380  call store_error(errmsg)
381  call store_error_filename(this%input_fname)
382  end if
383  end select
384  end subroutine check_flow_package
385 
386 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:204
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:291
subroutine spc_da(this)
Deallocate variables.
Definition: TspSpc.f90:306
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:331
real(dp) function get_value(this, ientry, nbound_flow)
Get the data value from this package.
Definition: TspSpc.f90:189
subroutine allocate_scalars(this)
Allocate package scalars.
Definition: TspSpc.f90:143
subroutine apply_input_values(this)
Apply current input mempath values to dblvec, then echo them.
Definition: TspSpc.f90:226
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:262
Derived type for managing SPC input.
Definition: TspSpc.f90:34