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, has_dis
281 
282  ! allocate
283  allocate (cunit_idxs(0))
284  has_dis = .false.
285 
286  ! identify input packages and check that each is supported
287  do n = 1, size(ftypes)
288  ! type from model nam file packages block
289  ftype = ftypes(n)
290  found = .false.
291 
292  ! check for discretization package (any type starting with 'DIS')
293  if (ftype(1:3) == 'DIS') has_dis = .true.
294 
295  ! search supported types for this filetype
296  do m = 1, this%niunit
297  if (this%cunit(m) == ftype) then
298  ! set found
299  found = .true.
300 
301  ! add to cunit list if first instance of this type
302  if (any(cunit_idxs == m)) then
303  ! no-op
304  else
305  call expandarray(cunit_idxs)
306  cunit_idxs(size(cunit_idxs)) = m
307  end if
308 
309  ! exit search
310  exit
311  end if
312  end do
313 
314  ! set error if namfile pkg filetype is not supported
315  if (.not. found) then
316  write (errmsg, '(a,a,a,a,a)') 'Model package type not supported &
317  &[model=', trim(this%modelname), ', type=', &
318  trim(ftype), '].'
319  call store_error(errmsg)
320  call store_error_filename(this%modelfname)
321  end if
322  end do
323 
324  ! check that a discretization package is specified
325  if (.not. has_dis) then
326  write (errmsg, '(3a)') &
327  'Discretization package not specified for model "', &
328  trim(this%modelname), '".'
329  call store_error(errmsg)
330  call store_error_filename(this%modelfname)
331  end if
332 
333  ! allocate the pkglist
334  allocate (this%pkglist(size(cunit_idxs)))
335 
336  ! sort cunit indexes
337  allocate (indx(size(cunit_idxs)))
338  call qsort(indx, cunit_idxs)
339 
340  ! create sorted LoadablePackageType object list
341  do n = 1, size(cunit_idxs)
342  call this%pkglist(n)%create(this%modeltype, this%modelname, &
343  this%cunit(cunit_idxs(n)))
344  end do
345 
346  ! cleanup
347  deallocate (cunit_idxs)
348  deallocate (indx)
349  end subroutine modelpkgs_create
350 
351  !> @brief add a model package instance to package type list
352  !<
353  subroutine modelpkgs_add(this, pkgtype, filename, pkgname)
354  class(modelpackageinputstype) :: this
355  character(len=*), intent(in) :: pkgtype
356  character(len=*), intent(in) :: filename
357  character(len=*), intent(in) :: pkgname
358  type(loadablepackagetype) :: pkg
359  integer(I4B) :: n
360  ! locate index of pkgtype in pkglist
361  do n = 1, size(this%pkglist)
362  pkg = this%pkglist(n)
363  if (pkg%pkgtype == pkgtype) then
364  call this%pkglist(n)%add(this%modelname, this%component_type, &
365  pkgtype, filename, pkgname, this%iout)
366  exit
367  end if
368  end do
369  end subroutine modelpkgs_add
370 
371  !> @brief build the type list with all model package instances
372  !<
373  subroutine modelpkgs_addpkgs(this)
376  class(modelpackageinputstype) :: this
377  type(characterstringtype), dimension(:), contiguous, &
378  pointer :: ftypes !< file types
379  type(characterstringtype), dimension(:), contiguous, &
380  pointer :: fnames !< file names
381  type(characterstringtype), dimension(:), contiguous, &
382  pointer :: pnames !< package names
383  character(len=LINELENGTH) :: ftype, fname, pname
384  integer(I4B) :: n
385 
386  ! set pointers to input context model package attribute arrays
387  call mem_setptr(ftypes, 'FTYPE', this%input_mempath)
388  call mem_setptr(fnames, 'FNAME', this%input_mempath)
389  call mem_setptr(pnames, 'PNAME', this%input_mempath)
390 
391  ! create the package list
392  call this%create(ftypes)
393 
394  ! load model packages
395  do n = 1, size(ftypes)
396  ! attributes for this package
397  ftype = ftypes(n)
398  fname = fnames(n)
399  call inlen_check(pnames(n), pname, lenpackagename, 'PACKAGENAME')
400 
401  ! add this instance to package list
402  call this%add(ftype, fname, pname)
403  end do
404 
405  ! terminate if errors were detected
406  if (count_errors() > 0) then
407  call store_error_filename(this%modelfname)
408  end if
409  end subroutine modelpkgs_addpkgs
410 
411  !> @brief get package instance count and verify base or multi of each
412  !<
413  function modelpkgs_pkgcount(this) result(pnum)
414  class(modelpackageinputstype) :: this
415  integer(I4B) :: pnum
416  integer(I4B) :: n
417 
418  ! initialize
419  pnum = 0
420 
421  ! count model package instances
422  do n = 1, size(this%pkglist)
423  if (multi_pkg_type(this%component_type, &
424  this%pkglist(n)%subcomponent_type, &
425  this%pkglist(n)%pkgtype)) then
426  ! multiple instances ok
427  else
428  ! set error for unexpected extra packages
429  if (this%pkglist(n)%pnum > 1) then
430  write (errmsg, '(a,a,a,a,a)') &
431  'Multiple instances specified for model base package type &
432  &[model=', trim(this%modelname), ', type=', &
433  trim(this%pkglist(n)%pkgtype), '].'
434  call store_error(errmsg)
435  call store_error_filename(this%modelfname)
436  end if
437  end if
438 
439  ! add to package count
440  pnum = pnum + this%pkglist(n)%pnum
441  end do
442  end function modelpkgs_pkgcount
443 
444  !> @brief load package descriptors to managed memory
445  !<
446  subroutine modelpkgs_memload(this)
448  class(modelpackageinputstype) :: this
449  integer(I4B) :: n, m, idx
450  integer(I4B) :: pnum
451 
452  ! initialize load index
453  idx = 0
454 
455  ! set total number of package instances
456  pnum = this%pkgcount()
457 
458  ! reallocate model input package attribute arrays
459  call mem_reallocate(this%pkgtypes, lenpackagetype, pnum, 'PKGTYPES', &
460  this%model_mempath)
461  call mem_reallocate(this%pkgnames, lenpackagename, pnum, 'PKGNAMES', &
462  this%model_mempath)
463  call mem_reallocate(this%mempaths, lenmempath, pnum, 'MEMPATHS', &
464  this%model_mempath)
465  call mem_reallocate(this%inunits, pnum, 'INUNITS', this%model_mempath)
466 
467  ! load pkinfo
468  do n = 1, size(this%pkglist)
469  do m = 1, this%pkglist(n)%pnum
470  ! increment index
471  idx = idx + 1
472  ! package type like 'CHD6'
473  this%pkgtypes(idx) = trim(this%pkglist(n)%pkgtype)
474  ! package name like 'CHD-2'
475  this%pkgnames(idx) = trim(this%pkglist(n)%pkgnames(m))
476  ! memory path like '__INPUT__/MYMODEL/CHD-2'
477  this%mempaths(idx) = trim(this%pkglist(n)%mempaths(m))
478  ! input file unit number
479  this%inunits(idx) = this%pkglist(n)%inunits(m)
480  end do
481  end do
482  end subroutine modelpkgs_memload
483 
484  !> @brief deallocate object
485  !<
486  subroutine modelpkgs_destroy(this)
487  class(modelpackageinputstype) :: this
488  integer(I4B) :: n
489  do n = 1, size(this%pkglist)
490  call this%pkglist(n)%destroy()
491  end do
492  deallocate (this%pkglist)
493  deallocate (this%cunit)
494  end subroutine modelpkgs_destroy
495 
496 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