MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
tsp-ssm.f90
Go to the documentation of this file.
1!> @brief This module contains the TspSsm Module
2!!
3!! This module contains the code for handling sources and sinks
4!! associated with groundwater flow model stress packages.
5!!
6!! todo: need observations for SSM terms
7!<
9
10 use kindmodule, only: dp, i4b, lgp
15 use simvariablesmodule, only: errmsg
17 use basedismodule, only: disbasetype
18 use tspfmimodule, only: tspfmitype
21 use tspspcmodule, only: tspspctype
23
24 implicit none
25 public :: tspssmtype
26 public :: ssm_cr
27
28 character(len=LENFTYPE) :: ftype = 'SSM'
29 character(len=LENPACKAGENAME) :: text = ' SOURCE-SINK MIX'
30
31 !> @brief Derived type for the SSM Package
32 !!
33 !! This derived type corresponds to the SSM Package, which adds
34 !! the effects of groundwater sources and sinks to the solute transport
35 !! equation.
36 !<
38
39 integer(I4B), pointer :: nbound !< total number of flow boundaries in this time step
40 integer(I4B), dimension(:), pointer, contiguous :: isrctype => null() !< source type 0 is unspecified, 1 is aux, 2 is auxmixed, 3 is ssmi, 4 is ssmimixed
41 integer(I4B), dimension(:), pointer, contiguous :: iauxpak => null() !< aux col for concentration/temperature
42 integer(I4B), dimension(:), pointer, contiguous :: ibound => null() !< pointer to model ibound
43 real(dp), dimension(:), pointer, contiguous :: cnew => null() !< pointer to gwt%x
44 type(tspfmitype), pointer :: fmi => null() !< pointer to fmi object
45 type(tabletype), pointer :: outputtab => null() !< output table object
46 type(tspspctype), dimension(:), pointer :: ssmivec => null() !< array of stress package concentration or temperature objects
47 real(dp), pointer :: eqnsclfac => null() !< governing equation scale factor; =1. for solute; =rhow*cpw for energy
48 character(len=LENVARNAME) :: depvartype = ''
49
50 contains
51
52 procedure :: ssm_df
53 procedure :: ssm_ar
54 procedure :: ssm_rp
55 procedure :: ssm_ad
56 procedure :: ssm_fc
57 procedure :: ssm_cq
58 procedure :: ssm_bd
59 procedure :: ssm_ot_flow
60 procedure :: ssm_da
61 procedure :: allocate_scalars
62 procedure, private :: ssm_term
63 procedure, private :: allocate_arrays
64 procedure, private :: source_options
65 procedure, private :: source_sources
66 procedure, private :: source_fileinput
67 procedure, private :: pak_setup_outputtab
68 procedure, private :: set_iauxpak
69 procedure, private :: set_ssmivec
70 procedure, private :: get_ssm_conc
71
72 end type tspssmtype
73
74contains
75
76 !> @ brief Create a new SSM package
77 !!
78 !! Create a new SSM package by defining names, allocating scalars
79 !<
80 subroutine ssm_cr(ssmobj, name_model, input_mempath, inunit, iout, fmi, &
81 eqnsclfac, depvartype)
82 ! -- dummy
83 type(tspssmtype), pointer :: ssmobj !< TspSsmType object
84 character(len=*), intent(in) :: name_model !< name of the model
85 character(len=*), intent(in) :: input_mempath !< input mempath
86 integer(I4B), intent(in) :: inunit !< fortran unit for input
87 integer(I4B), intent(in) :: iout !< fortran unit for output
88 type(tspfmitype), intent(in), target :: fmi !< Transport FMI package
89 real(dp), intent(in), pointer :: eqnsclfac !< governing equation scale factor
90 character(len=LENVARNAME), intent(in) :: depvartype !< dependent variable type ('concentration' or 'temperature')
91 !
92 ! -- Create the object
93 allocate (ssmobj)
94 !
95 ! -- create name and memory path
96 call ssmobj%set_names(1, name_model, 'SSM', 'SSM', input_mempath)
97 !
98 ! -- Allocate scalars
99 call ssmobj%allocate_scalars()
100 !
101 ! -- Set variables
102 ssmobj%inunit = inunit
103 ssmobj%iout = iout
104 ssmobj%fmi => fmi
105 ssmobj%eqnsclfac => eqnsclfac
106 !
107 ! -- Store pointer to labels associated with the current model so that the
108 ! package has access to the corresponding dependent variable type
109 ssmobj%depvartype = depvartype
110 end subroutine ssm_cr
111
112 !> @ brief Define SSM Package
113 !!
114 !! This routine is called from gwt_df(), but does not do anything because
115 !! df is typically used to set up dimensions. For the ssm package, the
116 !! total number of ssm entries is defined by the flow model.
117 !<
118 subroutine ssm_df(this)
119 ! -- modules
121 ! -- dummy
122 class(tspssmtype) :: this !< TspSsmType object
123 end subroutine ssm_df
124
125 !> @ brief Allocate and read SSM Package
126 !!
127 !! This routine is called from gwt_ar(). It allocates arrays, reads
128 !! options and data, and sets up the output table.
129 !<
130 subroutine ssm_ar(this, dis, ibound, cnew)
131 ! -- modules
133 ! -- dummy
134 class(tspssmtype) :: this !< TspSsmType object
135 class(disbasetype), pointer, intent(in) :: dis !< discretization package
136 integer(I4B), dimension(:), pointer, contiguous :: ibound !< GWT model ibound
137 real(DP), dimension(:), pointer, contiguous :: cnew !< GWT model dependent variable
138 ! -- formats
139 character(len=*), parameter :: fmtssm = &
140 "(1x,/1x,'SSM -- SOURCE-SINK MIXING PACKAGE, VERSION 1, 8/25/2017', &
141 &' INPUT READ FROM MEMPATH: ', A, //)"
142 !
143 ! -- print a message identifying the storage package.
144 write (this%iout, fmtssm) this%input_mempath
145 !
146 ! -- store pointers to arguments that were passed in
147 this%dis => dis
148 this%ibound => ibound
149 this%cnew => cnew
150 !
151 ! -- Check to make sure that there are flow packages
152 if (this%fmi%nflowpack == 0) then
153 write (errmsg, '(a)') 'SSM package does not detect any boundary flows &
154 &that require SSM terms. Activate GWF-GWT (or &
155 &GWF-GWE, as appropriate) exchange or activate &
156 &FMI package and provide a budget file that &
157 &contains boundary flows. If no boundary flows &
158 &are present in corresponding GWF model then this &
159 &SSM package should be removed.'
160 call store_error(errmsg)
161 call store_error_filename(this%input_fname)
162 end if
163 !
164 ! -- Allocate arrays
165 call this%allocate_arrays()
166 !
167 ! -- read ssm options
168 call this%source_options()
169 !
170 ! -- read data blocks
171 call this%source_sources()
172 call this%source_fileinput()
173 !
174 ! -- setup the output table
175 call this%pak_setup_outputtab()
176 end subroutine ssm_ar
177
178 !> @ brief Read and prepare this SSM Package
179 !!
180 !! This routine is called from gwt_rp(). It is called at the beginning of
181 !! each stress period. If any SPC input files are used to provide source
182 !! and sink concentrations (or temperatures), then period blocks for the
183 !! current stress period are read.
184 !<
185 subroutine ssm_rp(this)
186 ! -- dummy
187 class(tspssmtype) :: this !< TspSsmType object
188 ! -- local
189 integer(I4B) :: ip
190 type(tspspctype), pointer :: ssmiptr
191 ! -- formats
192 !
193 ! -- Call the rp method on any ssm input files
194 do ip = 1, this%fmi%nflowpack
195 if (this%fmi%iatp(ip) /= 0) cycle
196 if (this%isrctype(ip) == 3 .or. this%isrctype(ip) == 4) then
197 ssmiptr => this%ssmivec(ip)
198 call ssmiptr%spc_rp()
199 end if
200 end do
201 end subroutine ssm_rp
202
203 !> @ brief Advance the SSM Package
204 !!
205 !! This routine is called from gwt_ad(). It is called at the beginning of
206 !! each time step. The total number of flow boundaries is counted and stored
207 !! in this%nbound. Also, if any SPC input files are used to provide source
208 !! and sink concentrations (or temperatures) and time series are referenced
209 !! in those files, then ssm concenrations must be interpolated for the time
210 !! step.
211 !<
212 subroutine ssm_ad(this)
213 ! -- dummy
214 class(tspssmtype) :: this !< TspSsmType object
215 ! -- local
216 integer(I4B) :: ip
217 type(tspspctype), pointer :: ssmiptr
218 integer(I4B) :: i
219 integer(I4B) :: node
220 !
221 ! -- Calculate total number of existing flow boundaries. It is possible
222 ! that a node may equal zero. In this case, the bound should be
223 ! skipped and not written to ssm output.
224 this%nbound = 0
225 do ip = 1, this%fmi%nflowpack
226 if (this%fmi%iatp(ip) /= 0) cycle
227 do i = 1, this%fmi%gwfpackages(ip)%nbound
228 node = this%fmi%gwfpackages(ip)%nodelist(i)
229 if (node > 0) then
230 this%nbound = this%nbound + 1
231 end if
232 end do
233 end do
234 !
235 ! -- Call the ad method on any ssm input files so that values for
236 ! time-series are interpolated
237 do ip = 1, this%fmi%nflowpack
238 if (this%fmi%iatp(ip) /= 0) cycle
239 if (this%isrctype(ip) == 3 .or. this%isrctype(ip) == 4) then
240 ssmiptr => this%ssmivec(ip)
241 call ssmiptr%spc_ad(this%fmi%gwfpackages(ip)%nbound, &
242 this%fmi%gwfpackages(ip)%budtxt)
243 end if
244 end do
245 end subroutine ssm_ad
246
247 !> @ brief Calculate the SSM mass flow rate and hcof and rhs values
248 !!
249 !! This is the primary SSM routine that calculates the matrix coefficient
250 !! and right-hand-side value for any package and package entry. It returns
251 !! several different optional variables that are used throughout this
252 !! package to update matrix terms, budget calculations, and output tables.
253 !<
254 subroutine ssm_term(this, ipackage, ientry, rrate, rhsval, hcofval, &
255 cssm, qssm)
256 ! -- dummy
257 class(tspssmtype) :: this !< TspSsmType
258 integer(I4B), intent(in) :: ipackage !< package number
259 integer(I4B), intent(in) :: ientry !< bound number
260 real(DP), intent(out), optional :: rrate !< calculated mass flow rate
261 real(DP), intent(out), optional :: rhsval !< calculated rhs value
262 real(DP), intent(out), optional :: hcofval !< calculated hcof value
263 real(DP), intent(out), optional :: cssm !< calculated source concentration/temperature depending on flow direction
264 real(DP), intent(out), optional :: qssm !< water flow rate into model cell from boundary package
265 ! -- local
266 logical(LGP) :: lauxmixed
267 integer(I4B) :: n
268 integer(I4B) :: nbound_flow
269 real(DP) :: qbnd
270 real(DP) :: ctmp
271 real(DP) :: omega
272 real(DP) :: hcoftmp
273 real(DP) :: rhstmp
274 !
275 ! -- retrieve node number, qbnd and iauxpos
276 hcoftmp = dzero
277 rhstmp = dzero
278 ctmp = dzero
279 qbnd = dzero
280 nbound_flow = this%fmi%gwfpackages(ipackage)%nbound
281 n = this%fmi%gwfpackages(ipackage)%nodelist(ientry)
282 !
283 ! -- If cell is active (ibound > 0) then calculate values
284 if (this%ibound(n) > 0) then
285 !
286 ! -- retrieve qbnd and iauxpos
287 qbnd = this%fmi%gwfpackages(ipackage)%get_flow(ientry)
288 call this%get_ssm_conc(ipackage, ientry, nbound_flow, ctmp, lauxmixed)
289 !
290 ! -- assign values for hcoftmp, rhstmp, and ctmp for subsequent assignment
291 ! of hcof, rhs, and rate
292 if (.not. lauxmixed) then
293 !
294 ! -- If qbnd is positive, then concentration (or temperature) represents
295 ! the inflow concentration (or temperature). If qbnd is negative,
296 ! then the outflow concentration (or temperature) is set equal to the
297 ! simulated cell's concentration (or temperature).
298 if (qbnd >= dzero) then
299 omega = dzero ! rhs
300 else
301 ctmp = this%cnew(n)
302 omega = done ! lhs
303 if (ctmp < dzero) then
304 omega = dzero ! concentration/temperature is negative, so set mass flux to zero
305 end if
306 end if
307 else
308 !
309 ! -- lauxmixed value indicates that this is a mixed sink type where
310 ! the concentration (or temperature) value represents the injected
311 ! concentration (or temperature) if qbnd is positive. If qbnd is
312 ! negative, then the withdrawn water is equal to the minimum of the
313 ! aux concentration (or temperature) and the cell concentration
314 ! (or temperature).
315 if (qbnd >= dzero) then
316 omega = dzero ! rhs (ctmp is aux value)
317 else
318 if (ctmp < this%cnew(n)) then
319 omega = dzero ! rhs (ctmp is aux value)
320 else
321 omega = done ! lhs (ctmp is cell concentration)
322 ctmp = this%cnew(n)
323 end if
324 end if
325 end if
326 !
327 ! -- Add terms based on qbnd sign
328 if (qbnd <= dzero) then
329 hcoftmp = qbnd * omega * this%eqnsclfac
330 else
331 rhstmp = -qbnd * ctmp * (done - omega) * this%eqnsclfac
332 end if
333 !
334 ! -- end of active ibound
335 end if
336 !
337 ! -- set requested values
338 if (present(hcofval)) hcofval = hcoftmp
339 if (present(rhsval)) rhsval = rhstmp
340 if (present(rrate)) rrate = hcoftmp * ctmp - rhstmp
341 if (present(cssm)) cssm = ctmp
342 if (present(qssm)) qssm = qbnd
343 end subroutine ssm_term
344
345 !> @ brief Provide bound concentration (or temperature) and mixed flag
346 !!
347 !! SSM concentrations and temperatures can be provided in auxiliary variables
348 !! or through separate SPC files. If not provided, the default
349 !! concentration (or temperature) is zero. This single routine provides
350 !! the SSM bound concentration (or temperature) based on these different
351 !! approaches. The mixed flag indicates whether or not the boundary as a
352 !! mixed type.
353 !<
354 subroutine get_ssm_conc(this, ipackage, ientry, nbound_flow, conc, &
355 lauxmixed)
356 ! -- dummy
357 class(tspssmtype) :: this !< TspSsmType
358 integer(I4B), intent(in) :: ipackage !< package number
359 integer(I4B), intent(in) :: ientry !< bound number
360 integer(I4B), intent(in) :: nbound_flow !< size of flow package bound list
361 real(DP), intent(out) :: conc !< user-specified concentration/temperature for this bound
362 logical(LGP), intent(out) :: lauxmixed !< user-specified flag for marking this as a mixed boundary
363 ! -- local
364 integer(I4B) :: isrctype
365 integer(I4B) :: iauxpos
366 !
367 conc = dzero
368 lauxmixed = .false.
369 isrctype = this%isrctype(ipackage)
370 !
371 select case (isrctype)
372 case (1, 2)
373 iauxpos = this%iauxpak(ipackage)
374 conc = this%fmi%gwfpackages(ipackage)%auxvar(iauxpos, ientry)
375 if (isrctype == 2) lauxmixed = .true.
376 case (3, 4)
377 conc = this%ssmivec(ipackage)%get_value(ientry, nbound_flow)
378 if (isrctype == 4) lauxmixed = .true.
379 end select
380 end subroutine get_ssm_conc
381
382 !> @ brief Fill coefficients
383 !!
384 !! This routine adds the effects of the SSM to the matrix equations by
385 !! updating the a matrix and right-hand side vector.
386 !<
387 subroutine ssm_fc(this, matrix_sln, idxglo, rhs)
388 ! -- dummy
389 class(tspssmtype) :: this
390 class(matrixbasetype), pointer :: matrix_sln
391 integer(I4B), intent(in), dimension(:) :: idxglo
392 real(DP), intent(inout), dimension(:) :: rhs
393 ! -- local
394 integer(I4B) :: ip
395 integer(I4B) :: i
396 integer(I4B) :: n
397 integer(I4B) :: idiag
398 integer(I4B) :: nflowpack
399 integer(I4B) :: nbound
400 real(DP) :: hcofval
401 real(DP) :: rhsval
402 !
403 ! -- do for each flow package
404 nflowpack = this%fmi%nflowpack
405 do ip = 1, nflowpack
406 if (this%fmi%iatp(ip) /= 0) cycle
407 !
408 ! -- do for each entry in package (ip)
409 nbound = this%fmi%gwfpackages(ip)%nbound
410 do i = 1, nbound
411 n = this%fmi%gwfpackages(ip)%nodelist(i)
412 if (n <= 0) cycle
413 call this%ssm_term(ip, i, rhsval=rhsval, hcofval=hcofval)
414 idiag = idxglo(this%dis%con%ia(n))
415 call matrix_sln%add_value_pos(idiag, hcofval)
416 rhs(n) = rhs(n) + rhsval
417 !
418 end do
419 !
420 end do
421 end subroutine ssm_fc
422
423 !> @ brief Calculate flow
424 !!
425 !! Calculate the resulting mass flow between the boundary and the connected
426 !! GWT/GWE model cell. Update the diagonal position of the flowja array so
427 !! that it ultimately contains the solute balance residual.
428 !<
429 subroutine ssm_cq(this, flowja)
430 ! -- dummy
431 class(tspssmtype) :: this !< TspSsmType object
432 real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow across each face in the model grid
433 ! -- local
434 integer(I4B) :: ip
435 integer(I4B) :: i
436 integer(I4B) :: n
437 integer(I4B) :: idiag
438 real(DP) :: rate
439 !
440 ! -- do for each flow package
441 do ip = 1, this%fmi%nflowpack
442 !
443 ! -- cycle if package is being managed as an advanced package
444 if (this%fmi%iatp(ip) /= 0) cycle
445 !
446 ! -- do for each boundary
447 do i = 1, this%fmi%gwfpackages(ip)%nbound
448 n = this%fmi%gwfpackages(ip)%nodelist(i)
449 if (n <= 0) cycle
450 call this%ssm_term(ip, i, rrate=rate)
451 idiag = this%dis%con%ia(n)
452 flowja(idiag) = flowja(idiag) + rate
453 !
454 end do
455 !
456 end do
457 end subroutine ssm_cq
458
459 !> @ brief Calculate the global SSM budget terms
460 !!
461 !! Calculate the global SSM budget terms using separate in and out entries
462 !! for each flow package.
463 !<
464 subroutine ssm_bd(this, isuppress_output, model_budget)
465 ! -- modules
466 use tdismodule, only: delt
467 use budgetmodule, only: budgettype
468 ! -- dummy
469 class(tspssmtype) :: this !< TspSsmType object
470 integer(I4B), intent(in) :: isuppress_output !< flag to suppress output
471 type(budgettype), intent(inout) :: model_budget !< budget object for the GWT model
472 ! -- local
473 character(len=LENBUDROWLABEL) :: rowlabel
474 integer(I4B) :: ip
475 integer(I4B) :: i
476 integer(I4B) :: n
477 real(DP) :: rate
478 real(DP) :: rin
479 real(DP) :: rout
480 !
481 ! -- do for each flow package, unless it is being handled by an advanced
482 ! transport package
483 do ip = 1, this%fmi%nflowpack
484 !
485 ! -- cycle if package is being managed as an advanced package
486 if (this%fmi%iatp(ip) /= 0) cycle
487 !
488 ! -- Initialize the rate accumulators
489 rin = dzero
490 rout = dzero
491 !
492 ! -- do for each boundary
493 do i = 1, this%fmi%gwfpackages(ip)%nbound
494 n = this%fmi%gwfpackages(ip)%nodelist(i)
495 if (n <= 0) cycle
496 call this%ssm_term(ip, i, rrate=rate)
497 if (rate < dzero) then
498 rout = rout - rate
499 else
500 rin = rin + rate
501 end if
502 !
503 end do
504 !
505 rowlabel = 'SSM_'//adjustl(trim(this%fmi%flowpacknamearray(ip)))
506 call model_budget%addentry(rin, rout, delt, &
507 this%fmi%gwfpackages(ip)%budtxt, &
508 isuppress_output, rowlabel=rowlabel)
509 end do
510 end subroutine ssm_bd
511
512 !> @ brief Output flows
513 !!
514 !! Based on user-specified controls, print SSM mass flow rates to the GWT
515 !! listing file and/or write the SSM mass flow rates to the GWT binary
516 !! budget file.
517 !<
518 subroutine ssm_ot_flow(this, icbcfl, ibudfl, icbcun)
519 ! -- modules
520 use tdismodule, only: kstp, kper
522 ! -- dummy
523 class(tspssmtype) :: this !< TspSsmType object
524 integer(I4B), intent(in) :: icbcfl !< flag for writing binary budget terms
525 integer(I4B), intent(in) :: ibudfl !< flag for printing budget terms to list file
526 integer(I4B), intent(in) :: icbcun !< fortran unit number for binary budget file
527 ! -- local
528 character(len=LINELENGTH) :: title
529 integer(I4B) :: node, nodeu
530 character(len=20) :: nodestr
531 integer(I4B) :: maxrows
532 integer(I4B) :: ip
533 integer(I4B) :: i, n2, ibinun
534 real(DP) :: rrate
535 real(DP) :: qssm
536 real(DP) :: cssm
537 integer(I4B) :: naux
538 real(DP), dimension(0) :: auxrow
539 character(len=LENAUXNAME), dimension(0) :: auxname
540 ! -- for observations
541 character(len=LENBOUNDNAME) :: bname
542 ! -- formats
543 character(len=*), parameter :: fmttkk = &
544 &"(1X,/1X,A,' PERIOD ',I0,' STEP ',I0)"
545 !
546 ! -- initialize
547 naux = 0
548 maxrows = 0
549 if (ibudfl /= 0 .and. this%iprflow /= 0) then
550 call this%outputtab%set_kstpkper(kstp, kper)
551 do ip = 1, this%fmi%nflowpack
552 if (this%fmi%iatp(ip) /= 0) cycle
553 !
554 ! -- do for each boundary
555 do i = 1, this%fmi%gwfpackages(ip)%nbound
556 node = this%fmi%gwfpackages(ip)%nodelist(i)
557 if (node > 0) then
558 maxrows = maxrows + 1
559 end if
560 end do
561 end do
562 if (maxrows > 0) then
563 call this%outputtab%set_maxbound(maxrows)
564 end if
565 title = 'SSM PACKAGE ('//trim(this%packName)// &
566 ') FLOW RATES'
567 call this%outputtab%set_title(title)
568 end if
569 !
570 ! -- Set unit number for binary output
571 if (this%ipakcb < 0) then
572 ibinun = icbcun
573 else if (this%ipakcb == 0) then
574 ibinun = 0
575 else
576 ibinun = this%ipakcb
577 end if
578 if (icbcfl == 0) ibinun = 0
579 !
580 ! -- If cell-by-cell flows will be saved as a list, write header.
581 if (ibinun /= 0) then
582 call this%dis%record_srcdst_list_header(text, this%name_model, &
583 this%name_model, this%name_model, &
584 this%packName, naux, auxname, &
585 ibinun, this%nbound, this%iout)
586 end if
587 !
588 ! -- If no boundaries, skip flow calculations.
589 if (this%nbound > 0) then
590 !
591 ! -- Loop through each boundary calculating flow.
592 do ip = 1, this%fmi%nflowpack
593 if (this%fmi%iatp(ip) /= 0) cycle
594 !
595 ! -- do for each boundary
596 do i = 1, this%fmi%gwfpackages(ip)%nbound
597 !
598 ! -- Calculate rate for this entry
599 node = this%fmi%gwfpackages(ip)%nodelist(i)
600 if (node <= 0) cycle
601 call this%ssm_term(ip, i, rrate=rrate, qssm=qssm, cssm=cssm)
602 !
603 ! -- Print the individual rates if the budget is being printed
604 ! and PRINT_FLOWS was specified (this%iprflow<0)
605 if (ibudfl /= 0) then
606 if (this%iprflow /= 0) then
607 !
608 ! -- set nodestr and write outputtab table
609 nodeu = this%dis%get_nodeuser(node)
610 call this%dis%nodeu_to_string(nodeu, nodestr)
611 bname = this%fmi%gwfpackages(ip)%name
612 call this%outputtab%add_term(i)
613 call this%outputtab%add_term(trim(adjustl(nodestr)))
614 call this%outputtab%add_term(qssm)
615 call this%outputtab%add_term(cssm)
616 call this%outputtab%add_term(rrate)
617 call this%outputtab%add_term(bname)
618 end if
619 end if
620 !
621 ! -- If saving cell-by-cell flows in list, write flow
622 if (ibinun /= 0) then
623 n2 = i
624 call this%dis%record_mf6_list_entry(ibinun, node, n2, rrate, &
625 naux, auxrow, &
626 olconv2=.false.)
627 end if
628 !
629 end do
630 !
631 end do
632 end if
633 if (ibudfl /= 0) then
634 if (this%iprflow /= 0) then
635 write (this%iout, '(1x)')
636 end if
637 end if
638 end subroutine ssm_ot_flow
639
640 !> @ brief Deallocate
641 !!
642 !! Deallocate the memory associated with this derived type
643 !<
644 subroutine ssm_da(this)
645 ! -- modules
647 ! -- dummy
648 class(tspssmtype) :: this !< TspSsmType object
649 ! -- local
650 integer(I4B) :: ip
651 type(tspspctype), pointer :: ssmiptr
652 !
653 ! -- Deallocate the ssmi objects if package was active
654 if (this%inunit > 0) then
655 do ip = 1, size(this%ssmivec)
656 if (this%isrctype(ip) == 3 .or. this%isrctype(ip) == 4) then
657 ssmiptr => this%ssmivec(ip)
658 call ssmiptr%spc_da()
659 end if
660 end do
661 deallocate (this%ssmivec)
662 end if
663 !
664 ! -- Deallocate arrays if package was active
665 if (this%inunit > 0) then
666 call mem_deallocate(this%iauxpak)
667 call mem_deallocate(this%isrctype)
668 this%ibound => null()
669 this%fmi => null()
670 end if
671 !
672 ! -- output table object
673 if (associated(this%outputtab)) then
674 call this%outputtab%table_da()
675 deallocate (this%outputtab)
676 nullify (this%outputtab)
677 end if
678 !
679 ! -- Scalars
680 call mem_deallocate(this%nbound)
681 !
682 ! -- deallocate parent
683 call this%NumericalPackageType%da()
684 end subroutine ssm_da
685
686 !> @ brief Allocate scalars
687 !!
688 !! Allocate scalar variables for this derived type
689 !<
690 subroutine allocate_scalars(this)
691 ! -- modules
693 ! -- dummy
694 class(tspssmtype) :: this !< TspSsmType object
695 !
696 ! -- allocate scalars in NumericalPackageType
697 call this%NumericalPackageType%allocate_scalars()
698 !
699 ! -- Allocate
700 call mem_allocate(this%nbound, 'NBOUND', this%memoryPath)
701 !
702 ! -- Initialize
703 this%nbound = 0
704 end subroutine allocate_scalars
705
706 !> @ brief Allocate arrays
707 !!
708 !! Allocate array variables for this derived type
709 !<
710 subroutine allocate_arrays(this)
711 ! -- modules
713 ! -- dummy
714 class(tspssmtype) :: this !< TspSsmType object
715 ! -- local
716 integer(I4B) :: nflowpack
717 integer(I4B) :: i
718 !
719 ! -- Allocate
720 nflowpack = this%fmi%nflowpack
721 call mem_allocate(this%iauxpak, nflowpack, 'IAUXPAK', this%memoryPath)
722 call mem_allocate(this%isrctype, nflowpack, 'ISRCTYPE', this%memoryPath)
723 !
724 ! -- Initialize
725 do i = 1, nflowpack
726 this%iauxpak(i) = 0
727 this%isrctype(i) = 0
728 end do
729 !
730 ! -- Allocate the ssmivec array
731 allocate (this%ssmivec(nflowpack))
732 end subroutine allocate_arrays
733
734 !> @brief Source input options
735 !<
736 subroutine source_options(this)
737 ! -- modules
738 !use KindModule, only: LGP
741 ! -- dummy
742 class(tspssmtype) :: this
743 ! -- locals
744 type(gwtssmparamfoundtype) :: found
745 ! -- formats
746 character(len=*), parameter :: fmtiprflow = &
747 "(4x,'SSM FLOW INFORMATION WILL BE PRINTED TO LISTING FILE &
748 &WHENEVER ICBCFL IS NOT ZERO.')"
749 character(len=*), parameter :: fmtisvflow = &
750 "(4x,'CELL-BY-CELL FLOW INFORMATION WILL BE SAVED TO BINARY FILE &
751 &WHENEVER ICBCFL IS NOT ZERO.')"
752 !
753 ! -- update defaults with idm sourced values
754 call mem_set_value(this%iprflow, 'PRINT_FLOWS', this%input_mempath, &
755 found%print_flows)
756 call mem_set_value(this%ipakcb, 'SAVE_FLOWS', this%input_mempath, &
757 found%save_flows)
758
759 if (found%save_flows) this%ipakcb = -1
760
761 ! log options
762 write (this%iout, '(1x,a)') 'PROCESSING SSM OPTIONS'
763 if (found%print_flows) write (this%iout, fmtiprflow)
764 if (found%save_flows) write (this%iout, fmtisvflow)
765 write (this%iout, '(1x,a)') 'END OF SSM OPTIONS'
766 end subroutine source_options
767
768 !> @brief Source sources input block
769 !<
770 subroutine source_sources(this)
771 ! -- modules
772 !use KindModule, only: LGP
776 ! -- dummy
777 class(tspssmtype) :: this
778 ! -- locals
779 type(characterstringtype), dimension(:), pointer, &
780 contiguous :: pnames, srctypes, auxnames
781 character(len=LINELENGTH) :: pname, srctype, auxname
782 integer(I4B) :: n, ip
783 logical(LGP) :: found
784 ! -- formats
785
786 ! set pointers to input context
787 call mem_setptr(pnames, 'PNAME_SOURCES', this%input_mempath)
788 call mem_setptr(srctypes, 'SRCTYPE', this%input_mempath)
789 call mem_setptr(auxnames, 'AUXNAME', this%input_mempath)
790
791 write (this%iout, '(/1x,a)') 'PROCESSING SSM SOURCES'
792 do n = 1, size(pnames)
793
794 pname = pnames(n)
795 srctype = srctypes(n)
796 auxname = auxnames(n)
797 found = .false.
798
799 do ip = 1, this%fmi%nflowpack
800 if (trim(adjustl(this%fmi%gwfpackages(ip)%name)) == pname) then
801 found = .true.
802 exit
803 end if
804 end do
805
806 if (.not. found) then
807 write (errmsg, '(a,a)') 'Flow package cannot be found: ', &
808 trim(pname)
809 call store_error(errmsg)
810 cycle
811 end if
812
813 ! -- Ensure package was not specified more than once in SOURCES block
814 if (this%isrctype(ip) /= 0) then
815 write (errmsg, '(a, a)') &
816 'A package cannot be specified more than once in the SSM SOURCES &
817 &block. The following package was specified more than once: ', &
818 trim(pname)
819 call store_error(errmsg)
820 cycle
821 end if
822
823 if (srctype == 'AUX') then
824 this%isrctype(ip) = 1
825 write (this%iout, '(4x,a)') 'AUX SOURCE DETECTED.'
826 else if (srctype == 'AUXMIXED') then
827 this%isrctype(ip) = 2
828 write (this%iout, '(4x,a)') 'AUXMIXED SOURCE DETECTED.'
829 else
830 write (errmsg, '(a, a)') &
831 'SRCTYPE must be AUX or AUXMIXED. Found: ', trim(srctype)
832 call store_error(errmsg)
833 cycle
834 end if
835
836 ! -- Find and store the auxiliary column
837 call this%set_iauxpak(ip, srctype, auxname)
838 end do
839 write (this%iout, '(1x,a)') 'END PROCESSING SSM SOURCES'
840
841 ! -- terminate if errors
842 if (count_errors() > 0) then
843 call store_error_filename(this%input_fname)
844 end if
845
846 call memorystore_release('PNAME_SOURCES', this%input_mempath)
847 call memorystore_release('SRCTYPE', this%input_mempath)
848 call memorystore_release('AUXNAME', this%input_mempath)
849 end subroutine source_sources
850
851 !> @brief Source fileinput input block
852 !!
853 !! Initialize an SPC input file reader for each input entry.
854 !<
855 subroutine source_fileinput(this)
856 ! -- modules
860 ! -- dummy
861 class(tspssmtype) :: this
862 ! -- locals
863 type(characterstringtype), dimension(:), pointer, &
864 contiguous :: pnames, ftypes, iotypes, fnames, conditions, spc6_mempaths
865 character(len=LINELENGTH) :: pname, ftype, iotype, fname, condition
866 character(len=LENMEMPATH) :: spc_mempath
867 integer(I4B) :: n, ip, isize
868 logical(LGP) :: found
869 ! -- formats
870
871 call get_isize('PNAME', this%input_mempath, isize)
872 if (isize <= 0) then
873 write (this%iout, '(/1x,a)') &
874 'OPTIONAL SSM FILEINPUT BLOCK NOT FOUND OR EMPTY.'
875 return
876 end if
877
878 ! set pointers to input context
879 call mem_setptr(pnames, 'PNAME', this%input_mempath)
880 call mem_setptr(ftypes, 'SPC6', this%input_mempath)
881 call mem_setptr(iotypes, 'FILEIN', this%input_mempath)
882 call mem_setptr(fnames, 'SPC6_FILENAME', this%input_mempath)
883 call mem_setptr(conditions, 'MIXED', this%input_mempath)
884 call mem_setptr(spc6_mempaths, 'SPC6_MEMPATH', this%input_mempath)
885
886 write (this%iout, '(/1x,a)') 'PROCESSING SSM FILEINPUT'
887 do n = 1, size(pnames)
888
889 pname = pnames(n)
890 ftype = ftypes(n)
891 iotype = iotypes(n)
892 fname = fnames(n)
893 condition = conditions(n)
894 spc_mempath = spc6_mempaths(n)
895 found = .false.
896
897 do ip = 1, this%fmi%nflowpack
898 if (trim(adjustl(this%fmi%gwfpackages(ip)%name)) == pname) then
899 found = .true.
900 exit
901 end if
902 end do
903
904 if (.not. found) then
905 write (errmsg, '(a,a)') 'Flow package cannot be found: ', &
906 trim(pname)
907 call store_error(errmsg)
908 cycle
909 end if
910
911 ! -- Ensure package was not specified more than once in SOURCES block
912 if (this%isrctype(ip) /= 0) then
913 write (errmsg, '(a, a)') &
914 'A package cannot be specified more than once in the SSM SOURCES &
915 &block. The following package was specified more than once: ', &
916 trim(pname)
917 call store_error(errmsg)
918 cycle
919 end if
920
921 ! verify ftype
922 if (ftype == 'SPC6') then
923 write (this%iout, '(4x,a)') 'SPC6 SOURCE DETECTED:'
924 else
925 write (errmsg, '(a,a)') &
926 'SRCTYPE must be SPC6. Found: ', trim(ftype)
927 call store_error(errmsg)
928 cycle
929 end if
930
931 ! verify iotype
932 if (iotype /= 'FILEIN') then
933 errmsg = 'SPC6 keyword must be followed by "FILEIN" '// &
934 'then by filename and optionally by <MIXED>.'
935 call store_error(errmsg)
936 cycle
937 end if
938
939 ! -- Use set_ssmivec to initialize the ssmi object from the
940 ! input mempath
941 call this%set_ssmivec(ip, pname, spc_mempath, trim(fname))
942
943 if (condition == 'MIXED') then
944 this%isrctype(ip) = 4
945 write (this%iout, '(4x,a,a)') 'ASSIGNED MIXED SSM TYPE TO PACKAGE ', &
946 trim(pname)
947 else
948 this%isrctype(ip) = 3
949 end if
950 end do
951 write (this%iout, '(1x,a)') 'END PROCESSING SSM FILEINPUT'
952
953 ! -- terminate if errors
954 if (count_errors() > 0) then
955 call store_error_filename(this%input_fname)
956 end if
957
958 call memorystore_release('PNAME', this%input_mempath)
959 call memorystore_release('SPC6', this%input_mempath)
960 call memorystore_release('FILEIN', this%input_mempath)
961 call memorystore_release('SPC6_FILENAME', this%input_mempath)
962 call memorystore_release('MIXED', this%input_mempath)
963 call memorystore_release('SPC6_MEMPATH', this%input_mempath)
964 end subroutine source_fileinput
965
966 !> @ brief Set iauxpak array value for package ip
967 !!
968 !! The routine searches through the auxiliary names in package
969 !! ip and sets iauxpak to the column number corresponding to the
970 !! correct auxiliary column.
971 !<
972 subroutine set_iauxpak(this, ip, packname, auxname)
973 ! -- dummy
974 class(tspssmtype), intent(inout) :: this !< TspSsmType
975 integer(I4B), intent(in) :: ip !< package number
976 character(len=*), intent(in) :: packname !< name of package
977 character(len=*), intent(in) :: auxname !< name of aux
978 ! -- local
979 logical :: auxfound
980 integer(I4B) :: iaux
981 !
982 ! -- match package auxiliary
983 auxfound = .false.
984 do iaux = 1, this%fmi%gwfpackages(ip)%naux
985 if (trim(this%fmi%gwfpackages(ip)%auxname(iaux)) == &
986 trim(auxname)) then
987 auxfound = .true.
988 exit
989 end if
990 end do
991 if (.not. auxfound) then
992 write (errmsg, '(a, a)') &
993 'Auxiliary name cannot be found: ', trim(auxname)
994 call store_error(errmsg)
995 call store_error_filename(this%input_fname)
996 end if
997 !
998 ! -- set iauxpak and write message
999 this%iauxpak(ip) = iaux
1000 write (this%iout, '(4x, a, i0, a, a)') 'USING AUX COLUMN ', &
1001 iaux, ' IN PACKAGE ', trim(packname)
1002 end subroutine set_iauxpak
1003
1004 !> @brief Set ssmivec array value for package ip
1005 !!
1006 !! Initialize TspSpcType from the input mempath.
1007 !<
1008 subroutine set_ssmivec(this, ip, packname, spc_mempath, input_fname)
1009 ! -- dummy
1010 class(tspssmtype), intent(inout) :: this !< TspSsmType
1011 integer(I4B), intent(in) :: ip !< package number
1012 character(len=*), intent(in) :: packname !< name of corresponding flow package
1013 character(len=*), intent(in) :: spc_mempath !< input mempath for this SPC instance
1014 character(len=*), intent(in) :: input_fname !< SPC input file name (for error messages)
1015 ! -- local
1016 type(tspspctype), pointer :: ssmiptr
1017 !
1018 ! -- initialize the TspSpcType reader for this package
1019 ssmiptr => this%ssmivec(ip)
1020 call ssmiptr%initialize(this%dis, ip, spc_mempath, this%iout, &
1021 this%name_model, trim(packname), &
1022 this%depvartype, input_fname)
1023 end subroutine set_ssmivec
1024
1025 !> @ brief Setup the output table
1026 !!
1027 !! Setup the output table by creating the column headers.
1028 !<
1029 subroutine pak_setup_outputtab(this)
1030 ! -- dummy
1031 class(tspssmtype), intent(inout) :: this
1032 ! -- local
1033 character(len=LINELENGTH) :: title
1034 character(len=LINELENGTH) :: text
1035 integer(I4B) :: ntabcol
1036 !
1037 ! -- allocate and initialize the output table
1038 if (this%iprflow /= 0) then
1039 !
1040 ! -- dimension table
1041 ntabcol = 6
1042 !if (this%inamedbound > 0) then
1043 ! ntabcol = ntabcol + 1
1044 !end if
1045 !
1046 ! -- initialize the output table object
1047 title = 'SSM PACKAGE ('//trim(this%packName)// &
1048 ') FLOW RATES'
1049 call table_cr(this%outputtab, this%packName, title)
1050 call this%outputtab%table_df(1, ntabcol, this%iout, transient=.true.)
1051 text = 'NUMBER'
1052 call this%outputtab%initialize_column(text, 10, alignment=tabcenter)
1053 text = 'CELLID'
1054 call this%outputtab%initialize_column(text, 20, alignment=tableft)
1055 text = 'BOUND Q'
1056 call this%outputtab%initialize_column(text, 15, alignment=tabcenter)
1057 text = 'SSM CONC'
1058 call this%outputtab%initialize_column(text, 15, alignment=tabcenter)
1059 text = 'RATE'
1060 call this%outputtab%initialize_column(text, 15, alignment=tabcenter)
1061 text = 'PACKAGE NAME'
1062 call this%outputtab%initialize_column(text, 16, alignment=tabcenter)
1063 !if (this%inamedbound > 0) then
1064 ! text = 'NAME'
1065 ! call this%outputtab%initialize_column(text, 20, alignment=TABLEFT)
1066 !end if
1067 end if
1068 end subroutine pak_setup_outputtab
1069
1070end module tspssmmodule
subroutine allocate_scalars(this, name_model, input_mempath)
Allocate and initialize scalar variables.
subroutine allocate_arrays(this)
Allocate and initialize arrays.
This module contains the BudgetModule.
Definition Budget.f90:20
This module contains simulation constants.
Definition Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition Constants.f90:45
@ tabcenter
centered table column
@ tableft
left justified table column
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition Constants.f90:23
integer(i4b), parameter lenbudrowlabel
maximum length of the rowlabel string used in the budget table
Definition Constants.f90:25
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
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition Constants.f90:35
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition Constants.f90:36
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
real(dp), parameter done
real constant 1
Definition Constants.f90:76
This module defines variable data types.
Definition kind.f90:8
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
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.
character(len=maxcharlen) errmsg
error message string
integer(i4b) iout
file unit number for simulation output
subroutine, public table_cr(this, name, title)
Definition Table.f90:87
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
real(dp), pointer, public delt
length of the current time step
Definition tdis.f90:32
character(len=lenpackagename) text
Definition tsp-fmi.f90:22
This module contains the TspSpc Module.
Definition TspSpc.f90:8
character(len=lenftype) ftype
Definition TspSpc.f90:26
This module contains the TspSsm Module.
Definition tsp-ssm.f90:8
subroutine ssm_fc(this, matrix_sln, idxglo, rhs)
@ brief Fill coefficients
Definition tsp-ssm.f90:388
subroutine ssm_ot_flow(this, icbcfl, ibudfl, icbcun)
@ brief Output flows
Definition tsp-ssm.f90:519
subroutine source_sources(this)
Source sources input block.
Definition tsp-ssm.f90:771
subroutine ssm_term(this, ipackage, ientry, rrate, rhsval, hcofval, cssm, qssm)
@ brief Calculate the SSM mass flow rate and hcof and rhs values
Definition tsp-ssm.f90:256
subroutine ssm_cq(this, flowja)
@ brief Calculate flow
Definition tsp-ssm.f90:430
subroutine source_fileinput(this)
Source fileinput input block.
Definition tsp-ssm.f90:856
subroutine ssm_bd(this, isuppress_output, model_budget)
@ brief Calculate the global SSM budget terms
Definition tsp-ssm.f90:465
subroutine source_options(this)
Source input options.
Definition tsp-ssm.f90:737
subroutine pak_setup_outputtab(this)
@ brief Setup the output table
Definition tsp-ssm.f90:1030
subroutine ssm_df(this)
@ brief Define SSM Package
Definition tsp-ssm.f90:119
subroutine get_ssm_conc(this, ipackage, ientry, nbound_flow, conc, lauxmixed)
@ brief Provide bound concentration (or temperature) and mixed flag
Definition tsp-ssm.f90:356
subroutine ssm_rp(this)
@ brief Read and prepare this SSM Package
Definition tsp-ssm.f90:186
subroutine set_ssmivec(this, ip, packname, spc_mempath, input_fname)
Set ssmivec array value for package ip.
Definition tsp-ssm.f90:1009
subroutine ssm_ar(this, dis, ibound, cnew)
@ brief Allocate and read SSM Package
Definition tsp-ssm.f90:131
subroutine ssm_ad(this)
@ brief Advance the SSM Package
Definition tsp-ssm.f90:213
subroutine ssm_da(this)
@ brief Deallocate
Definition tsp-ssm.f90:645
subroutine, public ssm_cr(ssmobj, name_model, input_mempath, inunit, iout, fmi, eqnsclfac, depvartype)
@ brief Create a new SSM package
Definition tsp-ssm.f90:82
subroutine set_iauxpak(this, ip, packname, auxname)
@ brief Set iauxpak array value for package ip
Definition tsp-ssm.f90:973
Derived type for the Budget object.
Definition Budget.f90:40
This class is used to store a single deferred-length character string. It was designed to work in an ...
Data for sharing among multiple packages. Originally read in from.
Derived type for managing SPC input.
Definition TspSpc.f90:34
Derived type for the SSM Package.
Definition tsp-ssm.f90:37