MODFLOW 6  version 6.7.0.dev1
USGS Modular Hydrologic Model
NCModel.f90
Go to the documentation of this file.
1 !> @brief This module contains the NCModelExportModule
2 !!
3 !! This module defines a model export and base type for
4 !! supported netcdf files and is not dependent on
5 !! netcdf libraries.
6 !!
7 !<
9 
10  use kindmodule, only: dp, i4b, lgp
13  dis, disu, disv
19  use listmodule, only: listtype
20 
21  implicit none
22  private
24  public :: ncexportannotation
25  public :: exportpackagetype
27  public :: export_longname
28 
29  !> @brief netcdf export types enumerator
30  !<
31  ENUM, BIND(C)
32  ENUMERATOR :: netcdf_undef = 0 !< undefined netcdf export type
33  ENUMERATOR :: netcdf_structured = 1 !< netcdf structrured export
34  ENUMERATOR :: netcdf_mesh2d = 2 !< netcdf ugrid layered mesh export
35  END ENUM
36 
38  type(modflowinputtype) :: mf6_input !< description of modflow6 input
39  character(len=LINELENGTH), dimension(:), allocatable :: param_names !< dynamic param tagnames
40  type(readstatevartype), dimension(:), allocatable :: param_reads !< param read states
41  integer(I4B), dimension(:), pointer, contiguous :: mshape => null() !< model shape
42  integer(I4B), pointer :: iper !< most recent package rp load
43  integer(I4B) :: iper_export !< most recent period of netcdf package export
44  integer(I4B) :: nparam !< number of in scope params
45  contains
46  procedure :: init => epkg_init
47  procedure :: destroy => epkg_destroy
48  end type exportpackagetype
49 
50  !> @brief netcdf export attribute annotations
51  !<
53  character(len=LINELENGTH) :: title !< file scoped title attribute
54  character(len=LINELENGTH) :: model !< file scoped model attribute
55  character(len=LINELENGTH) :: grid !< grid type
56  character(len=LINELENGTH) :: history !< file scoped history attribute
57  character(len=LINELENGTH) :: source !< file scoped source attribute
58  character(len=LINELENGTH) :: conventions !< file scoped conventions attribute
59  character(len=LINELENGTH) :: stdname !< dependent variable standard name
60  character(len=LINELENGTH) :: longname !< dependent variable long name
61  contains
62  procedure :: set
63  end type ncexportannotation
64 
65  !> @brief base class for an export model
66  !<
68  type(listtype) :: pkglist
69  character(len=LENMODELNAME) :: modelname !< name of model
70  character(len=LENCOMPONENTNAME) :: modeltype !< type of model
71  character(len=LINELENGTH) :: modelfname !< name of model input file
72  character(len=LINELENGTH) :: nc_fname !< name of netcdf export file
73  character(len=LINELENGTH) :: gridmap_name !< name of grid mapping variable
74  character(len=LINELENGTH) :: mesh_name = 'mesh' !< name of mesh container variable
75  character(len=LENMEMPATH) :: dis_mempath !< discretization input mempath
76  character(len=LENMEMPATH) :: ncf_mempath !< netcdf utility package input mempath
77  character(len=LENBIGLINE) :: wkt !< wkt user string
78  character(len=LINELENGTH) :: datetime !< export file creation time
79  character(len=LINELENGTH) :: xname !< dependent variable name
80  character(len=LINELENGTH) :: lenunits !< unidata udunits length units
81  type(ncexportannotation) :: annotation !< export file annotation
82  real(dp), dimension(:), pointer, contiguous :: x !< dependent variable pointer
83  integer(I4B) :: disenum !< type of discretization
84  integer(I4B) :: ncid !< netcdf file descriptor
85  integer(I4B) :: stepcnt !< simulation step count
86  integer(I4B) :: totnstp !< simulation total number of steps
87  integer(I4B), pointer :: deflate !< variable deflate level
88  integer(I4B), pointer :: shuffle !< variable shuffle filter
89  integer(I4B), pointer :: input_attr !< assign variable input attr
90  integer(I4B), pointer :: chunk_time !< chunking parameter for time dimension
91  integer(I4B) :: iout !< lst file descriptor
92  logical(LGP) :: chunking_active !< have chunking parameters been provided
93  contains
94  procedure :: init => export_init
95  procedure :: get => export_get
96  procedure :: input_attribute
97  procedure :: destroy => export_destroy
98  end type ncmodelexporttype
99 
100  !> @brief abstract type for model netcdf export type
101  !<
102  type, abstract, extends(ncmodelexporttype) :: ncbasemodelexporttype
103  contains
104  procedure :: export_input
105  procedure(model_define), deferred :: df
106  procedure(model_step), deferred :: step
107  procedure(package_export), deferred :: package_step
108  procedure(package_export_ilayer), deferred :: package_step_ilayer
109  end type ncbasemodelexporttype
110 
111  !> @brief abstract interfaces for model netcdf export type
112  !<
113  abstract interface
114  subroutine model_define(this)
115  import ncbasemodelexporttype
116  class(ncbasemodelexporttype), intent(inout) :: this
117  end subroutine
118  subroutine model_step(this)
119  import ncbasemodelexporttype
120  class(ncbasemodelexporttype), intent(inout) :: this
121  end subroutine
122  subroutine package_export(this, export_pkg)
124  class(ncbasemodelexporttype), intent(inout) :: this
125  class(exportpackagetype), pointer, intent(in) :: export_pkg
126  end subroutine
127  subroutine package_export_ilayer(this, export_pkg, ilayer_varname, &
128  ilayer)
130  class(ncbasemodelexporttype), intent(inout) :: this
131  class(exportpackagetype), pointer, intent(in) :: export_pkg
132  character(len=*), intent(in) :: ilayer_varname
133  integer(I4B), intent(in) :: ilayer
134  end subroutine
135  end interface
136 
137 contains
138 
139  !> @brief initialize dynamic package export object
140  !<
141  subroutine epkg_init(this, mf6_input, mshape, param_names, &
142  nparam)
147  class(exportpackagetype), intent(inout) :: this
148  type(modflowinputtype), intent(in) :: mf6_input
149  integer(I4B), dimension(:), pointer, contiguous, intent(in) :: mshape !< model shape
150  character(len=LINELENGTH), dimension(:), allocatable, &
151  intent(in) :: param_names
152  integer(I4B), intent(in) :: nparam
153  integer(I4B) :: n
154  character(len=LENVARNAME) :: rs_varname
155  character(len=LENMEMPATH) :: input_mempath
156  integer(I4B), pointer :: rsvar
157 
158  this%mf6_input = mf6_input
159  this%mshape => mshape
160  this%nparam = nparam
161  this%iper_export = 0
162 
163  input_mempath = create_mem_path(component=mf6_input%component_name, &
164  subcomponent=mf6_input%subcomponent_name, &
165  context=idm_context)
166 
167  ! allocate param arrays
168  allocate (this%param_names(nparam))
169  allocate (this%param_reads(nparam))
170 
171  ! set param arrays
172  do n = 1, nparam
173  this%param_names(n) = param_names(n)
174  rs_varname = rsv_name(param_names(n))
175  call mem_setptr(rsvar, rs_varname, mf6_input%mempath)
176  this%param_reads(n)%invar => rsvar
177  end do
178 
179  ! set pointer to loaded input period
180  call mem_setptr(this%iper, 'IPER', mf6_input%mempath)
181  end subroutine epkg_init
182 
183  !> @brief destroy dynamic package export object
184  !<
185  subroutine epkg_destroy(this)
187  class(exportpackagetype), intent(inout) :: this
188  if (allocated(this%param_names)) deallocate (this%param_names)
189  end subroutine epkg_destroy
190 
191  !> @brief set netcdf file scoped attributes
192  !<
193  subroutine set(this, modelname, modeltype, modelfname, nctype)
194  use versionmodule, only: version
195  class(ncexportannotation), intent(inout) :: this
196  character(len=*), intent(in) :: modelname
197  character(len=*), intent(in) :: modeltype
198  character(len=*), intent(in) :: modelfname
199  integer(I4B), intent(in) :: nctype
200  character(len=LINELENGTH) :: fullname
201  integer :: values(8)
202 
203  this%title = ''
204  this%model = ''
205  this%grid = ''
206  this%history = ''
207  this%source = ''
208  this%conventions = ''
209  this%stdname = ''
210  this%longname = ''
211 
212  ! set file conventions
213  this%conventions = 'CF-1.11'
214  if (nctype == netcdf_mesh2d) this%conventions = &
215  trim(this%conventions)//' UGRID-1.0'
216 
217  ! set model specific attributes
218  select case (modeltype)
219  case ('GWF')
220  fullname = 'Groundwater Flow'
221  this%title = trim(modelname)//' hydraulic head'
222  this%longname = 'head'
223  case ('GWT')
224  fullname = 'Groundwater Transport'
225  this%title = trim(modelname)//' concentration'
226  this%longname = 'concentration'
227  case ('GWE')
228  fullname = 'Groundwater Energy'
229  this%title = trim(modelname)//' temperature'
230  this%longname = 'temperature'
231  case default
232  errmsg = trim(modeltype)//' models not supported for NetCDF export.'
233  call store_error(errmsg)
234  call store_error_filename(modelfname)
235  end select
236 
237  if (isim_mode == mvalidate) then
238  this%title = trim(this%title)//' array input'
239  end if
240 
241  ! set export type
242  if (nctype == netcdf_mesh2d) then
243  this%grid = 'LAYERED MESH'
244  else if (nctype == netcdf_structured) then
245  this%grid = 'STRUCTURED'
246  end if
247 
248  ! model description string
249  this%model = trim(modelname)//': MODFLOW 6 '//trim(fullname)// &
250  ' ('//trim(modeltype)//') model'
251 
252  ! modflow6 version string
253  this%source = 'MODFLOW 6 '//trim(adjustl(version))
254 
255  ! create timestamp
256  call date_and_time(values=values)
257  write (this%history, '(a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0)') &
258  'first created ', values(1), '/', values(2), '/', values(3), ' ', &
259  values(5), ':', values(6), ':', values(7), '.', values(8)
260  end subroutine set
261 
262  !> @brief initialization of model netcdf export
263  !<
264  subroutine export_init(this, modelname, modeltype, modelfname, nc_fname, &
265  disenum, nctype, iout)
266  use tdismodule, only: datetime0, nstp
270  use inputoutputmodule, only: lowcase
272  class(ncmodelexporttype), intent(inout) :: this
273  character(len=*), intent(in) :: modelname
274  character(len=*), intent(in) :: modeltype
275  character(len=*), intent(in) :: modelfname
276  character(len=*), intent(in) :: nc_fname
277  integer(I4B), intent(in) :: disenum
278  integer(I4B), intent(in) :: nctype
279  integer(I4B), intent(in) :: iout
280  character(len=LENMEMPATH) :: model_mempath
281  type(utlncfparamfoundtype) :: ncf_found
282  logical(LGP) :: found_mempath
283 
284  ! allocate
285  allocate (this%deflate)
286  allocate (this%shuffle)
287  allocate (this%input_attr)
288  allocate (this%chunk_time)
289 
290  ! initialize
291  this%modelname = modelname
292  this%modeltype = modeltype
293  this%modelfname = modelfname
294  this%nc_fname = nc_fname
295  this%gridmap_name = ''
296  this%ncf_mempath = ''
297  this%wkt = ''
298  this%datetime = ''
299  this%xname = ''
300  this%lenunits = ''
301  this%disenum = disenum
302  this%ncid = 0
303  this%stepcnt = 0
304  this%totnstp = 0
305  this%deflate = -1
306  this%shuffle = 0
307  this%input_attr = 1
308  this%chunk_time = -1
309  this%iout = iout
310  this%chunking_active = .false.
311 
312  ! set file scoped attributes
313  call this%annotation%set(modelname, modeltype, modelfname, nctype)
314 
315  ! set dependent variable basename
316  select case (modeltype)
317  case ('GWF')
318  this%xname = 'head'
319  case ('GWT')
320  this%xname = 'concentration'
321  case ('GWE')
322  this%xname = 'temperature'
323  case default
324  errmsg = trim(modeltype)//' models not supported for NetCDF export.'
325  call store_error(errmsg)
326  call store_error_filename(modelfname)
327  end select
328 
329  ! set discretization input mempath
330  if (disenum == dis) then
331  this%dis_mempath = create_mem_path(modelname, 'DIS', idm_context)
332  else if (disenum == disu) then
333  this%dis_mempath = create_mem_path(modelname, 'DISU', idm_context)
334  else if (disenum == disv) then
335  this%dis_mempath = create_mem_path(modelname, 'DISV', idm_context)
336  end if
337 
338  ! set dependent variable pointer
339  model_mempath = create_mem_path(component=modelname)
340  call mem_setptr(this%x, 'X', model_mempath)
341 
342  ! set ncf_mempath if provided
343  call mem_set_value(this%ncf_mempath, 'NCF6_MEMPATH', this%dis_mempath, &
344  found_mempath)
345 
346  if (found_mempath) then
347  call mem_set_value(this%wkt, 'WKT', this%ncf_mempath, &
348  ncf_found%wkt)
349  call mem_set_value(this%deflate, 'DEFLATE', this%ncf_mempath, &
350  ncf_found%deflate)
351  call mem_set_value(this%shuffle, 'SHUFFLE', this%ncf_mempath, &
352  ncf_found%shuffle)
353  call mem_set_value(this%input_attr, 'ATTR_OFF', this%ncf_mempath, &
354  ncf_found%attr_off)
355  call mem_set_value(this%chunk_time, 'CHUNK_TIME', this%ncf_mempath, &
356  ncf_found%chunk_time)
357  end if
358 
359  if (ncf_found%wkt) then
360  this%gridmap_name = 'projection'
361  end if
362 
363  ! ATTR_OFF turns off modflow 6 input attributes
364  if (ncf_found%attr_off) then
365  this%input_attr = 0
366  end if
367 
368  ! set datetime string
369  if (datetime0 /= '') then
370  this%datetime = 'days since '//trim(datetime0)
371  else
372  ! January 1, 1970 at 00:00:00 UTC
373  this%datetime = 'days since 1970-01-01T00:00:00'
374  end if
375 
376  ! set total nstp
377  this%totnstp = sum(nstp)
378  end subroutine export_init
379 
380  !> @brief retrieve dynamic export object from package list
381  !<
382  function export_get(this, idx) result(res)
383  use listmodule, only: listtype
384  class(ncmodelexporttype), intent(inout) :: this
385  integer(I4B), intent(in) :: idx
386  class(exportpackagetype), pointer :: res
387  class(*), pointer :: obj
388  nullify (res)
389  obj => this%pkglist%GetItem(idx)
390  if (associated(obj)) then
391  select type (obj)
392  class is (exportpackagetype)
393  res => obj
394  end select
395  end if
396  end function export_get
397 
398  !> @brief build modflow6_input attribute string
399  !<
400  function input_attribute(this, pkgname, idt) result(attr)
401  use inputoutputmodule, only: lowcase
404  class(ncmodelexporttype), intent(inout) :: this
405  character(len=*), intent(in) :: pkgname
406  type(inputparamdefinitiontype), pointer, intent(in) :: idt
407  character(len=LINELENGTH) :: attr
408  attr = ''
409  if (this%input_attr > 0) then
410  attr = trim(this%modelname)//mempathseparator//trim(pkgname)// &
411  mempathseparator//trim(idt%mf6varname)
412  end if
413  end function input_attribute
414 
415  !> @brief build netcdf variable longname
416  !<
417  function export_longname(longname, pkgname, tagname, layer, iper) result(lname)
418  use inputoutputmodule, only: lowcase
419  character(len=*), intent(in) :: longname
420  character(len=*), intent(in) :: pkgname
421  character(len=*), intent(in) :: tagname
422  integer(I4B), intent(in) :: layer
423  integer(I4B), optional, intent(in) :: iper
424  character(len=LINELENGTH) :: lname
425  character(len=LINELENGTH) :: pname, vname
426  pname = pkgname
427  vname = tagname
428  call lowcase(pname)
429  call lowcase(vname)
430  if (longname == '') then
431  lname = trim(pname)//' '//trim(vname)
432  else
433  lname = longname
434  end if
435  if (layer > 0) then
436  write (lname, '(a,i0)') trim(lname)//' layer=', layer
437  end if
438  if (present(iper)) then
439  if (iper > 0) then
440  write (lname, '(a,i0)') trim(lname)//' period=', iper
441  end if
442  end if
443  end function export_longname
444 
445  !> @brief netcdf dynamic package period export
446  !<
447  subroutine export_input(this)
448  use tdismodule, only: kper
449  use arrayhandlersmodule, only: ifind
450  class(ncbasemodelexporttype), intent(inout) :: this
451  integer(I4B) :: idx, ilayer
452  class(exportpackagetype), pointer :: export_pkg
453  character(len=LENVARNAME) :: ilayer_varname
454 
455  do idx = 1, this%pkglist%Count()
456  export_pkg => this%get(idx)
457  ! last loaded data is not current period
458  if (export_pkg%iper /= kper) cycle
459  ! period input already exported
460  if (export_pkg%iper_export >= export_pkg%iper) cycle
461  ! set exported iper
462  export_pkg%iper_export = export_pkg%iper
463 
464  ! initialize ilayer
465  ilayer = 0
466 
467  ! set expected ilayer index variable name
468  ilayer_varname = 'I'//trim(export_pkg%mf6_input%subcomponent_type(1:3))
469 
470  ! is ilayer variable in param name list
471  ilayer = ifind(export_pkg%param_names, ilayer_varname)
472 
473  ! layer index variable is required to be first defined in period block
474  if (ilayer == 1) then
475  call this%package_step_ilayer(export_pkg, ilayer_varname, ilayer)
476  else
477  call this%package_step(export_pkg)
478  end if
479  end do
480  end subroutine export_input
481 
482  !> @brief destroy model netcdf export object
483  !<
484  subroutine export_destroy(this)
487  class(ncmodelexporttype), intent(inout) :: this
488  ! override in derived class
489  deallocate (this%deflate)
490  deallocate (this%shuffle)
491  deallocate (this%input_attr)
492  deallocate (this%chunk_time)
493  ! Deallocate idm memory
494  if (this%ncf_mempath /= '') then
495  call memorystore_remove(this%modelname, 'NCF', idm_context)
496  end if
497  end subroutine export_destroy
498 
499 end module ncmodelexportmodule
subroutine init()
Definition: GridSorting.f90:24
abstract interfaces for model netcdf export type
Definition: NCModel.f90:114
This module contains the BoundInputContextModule.
character(len=lenvarname) function, public rsv_name(mf6varname)
create read state variable name
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
@ mvalidate
validation mode - do not run time steps
Definition: Constants.f90:205
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition: Constants.f90:22
integer(i4b), parameter lenbigline
maximum length of a big line
Definition: Constants.f90:15
@ disu
DISV6 discretization.
Definition: Constants.f90:157
@ dis
DIS6 discretization.
Definition: Constants.f90:155
@ disv
DISU6 discretization.
Definition: Constants.f90:156
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
This module contains the InputDefinitionModule.
This module contains the InputLoadTypeModule.
subroutine, public lowcase(word)
Convert to lower 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
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
subroutine, public memorystore_remove(component, subcomponent, context)
This module contains the ModflowInputModule.
Definition: ModflowInput.f90:9
This module contains the NCModelExportModule.
Definition: NCModel.f90:8
class(exportpackagetype) function, pointer export_get(this, idx)
retrieve dynamic export object from package list
Definition: NCModel.f90:383
subroutine epkg_init(this, mf6_input, mshape, param_names, nparam)
initialize dynamic package export object
Definition: NCModel.f90:143
@, public netcdf_structured
netcdf structrured export
Definition: NCModel.f90:33
character(len=linelength) function, public export_longname(longname, pkgname, tagname, layer, iper)
build netcdf variable longname
Definition: NCModel.f90:418
subroutine export_destroy(this)
destroy model netcdf export object
Definition: NCModel.f90:485
subroutine export_init(this, modelname, modeltype, modelfname, nc_fname, disenum, nctype, iout)
initialization of model netcdf export
Definition: NCModel.f90:266
subroutine set(this, modelname, modeltype, modelfname, nctype)
set netcdf file scoped attributes
Definition: NCModel.f90:194
@, public netcdf_mesh2d
netcdf ugrid layered mesh export
Definition: NCModel.f90:34
@, public netcdf_undef
undefined netcdf export type
Definition: NCModel.f90:32
character(len=linelength) function input_attribute(this, pkgname, idt)
build modflow6_input attribute string
Definition: NCModel.f90:401
subroutine epkg_destroy(this)
destroy dynamic package export object
Definition: NCModel.f90:186
subroutine export_input(this)
netcdf dynamic package period export
Definition: NCModel.f90:448
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
character(len=linelength) idm_context
integer(i4b) isim_mode
simulation mode
integer(i4b), dimension(:), pointer, public, contiguous nstp
number of time steps in each stress period
Definition: tdis.f90:39
character(len=lendatetime), pointer, public datetime0
starting date and time for the simulation
Definition: tdis.f90:41
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:23
This module contains version information.
Definition: version.f90:7
character(len=40), parameter version
Definition: version.f90:22
Pointer type for read state variable.
type for storing a dynamic package load list
A generic heterogeneous doubly-linked list.
Definition: List.f90:14
derived type for storing input definition for a file
abstract type for model netcdf export type
Definition: NCModel.f90:102
netcdf export attribute annotations
Definition: NCModel.f90:52
base class for an export model
Definition: NCModel.f90:67