MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
swf-pcp.f90
Go to the documentation of this file.
1 !> @brief This module contains the precipitation (PCP) package methods
2 !!
3 !! This module can be used to represent precipitation onto streams and
4 !! overland flow cells.
5 !<
7 
8  use kindmodule, only: dp, i4b, lgp
12  use bndmodule, only: bndtype
13  use bndextmodule, only: bndexttype
15  use simvariablesmodule, only: errmsg
21  use geomutilmodule, only: get_node
22  use basedismodule, only: disbasetype
23  use disv1dmodule, only: disv1dtype
24  use swfdfwmodule, only: swfdfwtype
25  use swfcxsmodule, only: swfcxstype
26 
27  implicit none
28 
29  private
30  public :: pcp_create
31 
32  character(len=LENFTYPE) :: ftype = 'PCP'
33  character(len=LENPACKAGENAME) :: text = ' PCP'
34  ! character(len=LENPACKAGENAME) :: texta = ' PCPA'
35 
36  type, extends(bndexttype) :: swfpcptype
37  real(dp), dimension(:), pointer, contiguous :: precipitation => null() !< boundary precipitation array
38  logical, pointer, private :: read_as_arrays
39 
40  ! pointers to other objects
41  type(swfdfwtype), pointer :: dfw
42  type(swfcxstype), pointer :: cxs
43 
44  contains
45 
46  procedure :: pcp_allocate_scalars
47  procedure :: allocate_arrays => pcp_allocate_arrays
48  procedure :: source_options => pcp_source_options
49  procedure :: source_dimensions => pcp_source_dimensions
50  procedure :: log_pcp_options
51  procedure :: read_initial_attr => pcp_read_initial_attr
52  procedure :: bnd_rp => pcp_rp
53  procedure :: bnd_ck => pcp_ck
54  procedure :: bnd_cf => pcp_cf
55  procedure :: bnd_fc => pcp_fc
56  procedure :: bnd_da => pcp_da
57  procedure :: define_listlabel => pcp_define_listlabel
58  procedure :: bound_value => pcp_bound_value
59  procedure :: default_nodelist
60  procedure, private :: reach_length_pointer
61  ! for observations
62  procedure, public :: bnd_obs_supported => pcp_obs_supported
63  procedure, public :: bnd_df_obs => pcp_df_obs
64 
65  end type swfpcptype
66 
67 contains
68 
69  !> @brief Create a Precipitation Package
70  !<
71  subroutine pcp_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, &
72  mempath, dis, dfw, cxs)
73  ! dummy
74  class(bndtype), pointer :: packobj !< pointer to default package type
75  integer(I4B), intent(in) :: id !< package id
76  integer(I4B), intent(in) :: ibcnum !< boundary condition number
77  integer(I4B), intent(in) :: inunit !< unit number of CDB package input file
78  integer(I4B), intent(in) :: iout !< unit number of model listing file
79  character(len=*), intent(in) :: namemodel !< model name
80  character(len=*), intent(in) :: pakname !< package name
81  character(len=*), intent(in) :: mempath !< input mempath
82  class(disbasetype), pointer, intent(inout) :: dis !< the pointer to the discretization
83  type(swfdfwtype), pointer, intent(in) :: dfw !< the pointer to the dfw package
84  type(swfcxstype), pointer, intent(in) :: cxs !< the pointer to the cxs package
85  ! local
86  type(swfpcptype), pointer :: pcpobj
87 
88  ! allocate precipitation object and scalar variables
89  allocate (pcpobj)
90  packobj => pcpobj
91 
92  ! create name and memory path
93  call packobj%set_names(ibcnum, namemodel, pakname, ftype, mempath)
94  packobj%text = text
95 
96  ! allocate scalars
97  call pcpobj%pcp_allocate_scalars()
98 
99  ! initialize package
100  call packobj%pack_initialize()
101 
102  packobj%inunit = inunit
103  packobj%iout = iout
104  packobj%id = id
105  packobj%ibcnum = ibcnum
106  packobj%ncolbnd = 1
107  packobj%ictMemPath = create_mem_path(namemodel, 'DFW')
108 
109  ! store pointer to dis
110  pcpobj%dis => dis
111 
112  ! store pointer to dfw
113  pcpobj%dfw => dfw
114 
115  ! store pointer to cxs
116  pcpobj%cxs => cxs
117  end subroutine pcp_create
118 
119  !> @brief Allocate scalar members
120  !<
121  subroutine pcp_allocate_scalars(this)
122  ! dummy
123  class(swfpcptype), intent(inout) :: this
124 
125  ! allocate base scalars
126  call this%BndExtType%allocate_scalars()
127 
128  ! allocate internal members
129  allocate (this%read_as_arrays)
130 
131  ! Set values
132  this%read_as_arrays = .false.
133  end subroutine pcp_allocate_scalars
134 
135  !> @brief Allocate package arrays
136  !<
137  subroutine pcp_allocate_arrays(this, nodelist, auxvar)
138  ! modules
140  ! dummy
141  class(swfpcptype) :: this
142  integer(I4B), dimension(:), pointer, contiguous, optional :: nodelist
143  real(DP), dimension(:, :), pointer, contiguous, optional :: auxvar
144 
145  ! allocate base arrays
146  call this%BndExtType%allocate_arrays(nodelist, auxvar)
147 
148  ! set input context pointers
149  call mem_setptr(this%precipitation, 'PRECIPITATION', this%input_mempath)
150 
151  ! checkin input context pointers
152  call mem_checkin(this%precipitation, 'PRECIPITATION', this%memoryPath, &
153  'PRECIPITATION', this%input_mempath)
154  end subroutine pcp_allocate_arrays
155 
156  !> @brief Source options specific to PCPType
157  !<
158  subroutine pcp_source_options(this)
159  ! modules
161  implicit none
162  ! dummy
163  class(swfpcptype), intent(inout) :: this
164  ! local
165  logical(LGP) :: found_readasarrays = .false.
166 
167  ! source common bound options
168  call this%BndExtType%source_options()
169 
170  ! update defaults with idm sourced values
171  call mem_set_value(this%read_as_arrays, 'READASARRAYS', this%input_mempath, &
172  found_readasarrays)
173 
174  ! log pcp params
175  call this%log_pcp_options(found_readasarrays)
176  end subroutine pcp_source_options
177 
178  !> @brief Log options specific to SwfPcpType
179  !<
180  subroutine log_pcp_options(this, found_readasarrays)
181  implicit none
182  ! dummy
183  class(swfpcptype), intent(inout) :: this
184  logical(LGP), intent(in) :: found_readasarrays
185  ! formats
186  character(len=*), parameter :: fmtreadasarrays = &
187  &"(4x, 'PRECIPITATION INPUT WILL BE READ AS ARRAY(S).')"
188 
189  ! log found options
190  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text)) &
191  //' OPTIONS'
192 
193  if (found_readasarrays) then
194  write (this%iout, fmtreadasarrays)
195  end if
196 
197  ! close logging block
198  write (this%iout, '(1x,a)') &
199  'END OF '//trim(adjustl(this%text))//' OPTIONS'
200  end subroutine log_pcp_options
201 
202  !> @brief Source the dimensions for this package
203  !<
204  subroutine pcp_source_dimensions(this)
205  ! dummy
206  class(swfpcptype), intent(inout) :: this
207 
208  if (this%read_as_arrays) then
209 
210  ! Set maxbound to the number of cells per layer, which is simply
211  ! nrow * ncol for a dis2d grid, and nodesuser for disv2d and disv1d
212  this%maxbound = this%dis%get_ncpl()
213 
214  ! verify dimensions were set
215  if (this%maxbound <= 0) then
216  write (errmsg, '(a)') &
217  'MAXBOUND must be an integer greater than zero.'
218  call store_error(errmsg)
219  call store_error_filename(this%input_fname)
220  end if
221 
222  else
223 
224  ! source maxbound
225  call this%BndExtType%source_dimensions()
226 
227  end if
228 
229  ! Call define_listlabel to construct the list label that is written
230  ! when PRINT_INPUT option is used.
231  call this%define_listlabel()
232  end subroutine pcp_source_dimensions
233 
234  !> @brief Part of allocate and read
235  !<
236  subroutine pcp_read_initial_attr(this)
237  ! dummy
238  class(swfpcptype), intent(inout) :: this
239 
240  if (this%read_as_arrays) then
241  call this%default_nodelist()
242  end if
243  end subroutine pcp_read_initial_attr
244 
245  !> @brief Read and Prepare
246  !!
247  !! Read itmp and read new boundaries if itmp > 0
248  !<
249  subroutine pcp_rp(this)
250  ! modules
251  use tdismodule, only: kper
252  implicit none
253  ! dummy
254  class(swfpcptype), intent(inout) :: this
255 
256  if (this%iper /= kper) return
257 
258  if (this%read_as_arrays) then
259  ! no need to do anything because this%precipitation points directly to
260  ! the input context precipitation, which is automatically updated by idm
261  else
262  call this%BndExtType%bnd_rp()
263  end if
264  end subroutine pcp_rp
265 
266  !> @brief Ensure precipitation is positive
267  !<
268  subroutine pcp_ck(this)
269  ! dummy
270  class(swfpcptype), intent(inout) :: this
271  ! local
272  character(len=30) :: nodestr
273  integer(I4B) :: i, nr
274  character(len=*), parameter :: fmterr = &
275  &"('Specified stress ',i0, &
276  &' precipitation (',g0,') is less than zero for cell', a)"
277 
278  ! Ensure precipitation rates are positive
279  do i = 1, this%nbound
280  nr = this%nodelist(i)
281  if (nr <= 0) cycle
282  if (this%precipitation(i) < dzero) then
283  call this%dis%noder_to_string(nr, nodestr)
284  write (errmsg, fmt=fmterr) i, this%precipitation(i), trim(nodestr)
285  call store_error(errmsg)
286  end if
287  end do
288 
289  ! write summary of package error messages
290  if (count_errors() > 0) then
291  call store_error_filename(this%input_fname)
292  end if
293  end subroutine pcp_ck
294 
295  !> @brief Formulate the HCOF and RHS terms
296  !!
297  !! Skip if no precipitation. Otherwise, calculate hcof and rhs
298  !<
299  subroutine pcp_cf(this)
300  ! dummy
301  class(swfpcptype) :: this
302  ! local
303  integer(I4B) :: i
304  integer(I4B) :: node
305  integer(I4B) :: idcxs
306  real(DP) :: qpcp
307  real(DP) :: area
308  real(DP) :: width_channel
309  real(DP) :: top_width
310  real(DP) :: dummy
311  real(DP), dimension(:), pointer :: reach_length
312 
313  ! Return if no precipitation
314  if (this%nbound == 0) return
315 
316  ! Set pointer to reach_length for 1d
317  reach_length => this%reach_length_pointer()
318 
319  ! Calculate hcof and rhs for each precipitation entry
320  do i = 1, this%nbound
321 
322  ! Find the node number
323  node = this%nodelist(i)
324 
325  ! cycle if nonexistent bound
326  if (node <= 0) then
327  this%hcof(i) = dzero
328  this%rhs(i) = dzero
329  cycle
330  end if
331 
332  ! Initialize hcof
333  this%hcof(i) = dzero
334 
335  ! Determine the water surface area
336  if (this%dis%is_2d()) then
337  ! this is for overland flow case
338  area = this%dis%get_area(node)
339  else if (this%dis%is_1d()) then
340  ! this is for channel case
341  idcxs = this%dfw%idcxs(node)
342  call this%dis%get_flow_width(node, node, 0, width_channel, &
343  dummy)
344  top_width = this%cxs%get_maximum_top_width(idcxs, width_channel)
345  area = reach_length(node) * top_width
346  end if
347 
348  ! calculate volumetric precipitation flow in L^3/T
349  qpcp = this%precipitation(i) * area
350 
351  ! multiplier
352  if (this%iauxmultcol > 0) then
353  qpcp = qpcp * this%auxvar(this%iauxmultcol, i)
354  end if
355 
356  ! rhs contribution
357  this%rhs(i) = -qpcp
358 
359  ! zero out contribution if cell is inactive or constant head
360  if (this%ibound(node) <= 0) then
361  this%rhs(i) = dzero
362  cycle
363  end if
364 
365  end do
366  end subroutine pcp_cf
367 
368  !> @brief Copy rhs and hcof into solution rhs and amat
369  !<
370  subroutine pcp_fc(this, rhs, ia, idxglo, matrix_sln)
371  ! dummy
372  class(swfpcptype) :: this
373  real(DP), dimension(:), intent(inout) :: rhs
374  integer(I4B), dimension(:), intent(in) :: ia
375  integer(I4B), dimension(:), intent(in) :: idxglo
376  class(matrixbasetype), pointer :: matrix_sln
377  ! local
378  integer(I4B) :: i, n, ipos
379 
380  ! Copy package rhs and hcof into solution rhs and amat
381  do i = 1, this%nbound
382  n = this%nodelist(i)
383  if (n <= 0) cycle
384  rhs(n) = rhs(n) + this%rhs(i)
385  ipos = ia(n)
386  call matrix_sln%add_value_pos(idxglo(ipos), this%hcof(i))
387  end do
388  end subroutine pcp_fc
389 
390  !> @brief Deallocate memory
391  !<
392  subroutine pcp_da(this)
393  ! modules
395  ! dummy
396  class(swfpcptype) :: this
397 
398  ! Deallocate parent package
399  call this%BndExtType%bnd_da()
400 
401  ! scalars
402  deallocate (this%read_as_arrays)
403 
404  ! arrays
405  call mem_deallocate(this%precipitation, 'PRECIPITATION', this%memoryPath)
406 
407  ! pointers
408  nullify (this%dis)
409  nullify (this%dfw)
410  nullify (this%cxs)
411  end subroutine pcp_da
412 
413  !> @brief Define the list heading that is written to iout when PRINT_INPUT
414  !! option is used.
415  !<
416  subroutine pcp_define_listlabel(this)
417  ! dummy
418  class(swfpcptype), intent(inout) :: this
419  !
420  ! create the header list label
421  this%listlabel = trim(this%filtyp)//' NO.'
422  if (this%dis%ndim == 3) then
423  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
424  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
425  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
426  elseif (this%dis%ndim == 2) then
427  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
428  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
429  else
430  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
431  end if
432  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'PRECIPITATION'
433 ! if(this%multindex > 0) &
434 ! write(this%listlabel, '(a, a16)') trim(this%listlabel), 'MULTIPLIER'
435  if (this%inamedbound == 1) then
436  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
437  end if
438  end subroutine pcp_define_listlabel
439 
440  !> @brief Assign default nodelist when READASARRAYS is specified.
441  !<
442  subroutine default_nodelist(this)
443  ! dummy
444  class(swfpcptype) :: this
445  ! local
446  integer(I4B) :: nodeu, noder
447 
448  ! This is only called for readasarrays, so nodelist will be the size of
449  ! the user grid, and will have a value of 0 for any entries where idomain
450  ! is not 1
451  do nodeu = 1, this%maxbound
452  noder = this%dis%get_nodenumber(nodeu, 0)
453  this%nodelist(nodeu) = noder
454  end do
455 
456  ! Assign nbound
457  this%nbound = this%maxbound
458 
459  end subroutine default_nodelist
460 
461  ! Procedures related to observations
462 
463  !> @brief
464  !!
465  !! Overrides BndType%bnd_obs_supported()
466  !<
467  logical function pcp_obs_supported(this)
468  implicit none
469  ! dummy
470  class(swfpcptype) :: this
471  pcp_obs_supported = .true.
472  end function pcp_obs_supported
473 
474  !> @brief Implements bnd_df_obs
475  !!
476  !! Store observation type supported by PCP package. Overrides
477  !! BndType%bnd_df_obs
478  !<
479  subroutine pcp_df_obs(this)
480  implicit none
481  ! dummy
482  class(swfpcptype) :: this
483  ! local
484  integer(I4B) :: indx
485 
486  call this%obs%StoreObsType('pcp', .true., indx)
487  this%obs%obsData(indx)%ProcessIdPtr => defaultobsidprocessor
488  end subroutine pcp_df_obs
489 
490  !> @brief Return requested boundary value
491  !<
492  function pcp_bound_value(this, col, row) result(bndval)
493  ! modules
494  use constantsmodule, only: dzero
495  ! dummy
496  class(swfpcptype), intent(inout) :: this
497  integer(I4B), intent(in) :: col
498  integer(I4B), intent(in) :: row
499  ! result
500  real(dp) :: bndval
501 
502  select case (col)
503  case (1)
504  if (this%iauxmultcol > 0) then
505  bndval = this%precipitation(row) * this%auxvar(this%iauxmultcol, row)
506  else
507  bndval = this%precipitation(row)
508  end if
509  case default
510  errmsg = 'Programming error. PCP bound value requested column '&
511  &'outside range of ncolbnd (1).'
512  call store_error(errmsg)
513  call store_error_filename(this%input_fname)
514  end select
515  end function pcp_bound_value
516 
517  function reach_length_pointer(this) result(ptr)
518  ! dummy
519  class(swfpcptype) :: this !< this instance
520  ! return
521  real(dp), dimension(:), pointer :: ptr
522  ! local
523  class(disbasetype), pointer :: dis
524 
525  ptr => null()
526  dis => this%dis
527  select type (dis)
528  type is (disv1dtype)
529  ptr => dis%length
530  end select
531 
532  end function reach_length_pointer
533 
534 end module swfpcpmodule
535 
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains the extended boundary package.
This module contains the base boundary package.
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 lenpackagename
maximum length of the package name
Definition: Constants.f90:23
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 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:83
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
This module contains the derived type ObsType.
Definition: Obs.f90:127
subroutine, public defaultobsidprocessor(obsrv, dis, inunitobs, iout)
@ brief Process IDstring provided for each observation
Definition: Obs.f90:246
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
This module contains the precipitation (PCP) package methods.
Definition: swf-pcp.f90:6
subroutine pcp_source_options(this)
Source options specific to PCPType.
Definition: swf-pcp.f90:159
real(dp) function, dimension(:), pointer reach_length_pointer(this)
Definition: swf-pcp.f90:518
subroutine pcp_allocate_arrays(this, nodelist, auxvar)
Allocate package arrays.
Definition: swf-pcp.f90:138
subroutine pcp_rp(this)
Read and Prepare.
Definition: swf-pcp.f90:250
subroutine log_pcp_options(this, found_readasarrays)
Log options specific to SwfPcpType.
Definition: swf-pcp.f90:181
subroutine pcp_fc(this, rhs, ia, idxglo, matrix_sln)
Copy rhs and hcof into solution rhs and amat.
Definition: swf-pcp.f90:371
character(len=lenftype) ftype
Definition: swf-pcp.f90:32
real(dp) function pcp_bound_value(this, col, row)
Return requested boundary value.
Definition: swf-pcp.f90:493
subroutine pcp_da(this)
Deallocate memory.
Definition: swf-pcp.f90:393
logical function pcp_obs_supported(this)
Overrides BndTypebnd_obs_supported()
Definition: swf-pcp.f90:468
subroutine default_nodelist(this)
Assign default nodelist when READASARRAYS is specified.
Definition: swf-pcp.f90:443
subroutine pcp_allocate_scalars(this)
Allocate scalar members.
Definition: swf-pcp.f90:122
subroutine pcp_read_initial_attr(this)
Part of allocate and read.
Definition: swf-pcp.f90:237
subroutine pcp_define_listlabel(this)
Define the list heading that is written to iout when PRINT_INPUT option is used.
Definition: swf-pcp.f90:417
subroutine pcp_df_obs(this)
Implements bnd_df_obs.
Definition: swf-pcp.f90:480
subroutine pcp_source_dimensions(this)
Source the dimensions for this package.
Definition: swf-pcp.f90:205
subroutine, public pcp_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, mempath, dis, dfw, cxs)
Create a Precipitation Package.
Definition: swf-pcp.f90:73
subroutine pcp_ck(this)
Ensure precipitation is positive.
Definition: swf-pcp.f90:269
character(len=lenpackagename) text
Definition: swf-pcp.f90:33
subroutine pcp_cf(this)
Formulate the HCOF and RHS terms.
Definition: swf-pcp.f90:300
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:23
@ brief BndType
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23