MODFLOW 6  version 6.7.0.dev3
USGS Modular Hydrologic Model
OutputControl.f90
Go to the documentation of this file.
1 !> @brief Model output control.
3 
4  use kindmodule, only: dp, i4b, lgp
6  use simvariablesmodule, only: errmsg
9 
10  implicit none
11  private
12  public outputcontroltype, oc_cr
13 
14  !> @ brief Controls model output. Overridden for each model type.
16  character(len=LENMEMPATH) :: memorypath !< path to data stored in the memory manager
17  character(len=LENMEMPATH) :: input_mempath !< input memory path
18  character(len=LENMODELNAME), pointer :: name_model => null() !< name of the model
19  character(len=LINELENGTH), pointer :: input_fname => null() !< input file name
20  integer(I4B), pointer :: inunit => null() !< unit number for input file
21  integer(I4B), pointer :: iout => null() !< unit number for output file
22  integer(I4B), pointer :: ibudcsv => null() !< unit number for budget csv output file
23  integer(I4B), pointer :: iperoc => null() !< stress period number for next output control
24  integer(I4B), pointer :: iocrep => null() !< output control repeat flag (period 0 step 0)
25  type(outputcontroldatatype), pointer, contiguous :: ocds(:) => null() !< output control objects
26  contains
27  procedure :: oc_df
28  procedure :: oc_rp
29  procedure :: oc_ot
30  procedure :: oc_da
31  procedure :: allocate_scalars => allocate
32  procedure :: source_options
33  procedure :: set_ocfile
34  procedure :: oc_save
35  procedure :: oc_print
36  procedure :: oc_save_unit
37  procedure :: set_print_flag
38  end type outputcontroltype
39 
40 contains
41 
42  !> @brief Create a new output control object.
43  subroutine oc_cr(oc, name_model, input_mempath, inunit, iout)
44  type(outputcontroltype), pointer :: oc !< OutputControlType object
45  character(len=*), intent(in) :: name_model !< name of the model
46  character(len=*), intent(in) :: input_mempath !< input mempath of the package
47  integer(I4B), intent(in) :: inunit !< unit number for input
48  integer(I4B), intent(in) :: iout !< unit number for output
49 
50  allocate (oc)
51  call oc%allocate_scalars(name_model, input_mempath)
52  oc%inunit = inunit
53  oc%iout = iout
54  end subroutine oc_cr
55 
56  !> @ brief Define the output control type. Placeholder routine.
57  subroutine oc_df(this)
58  class(outputcontroltype) :: this !< this instance
59  end subroutine oc_df
60 
61  !> @ brief Read period block options and prepare the output control type.
62  subroutine oc_rp(this)
63  ! modules
64  use tdismodule, only: kper
68  ! dummy
69  class(outputcontroltype) :: this !< this instance
70  ! local
71  class(outputcontroldatatype), pointer :: ocdobjptr
72  integer(I4B), pointer :: iper
73  type(characterstringtype), dimension(:), &
74  pointer, contiguous :: ocactions
75  type(characterstringtype), dimension(:), &
76  pointer, contiguous :: rtypes
77  type(characterstringtype), dimension(:), &
78  pointer, contiguous :: ocsettings
79  integer(I4B), pointer :: nlist
80  integer(I4B) :: n, ipos
81  character(len=LINELENGTH) :: ocaction, rtype, ocsetting
82  logical(LGP) :: found_rtype
83  ! formats
84  character(len=*), parameter :: fmtboc = &
85  &"(1X,/1X,'BEGIN READING OUTPUT CONTROL FOR STRESS PERIOD ',I0)"
86  character(len=*), parameter :: fmteoc = &
87  &"(/,1X,'END READING OUTPUT CONTROL FOR STRESS PERIOD ',I0)"
88  character(len=*), parameter :: fmtroc = &
89  "(1X,/1X,'OUTPUT CONTROL FOR STRESS PERIOD ',I0, &
90  &' IS REPEATED USING SETTINGS FROM A PREVIOUS STRESS PERIOD.')"
91 
92  if (this%input_mempath == '') return
93  call mem_setptr(iper, 'IPER', this%input_mempath)
94  if (iper /= kper) then
95  ! previous output control settings are still active
96  write (this%iout, fmtroc) kper
97  return
98  else
99  this%iperoc = iper
100  write (this%iout, fmtboc) this%iperoc
101  end if
102 
103  ! Clear io flags
104  do ipos = 1, size(this%ocds)
105  ocdobjptr => this%ocds(ipos)
106  call ocdobjptr%psm%init()
107  end do
108 
109  call mem_setptr(nlist, 'NBOUND', this%input_mempath)
110  call mem_setptr(ocactions, 'OCACTION', this%input_mempath)
111  call mem_setptr(rtypes, 'RTYPE', this%input_mempath)
112  call mem_setptr(ocsettings, 'SETTING', this%input_mempath)
113 
114  do n = 1, nlist
115  ocaction = ocactions(n)
116  rtype = rtypes(n)
117  ocsetting = ocsettings(n)
118 
119  found_rtype = .false.
120  do ipos = 1, size(this%ocds)
121  ocdobjptr => this%ocds(ipos)
122  if (rtype == trim(ocdobjptr%cname)) then
123  found_rtype = .true.
124  call ocdobjptr%psm%set(ocaction, ocsetting, this%iout)
125  call ocdobjptr%ocd_rp_check(this%input_fname)
126  end if
127  end do
128  if (.not. found_rtype) then
129  call store_error('Input OC period block rtype not found: "'// &
130  trim(rtype)//'".')
131  call store_error_filename(this%input_fname)
132  end if
133  end do
134 
135  write (this%iout, fmteoc) this%iperoc
136  end subroutine oc_rp
137 
138  !> @ brief Write output.
139  !!
140  !! Go through each output control data type and print
141  !! and/or save data based on user-specified controls.
142  !<
143  subroutine oc_ot(this, ipflg)
144  ! modules
145  use tdismodule, only: kstp, endofperiod
146  ! dummy
147  class(outputcontroltype) :: this !< OutputControlType object
148  integer(I4B), intent(inout) :: ipflg !< flag indicating if data was printed
149  ! local
150  integer(I4B) :: ipos
151  type(outputcontroldatatype), pointer :: ocdobjptr
152 
153  ! Clear printout flag(ipflg). This flag indicates that an array was
154  ! printed to the listing file.
155  ipflg = 0
156 
157  do ipos = 1, size(this%ocds)
158  ocdobjptr => this%ocds(ipos)
159  call ocdobjptr%ocd_ot(ipflg, kstp, endofperiod, this%iout)
160  end do
161  end subroutine oc_ot
162 
163  !> @ brief Deallocate method for OutputControlType
164  !!
165  !! Deallocate member variables.
166  !!
167  !<
168  subroutine oc_da(this)
169  ! modules
171  ! dummy
172  class(outputcontroltype) :: this !< OutputControlType object
173  ! local
174  integer(I4B) :: i
175 
176  do i = 1, size(this%ocds)
177  call this%ocds(i)%ocd_da()
178  end do
179  deallocate (this%ocds)
180 
181  deallocate (this%name_model)
182  deallocate (this%input_fname)
183  call mem_deallocate(this%inunit)
184  call mem_deallocate(this%iout)
185  call mem_deallocate(this%ibudcsv)
186  call mem_deallocate(this%iperoc)
187  call mem_deallocate(this%iocrep)
188  end subroutine oc_da
189 
190  !> @ brief Allocate variables for the output control object
191  subroutine allocate (this, name_model, input_mempath)
192  ! modules
196  ! dummy
197  class(outputcontroltype) :: this !< this instance
198  character(len=*), intent(in) :: name_model !< name of model
199  character(len=*), intent(in) :: input_mempath !< input mempath of the package
200  logical(LGP) :: found
201 
202  this%memoryPath = create_mem_path(name_model, 'OC')
203 
204  allocate (this%name_model)
205  allocate (this%input_fname)
206  call mem_allocate(this%inunit, 'INUNIT', this%memoryPath)
207  call mem_allocate(this%iout, 'IOUT', this%memoryPath)
208  call mem_allocate(this%ibudcsv, 'IBUDCSV', this%memoryPath)
209  call mem_allocate(this%iperoc, 'IPEROC', this%memoryPath)
210  call mem_allocate(this%iocrep, 'IOCREP', this%memoryPath)
211 
212  this%name_model = name_model
213  this%input_mempath = input_mempath
214  this%input_fname = ''
215  this%inunit = 0
216  this%iout = 0
217  this%ibudcsv = 0
218  this%iperoc = 0
219  this%iocrep = 0
220 
221  if (this%input_mempath /= '') then
222  call mem_set_value(this%input_fname, 'INPUT_FNAME', &
223  this%input_mempath, found)
224  end if
225  end subroutine allocate
226 
227  !> @ brief Read the output control options block
228  subroutine source_options(this)
229  ! modules
231  ! dummy
232  class(outputcontroltype) :: this !< this instance
233  type(outputcontroldatatype), pointer :: ocdobjptr
234  character(len=LINELENGTH) :: budgetfn, budgetcsv
235  character(len=LINELENGTH) :: prnfmt, print_format
236  logical(LGP) :: found_budcsv, found_budget
237  logical(LGP), dimension(4) :: found_format
238  integer(I4B), pointer :: columns, width, ndigits
239  integer(I4B) :: ipos
240 
241  found_format = .false.
242  allocate (columns)
243  allocate (width)
244  allocate (ndigits)
245 
246  call mem_set_value(columns, 'COLUMNS', this%input_mempath, &
247  found_format(1))
248  call mem_set_value(width, 'WIDTH', this%input_mempath, &
249  found_format(2))
250  call mem_set_value(ndigits, 'DIGITS', this%input_mempath, &
251  found_format(3))
252  call mem_set_value(prnfmt, 'FORMAT', this%input_mempath, &
253  found_format(4))
254  call mem_set_value(budgetcsv, 'BUDGETCSVFILE', this%input_mempath, &
255  found_budcsv)
256  call mem_set_value(budgetfn, 'BUDGETFILE', this%input_mempath, &
257  found_budget)
258 
259  if (found_budcsv) then
260  this%ibudcsv = getunit()
261  call openfile(this%ibudcsv, this%iout, budgetcsv, 'CSV', &
262  filstat_opt='REPLACE')
263  end if
264 
265  if (found_budget) then
266  call this%set_ocfile('BUDGET', budgetfn, this%iout)
267  end if
268 
269  if (found_format(1) .and. &
270  found_format(2) .and. &
271  found_format(3) .and. &
272  found_format(4)) then
273  write (print_format, '(a,i0,a,i0,a,i0,a)') 'COLUMNS ', columns, &
274  ' WIDTH ', width, ' DIGITS ', ndigits, ' '//trim(prnfmt)//' '
275  do ipos = 1, size(this%ocds)
276  ocdobjptr => this%ocds(ipos)
277  if (ocdobjptr%cname /= 'BUDGET') then
278  call ocdobjptr%set_prnfmt(print_format, 0)
279  end if
280  end do
281  end if
282 
283  deallocate (columns)
284  deallocate (width)
285  deallocate (ndigits)
286  end subroutine source_options
287 
288  subroutine set_ocfile(this, cname, ocfile, iout)
289  ! modules
291  ! dummy
292  class(outputcontroltype) :: this !< OutputControlDataType object
293  character(len=*), intent(in) :: cname !< data object cname
294  character(len=*), intent(in) :: ocfile !< OC output filename
295  integer(I4B), intent(in) :: iout !< Unit number for output
296  type(outputcontroldatatype), pointer :: ocdobjptr
297  integer(I4B) :: ipos
298  logical(LGP) :: found
299  found = .false.
300  do ipos = 1, size(this%ocds)
301  ocdobjptr => this%ocds(ipos)
302  if (cname == trim(ocdobjptr%cname)) then
303  found = .true.
304  call ocdobjptr%set_ocfile(ocfile, iout)
305  end if
306  end do
307  if (.not. found) then
308  call store_error('OC internal error: oc data type not found for name "'// &
309  trim(cname)//'".')
310  call store_error_filename(this%input_fname)
311  end if
312  end subroutine set_ocfile
313 
314  !> @ brief Determine if it is time to save.
315  logical function oc_save(this, cname)
316  ! modules
317  use tdismodule, only: kstp, endofperiod
318  ! dummy
319  class(outputcontroltype) :: this !< OutputControlType object
320  character(len=*), intent(in) :: cname !< character string for data name
321  ! local
322  integer(I4B) :: ipos
323  logical(LGP) :: found
324  class(outputcontroldatatype), pointer :: ocdobjptr
325  !
326  oc_save = .false.
327  found = .false.
328  do ipos = 1, size(this%ocds)
329  ocdobjptr => this%ocds(ipos)
330  if (cname == trim(ocdobjptr%cname)) then
331  found = .true.
332  exit
333  end if
334  end do
335  if (found) then
336  oc_save = ocdobjptr%psm%should_save(kstp, endofperiod)
337  end if
338  end function oc_save
339 
340  !> @ brief Determine if it is time to print.
341  logical function oc_print(this, cname)
342  ! modules
343  use tdismodule, only: kstp, endofperiod
344  ! dummy
345  class(outputcontroltype) :: this !< OutputControlType object
346  character(len=*), intent(in) :: cname !< character string for data name
347  ! local
348  integer(I4B) :: ipos
349  logical(LGP) :: found
350  class(outputcontroldatatype), pointer :: ocdobjptr
351 
352  oc_print = .false.
353  found = .false.
354  do ipos = 1, size(this%ocds)
355  ocdobjptr => this%ocds(ipos)
356  if (cname == trim(ocdobjptr%cname)) then
357  found = .true.
358  exit
359  end if
360  end do
361  if (found) then
362  oc_print = ocdobjptr%psm%should_print(kstp, endofperiod)
363  end if
364  end function oc_print
365 
366  !> @ brief Determine unit number for saving
367  function oc_save_unit(this, cname)
368  ! -- modules
369  ! -- return
370  integer(I4B) :: oc_save_unit
371  ! -- dummy
372  class(outputcontroltype) :: this !< OutputControlType object
373  character(len=*), intent(in) :: cname !< character string for data name
374  ! -- local
375  integer(I4B) :: ipos
376  logical(LGP) :: found
377  class(outputcontroldatatype), pointer :: ocdobjptr
378  !
379  oc_save_unit = 0
380  found = .false.
381  do ipos = 1, size(this%ocds)
382  ocdobjptr => this%ocds(ipos)
383  if (cname == trim(ocdobjptr%cname)) then
384  found = .true.
385  exit
386  end if
387  end do
388  if (found) then
389  oc_save_unit = ocdobjptr%idataun
390  end if
391  end function oc_save_unit
392 
393  !> @ brief Set the print flag based on convergence and other parameters
394  function set_print_flag(this, cname, icnvg, endofperiod) result(iprint_flag)
395  ! -- modules
397  ! -- return
398  integer(I4B) :: iprint_flag
399  ! -- dummy
400  class(outputcontroltype) :: this !< OutputControlType object
401  character(len=*), intent(in) :: cname !< character string for data name
402  integer(I4B), intent(in) :: icnvg !< convergence flag
403  logical, intent(in) :: endofperiod !< end of period logical flag
404  ! -- local
405  !
406  ! -- default is to not print
407  iprint_flag = 0
408  !
409  ! -- if the output control file indicates that cname should be printed
410  if (this%oc_print(cname)) iprint_flag = 1
411  !
412  ! -- if it is not a CONTINUE run, then set to print if not converged
413  if (isimcontinue == 0) then
414  if (icnvg == 0) iprint_flag = 1
415  end if
416  !
417  ! -- if it's the end of the period, then set flag to print
418  if (endofperiod) iprint_flag = 1
419  end function set_print_flag
420 
421 end module outputcontrolmodule
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition: Constants.f90:22
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
Output control data module.
subroutine, public ocd_cr(ocdobj)
@ brief Create a new output control data type.
Model output control.
subroutine allocate(this, name_model, input_mempath)
@ brief Allocate variables for the output control object
subroutine source_options(this)
@ brief Read the output control options block
subroutine set_ocfile(this, cname, ocfile, iout)
subroutine oc_rp(this)
@ brief Read period block options and prepare the output control type.
logical function oc_save(this, cname)
@ brief Determine if it is time to save.
logical function oc_print(this, cname)
@ brief Determine if it is time to print.
subroutine oc_df(this)
@ brief Define the output control type. Placeholder routine.
integer(i4b) function set_print_flag(this, cname, icnvg, endofperiod)
@ brief Set the print flag based on convergence and other parameters
subroutine, public oc_cr(oc, name_model, input_mempath, inunit, iout)
Create a new output control object.
integer(i4b) function oc_save_unit(this, cname)
@ brief Determine unit number for saving
subroutine oc_ot(this, ipflg)
@ brief Write output.
subroutine oc_da(this)
@ brief Deallocate method for OutputControlType
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
integer(i4b) isimcontinue
simulation continue flag (1) to continue if isimcnvg = 0, (0) to terminate
logical(lgp), pointer, public endofperiod
flag indicating end of stress period
Definition: tdis.f90:27
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:24
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:23
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
@ brief Controls model output. Overridden for each model type.