MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
ModelPackageInputs.f90
Go to the documentation of this file.
1 !> @brief This module contains the ModelPackageInputsModule
2 !!
3 !! This module contains the high-level routines for assembling
4 !! model package information and loading to the input context
5 !!
6 !<
8 
9  use kindmodule, only: dp, i4b, lgp
10  use simvariablesmodule, only: errmsg
14  use simvariablesmodule, only: iout
17 
18  implicit none
19  private
20  public :: modelpackageinputstype
21  public :: supported_model
22 
23  !> @brief derived type for loadable package type
24  !!
25  !! This derived type is used to store package instance
26  !! descriptions for a supported package type.
27  !!
28  !<
30  ! package type, e.g. 'DIS6' or 'CHD6'
31  character(len=LENPACKAGETYPE) :: pkgtype
32  ! component type, e.g. 'DIS' or 'CHD'
33  character(len=LENCOMPONENTNAME) :: subcomponent_type
34  ! package instance attribute arrays
35  character(len=LINELENGTH), dimension(:), allocatable :: filenames
36  character(len=LENPACKAGENAME), dimension(:), allocatable :: pkgnames
37  character(len=LENMEMPATH), dimension(:), allocatable :: mempaths
38  integer(I4B), dimension(:), allocatable :: inunits
39  ! number of package instances
40  integer(I4B) :: pnum
41  contains
42  procedure :: create => pkgtype_create
43  procedure :: add => pkgtype_add
44  procedure :: destroy => pkgtype_destroy
45  end type loadablepackagetype
46 
47  !> @brief derived type for model package inputs type
48  !!
49  !! This derived type is used to define input package
50  !! descriptors for a model and load to managed memory.
51  !!
52  !<
54  ! model attributes
55  character(len=LENPACKAGETYPE) :: modeltype ! model type, e.g. 'GWF6'
56  character(len=LINELENGTH) :: modelfname
57  character(len=LENMODELNAME) :: modelname
58  ! component type
59  character(len=LENCOMPONENTNAME) :: component_type ! e.g. 'GWF'
60  ! mempaths
61  character(len=LENMEMPATH) :: input_mempath
62  character(len=LENMEMPATH) :: model_mempath
63  ! pointers to created managed memory
64  type(characterstringtype), dimension(:), contiguous, &
65  pointer :: pkgtypes => null()
66  type(characterstringtype), dimension(:), contiguous, &
67  pointer :: pkgnames => null()
68  type(characterstringtype), dimension(:), contiguous, &
69  pointer :: mempaths => null()
70  integer(I4B), dimension(:), contiguous, &
71  pointer :: inunits => null()
72  ! loadable package type array
73  type(loadablepackagetype), dimension(:), allocatable :: pkglist
74  ! pkgtype definitions
75  integer(I4B) :: niunit
76  character(len=LENPACKAGETYPE), dimension(:), allocatable :: cunit
77  ! out handle
78  integer(I4B) :: iout
79  contains
80  procedure :: init => modelpkgs_init
81  procedure :: memload => modelpkgs_memload
82  procedure :: destroy => modelpkgs_destroy
83  procedure, private :: create => modelpkgs_create
84  procedure, private :: addpkgs => modelpkgs_addpkgs
85  procedure, private :: add => modelpkgs_add
86  procedure, private :: pkgcount => modelpkgs_pkgcount
87  end type modelpackageinputstype
88 
89 contains
90 
91  !> @brief does model support multiple instances of this package type
92  !<
93  function multi_pkg_type(mtype_component, ptype_component, pkgtype) &
94  result(multi_pkg)
97  character(len=LENCOMPONENTNAME), intent(in) :: mtype_component
98  character(len=LENCOMPONENTNAME), intent(in) :: ptype_component
99  character(len=LENFTYPE), intent(in) :: pkgtype
100  logical(LGP) :: multi_pkg
101  multi_pkg = .false.
102  if (idm_integrated(mtype_component, ptype_component)) then
103  multi_pkg = idm_multi_package(mtype_component, ptype_component)
104  else
105  multi_pkg = multi_package_type(mtype_component, ptype_component, pkgtype)
106  end if
107  end function multi_pkg_type
108 
109  !> @brief is this a supported MODFLOW 6 model type
110  !<
111  function supported_model(ctype)
113  character(len=*), intent(in) :: ctype
114  logical(LGP) :: supported_model
115  integer(I4B) :: n
116  supported_model = .false.
117  do n = 1, nmodel
118  if (ctype == modflow6models(n)) then
119  supported_model = .true.
120  exit
121  end if
122  end do
123  end function supported_model
124 
125  !> @brief create a new package type
126  !<
127  subroutine pkgtype_create(this, modeltype, modelname, pkgtype)
129  class(loadablepackagetype) :: this
130  character(len=*), intent(in) :: modeltype
131  character(len=*), intent(in) :: modelname
132  character(len=*), intent(in) :: pkgtype
133 
134  ! initialize
135  this%pkgtype = pkgtype
136  this%subcomponent_type = idm_subcomponent_type(modeltype, pkgtype)
137  this%pnum = 0
138 
139  ! allocate arrays
140  allocate (this%filenames(0))
141  allocate (this%pkgnames(0))
142  allocate (this%mempaths(0))
143  allocate (this%inunits(0))
144  end subroutine pkgtype_create
145 
146  !> @brief add a new package instance to this package type
147  !<
148  subroutine pkgtype_add(this, modelname, mtype_component, filetype, &
149  filename, pkgname, iout)
155  class(loadablepackagetype) :: this
156  character(len=*), intent(in) :: modelname
157  character(len=*), intent(in) :: mtype_component
158  character(len=*), intent(in) :: filetype
159  character(len=*), intent(in) :: filename
160  character(len=*), intent(in) :: pkgname
161  integer(I4B), intent(in) :: iout
162  character(len=LENPACKAGENAME) :: sc_name, pname
163  character(len=LENMEMPATH) :: mempath
164  character(len=LINELENGTH), pointer :: cstr
165 
166  ! reallocate
167  call expandarray(this%filenames)
168  call expandarray(this%pkgnames)
169  call expandarray(this%inunits)
170  call expandarray(this%mempaths)
171 
172  ! add new package instance
173  this%pnum = this%pnum + 1
174  this%filenames(this%pnum) = filename
175  this%pkgnames(this%pnum) = pkgname
176  this%inunits(this%pnum) = 0
177 
178  ! set pkgname if empty
179  if (this%pkgnames(this%pnum) == '') then
180  if (multi_pkg_type(mtype_component, &
181  this%subcomponent_type, &
182  filetype)) then
183  pname = idm_pkg_instance_name(this%subcomponent_type, &
184  this%pnum)
185  else
186  write (pname, '(a)') trim(this%subcomponent_type)
187  end if
188  this%pkgnames(this%pnum) = pname
189  end if
190 
191  ! set up input context for model
192  if (idm_integrated(mtype_component, this%subcomponent_type)) then
193  ! set subcomponent name
194  sc_name = idm_subcomponent_name(mtype_component, this%subcomponent_type, &
195  this%pkgnames(this%pnum))
196  ! create and store the mempath
197  this%mempaths(this%pnum) = &
198  create_mem_path(modelname, sc_name, idm_context)
199  ! allocate and initialize filename for package
200  mempath = create_mem_path(modelname, sc_name, idm_context)
201  call mem_allocate(cstr, linelength, 'INPUT_FNAME', mempath)
202  cstr = filename
203  else
204  ! set mempath empty
205  this%mempaths(this%pnum) = ''
206  end if
207  end subroutine pkgtype_add
208 
209  !> @brief deallocate object
210  !<
211  subroutine pkgtype_destroy(this)
212  class(loadablepackagetype) :: this
213  ! deallocate dynamic arrays
214  deallocate (this%filenames)
215  deallocate (this%pkgnames)
216  deallocate (this%inunits)
217  deallocate (this%mempaths)
218  end subroutine pkgtype_destroy
219 
220  !> @brief initialize model package inputs object
221  !<
222  subroutine modelpkgs_init(this, modeltype, modelfname, modelname, iout)
228  class(modelpackageinputstype) :: this
229  character(len=*), intent(in) :: modeltype
230  character(len=*), intent(in) :: modelfname
231  character(len=*), intent(in) :: modelname
232  integer(I4B), intent(in) :: iout
233 
234  ! initialize object
235  this%modeltype = modeltype
236  this%modelfname = modelfname
237  this%modelname = modelname
238  this%component_type = idm_component_type(modeltype)
239  this%iout = iout
240 
241  ! verify user specified model type
242  if (.not. supported_model(modeltype)) then
243  ! -- error and exit for unsupported model type
244  write (errmsg, '(3a)') 'Models block model type "', trim(modeltype), &
245  '" is not valid.'
246  call store_error(errmsg)
248  end if
249 
250  ! allocate and set model supported package types
251  call supported_model_packages(modeltype, this%cunit, this%niunit)
252 
253  ! set memory paths
254  this%input_mempath = create_mem_path(this%modelname, 'NAM', idm_context)
255  this%model_mempath = create_mem_path(component=this%modelname, &
256  context=idm_context)
257  ! allocate managed memory
258  call mem_allocate(this%pkgtypes, lenpackagetype, 0, 'PKGTYPES', &
259  this%model_mempath)
260  call mem_allocate(this%pkgnames, lenpackagename, 0, 'PKGNAMES', &
261  this%model_mempath)
262  call mem_allocate(this%mempaths, lenmempath, 0, 'MEMPATHS', &
263  this%model_mempath)
264  call mem_allocate(this%inunits, 0, 'INUNITS', this%model_mempath)
265 
266  ! build descriptions of packages
267  call this%addpkgs()
268  end subroutine modelpkgs_init
269 
270  !> @brief create the package type list
271  !<
272  subroutine modelpkgs_create(this, ftypes)
273  use sortmodule, only: qsort
274  class(modelpackageinputstype) :: this
275  type(characterstringtype), dimension(:), contiguous, &
276  pointer :: ftypes
277  integer(I4B), dimension(:), allocatable :: cunit_idxs, indx
278  character(len=LENPACKAGETYPE) :: ftype
279  integer(I4B) :: n, m
280  logical(LGP) :: found
281 
282  ! allocate
283  allocate (cunit_idxs(0))
284 
285  ! identify input packages and check that each is supported
286  do n = 1, size(ftypes)
287  ! type from model nam file packages block
288  ftype = ftypes(n)
289  found = .false.
290 
291  ! search supported types for this filetype
292  do m = 1, this%niunit
293  if (this%cunit(m) == ftype) then
294  ! set found
295  found = .true.
296 
297  ! add to cunit list if first instance of this type
298  if (any(cunit_idxs == m)) then
299  ! no-op
300  else
301  call expandarray(cunit_idxs)
302  cunit_idxs(size(cunit_idxs)) = m
303  end if
304 
305  ! exit search
306  exit
307  end if
308  end do
309 
310  ! set error if namfile pkg filetype is not supported
311  if (.not. found) then
312  write (errmsg, '(a,a,a,a,a)') 'Model package type not supported &
313  &[model=', trim(this%modelname), ', type=', &
314  trim(ftype), '].'
315  call store_error(errmsg)
316  call store_error_filename(this%modelfname)
317  end if
318  end do
319 
320  ! allocate the pkglist
321  allocate (this%pkglist(size(cunit_idxs)))
322 
323  ! sort cunit indexes
324  allocate (indx(size(cunit_idxs)))
325  call qsort(indx, cunit_idxs)
326 
327  ! create sorted LoadablePackageType object list
328  do n = 1, size(cunit_idxs)
329  call this%pkglist(n)%create(this%modeltype, this%modelname, &
330  this%cunit(cunit_idxs(n)))
331  end do
332 
333  ! cleanup
334  deallocate (cunit_idxs)
335  deallocate (indx)
336  end subroutine modelpkgs_create
337 
338  !> @brief add a model package instance to package type list
339  !<
340  subroutine modelpkgs_add(this, pkgtype, filename, pkgname)
341  class(modelpackageinputstype) :: this
342  character(len=*), intent(in) :: pkgtype
343  character(len=*), intent(in) :: filename
344  character(len=*), intent(in) :: pkgname
345  type(loadablepackagetype) :: pkg
346  integer(I4B) :: n
347  ! locate index of pkgtype in pkglist
348  do n = 1, size(this%pkglist)
349  pkg = this%pkglist(n)
350  if (pkg%pkgtype == pkgtype) then
351  call this%pkglist(n)%add(this%modelname, this%component_type, &
352  pkgtype, filename, pkgname, this%iout)
353  exit
354  end if
355  end do
356  end subroutine modelpkgs_add
357 
358  !> @brief build the type list with all model package instances
359  !<
360  subroutine modelpkgs_addpkgs(this)
363  class(modelpackageinputstype) :: this
364  type(characterstringtype), dimension(:), contiguous, &
365  pointer :: ftypes !< file types
366  type(characterstringtype), dimension(:), contiguous, &
367  pointer :: fnames !< file names
368  type(characterstringtype), dimension(:), contiguous, &
369  pointer :: pnames !< package names
370  character(len=LINELENGTH) :: ftype, fname, pname
371  integer(I4B) :: n
372 
373  ! set pointers to input context model package attribute arrays
374  call mem_setptr(ftypes, 'FTYPE', this%input_mempath)
375  call mem_setptr(fnames, 'FNAME', this%input_mempath)
376  call mem_setptr(pnames, 'PNAME', this%input_mempath)
377 
378  ! create the package list
379  call this%create(ftypes)
380 
381  ! load model packages
382  do n = 1, size(ftypes)
383  ! attributes for this package
384  ftype = ftypes(n)
385  fname = fnames(n)
386  call inlen_check(pnames(n), pname, lenpackagename, 'PACKAGENAME')
387 
388  ! add this instance to package list
389  call this%add(ftype, fname, pname)
390  end do
391 
392  ! terminate if errors were detected
393  if (count_errors() > 0) then
394  call store_error_filename(this%modelfname)
395  end if
396  end subroutine modelpkgs_addpkgs
397 
398  !> @brief get package instance count and verify base or multi of each
399  !<
400  function modelpkgs_pkgcount(this) result(pnum)
401  class(modelpackageinputstype) :: this
402  integer(I4B) :: pnum
403  integer(I4B) :: n
404 
405  ! initialize
406  pnum = 0
407 
408  ! count model package instances
409  do n = 1, size(this%pkglist)
410  if (multi_pkg_type(this%component_type, &
411  this%pkglist(n)%subcomponent_type, &
412  this%pkglist(n)%pkgtype)) then
413  ! multiple instances ok
414  else
415  ! set error for unexpected extra packages
416  if (this%pkglist(n)%pnum > 1) then
417  write (errmsg, '(a,a,a,a,a)') &
418  'Multiple instances specified for model base package type &
419  &[model=', trim(this%modelname), ', type=', &
420  trim(this%pkglist(n)%pkgtype), '].'
421  call store_error(errmsg)
422  call store_error_filename(this%modelfname)
423  end if
424  end if
425 
426  ! add to package count
427  pnum = pnum + this%pkglist(n)%pnum
428  end do
429  end function modelpkgs_pkgcount
430 
431  !> @brief load package descriptors to managed memory
432  !<
433  subroutine modelpkgs_memload(this)
435  class(modelpackageinputstype) :: this
436  integer(I4B) :: n, m, idx
437  integer(I4B) :: pnum
438 
439  ! initialize load index
440  idx = 0
441 
442  ! set total number of package instances
443  pnum = this%pkgcount()
444 
445  ! reallocate model input package attribute arrays
446  call mem_reallocate(this%pkgtypes, lenpackagetype, pnum, 'PKGTYPES', &
447  this%model_mempath)
448  call mem_reallocate(this%pkgnames, lenpackagename, pnum, 'PKGNAMES', &
449  this%model_mempath)
450  call mem_reallocate(this%mempaths, lenmempath, pnum, 'MEMPATHS', &
451  this%model_mempath)
452  call mem_reallocate(this%inunits, pnum, 'INUNITS', this%model_mempath)
453 
454  ! load pkinfo
455  do n = 1, size(this%pkglist)
456  do m = 1, this%pkglist(n)%pnum
457  ! increment index
458  idx = idx + 1
459  ! package type like 'CHD6'
460  this%pkgtypes(idx) = trim(this%pkglist(n)%pkgtype)
461  ! package name like 'CHD-2'
462  this%pkgnames(idx) = trim(this%pkglist(n)%pkgnames(m))
463  ! memory path like '__INPUT__/MYMODEL/CHD-2'
464  this%mempaths(idx) = trim(this%pkglist(n)%mempaths(m))
465  ! input file unit number
466  this%inunits(idx) = this%pkglist(n)%inunits(m)
467  end do
468  end do
469  end subroutine modelpkgs_memload
470 
471  !> @brief deallocate object
472  !<
473  subroutine modelpkgs_destroy(this)
474  class(modelpackageinputstype) :: this
475  integer(I4B) :: n
476  do n = 1, size(this%pkglist)
477  call this%pkglist(n)%destroy()
478  end do
479  deallocate (this%pkglist)
480  deallocate (this%cunit)
481  end subroutine modelpkgs_destroy
482 
483 end module modelpackageinputsmodule
subroutine init()
Definition: GridSorting.f90:25
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 lencomponentname
maximum length of a component name
Definition: Constants.f90:18
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition: Constants.f90:22
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 lenftype
maximum length of a package type (DIS, WEL, OC, etc.)
Definition: Constants.f90:39
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
logical function, public idm_integrated(component, subcomponent)
logical function, public idm_multi_package(component, subcomponent)
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
This module contains the ModelPackageInputModule.
integer(i4b), parameter, public nmodel
Valid simulation model types.
logical(lgp) function, public multi_package_type(mtype_component, ptype_component, pkgtype)
Is the package multi-instance.
subroutine, public supported_model_packages(mtype, pkgtypes, numpkgs)
set supported package types for model
character(len=lenpackagetype), dimension(nmodel), public modflow6models
This module contains the ModelPackageInputsModule.
subroutine modelpkgs_add(this, pkgtype, filename, pkgname)
add a model package instance to package type list
logical(lgp) function, public supported_model(ctype)
is this a supported MODFLOW 6 model type
subroutine modelpkgs_init(this, modeltype, modelfname, modelname, iout)
initialize model package inputs object
subroutine pkgtype_destroy(this)
deallocate object
subroutine pkgtype_create(this, modeltype, modelname, pkgtype)
create a new package type
logical(lgp) function multi_pkg_type(mtype_component, ptype_component, pkgtype)
does model support multiple instances of this package type
subroutine modelpkgs_destroy(this)
deallocate object
subroutine modelpkgs_addpkgs(this)
build the type list with all model package instances
subroutine modelpkgs_memload(this)
load package descriptors to managed memory
subroutine modelpkgs_create(this, ftypes)
create the package type list
subroutine pkgtype_add(this, modelname, mtype_component, filetype, filename, pkgname, iout)
add a new package instance to this package type
integer(i4b) function modelpkgs_pkgcount(this)
get package instance count and verify base or multi of each
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
character(len=linelength) idm_context
integer(i4b) iout
file unit number for simulation output
character(len=linelength) simfile
simulation name file
This module contains the SourceCommonModule.
Definition: SourceCommon.f90:7
character(len=lencomponentname) function, public idm_subcomponent_type(component, subcomponent)
component from package or model type
character(len=lenpackagename) function, public idm_pkg_instance_name(pkg_type, inst)
default name for a multi-package instance
subroutine, public inlen_check(input_name, mf6_name, maxlen, name_type)
store an error for input exceeding internal name length
character(len=lencomponentname) function, public idm_component_type(component)
component from package or model type
character(len=lenpackagename) function, public idm_subcomponent_name(component_type, subcomponent_type, sc_name)
model package subcomponent name
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
derived type for loadable package type
derived type for model package inputs type