MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
prt.f90
Go to the documentation of this file.
1 module prtmodule
2  use kindmodule, only: dp, i4b, lgp
3  use errorutilmodule, only: pstop
12  use dismodule, only: distype, dis_cr
13  use disvmodule, only: disvtype, disv_cr
14  use disumodule, only: disutype, disu_cr
16  use prtfmimodule, only: prtfmitype
17  use prtmipmodule, only: prtmiptype
18  use prtocmodule, only: prtoctype
19  use budgetmodule, only: budgettype
20  use listmodule, only: listtype
24  particletrackfiletype, &
34 
35  implicit none
36 
37  private
38  public :: prt_cr
39  public :: prtmodeltype
40  public :: prt_nbasepkg, prt_nmultipkg
41  public :: prt_basepkg, prt_multipkg
42 
43  integer(I4B), parameter :: nbditems = 2
44  character(len=LENBUDTXT), dimension(NBDITEMS) :: budtxt
45  data budtxt/' STORAGE', ' TERMINATION'/
46 
47  !> @brief Particle tracking (PRT) model
48  type, extends(explicitmodeltype) :: prtmodeltype
49  type(prtfmitype), pointer :: fmi => null() ! flow model interface
50  type(prtmiptype), pointer :: mip => null() ! model input package
51  type(prtoctype), pointer :: oc => null() ! output control package
52  type(budgettype), pointer :: budget => null() ! budget object
53  class(methodtype), pointer :: method => null() ! tracking method
54  type(methoddistype), pointer :: method_dis => null() ! DIS tracking method
55  type(methoddisvtype), pointer :: method_disv => null() ! DISV tracking method
56  type(particleeventdispatchertype), pointer :: events => null() ! event dispatcher
57  type(particletrackstype), pointer :: tracks ! track output manager
58  integer(I4B), pointer :: infmi => null() ! unit number FMI
59  integer(I4B), pointer :: inmip => null() ! unit number MIP
60  integer(I4B), pointer :: inmvt => null() ! unit number MVT
61  integer(I4B), pointer :: inmst => null() ! unit number MST
62  integer(I4B), pointer :: inadv => null() ! unit number ADV
63  integer(I4B), pointer :: indsp => null() ! unit number DSP
64  integer(I4B), pointer :: inssm => null() ! unit number SSM
65  integer(I4B), pointer :: inoc => null() ! unit number OC
66  integer(I4B), pointer :: nprp => null() ! number of PRP packages in the model
67  real(dp), dimension(:), pointer, contiguous :: masssto => null() !< particle mass storage in cells, new value
68  real(dp), dimension(:), pointer, contiguous :: massstoold => null() !< particle mass storage in cells, old value
69  real(dp), dimension(:), pointer, contiguous :: ratesto => null() !< particle mass storage rate in cells
70  real(dp), dimension(:), pointer, contiguous :: masstrm => null() !< particle mass terminating in cells, new value
71  real(dp), dimension(:), pointer, contiguous :: ratetrm => null() !< particle mass termination rate in cells
72  type(hashtabletype), pointer :: trm_ids => null() !< terminated particle ids
73  contains
74  ! Override BaseModelType procs
75  procedure :: model_df => prt_df
76  procedure :: model_ar => prt_ar
77  procedure :: model_rp => prt_rp
78  procedure :: model_ad => prt_ad
79  procedure :: model_cq => prt_cq
80  procedure :: model_bd => prt_bd
81  procedure :: model_ot => prt_ot
82  procedure :: model_da => prt_da
83  procedure :: model_solve => prt_solve
84 
85  ! Private utilities
86  procedure :: allocate_scalars
87  procedure :: allocate_arrays
88  procedure, private :: package_create
89  procedure, private :: ftype_check
90  procedure, private :: prt_ot_flow
91  procedure, private :: prt_ot_saveflow
92  procedure, private :: prt_ot_printflow
93  procedure, private :: prt_ot_dv
94  procedure, private :: prt_ot_bdsummary
95  procedure, private :: prt_cq_budterms
96  procedure, private :: create_packages
97  procedure, private :: create_bndpkgs
98  procedure, private :: create_exg_prp
99  procedure, private :: log_namfile_options
100 
101  end type prtmodeltype
102 
103  !> @brief PRT base package array descriptors
104  !!
105  !! PRT6 model base package types. Only listed packages are candidates
106  !! for input and these will be loaded in the order specified.
107  !<
108  integer(I4B), parameter :: prt_nbasepkg = 50
109  character(len=LENPACKAGETYPE), dimension(PRT_NBASEPKG) :: prt_basepkg
110  data prt_basepkg/'DIS6 ', 'DISV6', 'DISU6', 'IC6 ', 'MST6 ', & ! 5
111  &'ADV6 ', 'DSP6 ', 'SSM6 ', 'MIP6 ', 'CNC6 ', & ! 10
112  &'OC6 ', ' ', 'FMI6 ', ' ', 'IST6 ', & ! 15
113  &'LKT6 ', 'SFT6 ', 'MWT6 ', 'UZT6 ', 'MVT6 ', & ! 20
114  &'API6 ', ' ', ' ', ' ', ' ', & ! 25
115  25*' '/ ! 50
116 
117  !> @brief PRT multi package array descriptors
118  !!
119  !! PRT6 model multi-instance package types. Only listed packages are
120  !! candidates for input and these will be loaded in the order specified.
121  !<
122  integer(I4B), parameter :: prt_nmultipkg = 50
123  character(len=LENPACKAGETYPE), dimension(PRT_NMULTIPKG) :: prt_multipkg
124  data prt_multipkg/'PRP6 ', ' ', ' ', ' ', ' ', & ! 5
125  &45*' '/ ! 50
126 
127  ! size of supported model package arrays
128  integer(I4B), parameter :: niunit_prt = prt_nbasepkg + prt_nmultipkg
129 
130 contains
131 
132  !> @brief Create a new particle tracking model object
133  subroutine prt_cr(filename, id, modelname)
134  ! modules
135  use listsmodule, only: basemodellist
138  use compilerversion
143  ! dummy
144  character(len=*), intent(in) :: filename
145  integer(I4B), intent(in) :: id
146  character(len=*), intent(in) :: modelname
147  ! local
148  type(prtmodeltype), pointer :: this
149  class(basemodeltype), pointer :: model
150  character(len=LENMEMPATH) :: input_mempath
151  character(len=LINELENGTH) :: lst_fname
152  type(prtnamparamfoundtype) :: found
153 
154  ! Allocate a new PRT Model (this)
155  allocate (this)
156 
157  ! Set this before any allocs in the memory manager can be done
158  this%memoryPath = create_mem_path(modelname)
159 
160  ! Allocate event system and track output manager
161  allocate (this%events)
162  allocate (this%tracks)
163 
164  ! Allocate scalars and add model to basemodellist
165  call this%allocate_scalars(modelname)
166  model => this
167  call addbasemodeltolist(basemodellist, model)
168 
169  ! Assign variables
170  this%filename = filename
171  this%name = modelname
172  this%macronym = 'PRT'
173  this%id = id
174 
175  ! Set input model namfile memory path
176  input_mempath = create_mem_path(modelname, 'NAM', idm_context)
177 
178  ! Copy options from input context
179  call mem_set_value(this%iprpak, 'PRINT_INPUT', input_mempath, &
180  found%print_input)
181  call mem_set_value(this%iprflow, 'PRINT_FLOWS', input_mempath, &
182  found%print_flows)
183  call mem_set_value(this%ipakcb, 'SAVE_FLOWS', input_mempath, &
184  found%save_flows)
185 
186  ! Create the list file
187  call this%create_lstfile(lst_fname, filename, found%list, &
188  'PARTICLE TRACKING MODEL (PRT)')
189 
190  ! Activate save_flows if found
191  if (found%save_flows) then
192  this%ipakcb = -1
193  end if
194 
195  ! Create model packages
196  call this%create_packages()
197 
198  ! Create hash table for terminated particle ids
199  call hash_table_cr(this%trm_ids)
200 
201  ! Log options
202  if (this%iout > 0) then
203  call this%log_namfile_options(found)
204  end if
205 
206  end subroutine prt_cr
207 
208  !> @brief Define packages
209  !!
210  !! (1) call df routines for each package
211  !! (2) set variables and pointers
212  !<
213  subroutine prt_df(this)
214  ! modules
215  use prtprpmodule, only: prtprptype
216  ! dummy
217  class(prtmodeltype) :: this
218  ! local
219  integer(I4B) :: ip
220  class(bndtype), pointer :: packobj
221 
222  ! Define packages and utility objects
223  call this%dis%dis_df()
224  call this%fmi%fmi_df(this%dis, 1)
225  call this%oc%oc_df()
226  call this%budget%budget_df(niunit_prt, 'MASS', 'M')
227 
228  ! Define packages and assign iout for time series managers
229  do ip = 1, this%bndlist%Count()
230  packobj => getbndfromlist(this%bndlist, ip)
231  call packobj%bnd_df(this%dis%nodes, this%dis)
232  packobj%TsManager%iout = this%iout
233  packobj%TasManager%iout = this%iout
234  end do
235 
236  ! Allocate model arrays
237  call this%allocate_arrays()
238 
239  end subroutine prt_df
240 
241  !> @brief Allocate and read
242  !!
243  !! (1) allocates and reads packages part of this model,
244  !! (2) allocates memory for arrays part of this model object
245  !<
246  subroutine prt_ar(this)
247  ! modules
248  use constantsmodule, only: dhnoflo
249  use prtprpmodule, only: prtprptype
250  use prtmipmodule, only: prtmiptype
251  ! dummy
252  class(prtmodeltype) :: this
253  ! locals
254  integer(I4B) :: ip, nprp
255  class(bndtype), pointer :: packobj
256  class(*), pointer :: p
257 
258  ! Set up basic packages
259  call this%fmi%fmi_ar(this%ibound)
260  if (this%inmip > 0) call this%mip%mip_ar()
261 
262  ! Set up output control and budget
263  call this%oc%oc_ar(this%dis, dhnoflo)
264  call this%budget%set_ibudcsv(this%oc%ibudcsv)
265 
266  ! Initialize the event buffer (memory or scratch file per OC option)
267  call this%tracks%init_buffer(this%oc%scratch_buffer)
268 
269  ! Select tracking events
270  call this%tracks%select_events( &
271  this%oc%trackrelease, &
272  this%oc%trackfeatexit, &
273  this%oc%tracktimestep, &
274  this%oc%trackterminate, &
275  this%oc%trackweaksink, &
276  this%oc%trackusertime, &
277  this%oc%tracksubfexit, &
278  this%oc%trackdropped)
279 
280  ! Set up boundary pkgs and pkg-scoped track files
281  nprp = 0
282  do ip = 1, this%bndlist%Count()
283  packobj => getbndfromlist(this%bndlist, ip)
284  select type (packobj)
285  type is (prtprptype)
286  nprp = nprp + 1
287  call packobj%prp_set_pointers(this%ibound, this%mip%izone)
288  call packobj%bnd_ar()
289  call packobj%bnd_ar()
290  if (packobj%itrkout > 0) then
291  call this%tracks%init_file( &
292  packobj%itrkout, &
293  iprp=nprp)
294  end if
295  if (packobj%itrkcsv > 0) then
296  call this%tracks%init_file( &
297  packobj%itrkcsv, &
298  csv=.true., &
299  iprp=nprp)
300  end if
301  class default
302  call packobj%bnd_ar()
303  end select
304  end do
305 
306  ! Set up model-scoped track files
307  if (this%oc%itrkout > 0) &
308  call this%tracks%init_file(this%oc%itrkout)
309  if (this%oc%itrkcsv > 0) &
310  call this%tracks%init_file(this%oc%itrkcsv, csv=.true.)
311 
312  ! Initialize and select the tracking method based on discretization
313  select type (dis => this%dis)
314  type is (distype)
315  call this%method_dis%init( &
316  fmi=this%fmi, &
317  events=this%events, &
318  izone=this%mip%izone, &
319  flowja=this%flowja, &
320  porosity=this%mip%porosity, &
321  retfactor=this%mip%retfactor, &
322  tracktimes=this%oc%tracktimes)
323  this%method => this%method_dis
324  type is (disvtype)
325  call this%method_disv%init( &
326  fmi=this%fmi, &
327  events=this%events, &
328  izone=this%mip%izone, &
329  flowja=this%flowja, &
330  porosity=this%mip%porosity, &
331  retfactor=this%mip%retfactor, &
332  tracktimes=this%oc%tracktimes)
333  this%method => this%method_disv
334  end select
335 
336  ! Subscribe particle track output manager to events
337  p => this%tracks
338  call this%events%subscribe(add_particle_event, p)
339 
340  ! Set verbose tracing if requested
341  if (this%oc%dump_event_trace) this%tracks%iout = 0
342  end subroutine prt_ar
343 
344  !> @brief Read and prepare (calls package read and prepare routines)
345  subroutine prt_rp(this)
346  use tdismodule, only: readnewdata
347  ! dummy
348  class(prtmodeltype) :: this
349  ! local
350  class(bndtype), pointer :: packobj
351  integer(I4B) :: ip
352 
353  ! Check with TDIS on whether or not it is time to RP
354  if (.not. readnewdata) return
355 
356  ! Read and prepare
357  if (this%inoc > 0) call this%oc%oc_rp()
358  do ip = 1, this%bndlist%Count()
359  packobj => getbndfromlist(this%bndlist, ip)
360  call packobj%bnd_rp()
361  end do
362  end subroutine prt_rp
363 
364  !> @brief Time step advance (calls package advance subroutines)
365  subroutine prt_ad(this)
366  ! modules
367  use simvariablesmodule, only: isimcheck
368  ! dummy
369  class(prtmodeltype) :: this
370  class(bndtype), pointer :: packobj
371  ! local
372  integer(I4B) :: ip, n, i
373 
374  ! Discard buffered events from previous time step solve attempts.
375  ! prt_advance() is called on every sln_ca(): once per ATS retry,
376  ! once per Picard iteration, and once for the post-Picard output
377  ! rerun if mxiter > 1. Tracking is skipped during Picard iterations
378  ! (isuppress_output=1) in prt_solve, so the buffer is empty here on
379  ! Picard calls and the discard is a no-op. On the output rerun
380  ! (isuppress_output=0), tracking runs once and the buffer is cleared
381  ! before it is filled, so only events from that run reach disk.
382  call this%tracks%discard_buffer()
383 
384  ! Update look-behind mass
385  do n = 1, this%dis%nodes
386  this%massstoold(n) = this%masssto(n)
387  end do
388 
389  ! Advance fmi
390  call this%fmi%fmi_ad()
391 
392  ! Advance release packages
393  do ip = 1, this%bndlist%Count()
394  packobj => getbndfromlist(this%bndlist, ip)
395  call packobj%bnd_ad()
396  if (isimcheck > 0) &
397  call packobj%bnd_ck()
398  end do
399 
400  ! Initialize the flowja array. Flowja is calculated each time,
401  ! even if output is suppressed. (Flowja represents flow of particle
402  ! mass and is positive into a cell. Currently, each particle is assigned
403  ! unit mass.) Flowja is updated continually as particles are tracked
404  ! over the time step and at the end of the time step. The diagonal
405  ! position of the flowja array will contain the flow residual.
406  do i = 1, this%dis%nja
407  this%flowja(i) = dzero
408  end do
409  end subroutine prt_ad
410 
411  !> @brief Calculate intercell flow (flowja)
412  subroutine prt_cq(this, icnvg, isuppress_output)
413  ! modules
414  use sparsemodule, only: csr_diagsum
415  use tdismodule, only: delt
416  use prtprpmodule, only: prtprptype
417  ! dummy
418  class(prtmodeltype) :: this
419  integer(I4B), intent(in) :: icnvg
420  integer(I4B), intent(in) :: isuppress_output
421  ! local
422  integer(I4B) :: i
423  integer(I4B) :: ip
424  class(bndtype), pointer :: packobj
425  real(DP) :: tled
426 
427  ! Flowja is calculated each time, even if output is suppressed.
428  ! Flowja represents flow of particle mass and is positive into a cell.
429  ! Currently, each particle is assigned unit mass.
430  !
431  ! Reciprocal of time step size.
432  tled = done / delt
433  !
434  ! Flowja was updated continually as particles were tracked over the
435  ! time step. At this point, flowja contains the net particle mass
436  ! exchanged between cells during the time step. To convert these to
437  ! flow rates (particle mass per time), divide by the time step size.
438  do i = 1, this%dis%nja
439  this%flowja(i) = this%flowja(i) * tled
440  end do
441 
442  ! Particle mass budget terms
443  call this%prt_cq_budterms()
444 
445  ! Go through packages and call cq routines. Just a formality.
446  do ip = 1, this%bndlist%Count()
447  packobj => getbndfromlist(this%bndlist, ip)
448  call packobj%bnd_cq(this%masssto, this%flowja)
449  end do
450 
451  ! Finalize calculation of flowja by adding face flows to the diagonal.
452  ! This results in the flow residual being stored in the diagonal
453  ! position for each cell.
454  call csr_diagsum(this%dis%con%ia, this%flowja)
455  end subroutine prt_cq
456 
457  !> @brief Calculate particle mass budget terms
458  subroutine prt_cq_budterms(this)
459  ! modules
460  use tdismodule, only: delt
461  use prtprpmodule, only: prtprptype
462  ! dummy
463  class(prtmodeltype) :: this
464  ! local
465  integer(I4B) :: ip
466  class(bndtype), pointer :: packobj
467  integer(I4B) :: n
468  integer(I4B) :: np
469  integer(I4B) :: idiag
470  integer(I4B) :: iprp
471  integer(I4B) :: istatus
472  real(DP) :: tled
473  real(DP) :: ratesto, ratetrm
474  character(len=:), allocatable :: particle_id
475  type(particletype), pointer :: particle
476 
477  call create_particle(particle)
478 
479  ! Reciprocal of time step size.
480  tled = done / delt
481 
482  ! Reset mass and rate arrays
483  do n = 1, this%dis%nodes
484  this%masssto(n) = dzero
485  this%masstrm(n) = dzero
486  this%ratesto(n) = dzero
487  this%ratetrm(n) = dzero
488  end do
489 
490  ! Loop over PRP packages and assign particle mass to the
491  ! appropriate budget term based on the particle status.
492  iprp = 0
493  do ip = 1, this%bndlist%Count()
494  packobj => getbndfromlist(this%bndlist, ip)
495  select type (packobj)
496  type is (prtprptype)
497  iprp = iprp + 1
498  do np = 1, packobj%nparticles
499  call packobj%particles_staging%get(particle, this%id, iprp, np)
500  istatus = packobj%particles_staging%istatus(np)
501  particle_id = particle%get_id()
502  if (istatus == active) then
503  ! calculate storage mass
504  n = packobj%particles_staging%itrdomain(np, level_feature)
505  this%masssto(n) = this%masssto(n) + done ! unit mass
506  else if (istatus > active) then
507  if (this%trm_ids%get(particle_id) /= 0) cycle
508  ! calculate terminating mass
509  n = packobj%particles_staging%itrdomain(np, level_feature)
510  this%masstrm(n) = this%masstrm(n) + done ! unit mass
511  call this%trm_ids%add(particle_id, 1) ! mark id terminated
512  end if
513  end do
514  end select
515  end do
516 
517  ! Calculate rates and update flowja
518  do n = 1, this%dis%nodes
519  ratesto = -(this%masssto(n) - this%massstoold(n)) * tled
520  ratetrm = -this%masstrm(n) * tled
521  this%ratesto(n) = ratesto
522  this%ratetrm(n) = ratetrm
523  idiag = this%dis%con%ia(n)
524  this%flowja(idiag) = this%flowja(idiag) + ratesto
525  end do
526 
527  call particle%destroy()
528  deallocate (particle)
529 
530  end subroutine prt_cq_budterms
531 
532  !> @brief Calculate flows and budget
533  !!
534  !! (1) Calculate intercell flows (flowja)
535  !! (2) Calculate package contributions to model budget
536  !!
537  !<
538  subroutine prt_bd(this, icnvg, isuppress_output)
539  ! modules
540  use tdismodule, only: delt
541  use budgetmodule, only: rate_accumulator
542  ! dummy
543  class(prtmodeltype) :: this
544  integer(I4B), intent(in) :: icnvg
545  integer(I4B), intent(in) :: isuppress_output
546  ! local
547  integer(I4B) :: ip
548  class(bndtype), pointer :: packobj
549  real(DP) :: rin
550  real(DP) :: rout
551 
552  ! Budget routines (start by resetting). Sole purpose of this section
553  ! is to add in and outs to model budget. All ins and out for a model
554  ! should be added here to this%budget. In a subsequent exchange call,
555  ! exchange flows might also be added.
556  call this%budget%reset()
557  ! storage term
558  call rate_accumulator(this%ratesto, rin, rout)
559  call this%budget%addentry(rin, rout, delt, budtxt(1), &
560  isuppress_output, ' PRT')
561  ! termination term
562  call rate_accumulator(this%ratetrm, rin, rout)
563  call this%budget%addentry(rin, rout, delt, budtxt(2), &
564  isuppress_output, ' PRT')
565  ! boundary packages
566  do ip = 1, this%bndlist%Count()
567  packobj => getbndfromlist(this%bndlist, ip)
568  call packobj%bnd_bd(this%budget)
569  end do
570  end subroutine prt_bd
571 
572  !> @brief Print and/or save model output
573  subroutine prt_ot(this)
574  use tdismodule, only: tdis_ot, endofperiod
575  use prtprpmodule, only: prtprptype
576  ! dummy
577  class(prtmodeltype) :: this
578  ! local
579  integer(I4B) :: idvsave
580  integer(I4B) :: idvprint
581  integer(I4B) :: icbcfl
582  integer(I4B) :: icbcun
583  integer(I4B) :: ibudfl
584  integer(I4B) :: ipflag
585  integer(I4B) :: ip
586  class(bndtype), pointer :: packobj
587 
588  ! Flush buffered events to disk
589  call this%tracks%flush_buffer()
590 
591  ! Commit each PRP's staged state
592  do ip = 1, this%bndlist%Count()
593  packobj => getbndfromlist(this%bndlist, ip)
594  select type (packobj)
595  type is (prtprptype)
596  call packobj%prp_commit()
597  end select
598  end do
599 
600  ! Set write and print flags
601  idvsave = 0
602  idvprint = 0
603  icbcfl = 0
604  ibudfl = 0
605  if (this%oc%oc_save('CONCENTRATION')) idvsave = 1
606  if (this%oc%oc_print('CONCENTRATION')) idvprint = 1
607  if (this%oc%oc_save('BUDGET')) icbcfl = 1
608  if (this%oc%oc_print('BUDGET')) ibudfl = 1
609  icbcun = this%oc%oc_save_unit('BUDGET')
610 
611  ! Override ibudfl and idvprint flags for nonconvergence
612  ! and end of period
613  ibudfl = this%oc%set_print_flag('BUDGET', 1, endofperiod)
614  idvprint = this%oc%set_print_flag('CONCENTRATION', 1, endofperiod)
615 
616  ! Save and print flows
617  call this%prt_ot_flow(icbcfl, ibudfl, icbcun)
618 
619  ! Save and print dependent variables
620  call this%prt_ot_dv(idvsave, idvprint, ipflag)
621 
622  ! Print budget summaries
623  call this%prt_ot_bdsummary(ibudfl, ipflag)
624 
625  ! Timing Output; if any dependent variables or budgets
626  ! are printed, then ipflag is set to 1.
627  if (ipflag == 1) call tdis_ot(this%iout)
628  end subroutine prt_ot
629 
630  !> @brief Save flows
631  subroutine prt_ot_flow(this, icbcfl, ibudfl, icbcun)
632  use prtprpmodule, only: prtprptype
633  class(prtmodeltype) :: this
634  integer(I4B), intent(in) :: icbcfl
635  integer(I4B), intent(in) :: ibudfl
636  integer(I4B), intent(in) :: icbcun
637  class(bndtype), pointer :: packobj
638  integer(I4B) :: ip
639 
640  ! Save PRT flows
641  call this%prt_ot_saveflow(this%dis%nja, this%flowja, icbcfl, icbcun)
642  do ip = 1, this%bndlist%Count()
643  packobj => getbndfromlist(this%bndlist, ip)
644  call packobj%bnd_ot_model_flows(icbcfl=icbcfl, ibudfl=0, icbcun=icbcun)
645  end do
646 
647  ! Save advanced package flows
648  do ip = 1, this%bndlist%Count()
649  packobj => getbndfromlist(this%bndlist, ip)
650  call packobj%bnd_ot_package_flows(icbcfl=icbcfl, ibudfl=0)
651  end do
652 
653  ! Print PRT flows
654  call this%prt_ot_printflow(ibudfl, this%flowja)
655  do ip = 1, this%bndlist%Count()
656  packobj => getbndfromlist(this%bndlist, ip)
657  call packobj%bnd_ot_model_flows(icbcfl=icbcfl, ibudfl=ibudfl, icbcun=0)
658  end do
659 
660  ! Print advanced package flows
661  do ip = 1, this%bndlist%Count()
662  packobj => getbndfromlist(this%bndlist, ip)
663  call packobj%bnd_ot_package_flows(icbcfl=0, ibudfl=ibudfl)
664  end do
665  end subroutine prt_ot_flow
666 
667  !> @brief Save intercell flows
668  subroutine prt_ot_saveflow(this, nja, flowja, icbcfl, icbcun)
669  ! dummy
670  class(prtmodeltype) :: this
671  integer(I4B), intent(in) :: nja
672  real(DP), dimension(nja), intent(in) :: flowja
673  integer(I4B), intent(in) :: icbcfl
674  integer(I4B), intent(in) :: icbcun
675  ! local
676  integer(I4B) :: ibinun
677  integer(I4B) :: naux
678  real(DP), dimension(0) :: auxrow
679  character(len=LENAUXNAME), dimension(0) :: auxname
680  logical(LGP) :: header_written
681  integer(I4B) :: i, nn
682  real(DP) :: m
683  integer(I4B) :: nsto, ntrm
684  logical(LGP), allocatable :: msto_mask(:), mtrm_mask(:)
685  integer(I4B), allocatable :: msto_nns(:), mtrm_nns(:)
686  real(DP), allocatable :: msto_vals(:), mtrm_vals(:)
687 
688  ! Set unit number for binary output
689  if (this%ipakcb < 0) then
690  ibinun = icbcun
691  elseif (this%ipakcb == 0) then
692  ibinun = 0
693  else
694  ibinun = this%ipakcb
695  end if
696  if (icbcfl == 0) ibinun = 0
697 
698  ! Return if nothing to do
699  if (ibinun == 0) return
700 
701  ! Write mass face flows
702  call this%dis%record_connection_array(flowja, ibinun, this%iout)
703 
704  ! Write mass storage term
705  naux = 0
706  header_written = .false.
707  msto_mask = this%masssto > dzero
708  msto_vals = pack(this%masssto, msto_mask)
709  msto_nns = [(i, i=1, size(this%masssto))]
710  msto_nns = pack(msto_nns, msto_mask)
711  nsto = size(msto_nns)
712  do i = 1, nsto
713  nn = msto_nns(i)
714  m = msto_vals(i)
715  if (.not. header_written) then
716  call this%dis%record_srcdst_list_header(budtxt(1), &
717  'PRT ', &
718  'PRT ', &
719  'PRT ', &
720  'STORAGE ', &
721  naux, auxname, ibinun, &
722  nsto, this%iout)
723  header_written = .true.
724  end if
725  call this%dis%record_mf6_list_entry(ibinun, nn, nn, m, &
726  0, auxrow, &
727  olconv2=.false.)
728  end do
729 
730  ! Write mass termination term
731  header_written = .false.
732  mtrm_mask = this%masstrm > dzero
733  mtrm_vals = pack(this%masstrm, mtrm_mask)
734  mtrm_nns = [(i, i=1, size(this%masstrm))]
735  mtrm_nns = pack(mtrm_nns, mtrm_mask)
736  ntrm = size(mtrm_nns)
737  do i = 1, ntrm
738  nn = mtrm_nns(i)
739  m = mtrm_vals(i)
740  if (.not. header_written) then
741  call this%dis%record_srcdst_list_header(budtxt(2), &
742  'PRT ', &
743  'PRT ', &
744  'PRT ', &
745  'TERMINATION ', &
746  naux, auxname, ibinun, &
747  ntrm, this%iout)
748  header_written = .true.
749  end if
750  call this%dis%record_mf6_list_entry(ibinun, nn, nn, m, &
751  0, auxrow, &
752  olconv2=.false.)
753  end do
754 
755  end subroutine prt_ot_saveflow
756 
757  !> @brief Print intercell flows
758  subroutine prt_ot_printflow(this, ibudfl, flowja)
759  ! modules
760  use tdismodule, only: kper, kstp
761  use constantsmodule, only: lenbigline
762  ! dummy
763  class(prtmodeltype) :: this
764  integer(I4B), intent(in) :: ibudfl
765  real(DP), intent(inout), dimension(:) :: flowja
766  ! local
767  character(len=LENBIGLINE) :: line
768  character(len=30) :: tempstr
769  integer(I4B) :: n, ipos, m
770  real(DP) :: qnm
771  ! formats
772  character(len=*), parameter :: fmtiprflow = &
773  "(/,4x,'CALCULATED INTERCELL FLOW &
774  &FOR PERIOD ', i0, ' STEP ', i0)"
775 
776  ! Write flowja to list file if requested
777  if (ibudfl /= 0 .and. this%iprflow > 0) then
778  write (this%iout, fmtiprflow) kper, kstp
779  do n = 1, this%dis%nodes
780  line = ''
781  call this%dis%noder_to_string(n, tempstr)
782  line = trim(tempstr)//':'
783  do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
784  m = this%dis%con%ja(ipos)
785  call this%dis%noder_to_string(m, tempstr)
786  line = trim(line)//' '//trim(tempstr)
787  qnm = flowja(ipos)
788  write (tempstr, '(1pg15.6)') qnm
789  line = trim(line)//' '//trim(adjustl(tempstr))
790  end do
791  write (this%iout, '(a)') trim(line)
792  end do
793  end if
794  end subroutine prt_ot_printflow
795 
796  !> @brief Print dependent variables
797  subroutine prt_ot_dv(this, idvsave, idvprint, ipflag)
798  ! dummy
799  class(prtmodeltype) :: this
800  integer(I4B), intent(in) :: idvsave
801  integer(I4B), intent(in) :: idvprint
802  integer(I4B), intent(inout) :: ipflag
803  ! local
804  class(bndtype), pointer :: packobj
805  integer(I4B) :: ip
806 
807  ! Print advanced package dependent variables
808  do ip = 1, this%bndlist%Count()
809  packobj => getbndfromlist(this%bndlist, ip)
810  call packobj%bnd_ot_dv(idvsave, idvprint)
811  end do
812 
813  ! save head and print head
814  call this%oc%oc_ot(ipflag)
815  end subroutine prt_ot_dv
816 
817  !> @brief Print budget summary
818  subroutine prt_ot_bdsummary(this, ibudfl, ipflag)
819  ! modules
820  use tdismodule, only: kstp, kper, totim, delt
821  ! dummy
822  class(prtmodeltype) :: this
823  integer(I4B), intent(in) :: ibudfl
824  integer(I4B), intent(inout) :: ipflag
825  ! local
826  class(bndtype), pointer :: packobj
827  integer(I4B) :: ip
828 
829  ! Package budget summary
830  do ip = 1, this%bndlist%Count()
831  packobj => getbndfromlist(this%bndlist, ip)
832  call packobj%bnd_ot_bdsummary(kstp, kper, this%iout, ibudfl)
833  end do
834 
835  ! model budget summary
836  call this%budget%finalize_step(delt)
837  if (ibudfl /= 0) then
838  ipflag = 1
839  ! model budget summary
840  call this%budget%budget_ot(kstp, kper, this%iout)
841  end if
842 
843  ! Write to budget csv
844  call this%budget%writecsv(totim)
845  end subroutine prt_ot_bdsummary
846 
847  !> @brief Deallocate
848  subroutine prt_da(this)
849  ! modules
853  ! dummy
854  class(prtmodeltype) :: this
855  ! local
856  integer(I4B) :: ip
857  class(bndtype), pointer :: packobj
858 
859  ! Deallocate idm memory
860  call memorystore_remove(this%name, 'NAM', idm_context)
861  call memorystore_remove(component=this%name, context=idm_context)
862 
863  ! Internal packages
864  call this%dis%dis_da()
865  call this%fmi%fmi_da()
866  call this%mip%mip_da()
867  call this%budget%budget_da()
868  call this%oc%oc_da()
869  deallocate (this%dis)
870  deallocate (this%fmi)
871  deallocate (this%mip)
872  deallocate (this%budget)
873  deallocate (this%oc)
874 
875  ! Method objects
876  call this%method_dis%deallocate()
877  deallocate (this%method_dis)
878  call this%method_disv%deallocate()
879  deallocate (this%method_disv)
880 
881  ! Boundary packages
882  do ip = 1, this%bndlist%Count()
883  packobj => getbndfromlist(this%bndlist, ip)
884  call packobj%bnd_da()
885  deallocate (packobj)
886  end do
887 
888  ! Scalars
889  call mem_deallocate(this%infmi)
890  call mem_deallocate(this%inmip)
891  call mem_deallocate(this%inadv)
892  call mem_deallocate(this%indsp)
893  call mem_deallocate(this%inssm)
894  call mem_deallocate(this%inmst)
895  call mem_deallocate(this%inmvt)
896  call mem_deallocate(this%inoc)
897 
898  ! Arrays
899  call mem_deallocate(this%masssto)
900  call mem_deallocate(this%massstoold)
901  call mem_deallocate(this%ratesto)
902  call mem_deallocate(this%masstrm)
903  call mem_deallocate(this%ratetrm)
904 
905  call this%tracks%destroy()
906  deallocate (this%events)
907  deallocate (this%tracks)
908 
909  call this%ExplicitModelType%model_da()
910  end subroutine prt_da
911 
912  !> @brief Allocate memory for scalars
913  subroutine allocate_scalars(this, modelname)
914  ! dummy
915  class(prtmodeltype) :: this
916  character(len=*), intent(in) :: modelname
917 
918  ! allocate members from parent class
919  call this%ExplicitModelType%allocate_scalars(modelname)
920 
921  ! allocate members that are part of model class
922  call mem_allocate(this%infmi, 'INFMI', this%memoryPath)
923  call mem_allocate(this%inmip, 'INMIP', this%memoryPath)
924  call mem_allocate(this%inmvt, 'INMVT', this%memoryPath)
925  call mem_allocate(this%inmst, 'INMST', this%memoryPath)
926  call mem_allocate(this%inadv, 'INADV', this%memoryPath)
927  call mem_allocate(this%indsp, 'INDSP', this%memoryPath)
928  call mem_allocate(this%inssm, 'INSSM', this%memoryPath)
929  call mem_allocate(this%inoc, 'INOC ', this%memoryPath)
930 
931  this%infmi = 0
932  this%inmip = 0
933  this%inmvt = 0
934  this%inmst = 0
935  this%inadv = 0
936  this%indsp = 0
937  this%inssm = 0
938  this%inoc = 0
939  end subroutine allocate_scalars
940 
941  !> @brief Allocate arrays
942  subroutine allocate_arrays(this)
944  class(prtmodeltype) :: this
945  integer(I4B) :: n
946 
947  ! Allocate arrays in parent type (ibound, flowja, nja)
948  call this%ExplicitModelType%allocate_arrays()
949 
950  ! Allocate and initialize PRT-specific arrays
951  call mem_allocate(this%masssto, this%dis%nodes, &
952  'MASSSTO', this%memoryPath)
953  call mem_allocate(this%massstoold, this%dis%nodes, &
954  'MASSSTOOLD', this%memoryPath)
955  call mem_allocate(this%ratesto, this%dis%nodes, &
956  'RATESTO', this%memoryPath)
957  call mem_allocate(this%masstrm, this%dis%nodes, &
958  'MASSTRM', this%memoryPath)
959  call mem_allocate(this%ratetrm, this%dis%nodes, &
960  'RATETRM', this%memoryPath)
961  do n = 1, this%dis%nodes
962  this%masssto(n) = dzero
963  this%massstoold(n) = dzero
964  this%ratesto(n) = dzero
965  this%masstrm(n) = dzero
966  this%ratetrm(n) = dzero
967  end do
968  end subroutine allocate_arrays
969 
970  !> @brief Create boundary condition packages for this model
971  subroutine package_create(this, filtyp, ipakid, ipaknum, pakname, mempath, &
972  inunit, iout)
973  ! modules
974  use constantsmodule, only: linelength
975  use apimodule, only: api_create
976  ! dummy
977  class(prtmodeltype) :: this
978  character(len=*), intent(in) :: filtyp
979  character(len=LINELENGTH) :: errmsg
980  integer(I4B), intent(in) :: ipakid
981  integer(I4B), intent(in) :: ipaknum
982  character(len=*), intent(in) :: pakname
983  character(len=*), intent(in) :: mempath
984  integer(I4B), intent(in) :: inunit
985  integer(I4B), intent(in) :: iout
986  ! local
987  class(bndtype), pointer :: packobj
988  class(bndtype), pointer :: packobj2
989  integer(I4B) :: ip
990 
991  ! This part creates the package object
992  select case (filtyp)
993  case ('PRP6')
994  call prp_create(packobj, ipakid, ipaknum, inunit, iout, &
995  this%name, pakname, this%fmi, mempath)
996  case ('API6')
997  call api_create(packobj, ipakid, ipaknum, inunit, iout, &
998  this%name, pakname, mempath)
999  case default
1000  write (errmsg, *) 'Invalid package type: ', filtyp
1001  call store_error(errmsg, terminate=.true.)
1002  end select
1003 
1004  ! Packages is the bndlist that is associated with the parent model
1005  ! The following statement puts a pointer to this package in the ipakid
1006  ! position of packages.
1007  do ip = 1, this%bndlist%Count()
1008  packobj2 => getbndfromlist(this%bndlist, ip)
1009  if (packobj2%packName == pakname) then
1010  write (errmsg, '(a,a)') 'Cannot create package. Package name '// &
1011  'already exists: ', trim(pakname)
1012  call store_error(errmsg, terminate=.true.)
1013  end if
1014  end do
1015  call addbndtolist(this%bndlist, packobj)
1016  end subroutine package_create
1017 
1018  !> @brief Check to make sure required input files have been specified
1019  subroutine ftype_check(this, indis)
1020  ! dummy
1021  class(prtmodeltype) :: this
1022  integer(I4B), intent(in) :: indis
1023  ! local
1024  character(len=LINELENGTH) :: errmsg
1025 
1026  ! Check for DIS(u) and MIP. Stop if not present.
1027  if (indis == 0) then
1028  write (errmsg, '(1x,a)') &
1029  'Discretization (DIS6, DISV6, or DISU6) package not specified.'
1030  call store_error(errmsg)
1031  end if
1032  if (this%inmip == 0) then
1033  write (errmsg, '(1x,a)') &
1034  'Model input (MIP6) package not specified.'
1035  call store_error(errmsg)
1036  end if
1037 
1038  if (count_errors() > 0) then
1039  write (errmsg, '(1x,a)') 'One or more required package(s) not specified.'
1040  call store_error(errmsg)
1041  call store_error_filename(this%filename)
1042  end if
1043  end subroutine ftype_check
1044 
1045  !> @brief Solve the model
1046  subroutine prt_solve(this, isuppress_output)
1047  use tdismodule, only: totimc, delt, endofsimulation
1048  use prtprpmodule, only: prtprptype
1051  use simvariablesmodule, only: warnmsg
1052  ! dummy
1053  class(prtmodeltype) :: this
1054  integer(I4B), intent(in) :: isuppress_output
1055  ! local
1056  integer(I4B) :: np, ip
1057  class(bndtype), pointer :: packobj
1058  type(particletype), pointer :: particle
1059  real(DP) :: tmax
1060  integer(I4B) :: iprp
1061 
1062  ! Skip tracking during Picard iterations: PRT doesn't affect the flow
1063  ! solution, so tracking is only needed once on the final output rerun
1064  ! (or on the single call when mxiter=1, which also has isuppress_output=0).
1065  if (isuppress_output /= 0) return
1066 
1067  ! A single particle is reused in the tracking loops
1068  ! to avoid allocating and deallocating it each time.
1069  ! get() and put() retrieve and store particle state.
1070  call create_particle(particle)
1071  ! Loop over PRP packages and particles within them.
1072  iprp = 0
1073  do ip = 1, this%bndlist%Count()
1074  packobj => getbndfromlist(this%bndlist, ip)
1075  select type (packobj)
1076  type is (prtprptype)
1077  iprp = iprp + 1
1078  do np = 1, packobj%nparticles
1079  ! Get the particle from the staging store
1080  call packobj%particles_staging%get(particle, this%id, iprp, np)
1081  ! If particle is permanently unreleased, cycle.
1082  ! Raise a termination event if we haven't yet.
1083  ! TODO: when we have generic dynamic vectors,
1084  ! consider terminating permanently unreleased
1085  ! in PRP instead of here. For now, status -8
1086  ! indicates the permanently unreleased event
1087  ! is not yet recorded, status 8 it has been.
1088  if (particle%istatus == (-1 * term_unreleased)) then
1089  call this%method%terminate(particle, status=term_unreleased)
1090  call packobj%particles_staging%put(particle, np)
1091  end if
1092  if (particle%istatus > active) cycle ! Skip terminated particles
1093  particle%istatus = active ! Set active status in case of release
1094  if (particle%trelease >= totimc) then
1095  if (particle%trelease > particle%tstop) then
1096  ! The package's stop time is earlier than the release time.
1097  ! Terminate it permanently unreleased and show a warning.
1098  write (warnmsg, '(a,g0,a,g0,a,g0,a)') &
1099  'Particle release point ', particle%irpt, ' has &
1100  &release time ', particle%trelease, ' after package &
1101  &stop time ', particle%tstop, '; particle will not &
1102  &be released.'
1103  call store_warning(warnmsg)
1104  call this%method%terminate(particle, status=term_unreleased)
1105  else
1106  ! The particle was released this time step; emit a
1107  ! release event.
1108  call this%method%release(particle)
1109  end if
1110  end if
1111  if (particle%istatus <= active) then
1112  ! Maximum time is the end of the time step or the particle
1113  ! stop time, whichever comes first, unless it's the final
1114  ! time step and the extend option is on, in which case
1115  ! it's just the particle stop time.
1116  if (endofsimulation .and. particle%extend) then
1117  tmax = particle%tstop
1118  else
1119  tmax = min(totimc + delt, particle%tstop)
1120  end if
1121  ! tmax should never be less than the particle's current
1122  ! tracked time: ttrack can't get ahead of totimc, the
1123  ! smaller of the two terms tmax is drawn from, and a
1124  ! release whose time precedes the stop time was already
1125  ! caught above and never reaches this point. If it
1126  ! happens anyway, that's a programmer error: tracking
1127  ! methods assume a nonnegative time interval, and calling
1128  ! apply() with tmax < ttrack sends them a negative one,
1129  ! which corrupts the tracking method.
1130  if (tmax < particle%ttrack) &
1131  call pstop(1, 'Programmer error: PRT tracking tmax &
1132  &precedes particle%ttrack.')
1133  ! Apply the tracking method until the maximum time.
1134  call this%method%apply(particle, tmax)
1135  ! If the particle timed out, terminate it.
1136  ! "Timed out" means it's still active but
1137  ! - it reached its stop time, or
1138  ! - the simulation is over.
1139  ! We can't detect timeout within the tracking
1140  ! method because the method just receives the
1141  ! maximum time with no context on what it is.
1142  ! TODO maybe think about changing that?
1143  if (particle%istatus <= active .and. &
1144  (particle%ttrack == particle%tstop .or. endofsimulation)) &
1145  call this%method%terminate(particle, status=term_timeout)
1146  end if
1147  ! Return the particle to the staging store
1148  call packobj%particles_staging%put(particle, np)
1149  end do
1150  end select
1151  end do
1152  call particle%destroy()
1153  deallocate (particle)
1154  end subroutine prt_solve
1155 
1156  !> @brief Source package info and begin to process
1157  subroutine create_bndpkgs(this, bndpkgs, pkgtypes, pkgnames, &
1158  mempaths, inunits)
1159  ! modules
1162  ! dummy
1163  class(prtmodeltype) :: this
1164  integer(I4B), dimension(:), allocatable, intent(inout) :: bndpkgs
1165  type(characterstringtype), dimension(:), contiguous, &
1166  pointer, intent(inout) :: pkgtypes
1167  type(characterstringtype), dimension(:), contiguous, &
1168  pointer, intent(inout) :: pkgnames
1169  type(characterstringtype), dimension(:), contiguous, &
1170  pointer, intent(inout) :: mempaths
1171  integer(I4B), dimension(:), contiguous, &
1172  pointer, intent(inout) :: inunits
1173  ! local
1174  integer(I4B) :: ipakid, ipaknum
1175  character(len=LENFTYPE) :: pkgtype, bndptype
1176  character(len=LENPACKAGENAME) :: pkgname
1177  character(len=LENMEMPATH) :: mempath
1178  integer(I4B), pointer :: inunit
1179  integer(I4B) :: n
1180 
1181  if (allocated(bndpkgs)) then
1182  ! create stress packages
1183  ipakid = 1
1184  bndptype = ''
1185  do n = 1, size(bndpkgs)
1186  pkgtype = pkgtypes(bndpkgs(n))
1187  pkgname = pkgnames(bndpkgs(n))
1188  mempath = mempaths(bndpkgs(n))
1189  inunit => inunits(bndpkgs(n))
1190 
1191  if (bndptype /= pkgtype) then
1192  ipaknum = 1
1193  bndptype = pkgtype
1194  end if
1195 
1196  call this%package_create(pkgtype, ipakid, ipaknum, pkgname, mempath, &
1197  inunit, this%iout)
1198  ipakid = ipakid + 1
1199  ipaknum = ipaknum + 1
1200  end do
1201 
1202  ! cleanup
1203  deallocate (bndpkgs)
1204  end if
1205 
1206  end subroutine create_bndpkgs
1207 
1208  !> @brief Source package info and begin to process
1209  subroutine create_packages(this)
1210  ! modules
1213  use arrayhandlersmodule, only: expandarray
1214  use memorymanagermodule, only: mem_setptr
1216  use simvariablesmodule, only: idm_context
1217  use budgetmodule, only: budget_cr
1218  use prtmipmodule, only: mip_cr
1219  use prtfmimodule, only: fmi_cr
1220  use prtocmodule, only: oc_cr
1221  ! dummy
1222  class(prtmodeltype) :: this
1223  ! local
1224  type(characterstringtype), dimension(:), contiguous, &
1225  pointer :: pkgtypes => null()
1226  type(characterstringtype), dimension(:), contiguous, &
1227  pointer :: pkgnames => null()
1228  type(characterstringtype), dimension(:), contiguous, &
1229  pointer :: mempaths => null()
1230  integer(I4B), dimension(:), contiguous, &
1231  pointer :: inunits => null()
1232  character(len=LENMEMPATH) :: model_mempath
1233  character(len=LENFTYPE) :: pkgtype
1234  character(len=LENPACKAGENAME) :: pkgname
1235  character(len=LENMEMPATH) :: mempath
1236  integer(I4B), pointer :: inunit
1237  integer(I4B), dimension(:), allocatable :: bndpkgs
1238  integer(I4B) :: n
1239  integer(I4B) :: indis = 0 ! DIS enabled flag
1240  character(len=LENMEMPATH) :: mempathmip = ''
1241  character(len=LENMEMPATH) :: mempathfmi = ''
1242  character(len=LENMEMPATH) :: mempathoc = ''
1243 
1244  ! set input memory paths, input/model and input/model/namfile
1245  model_mempath = create_mem_path(component=this%name, context=idm_context)
1246 
1247  ! set pointers to model path package info
1248  call mem_setptr(pkgtypes, 'PKGTYPES', model_mempath)
1249  call mem_setptr(pkgnames, 'PKGNAMES', model_mempath)
1250  call mem_setptr(mempaths, 'MEMPATHS', model_mempath)
1251  call mem_setptr(inunits, 'INUNITS', model_mempath)
1252 
1253  ! determine which packages we have. create
1254  ! dis up front as the others depend on it.
1255  do n = 1, size(pkgtypes)
1256  pkgtype = pkgtypes(n)
1257  pkgname = pkgnames(n)
1258  mempath = mempaths(n)
1259  inunit => inunits(n)
1260 
1261  select case (pkgtype)
1262  case ('DIS6')
1263  indis = 1
1264  call dis_cr(this%dis, this%name, mempath, indis, this%iout)
1265  case ('DISV6')
1266  indis = 1
1267  call disv_cr(this%dis, this%name, mempath, indis, this%iout)
1268  case ('DISU6')
1269  indis = 1
1270  call disu_cr(this%dis, this%name, mempath, indis, this%iout)
1271  case ('MIP6')
1272  this%inmip = 1
1273  mempathmip = mempath
1274  case ('FMI6')
1275  this%infmi = 1
1276  mempathfmi = mempath
1277  case ('OC6')
1278  this%inoc = 1
1279  mempathoc = mempath
1280  case ('PRP6')
1281  call expandarray(bndpkgs)
1282  bndpkgs(size(bndpkgs)) = n
1283  case default
1284  call pstop(1, "Unrecognized package type: "//pkgtype)
1285  end select
1286  end do
1287 
1288  ! Create budget manager
1289  call budget_cr(this%budget, this%name)
1290 
1291  ! Create tracking methods
1292  call create_method_dis(this%method_dis)
1293  call create_method_disv(this%method_disv)
1294 
1295  ! Create non-boundary packages
1296  call mip_cr(this%mip, this%name, mempathmip, this%inmip, this%iout, this%dis)
1297  call fmi_cr(this%fmi, this%name, mempathfmi, this%infmi, this%iout)
1298  call oc_cr(this%oc, this%name, mempathoc, this%inoc, this%iout)
1299 
1300  ! Check required input files
1301  call this%ftype_check(indis)
1302 
1303  ! Create boundary packages
1304  call this%create_bndpkgs(bndpkgs, pkgtypes, pkgnames, mempaths, inunits)
1305  call this%create_exg_prp()
1306  end subroutine create_packages
1307 
1308  !> @brief Create an exchange PRP package for particles
1309  !! entering this model from other model.
1310  subroutine create_exg_prp(this)
1311  class(prtmodeltype) :: this
1312  ! local
1313  class(bndtype), pointer :: packobj
1314  character(len=LENPACKAGENAME) :: exgprp_name
1315 
1316  exgprp_name = 'EXGPRP'
1317 
1318  call prp_create(packobj, &
1319  id=0, &
1320  ibcnum=0, &
1321  inunit=-1, &
1322  iout=this%iout, &
1323  namemodel=this%name, &
1324  pakname=exgprp_name, &
1325  fmi=this%fmi)
1326  call addbndtolist(this%bndlist, packobj)
1327  end subroutine create_exg_prp
1328 
1329  !> @brief Write model namfile options to list file
1330  subroutine log_namfile_options(this, found)
1332  class(prtmodeltype) :: this
1333  type(prtnamparamfoundtype), intent(in) :: found
1334 
1335  write (this%iout, '(1x,a)') 'NAMEFILE OPTIONS:'
1336 
1337  if (found%print_input) then
1338  write (this%iout, '(4x,a)') 'STRESS PACKAGE INPUT WILL BE PRINTED '// &
1339  'FOR ALL MODEL STRESS PACKAGES'
1340  end if
1341 
1342  if (found%print_flows) then
1343  write (this%iout, '(4x,a)') 'PACKAGE FLOWS WILL BE PRINTED '// &
1344  'FOR ALL MODEL PACKAGES'
1345  end if
1346 
1347  if (found%save_flows) then
1348  write (this%iout, '(4x,a)') &
1349  'FLOWS WILL BE SAVED TO BUDGET FILE SPECIFIED IN OUTPUT CONTROL'
1350  end if
1351 
1352  write (this%iout, '(1x,a)') 'END NAMEFILE OPTIONS:'
1353  end subroutine log_namfile_options
1354 
1355 end module prtmodule
Event handler interface. Handlers may signal to the dispatching caller whether they have handled the ...
This module contains the API package methods.
Definition: gwf-api.f90:12
subroutine, public api_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, mempath)
@ brief Create a new package object
Definition: gwf-api.f90:51
subroutine, public addbasemodeltolist(list, model)
Definition: BaseModel.f90:160
This module contains the base boundary package.
subroutine, public addbndtolist(list, bnd)
Add boundary to package list.
class(bndtype) function, pointer, public getbndfromlist(list, idx)
Get boundary from package list.
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public budget_cr(this, name_model)
@ brief Create a new budget object
Definition: Budget.f90:84
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
Definition: Budget.f90:632
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
@ mnormal
normal output mode
Definition: Constants.f90:206
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
integer(i4b), parameter lenpackagetype
maximum length of a package type (DIS6, SFR6, CSUB6, etc.)
Definition: Constants.f90:38
integer(i4b), parameter lenbigline
maximum length of a big line
Definition: Constants.f90:15
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:93
integer(i4b), parameter lenpakloc
maximum length of a package location
Definition: Constants.f90:50
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
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
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
Definition: Dis.f90:1
subroutine, public dis_cr(dis, name_model, input_mempath, inunit, iout)
Create a new structured discretization object.
Definition: Dis.f90:99
subroutine, public disu_cr(dis, name_model, input_mempath, inunit, iout)
Create a new unstructured discretization object.
Definition: Disu.f90:131
subroutine, public disv_cr(dis, name_model, input_mempath, inunit, iout)
Create a new discretization by vertices object.
Definition: Disv.f90:112
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
Definition: ErrorUtil.f90:24
Models that solve themselves.
A chaining hash map for integers.
Definition: HashTable.f90:7
subroutine, public hash_table_cr(map)
Create a hash table.
Definition: HashTable.f90:46
subroutine, public hash_table_da(map)
Deallocate the hash table.
Definition: HashTable.f90:64
subroutine, public lowcase(word)
Convert to lower case.
subroutine, public parseline(line, nwords, words, inunit, filename)
Parse a line into words.
subroutine, public upcase(word)
Convert to upper case.
This module defines variable data types.
Definition: kind.f90:8
type(listtype), public basemodellist
Definition: mf6lists.f90:16
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
subroutine, public memorystore_remove(component, subcomponent, context)
subroutine, public create_method_dis(method)
Create a new structured grid (DIS) tracking method.
Definition: MethodDis.f90:50
subroutine, public create_method_disv(method)
Create a new vertex grid (DISV) tracking method.
Definition: MethodDisv.f90:58
Particle tracking strategies.
Definition: Method.f90:2
@, public level_feature
Definition: Method.f90:40
@, public release
particle was released
@, public terminate
particle terminated
@ term_timeout
terminated at stop time or end of simulation
Definition: Particle.f90:40
@ term_unreleased
terminated permanently unreleased
Definition: Particle.f90:38
subroutine create_particle(particle)
Create a new particle.
Definition: Particle.f90:153
Particle track output module.
logical(lgp) function, public add_particle_event(context, particle, event)
Add a particle event to be written to eligible files and printed to an output file unit if requested....
subroutine, public fmi_cr(fmiobj, name_model, input_mempath, inunit, iout)
Create a new PrtFmi object.
Definition: prt-fmi.f90:60
subroutine, public mip_cr(mip, name_model, input_mempath, inunit, iout, dis)
Create a model input object.
Definition: prt-mip.f90:34
Definition: prt.f90:1
integer(i4b), parameter niunit_prt
Definition: prt.f90:128
subroutine prt_ot(this)
Print and/or save model output.
Definition: prt.f90:574
subroutine prt_rp(this)
Read and prepare (calls package read and prepare routines)
Definition: prt.f90:346
subroutine create_bndpkgs(this, bndpkgs, pkgtypes, pkgnames, mempaths, inunits)
Source package info and begin to process.
Definition: prt.f90:1159
subroutine prt_ar(this)
Allocate and read.
Definition: prt.f90:247
subroutine ftype_check(this, indis)
Check to make sure required input files have been specified.
Definition: prt.f90:1020
subroutine prt_ot_saveflow(this, nja, flowja, icbcfl, icbcun)
Save intercell flows.
Definition: prt.f90:669
subroutine prt_ad(this)
Time step advance (calls package advance subroutines)
Definition: prt.f90:366
subroutine prt_cq(this, icnvg, isuppress_output)
Calculate intercell flow (flowja)
Definition: prt.f90:413
subroutine package_create(this, filtyp, ipakid, ipaknum, pakname, mempath, inunit, iout)
Create boundary condition packages for this model.
Definition: prt.f90:973
subroutine prt_ot_flow(this, icbcfl, ibudfl, icbcun)
Save flows.
Definition: prt.f90:632
subroutine allocate_scalars(this, modelname)
Allocate memory for scalars.
Definition: prt.f90:914
subroutine prt_ot_bdsummary(this, ibudfl, ipflag)
Print budget summary.
Definition: prt.f90:819
character(len=lenpackagetype), dimension(prt_nmultipkg), public prt_multipkg
Definition: prt.f90:123
subroutine create_packages(this)
Source package info and begin to process.
Definition: prt.f90:1210
character(len=lenpackagetype), dimension(prt_nbasepkg), public prt_basepkg
Definition: prt.f90:109
subroutine prt_solve(this, isuppress_output)
Solve the model.
Definition: prt.f90:1047
integer(i4b), parameter, public prt_nmultipkg
PRT multi package array descriptors.
Definition: prt.f90:122
character(len=lenbudtxt), dimension(nbditems) budtxt
Definition: prt.f90:44
subroutine prt_da(this)
Deallocate.
Definition: prt.f90:849
subroutine, public prt_cr(filename, id, modelname)
Create a new particle tracking model object.
Definition: prt.f90:134
subroutine prt_ot_printflow(this, ibudfl, flowja)
Print intercell flows.
Definition: prt.f90:759
subroutine prt_bd(this, icnvg, isuppress_output)
Calculate flows and budget.
Definition: prt.f90:539
subroutine prt_df(this)
Define packages.
Definition: prt.f90:214
integer(i4b), parameter, public prt_nbasepkg
PRT base package array descriptors.
Definition: prt.f90:108
integer(i4b), parameter nbditems
Definition: prt.f90:43
subroutine allocate_arrays(this)
Allocate arrays.
Definition: prt.f90:943
subroutine log_namfile_options(this, found)
Write model namfile options to list file.
Definition: prt.f90:1331
subroutine prt_cq_budterms(this)
Calculate particle mass budget terms.
Definition: prt.f90:459
subroutine prt_ot_dv(this, idvsave, idvprint, ipflag)
Print dependent variables.
Definition: prt.f90:798
subroutine create_exg_prp(this)
Create an exchange PRP package for particles entering this model from other model.
Definition: prt.f90:1311
subroutine, public oc_cr(ocobj, name_model, input_mempath, inunit, iout)
@ brief Create an output control object
Definition: prt-oc.f90:53
subroutine, public prp_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, fmi, input_mempath)
Create a new particle release point package.
Definition: prt-prp.f90:129
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:237
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=linelength) idm_context
integer(i4b) isimcheck
simulation input check flag (1) to check input, (0) to ignore checks
character(len=maxcharlen) warnmsg
warning message string
subroutine csr_diagsum(ia, flowja)
Definition: Sparse.f90:263
logical(lgp), pointer, public endofperiod
flag indicating end of stress period
Definition: tdis.f90:30
logical(lgp), pointer, public endofsimulation
flag indicating end of simulation
Definition: tdis.f90:31
subroutine, public tdis_ot(iout)
Print simulation time.
Definition: tdis.f90:271
real(dp), pointer, public totim
time relative to start of simulation
Definition: tdis.f90:35
logical(lgp), pointer, public readnewdata
flag indicating time to read new data
Definition: tdis.f90:29
real(dp), pointer, public totimc
simulation time at start of time step
Definition: tdis.f90:36
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
This module contains version information.
Definition: version.f90:7
subroutine write_listfile_header(iout, cmodel_type, write_sys_command, write_kind_info)
@ brief Write program header
Definition: version.f90:103
Highest level model type. All models extend this parent type.
Definition: BaseModel.f90:16
@ brief BndType
Derived type for the Budget object.
Definition: Budget.f90:39
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
Structured grid discretization.
Definition: Dis.f90:23
Unstructured grid discretization.
Definition: Disu.f90:29
Vertex grid discretization.
Definition: Disv.f90:25
Base type for models that solve themselves.
A generic heterogeneous doubly-linked list.
Definition: List.f90:14
Base type for particle tracking methods.
Definition: Method.f90:57
Dispatcher for particle events. Consumers subscribe handlers to the dispatcher. Events may be dispatc...
Particle tracked by the PRT model.
Definition: Particle.f90:64
Particle track output manager. Handles printing as well as writing to files. One output unit can be c...
Particle tracking (PRT) model.
Definition: prt.f90:48
@ brief Output control for particle tracking models
Definition: prt-oc.f90:21
Particle release point (PRP) package.
Definition: prt-prp.f90:39