MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
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
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
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
67contains
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
534end module swfpcpmodule
535
This module contains block parser methods.
This module contains the extended boundary package.
subroutine default_nodelist(this)
Assign default nodelist when READASARRAYS is specified.
real(dp) function bound_value(this, col, row)
@ brief Return a bound value
This module contains the base boundary package.
logical(lgp) function bnd_obs_supported(this)
Determine if observations are supported.
subroutine bnd_rp(this)
@ brief Allocate and read method for package
subroutine bnd_da(this)
@ brief Deallocate package memory
subroutine bnd_fc(this, rhs, ia, idxglo, matrix_sln)
@ brief Copy hcof and rhs terms into solution.
subroutine bnd_ck(this)
@ brief Check boundary package period data
subroutine bnd_df_obs(this)
Define the observation types available in the package.
subroutine bnd_cf(this)
@ brief Formulate the package hcof and rhs terms.
subroutine define_listlabel(this)
@ brief Define the list label for the 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
@ dis
DIS6 discretization.
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
subroutine source_dimensions(this)
Copy dimensions from IDM into package.
Definition Disv1d.f90:341
subroutine allocate_arrays(this)
Definition Disv1d.f90:796
subroutine source_options(this)
Copy options from IDM into package.
Definition Disv1d.f90:272
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
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:204
This module contains simulation variables.
character(len=maxcharlen) errmsg
error message string
integer(i4b) iout
file unit number for simulation output
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 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:26
This class is used to store a single deferred-length character string. It was designed to work in an ...