MODFLOW 6  version 6.6.0.dev0
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  use simvariablesmodule, only: errmsg
18  use listmodule, only: listtype
19 
20  implicit none
21  private
23  public :: ncexportannotation
24  public :: exportpackagetype
26  public :: export_longname
27 
28  !> @brief netcdf export types enumerator
29  !<
30  ENUM, BIND(C)
31  ENUMERATOR :: netcdf_undef = 0 !< undefined netcdf export type
32  ENUMERATOR :: netcdf_ugrid = 1 !< netcdf mesh export
33  ENUMERATOR :: netcdf_structured = 2 !< netcdf structrured export
34  END ENUM
35 
37  type(modflowinputtype) :: mf6_input !< description of modflow6 input
38  character(len=LINELENGTH), dimension(:), allocatable :: param_names !< dynamic param tagnames
39  type(readstatevartype), dimension(:), allocatable :: param_reads !< param read states
40  integer(I4B), dimension(:), pointer, contiguous :: mshape => null() !< model shape
41  integer(I4B), pointer :: iper !< most recent package rp load
42  integer(I4B) :: iper_export !< most recent period of netcdf package export
43  integer(I4B) :: nparam !< number of in scope params
44  contains
45  procedure :: init => epkg_init
46  procedure :: destroy => epkg_destroy
47  end type exportpackagetype
48 
49  !> @brief netcdf export attribute annotations
50  !<
52  character(len=LINELENGTH) :: title !< file scoped title attribute
53  character(len=LINELENGTH) :: model !< file scoped model attribute
54  character(len=LINELENGTH) :: grid !< grid type
55  character(len=LINELENGTH) :: history !< file scoped history attribute
56  character(len=LINELENGTH) :: source !< file scoped source attribute
57  character(len=LINELENGTH) :: conventions !< file scoped conventions attribute
58  character(len=LINELENGTH) :: stdname !< dependent variable standard name
59  character(len=LINELENGTH) :: longname !< dependent variable long name
60  contains
61  procedure :: set
62  end type ncexportannotation
63 
64  !> @brief base class for an export model
65  !<
67  type(listtype) :: pkglist
68  character(len=LENMODELNAME) :: modelname !< name of model
69  character(len=LENCOMPONENTNAME) :: modeltype !< type of model
70  character(len=LINELENGTH) :: modelfname !< name of model input file
71  character(len=LINELENGTH) :: nc_fname !< name of netcdf export file
72  character(len=LINELENGTH) :: gridmap_name !< name of grid mapping variable
73  character(len=LINELENGTH) :: mesh_name = 'mesh' !< name of mesh container variable
74  character(len=LENMEMPATH) :: dis_mempath !< discretization input mempath
75  character(len=LENMEMPATH) :: ncf_mempath !< netcdf utility package input mempath
76  character(len=LENBIGLINE) :: ogc_wkt !< wkt user string
77  character(len=LINELENGTH) :: datetime !< export file creation time
78  character(len=LINELENGTH) :: xname !< dependent variable name
79  type(ncexportannotation) :: annotation !< export file annotation
80  real(dp), dimension(:), pointer, contiguous :: x !< dependent variable pointer
81  integer(I4B) :: disenum !< type of discretization
82  integer(I4B) :: ncid !< netcdf file descriptor
83  integer(I4B) :: stepcnt !< simulation step count
84  integer(I4B) :: totnstp !< simulation total number of steps
85  integer(I4B), pointer :: deflate !< variable deflate level
86  integer(I4B), pointer :: shuffle !< variable shuffle filter
87  integer(I4B), pointer :: input_attr !< assign variable input attr
88  integer(I4B), pointer :: chunk_time !< chunking parameter for time dimension
89  integer(I4B) :: iout !< lst file descriptor
90  logical(LGP) :: chunking_active !< have chunking parameters been provided
91  contains
92  procedure :: init => export_init
93  procedure :: get => export_get
94  procedure :: input_attribute
95  procedure :: destroy => export_destroy
96  end type ncmodelexporttype
97 
98  !> @brief abstract type for model netcdf export type
99  !<
100  type, abstract, extends(ncmodelexporttype) :: ncbasemodelexporttype
101  contains
102  procedure :: export_input
103  procedure(model_define), deferred :: df
104  procedure(model_step), deferred :: step
105  procedure(package_export), deferred :: package_step
106  procedure(package_export_ilayer), deferred :: package_step_ilayer
107  end type ncbasemodelexporttype
108 
109  !> @brief abstract interfaces for model netcdf export type
110  !<
111  abstract interface
112  subroutine model_define(this)
113  import ncbasemodelexporttype
114  class(ncbasemodelexporttype), intent(inout) :: this
115  end subroutine
116  subroutine model_step(this)
117  import ncbasemodelexporttype
118  class(ncbasemodelexporttype), intent(inout) :: this
119  end subroutine
120  subroutine package_export(this, export_pkg)
122  class(ncbasemodelexporttype), intent(inout) :: this
123  class(exportpackagetype), pointer, intent(in) :: export_pkg
124  end subroutine
125  subroutine package_export_ilayer(this, export_pkg, ilayer_varname, &
126  ilayer)
128  class(ncbasemodelexporttype), intent(inout) :: this
129  class(exportpackagetype), pointer, intent(in) :: export_pkg
130  character(len=*), intent(in) :: ilayer_varname
131  integer(I4B), intent(in) :: ilayer
132  end subroutine
133  end interface
134 
135 contains
136 
137  !> @brief initialize dynamic package export object
138  !<
139  subroutine epkg_init(this, mf6_input, mshape, param_names, &
140  nparam)
145  ! -- dummy
146  class(exportpackagetype), intent(inout) :: this
147  type(modflowinputtype), intent(in) :: mf6_input
148  integer(I4B), dimension(:), pointer, contiguous, intent(in) :: mshape !< model shape
149  character(len=LINELENGTH), dimension(:), allocatable, &
150  intent(in) :: param_names
151  integer(I4B), intent(in) :: nparam
152  integer(I4B) :: n
153  character(len=LENVARNAME) :: rs_varname
154  character(len=LENMEMPATH) :: input_mempath
155  integer(I4B), pointer :: rsvar
156  !
157  this%mf6_input = mf6_input
158  this%mshape => mshape
159  this%nparam = nparam
160  this%iper_export = 0
161  !
162  input_mempath = create_mem_path(component=mf6_input%component_name, &
163  subcomponent=mf6_input%subcomponent_name, &
164  context=idm_context)
165  !
166  ! -- allocate param arrays
167  allocate (this%param_names(nparam))
168  allocate (this%param_reads(nparam))
169  !
170  ! -- set param arrays
171  do n = 1, nparam
172  this%param_names(n) = param_names(n)
173  rs_varname = rsv_name(param_names(n))
174  call mem_setptr(rsvar, rs_varname, mf6_input%mempath)
175  this%param_reads(n)%invar => rsvar
176  end do
177  !
178  ! -- set pointer to loaded input period
179  call mem_setptr(this%iper, 'IPER', mf6_input%mempath)
180  end subroutine epkg_init
181 
182  !> @brief destroy dynamic package export object
183  !<
184  subroutine epkg_destroy(this)
186  ! -- dummy
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_ugrid) 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  ! -- set export type
238  if (nctype == netcdf_ugrid) then
239  this%grid = 'LAYERED MESH'
240  else if (nctype == netcdf_structured) then
241  this%grid = 'STRUCTURED'
242  end if
243  !
244  ! -- model description string
245  this%model = trim(modelname)//': MODFLOW 6 '//trim(fullname)// &
246  ' ('//trim(modeltype)//') model'
247  !
248  ! -- modflow6 version string
249  this%source = 'MODFLOW 6 '//trim(adjustl(version))
250  !
251  ! -- create timestamp
252  call date_and_time(values=values)
253  write (this%history, '(a,i0,a,i0,a,i0,a,i0,a,i0,a,i0,a,i0)') &
254  'first created ', values(1), '/', values(2), '/', values(3), ' ', &
255  values(5), ':', values(6), ':', values(7), '.', values(8)
256  end subroutine set
257 
258  !> @brief initialization of model netcdf export
259  !<
260  subroutine export_init(this, modelname, modeltype, modelfname, disenum, &
261  nctype, iout)
263  use tdismodule, only: datetime0, nstp
264  use constantsmodule, only: mvalidate
268  use inputoutputmodule, only: lowcase
270  class(ncmodelexporttype), intent(inout) :: this
271  character(len=*), intent(in) :: modelname
272  character(len=*), intent(in) :: modeltype
273  character(len=*), intent(in) :: modelfname
274  integer(I4B), intent(in) :: disenum
275  integer(I4B), intent(in) :: nctype
276  integer(I4B), intent(in) :: iout
277  character(len=LENMEMPATH) :: model_mempath
278  type(utlncfparamfoundtype) :: found
279  logical(LGP) :: found_mempath
280  !
281  ! -- allocate
282  allocate (this%deflate)
283  allocate (this%shuffle)
284  allocate (this%input_attr)
285  allocate (this%chunk_time)
286  !
287  ! -- initialize
288  this%modelname = modelname
289  this%modeltype = modeltype
290  this%modelfname = modelfname
291  this%nc_fname = trim(modelname)//'.nc'
292  this%gridmap_name = ''
293  this%ncf_mempath = ''
294  this%ogc_wkt = ''
295  this%datetime = ''
296  this%xname = ''
297  this%disenum = disenum
298  this%ncid = 0
299  this%stepcnt = 0
300  this%totnstp = 0
301  this%deflate = -1
302  this%shuffle = 0
303  this%input_attr = 1
304  this%chunk_time = -1
305  this%iout = iout
306  this%chunking_active = .false.
307  !
308  call lowcase(this%nc_fname)
309  !
310  ! -- set file scoped attributes
311  call this%annotation%set(modelname, modeltype, modelfname, nctype)
312  !
313  ! -- set dependent variable basename
314  select case (modeltype)
315  case ('GWF')
316  this%xname = 'head'
317  case ('GWT')
318  this%xname = 'concentration'
319  case ('GWE')
320  this%xname = 'temperature'
321  case default
322  errmsg = trim(modeltype)//' models not supported for NetCDF export.'
323  call store_error(errmsg)
324  call store_error_filename(modelfname)
325  end select
326  !
327  ! -- set discretization input mempath
328  if (disenum == dis) then
329  this%dis_mempath = create_mem_path(modelname, 'DIS', idm_context)
330  else if (disenum == disu) then
331  this%dis_mempath = create_mem_path(modelname, 'DISU', idm_context)
332  else if (disenum == disv) then
333  this%dis_mempath = create_mem_path(modelname, 'DISV', idm_context)
334  end if
335  !
336  ! -- set dependent variable pointer
337  model_mempath = create_mem_path(component=modelname)
338  call mem_setptr(this%x, 'X', model_mempath)
339  !
340  ! --set ncf_mempath if provided
341  call mem_set_value(this%ncf_mempath, 'NCF6_MEMPATH', this%dis_mempath, &
342  found_mempath)
343  !
344  if (found_mempath) then
345  call mem_set_value(this%ogc_wkt, 'OGC_WKT', this%ncf_mempath, &
346  found%ogc_wkt)
347  call mem_set_value(this%deflate, 'DEFLATE', this%ncf_mempath, &
348  found%deflate)
349  call mem_set_value(this%shuffle, 'SHUFFLE', this%ncf_mempath, &
350  found%shuffle)
351  call mem_set_value(this%input_attr, 'ATTR_OFF', this%ncf_mempath, &
352  found%attr_off)
353  call mem_set_value(this%chunk_time, 'CHUNK_TIME', this%ncf_mempath, &
354  found%chunk_time)
355  end if
356  !
357  if (found%ogc_wkt) then
358  this%gridmap_name = 'projection'
359  end if
360  !
361  ! -- ATTR_OFF turns off modflow 6 input attributes
362  if (found%attr_off) then
363  this%input_attr = 0
364  end if
365  !
366  ! -- set datetime string
367  if (isim_mode /= mvalidate .and. datetime0 == '') then
368  errmsg = 'TDIS parameter START_DATE_TIME required for NetCDF export.'
369  call store_error(errmsg)
370  call store_error_filename(modelfname)
371  else
372  this%datetime = 'days since '//trim(datetime0)
373  end if
374  !
375  ! -- set total nstp
376  this%totnstp = sum(nstp)
377  end subroutine export_init
378 
379  !> @brief retrieve dynamic export object from package list
380  !<
381  function export_get(this, idx) result(res)
382  use listmodule, only: listtype
383  class(ncmodelexporttype), intent(inout) :: this
384  integer(I4B), intent(in) :: idx
385  class(exportpackagetype), pointer :: res
386  class(*), pointer :: obj
387  !
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  !
409  attr = ''
410  !
411  if (this%input_attr > 0) then
412  attr = trim(this%modelname)//mempathseparator//trim(pkgname)// &
413  mempathseparator//trim(idt%mf6varname)
414  end if
415  end function input_attribute
416 
417  !> @brief build netcdf variable longname
418  !<
419  function export_longname(longname, pkgname, tagname, layer, iper) result(lname)
420  use inputoutputmodule, only: lowcase
421  character(len=*), intent(in) :: longname
422  character(len=*), intent(in) :: pkgname
423  character(len=*), intent(in) :: tagname
424  integer(I4B), intent(in) :: layer
425  integer(I4B), optional, intent(in) :: iper
426  character(len=LINELENGTH) :: lname
427  character(len=LINELENGTH) :: pname, vname
428  !
429  pname = pkgname
430  vname = tagname
431  call lowcase(pname)
432  call lowcase(vname)
433  if (longname == '') then
434  lname = trim(pname)//' '//trim(vname)
435  else
436  lname = longname
437  end if
438  if (layer > 0) then
439  write (lname, '(a,i0)') trim(lname)//' layer=', layer
440  end if
441  if (present(iper)) then
442  if (iper > 0) then
443  write (lname, '(a,i0)') trim(lname)//' period=', iper
444  end if
445  end if
446  end function export_longname
447 
448  !> @brief netcdf dynamic package period export
449  !<
450  subroutine export_input(this)
451  use tdismodule, only: kper
452  use arrayhandlersmodule, only: ifind
453  class(ncbasemodelexporttype), intent(inout) :: this
454  integer(I4B) :: idx, ilayer
455  class(exportpackagetype), pointer :: export_pkg
456  character(len=LENVARNAME) :: ilayer_varname
457  !
458  do idx = 1, this%pkglist%Count()
459  !
460  export_pkg => this%get(idx)
461  ! -- last loaded data is not current period
462  if (export_pkg%iper /= kper) cycle
463  ! -- period input already exported
464  if (export_pkg%iper_export >= export_pkg%iper) cycle
465  ! -- set exported iper
466  export_pkg%iper_export = export_pkg%iper
467  !
468  ! -- initialize ilayer
469  ilayer = 0
470  !
471  ! -- set expected ilayer index variable name
472  ilayer_varname = 'I'//trim(export_pkg%mf6_input%subcomponent_type(1:3))
473  !
474  ! -- is ilayer variable in param name list
475  ilayer = ifind(export_pkg%param_names, ilayer_varname)
476  !
477  ! -- layer index variable is required to be first defined in period block
478  if (ilayer == 1) then
479  call this%package_step_ilayer(export_pkg, ilayer_varname, ilayer)
480  else
481  call this%package_step(export_pkg)
482  end if
483  !
484  end do
485  end subroutine export_input
486 
487  !> @brief destroy model netcdf export object
488  !<
489  subroutine export_destroy(this)
492  class(ncmodelexporttype), intent(inout) :: this
493  !
494  ! -- override in derived class
495  deallocate (this%deflate)
496  deallocate (this%shuffle)
497  deallocate (this%input_attr)
498  deallocate (this%chunk_time)
499  !
500  ! -- Deallocate idm memory
501  if (this%ncf_mempath /= '') then
502  call memorystore_remove(this%modelname, 'NCF', idm_context)
503  end if
504  end subroutine export_destroy
505 
506 end module ncmodelexportmodule
subroutine init()
Definition: GridSorting.f90:24
abstract interfaces for model netcdf export type
Definition: NCModel.f90:112
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:382
subroutine epkg_init(this, mf6_input, mshape, param_names, nparam)
initialize dynamic package export object
Definition: NCModel.f90:141
subroutine export_init(this, modelname, modeltype, modelfname, disenum, nctype, iout)
initialization of model netcdf export
Definition: NCModel.f90:262
@, 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:420
subroutine export_destroy(this)
destroy model netcdf export object
Definition: NCModel.f90:490
subroutine set(this, modelname, modeltype, modelfname, nctype)
set netcdf file scoped attributes
Definition: NCModel.f90:194
@, public netcdf_undef
undefined netcdf export type
Definition: NCModel.f90:31
character(len=linelength) function input_attribute(this, pkgname, idt)
build modflow6_input attribute string
Definition: NCModel.f90:401
@, public netcdf_ugrid
netcdf mesh export
Definition: NCModel.f90:32
subroutine epkg_destroy(this)
destroy dynamic package export object
Definition: NCModel.f90:185
subroutine export_input(this)
netcdf dynamic package period export
Definition: NCModel.f90:451
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:100
netcdf export attribute annotations
Definition: NCModel.f90:51
base class for an export model
Definition: NCModel.f90:66