MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
Mf6FileKeystring.f90
Go to the documentation of this file.
1 !> @brief Period block keystring-based input loader
2 !!
3 !! Each keystring member maps to a typed column in a StructArrayType.
4 !! A dispatch keyword on each input row selects the target column.
5 !!
6 !! Simple dispatch: keyword matches a DOUBLE/STRING/INTEGER column;
7 !! one value token is read into that column.
8 !!
9 !! Compound dispatch: keyword matches a KEYWORD-type column (e.g.
10 !! FLOWING_WELL). The keyword token is stored directly; subsequent
11 !! non-KEYWORD sub-member columns are read in order.
12 !!
13 !<
15 
16  use kindmodule, only: i4b, lgp
29 
30  implicit none
31  private
32  public :: keystringloadtype
33 
34  !> @brief Keystring period block loader
35  !!
36  !! Leading fixed columns (e.g. CELLID) followed by a dispatch
37  !! keyword that routes each input row to a typed member column.
38  !!
39  !<
41  type(timeseriesmanagertype), pointer :: tsmanager => null()
42  type(structarraytype), pointer :: structarray => null()
43  type(loadcontexttype) :: ctx !< input load context
44  type(loadmf6filetype) :: static_loader !< persistent static loader
45  logical(LGP) :: ts_active !< .true. if TS files are loaded
46  integer(I4B) :: nleading !< number of leading (pre-keystring) columns
47  contains
48  procedure :: ainit
49  procedure :: df
50  procedure :: ad
51  procedure :: rp
52  procedure :: reset
53  procedure :: destroy
54  procedure :: create_structarray
55  end type keystringloadtype
56 
57 contains
58 
59  subroutine ainit(this, mf6_input, component_name, component_input_name, &
60  input_name, iperblock, parser, iout)
61  use inputoutputmodule, only: getunit
66  class(keystringloadtype), intent(inout) :: this
67  type(modflowinputtype), intent(in) :: mf6_input
68  character(len=*), intent(in) :: component_name
69  character(len=*), intent(in) :: component_input_name
70  character(len=*), intent(in) :: input_name
71  integer(I4B), intent(in) :: iperblock
72  type(blockparsertype), pointer, intent(inout) :: parser
73  integer(I4B), intent(in) :: iout
74  type(characterstringtype), dimension(:), pointer, contiguous :: ts_fnames
75  character(len=LINELENGTH) :: fname
76  character(len=LENVARNAME), allocatable :: named_bound(:)
77  character(len=LINELENGTH), dimension(:), allocatable :: member_names
78  integer(I4B) :: n, nmembers, isize
79 
80  call this%DynamicPkgLoadType%init(mf6_input, component_name, &
81  component_input_name, input_name, &
82  iperblock, iout)
83  this%ts_active = .false.
84  this%nleading = 0
85 
86  allocate (this%tsmanager)
87  call tsmanager_cr(this%tsmanager, iout)
88 
89  ! load static input (TS6_FILENAME tag sets static_loader%ts_active)
90  call this%static_loader%load(parser, mf6_input, this%nc_vars, &
91  this%input_name, iout)
92 
93  ! add declared TS files to tsmanager
94  if (this%static_loader%ts_active) then
95  this%ts_active = .true.
96  call get_isize('TS6_FILENAME', mf6_input%mempath, isize)
97  if (isize > 0) then
98  call mem_setptr(ts_fnames, 'TS6_FILENAME', mf6_input%mempath)
99  do n = 1, size(ts_fnames)
100  fname = ts_fnames(n)
101  call this%tsmanager%add_tsfile(fname, getunit())
102  end do
103  end if
104  end if
105 
106  ! collect DIMENSIONS block parameter names for LoadContext;
107  ! absent for TVK/TVS — LoadContext falls back to nodes * nmembers
108  do n = 1, size(mf6_input%param_dfns)
109  if (mf6_input%param_dfns(n)%blockname == 'DIMENSIONS') then
110  call expandarray(named_bound)
111  named_bound(size(named_bound)) = trim(mf6_input%param_dfns(n)%mf6varname)
112  end if
113  end do
114 
115  ! init load context
116  if (allocated(named_bound)) then
117  call this%ctx%init(mf6_input, named_bound=named_bound)
118  else
119  call this%ctx%init(mf6_input)
120  end if
121 
122  call this%ctx%tags(this%param_names, this%nparam, this%input_name)
123  this%nleading = this%ctx%nleading
124 
125  ! append keystring member column names
126  call this%ctx%keystring_member_names(member_names, nmembers)
127  do n = 1, nmembers
128  this%nparam = this%nparam + 1
129  call expandarray(this%param_names)
130  this%param_names(this%nparam) = trim(member_names(n))
131  end do
132 
133  ! finalize context setup (allocates NBOUND, NODEULIST, etc.)
134  call this%ctx%allocate_arrays()
135 
136  ! pre-allocate structarray; reused across all periods
137  call this%create_structarray()
138  end subroutine ainit
139 
140  subroutine df(this)
142  class(keystringloadtype), intent(inout) :: this
143  type(structarraytype), pointer :: sa
144  integer(I4B) :: n
145  ! init tsmanager (TDIS now available)
146  call this%tsmanager%tsmanager_df()
147  ! link static TS strlocs; preserve for re-registration after reset()
148  do n = 1, this%static_loader%ts_sa_count()
149  sa => this%static_loader%get_ts_sa(n)
150  if (associated(sa)) then
151  call sa%ts_update(this%tsmanager, &
152  this%mf6_input%subcomponent_name, &
153  this%ctx%iprpak, this%input_name, &
154  clear_strlocs=.false.)
155  end if
156  end do
157  end subroutine df
158 
159  subroutine ad(this)
160  class(keystringloadtype), intent(inout) :: this
161  call this%tsmanager%ad()
162  end subroutine ad
163 
164  subroutine rp(this, parser)
166  class(keystringloadtype), intent(inout) :: this
167  type(blockparsertype), pointer, intent(inout) :: parser
168 
169  call this%reset()
170 
171  call idm_log_header(this%mf6_input%component_name, &
172  this%mf6_input%subcomponent_name, this%iout)
173 
174  this%ctx%nbound = &
175  this%structarray%read_from_parser_keystring(parser, this%ts_active, &
176  this%nleading, this%iout, &
177  this%input_name)
178 
179  if (this%ts_active) then
180  call this%structarray%ts_update(this%tsmanager, &
181  this%mf6_input%subcomponent_name, &
182  this%ctx%iprpak, this%input_name)
183  end if
184 
185  call idm_log_close(this%mf6_input%component_name, &
186  this%mf6_input%subcomponent_name, this%iout)
187  end subroutine rp
188 
189  subroutine reset(this)
191  class(keystringloadtype), intent(inout) :: this
192  type(structarraytype), pointer :: sa
193  integer(I4B) :: n
194  ! clear TS links
195  call this%tsmanager%reset(this%mf6_input%subcomponent_name)
196  ! re-register static TS links (strlocs preserved in df)
197  if (this%ts_active) then
198  do n = 1, this%static_loader%ts_sa_count()
199  sa => this%static_loader%get_ts_sa(n)
200  if (associated(sa)) then
201  call sa%ts_update(this%tsmanager, &
202  this%mf6_input%subcomponent_name, &
203  this%ctx%iprpak, this%input_name, &
204  clear_strlocs=.false.)
205  end if
206  end do
207  end if
208  end subroutine reset
209 
210  subroutine destroy(this)
211  class(keystringloadtype), intent(inout) :: this
212 
213  call this%static_loader%cleanup()
214 
215  call this%tsmanager%da()
216  deallocate (this%tsmanager)
217  nullify (this%tsmanager)
218 
219  if (associated(this%structarray)) then
220  call destructstructarray(this%structarray)
221  end if
222 
223  call this%ctx%destroy()
224  call this%DynamicPkgLoadType%destroy()
225  end subroutine destroy
226 
227  subroutine create_structarray(this)
230  use inputoutputmodule, only: upcase
231  class(keystringloadtype), intent(inout) :: this
232  type(inputparamdefinitiontype), pointer :: idt, pidt
233  character(len=LINELENGTH), allocatable :: rec_cols(:)
234  character(len=LINELENGTH) :: kwname, first_col
235  integer(I4B) :: icol, nrow_prealloc, jparam, nrec_col, nsub
236 
237  ! use pre-allocated managed memory (maxbound = features * nmembers);
238  ! fall back to deferred shape (-1) if maxbound is unavailable
239  if (associated(this%ctx%maxbound) .and. this%ctx%maxbound > 0) then
240  nrow_prealloc = this%ctx%maxbound
241  else
242  nrow_prealloc = -1
243  end if
244 
245  this%structarray => constructstructarray(this%mf6_input, this%nparam, &
246  nrow_prealloc, 0, &
247  this%mf6_input%mempath, &
248  this%mf6_input%component_mempath)
249  do icol = 1, this%nparam
250  idt => get_param_definition_type(this%mf6_input%param_dfns, &
251  this%mf6_input%component_type, &
252  this%mf6_input%subcomponent_type, &
253  'PERIOD', &
254  this%param_names(icol), this%input_name)
255  call this%structarray%mem_create_vector(icol, idt)
256 
257  ! For KEYWORD member columns, store the compound sub-member count
258  ! from the RECORD definition so read_from_parser_keystring reads
259  ! exactly the right number of sub-values.
260  if (trim(idt%datatype) == 'KEYWORD' .and. icol > this%nleading) then
261  kwname = trim(idt%tagname)
262  call upcase(kwname)
263  nsub = 0
264  do jparam = 1, size(this%mf6_input%param_dfns)
265  pidt => this%mf6_input%param_dfns(jparam)
266  if (pidt%blockname /= 'PERIOD') cycle
267  if (pidt%datatype(1:6) /= 'RECORD') cycle
268  call idt_parse_rectype(pidt, rec_cols, nrec_col)
269  if (nrec_col >= 1) then
270  first_col = trim(rec_cols(1))
271  call upcase(first_col)
272  if (trim(first_col) == trim(kwname)) then
273  nsub = nrec_col - 1
274  if (allocated(rec_cols)) deallocate (rec_cols)
275  exit
276  end if
277  end if
278  if (allocated(rec_cols)) deallocate (rec_cols)
279  end do
280  this%structarray%struct_vectors(icol)%nsubmembers = nsub
281  end if
282  end do
283  end subroutine create_structarray
284 
285 end module mf6filekeystringmodule
This module contains the AsciiInputLoadTypeModule.
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
This module contains the DefinitionSelectModule.
subroutine, public idt_parse_rectype(idt, cols, ncol)
allocate and set RECARRAY, KEYSTRING or RECORD param list
type(inputparamdefinitiontype) function, pointer, public get_param_definition_type(input_definition_types, component_type, subcomponent_type, blockname, tagname, filename, found)
Return parameter definition.
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.
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public upcase(word)
Convert to upper case.
This module defines variable data types.
Definition: kind.f90:8
This module contains the LoadContextModule.
Definition: LoadContext.f90:10
This module contains the LoadMf6FileModule.
Definition: LoadMf6File.f90:8
subroutine, public get_isize(name, mem_path, isize)
@ brief Get the number of elements for this variable
Period block keystring-based input loader.
subroutine ainit(this, mf6_input, component_name, component_input_name, input_name, iperblock, parser, iout)
subroutine create_structarray(this)
subroutine rp(this, parser)
This module contains the ModflowInputModule.
Definition: ModflowInput.f90:9
This module contains the StructArrayModule.
Definition: StructArray.f90:8
type(structarraytype) function, pointer, public constructstructarray(mf6_input, ncol, nrow, blocknum, mempath, component_mempath)
constructor for a struct_array
Definition: StructArray.f90:80
subroutine, public destructstructarray(struct_array)
destructor for a struct_array
subroutine, public tsmanager_cr(this, iout, removeTsLinksOnCompletion, extendTsToEndOfSimulation)
Create the tsmanager.
base abstract type for ascii source dynamic load
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.
derived type for boundary package input context
Definition: LoadContext.f90:65
Static parser based input loader.
Definition: LoadMf6File.f90:54
derived type for storing input definition for a file
type for structured array
Definition: StructArray.f90:41