MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
IdmMf6File.f90
Go to the documentation of this file.
1 !> @brief This module contains the IdmMf6FileModule
2 !!
3 !! This module contains high-level routines for loading
4 !! MODFLOW 6 ASCII source input. This module implements the
5 !! loader types that the IdmLoadModule creates and invokes.
6 !! It also creates and manages dynamic ASCII input loaders
7 !! for all supported types of MODFLOW 6 ASCII dynamic input.
8 !!
9 !<
11 
12  use kindmodule, only: dp, i4b, lgp
13  use simvariablesmodule, only: errmsg
14  use constantsmodule, only: linelength
21 
22  implicit none
23  private
24  public :: input_load
26  public :: open_mf6file
27 
28  !> @brief MF6File static loader type
29  !<
31  contains
32  procedure :: init => static_init
33  procedure :: load => static_load
34  procedure :: destroy => static_destroy
36 
37  !> @brief MF6File dynamic loader type
38  !<
40  type(blockparsertype), pointer :: parser !< parser for MF6File period blocks
41  integer(I4B), pointer :: iper => null() !< memory managed variable, loader iper
42  integer(I4B), pointer :: ionper => null() !< memory managed variable, next load period
43  class(asciidynamicpkgloadbasetype), pointer :: rp_loader => null()
44  contains
45  procedure :: init => dynamic_init
46  procedure :: df => dynamic_df
47  procedure :: ad => dynamic_ad
48  procedure :: rp => dynamic_rp
49  procedure :: read_ionper => dynamic_read_ionper
50  procedure :: create_loader => dynamic_create_loader
51  procedure :: destroy => dynamic_destroy
53 
54 contains
55 
56  !> @brief input load for traditional mf6 simulation static input file
57  !<
58  subroutine input_load(filename, mf6_input, component_filename, iout, nc_vars)
60  character(len=*), intent(in) :: filename
61  type(modflowinputtype), intent(in) :: mf6_input
62  character(len=*), intent(in) :: component_filename !< component (e.g. model) filename
63  integer(I4B), intent(in) :: iout !< unit number for output
64  type(ncpackagevarstype), pointer, optional, intent(in) :: nc_vars
65  type(blockparsertype), allocatable, target :: parser !< block parser
66  type(ncpackagevarstype), pointer :: netcdf_vars
67  type(loadmf6filetype) :: loader
68  integer(I4B) :: inunit
69 
70  if (present(nc_vars)) then
71  netcdf_vars => nc_vars
72  else
73  nullify (netcdf_vars)
74  end if
75 
76  ! open input file
77  inunit = open_mf6file(mf6_input%pkgtype, filename, component_filename, iout)
78 
79  ! allocate and initialize parser
80  allocate (parser)
81  call parser%Initialize(inunit, iout)
82 
83  ! invoke the load routine
84  call loader%load(parser, mf6_input, netcdf_vars, filename, iout)
85 
86  ! clear parser file handles
87  call parser%clear()
88 
89  ! cleanup
90  deallocate (parser)
91  end subroutine input_load
92 
93  !> @brief static loader init
94  !<
95  subroutine static_init(this, mf6_input, component_name, component_input_name, &
96  input_name)
97  class(mf6filestaticpkgloadtype), intent(inout) :: this
98  type(modflowinputtype), intent(in) :: mf6_input
99  character(len=*), intent(in) :: component_name
100  character(len=*), intent(in) :: component_input_name
101  character(len=*), intent(in) :: input_name
102  ! initialize base type
103  call this%StaticPkgLoadType%init(mf6_input, component_name, &
104  component_input_name, input_name)
105  end subroutine static_init
106 
107  !> @brief load routine for static loader
108  !<
109  function static_load(this, iout) result(rp_loader)
110  class(mf6filestaticpkgloadtype), intent(inout) :: this
111  integer(I4B), intent(in) :: iout
112  class(dynamicpkgloadbasetype), pointer :: rp_loader
113  class(mf6filedynamicpkgloadtype), pointer :: mf6_loader
114 
115  ! initialize return pointer
116  nullify (rp_loader)
117 
118  ! load model package to input context
119  if (this%iperblock > 0) then
120  ! allocate dynamic loader
121  allocate (mf6_loader)
122  ! point to nc_vars structure
123  mf6_loader%nc_vars => this%nc_vars
124  ! nullify nc_vars pointer so it isn't deallocated
125  nullify (this%nc_vars)
126  ! initialize dynamic loader
127  call mf6_loader%init(this%mf6_input, this%component_name, &
128  this%component_input_name, this%input_name, &
129  this%iperblock, iout)
130  ! set return pointer to base dynamic loader
131  rp_loader => mf6_loader
132  else
133  ! load static input
134  call input_load(this%input_name, this%mf6_input, &
135  this%component_input_name, iout, this%nc_vars)
136  end if
137  end function static_load
138 
139  !> @brief static loader destroy
140  !<
141  subroutine static_destroy(this)
142  class(mf6filestaticpkgloadtype), intent(inout) :: this
143  ! deallocate base type
144  call this%StaticPkgLoadType%destroy()
145  end subroutine static_destroy
146 
147  !> @brief dynamic loader init
148  !<
149  subroutine dynamic_init(this, mf6_input, component_name, component_input_name, &
150  input_name, iperblock, iout)
153  class(mf6filedynamicpkgloadtype), intent(inout) :: this
154  type(modflowinputtype), intent(in) :: mf6_input
155  character(len=*), intent(in) :: component_name
156  character(len=*), intent(in) :: component_input_name
157  character(len=*), intent(in) :: input_name
158  integer(I4B), intent(in) :: iperblock
159  integer(I4B), intent(in) :: iout
160  integer(I4B) :: inunit
161 
162  ! initialize base loader
163  call this%DynamicPkgLoadType%init(mf6_input, component_name, &
164  component_input_name, input_name, &
165  iperblock, iout)
166  ! allocate scalars
167  call mem_allocate(this%iper, 'IPER', mf6_input%mempath)
168  call mem_allocate(this%ionper, 'IONPER', mf6_input%mempath)
169 
170  ! initialize
171  this%iper = 0
172  this%ionper = 0
173 
174  ! open input file
175  inunit = open_mf6file(mf6_input%pkgtype, input_name, &
176  component_input_name, iout)
177 
178  ! allocate and initialize parser
179  allocate (this%parser)
180  call this%parser%Initialize(inunit, iout)
181 
182  ! allocate and initialize loader
183  call this%create_loader()
184  end subroutine dynamic_init
185 
186  !> @brief define routine for dynamic loader
187  !<
188  subroutine dynamic_df(this)
189  class(mf6filedynamicpkgloadtype), intent(inout) :: this
190  ! invoke loader define
191  call this%rp_loader%df()
192  ! read first ionper
193  call this%read_ionper()
194  end subroutine dynamic_df
195 
196  !> @brief advance routine for dynamic loader
197  !<
198  subroutine dynamic_ad(this)
199  class(mf6filedynamicpkgloadtype), intent(inout) :: this
200  ! invoke loader advance
201  call this%rp_loader%ad()
202  end subroutine dynamic_ad
203 
204  !> @brief read and prepare routine for dynamic loader
205  !<
206  subroutine dynamic_rp(this)
207  use tdismodule, only: kper, nper
208  class(mf6filedynamicpkgloadtype), intent(inout) :: this
209 
210  ! check if ready to load
211  if (this%ionper /= kper) return
212 
213  ! dynamic load
214  call this%rp_loader%rp(this%parser)
215 
216  ! update loaded iper
217  this%iper = kper
218 
219  ! read next iper
220  if (kper < nper) then
221  call this%read_ionper()
222  else
223  this%ionper = nper + 1
224  end if
225  end subroutine dynamic_rp
226 
227  !> @brief dynamic loader read ionper of next period block
228  !<
229  subroutine dynamic_read_ionper(this)
230  use tdismodule, only: kper, nper
231  class(mf6filedynamicpkgloadtype), intent(inout) :: this
232  character(len=LINELENGTH) :: line
233  logical(LGP) :: isblockfound
234  integer(I4B) :: ierr
235  character(len=*), parameter :: fmtblkerr = &
236  &"('Looking for BEGIN PERIOD iper. Found ', a, ' instead.')"
237 
238  call this%parser%GetBlock('PERIOD', isblockfound, ierr, &
239  supportopenclose=.true., &
240  blockrequired=.false.)
241  ! set first period block IPER
242  if (isblockfound) then
243  this%ionper = this%parser%GetInteger()
244  if (this%ionper <= this%iper) then
245  write (errmsg, '(a, i0, a, i0, a, i0, a)') &
246  'Error in stress period ', kper, &
247  '. Period numbers not increasing. Found ', this%ionper, &
248  ' but last period block was assigned ', this%iper, '.'
249  call store_error(errmsg)
250  call this%parser%StoreErrorUnit()
251  end if
252  else
253  ! PERIOD block not found
254  if (ierr < 0) then
255  ! End of file found; data applies for remainder of simulation.
256  this%ionper = nper + 1
257  else
258  ! Found invalid block
259  call this%parser%GetCurrentLine(line)
260  write (errmsg, fmtblkerr) adjustl(trim(line))
261  call store_error(errmsg)
262  call this%parser%StoreErrorUnit()
263  end if
264  end if
265  end subroutine dynamic_read_ionper
266 
267  !> @brief allocate a dynamic loader based on load context
268  !<
269  subroutine dynamic_create_loader(this)
272  use listloadmodule, only: listloadtype
276  class(mf6filedynamicpkgloadtype), intent(inout) :: this
277  class(listloadtype), pointer :: list_loader
278  class(gridarrayloadtype), pointer :: arrgrid_loader
279  class(layerarrayloadtype), pointer :: arrlayer_loader
280  class(settingloadtype), pointer :: setting_loader
281  class(stoinputtype), pointer :: sto_loader
282 
283  ! allocate and set loader
284  if (this%mf6_input%subcomponent_type == 'STO') then
285  allocate (sto_loader)
286  this%rp_loader => sto_loader
287  else if (this%has_setting) then
288  allocate (setting_loader)
289  this%rp_loader => setting_loader
290  else if (this%readasarrays) then
291  allocate (arrlayer_loader)
292  this%rp_loader => arrlayer_loader
293  else if (this%readarraygrid) then
294  call developmode('Input file "'//trim(this%input_name)// &
295  '" READARRAYGRID option is still under development, install the &
296  &nightly build or compile from source with IDEVELOPMODE = 1.', &
297  this%iout)
298  allocate (arrgrid_loader)
299  this%rp_loader => arrgrid_loader
300  else
301  allocate (list_loader)
302  this%rp_loader => list_loader
303  end if
304 
305  ! set nc_vars pointer
306  this%rp_loader%nc_vars => this%nc_vars
307 
308  ! initialize loader
309  call this%rp_loader%ainit(this%mf6_input, &
310  this%component_name, &
311  this%component_input_name, &
312  this%input_name, &
313  this%iperblock, &
314  this%parser, &
315  this%iout)
316  end subroutine dynamic_create_loader
317 
318  !> @brief dynamic loader destroy
319  !<
320  subroutine dynamic_destroy(this)
322  class(mf6filedynamicpkgloadtype), intent(inout) :: this
323 
324  ! deallocate scalars
325  call mem_deallocate(this%iper)
326  call mem_deallocate(this%ionper)
327 
328  ! deallocate loader
329  nullify (this%rp_loader%nc_vars)
330  call this%rp_loader%destroy()
331  deallocate (this%rp_loader)
332 
333  ! deallocate parser
334  call this%parser%clear()
335  deallocate (this%parser)
336 
337  ! deallocate input context
338  call this%DynamicPkgLoadType%destroy()
339  end subroutine dynamic_destroy
340 
341  !> @brief open a model package files
342  !<
343  function open_mf6file(filetype, filename, component_fname, iout) result(inunit)
345  character(len=*), intent(in) :: filetype
346  character(len=*), intent(in) :: filename
347  character(len=*), intent(in) :: component_fname
348  integer(I4B), intent(in) :: iout
349  integer(I4B) :: inunit
350 
351  ! initialize
352  inunit = 0
353 
354  if (filename /= '') then
355  ! get unit number and open file
356  inunit = getunit()
357  call openfile(inunit, iout, trim(adjustl(filename)), filetype, &
358  'FORMATTED', 'SEQUENTIAL', 'OLD')
359  else
360  write (errmsg, '(a,a,a)') &
361  'File unspecified, cannot load model or package &
362  &type "', trim(filetype), '".'
363  call store_error(errmsg)
364  call store_error_filename(component_fname)
365  end if
366  end function open_mf6file
367 
368 end module idmmf6filemodule
subroutine init()
Definition: GridSorting.f90:25
This module contains the AsciiInputLoadTypeModule.
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
Disable development features in release mode.
Definition: FeatureFlags.f90:2
subroutine, public developmode(errmsg, iunit)
Terminate if in release mode (guard development features)
This module contains the GridArrayLoadModule.
This module contains the IdmMf6FileModule.
Definition: IdmMf6File.f90:10
subroutine dynamic_df(this)
define routine for dynamic loader
Definition: IdmMf6File.f90:189
integer(i4b) function, public open_mf6file(filetype, filename, component_fname, iout)
open a model package files
Definition: IdmMf6File.f90:344
subroutine dynamic_create_loader(this)
allocate a dynamic loader based on load context
Definition: IdmMf6File.f90:270
subroutine dynamic_destroy(this)
dynamic loader destroy
Definition: IdmMf6File.f90:321
subroutine dynamic_init(this, mf6_input, component_name, component_input_name, input_name, iperblock, iout)
dynamic loader init
Definition: IdmMf6File.f90:151
subroutine, public input_load(filename, mf6_input, component_filename, iout, nc_vars)
input load for traditional mf6 simulation static input file
Definition: IdmMf6File.f90:59
subroutine dynamic_ad(this)
advance routine for dynamic loader
Definition: IdmMf6File.f90:199
subroutine static_destroy(this)
static loader destroy
Definition: IdmMf6File.f90:142
subroutine dynamic_rp(this)
read and prepare routine for dynamic loader
Definition: IdmMf6File.f90:207
subroutine static_init(this, mf6_input, component_name, component_input_name, input_name)
static loader init
Definition: IdmMf6File.f90:97
subroutine dynamic_read_ionper(this)
dynamic loader read ionper of next period block
Definition: IdmMf6File.f90:230
class(dynamicpkgloadbasetype) function, pointer static_load(this, iout)
load routine for static loader
Definition: IdmMf6File.f90:110
Input definition module.
This module contains the InputLoadTypeModule.
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
This module contains the LayerArrayLoadModule.
This module contains the ListLoadModule.
Definition: Mf6FileList.f90:7
This module contains the LoadMf6FileModule.
Definition: LoadMf6File.f90:8
This module contains the Mf6FileSettingLoadModule.
This module contains the Mf6FileStoInputModule.
This module contains the ModflowInputModule.
Definition: ModflowInput.f90:9
This module contains the NCFileVarsModule.
Definition: NCFileVars.f90:7
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), pointer, public kper
current stress period number
Definition: tdis.f90:23
integer(i4b), pointer, public nper
number of stress period
Definition: tdis.f90:21
base abstract type for ascii source dynamic load
Ascii grid based dynamic loader type.
MF6File dynamic loader type.
Definition: IdmMf6File.f90:39
Input parameter definition. Describes an input parameter.
Base abstract type for dynamic input loader.
Base abstract type for static input loader.
Ascii array layer dynamic loader type.
list input loader for dynamic packages.
Definition: Mf6FileList.f90:30
Static parser based input loader.
Definition: LoadMf6File.f90:47
derived type for storing input definition for a file
Type describing input variables for a package in NetCDF file.
Definition: NCFileVars.f90:22