MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
SourceCommon.f90
Go to the documentation of this file.
1 !> @brief This module contains the SourceCommonModule
2 !!
3 !! This module contains source independent input
4 !! processing helper routines.
5 !!
6 !<
8 
9  use kindmodule, only: dp, i4b, lgp
10  use simvariablesmodule, only: errmsg
14 
15  implicit none
16  private
17  public :: package_source_type
19  public :: set_model_shape
20  public :: get_shape_from_string
21  public :: get_layered_shape
22  public :: file_ext
23  public :: ifind_charstr
24  public :: filein_fname
25  public :: inlen_check
26 
27 contains
28 
29  !> @brief source identifier from model namfile FNAME array
30  !!
31  !! Return the source type for a package listed in the
32  !! model nam file packages block FNAME field.
33  !!
34  !<
35  function package_source_type(sourcename) result(sourcetype)
36  ! -- modules
37  use inputoutputmodule, only: upcase
38  ! -- dummy
39  character(len=*), intent(in) :: sourcename
40  ! -- result
41  character(len=LENPACKAGENAME) :: sourcetype
42  ! -- local
43  character(len=LENPACKAGENAME) :: ext
44  !
45  ext = file_ext(sourcename)
46  !
47  select case (ext)
48  case default
49  sourcetype = 'MF6FILE'
50  end select
51  end function package_source_type
52 
53  !> @brief component from package or model type
54  !!
55  !! Return the component type typically derived from package file type,
56  !! i.e. return GWF when input is GWF6. This function checks the
57  !! resultant component type and throws a terminating error if not
58  !! supported by IDM in some capacity.
59  !!
60  !<
61  function idm_component_type(component) result(component_type)
62  ! -- modules
64  ! -- dummy
65  character(len=*), intent(in) :: component
66  ! -- return
67  character(len=LENCOMPONENTNAME) :: component_type
68  ! -- local
69  integer(I4B) :: i, ilen, idx
70  !
71  ! -- initialize
72  component_type = ''
73  idx = 0
74  !
75  ilen = len_trim(component)
76  do i = 1, ilen
77  if (component(i:i) == '6' .or. component(i:i) == '-') then
78  else
79  idx = idx + 1
80  component_type(idx:idx) = component(i:i)
81  end if
82  end do
83  !
84  if (.not. idm_component(component_type)) then
85  write (errmsg, '(a)') &
86  'IDP input error, unrecognized component: "'//trim(component)//'"'
87  call store_error(errmsg, .true.)
88  end if
89  end function idm_component_type
90 
91  !> @brief component from package or model type
92  !!
93  !! Return the subcomponent type typically derived from package file type,
94  !! i.e. return CHD when input is CHD6. Note this function is called on
95  !! file types that are both idm integrated and not and should not set
96  !! an error based on this difference.
97  !!
98  !<
99  function idm_subcomponent_type(component, subcomponent) &
100  result(subcomponent_type)
101  ! -- modules
102  ! -- dummy
103  character(len=*), intent(in) :: component !< component, e.g. GWF6
104  character(len=*), intent(in) :: subcomponent !< subcomponent, e.g. CHD6
105  ! -- return
106  character(len=LENCOMPONENTNAME) :: subcomponent_type
107  ! -- local
108  character(len=LENCOMPONENTNAME) :: component_type
109  integer(I4B) :: i, ilen, idx
110  !
111  ! -- initialize
112  subcomponent_type = ''
113  idx = 0
114  !
115  ! -- verify component
116  component_type = idm_component_type(component)
117  !
118  ilen = len_trim(subcomponent)
119  do i = 1, ilen
120  if (subcomponent(i:i) == '6' .or. subcomponent(i:i) == '-') then
121  else
122  idx = idx + 1
123  subcomponent_type(idx:idx) = subcomponent(i:i)
124  end if
125  end do
126  end function idm_subcomponent_type
127 
128  !> @brief model package subcomponent name
129  !!
130  !! Return the IDM component name, which is the package type for
131  !! base packages and the package name for multi package (i.e.
132  !! stress) types.
133  !!
134  !<
135  function idm_subcomponent_name(component_type, subcomponent_type, sc_name) &
136  result(subcomponent_name)
137  ! -- modules
139  ! -- dummy
140  character(len=*), intent(in) :: component_type
141  character(len=*), intent(in) :: subcomponent_type
142  character(len=*), intent(in) :: sc_name
143  ! -- return
144  character(len=LENPACKAGENAME) :: subcomponent_name
145  ! -- local
146  !
147  subcomponent_name = ''
148  !
149  if (idm_multi_package(component_type, subcomponent_type)) then
150  !
151  subcomponent_name = sc_name
152  else
153  !
154  subcomponent_name = subcomponent_type
155  end if
156  end function idm_subcomponent_name
157 
158  !> @brief input file extension
159  !!
160  !! Return a file extension, or an empty string if
161  !! not identified.
162  !!
163  !<
164  function file_ext(filename) result(ext)
165  ! -- modules
167  ! -- dummy
168  character(len=*), intent(in) :: filename
169  ! -- return
170  character(len=LENPACKAGETYPE) :: ext
171  ! -- local
172  integer(I4B) :: idx
173  !
174  ! -- initialize
175  ext = ''
176  idx = 0
177  !
178  ! -- identify '.' character position from back of string
179  idx = index(filename, '.', back=.true.)
180  !
181  !
182  if (idx > 0) then
183  ext = filename(idx + 1:len_trim(filename))
184  end if
185  end function file_ext
186 
187  subroutine get_shape_from_string(shape_string, array_shape, memoryPath)
188  use inputoutputmodule, only: parseline
190  character(len=*), intent(in) :: shape_string
191  integer(I4B), dimension(:), allocatable, intent(inout) :: array_shape
192  character(len=*), intent(in) :: memorypath !< memorypath to put loaded information
193  integer(I4B) :: ndim
194  integer(I4B) :: i
195  integer(I4B), pointer :: int_ptr
196  character(len=16), dimension(:), allocatable :: array_shape_string
197  character(len=:), allocatable :: shape_string_copy
198  !
199  ! -- parse the string into multiple words
200  shape_string_copy = trim(shape_string)//' '
201  call parseline(shape_string_copy, ndim, array_shape_string)
202  allocate (array_shape(ndim))
203  !
204  ! -- find shape in memory manager and put into array_shape
205  do i = 1, ndim
206  call mem_setptr(int_ptr, array_shape_string(i), memorypath)
207  array_shape(i) = int_ptr
208  end do
209  end subroutine get_shape_from_string
210 
211  subroutine get_layered_shape(mshape, nlay, layer_shape)
212  integer(I4B), dimension(:), intent(in) :: mshape
213  integer(I4B), intent(out) :: nlay
214  integer(I4B), dimension(:), allocatable, intent(out) :: layer_shape
215  integer(I4B) :: ndim
216 
217  ndim = size(mshape)
218  nlay = 0
219 
220  if (ndim == 1) then ! disu
221  nlay = 1
222  allocate (layer_shape(1))
223  layer_shape(1) = mshape(1)
224  else if (ndim == 2) then ! disv
225  nlay = mshape(1)
226  allocate (layer_shape(1))
227  layer_shape(1) = mshape(2)
228  else if (ndim == 3) then ! disu
229  nlay = mshape(1)
230  allocate (layer_shape(2))
231  layer_shape(1) = mshape(3) ! ncol
232  layer_shape(2) = mshape(2) ! nrow
233  end if
234 
235  return
236  end subroutine get_layered_shape
237 
238  !> @brief routine for setting the model shape
239  !!
240  !! The model shape must be set in the memory manager because
241  !! individual packages need to know the shape of the arrays
242  !! to read.
243  !!
244  !<
245  subroutine set_model_shape(ftype, fname, model_mempath, dis_mempath, &
246  model_shape)
249  character(len=*), intent(in) :: ftype
250  character(len=*), intent(in) :: fname
251  character(len=*), intent(in) :: model_mempath
252  character(len=*), intent(in) :: dis_mempath
253  integer(I4B), dimension(:), pointer, contiguous, intent(inout) :: model_shape
254  integer(I4B), pointer :: ndim1
255  integer(I4B), pointer :: ndim2
256  integer(I4B), pointer :: ndim3
257  integer(I4B), pointer :: ncelldim
258  integer(I4B), pointer :: distype
259  integer(I4B) :: dim1_size, dim2_size, dim3_size, dis_type
260  !
261  ! -- initialize dis_type
262  dis_type = disundef
263  !
264  ! -- allocate and set model shape in model input context
265  select case (ftype)
266  case ('DIS6')
267  !
268  ! -- set dis_type
269  dis_type = dis
270  !
271  call get_isize('NLAY', dis_mempath, dim1_size)
272  call get_isize('NROW', dis_mempath, dim2_size)
273  call get_isize('NCOL', dis_mempath, dim3_size)
274  !
275  if (dim1_size <= 0) then
276  write (errmsg, '(a)') &
277  'Required input dimension "NLAY" not found.'
278  call store_error(errmsg)
279  end if
280  !
281  if (dim2_size <= 0) then
282  write (errmsg, '(a)') &
283  'Required input dimension "NROW" not found.'
284  call store_error(errmsg)
285  end if
286  !
287  if (dim3_size <= 0) then
288  write (errmsg, '(a)') &
289  'Required input dimension "NCOL" not found.'
290  call store_error(errmsg)
291  end if
292  !
293  if (dim1_size >= 1 .and. dim2_size >= 1 .and. dim3_size >= 1) then
294  call mem_allocate(model_shape, 3, 'MODEL_SHAPE', model_mempath)
295  call mem_setptr(ndim1, 'NLAY', dis_mempath)
296  call mem_setptr(ndim2, 'NROW', dis_mempath)
297  call mem_setptr(ndim3, 'NCOL', dis_mempath)
298  model_shape = [ndim1, ndim2, ndim3]
299  else
300  call store_error_filename(fname)
301  end if
302  !
303  case ('DIS2D6')
304  !
305  ! -- set dis_type
306  dis_type = dis2d
307  !
308  call get_isize('NROW', dis_mempath, dim1_size)
309  call get_isize('NCOL', dis_mempath, dim2_size)
310  !
311  if (dim1_size <= 0) then
312  write (errmsg, '(a)') &
313  'Required input dimension "NROW" not found.'
314  call store_error(errmsg)
315  end if
316  !
317  if (dim2_size <= 0) then
318  write (errmsg, '(a)') &
319  'Required input dimension "NCOL" not found.'
320  call store_error(errmsg)
321  end if
322  !
323  if (dim1_size >= 1 .and. dim2_size >= 1) then
324  call mem_allocate(model_shape, 2, 'MODEL_SHAPE', model_mempath)
325  call mem_setptr(ndim1, 'NROW', dis_mempath)
326  call mem_setptr(ndim2, 'NCOL', dis_mempath)
327  model_shape = [ndim1, ndim2]
328  else
329  call store_error_filename(fname)
330  end if
331  !
332  case ('DISV6')
333  !
334  ! -- set dis_type
335  dis_type = disv
336  !
337  call get_isize('NLAY', dis_mempath, dim1_size)
338  call get_isize('NCPL', dis_mempath, dim2_size)
339  !
340  if (dim1_size <= 0) then
341  write (errmsg, '(a)') &
342  'Required input dimension "NLAY" not found.'
343  call store_error(errmsg)
344  end if
345  !
346  if (dim2_size <= 0) then
347  write (errmsg, '(a)') &
348  'Required input dimension "NCPL" not found.'
349  call store_error(errmsg)
350  end if
351  !
352  if (dim1_size >= 1 .and. dim2_size >= 1) then
353  call mem_allocate(model_shape, 2, 'MODEL_SHAPE', model_mempath)
354  call mem_setptr(ndim1, 'NLAY', dis_mempath)
355  call mem_setptr(ndim2, 'NCPL', dis_mempath)
356  model_shape = [ndim1, ndim2]
357  else
358  call store_error_filename(fname)
359  end if
360  case ('DISV2D6')
361  !
362  call get_isize('NODES', dis_mempath, dim1_size)
363  !
364  if (dim1_size <= 0) then
365  write (errmsg, '(a)') &
366  'Required input dimension "NODES" not found.'
367  call store_error(errmsg)
368  end if
369  !
370  if (dim1_size >= 1) then
371  call mem_allocate(model_shape, 1, 'MODEL_SHAPE', model_mempath)
372  call mem_setptr(ndim1, 'NODES', dis_mempath)
373  model_shape = [ndim1]
374  else
375  call store_error_filename(fname)
376  end if
377  case ('DISU6', 'DISV1D6')
378  !
379  ! -- set dis_type
380  if (ftype == 'DISU6') then
381  dis_type = disu
382  else if (ftype == 'DISV1D6') then
383  dis_type = disv1d
384  end if
385  !
386  call get_isize('NODES', dis_mempath, dim1_size)
387  !
388  if (dim1_size <= 0) then
389  write (errmsg, '(a)') &
390  'Required input dimension "NODES" not found.'
391  call store_error(errmsg)
392  call store_error_filename(fname)
393  end if
394  !
395  call mem_allocate(model_shape, 1, 'MODEL_SHAPE', model_mempath)
396  call mem_setptr(ndim1, 'NODES', dis_mempath)
397  model_shape = [ndim1]
398  case default
399  errmsg = 'Unknown discretization type. IDM cannot set shape for "' &
400  //trim(ftype)//"'"
401  call store_error(errmsg)
402  call store_error_filename(fname)
403  end select
404  !
405  ! -- allocate and set ncelldim in model input context
406  call mem_allocate(ncelldim, 'NCELLDIM', model_mempath)
407  ncelldim = size(model_shape)
408  !
409  ! -- allocate and set distype in model input context
410  call mem_allocate(distype, 'DISENUM', model_mempath)
411  distype = dis_type
412  end subroutine set_model_shape
413 
414  function ifind_charstr(array, str)
416  ! -- Find the first array element containing str
417  ! -- Return -1 if not found.
418  implicit none
419  ! -- return
420  integer(I4B) :: ifind_charstr
421  ! -- dummy
422  type(characterstringtype), dimension(:), intent(in) :: array
423  character(len=*) :: str
424  character(len=LINELENGTH) :: compare_str
425  ! -- local
426  integer(I4B) :: i
427  !
428  ! -- initialize
429  ifind_charstr = -1
430  !
431  findloop: do i = 1, size(array)
432  compare_str = array(i)
433  if (compare_str == str) then
434  ifind_charstr = i
435  exit findloop
436  end if
437  end do findloop
438  end function ifind_charstr
439 
440  !> @brief enforce and set a single input filename provided via FILEIN keyword
441  !!
442  !! Set a FILEIN filename provided via an OPTIONS block.
443  !! Only use this function if a maximum of one FILEIN file name
444  !! string is expected.
445  !!
446  !! Return true if single FILEIN file name found and set, return
447  !! false if FILEIN tag not found.
448  !!
449  !<
450  function filein_fname(filename, tagname, input_mempath, input_fname) &
451  result(found)
454  character(len=*), intent(inout) :: filename
455  character(len=*), intent(in) :: tagname
456  character(len=*), intent(in) :: input_mempath
457  character(len=*), intent(in) :: input_fname
458  logical(LGP) :: found
459  type(characterstringtype), dimension(:), pointer, &
460  contiguous :: fnames
461  integer(I4B) :: isize
462  !
463  ! -- initialize
464  found = .false.
465  filename = ''
466  !
467  call get_isize(tagname, input_mempath, isize)
468  !
469  if (isize > 0) then
470  !
471  if (isize /= 1) then
472  errmsg = 'Multiple FILEIN keywords detected for tag "'//trim(tagname)// &
473  '" in OPTIONS block. Only one entry allowed.'
474  call store_error(errmsg)
475  call store_error_filename(input_fname)
476  end if
477  !
478  call mem_setptr(fnames, tagname, input_mempath)
479  !
480  filename = fnames(1)
481  found = .true.
482  !
483  end if
484  end function filein_fname
485 
486  !> @brief store an error for input exceeding internal name length
487  !<
488  subroutine inlen_check(input_name, mf6_name, maxlen, name_type)
490  type(characterstringtype), intent(in) :: input_name
491  character(len=*), intent(inout) :: mf6_name
492  integer(I4B), intent(in) :: maxlen
493  character(len=*), intent(in) :: name_type
494  character(len=LINELENGTH) :: input_str
495  integer(I4B) :: ilen
496  !
497  ! -- initialize
498  mf6_name = ''
499  input_str = input_name
500  ilen = len_trim(input_str)
501  if (ilen > maxlen) then
502  write (errmsg, '(a,i0,a)') &
503  'Input name "'//trim(input_str)//'" exceeds maximum allowed length (', &
504  maxlen, ') for '//trim(name_type)//'.'
505  call store_error(errmsg)
506  end if
507  !
508  ! -- set truncated name
509  mf6_name = trim(input_str)
510  end subroutine inlen_check
511 
512 end module sourcecommonmodule
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 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
@ disu
DISV6 discretization.
Definition: Constants.f90:157
@ dis
DIS6 discretization.
Definition: Constants.f90:155
@ disv1d
DISV1D6 discretization.
Definition: Constants.f90:160
@ dis2d
DIS2D6 discretization.
Definition: Constants.f90:163
@ disv
DISU6 discretization.
Definition: Constants.f90:156
@ disundef
undefined discretization
Definition: Constants.f90:153
logical function, public idm_component(component)
logical function, public idm_multi_package(component, subcomponent)
subroutine, public parseline(line, nwords, words, inunit, filename)
Parse a line into words.
subroutine, public upcase(word)
Convert to upper case.
This module defines variable data types.
Definition: kind.f90:8
subroutine, public get_isize(name, mem_path, isize)
@ brief Get the number of elements for this variable
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
This module contains the SourceCommonModule.
Definition: SourceCommon.f90:7
character(len=lenpackagename) function, public package_source_type(sourcename)
source identifier from model namfile FNAME array
subroutine, public get_layered_shape(mshape, nlay, layer_shape)
subroutine, public get_shape_from_string(shape_string, array_shape, memoryPath)
character(len=lencomponentname) function, public idm_subcomponent_type(component, subcomponent)
component from package or model type
subroutine, public inlen_check(input_name, mf6_name, maxlen, name_type)
store an error for input exceeding internal name length
subroutine, public set_model_shape(ftype, fname, model_mempath, dis_mempath, model_shape)
routine for setting the model shape
character(len=lencomponentname) function, public idm_component_type(component)
component from package or model type
character(len=lenpackagetype) function, public file_ext(filename)
input file extension
integer(i4b) function, public ifind_charstr(array, str)
character(len=lenpackagename) function, public idm_subcomponent_name(component_type, subcomponent_type, sc_name)
model package subcomponent name
logical(lgp) function, public filein_fname(filename, tagname, input_mempath, input_fname)
enforce and set a single input filename provided via FILEIN keyword
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23