MODFLOW 6  version 6.7.0.dev3
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
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(:, :), allocatable :: varids_param
42  integer(I4B), dimension(:, :), allocatable :: varids_aux
43  integer(I4B), dimension(:), pointer, contiguous :: mshape => null() !< model shape
44  integer(I4B), pointer :: iper !< most recent package rp load
45  integer(I4B) :: iper_export !< most recent period of netcdf package export
46  integer(I4B) :: nparam !< number of in scope params
47  integer(I4B) :: naux !< number of auxiliary variables
48  contains
49  procedure :: init => epkg_init
50  procedure :: destroy => epkg_destroy
51  end type exportpackagetype
52 
53  !> @brief netcdf export attribute annotations
54  !<
56  character(len=LINELENGTH) :: title !< file scoped title attribute
57  character(len=LINELENGTH) :: model !< file scoped model attribute
58  character(len=LINELENGTH) :: mesh !< mesh type
59  character(len=LINELENGTH) :: grid !< grid type
60  character(len=LINELENGTH) :: history !< file scoped history attribute
61  character(len=LINELENGTH) :: source !< file scoped source attribute
62  character(len=LINELENGTH) :: conventions !< file scoped conventions attribute
63  character(len=LINELENGTH) :: stdname !< dependent variable standard name
64  character(len=LINELENGTH) :: longname !< dependent variable long name
65  contains
66  procedure :: set
67  end type ncexportannotation
68 
69  !> @brief base class for an export model
70  !<
72  type(listtype) :: pkglist
73  character(len=LENMODELNAME) :: modelname !< name of model
74  character(len=LENCOMPONENTNAME) :: modeltype !< type of model
75  character(len=LINELENGTH) :: modelfname !< name of model input file
76  character(len=LINELENGTH) :: nc_fname !< name of netcdf export file
77  character(len=LINELENGTH) :: gridmap_name !< name of grid mapping variable
78  character(len=LINELENGTH) :: mesh_name = 'mesh' !< name of mesh container variable
79  character(len=LENMEMPATH) :: dis_mempath !< discretization input mempath
80  character(len=LENMEMPATH) :: ncf_mempath !< netcdf utility package input mempath
81  character(len=LENBIGLINE) :: wkt !< wkt user string
82  character(len=LINELENGTH) :: datetime !< export file creation time
83  character(len=LINELENGTH) :: xname !< dependent variable name
84  character(len=LINELENGTH) :: lenunits !< unidata udunits length units
85  type(ncexportannotation) :: annotation !< export file annotation
86  real(dp), dimension(:), pointer, contiguous :: x !< dependent variable pointer
87  integer(I4B) :: disenum !< type of discretization
88  integer(I4B) :: ncid !< netcdf file descriptor
89  integer(I4B) :: totnstp !< simulation total number of steps
90  integer(I4B), pointer :: deflate !< variable deflate level
91  integer(I4B), pointer :: shuffle !< variable shuffle filter
92  integer(I4B), pointer :: input_attr !< assign variable input attr
93  integer(I4B), pointer :: chunk_time !< chunking parameter for time dimension
94  integer(I4B) :: iout !< lst file descriptor
95  logical(LGP) :: chunking_active !< have chunking parameters been provided
96  contains
97  procedure :: init => export_init
98  procedure :: get => export_get
99  procedure :: input_attribute
100  procedure :: destroy => export_destroy
101  end type ncmodelexporttype
102 
103  !> @brief abstract type for model netcdf export type
104  !<
105  type, abstract, extends(ncmodelexporttype) :: ncbasemodelexporttype
106  contains
107  procedure :: export_input
108  procedure(model_define), deferred :: df
109  procedure(package_export), deferred :: export_df
110  procedure(model_step), deferred :: step
111  procedure(package_export), deferred :: package_step
112  end type ncbasemodelexporttype
113 
114  !> @brief abstract interfaces for model netcdf export type
115  !<
116  abstract interface
117  subroutine model_define(this)
118  import ncbasemodelexporttype
119  class(ncbasemodelexporttype), intent(inout) :: this
120  end subroutine
121  subroutine model_step(this)
122  import ncbasemodelexporttype
123  class(ncbasemodelexporttype), intent(inout) :: this
124  end subroutine
125  subroutine package_export(this, export_pkg)
127  class(ncbasemodelexporttype), intent(inout) :: this
128  class(exportpackagetype), pointer, intent(in) :: export_pkg
129  end subroutine
130  subroutine package_export_ilayer(this, export_pkg, ilayer_varname, &
131  ilayer)
133  class(ncbasemodelexporttype), intent(inout) :: this
134  class(exportpackagetype), pointer, intent(in) :: export_pkg
135  character(len=*), intent(in) :: ilayer_varname
136  integer(I4B), intent(in) :: ilayer
137  end subroutine
138  end interface
139 
140 contains
141 
142  !> @brief initialize dynamic package export object
143  !<
144  subroutine epkg_init(this, mf6_input, mshape, naux, param_names, &
145  nparam)
150  class(exportpackagetype), intent(inout) :: this
151  type(modflowinputtype), intent(in) :: mf6_input
152  integer(I4B), dimension(:), pointer, contiguous, intent(in) :: mshape !< model shape
153  integer(I4B), intent(in) :: naux
154  character(len=LINELENGTH), dimension(:), allocatable, &
155  intent(in) :: param_names
156  integer(I4B), intent(in) :: nparam
157  integer(I4B) :: n
158  character(len=LENVARNAME) :: rs_varname
159  character(len=LENMEMPATH) :: input_mempath
160  integer(I4B), pointer :: rsvar
161 
162  this%mf6_input = mf6_input
163  this%mshape => mshape
164  this%nparam = nparam
165  this%naux = naux
166  this%iper_export = 0
167 
168  input_mempath = create_mem_path(component=mf6_input%component_name, &
169  subcomponent=mf6_input%subcomponent_name, &
170  context=idm_context)
171 
172  ! allocate param arrays
173  allocate (this%param_names(nparam))
174  allocate (this%param_reads(nparam))
175  allocate (this%varids_param(nparam, mshape(1)))
176  allocate (this%varids_aux(naux, mshape(1)))
177 
178  ! set param arrays
179  do n = 1, nparam
180  this%param_names(n) = param_names(n)
181  rs_varname = rsv_name(param_names(n))
182  call mem_setptr(rsvar, rs_varname, mf6_input%mempath)
183  this%param_reads(n)%invar => rsvar
184  end do
185 
186  ! set pointer to loaded input period
187  call mem_setptr(this%iper, 'IPER', mf6_input%mempath)
188  end subroutine epkg_init
189 
190  !> @brief destroy dynamic package export object
191  !<
192  subroutine epkg_destroy(this)
194  class(exportpackagetype), intent(inout) :: this
195  if (allocated(this%param_names)) deallocate (this%param_names)
196  end subroutine epkg_destroy
197 
198  !> @brief set netcdf file scoped attributes
199  !<
200  subroutine set(this, modelname, modeltype, modelfname, nctype, disenum)
201  use versionmodule, only: version
202  class(ncexportannotation), intent(inout) :: this
203  character(len=*), intent(in) :: modelname
204  character(len=*), intent(in) :: modeltype
205  character(len=*), intent(in) :: modelfname
206  integer(I4B), intent(in) :: nctype
207  integer(I4B), intent(in) :: disenum
208  integer :: values(8)
209 
210  this%title = ''
211  this%model = ''
212  this%mesh = ''
213  this%grid = ''
214  this%history = ''
215  this%source = ''
216  this%conventions = ''
217  this%stdname = ''
218  this%longname = ''
219 
220  ! set file conventions
221  this%conventions = 'CF-1.11'
222  if (nctype == netcdf_mesh2d) this%conventions = &
223  trim(this%conventions)//' UGRID-1.0'
224 
225  ! set model specific attributes
226  select case (modeltype)
227  case ('GWF')
228  this%title = trim(modelname)//' hydraulic head'
229  this%longname = 'head'
230  case ('GWT')
231  this%title = trim(modelname)//' concentration'
232  this%longname = 'concentration'
233  case ('GWE')
234  this%title = trim(modelname)//' temperature'
235  this%longname = 'temperature'
236  case default
237  errmsg = trim(modeltype)//' models not supported for NetCDF export.'
238  call store_error(errmsg)
239  call store_error_filename(modelfname)
240  end select
241 
242  if (isim_mode == mvalidate) then
243  this%title = trim(this%title)//' array input'
244  end if
245 
246  ! set mesh type
247  if (nctype == netcdf_mesh2d) then
248  this%mesh = 'LAYERED'
249  end if
250 
251  ! set grid type
252  if (disenum == dis) then
253  this%grid = 'STRUCTURED'
254  else if (disenum == disv) then
255  this%grid = 'VERTEX'
256  end if
257 
258  ! model description string
259  this%model = trim(modeltype)//'6: '//trim(modelname)
260 
261  ! modflow6 version string
262  this%source = 'MODFLOW 6 '//trim(adjustl(version))
263 
264  ! create timestamp
265  call date_and_time(values=values)
266  write (this%history, '(a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0)') &
267  'first created ', values(1), '/', values(2), '/', values(3), ' ', &
268  values(5), ':', values(6), ':', values(7), '.', values(8)
269  end subroutine set
270 
271  !> @brief initialization of model netcdf export
272  !<
273  subroutine export_init(this, modelname, modeltype, modelfname, nc_fname, &
274  disenum, nctype, iout)
275  use tdismodule, only: datetime0, nstp, inats
279  use inputoutputmodule, only: lowcase
281  class(ncmodelexporttype), intent(inout) :: this
282  character(len=*), intent(in) :: modelname
283  character(len=*), intent(in) :: modeltype
284  character(len=*), intent(in) :: modelfname
285  character(len=*), intent(in) :: nc_fname
286  integer(I4B), intent(in) :: disenum
287  integer(I4B), intent(in) :: nctype
288  integer(I4B), intent(in) :: iout
289  character(len=LENMEMPATH) :: model_mempath
290  type(utlncfparamfoundtype) :: ncf_found
291  logical(LGP) :: found_mempath
292 
293  ! allocate
294  allocate (this%deflate)
295  allocate (this%shuffle)
296  allocate (this%input_attr)
297  allocate (this%chunk_time)
298 
299  ! initialize
300  this%modelname = modelname
301  this%modeltype = modeltype
302  this%modelfname = modelfname
303  this%nc_fname = nc_fname
304  this%gridmap_name = ''
305  this%ncf_mempath = ''
306  this%wkt = ''
307  this%datetime = ''
308  this%xname = ''
309  this%lenunits = ''
310  this%disenum = disenum
311  this%ncid = 0
312  this%totnstp = 0
313  this%deflate = -1
314  this%shuffle = 0
315  this%input_attr = 1
316  this%chunk_time = -1
317  this%iout = iout
318  this%chunking_active = .false.
319 
320  ! set file scoped attributes
321  call this%annotation%set(modelname, modeltype, modelfname, nctype, disenum)
322 
323  ! set dependent variable basename
324  select case (modeltype)
325  case ('GWF')
326  this%xname = 'head'
327  case ('GWT')
328  this%xname = 'concentration'
329  case ('GWE')
330  this%xname = 'temperature'
331  case default
332  errmsg = trim(modeltype)//' models not supported for NetCDF export.'
333  call store_error(errmsg)
334  call store_error_filename(modelfname)
335  end select
336 
337  ! set discretization input mempath
338  if (disenum == dis) then
339  this%dis_mempath = create_mem_path(modelname, 'DIS', idm_context)
340  else if (disenum == disu) then
341  this%dis_mempath = create_mem_path(modelname, 'DISU', idm_context)
342  else if (disenum == disv) then
343  this%dis_mempath = create_mem_path(modelname, 'DISV', idm_context)
344  end if
345 
346  ! set dependent variable pointer
347  model_mempath = create_mem_path(component=modelname)
348  call mem_setptr(this%x, 'X', model_mempath)
349 
350  ! set ncf_mempath if provided
351  call mem_set_value(this%ncf_mempath, 'NCF6_MEMPATH', this%dis_mempath, &
352  found_mempath)
353 
354  if (found_mempath) then
355  call mem_set_value(this%wkt, 'WKT', this%ncf_mempath, &
356  ncf_found%wkt)
357  call mem_set_value(this%deflate, 'DEFLATE', this%ncf_mempath, &
358  ncf_found%deflate)
359  call mem_set_value(this%shuffle, 'SHUFFLE', this%ncf_mempath, &
360  ncf_found%shuffle)
361  call mem_set_value(this%input_attr, 'ATTR_OFF', this%ncf_mempath, &
362  ncf_found%attr_off)
363  call mem_set_value(this%chunk_time, 'CHUNK_TIME', this%ncf_mempath, &
364  ncf_found%chunk_time)
365  end if
366 
367  if (ncf_found%wkt) then
368  this%gridmap_name = 'projection'
369  end if
370 
371  ! ATTR_OFF turns off modflow 6 input attributes
372  if (ncf_found%attr_off) then
373  this%input_attr = 0
374  end if
375 
376  ! set datetime string
377  if (datetime0 /= '') then
378  this%datetime = 'days since '//trim(datetime0)
379  else
380  ! January 1, 1970 at 00:00:00 UTC
381  this%datetime = 'days since 1970-01-01T00:00:00'
382  end if
383 
384  ! Set error and exit if ATS is on
385  if (inats > 0) then
386  errmsg = 'Adaptive time stepping not currently supported &
387  &with NetCDF exports.'
388  call store_error(errmsg)
389  call store_error_filename(modelfname)
390  end if
391 
392  ! set total nstp
393  this%totnstp = sum(nstp)
394  end subroutine export_init
395 
396  !> @brief retrieve dynamic export object from package list
397  !<
398  function export_get(this, idx) result(res)
399  use listmodule, only: listtype
400  class(ncmodelexporttype), intent(inout) :: this
401  integer(I4B), intent(in) :: idx
402  class(exportpackagetype), pointer :: res
403  class(*), pointer :: obj
404  nullify (res)
405  obj => this%pkglist%GetItem(idx)
406  if (associated(obj)) then
407  select type (obj)
408  class is (exportpackagetype)
409  res => obj
410  end select
411  end if
412  end function export_get
413 
414  !> @brief build modflow_input attribute string
415  !<
416  function input_attribute(this, pkgname, idt) result(attr)
417  use inputoutputmodule, only: lowcase
420  class(ncmodelexporttype), intent(inout) :: this
421  character(len=*), intent(in) :: pkgname
422  type(inputparamdefinitiontype), pointer, intent(in) :: idt
423  character(len=LINELENGTH) :: attr
424  attr = ''
425  if (this%input_attr > 0) then
426  attr = trim(this%modelname)//mempathseparator//trim(pkgname)// &
427  mempathseparator//trim(idt%tagname)
428  end if
429  end function input_attribute
430 
431  !> @brief build netcdf variable name
432  !<
433  function export_varname(pkgname, tagname, mempath, layer, iaux) &
434  result(varname)
437  use inputoutputmodule, only: lowcase
438  character(len=*), intent(in) :: pkgname
439  character(len=*), intent(in) :: tagname
440  character(len=*), intent(in) :: mempath
441  integer(I4B), optional, intent(in) :: layer
442  integer(I4B), optional, intent(in) :: iaux
443  character(len=LINELENGTH) :: varname
444  type(characterstringtype), dimension(:), pointer, &
445  contiguous :: auxnames
446  character(len=LINELENGTH) :: pname, vname
447  vname = tagname
448  pname = pkgname
449 
450  if (present(iaux)) then
451  if (iaux > 0) then
452  if (tagname == 'AUX') then
453  ! reset vname to auxiliary variable name
454  call mem_setptr(auxnames, 'AUXILIARY', mempath)
455  vname = auxnames(iaux)
456  end if
457  end if
458  end if
459 
460  call lowcase(vname)
461  call lowcase(pname)
462  varname = trim(pname)//'_'//trim(vname)
463 
464  if (present(layer)) then
465  if (layer > 0) then
466  !write (varname, '(a,i0)') trim(varname)//'_L', layer
467  write (varname, '(a,i0)') trim(varname)//'_l', layer
468  end if
469  end if
470  end function export_varname
471 
472  !> @brief build netcdf variable longname
473  !<
474  function export_longname(longname, pkgname, tagname, mempath, layer, iaux) &
475  result(lname)
478  use inputoutputmodule, only: lowcase
479  character(len=*), intent(in) :: longname
480  character(len=*), intent(in) :: pkgname
481  character(len=*), intent(in) :: tagname
482  character(len=*), intent(in) :: mempath
483  integer(I4B), optional, intent(in) :: layer
484  integer(I4B), optional, intent(in) :: iaux
485  character(len=LINELENGTH) :: lname
486  type(characterstringtype), dimension(:), pointer, &
487  contiguous :: auxnames
488  character(len=LINELENGTH) :: pname, vname, auxname
489  pname = pkgname
490  vname = tagname
491  call lowcase(pname)
492  call lowcase(vname)
493  if (longname == '') then
494  lname = trim(pname)//' '//trim(vname)
495  else
496  lname = longname
497  end if
498 
499  if (present(iaux)) then
500  if (iaux > 0) then
501  if (tagname == 'AUX') then
502  ! reset vname to auxiliary variable name
503  call mem_setptr(auxnames, 'AUXILIARY', mempath)
504  auxname = auxnames(iaux)
505  call lowcase(auxname)
506  lname = trim(lname)//' '//trim(auxname)
507  end if
508  end if
509  end if
510 
511  if (present(layer)) then
512  if (layer > 0) then
513  write (lname, '(a,i0)') trim(lname)//' layer ', layer
514  end if
515  end if
516  end function export_longname
517 
518  !> @brief netcdf dynamic package period export
519  !<
520  subroutine export_input(this)
521  use tdismodule, only: kper
522  class(ncbasemodelexporttype), intent(inout) :: this
523  integer(I4B) :: idx
524  class(exportpackagetype), pointer :: export_pkg
525  do idx = 1, this%pkglist%Count()
526  export_pkg => this%get(idx)
527  ! last loaded data is not current period
528  if (export_pkg%iper /= kper) cycle
529  ! period input already exported
530  if (export_pkg%iper_export >= export_pkg%iper) cycle
531  ! set exported iper
532  export_pkg%iper_export = export_pkg%iper
533  ! update export package
534  call this%package_step(export_pkg)
535  end do
536  end subroutine export_input
537 
538  !> @brief destroy model netcdf export object
539  !<
540  subroutine export_destroy(this)
543  class(ncmodelexporttype), intent(inout) :: this
544  ! override in derived class
545  deallocate (this%deflate)
546  deallocate (this%shuffle)
547  deallocate (this%input_attr)
548  deallocate (this%chunk_time)
549  ! Deallocate idm memory
550  if (this%ncf_mempath /= '') then
551  call memorystore_remove(this%modelname, 'NCF', idm_context)
552  end if
553  end subroutine export_destroy
554 
555 end module ncmodelexportmodule
subroutine init()
Definition: GridSorting.f90:24
abstract interfaces for model netcdf export type
Definition: NCModel.f90:117
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
This module contains the LoadContextModule.
Definition: LoadContext.f90:10
character(len=lenvarname) function, public rsv_name(mf6varname)
create read state variable name
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:399
character(len=linelength) function, public export_varname(pkgname, tagname, mempath, layer, iaux)
build netcdf variable name
Definition: NCModel.f90:435
subroutine epkg_init(this, mf6_input, mshape, naux, param_names, nparam)
initialize dynamic package export object
Definition: NCModel.f90:146
@, public netcdf_structured
netcdf structrured export
Definition: NCModel.f90:33
subroutine export_destroy(this)
destroy model netcdf export object
Definition: NCModel.f90:541
character(len=linelength) function, public export_longname(longname, pkgname, tagname, mempath, layer, iaux)
build netcdf variable longname
Definition: NCModel.f90:476
subroutine export_init(this, modelname, modeltype, modelfname, nc_fname, disenum, nctype, iout)
initialization of model netcdf export
Definition: NCModel.f90:275
@, public netcdf_mesh2d
netcdf ugrid layered mesh export
Definition: NCModel.f90:34
@, public netcdf_undef
undefined netcdf export type
Definition: NCModel.f90:32
subroutine set(this, modelname, modeltype, modelfname, nctype, disenum)
set netcdf file scoped attributes
Definition: NCModel.f90:201
character(len=linelength) function input_attribute(this, pkgname, idt)
build modflow_input attribute string
Definition: NCModel.f90:417
subroutine epkg_destroy(this)
destroy dynamic package export object
Definition: NCModel.f90:193
subroutine export_input(this)
netcdf dynamic package period export
Definition: NCModel.f90:521
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 inats
flag indicating ats active for simulation
Definition: tdis.f90:25
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
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
type for storing a dynamic package load list
A generic heterogeneous doubly-linked list.
Definition: List.f90:14
Pointer type for read state variable.
Definition: LoadContext.f90:46
derived type for storing input definition for a file
abstract type for model netcdf export type
Definition: NCModel.f90:105
netcdf export attribute annotations
Definition: NCModel.f90:55
base class for an export model
Definition: NCModel.f90:71