MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
NCContextBuild.f90
Go to the documentation of this file.
1 !> @brief This module contains the NCContextBuildModule
2 !!
3 !! Read NetCDF input file and add modflow6 input variables
4 !1 information to internal NCFileVarsType structure.
5 !!
6 !<
8 
9  use kindmodule, only: dp, i4b, lgp
15  use netcdf
16 
17  implicit none
18  private
19  public :: open_ncfile
20  public :: create_netcdf_context
21 
22 contains
23 
24  !> @brief open netcdf file
25  !<
26  function open_ncfile(nc_fname, iout) result(ncid)
27  use netcdfcommonmodule, only: nc_fopen
28  character(len=*) :: nc_fname
29  integer(I4B) :: iout
30  integer(I4B) :: ncid
31  logical(LGP) :: exists
32 
33  ! initialize
34  ncid = 0
35 
36  ! check if NETCDF file exists
37  inquire (file=nc_fname, exist=exists)
38  if (.not. exists) then
39  write (errmsg, '(a,a,a)') 'Specified NetCDF input file does &
40  &not exist [file=', trim(nc_fname), '].'
41  call store_error(errmsg, .true.)
42  end if
43 
44  ! open
45  ncid = nc_fopen(nc_fname, iout)
46  end function open_ncfile
47 
48  !> @brief add a package input variable to nc_vars structure
49  !<
50  subroutine add_package_var(modeltype, modelname, nc_vars, input_name, varid, &
51  iout)
52  use inputoutputmodule, only: lowcase, upcase
56  character(len=*), intent(in) :: modeltype
57  character(len=*), intent(in) :: modelname
58  type(ncfilevarstype), intent(inout) :: nc_vars
59  character(len=*), intent(in) :: input_name
60  integer(I4B), intent(in) :: varid
61  integer(I4B), intent(in) :: iout
62  character(len=NETCDF_ATTR_STRLEN) :: input_str
63  character(len=LENCOMPONENTNAME) :: c_name, sc_name
64  character(len=LINELENGTH) :: mempath, varname
65  integer(I4B) :: layer, iaux, mf6_layer, mf6_iaux, idx
66  logical(LGP) :: success
67 
68  ! initialize
69  layer = -1
70  iaux = -1
71  mempath = ''
72  varname = ''
73  c_name = ''
74  sc_name = ''
75 
76  ! process mf6_input attribute
77  if (nf90_get_att(nc_vars%ncid, varid, 'modflow_input', &
78  input_str) == nf90_noerr) then
79  ! modflow_input is "<model>/<package>/<tagname>"; a tag name can be
80  ! longer than a memory variable name, so split on the last separator
81  idx = index(input_str, mempathseparator, back=.true.)
82  success = (idx > 1 .and. idx < len_trim(input_str))
83  if (success) then
84  mempath = input_str(:idx - 1)
85  varname = input_str(idx + 1:)
86  end if
87 
88  if (success) then
89  ! split the mempath
90  call split_mem_path(mempath, c_name, sc_name)
91  ! set read tokens to upper case
92  call upcase(varname)
93  call upcase(c_name)
94  call upcase(sc_name)
95  ! check for optional layer attribute
96  if (nf90_get_att(nc_vars%ncid, varid, &
97  'layer', mf6_layer) == nf90_noerr) then
98  layer = mf6_layer
99  end if
100 
101  ! check for optional iaux attribute
102  if (nf90_get_att(nc_vars%ncid, varid, &
103  'modflow_iaux', mf6_iaux) == nf90_noerr) then
104  iaux = mf6_iaux
105  end if
106 
107  ! add the variable to netcdf description
108  call nc_vars%add(sc_name, varname, layer, iaux, varid)
109  else
110  errmsg = 'NetCDF variable invalid modflow_input attribute: "'// &
111  trim(input_str)//'".'
112  call store_error(errmsg)
113  call store_error_filename(nc_vars%nc_fname)
114  end if
115  end if
116  end subroutine add_package_var
117 
118  !> @brief verify global attribute modflow_grid is present and return value
119  !<
120  function verify_global_attr(modeltype, modelname, input_name, nc_fname, ncid) &
121  result(nctype)
122  use inputoutputmodule, only: lowcase, upcase
123  character(len=*), intent(in) :: modeltype
124  character(len=*), intent(in) :: modelname
125  character(len=*), intent(in) :: input_name
126  character(len=*), intent(in) :: nc_fname
127  integer(I4B), intent(in) :: ncid
128  character(len=NETCDF_ATTR_STRLEN) :: grid, mesh, nctype
129  integer(I4B) :: mesh_ierr
130 
131  ! initialize grid
132  grid = ''
133  mesh = ''
134  nctype = ''
135 
136  ! verify expected mf6_modeltype file attribute
137  if (nf90_get_att(ncid, nf90_global, "modflow_grid", &
138  grid) == nf90_noerr) then
139  call upcase(grid)
140  mesh_ierr = nf90_get_att(ncid, nf90_global, "modflow_mesh", mesh)
141  if (mesh_ierr /= nf90_noerr) then
142  ! fall back to the legacy unprefixed name for files written by
143  ! older MF6 versions
144  mesh_ierr = nf90_get_att(ncid, nf90_global, "mesh", mesh)
145  end if
146  if (mesh_ierr == nf90_noerr) then
147  call upcase(mesh)
148  if (mesh == 'LAYERED') then
149  nctype = 'LAYERED MESH'
150  else
151  errmsg = 'NetCDF unsupported mesh type: "'//trim(mesh)//'".'
152  call store_error(errmsg)
153  call store_error_filename(nc_fname)
154  end if
155  else if (grid == 'STRUCTURED') then
156  nctype = 'STRUCTURED'
157  else if (grid == 'VERTEX' .or. grid == 'LAYERED MESH') then
158  warnmsg = 'Verify "modflow_grid" and "modflow_mesh" global &
159  &attributes in file: '//trim(nc_fname)
160  call store_warning(warnmsg)
161  nctype = 'LAYERED MESH'
162  end if
163  else
164  errmsg = 'NetCDF input file global attribute "modflow_grid" not found.'
165  call store_error(errmsg)
166  call store_error_filename(nc_fname)
167  end if
168  end function verify_global_attr
169 
170  !> @brief create internal description of modflow6 input variables in netcdf file
171  !<
172  subroutine create_netcdf_context(modeltype, modelname, input_name, &
173  nc_vars, nc_fname, ncid, iout)
174  use inputoutputmodule, only: lowcase, upcase
175  character(len=*), intent(in) :: modeltype
176  character(len=*), intent(in) :: modelname
177  character(len=*), intent(in) :: input_name
178  type(ncfilevarstype), intent(inout) :: nc_vars
179  character(len=*), intent(in) :: nc_fname
180  integer(I4B), intent(in) :: ncid
181  integer(I4B), intent(in) :: iout
182  integer(I4B) :: ndim, nvar, nattr, unlimdimid
183  integer(I4B), dimension(:), allocatable :: varids
184  character(len=LINELENGTH) :: grid
185  integer(I4B) :: iparam
186 
187  ! check global attributes
188  grid = verify_global_attr(modeltype, modelname, input_name, nc_fname, ncid)
189 
190  ! initialize netcdf input structure
191  call nc_vars%init(modelname, nc_fname, ncid, grid)
192 
193  ! inquire for root dataset info
194  call nf_verify(nf90_inquire(ncid, ndim, nvar, nattr, unlimdimid), &
195  nc_vars%nc_fname)
196 
197  ! allocate and set varids
198  allocate (varids(nvar))
199  call nf_verify(nf90_inq_varids(ncid, nvar, varids), nc_vars%nc_fname)
200  do iparam = 1, nvar
201  ! validate and add netcdf file input variable
202  call add_package_var(modeltype, modelname, nc_vars, input_name, &
203  varids(iparam), iout)
204  end do
205 
206  ! cleanup
207  deallocate (varids)
208  end subroutine create_netcdf_context
209 
210 end module nccontextbuildmodule
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
subroutine, public lowcase(word)
Convert to lower case.
subroutine, public upcase(word)
Convert to upper case.
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmemseparator), parameter mempathseparator
used to build up the memory address for the stored variables
subroutine split_mem_path(mem_path, component, subcomponent)
Split the memory path into component(s)
This module contains the NCContextBuildModule.
integer(i4b) function, public open_ncfile(nc_fname, iout)
open netcdf file
subroutine add_package_var(modeltype, modelname, nc_vars, input_name, varid, iout)
add a package input variable to nc_vars structure
character(len=netcdf_attr_strlen) function verify_global_attr(modeltype, modelname, input_name, nc_fname, ncid)
verify global attribute modflow_grid is present and return value
subroutine, public create_netcdf_context(modeltype, modelname, input_name, nc_vars, nc_fname, ncid, iout)
create internal description of modflow6 input variables in netcdf file
This module contains the NCFileVarsModule.
Definition: NCFileVars.f90:7
This module contains the NetCDFCommonModule.
Definition: NetCDFCommon.f90:6
integer(i4b), parameter, public netcdf_attr_strlen
subroutine, public nf_verify(res, nc_fname)
error check a netcdf-fortran interface call
integer(i4b) function, public nc_fopen(nc_fname, iout)
Open netcdf file.
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:237
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:204
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
character(len=maxcharlen) warnmsg
warning message string
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_subcomponent_name(component_type, subcomponent_type, sc_name)
model package subcomponent name
Type describing modflow6 input variables in model NetCDF file.
Definition: NCFileVars.f90:47