MODFLOW 6  version 6.7.0.dev2
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
275  use devfeaturemodule, only: dev_feature
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%mf6_input%subcomponent_type == 'PRP') 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 dev_feature('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:24
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: DevFeature.f90:2
subroutine, public dev_feature(errmsg, iunit)
Terminate if in release mode (guard development features)
Definition: DevFeature.f90:21
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
This module contains the InputDefinitionModule.
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
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