MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
LoadMf6File.f90
Go to the documentation of this file.
1 !> @brief This module contains the LoadMf6FileModule
2 !!
3 !! This module contains the input data model routines for
4 !! loading static data from a MODFLOW 6 input file using the
5 !! block parser.
6 !!
7 !<
9 
10  use kindmodule, only: dp, i4b, lgp
11  use simvariablesmodule, only: errmsg
12  use simmodule, only: store_error
25  use inputoutputmodule, only: parseline
36 
37  implicit none
38  private
39  public :: loadmf6filetype
40  public :: read_control_record
41 
42  !> @brief Fortran workaround for allocatable arrays of pointers; wraps a StructArray pointer for deferred TS linking.
43  !<
44  type :: staticsatype
45  type(structarraytype), pointer :: sa => null()
46  end type staticsatype
47 
48  !> @brief Static parser based input loader
49  !!
50  !! This type defines a static input context loader
51  !! for traditional mf6 ascii input files.
52  !!
53  !<
55  type(blockparsertype), pointer :: parser !< ascii block parser
56  integer(I4B), dimension(:), pointer, contiguous :: mshape => null() !< model shape
57  type(structarraytype), pointer :: structarray => null() !< structarray for loading list input
58  type(staticsatype), allocatable :: ts_sas(:) !< saved structarrays for deferred TS linking
59  type(modflowinputtype) :: mf6_input !< description of input
60  type(ncpackagevarstype), pointer :: nc_vars => null()
61  character(len=LINELENGTH) :: filename !< name of ascii input file
62  character(len=LINELENGTH), dimension(:), allocatable :: block_tags !< read block tags
63  logical(LGP) :: ts_active !< is timeseries active
64  logical(LGP) :: export !< is array export active
65  logical(LGP) :: readasarrays
66  logical(LGP) :: readarraygrid
67  integer(I4B) :: inamedbound
68  integer(I4B) :: iauxiliary
69  integer(I4B) :: iout !< inunit for list log
70  contains
71  procedure :: load
72  procedure :: init
73  procedure :: load_block
74  procedure :: finalize
75  procedure :: parse_block
76  procedure :: block_post_process
77  procedure :: parse_io_tag
78  procedure :: parse_record_tag
79  procedure :: load_tag
80  procedure :: block_index_dfn
82  procedure :: save_ts_sa
83  procedure :: ts_sa_count
84  procedure :: get_ts_sa
85  procedure :: cleanup
86  end type loadmf6filetype
87 
88 contains
89 
90  !> @brief load all static input blocks
91  !!
92  !! Invoke this routine to load all static input blocks
93  !! in single call.
94  !!
95  !<
96  subroutine load(this, parser, mf6_input, nc_vars, filename, iout)
97  class(loadmf6filetype) :: this
98  type(blockparsertype), target, intent(inout) :: parser
99  type(modflowinputtype), intent(in) :: mf6_input
100  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
101  character(len=*), intent(in) :: filename
102  integer(I4B), intent(in) :: iout
103  integer(I4B) :: iblk
104 
105  ! initialize static load
106  call this%init(parser, mf6_input, filename, iout)
107 
108  ! set netcdf vars
109  this%nc_vars => nc_vars
110 
111  ! process blocks
112  do iblk = 1, size(this%mf6_input%block_dfns)
113  ! don't load dynamic input data
114  if (this%mf6_input%block_dfns(iblk)%blockname == 'PERIOD') exit
115  ! load the block
116  call this%load_block(iblk)
117  end do
118 
119  ! finalize static load
120  call this%finalize()
121  end subroutine load
122 
123  !> @brief init
124  !!
125  !! init / finalize are only used when load_block() will be called
126  !!
127  !<
128  subroutine init(this, parser, mf6_input, filename, iout)
129  class(loadmf6filetype) :: this
130  type(blockparsertype), target, intent(inout) :: parser
131  type(modflowinputtype), intent(in) :: mf6_input
132  character(len=*), intent(in) :: filename
133  integer(I4B), intent(in) :: iout
134  integer(I4B) :: isize
135 
136  this%parser => parser
137  this%mf6_input = mf6_input
138  this%filename = filename
139  this%ts_active = .false.
140  this%export = .false.
141  this%readasarrays = .false.
142  this%readarraygrid = .false.
143  this%inamedbound = 0
144  this%iauxiliary = 0
145  this%iout = iout
146 
147  call get_isize('MODEL_SHAPE', mf6_input%component_mempath, isize)
148  if (isize > 0) then
149  call mem_setptr(this%mshape, 'MODEL_SHAPE', mf6_input%component_mempath)
150  end if
151 
152  ! init ts stuctarray list
153  allocate (this%ts_sas(0))
154 
155  ! log lst file header
156  call idm_log_header(this%mf6_input%component_name, &
157  this%mf6_input%subcomponent_name, this%iout)
158  end subroutine init
159 
160  !> @brief load a single block
161  !!
162  !! Assumed in order load of single (next) block. If a
163  !! StructArray object is allocated to load this block
164  !! it persists until this routine (or finalize) is
165  !! called again.
166  !!
167  !<
168  subroutine load_block(this, iblk)
170  class(loadmf6filetype) :: this
171  integer(I4B), intent(in) :: iblk
172 
173  ! reset structarray if it was created for previous block
174  if (associated(this%structarray)) then
175  ! destroy the structured array reader
176  call destructstructarray(this%structarray)
177  end if
178 
179  allocate (this%block_tags(0))
180  ! load the block
181  call this%parse_block(iblk, .false.)
182  ! post process block
183  call this%block_post_process(iblk)
184  ! cleanup
185  deallocate (this%block_tags)
186  end subroutine load_block
187 
188  !> @brief finalize
189  !!
190  !! init / finalize are only used when load_block() will be called
191  !!
192  !<
193  subroutine finalize(this)
195  class(loadmf6filetype) :: this
196  ! cleanup
197  if (associated(this%structarray)) then
198  ! destroy the structured array reader
199  call destructstructarray(this%structarray)
200  end if
201  ! close logging block
202  call idm_log_close(this%mf6_input%component_name, &
203  this%mf6_input%subcomponent_name, this%iout)
204  end subroutine finalize
205 
206  !> @brief Post parse block handling
207  !!
208  !<
209  subroutine block_post_process(this, iblk)
211  class(loadmf6filetype) :: this
212  integer(I4B), intent(in) :: iblk
213  type(inputparamdefinitiontype), pointer :: idt
214  integer(I4B) :: iparam
215  integer(I4B), pointer :: intptr
216 
217  ! update state based on read tags
218  do iparam = 1, size(this%block_tags)
219  select case (this%mf6_input%block_dfns(iblk)%blockname)
220  case ('OPTIONS')
221  if (this%block_tags(iparam) == 'AUXILIARY') then
222  this%iauxiliary = 1
223  else if (this%block_tags(iparam) == 'BOUNDNAMES') then
224  this%inamedbound = 1
225  else if (this%block_tags(iparam) == 'READASARRAYS') then
226  this%readasarrays = .true.
227  else if (this%block_tags(iparam) == 'READARRAYGRID') then
228  this%readarraygrid = .true.
229  else if (this%block_tags(iparam) == 'TS6_FILENAME') then
230  this%ts_active = .true.
231  else if (this%block_tags(iparam) == 'EXPORT_ARRAY_ASCII') then
232  this%export = .true.
233  end if
234  case default
235  end select
236  end do
237 
238  ! update input context allocations based on dfn set and input
239  select case (this%mf6_input%block_dfns(iblk)%blockname)
240  case ('OPTIONS')
241  ! allocate naux and set to 0 if not allocated
242  do iparam = 1, size(this%mf6_input%param_dfns)
243  idt => this%mf6_input%param_dfns(iparam)
244  if (idt%blockname == 'OPTIONS' .and. &
245  idt%tagname == 'AUXILIARY') then
246  if (this%iauxiliary == 0) then
247  call mem_allocate(intptr, 'NAUX', this%mf6_input%mempath)
248  intptr = 0
249  end if
250  exit
251  end if
252  end do
253  case ('DIMENSIONS')
254  ! set model shape if discretization dimensions have been read
255  if (this%mf6_input%pkgtype(1:3) == 'DIS') then
256  call set_model_shape(this%mf6_input%pkgtype, this%filename, &
257  this%mf6_input%component_mempath, &
258  this%mf6_input%mempath, this%mshape)
259  end if
260  case default
261  end select
262  end subroutine block_post_process
263 
264  !> @brief parse block
265  !!
266  !<
267  recursive subroutine parse_block(this, iblk, recursive_call)
268  use memorytypemodule, only: memorytype
270  class(loadmf6filetype) :: this
271  integer(I4B), intent(in) :: iblk
272  logical(LGP), intent(in) :: recursive_call !< true if recursive call
273  logical(LGP) :: isblockfound
274  logical(LGP) :: endofblock
275  logical(LGP) :: supportopenclose
276  integer(I4B) :: ierr
277  logical(LGP) :: found, required
278  type(memorytype), pointer :: mt
279  character(len=LINELENGTH) :: tag
280  type(inputparamdefinitiontype), pointer :: idt
281 
282  ! disu vertices/cell2d blocks are contingent on NVERT dimension
283  if (this%mf6_input%pkgtype == 'DISU6' .or. &
284  this%mf6_input%pkgtype == 'DISV1D6' .or. &
285  this%mf6_input%pkgtype == 'DISV2D6') then
286  if (this%mf6_input%block_dfns(iblk)%blockname == 'VERTICES' .or. &
287  this%mf6_input%block_dfns(iblk)%blockname == 'CELL2D') then
288  call get_from_memorystore('NVERT', this%mf6_input%mempath, mt, found, &
289  .false.)
290  if (.not. found) return
291  if (mt%intsclr == 0) return
292  end if
293  end if
294 
295  ! block open/close support
296  supportopenclose = (this%mf6_input%block_dfns(iblk)%blockname /= 'GRIDDATA')
297 
298  ! parser search for block
299  required = this%mf6_input%block_dfns(iblk)%required .and. .not. recursive_call
300  call this%parser%GetBlock(this%mf6_input%block_dfns(iblk)%blockname, &
301  isblockfound, ierr, &
302  supportopenclose=supportopenclose, &
303  blockrequired=required)
304  ! process block
305  if (isblockfound) then
306  if (this%mf6_input%block_dfns(iblk)%aggregate) then
307  ! process block recarray type, set of variable 1d/2d types
308  call this%parse_structarray_block(iblk)
309  else
310  do
311  ! process each line in block
312  call this%parser%GetNextLine(endofblock)
313  if (endofblock) exit
314  ! process line as tag(s)
315  call this%parser%GetStringCaps(tag)
316  idt => get_param_definition_type( &
317  this%mf6_input%param_dfns, &
318  this%mf6_input%component_type, &
319  this%mf6_input%subcomponent_type, &
320  this%mf6_input%block_dfns(iblk)%blockname, &
321  tag, this%filename)
322  if (idt%in_record) then
323  call this%parse_record_tag(iblk, idt, .false.)
324  else
325  call this%load_tag(iblk, idt)
326  end if
327  end do
328  end if
329  end if
330 
331  ! recurse if block is reloadable and was just read
332  if (this%mf6_input%block_dfns(iblk)%block_variable) then
333  if (isblockfound) then
334  call this%parse_block(iblk, .true.)
335  end if
336  end if
337  end subroutine parse_block
338 
339  subroutine parse_io_tag(this, iblk, pkgtype, which, tag)
341  class(loadmf6filetype) :: this
342  integer(I4B), intent(in) :: iblk
343  character(len=*), intent(in) :: pkgtype
344  character(len=*), intent(in) :: which
345  character(len=*), intent(in) :: tag
346  type(inputparamdefinitiontype), pointer :: idt !< input data type object describing this record
347  ! matches, read and load file name
348  idt => &
349  get_param_definition_type(this%mf6_input%param_dfns, &
350  this%mf6_input%component_type, &
351  this%mf6_input%subcomponent_type, &
352  this%mf6_input%block_dfns(iblk)%blockname, &
353  tag, this%filename)
354  ! load io tag
355  call load_io_tag(this%parser, idt, this%mf6_input%mempath, which, this%iout)
356  call expandarray(this%block_tags)
357  this%block_tags(size(this%block_tags)) = trim(idt%tagname)
358  end subroutine parse_io_tag
359 
360  recursive subroutine parse_record_tag(this, iblk, inidt, recursive_call)
364  class(loadmf6filetype) :: this
365  integer(I4B), intent(in) :: iblk
366  type(inputparamdefinitiontype), pointer, intent(in) :: inidt
367  logical(LGP), intent(in) :: recursive_call !< true if recursive call
368  type(inputparamdefinitiontype), pointer :: idt
369  character(len=40), dimension(:), allocatable :: words
370  integer(I4B) :: n, istart, nwords
371  character(len=LINELENGTH) :: tag
372 
373  nullify (idt)
374  istart = 1
375 
376  if (recursive_call) then
377  call split_record_dfn_tag1(this%mf6_input%param_dfns, &
378  this%mf6_input%component_type, &
379  this%mf6_input%subcomponent_type, &
380  inidt%tagname, nwords, words)
381  call this%load_tag(iblk, inidt)
382  istart = 3
383  else
384  call this%parser%GetStringCaps(tag)
385  if (tag /= '') then
386  call split_record_dfn_tag2(this%mf6_input%param_dfns, &
387  this%mf6_input%component_type, &
388  this%mf6_input%subcomponent_type, &
389  inidt%tagname, tag, nwords, words)
390  if (nwords == 4 .and. &
391  (tag == 'FILEIN' .or. &
392  tag == 'FILEOUT')) then
393  call this%parse_io_tag(iblk, words(2), words(3), words(4))
394  nwords = 0
395  else
396  idt => get_param_definition_type( &
397  this%mf6_input%param_dfns, &
398  this%mf6_input%component_type, &
399  this%mf6_input%subcomponent_type, &
400  this%mf6_input%block_dfns(iblk)%blockname, &
401  tag, this%filename)
402  ! avoid namespace collisions (CIM)
403  if (tag /= 'PRINT_FORMAT') call this%load_tag(iblk, inidt)
404  call this%load_tag(iblk, idt)
405  istart = 4
406  end if
407  else
408  call this%load_tag(iblk, inidt)
409  nwords = 0
410  end if
411  end if
412 
413  if (istart > 1 .and. nwords == 0) then
414  write (errmsg, '(5a)') &
415  '"', trim(this%mf6_input%block_dfns(iblk)%blockname), &
416  '" block input record that includes keyword "', trim(inidt%tagname), &
417  '" is not properly formed.'
418  call store_error(errmsg)
419  call this%parser%StoreErrorUnit()
420  end if
421 
422  do n = istart, nwords
423  idt => get_param_definition_type( &
424  this%mf6_input%param_dfns, &
425  this%mf6_input%component_type, &
426  this%mf6_input%subcomponent_type, &
427  this%mf6_input%block_dfns(iblk)%blockname, &
428  words(n), this%filename)
429  if (idt_datatype(idt) == 'RECORD') then
430  call this%parser%GetStringCaps(tag)
431  idt => get_param_definition_type( &
432  this%mf6_input%param_dfns, &
433  this%mf6_input%component_type, &
434  this%mf6_input%subcomponent_type, &
435  this%mf6_input%block_dfns(iblk)%blockname, &
436  tag, this%filename)
437  call this%parse_record_tag(iblk, idt, .true.)
438  exit
439  else
440  if (idt%tagname /= 'FORMAT') then
441  call this%parser%GetStringCaps(tag)
442  if (tag == '') then
443  exit
444  else if (idt%tagname /= tag) then
445  write (errmsg, '(5a)') 'Expecting record input tag "', &
446  trim(idt%tagname), '" but instead found "', trim(tag), '".'
447  call store_error(errmsg)
448  call this%parser%StoreErrorUnit()
449  end if
450  end if
451  call this%load_tag(iblk, idt)
452  end if
453  end do
454 
455  if (allocated(words)) deallocate (words)
456  end subroutine parse_record_tag
457 
458  !> @brief load input keyword
459  !! Load input associated with tag key into the memory manager.
460  !<
461  subroutine load_tag(this, iblk, idt)
464  class(loadmf6filetype) :: this
465  integer(I4B), intent(in) :: iblk
466  type(inputparamdefinitiontype), pointer, intent(in) :: idt !< input data type object describing this record
467  character(len=LINELENGTH) :: dev_msg
468 
469  ! check if input param is developmode
470  if (idt%developmode) then
471  dev_msg = 'Input tag "'//trim(idt%tagname)// &
472  &'" read from file "'//trim(this%filename)// &
473  &'" is still under development. Install the &
474  &nightly build or compile from source with IDEVELOPMODE = 1.'
475  call developmode(dev_msg, this%iout)
476  end if
477 
478  ! allocate and load data type
479  select case (idt%datatype)
480  case ('KEYWORD')
481  call load_keyword_type(this%parser, idt, this%mf6_input%mempath, this%iout)
482  ! check/set as dev option
483  if (idt%tagname(1:4) == 'DEV_' .and. &
484  this%mf6_input%block_dfns(iblk)%blockname == 'OPTIONS') then
485  call this%parser%DevOpt()
486  end if
487  case ('STRING')
488  if (idt%shape == 'NAUX') then
489  call load_auxvar_names(this%parser, idt, this%mf6_input%mempath, &
490  this%iout)
491  else
492  call load_string_type(this%parser, idt, this%mf6_input%mempath, this%iout)
493  end if
494  case ('INTEGER')
495  call load_integer_type(this%parser, idt, this%mf6_input%mempath, this%iout)
496  case ('INTEGER1D')
497  call load_integer1d_type(this%parser, idt, this%mf6_input, this%mshape, &
498  this%export, this%nc_vars, this%filename, &
499  this%iout)
500  case ('INTEGER2D')
501  call load_integer2d_type(this%parser, idt, this%mf6_input, this%mshape, &
502  this%export, this%nc_vars, this%filename, &
503  this%iout)
504  case ('INTEGER3D')
505  call load_integer3d_type(this%parser, idt, this%mf6_input, this%mshape, &
506  this%export, this%nc_vars, this%filename, &
507  this%iout)
508  case ('DOUBLE')
509  call load_double_type(this%parser, idt, this%mf6_input%mempath, this%iout)
510  case ('DOUBLE1D')
511  call load_double1d_type(this%parser, idt, this%mf6_input, this%mshape, &
512  this%export, this%nc_vars, this%filename, this%iout)
513  case ('DOUBLE2D')
514  call load_double2d_type(this%parser, idt, this%mf6_input, this%mshape, &
515  this%export, this%nc_vars, this%filename, this%iout)
516  case ('DOUBLE3D')
517  call load_double3d_type(this%parser, idt, this%mf6_input, this%mshape, &
518  this%export, this%nc_vars, this%filename, this%iout)
519  case default
520  write (errmsg, '(a,a)') 'Failure reading data for tag: ', trim(idt%tagname)
521  call store_error(errmsg)
522  call this%parser%StoreErrorUnit()
523  end select
524 
525  call expandarray(this%block_tags)
526  this%block_tags(size(this%block_tags)) = trim(idt%tagname)
527  end subroutine load_tag
528 
529  function block_index_dfn(this, iblk) result(idt)
530  class(loadmf6filetype) :: this
531  integer(I4B), intent(in) :: iblk
532  type(inputparamdefinitiontype) :: idt !< input data type object describing this record
533  character(len=LENVARNAME) :: varname
534  integer(I4B) :: ilen
535  character(len=3) :: block_suffix = 'NUM'
536 
537  ! assign first column as the block number
538  ilen = len_trim(this%mf6_input%block_dfns(iblk)%blockname)
539 
540  if (ilen > (lenvarname - len(block_suffix))) then
541  varname = &
542  this%mf6_input%block_dfns(iblk)% &
543  blockname(1:(lenvarname - len(block_suffix)))//block_suffix
544  else
545  varname = trim(this%mf6_input%block_dfns(iblk)%blockname)//block_suffix
546  end if
547 
548  idt%component_type = trim(this%mf6_input%component_type)
549  idt%subcomponent_type = trim(this%mf6_input%subcomponent_type)
550  idt%blockname = trim(this%mf6_input%block_dfns(iblk)%blockname)
551  idt%tagname = varname
552  idt%mf6varname = varname
553  idt%datatype = 'INTEGER'
554  end function block_index_dfn
555 
556  !> @brief parse a structured array record into memory manager
557  !!
558  !! A structarray is similar to a numpy recarray. It it used to
559  !! load a list of data in which each column in the list may be a
560  !! different type. Each column in the list is stored as a 1d
561  !! vector.
562  !!
563  !<
564  subroutine parse_structarray_block(this, iblk)
567  class(loadmf6filetype) :: this
568  integer(I4B), intent(in) :: iblk
569  type(loadcontexttype) :: ctx
570  character(len=LINELENGTH), dimension(:), allocatable :: param_names
571  type(inputparamdefinitiontype), pointer :: idt !< input data type object describing this record
572  type(inputparamdefinitiontype), pointer :: shape_idt
573  type(inputparamdefinitiontype), target :: blockvar_idt
574  integer(I4B) :: blocknum
575  integer(I4B), pointer :: nrow
576  integer(I4B), dimension(:), pointer, contiguous :: int1d
577  integer(I4B) :: nrows, nrowsread
578  integer(I4B) :: mem_rank, isize
579  integer(I4B) :: ibinary, oc_inunit
580  integer(I4B) :: icol, iparam
581  integer(I4B) :: ncol, nparam
582  logical(LGP) :: shape_found
583  integer(I4B), pointer :: pkgdata_maxbound
584 
585  nrows = -1
586  mem_rank = -1
587 
588  ! initialize load context
589  call ctx%init(this%mf6_input, blockname= &
590  this%mf6_input%block_dfns(iblk)%blockname)
591  ! set in-scope params directly from context
592  param_names = ctx%params
593  nparam = size(ctx%params)
594  call ctx%check_developmode(this%filename)
595  ! set input definition for this block
596  idt => &
597  get_aggregate_definition_type(this%mf6_input%aggregate_dfns, &
598  this%mf6_input%component_type, &
599  this%mf6_input%subcomponent_type, &
600  this%mf6_input%block_dfns(iblk)%blockname)
601  ! if block is reloadable read the block number
602  if (this%mf6_input%block_dfns(iblk)%block_variable) then
603  blocknum = this%parser%GetInteger()
604  else
605  blocknum = 0
606  end if
607 
608  ! set ncol
609  ncol = nparam
610  ! add col if block is reloadable
611  if (blocknum > 0) ncol = ncol + 1
612  ! use shape to set the max num of rows
613  if (idt%shape /= '') then
614  shape_idt => &
615  get_param_definition_type(this%mf6_input%param_dfns, &
616  this%mf6_input%component_type, &
617  this%mf6_input%subcomponent_type, &
618  'DIMENSIONS', idt%shape, this%filename, &
619  found=shape_found)
620  if (.not. shape_found) then
621  ! also allow a per-row PACKAGEDATA field (e.g. LAK's NLAKECONN)
622  shape_idt => &
623  get_param_definition_type(this%mf6_input%param_dfns, &
624  this%mf6_input%component_type, &
625  this%mf6_input%subcomponent_type, &
626  'PACKAGEDATA', idt%shape, this%filename, &
627  found=shape_found)
628  end if
629  if (shape_found) then
630  call get_isize(shape_idt%mf6varname, this%mf6_input%mempath, isize)
631  if (isize < 0) then
632  if (shape_idt%required) then
633  write (errmsg, '(3a)') 'Required dimension "', &
634  trim(idt%shape), '" not found.'
635  call store_error(errmsg)
636  call this%parser%StoreErrorUnit()
637  end if
638  else
639  call get_mem_rank(shape_idt%mf6varname, this%mf6_input%mempath, &
640  mem_rank)
641  end if
642  end if
643  if (mem_rank == 0) then
644  ! scalar shape variable (e.g. NLAKES, MAXBOUND) — use value directly
645  call mem_setptr(nrow, shape_idt%mf6varname, this%mf6_input%mempath)
646  nrows = nrow
647  else if (mem_rank == 1) then
648  ! 1D array shape (e.g. NLAKECONN): sum elements for total row
649  ! count, since sum(nlakeconn) itself isn't DFN-evaluable
650  call mem_setptr(int1d, shape_idt%mf6varname, this%mf6_input%mempath)
651  nrows = sum(int1d)
652  nullify (int1d)
653  end if
654  ! -- else: shape variable not found or unsupported rank; nrows stays
655  ! at its initial -1, so the block falls back to deferred sizing
656  end if
657 
658  ! create a structured array; use a larger deferred init for blocks with no
659  ! explicit shape, which include APT based advanced packages.
660  if (nrows < 0) then
661  this%structarray => constructstructarray(this%mf6_input, ncol, nrows, &
662  blocknum, this%mf6_input%mempath, &
663  this%mf6_input%component_mempath, &
664  size_init=64)
665  else
666  this%structarray => constructstructarray(this%mf6_input, ncol, nrows, &
667  blocknum, this%mf6_input%mempath, &
668  this%mf6_input%component_mempath)
669  end if
670  ! create structarray vectors for each column
671  do icol = 1, ncol
672  ! if block is reloadable, block number is first column
673  if (blocknum > 0) then
674  if (icol == 1) then
675  blockvar_idt = this%block_index_dfn(iblk)
676  idt => blockvar_idt
677  call this%structarray%mem_create_vector(icol, idt)
678  ! continue as this column managed by internally SA object
679  cycle
680  end if
681  ! set indexes (where first column is blocknum)
682  iparam = icol - 1
683  else
684  ! set indexes (no blocknum column)
685  iparam = icol
686  end if
687  ! set pointer to input definition for this 1d vector
688  idt => &
689  get_param_definition_type(this%mf6_input%param_dfns, &
690  this%mf6_input%component_type, &
691  this%mf6_input%subcomponent_type, &
692  this%mf6_input%block_dfns(iblk)%blockname, &
693  param_names(iparam), this%filename)
694  ! allocate variable in memory manager
695  call this%structarray%mem_create_vector(icol, idt)
696  end do
697 
698  ! finish context setup after allocating vectors
699  call ctx%allocate_arrays()
700 
701  ! read the block control record
702  ibinary = read_control_record(this%parser, oc_inunit, this%iout)
703 
704  if (ibinary == 1) then
705  ! read from binary
706  nrowsread = this%structarray%read_from_binary(oc_inunit, this%iout)
707  call this%parser%terminateblock()
708  close (oc_inunit)
709  else
710  ! read from ascii
711  nrowsread = this%structarray%read_from_parser(this%parser, this%ts_active, &
712  this%iout, this%filename)
713  ! save structarray for deferred TS linking in df() if any strlocs were stored
714  if (this%ts_active) call this%save_ts_sa()
715  end if
716 
717  ! an advanced package's PACKAGEDATA row count is published as
718  ! MAXBOUND, the feature count the PERIOD block's load context needs
719  if (this%mf6_input%block_dfns(iblk)%blockname == 'PACKAGEDATA' .and. &
720  is_feature_keystring(this%mf6_input) .and. ctx%is_advanced) then
721  call get_isize('MAXBOUND', this%mf6_input%mempath, isize)
722  if (isize < 0) then
723  call mem_allocate(pkgdata_maxbound, 'MAXBOUND', this%mf6_input%mempath)
724  pkgdata_maxbound = nrowsread
725  end if
726  end if
727 
728  ! clean up
729  call ctx%destroy()
730  end subroutine parse_structarray_block
731 
732  !> @brief Return number of saved static StructArrays with deferred TS strlocs
733  !<
734  function ts_sa_count(this) result(n)
735  class(loadmf6filetype), intent(in) :: this
736  integer(I4B) :: n
737  n = size(this%ts_sas)
738  end function ts_sa_count
739 
740  !> @brief Return the n-th saved static StructArray pointer
741  !<
742  function get_ts_sa(this, n) result(sa)
743  class(loadmf6filetype), intent(in) :: this
744  integer(I4B), intent(in) :: n
745  type(structarraytype), pointer :: sa
746  sa => this%ts_sas(n)%sa
747  end function get_ts_sa
748 
749  !> @brief load type keyword
750  !<
751  subroutine load_keyword_type(parser, idt, memoryPath, iout)
752  type(blockparsertype), intent(inout) :: parser !< block parser
753  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
754  character(len=*), intent(in) :: memoryPath !< memorypath to put loaded information
755  integer(I4B), intent(in) :: iout !< unit number for output
756  integer(I4B), pointer :: intvar
757  call mem_allocate(intvar, idt%mf6varname, memorypath)
758  intvar = 1
759  call idm_log_var(intvar, idt%tagname, memorypath, idt%datatype, iout)
760  end subroutine load_keyword_type
761 
762  !> @brief load type string
763  !<
764  subroutine load_string_type(parser, idt, memoryPath, iout)
765  use constantsmodule, only: lenbigline
766  type(blockparsertype), intent(inout) :: parser !< block parser
767  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
768  character(len=*), intent(in) :: memoryPath !< memorypath to put loaded information
769  integer(I4B), intent(in) :: iout !< unit number for output
770  character(len=LINELENGTH), pointer :: cstr
771  character(len=LENBIGLINE), pointer :: bigcstr
772  integer(I4B) :: ilen
773  select case (idt%shape)
774  case ('LENBIGLINE')
775  ilen = lenbigline
776  call mem_allocate(bigcstr, ilen, idt%mf6varname, memorypath)
777  call parser%GetString(bigcstr, (.not. idt%preserve_case))
778  call idm_log_var(bigcstr, idt%tagname, memorypath, iout)
779  case default
780  ilen = linelength
781  call mem_allocate(cstr, ilen, idt%mf6varname, memorypath)
782  call parser%GetString(cstr, (.not. idt%preserve_case))
783  call idm_log_var(cstr, idt%tagname, memorypath, iout)
784  end select
785  end subroutine load_string_type
786 
787  !> @brief load io tag
788  !<
789  subroutine load_io_tag(parser, idt, memoryPath, which, iout)
792  type(blockparsertype), intent(inout) :: parser !< block parser
793  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
794  character(len=*), intent(in) :: memoryPath !< memorypath to put loaded information
795  character(len=*), intent(in) :: which
796  integer(I4B), intent(in) :: iout !< unit number for output
797  character(len=LINELENGTH) :: cstr
798  type(characterstringtype), dimension(:), pointer, contiguous :: charstr1d
799  integer(I4B) :: ilen, isize, idx
800  ilen = linelength
801  if (which == 'FILEIN') then
802  call get_isize(idt%mf6varname, memorypath, isize)
803  if (isize < 0) then
804  call mem_allocate(charstr1d, ilen, 1, idt%mf6varname, memorypath)
805  idx = 1
806  else
807  call mem_setptr(charstr1d, idt%mf6varname, memorypath)
808  call mem_reallocate(charstr1d, ilen, isize + 1, idt%mf6varname, &
809  memorypath)
810  idx = isize + 1
811  end if
812  call parser%GetString(cstr, (.not. idt%preserve_case))
813  charstr1d(idx) = cstr
814  else if (which == 'FILEOUT') then
815  call load_string_type(parser, idt, memorypath, iout)
816  end if
817  end subroutine load_io_tag
818 
819  !> @brief load aux variable names
820  !!
821  !<
822  subroutine load_auxvar_names(parser, idt, memoryPath, iout)
824  use inputoutputmodule, only: urdaux
826  type(blockparsertype), intent(inout) :: parser !< block parser
827  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
828  character(len=*), intent(in) :: memoryPath !< memorypath to put loaded information
829  integer(I4B), intent(in) :: iout !< unit number for output
830  character(len=:), allocatable :: line
831  character(len=LENAUXNAME), dimension(:), allocatable :: caux
832  integer(I4B) :: lloc
833  integer(I4B) :: istart
834  integer(I4B) :: istop
835  integer(I4B) :: i
836  character(len=LENPACKAGENAME) :: text = ''
837  integer(I4B), pointer :: intvar
838  type(characterstringtype), dimension(:), &
839  pointer, contiguous :: acharstr1d !< variable for allocation
840  call mem_allocate(intvar, idt%shape, memorypath)
841  intvar = 0
842  call parser%GetRemainingLine(line)
843  lloc = 1
844  call urdaux(intvar, parser%iuactive, iout, lloc, &
845  istart, istop, caux, line, text)
846  call mem_allocate(acharstr1d, lenauxname, intvar, idt%mf6varname, memorypath)
847  do i = 1, intvar
848  acharstr1d(i) = caux(i)
849  end do
850  deallocate (line)
851  deallocate (caux)
852  end subroutine load_auxvar_names
853 
854  !> @brief load type integer
855  !<
856  subroutine load_integer_type(parser, idt, memoryPath, iout)
857  type(blockparsertype), intent(inout) :: parser !< block parser
858  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
859  character(len=*), intent(in) :: memoryPath !< memorypath to put loaded information
860  integer(I4B), intent(in) :: iout !< unit number for output
861  integer(I4B), pointer :: intvar
862  call mem_allocate(intvar, idt%mf6varname, memorypath)
863  intvar = parser%GetInteger()
864  call idm_log_var(intvar, idt%tagname, memorypath, idt%datatype, iout)
865  end subroutine load_integer_type
866 
867  !> @brief load type 1d integer
868  !<
869  subroutine load_integer1d_type(parser, idt, mf6_input, mshape, export, &
870  nc_vars, input_fname, iout)
873  type(blockparsertype), intent(inout) :: parser !< block parser
874  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
875  type(modflowinputtype), intent(in) :: mf6_input !< description of input
876  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: mshape !< model shape
877  logical(LGP), intent(in) :: export !< export to ascii layer files
878  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
879  character(len=*), intent(in) :: input_fname !< ascii input file name
880  integer(I4B), intent(in) :: iout !< unit number for output
881  integer(I4B), dimension(:), pointer, contiguous :: int1d
882  integer(I4B) :: nlay
883  integer(I4B) :: nvals
884  integer(I4B), dimension(:), allocatable :: array_shape
885  integer(I4B), dimension(:), allocatable :: layer_shape
886  character(len=LINELENGTH) :: keyword
887 
888  ! Check if it is a full grid sized array (NODES), otherwise use
889  ! idt%shape to construct shape from variables in memoryPath
890  if (idt%shape == 'NODES') then
891  nvals = product(mshape)
892  else
893  call get_shape_from_string(idt%shape, array_shape, mf6_input%mempath)
894  nvals = array_shape(1)
895  end if
896 
897  ! allocate memory for the array
898  call mem_allocate(int1d, nvals, idt%mf6varname, mf6_input%mempath)
899 
900  ! read keyword
901  keyword = ''
902  call parser%GetStringCaps(keyword)
903 
904  ! check for "NETCDF" and "LAYERED"
905  if (keyword == 'NETCDF') then
906  call netcdf_read_array(int1d, mshape, idt, mf6_input, nc_vars, &
907  input_fname, iout)
908  else if (keyword == 'LAYERED' .and. idt%layered) then
909  call get_layered_shape(mshape, nlay, layer_shape)
910  call read_int1d_layered(parser, int1d, idt%mf6varname, nlay, layer_shape)
911  else
912  call read_int1d(parser, int1d, idt%mf6varname)
913  end if
914 
915  ! log information on the loaded array to the list file
916  call idm_log_var(int1d, idt%tagname, mf6_input%mempath, iout)
917 
918  ! create export file for griddata parameters if optioned
919  if (export) then
920  if (idt%blockname == 'GRIDDATA') then
921  call idm_export(int1d, idt%tagname, mf6_input%mempath, idt%shape, iout)
922  end if
923  end if
924  end subroutine load_integer1d_type
925 
926  !> @brief load type 2d integer
927  !<
928  subroutine load_integer2d_type(parser, idt, mf6_input, mshape, export, &
929  nc_vars, input_fname, iout)
932  type(blockparsertype), intent(inout) :: parser !< block parser
933  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
934  type(modflowinputtype), intent(in) :: mf6_input !< description of input
935  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: mshape !< model shape
936  logical(LGP), intent(in) :: export !< export to ascii layer files
937  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
938  character(len=*), intent(in) :: input_fname !< ascii input file name
939  integer(I4B), intent(in) :: iout !< unit number for output
940  integer(I4B), dimension(:, :), pointer, contiguous :: int2d
941  integer(I4B) :: nlay
942  integer(I4B) :: nsize1, nsize2
943  integer(I4B), dimension(:), allocatable :: array_shape
944  integer(I4B), dimension(:), allocatable :: layer_shape
945  character(len=LINELENGTH) :: keyword
946 
947  ! determine the array shape from the input data definition (idt%shape),
948  ! which looks like "NCOL, NROW, NLAY"
949  call get_shape_from_string(idt%shape, array_shape, mf6_input%mempath)
950  nsize1 = array_shape(1)
951  nsize2 = array_shape(2)
952 
953  ! create a new 3d memory managed variable
954  call mem_allocate(int2d, nsize1, nsize2, idt%mf6varname, mf6_input%mempath)
955 
956  ! read keyword
957  keyword = ''
958  call parser%GetStringCaps(keyword)
959 
960  ! check for "NETCDF" and "LAYERED"
961  if (keyword == 'NETCDF') then
962  call netcdf_read_array(int2d, mshape, idt, mf6_input, nc_vars, &
963  input_fname, iout)
964  else if (keyword == 'LAYERED' .and. idt%layered) then
965  call get_layered_shape(mshape, nlay, layer_shape)
966  call read_int2d_layered(parser, int2d, idt%mf6varname, nlay, layer_shape)
967  else
968  call read_int2d(parser, int2d, idt%mf6varname)
969  end if
970 
971  ! log information on the loaded array to the list file
972  call idm_log_var(int2d, idt%tagname, mf6_input%mempath, iout)
973 
974  ! create export file for griddata parameters if optioned
975  if (export) then
976  if (idt%blockname == 'GRIDDATA') then
977  call idm_export(int2d, idt%tagname, mf6_input%mempath, idt%shape, iout)
978  end if
979  end if
980  end subroutine load_integer2d_type
981 
982  !> @brief load type 3d integer
983  !<
984  subroutine load_integer3d_type(parser, idt, mf6_input, mshape, export, &
985  nc_vars, input_fname, iout)
988  type(blockparsertype), intent(inout) :: parser !< block parser
989  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
990  type(modflowinputtype), intent(in) :: mf6_input !< description of input
991  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: mshape !< model shape
992  logical(LGP), intent(in) :: export !< export to ascii layer files
993  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
994  character(len=*), intent(in) :: input_fname !< ascii input file name
995  integer(I4B), intent(in) :: iout !< unit number for output
996  integer(I4B), dimension(:, :, :), pointer, contiguous :: int3d
997  integer(I4B) :: nlay
998  integer(I4B) :: nsize1, nsize2, nsize3
999  integer(I4B), dimension(:), allocatable :: array_shape
1000  integer(I4B), dimension(:), allocatable :: layer_shape
1001  integer(I4B), dimension(:), pointer, contiguous :: int1d_ptr
1002  character(len=LINELENGTH) :: keyword
1003 
1004  ! determine the array shape from the input data definition (idt%shape),
1005  ! which looks like "NCOL, NROW, NLAY"
1006  call get_shape_from_string(idt%shape, array_shape, mf6_input%mempath)
1007  nsize1 = array_shape(1)
1008  nsize2 = array_shape(2)
1009  nsize3 = array_shape(3)
1010 
1011  ! create a new 3d memory managed variable
1012  call mem_allocate(int3d, nsize1, nsize2, nsize3, idt%mf6varname, &
1013  mf6_input%mempath)
1014 
1015  ! read keyword
1016  keyword = ''
1017  call parser%GetStringCaps(keyword)
1018 
1019  ! check for "NETCDF" and "LAYERED"
1020  if (keyword == 'NETCDF') then
1021  call netcdf_read_array(int3d, mshape, idt, mf6_input, nc_vars, &
1022  input_fname, iout)
1023  else if (keyword == 'LAYERED' .and. idt%layered) then
1024  call get_layered_shape(mshape, nlay, layer_shape)
1025  call read_int3d_layered(parser, int3d, idt%mf6varname, nlay, &
1026  layer_shape)
1027  else
1028  int1d_ptr(1:nsize1 * nsize2 * nsize3) => int3d(:, :, :)
1029  call read_int1d(parser, int1d_ptr, idt%mf6varname)
1030  end if
1031 
1032  ! log information on the loaded array to the list file
1033  call idm_log_var(int3d, idt%tagname, mf6_input%mempath, iout)
1034 
1035  ! create export file for griddata parameters if optioned
1036  if (export) then
1037  if (idt%blockname == 'GRIDDATA') then
1038  call idm_export(int3d, idt%tagname, mf6_input%mempath, idt%shape, iout)
1039  end if
1040  end if
1041  end subroutine load_integer3d_type
1042 
1043  !> @brief load type double
1044  !<
1045  subroutine load_double_type(parser, idt, memoryPath, iout)
1046  type(blockparsertype), intent(inout) :: parser !< block parser
1047  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
1048  character(len=*), intent(in) :: memoryPath !< memorypath to put loaded information
1049  integer(I4B), intent(in) :: iout !< unit number for output
1050  real(DP), pointer :: dblvar
1051  call mem_allocate(dblvar, idt%mf6varname, memorypath)
1052  dblvar = parser%GetDouble()
1053  call idm_log_var(dblvar, idt%tagname, memorypath, iout)
1054  end subroutine load_double_type
1055 
1056  !> @brief load type 1d double
1057  !<
1058  subroutine load_double1d_type(parser, idt, mf6_input, mshape, export, &
1059  nc_vars, input_fname, iout)
1062  type(blockparsertype), intent(inout) :: parser !< block parser
1063  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
1064  type(modflowinputtype), intent(in) :: mf6_input !< description of input
1065  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: mshape !< model shape
1066  logical(LGP), intent(in) :: export !< export to ascii layer files
1067  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
1068  character(len=*), intent(in) :: input_fname !< ascii input file name
1069  integer(I4B), intent(in) :: iout !< unit number for output
1070  real(DP), dimension(:), pointer, contiguous :: dbl1d
1071  integer(I4B) :: nlay
1072  integer(I4B) :: nvals
1073  integer(I4B), dimension(:), allocatable :: array_shape
1074  integer(I4B), dimension(:), allocatable :: layer_shape
1075  character(len=LINELENGTH) :: keyword
1076 
1077  ! Check if it is a full grid sized array (NODES)
1078  if (idt%shape == 'NODES') then
1079  nvals = product(mshape)
1080  else
1081  call get_shape_from_string(idt%shape, array_shape, mf6_input%mempath)
1082  nvals = array_shape(1)
1083  end if
1084 
1085  ! allocate memory for the array
1086  call mem_allocate(dbl1d, nvals, idt%mf6varname, mf6_input%mempath)
1087 
1088  ! read keyword
1089  keyword = ''
1090  call parser%GetStringCaps(keyword)
1091 
1092  ! check for "NETCDF" and "LAYERED"
1093  if (keyword == 'NETCDF') then
1094  call netcdf_read_array(dbl1d, mshape, idt, mf6_input, nc_vars, &
1095  input_fname, iout)
1096  else if (keyword == 'LAYERED' .and. idt%layered) then
1097  call get_layered_shape(mshape, nlay, layer_shape)
1098  call read_dbl1d_layered(parser, dbl1d, idt%mf6varname, nlay, layer_shape)
1099  else
1100  call read_dbl1d(parser, dbl1d, idt%mf6varname)
1101  end if
1102 
1103  ! log information on the loaded array to the list file
1104  call idm_log_var(dbl1d, idt%tagname, mf6_input%mempath, iout)
1105 
1106  ! create export file for griddata parameters if optioned
1107  if (export) then
1108  if (idt%blockname == 'GRIDDATA') then
1109  call idm_export(dbl1d, idt%tagname, mf6_input%mempath, idt%shape, iout)
1110  end if
1111  end if
1112  end subroutine load_double1d_type
1113 
1114  !> @brief load type 2d double
1115  !<
1116  subroutine load_double2d_type(parser, idt, mf6_input, mshape, export, &
1117  nc_vars, input_fname, iout)
1120  type(blockparsertype), intent(inout) :: parser !< block parser
1121  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
1122  type(modflowinputtype), intent(in) :: mf6_input !< description of input
1123  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: mshape !< model shape
1124  logical(LGP), intent(in) :: export !< export to ascii layer files
1125  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
1126  character(len=*), intent(in) :: input_fname !< ascii input file name
1127  integer(I4B), intent(in) :: iout !< unit number for output
1128  real(DP), dimension(:, :), pointer, contiguous :: dbl2d
1129  integer(I4B) :: nlay
1130  integer(I4B) :: nsize1, nsize2
1131  integer(I4B), dimension(:), allocatable :: array_shape
1132  integer(I4B), dimension(:), allocatable :: layer_shape
1133  character(len=LINELENGTH) :: keyword
1134 
1135  ! determine the array shape from the input data definition (idt%shape),
1136  ! which looks like "NCOL, NROW, NLAY"
1137  call get_shape_from_string(idt%shape, array_shape, mf6_input%mempath)
1138  nsize1 = array_shape(1)
1139  nsize2 = array_shape(2)
1140 
1141  ! create a new 3d memory managed variable
1142  call mem_allocate(dbl2d, nsize1, nsize2, idt%mf6varname, mf6_input%mempath)
1143 
1144  ! read keyword
1145  keyword = ''
1146  call parser%GetStringCaps(keyword)
1147 
1148  ! check for "NETCDF" and "LAYERED"
1149  if (keyword == 'NETCDF') then
1150  call netcdf_read_array(dbl2d, mshape, idt, mf6_input, nc_vars, &
1151  input_fname, iout)
1152  else if (keyword == 'LAYERED' .and. idt%layered) then
1153  call get_layered_shape(mshape, nlay, layer_shape)
1154  call read_dbl2d_layered(parser, dbl2d, idt%mf6varname, nlay, layer_shape)
1155  else
1156  call read_dbl2d(parser, dbl2d, idt%mf6varname)
1157  end if
1158 
1159  ! log information on the loaded array to the list file
1160  call idm_log_var(dbl2d, idt%tagname, mf6_input%mempath, iout)
1161 
1162  ! create export file for griddata parameters if optioned
1163  if (export) then
1164  if (idt%blockname == 'GRIDDATA') then
1165  call idm_export(dbl2d, idt%tagname, mf6_input%mempath, idt%shape, iout)
1166  end if
1167  end if
1168  end subroutine load_double2d_type
1169 
1170  !> @brief load type 3d double
1171  !<
1172  subroutine load_double3d_type(parser, idt, mf6_input, mshape, export, &
1173  nc_vars, input_fname, iout)
1176  type(blockparsertype), intent(inout) :: parser !< block parser
1177  type(inputparamdefinitiontype), intent(in) :: idt !< input data type object describing this record
1178  type(modflowinputtype), intent(in) :: mf6_input !< description of input
1179  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: mshape !< model shape
1180  logical(LGP), intent(in) :: export !< export to ascii layer files
1181  type(ncpackagevarstype), pointer, intent(in) :: nc_vars
1182  character(len=*), intent(in) :: input_fname !< ascii input file name
1183  integer(I4B), intent(in) :: iout !< unit number for output
1184  real(DP), dimension(:, :, :), pointer, contiguous :: dbl3d
1185  integer(I4B) :: nlay
1186  integer(I4B) :: nsize1, nsize2, nsize3
1187  integer(I4B), dimension(:), allocatable :: array_shape
1188  integer(I4B), dimension(:), allocatable :: layer_shape
1189  real(DP), dimension(:), pointer, contiguous :: dbl1d_ptr
1190  character(len=LINELENGTH) :: keyword
1191 
1192  ! determine the array shape from the input data definition (idt%shape),
1193  ! which looks like "NCOL, NROW, NLAY"
1194  call get_shape_from_string(idt%shape, array_shape, mf6_input%mempath)
1195  nsize1 = array_shape(1)
1196  nsize2 = array_shape(2)
1197  nsize3 = array_shape(3)
1198 
1199  ! create a new 3d memory managed variable
1200  call mem_allocate(dbl3d, nsize1, nsize2, nsize3, idt%mf6varname, &
1201  mf6_input%mempath)
1202 
1203  ! read keyword
1204  keyword = ''
1205  call parser%GetStringCaps(keyword)
1206 
1207  ! check for "NETCDF" and "LAYERED"
1208  if (keyword == 'NETCDF') then
1209  call netcdf_read_array(dbl3d, mshape, idt, mf6_input, nc_vars, &
1210  input_fname, iout)
1211  else if (keyword == 'LAYERED' .and. idt%layered) then
1212  call get_layered_shape(mshape, nlay, layer_shape)
1213  call read_dbl3d_layered(parser, dbl3d, idt%mf6varname, nlay, &
1214  layer_shape)
1215  else
1216  dbl1d_ptr(1:nsize1 * nsize2 * nsize3) => dbl3d(:, :, :)
1217  call read_dbl1d(parser, dbl1d_ptr, idt%mf6varname)
1218  end if
1219 
1220  ! log information on the loaded array to the list file
1221  call idm_log_var(dbl3d, idt%tagname, mf6_input%mempath, iout)
1222 
1223  ! create export file for griddata parameters if optioned
1224  if (export) then
1225  if (idt%blockname == 'GRIDDATA') then
1226  call idm_export(dbl3d, idt%tagname, mf6_input%mempath, idt%shape, iout)
1227  end if
1228  end if
1229  end subroutine load_double3d_type
1230 
1231  function read_control_record(parser, oc_inunit, iout) result(ibinary)
1232  use simmodule, only: store_error_unit
1233  use inputoutputmodule, only: urword
1234  use inputoutputmodule, only: openfile
1235  use openspecmodule, only: form, access
1236  use constantsmodule, only: linelength
1238  type(blockparsertype), intent(inout) :: parser
1239  integer(I4B), intent(inout) :: oc_inunit
1240  integer(I4B), intent(in) :: iout
1241  integer(I4B) :: ibinary
1242  integer(I4B) :: lloc, istart, istop, idum, inunit, itmp, ierr
1243  integer(I4B) :: nunopn = 99
1244  character(len=:), allocatable :: line
1245  character(len=LINELENGTH) :: fname
1246  logical(LGP) :: exists
1247  real(dp) :: r
1248  character(len=*), parameter :: fmtocne = &
1249  &"('Specified OPEN/CLOSE file ',(A),' does not exist')"
1250  character(len=*), parameter :: fmtobf = &
1251  &"(1X,/1X,'OPENING BINARY FILE ON UNIT ',I0,':',/1X,A)"
1252 
1253  ! initialize oc_inunit and ibinary
1254  oc_inunit = 0
1255  ibinary = 0
1256  inunit = parser%getunit()
1257 
1258  ! Read to the first non-commented line
1259  lloc = 1
1260  call parser%line_reader%rdcom(inunit, iout, line, ierr)
1261  call urword(line, lloc, istart, istop, 1, idum, r, iout, inunit)
1262 
1263  if (line(istart:istop) == 'OPEN/CLOSE') then
1264  ! get filename
1265  call urword(line, lloc, istart, istop, 0, idum, r, &
1266  iout, inunit)
1267  fname = line(istart:istop)
1268  ! check to see if file OPEN/CLOSE file exists
1269  inquire (file=fname, exist=exists)
1270  if (.not. exists) then
1271  write (errmsg, fmtocne) line(istart:istop)
1272  call store_error(errmsg)
1273  call store_error('Specified OPEN/CLOSE file does not exist')
1274  call store_error_unit(inunit)
1275  end if
1276 
1277  ! Check for (BINARY) keyword
1278  call urword(line, lloc, istart, istop, 1, idum, r, &
1279  iout, inunit)
1280 
1281  if (line(istart:istop) == '(BINARY)') ibinary = 1
1282  ! Open the file depending on ibinary flag
1283  if (ibinary == 1) then
1284  oc_inunit = nunopn
1285  itmp = iout
1286  if (iout > 0) then
1287  itmp = 0
1288  write (iout, fmtobf) oc_inunit, trim(adjustl(fname))
1289  end if
1290  call openfile(oc_inunit, itmp, fname, 'OPEN/CLOSE', &
1291  fmtarg_opt=form, accarg_opt=access)
1292  end if
1293  end if
1294 
1295  if (ibinary == 0) then
1296  call parser%line_reader%bkspc(parser%getunit())
1297  end if
1298  end function read_control_record
1299 
1300  !> @brief Save structarray pointer for deferred TS linking
1301  !!
1302  !! Saves the current structarray pointer when it contains TS string locs,
1303  !! then nullifies the pointer so load_block does not destroy it.
1304  !<
1305  subroutine save_ts_sa(this)
1306  class(loadmf6filetype), intent(inout) :: this
1307  type(structvectortype), pointer :: svect
1308  type(staticsatype), allocatable :: tmp(:)
1309  logical(LGP) :: has_ts
1310  integer(I4B) :: m, n
1311 
1312  ! check if any column has deferred TS strlocs
1313  has_ts = .false.
1314  do m = 1, this%structarray%count()
1315  svect => this%structarray%get(m)
1316  if (svect%idt%timeseries .and. svect%ts_strlocs%count() > 0) then
1317  has_ts = .true.
1318  exit
1319  end if
1320  end do
1321 
1322  if (has_ts) then
1323  n = size(this%ts_sas)
1324  allocate (tmp(n + 1))
1325  tmp(1:n) = this%ts_sas
1326  tmp(n + 1)%sa => this%structarray
1327  call move_alloc(tmp, this%ts_sas)
1328  ! nullify so load_block does not destroy the saved SA
1329  nullify (this%structarray)
1330  end if
1331  end subroutine save_ts_sa
1332 
1333  !> @brief Clean up saved static structarrays
1334  !!
1335  !! Called from destroy() of dynamic loaders.
1336  !<
1337  subroutine cleanup(this)
1339  class(loadmf6filetype), intent(inout) :: this
1340  integer(I4B) :: n
1341  do n = 1, size(this%ts_sas)
1342  if (associated(this%ts_sas(n)%sa)) then
1343  call destructstructarray(this%ts_sas(n)%sa)
1344  nullify (this%ts_sas(n)%sa)
1345  end if
1346  end do
1347  deallocate (this%ts_sas)
1348  end subroutine cleanup
1349 
1350 end module loadmf6filemodule
subroutine init()
Definition: GridSorting.f90:25
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
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
integer(i4b), parameter lenbigline
maximum length of a big line
Definition: Constants.f90:15
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition: Constants.f90:35
This module contains the DefinitionSelectModule.
subroutine, public split_record_dfn_tag1(input_definition_types, component_type, subcomponent_type, tagname, nwords, words)
Return aggregate definition.
type(inputparamdefinitiontype) function, pointer, public get_aggregate_definition_type(input_definition_types, component_type, subcomponent_type, blockname)
Return aggregate definition.
subroutine, public split_record_dfn_tag2(input_definition_types, component_type, subcomponent_type, tagname, tag2, nwords, words)
Return aggregate definition.
character(len=linelength) function, public idt_datatype(idt)
return input definition type datatype
type(inputparamdefinitiontype) function, pointer, public get_param_definition_type(input_definition_types, component_type, subcomponent_type, blockname, tagname, filename, found)
Return parameter definition.
subroutine, public read_dbl1d(parser, dbl1d, aname)
subroutine, public read_dbl2d(parser, dbl2d, aname)
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 Input Data Model Logger Module.
Definition: IdmLogger.f90:7
subroutine, public idm_log_close(component, subcomponent, iout)
@ brief log the closing message
Definition: IdmLogger.f90:56
subroutine, public idm_log_header(component, subcomponent, iout)
@ brief log a header message
Definition: IdmLogger.f90:44
Input definition module.
subroutine, public urdaux(naux, inunit, iout, lloc, istart, istop, auxname, line, text)
Read auxiliary variables from an input line.
subroutine, public parseline(line, nwords, words, inunit, filename)
Parse a line into words.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
subroutine, public urword(line, icol, istart, istop, ncode, n, r, iout, in)
Extract a word from a string.
subroutine, public read_int1d(parser, int1d, aname)
subroutine, public read_int2d(parser, int2d, aname)
This module defines variable data types.
Definition: kind.f90:8
subroutine, public read_int1d_layered(parser, int1d, aname, nlay, layer_shape)
subroutine, public read_dbl1d_layered(parser, dbl1d, aname, nlay, layer_shape)
subroutine, public read_dbl2d_layered(parser, dbl2d, aname, nlay, layer_shape)
subroutine, public read_int3d_layered(parser, int3d, aname, nlay, layer_shape)
subroutine, public read_dbl3d_layered(parser, dbl3d, aname, nlay, layer_shape)
subroutine, public read_int2d_layered(parser, int2d, aname, nlay, layer_shape)
Load context for IDM generic dynamic loaders.
Definition: LoadContext.f90:10
logical(lgp) function, public is_feature_keystring(mf6_input)
.true. if mf6_input's PERIOD block is feature-addressed (see is_feature_tag). Block-independent,...
This module contains the LoadMf6FileModule.
Definition: LoadMf6File.f90:8
subroutine cleanup(this)
Clean up saved static structarrays.
type(inputparamdefinitiontype) function block_index_dfn(this, iblk)
subroutine load_integer1d_type(parser, idt, mf6_input, mshape, export, nc_vars, input_fname, iout)
load type 1d integer
subroutine load_io_tag(parser, idt, memoryPath, which, iout)
load io tag
subroutine load_double3d_type(parser, idt, mf6_input, mshape, export, nc_vars, input_fname, iout)
load type 3d double
subroutine load_string_type(parser, idt, memoryPath, iout)
load type string
type(structarraytype) function, pointer get_ts_sa(this, n)
Return the n-th saved static StructArray pointer.
subroutine load_keyword_type(parser, idt, memoryPath, iout)
load type keyword
subroutine load_auxvar_names(parser, idt, memoryPath, iout)
load aux variable names
subroutine load_double1d_type(parser, idt, mf6_input, mshape, export, nc_vars, input_fname, iout)
load type 1d double
subroutine load_block(this, iblk)
load a single block
subroutine parse_io_tag(this, iblk, pkgtype, which, tag)
subroutine save_ts_sa(this)
Save structarray pointer for deferred TS linking.
subroutine load_double2d_type(parser, idt, mf6_input, mshape, export, nc_vars, input_fname, iout)
load type 2d double
subroutine load_integer_type(parser, idt, memoryPath, iout)
load type integer
recursive subroutine parse_block(this, iblk, recursive_call)
parse block
subroutine load_integer3d_type(parser, idt, mf6_input, mshape, export, nc_vars, input_fname, iout)
load type 3d integer
subroutine block_post_process(this, iblk)
Post parse block handling.
integer(i4b) function ts_sa_count(this)
Return number of saved static StructArrays with deferred TS strlocs.
subroutine finalize(this)
finalize
subroutine load_tag(this, iblk, idt)
load input keyword Load input associated with tag key into the memory manager.
subroutine load_double_type(parser, idt, memoryPath, iout)
load type double
subroutine load_integer2d_type(parser, idt, mf6_input, mshape, export, nc_vars, input_fname, iout)
load type 2d integer
subroutine parse_structarray_block(this, iblk)
parse a structured array record into memory manager
subroutine load(this, parser, mf6_input, nc_vars, filename, iout)
load all static input blocks
Definition: LoadMf6File.f90:97
integer(i4b) function, public read_control_record(parser, oc_inunit, iout)
recursive subroutine parse_record_tag(this, iblk, inidt, recursive_call)
This module contains the LoadNCInputModule.
Definition: LoadNCInput.F90:7
subroutine, public get_from_memorystore(name, mem_path, mt, found, check)
@ brief Get a memory type entry from the memory list
subroutine, public get_isize(name, mem_path, isize)
@ brief Get the number of elements for this variable
subroutine, public get_mem_rank(name, mem_path, rank)
@ brief Get the variable rank
This module contains the ModflowInputModule.
Definition: ModflowInput.f90:9
This module contains the NCFileVarsModule.
Definition: NCFileVars.f90:7
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.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_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:169
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
This module contains the SourceCommonModule.
Definition: SourceCommon.f90:7
subroutine, public get_layered_shape(mshape, nlay, layer_shape)
subroutine, public get_shape_from_string(shape_string, array_shape, memoryPath)
subroutine, public set_model_shape(ftype, fname, model_mempath, dis_mempath, model_shape)
routine for setting the model shape
This module contains the StructArrayModule.
Definition: StructArray.f90:8
subroutine, public destructstructarray(struct_array)
destructor for a struct_array
type(structarraytype) function, pointer, public constructstructarray(mf6_input, ncol, nrow, blocknum, mempath, component_mempath, size_init)
constructor for a struct_array
Definition: StructArray.f90:90
This module contains the StructVectorModule.
Definition: StructVector.f90:7
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
Input parameter definition. Describes an input parameter.
Input load context for generic dynamic loaders and StructArray based static loads....
Definition: LoadContext.f90:75
Static parser based input loader.
Definition: LoadMf6File.f90:54
Fortran workaround for allocatable arrays of pointers; wraps a StructArray pointer for deferred TS li...
Definition: LoadMf6File.f90:44
derived type for storing input definition for a file
Type describing input variables for a package in NetCDF file.
Definition: NCFileVars.f90:22
type for structured array
Definition: StructArray.f90:47
derived type for generic vector