MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
Disu.f90
Go to the documentation of this file.
1 module disumodule
2 
4  use kindmodule, only: dp, i4b, lgp
13  use basedismodule, only: disbasetype
18  use tdismodule, only: kstp, kper, pertim, totim, delt
19  use disvgeom, only: line_unit_vector
20 
21  implicit none
22 
23  private
24  public :: disutype
25  public :: disu_cr
26  public :: castasdisutype
27 
28  !> @brief Unstructured grid discretization
29  type, extends(disbasetype) :: disutype
30  integer(I4B), pointer :: njausr => null() ! user-specified nja size
31  integer(I4B), pointer :: nvert => null() ! number of x,y vertices
32  real(dp), pointer :: voffsettol => null() ! vertical offset tolerance
33  real(dp), dimension(:, :), pointer, contiguous :: vertices => null() ! cell vertices stored as 2d array of x and y
34  real(dp), dimension(:, :), pointer, contiguous :: cellxy => null() ! cell center stored as 2d array of x and y
35  real(dp), dimension(:), pointer, contiguous :: top1d => null() ! (size:nodesuser) cell top elevation
36  real(dp), dimension(:), pointer, contiguous :: bot1d => null() ! (size:nodesuser) cell bottom elevation
37  real(dp), dimension(:), pointer, contiguous :: area1d => null() ! (size:nodesuser) cell area, in plan view
38  integer(I4B), dimension(:), pointer, contiguous :: iainp => null() ! (size:nodesuser+1) user iac converted ia
39  integer(I4B), dimension(:), pointer, contiguous :: jainp => null() ! (size:njausr) user-input ja array
40  integer(I4B), dimension(:), pointer, contiguous :: ihcinp => null() ! (size:njausr) user-input ihc array
41  real(dp), dimension(:), pointer, contiguous :: cl12inp => null() ! (size:njausr) user-input cl12 array
42  real(dp), dimension(:), pointer, contiguous :: hwvainp => null() ! (size:njausr) user-input hwva array
43  real(dp), dimension(:), pointer, contiguous :: angldegxinp => null() ! (size:njausr) user-input angldegx array
44  integer(I4B), pointer :: iangledegx => null() ! =1 when angle information was present in input, 0 otherwise
45  integer(I4B), dimension(:), pointer, contiguous :: iavert => null() ! cell vertex pointer ia array
46  integer(I4B), dimension(:), pointer, contiguous :: javert => null() ! cell vertex pointer ja array
47  integer(I4B), dimension(:), pointer, contiguous :: idomain => null() ! idomain (nodes)
48  logical(LGP) :: readfromfile ! True, when DIS is read from file (almost always)
49 
50  contains
51 
52  procedure :: dis_df => disu_df
53  procedure :: disu_load
54  procedure :: dis_da => disu_da
55  procedure :: get_dis_type => get_dis_type
56  procedure :: get_dis_enum => get_dis_enum
57  procedure :: disu_ck
58  procedure :: grid_finalize
59  procedure :: get_nodenumber_idx1
60  procedure :: nodeu_to_string
61  procedure :: nodeu_to_array
62  procedure :: nodeu_from_string
63  procedure :: nodeu_from_cellid
64  procedure :: connection_normal
65  procedure :: connection_vector
66  procedure :: supports_layers
67  procedure :: get_ncpl
68  procedure :: get_polyverts
69  procedure :: get_npolyverts
70  procedure :: get_max_npolyverts
71  procedure, public :: record_array
72  procedure, public :: record_srcdst_list_header
73  ! -- private
74  procedure :: allocate_scalars
75  procedure :: allocate_arrays
76  procedure :: allocate_arrays_mem
77  procedure :: source_options
78  procedure :: source_dimensions
79  procedure :: source_griddata
80  procedure :: source_connectivity
81  procedure :: source_vertices
82  procedure :: source_cell2d
83  procedure :: log_options
84  procedure :: log_dimensions
85  procedure :: log_griddata
86  procedure :: log_connectivity
87  procedure :: define_cellverts
88  procedure :: write_grb
89  !
90  ! -- Read a node-sized model array (reduced or not)
91  procedure :: read_int_array
92  procedure :: read_dbl_array
93 
94  end type disutype
95 
97  logical :: length_units = .false.
98  logical :: nogrb = .false.
99  logical :: xorigin = .false.
100  logical :: yorigin = .false.
101  logical :: angrot = .false.
102  logical :: voffsettol = .false.
103  logical :: nodes = .false.
104  logical :: nja = .false.
105  logical :: nvert = .false.
106  logical :: top = .false.
107  logical :: bot = .false.
108  logical :: area = .false.
109  logical :: idomain = .false.
110  logical :: iac = .false.
111  logical :: ja = .false.
112  logical :: ihc = .false.
113  logical :: cl12 = .false.
114  logical :: hwva = .false.
115  logical :: angldegx = .false.
116  logical :: iv = .false.
117  logical :: xv = .false.
118  logical :: yv = .false.
119  logical :: icell2d = .false.
120  logical :: xc = .false.
121  logical :: yc = .false.
122  logical :: ncvert = .false.
123  logical :: icvert = .false.
124  end type disufoundtype
125 
126 contains
127 
128  !> @brief Create a new unstructured discretization object
129  !<
130  subroutine disu_cr(dis, name_model, input_mempath, inunit, iout)
131  ! -- dummy
132  class(disbasetype), pointer :: dis
133  character(len=*), intent(in) :: name_model
134  character(len=*), intent(in) :: input_mempath
135  integer(I4B), intent(in) :: inunit
136  integer(I4B), intent(in) :: iout
137  ! -- local
138  type(disutype), pointer :: disnew
139  character(len=*), parameter :: fmtheader = &
140  "(1X, /1X, 'DISU -- UNSTRUCTURED GRID DISCRETIZATION PACKAGE,', &
141  &' VERSION 2 : 3/27/2014 - INPUT READ FROM MEMPATH: ', A, //)"
142  !
143  ! -- Create a new discretization object
144  allocate (disnew)
145  dis => disnew
146  !
147  ! -- Allocate scalars and assign data
148  call dis%allocate_scalars(name_model, input_mempath)
149  dis%inunit = inunit
150  dis%iout = iout
151  !
152  ! -- If disu is enabled
153  if (inunit > 0) then
154  !
155  ! -- Identify package
156  if (iout > 0) then
157  write (iout, fmtheader) dis%input_mempath
158  end if
159  !
160  ! -- load disu
161  call disnew%disu_load()
162  end if
163  !
164  end subroutine disu_cr
165 
166  !> @brief Transfer IDM data into this discretization object
167  !<
168  subroutine disu_load(this)
169  ! -- dummy
170  class(disutype) :: this
171  !
172  ! -- source input data
173  call this%source_options()
174  call this%source_dimensions()
175  call this%source_griddata()
176  call this%source_connectivity()
177  !
178  ! -- If NVERT specified and greater than 0, then source VERTICES and CELL2D
179  if (this%nvert > 0) then
180  call this%source_vertices()
181  call this%source_cell2d()
182  else
183  ! -- connection direction information cannot be calculated
184  this%icondir = 0
185  end if
186  !
187  ! -- Make some final disu checks on the non-reduced user-provided
188  ! input
189  call this%disu_ck()
190  !
191  end subroutine disu_load
192 
193  !> @brief Define the discretization
194  !<
195  subroutine disu_df(this)
196  ! -- dummy
197  class(disutype) :: this
198  !
199  call this%grid_finalize()
200  !
201  end subroutine disu_df
202 
203  !> @brief Finalize the grid
204  !<
205  subroutine grid_finalize(this)
206  ! -- dummy
207  class(disutype) :: this
208  ! -- locals
209  integer(I4B) :: n
210  integer(I4B) :: node
211  integer(I4B) :: noder
212  integer(I4B) :: nrsize
213  ! -- formats
214  character(len=*), parameter :: fmtdz = &
215  "('CELL (',i0,',',i0,',',i0,') THICKNESS <= 0. ', &
216  &'TOP, BOT: ',2(1pg24.15))"
217  character(len=*), parameter :: fmtnr = &
218  "(/1x, 'The specified IDOMAIN results in a reduced number of cells.',&
219  &/1x, 'Number of user nodes: ',I0,&
220  &/1X, 'Number of nodes in solution: ', I0, //)"
221  !
222  ! -- count active cells
223  this%nodes = 0
224  do n = 1, this%nodesuser
225  if (this%idomain(n) > 0) this%nodes = this%nodes + 1
226  end do
227  !
228  ! -- Check to make sure nodes is a valid number
229  if (this%nodes == 0) then
230  call store_error('Model does not have any active nodes. &
231  &Ensure IDOMAIN array has some values greater &
232  &than zero.')
233  call store_error_filename(this%input_fname)
234  end if
235  !
236  ! -- Write message if reduced grid
237  if (this%nodes < this%nodesuser) then
238  write (this%iout, fmtnr) this%nodesuser, this%nodes
239  end if
240  !
241  ! -- Array size is now known, so allocate
242  call this%allocate_arrays()
243  !
244  ! -- Fill the nodereduced array with the reduced nodenumber, or
245  ! a negative number to indicate it is a pass-through cell, or
246  ! a zero to indicate that the cell is excluded from the
247  ! solution. (negative idomain not supported for disu)
248  if (this%nodes < this%nodesuser) then
249  noder = 1
250  do node = 1, this%nodesuser
251  if (this%idomain(node) > 0) then
252  this%nodereduced(node) = noder
253  noder = noder + 1
254  elseif (this%idomain(node) < 0) then
255  this%nodereduced(node) = -1
256  else
257  this%nodereduced(node) = 0
258  end if
259  end do
260  end if
261  !
262  ! -- Fill nodeuser if a reduced grid
263  if (this%nodes < this%nodesuser) then
264  noder = 1
265  do node = 1, this%nodesuser
266  if (this%idomain(node) > 0) then
267  this%nodeuser(noder) = node
268  noder = noder + 1
269  end if
270  end do
271  end if
272  !
273  ! -- Move top1d, bot1d, and area1d into top, bot, and area
274  do node = 1, this%nodesuser
275  noder = node
276  if (this%nodes < this%nodesuser) noder = this%nodereduced(node)
277  if (noder <= 0) cycle
278  this%top(noder) = this%top1d(node)
279  this%bot(noder) = this%bot1d(node)
280  this%area(noder) = this%area1d(node)
281  end do
282  !
283  ! -- fill cell center coordinates
284  if (this%nvert > 0) then
285  do node = 1, this%nodesuser
286  noder = node
287  if (this%nodes < this%nodesuser) noder = this%nodereduced(node)
288  if (noder <= 0) cycle
289  this%xc(noder) = this%cellxy(1, node)
290  this%yc(noder) = this%cellxy(2, node)
291  end do
292  else
293  call mem_reallocate(this%xc, 0, 'XC', this%memoryPath)
294  call mem_reallocate(this%yc, 0, 'YC', this%memoryPath)
295  end if
296  !
297  ! -- create and fill the connections object
298  nrsize = 0
299  if (this%nodes < this%nodesuser) nrsize = this%nodes
300  allocate (this%con)
301  call this%con%disuconnections(this%name_model, this%nodes, &
302  this%nodesuser, nrsize, &
303  this%nodereduced, this%nodeuser, &
304  this%iainp, this%jainp, &
305  this%ihcinp, this%cl12inp, &
306  this%hwvainp, this%angldegxinp, &
307  this%iangledegx)
308  this%nja = this%con%nja
309  this%njas = this%con%njas
310  !
311  end subroutine grid_finalize
312 
313  !> @brief Check discretization info
314  !<
315  subroutine disu_ck(this)
316  ! -- dummy
317  class(disutype) :: this
318  ! -- local
319  integer(I4B) :: n, m
320  integer(I4B) :: ipos
321  integer(I4B) :: ihc
322  real(DP) :: dz
323  ! -- formats
324  character(len=*), parameter :: fmtidm = &
325  &"('Invalid idomain value ', i0, ' specified for node ', i0)"
326  character(len=*), parameter :: fmtdz = &
327  &"('Cell ', i0, ' with thickness <= 0. Top, bot: ', 2(1pg24.15))"
328  character(len=*), parameter :: fmtarea = &
329  &"('Cell ', i0, ' with area <= 0. Area: ', 1(1pg24.15))"
330  character(len=*), parameter :: fmtjan = &
331  &"('Cell ', i0, ' must have its first connection be itself. Found: ', i0)"
332  character(len=*), parameter :: fmtjam = &
333  &"('Cell ', i0, ' has invalid connection in JA. Found: ', i0)"
334  character(len=*), parameter :: fmterrmsg = &
335  "('Top elevation (', 1pg15.6, ') for cell ', i0, ' is above bottom &
336  &elevation (', 1pg15.6, ') for cell ', i0, '. Based on node numbering &
337  &rules cell ', i0, ' must be below cell ', i0, '.')"
338  !
339  ! -- Check connectivity
340  do n = 1, this%nodesuser
341  !
342  ! -- Ensure first connection is to itself, and
343  ! that ja(ia(n)) is positive
344  ipos = this%iainp(n)
345  m = this%jainp(ipos)
346  if (m < 0) then
347  m = abs(m)
348  this%jainp(ipos) = m
349  end if
350  if (n /= m) then
351  write (errmsg, fmtjan) n, m
352  call store_error(errmsg)
353  end if
354  !
355  ! -- Check for valid node numbers in connected cells
356  do ipos = this%iainp(n) + 1, this%iainp(n + 1) - 1
357  m = this%jainp(ipos)
358  if (m < 0 .or. m > this%nodesuser) then
359  ! -- make sure first connection is to itself
360  write (errmsg, fmtjam) n, m
361  call store_error(errmsg)
362  end if
363  end do
364  end do
365  !
366  ! -- terminate if errors found
367  if (count_errors() > 0) then
368  if (this%inunit > 0) then
369  call store_error_filename(this%input_fname)
370  end if
371  end if
372  !
373  ! -- Ensure idomain values are valid
374  do n = 1, this%nodesuser
375  if (this%idomain(n) > 1 .or. this%idomain(n) < 0) then
376  write (errmsg, fmtidm) this%idomain(n), n
377  call store_error(errmsg)
378  end if
379  end do
380  !
381  ! -- Check for zero and negative thickness and zero or negative areas
382  ! for cells with idomain == 1
383  do n = 1, this%nodesuser
384  if (this%idomain(n) == 1) then
385  dz = this%top1d(n) - this%bot1d(n)
386  if (dz <= dzero) then
387  write (errmsg, fmt=fmtdz) n, this%top1d(n), this%bot1d(n)
388  call store_error(errmsg)
389  end if
390  if (this%area1d(n) <= dzero) then
391  write (errmsg, fmt=fmtarea) n, this%area1d(n)
392  call store_error(errmsg)
393  end if
394  end if
395  end do
396  !
397  ! -- check to make sure voffsettol is >= 0
398  if (this%voffsettol < dzero) then
399  write (errmsg, '(a, 1pg15.6)') &
400  'Vertical offset tolerance must be greater than zero. Found ', &
401  this%voffsettol
402  call store_error(errmsg)
403  if (this%inunit > 0) then
404  call store_error_filename(this%input_fname)
405  end if
406  end if
407  !
408  ! -- For cell n, ensure that underlying cells have tops less than
409  ! or equal to the bottom of cell n
410  do n = 1, this%nodesuser
411  do ipos = this%iainp(n) + 1, this%iainp(n + 1) - 1
412  m = this%jainp(ipos)
413  ihc = this%ihcinp(ipos)
414  if (ihc == 0 .and. m > n) then
415  dz = this%top1d(m) - this%bot1d(n)
416  if (dz > this%voffsettol) then
417  write (errmsg, fmterrmsg) this%top1d(m), m, this%bot1d(n), n, m, n
418  call store_error(errmsg)
419  end if
420  end if
421  end do
422  end do
423  !
424  ! -- terminate if errors found
425  if (count_errors() > 0) then
426  if (this%inunit > 0) then
427  call store_error_filename(this%input_fname)
428  end if
429  end if
430  !
431  end subroutine disu_ck
432 
433  !> @brief Deallocate variables
434  !<
435  subroutine disu_da(this)
436  ! -- dummy
437  class(disutype) :: this
438  !
439  ! -- Deallocate idm memory
440  call memorystore_remove(this%name_model, 'DISU', idm_context)
441  call memorystore_remove(component=this%name_model, &
442  context=idm_context)
443  !
444  ! -- scalars
445  call mem_deallocate(this%njausr)
446  call mem_deallocate(this%nvert)
447  call mem_deallocate(this%voffsettol)
448  call mem_deallocate(this%iangledegx)
449  !
450  ! -- arrays
451  if (this%readFromFile) then
452  call mem_deallocate(this%top1d)
453  call mem_deallocate(this%bot1d)
454  call mem_deallocate(this%area1d)
455  if (associated(this%iavert)) then
456  call mem_deallocate(this%iavert)
457  call mem_deallocate(this%javert)
458  end if
459  call mem_deallocate(this%vertices)
460  call mem_deallocate(this%iainp)
461  call mem_deallocate(this%jainp)
462  call mem_deallocate(this%ihcinp)
463  call mem_deallocate(this%cl12inp)
464  call mem_deallocate(this%hwvainp)
465  call mem_deallocate(this%angldegxinp)
466  end if
467  !
468  call mem_deallocate(this%idomain)
469  call mem_deallocate(this%cellxy)
470  !
471  call mem_deallocate(this%nodeuser)
472  call mem_deallocate(this%nodereduced)
473  !
474  ! -- DisBaseType deallocate
475  call this%DisBaseType%dis_da()
476  !
477  end subroutine disu_da
478 
479  !> @brief Convert a user nodenumber to a string (nodenumber)
480  !<
481  subroutine nodeu_to_string(this, nodeu, str)
482  ! -- dummy
483  class(disutype) :: this
484  integer(I4B), intent(in) :: nodeu
485  character(len=*), intent(inout) :: str
486  ! -- local
487  character(len=10) :: nstr
488  !
489  write (nstr, '(i0)') nodeu
490  str = '('//trim(adjustl(nstr))//')'
491  !
492  end subroutine nodeu_to_string
493 
494  !> @brief Convert a user nodenumber to an array (nodenumber)
495  !<
496  subroutine nodeu_to_array(this, nodeu, arr)
497  class(disutype) :: this
498  integer(I4B), intent(in) :: nodeu
499  integer(I4B), dimension(:), intent(inout) :: arr
500  ! -- local
501  integer(I4B) :: isize
502  !
503  ! -- check the size of arr
504  isize = size(arr)
505  if (isize /= this%ndim) then
506  write (errmsg, '(a,i0,a,i0,a)') &
507  'Program error: nodeu_to_array size of array (', isize, &
508  ') is not equal to the discretization dimension (', this%ndim, ')'
509  call store_error(errmsg, terminate=.true.)
510  end if
511  !
512  ! -- fill array
513  arr(1) = nodeu
514  !
515  end subroutine nodeu_to_array
516 
517  !> @brief Copy options from IDM into package
518  !<
519  subroutine source_options(this)
520  ! -- dummy
521  class(disutype) :: this
522  ! -- locals
523  character(len=LENVARNAME), dimension(3) :: lenunits = &
524  &[character(len=LENVARNAME) :: 'FEET', 'METERS', 'CENTIMETERS']
525  type(disufoundtype) :: found
526  !
527  ! -- update defaults with idm sourced values
528  call mem_set_value(this%lenuni, 'LENGTH_UNITS', this%input_mempath, &
529  lenunits, found%length_units)
530  call mem_set_value(this%nogrb, 'NOGRB', this%input_mempath, found%nogrb)
531  call mem_set_value(this%xorigin, 'XORIGIN', this%input_mempath, found%xorigin)
532  call mem_set_value(this%yorigin, 'YORIGIN', this%input_mempath, found%yorigin)
533  call mem_set_value(this%angrot, 'ANGROT', this%input_mempath, found%angrot)
534  call mem_set_value(this%voffsettol, 'VOFFSETTOL', this%input_mempath, &
535  found%voffsettol)
536  !
537  ! -- log values to list file
538  if (this%iout > 0) then
539  call this%log_options(found)
540  end if
541  !
542  end subroutine source_options
543 
544  !> @brief Write user options to list file
545  !<
546  subroutine log_options(this, found)
547  ! -- dummy
548  class(disutype) :: this
549  type(disufoundtype), intent(in) :: found
550  !
551  write (this%iout, '(1x,a)') 'Setting Discretization Options'
552  !
553  if (found%length_units) then
554  write (this%iout, '(4x,a,i0)') 'Model length unit [0=UND, 1=FEET, &
555  &2=METERS, 3=CENTIMETERS] set as ', this%lenuni
556  end if
557  !
558  if (found%nogrb) then
559  write (this%iout, '(4x,a,i0)') 'Binary grid file [0=GRB, 1=NOGRB] &
560  &set as ', this%nogrb
561  end if
562  !
563  if (found%xorigin) then
564  write (this%iout, '(4x,a,G0)') 'XORIGIN = ', this%xorigin
565  end if
566  !
567  if (found%yorigin) then
568  write (this%iout, '(4x,a,G0)') 'YORIGIN = ', this%yorigin
569  end if
570  !
571  if (found%angrot) then
572  write (this%iout, '(4x,a,G0)') 'ANGROT = ', this%angrot
573  end if
574  !
575  if (found%voffsettol) then
576  write (this%iout, '(4x,a,G0)') 'VERTICAL_OFFSET_TOLERANCE = ', &
577  this%voffsettol
578  end if
579  !
580  write (this%iout, '(1x,a,/)') 'End Setting Discretization Options'
581  !
582  end subroutine log_options
583 
584  !> @brief Copy dimensions from IDM into package
585  !<
586  subroutine source_dimensions(this)
587  ! -- dummy
588  class(disutype) :: this
589  ! -- locals
590  integer(I4B) :: n
591  type(disufoundtype) :: found
592  !
593  ! -- update defaults with idm sourced values
594  call mem_set_value(this%nodesuser, 'NODES', this%input_mempath, found%nodes)
595  call mem_set_value(this%njausr, 'NJA', this%input_mempath, found%nja)
596  call mem_set_value(this%nvert, 'NVERT', this%input_mempath, found%nvert)
597  !
598  ! -- log simulation values
599  if (this%iout > 0) then
600  call this%log_dimensions(found)
601  end if
602  !
603  ! -- verify dimensions were set
604  if (this%nodesuser < 1) then
605  call store_error( &
606  'NODES was not specified or was specified incorrectly.')
607  end if
608  if (this%njausr < 1) then
609  call store_error( &
610  'NJA was not specified or was specified incorrectly.')
611  end if
612  !
613  ! -- terminate if errors were detected
614  if (count_errors() > 0) then
615  call store_error_filename(this%input_fname)
616  end if
617  !
618  ! -- allocate vectors that are the size of nodesuser
619  this%readFromFile = .true.
620  call mem_allocate(this%top1d, this%nodesuser, 'TOP1D', this%memoryPath)
621  call mem_allocate(this%bot1d, this%nodesuser, 'BOT1D', this%memoryPath)
622  call mem_allocate(this%area1d, this%nodesuser, 'AREA1D', this%memoryPath)
623  call mem_allocate(this%idomain, this%nodesuser, 'IDOMAIN', this%memoryPath)
624  call mem_allocate(this%vertices, 2, this%nvert, 'VERTICES', this%memoryPath)
625  call mem_allocate(this%iainp, this%nodesuser + 1, 'IAINP', this%memoryPath)
626  call mem_allocate(this%jainp, this%njausr, 'JAINP', this%memoryPath)
627  call mem_allocate(this%ihcinp, this%njausr, 'IHCINP', this%memoryPath)
628  call mem_allocate(this%cl12inp, this%njausr, 'CL12INP', this%memoryPath)
629  call mem_allocate(this%hwvainp, this%njausr, 'HWVAINP', this%memoryPath)
630  call mem_allocate(this%angldegxinp, this%njausr, 'ANGLDEGXINP', &
631  this%memoryPath)
632  if (this%nvert > 0) then
633  call mem_allocate(this%cellxy, 2, this%nodesuser, 'CELLXY', this%memoryPath)
634  else
635  call mem_allocate(this%cellxy, 2, 0, 'CELLXY', this%memoryPath)
636  end if
637  !
638  ! -- initialize all cells to be active (idomain = 1)
639  do n = 1, this%nodesuser
640  this%idomain(n) = 1
641  end do
642  !
643  end subroutine source_dimensions
644 
645  !> @brief Write dimensions to list file
646  !<
647  subroutine log_dimensions(this, found)
648  class(disutype) :: this
649  type(disufoundtype), intent(in) :: found
650  !
651  write (this%iout, '(1x,a)') 'Setting Discretization Dimensions'
652  !
653  if (found%nodes) then
654  write (this%iout, '(4x,a,i0)') 'NODES = ', this%nodesuser
655  end if
656  !
657  if (found%nja) then
658  write (this%iout, '(4x,a,i0)') 'NJA = ', this%njausr
659  end if
660  !
661  if (found%nvert) then
662  write (this%iout, '(4x,a,i0)') 'NVERT = ', this%nvert
663  end if
664  !
665  write (this%iout, '(1x,a,/)') 'End Setting Discretization Dimensions'
666  !
667  end subroutine log_dimensions
668 
669  !> @brief Copy grid data from IDM into package
670  !<
671  subroutine source_griddata(this)
672  ! -- dummy
673  class(disutype) :: this
674  ! -- locals
675  type(disufoundtype) :: found
676  !
677  ! -- update defaults with idm sourced values
678  call mem_set_value(this%top1d, 'TOP', this%input_mempath, found%top)
679  call mem_set_value(this%bot1d, 'BOT', this%input_mempath, found%bot)
680  call mem_set_value(this%area1d, 'AREA', this%input_mempath, found%area)
681  call mem_set_value(this%idomain, 'IDOMAIN', this%input_mempath, found%idomain)
682  !
683  ! -- log simulation values
684  if (this%iout > 0) then
685  call this%log_griddata(found)
686  end if
687  !
688  end subroutine source_griddata
689 
690  !> @brief Write griddata found to list file
691  !<
692  subroutine log_griddata(this, found)
693  ! -- dummy
694  class(disutype) :: this
695  type(disufoundtype), intent(in) :: found
696  !
697  write (this%iout, '(1x,a)') 'Setting Discretization Griddata'
698  !
699  if (found%top) then
700  write (this%iout, '(4x,a)') 'TOP set from input file'
701  end if
702  !
703  if (found%bot) then
704  write (this%iout, '(4x,a)') 'BOT set from input file'
705  end if
706  !
707  if (found%area) then
708  write (this%iout, '(4x,a)') 'AREA set from input file'
709  end if
710  !
711  if (found%idomain) then
712  write (this%iout, '(4x,a)') 'IDOMAIN set from input file'
713  end if
714  !
715  write (this%iout, '(1x,a,/)') 'End Setting Discretization Griddata'
716  !
717  end subroutine log_griddata
718 
719  !> @brief Copy grid connectivity info from IDM into package
720  !<
721  subroutine source_connectivity(this)
722  ! -- dummy
723  class(disutype) :: this
724  ! -- locals
725  type(disufoundtype) :: found
726  integer(I4B), dimension(:), contiguous, pointer :: iac => null()
727  ! -- formats
728  !
729  ! -- update defaults with idm sourced values
730  call mem_set_value(this%jainp, 'JA', this%input_mempath, found%ja)
731  call mem_set_value(this%ihcinp, 'IHC', this%input_mempath, found%ihc)
732  call mem_set_value(this%cl12inp, 'CL12', this%input_mempath, found%cl12)
733  call mem_set_value(this%hwvainp, 'HWVA', this%input_mempath, found%hwva)
734  call mem_set_value(this%angldegxinp, 'ANGLDEGX', this%input_mempath, &
735  found%angldegx)
736  !
737  ! -- set pointer to iac input array
738  call mem_setptr(iac, 'IAC', this%input_mempath)
739  !
740  ! -- Convert iac to ia
741  if (associated(iac)) call iac_to_ia(iac, this%iainp)
742  !
743  ! -- Set angldegx flag if found
744  if (found%angldegx) this%iangledegx = 1
745  !
746  ! -- log simulation values
747  if (this%iout > 0) then
748  call this%log_connectivity(found, iac)
749  end if
750  !
751  end subroutine source_connectivity
752 
753  !> @brief Write griddata found to list file
754  !<
755  subroutine log_connectivity(this, found, iac)
756  class(disutype) :: this
757  type(disufoundtype), intent(in) :: found
758  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: iac
759  !
760  write (this%iout, '(1x,a)') 'Setting Discretization Connectivity'
761  !
762  if (associated(iac)) then
763  write (this%iout, '(4x,a)') 'IAC set from input file'
764  end if
765  !
766  if (found%ja) then
767  write (this%iout, '(4x,a)') 'JA set from input file'
768  end if
769  !
770  if (found%ihc) then
771  write (this%iout, '(4x,a)') 'IHC set from input file'
772  end if
773  !
774  if (found%cl12) then
775  write (this%iout, '(4x,a)') 'CL12 set from input file'
776  end if
777  !
778  if (found%hwva) then
779  write (this%iout, '(4x,a)') 'HWVA set from input file'
780  end if
781  !
782  if (found%angldegx) then
783  write (this%iout, '(4x,a)') 'ANGLDEGX set from input file'
784  end if
785  !
786  write (this%iout, '(1x,a,/)') 'End Setting Discretization Connectivity'
787  !
788  end subroutine log_connectivity
789 
790  !> @brief Copy grid vertex data from IDM into package
791  !<
792  subroutine source_vertices(this)
793  ! -- dummy
794  class(disutype) :: this
795  ! -- local
796  integer(I4B) :: i
797  real(DP), dimension(:), contiguous, pointer :: vert_x => null()
798  real(DP), dimension(:), contiguous, pointer :: vert_y => null()
799  ! -- formats
800  !
801  ! -- set pointers to memory manager input arrays
802  call mem_setptr(vert_x, 'XV', this%input_mempath)
803  call mem_setptr(vert_y, 'YV', this%input_mempath)
804  !
805  ! -- set vertices 2d array
806  if (associated(vert_x) .and. associated(vert_y)) then
807  do i = 1, this%nvert
808  this%vertices(1, i) = vert_x(i)
809  this%vertices(2, i) = vert_y(i)
810  end do
811  else
812  call store_error('Required Vertex arrays not found.')
813  end if
814  !
815  ! -- log
816  if (this%iout > 0) then
817  write (this%iout, '(1x,a)') 'Discretization Vertex data loaded'
818  end if
819  !
820  call memorystore_release('XV', this%input_mempath)
821  call memorystore_release('YV', this%input_mempath)
822  end subroutine source_vertices
823 
824  !> @brief Build data structures to hold cell vertex info
825  !<
826  subroutine define_cellverts(this, icell2d, ncvert, icvert)
827  ! -- modules
828  use sparsemodule, only: sparsematrix
829  ! -- dummy
830  class(disutype) :: this
831  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: icell2d
832  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: ncvert
833  integer(I4B), dimension(:), contiguous, pointer, intent(in) :: icvert
834  ! -- locals
835  type(sparsematrix) :: vert_spm
836  integer(I4B) :: i, j, ierr
837  integer(I4B) :: icv_idx, startvert, maxnnz = 5
838  !
839  ! -- initialize sparse matrix
840  call vert_spm%init(this%nodesuser, this%nvert, maxnnz)
841  !
842  ! -- add sparse matrix connections from input memory paths
843  icv_idx = 1
844  do i = 1, this%nodesuser
845  if (icell2d(i) /= i) call store_error('ICELL2D input sequence violation.')
846  do j = 1, ncvert(i)
847  call vert_spm%addconnection(i, icvert(icv_idx), 0)
848  if (j == 1) then
849  startvert = icvert(icv_idx)
850  elseif (j == ncvert(i) .and. (icvert(icv_idx) /= startvert)) then
851  call vert_spm%addconnection(i, startvert, 0)
852  end if
853  icv_idx = icv_idx + 1
854  end do
855  end do
856  !
857  ! -- allocate and fill iavert and javert
858  call mem_allocate(this%iavert, this%nodesuser + 1, 'IAVERT', this%memoryPath)
859  call mem_allocate(this%javert, vert_spm%nnz, 'JAVERT', this%memoryPath)
860  call vert_spm%filliaja(this%iavert, this%javert, ierr)
861  call vert_spm%destroy()
862  !
863  end subroutine define_cellverts
864 
865  !> @brief Copy cell2d data from IDM into package
866  !<
867  subroutine source_cell2d(this)
868  ! -- dummy
869  class(disutype) :: this
870  ! -- locals
871  integer(I4B), dimension(:), contiguous, pointer :: icell2d => null()
872  integer(I4B), dimension(:), contiguous, pointer :: ncvert => null()
873  integer(I4B), dimension(:), contiguous, pointer :: icvert => null()
874  real(DP), dimension(:), contiguous, pointer :: cell_x => null()
875  real(DP), dimension(:), contiguous, pointer :: cell_y => null()
876  integer(I4B) :: i
877  !
878  ! -- set pointers to input path ncvert and icvert
879  call mem_setptr(icell2d, 'ICELL2D', this%input_mempath)
880  call mem_setptr(ncvert, 'NCVERT', this%input_mempath)
881  call mem_setptr(icvert, 'ICVERT', this%input_mempath)
882  !
883  ! --
884  if (associated(icell2d) .and. associated(ncvert) &
885  .and. associated(icvert)) then
886  call this%define_cellverts(icell2d, ncvert, icvert)
887  else
888  call store_error('Required cell vertex arrays not found.')
889  end if
890  !
891  ! -- set pointers to cell center arrays
892  call mem_setptr(cell_x, 'XC', this%input_mempath)
893  call mem_setptr(cell_y, 'YC', this%input_mempath)
894  !
895  ! -- set cell centers
896  if (associated(cell_x) .and. associated(cell_y)) then
897  do i = 1, this%nodesuser
898  this%cellxy(1, i) = cell_x(i)
899  this%cellxy(2, i) = cell_y(i)
900  end do
901  else
902  call store_error('Required cell center arrays not found.')
903  end if
904  !
905  ! -- log
906  if (this%iout > 0) then
907  write (this%iout, '(1x,a)') 'Discretization Cell2d data loaded'
908  end if
909  !
910  call memorystore_release('ICELL2D', this%input_mempath)
911  call memorystore_release('NCVERT', this%input_mempath)
912  call memorystore_release('ICVERT', this%input_mempath)
913  call memorystore_release('XC', this%input_mempath)
914  call memorystore_release('YC', this%input_mempath)
915  end subroutine source_cell2d
916 
917  !> @brief Write a binary grid file
918  !<
919  subroutine write_grb(this, icelltype)
920  ! -- modules
921  use openspecmodule, only: access, form
922  use constantsmodule, only: lenbigline
923  ! -- dummy
924  class(disutype) :: this
925  integer(I4B), dimension(:), intent(in) :: icelltype
926  ! -- local
927  integer(I4B) :: i, iunit, ntxt, version
928  integer(I4B), parameter :: lentxt = 100
929  character(len=50) :: txthdr
930  character(len=lentxt) :: txt
931  character(len=LINELENGTH) :: fname
932  character(len=LENBIGLINE) :: crs
933  logical(LGP) :: found_crs
934  ! -- formats
935  character(len=*), parameter :: fmtgrdsave = &
936  "(4X,'BINARY GRID INFORMATION WILL BE WRITTEN TO:', &
937  &/,6X,'UNIT NUMBER: ', I0,/,6X, 'FILE NAME: ', A)"
938  !
939  ! -- Initialize
940  version = 1
941  ntxt = 11
942  if (this%nvert > 0) ntxt = ntxt + 5
943  !
944  call mem_set_value(crs, 'CRS', this%input_mempath, found_crs)
945  !
946  ! -- set version
947  if (found_crs) then
948  ntxt = ntxt + 1
949  version = 2
950  end if
951  !
952  ! -- Open the file
953  fname = trim(this%output_fname)
954  iunit = getunit()
955  write (this%iout, fmtgrdsave) iunit, trim(adjustl(fname))
956  call openfile(iunit, this%iout, trim(adjustl(fname)), 'DATA(BINARY)', &
957  form, access, 'REPLACE')
958  !
959  ! -- write header information
960  write (txthdr, '(a)') 'GRID DISU'
961  txthdr(50:50) = new_line('a')
962  write (iunit) txthdr
963  write (txthdr, '(a, i0)') 'VERSION ', version
964  txthdr(50:50) = new_line('a')
965  write (iunit) txthdr
966  write (txthdr, '(a, i0)') 'NTXT ', ntxt
967  txthdr(50:50) = new_line('a')
968  write (iunit) txthdr
969  write (txthdr, '(a, i0)') 'LENTXT ', lentxt
970  txthdr(50:50) = new_line('a')
971  write (iunit) txthdr
972  !
973  ! -- write variable definitions
974  write (txt, '(3a, i0)') 'NODES ', 'INTEGER ', 'NDIM 0 # ', this%nodesuser
975  txt(lentxt:lentxt) = new_line('a')
976  write (iunit) txt
977  write (txt, '(3a, i0)') 'NJA ', 'INTEGER ', 'NDIM 0 # ', this%con%nja
978  txt(lentxt:lentxt) = new_line('a')
979  write (iunit) txt
980  write (txt, '(3a, 1pg24.15)') 'XORIGIN ', 'DOUBLE ', 'NDIM 0 # ', this%xorigin
981  txt(lentxt:lentxt) = new_line('a')
982  write (iunit) txt
983  write (txt, '(3a, 1pg24.15)') 'YORIGIN ', 'DOUBLE ', 'NDIM 0 # ', this%yorigin
984  txt(lentxt:lentxt) = new_line('a')
985  write (iunit) txt
986  write (txt, '(3a, 1pg24.15)') 'ANGROT ', 'DOUBLE ', 'NDIM 0 # ', this%angrot
987  txt(lentxt:lentxt) = new_line('a')
988  write (iunit) txt
989  write (txt, '(3a, i0)') 'TOP ', 'DOUBLE ', 'NDIM 1 ', this%nodesuser
990  txt(lentxt:lentxt) = new_line('a')
991  write (iunit) txt
992  write (txt, '(3a, i0)') 'BOT ', 'DOUBLE ', 'NDIM 1 ', this%nodesuser
993  txt(lentxt:lentxt) = new_line('a')
994  write (iunit) txt
995  write (txt, '(3a, i0)') 'IA ', 'INTEGER ', 'NDIM 1 ', this%nodesuser + 1
996  txt(lentxt:lentxt) = new_line('a')
997  write (iunit) txt
998  write (txt, '(3a, i0)') 'JA ', 'INTEGER ', 'NDIM 1 ', this%con%nja
999  txt(lentxt:lentxt) = new_line('a')
1000  write (iunit) txt
1001  write (txt, '(3a, i0)') 'IDOMAIN ', 'INTEGER ', 'NDIM 1 ', this%nodesuser
1002  txt(lentxt:lentxt) = new_line('a')
1003  write (iunit) txt
1004  write (txt, '(3a, i0)') 'ICELLTYPE ', 'INTEGER ', 'NDIM 1 ', this%nodesuser
1005  txt(lentxt:lentxt) = new_line('a')
1006  write (iunit) txt
1007  !
1008  ! -- if vertices have been read then write additional header information
1009  if (this%nvert > 0) then
1010  write (txt, '(3a, i0)') 'VERTICES ', 'DOUBLE ', 'NDIM 2 2 ', this%nvert
1011  txt(lentxt:lentxt) = new_line('a')
1012  write (iunit) txt
1013  write (txt, '(3a, i0)') 'CELLX ', 'DOUBLE ', 'NDIM 1 ', this%nodesuser
1014  txt(lentxt:lentxt) = new_line('a')
1015  write (iunit) txt
1016  write (txt, '(3a, i0)') 'CELLY ', 'DOUBLE ', 'NDIM 1 ', this%nodesuser
1017  txt(lentxt:lentxt) = new_line('a')
1018  write (iunit) txt
1019  write (txt, '(3a, i0)') 'IAVERT ', 'INTEGER ', 'NDIM 1 ', this%nodesuser + 1
1020  txt(lentxt:lentxt) = new_line('a')
1021  write (iunit) txt
1022  write (txt, '(3a, i0)') 'JAVERT ', 'INTEGER ', 'NDIM 1 ', size(this%javert)
1023  txt(lentxt:lentxt) = new_line('a')
1024  write (iunit) txt
1025  end if
1026  !
1027  ! -- if version 2 write character array headers
1028  if (version == 2) then
1029  if (found_crs) then
1030  write (txt, '(3a, i0)') 'CRS ', 'CHARACTER ', 'NDIM 1 ', &
1031  len_trim(crs)
1032  txt(lentxt:lentxt) = new_line('a')
1033  write (iunit) txt
1034  end if
1035  end if
1036  !
1037  ! -- write data
1038  write (iunit) this%nodesuser ! nodes
1039  write (iunit) this%nja ! nja
1040  write (iunit) this%xorigin ! xorigin
1041  write (iunit) this%yorigin ! yorigin
1042  write (iunit) this%angrot ! angrot
1043  write (iunit) this%top1d ! top
1044  write (iunit) this%bot1d ! bot
1045  write (iunit) this%con%iausr ! ia
1046  write (iunit) this%con%jausr ! ja
1047  write (iunit) this%idomain ! idomain
1048  write (iunit) icelltype ! icelltype
1049  !
1050  ! -- if vertices have been read then write additional data
1051  if (this%nvert > 0) then
1052  write (iunit) this%vertices ! vertices
1053  write (iunit) (this%cellxy(1, i), i=1, this%nodesuser) ! cellx
1054  write (iunit) (this%cellxy(2, i), i=1, this%nodesuser) ! celly
1055  write (iunit) this%iavert ! iavert
1056  write (iunit) this%javert ! javert
1057  end if
1058  !
1059  ! -- if version 2 write character array data
1060  if (version == 2) then
1061  if (found_crs) write (iunit) trim(crs) ! crs user input
1062  end if
1063  !
1064  ! -- Close the file
1065  close (iunit)
1066  !
1067  end subroutine write_grb
1068 
1069  !> @brief Get reduced node number from user node number
1070  !<
1071  function get_nodenumber_idx1(this, nodeu, icheck) result(nodenumber)
1072  class(disutype), intent(in) :: this
1073  integer(I4B), intent(in) :: nodeu
1074  integer(I4B), intent(in) :: icheck
1075  integer(I4B) :: nodenumber
1076  !
1077  if (icheck /= 0) then
1078  if (nodeu < 1 .or. nodeu > this%nodesuser) then
1079  write (errmsg, '(a,i0,a,i0,a)') &
1080  'Node number (', nodeu, ') is less than 1 or greater than nodes (', &
1081  this%nodesuser, ').'
1082  call store_error(errmsg)
1083  end if
1084  end if
1085  !
1086  ! -- set node number to passed in nodenumber since there is a one to one
1087  ! mapping for an unstructured grid
1088  if (this%nodes == this%nodesuser) then
1089  nodenumber = nodeu
1090  else
1091  nodenumber = this%nodereduced(nodeu)
1092  end if
1093  !
1094  end function get_nodenumber_idx1
1095 
1096  !> @brief Get normal vector components between the cell and a given neighbor
1097  !!
1098  !! The normal points outward from the shared face between noden and nodem.
1099  !<
1100  subroutine connection_normal(this, noden, nodem, ihc, xcomp, ycomp, zcomp, &
1101  ipos)
1102  ! -- dummy
1103  class(disutype) :: this
1104  integer(I4B), intent(in) :: noden !< cell (reduced nn)
1105  integer(I4B), intent(in) :: nodem !< neighbor (reduced nn)
1106  integer(I4B), intent(in) :: ihc !< horizontal connection flag
1107  real(DP), intent(inout) :: xcomp
1108  real(DP), intent(inout) :: ycomp
1109  real(DP), intent(inout) :: zcomp
1110  integer(I4B), intent(in) :: ipos
1111  ! -- local
1112  real(DP) :: angle, dmult
1113  !
1114  ! -- Set vector components based on ihc
1115  if (ihc == 0) then
1116  !
1117  ! -- connection is vertical
1118  xcomp = dzero
1119  ycomp = dzero
1120  if (nodem < noden) then
1121  !
1122  ! -- nodem must be above noden, so upward connection
1123  zcomp = done
1124  else
1125  !
1126  ! -- nodem must be below noden, so downward connection
1127  zcomp = -done
1128  end if
1129  else
1130  ! -- find from anglex, since anglex is symmetric, need to flip vector
1131  ! for lower triangle (nodem < noden)
1132  angle = this%con%anglex(this%con%jas(ipos))
1133  dmult = done
1134  if (nodem < noden) dmult = -done
1135  xcomp = cos(angle) * dmult
1136  ycomp = sin(angle) * dmult
1137  zcomp = dzero
1138  end if
1139  !
1140  end subroutine connection_normal
1141 
1142  !> @brief Get unit vector components between the cell and a given neighbor
1143  !!
1144  !! Saturation must be provided to compute cell center vertical coordinates.
1145  !! Also return the straight-line connection length.
1146  !<
1147  subroutine connection_vector(this, noden, nodem, nozee, satn, satm, ihc, &
1148  xcomp, ycomp, zcomp, conlen)
1149  ! -- dummy
1150  class(disutype) :: this
1151  integer(I4B), intent(in) :: noden
1152  integer(I4B), intent(in) :: nodem
1153  logical, intent(in) :: nozee
1154  real(DP), intent(in) :: satn
1155  real(DP), intent(in) :: satm
1156  integer(I4B), intent(in) :: ihc
1157  real(DP), intent(inout) :: xcomp
1158  real(DP), intent(inout) :: ycomp
1159  real(DP), intent(inout) :: zcomp
1160  real(DP), intent(inout) :: conlen
1161  ! -- local
1162  real(DP) :: xn, xm, yn, ym, zn, zm
1163  !
1164  ! -- Terminate with error if requesting unit vector components for problems
1165  ! without cell data
1166  if (size(this%cellxy, 2) < 1) then
1167  write (errmsg, '(a)') &
1168  'Cannot calculate unit vector components for DISU grid if VERTEX '// &
1169  'data are not specified'
1170  call store_error(errmsg, terminate=.true.)
1171  end if
1172  !
1173  ! -- get xy center coords
1174  xn = this%xc(noden)
1175  yn = this%yc(noden)
1176  xm = this%xc(nodem)
1177  ym = this%yc(nodem)
1178  !
1179  ! -- Set vector components based on ihc
1180  if (ihc == 0) then
1181  !
1182  ! -- vertical connection, calculate z as cell center elevation
1183  zn = this%bot(noden) + dhalf * (this%top(noden) - this%bot(noden))
1184  zm = this%bot(nodem) + dhalf * (this%top(nodem) - this%bot(nodem))
1185  else
1186  !
1187  ! -- horizontal connection, with possible z component due to cell offsets
1188  ! and/or water table conditions
1189  if (nozee) then
1190  zn = dzero
1191  zm = dzero
1192  else
1193  zn = this%bot(noden) + dhalf * satn * (this%top(noden) - this%bot(noden))
1194  zm = this%bot(nodem) + dhalf * satm * (this%top(nodem) - this%bot(nodem))
1195  end if
1196  end if
1197  !
1198  ! -- Use coords to find vector components and connection length
1199  call line_unit_vector(xn, yn, zn, xm, ym, zm, xcomp, ycomp, zcomp, &
1200  conlen)
1201  !
1202  end subroutine connection_vector
1203 
1204  !> @brief Get the discretization type
1205  !<
1206  subroutine get_dis_type(this, dis_type)
1207  ! -- dummy
1208  class(disutype), intent(in) :: this
1209  character(len=*), intent(out) :: dis_type
1210  !
1211  dis_type = "DISU"
1212  !
1213  end subroutine get_dis_type
1214 
1215  !> @brief Get the discretization type enumeration
1216  function get_dis_enum(this) result(dis_enum)
1217  use constantsmodule, only: disu
1218  class(disutype), intent(in) :: this
1219  integer(I4B) :: dis_enum
1220  dis_enum = disu
1221  end function get_dis_enum
1222 
1223  !> @brief Allocate and initialize scalar variables
1224  !<
1225  subroutine allocate_scalars(this, name_model, input_mempath)
1226  ! -- dummy
1227  class(disutype) :: this
1228  character(len=*), intent(in) :: name_model
1229  character(len=*), intent(in) :: input_mempath
1230  !
1231  ! -- Allocate parent scalars
1232  call this%DisBaseType%allocate_scalars(name_model, input_mempath)
1233  !
1234  ! -- Allocate variables for DISU
1235  call mem_allocate(this%njausr, 'NJAUSR', this%memoryPath)
1236  call mem_allocate(this%nvert, 'NVERT', this%memoryPath)
1237  call mem_allocate(this%voffsettol, 'VOFFSETTOL', this%memoryPath)
1238  call mem_allocate(this%iangledegx, 'IANGLEDEGX', this%memoryPath)
1239  !
1240  ! -- Set values
1241  this%ndim = 1
1242  this%njausr = 0
1243  this%nvert = 0
1244  this%voffsettol = dzero
1245  this%iangledegx = 0
1246  this%readFromFile = .false.
1247  !
1248  end subroutine allocate_scalars
1249 
1250  !> @brief Allocate and initialize arrays
1251  !<
1252  subroutine allocate_arrays(this)
1253  ! -- dummy
1254  class(disutype) :: this
1255  !
1256  ! -- Allocate arrays in DisBaseType (mshape, top, bot, area)
1257  call this%DisBaseType%allocate_arrays()
1258  !
1259  ! -- Allocate arrays in DISU
1260  if (this%nodes < this%nodesuser) then
1261  call mem_allocate(this%nodeuser, this%nodes, 'NODEUSER', this%memoryPath)
1262  call mem_allocate(this%nodereduced, this%nodesuser, 'NODEREDUCED', &
1263  this%memoryPath)
1264  else
1265  call mem_allocate(this%nodeuser, 1, 'NODEUSER', this%memoryPath)
1266  call mem_allocate(this%nodereduced, 1, 'NODEREDUCED', this%memoryPath)
1267  end if
1268  !
1269  ! -- Initialize
1270  this%mshape(1) = this%nodesuser
1271  !
1272  end subroutine allocate_arrays
1273 
1274  !> @brief Allocate arrays in memory manager
1275  !<
1276  subroutine allocate_arrays_mem(this)
1277  ! -- modules
1279  ! -- dummy
1280  class(disutype) :: this
1281  !
1282  call mem_allocate(this%idomain, this%nodes, 'IDOMAIN', this%memoryPath)
1283  call mem_allocate(this%vertices, 2, this%nvert, 'VERTICES', this%memoryPath)
1284  if (this%icondir > 0) then
1285  call mem_allocate(this%cellxy, 2, this%nodes, 'CELLXY', this%memoryPath)
1286  else
1287  call mem_allocate(this%cellxy, 2, 0, 'CELLXY', this%memoryPath)
1288  end if
1289  !
1290  end subroutine allocate_arrays_mem
1291 
1292  !> @brief Convert a string to a user nodenumber
1293  !!
1294  !! Parse and return user nodenumber.
1295  !! If flag_string is present and true, the first token may be
1296  !! non-numeric (e.g. boundary name). In this case, return -2.
1297  !<
1298  function nodeu_from_string(this, lloc, istart, istop, in, iout, line, &
1299  flag_string, allow_zero) result(nodeu)
1300  ! -- dummy
1301  class(disutype) :: this
1302  integer(I4B), intent(inout) :: lloc
1303  integer(I4B), intent(inout) :: istart
1304  integer(I4B), intent(inout) :: istop
1305  integer(I4B), intent(in) :: in
1306  integer(I4B), intent(in) :: iout
1307  character(len=*), intent(inout) :: line
1308  logical, optional, intent(in) :: flag_string
1309  logical, optional, intent(in) :: allow_zero
1310  integer(I4B) :: nodeu
1311  ! -- local
1312  integer(I4B) :: lloclocal, ndum, istat, n
1313  real(dp) :: r
1314  !
1315  if (present(flag_string)) then
1316  if (flag_string) then
1317  ! Check to see if first token in line can be read as an integer.
1318  lloclocal = lloc
1319  call urword(line, lloclocal, istart, istop, 1, ndum, r, iout, in)
1320  read (line(istart:istop), *, iostat=istat) n
1321  if (istat /= 0) then
1322  ! First token in line is not an integer; return flag to this effect.
1323  nodeu = -2
1324  return
1325  end if
1326  end if
1327  end if
1328  !
1329  call urword(line, lloc, istart, istop, 2, nodeu, r, iout, in)
1330  !
1331  if (nodeu == 0) then
1332  if (present(allow_zero)) then
1333  if (allow_zero) then
1334  return
1335  end if
1336  end if
1337  end if
1338  !
1339  if (nodeu < 1 .or. nodeu > this%nodesuser) then
1340  write (errmsg, '(a,i0,a)') &
1341  "Node number in list (", nodeu, ") is outside of the grid. "// &
1342  "Cell number cannot be determined in line '"// &
1343  trim(adjustl(line))//"'."
1344  call store_error(errmsg)
1345  call store_error_unit(in)
1346  end if
1347  !
1348  end function nodeu_from_string
1349 
1350  !> @brief Convert a cellid string to a user nodenumber
1351  !!
1352  !! If flag_string is present and true, the first token may be
1353  !! non-numeric (e.g. boundary name). In this case, return -2.
1354  !!
1355  !! If allow_zero is present and true, and all indices are zero, the
1356  !! result can be zero. If allow_zero is false, a zero in any index is an error.
1357  !<
1358  function nodeu_from_cellid(this, cellid, inunit, iout, flag_string, &
1359  allow_zero) result(nodeu)
1360  ! -- return
1361  integer(I4B) :: nodeu
1362  ! -- dummy
1363  class(disutype) :: this
1364  character(len=*), intent(inout) :: cellid
1365  integer(I4B), intent(in) :: inunit
1366  integer(I4B), intent(in) :: iout
1367  logical, optional, intent(in) :: flag_string
1368  logical, optional, intent(in) :: allow_zero
1369  ! -- local
1370  integer(I4B) :: lloclocal, istart, istop, ndum, n
1371  integer(I4B) :: istat
1372  real(dp) :: r
1373  !
1374  if (present(flag_string)) then
1375  if (flag_string) then
1376  ! Check to see if first token in cellid can be read as an integer.
1377  lloclocal = 1
1378  call urword(cellid, lloclocal, istart, istop, 1, ndum, r, iout, inunit)
1379  read (cellid(istart:istop), *, iostat=istat) n
1380  if (istat /= 0) then
1381  ! First token in cellid is not an integer; return flag to this effect.
1382  nodeu = -2
1383  return
1384  end if
1385  end if
1386  end if
1387  !
1388  lloclocal = 1
1389  call urword(cellid, lloclocal, istart, istop, 2, nodeu, r, iout, inunit)
1390  !
1391  if (nodeu == 0) then
1392  if (present(allow_zero)) then
1393  if (allow_zero) then
1394  return
1395  end if
1396  end if
1397  end if
1398  !
1399  if (nodeu < 1 .or. nodeu > this%nodesuser) then
1400  write (errmsg, '(a,i0,a)') &
1401  "Cell number cannot be determined for cellid ("// &
1402  trim(adjustl(cellid))//") and results in a user "// &
1403  "node number (", nodeu, ") that is outside of the grid."
1404  call store_error(errmsg)
1405  call store_error_unit(inunit)
1406  end if
1407  !
1408  end function nodeu_from_cellid
1409 
1410  !> @brief Indicates whether the grid discretization supports layers
1411  !<
1412  logical function supports_layers(this)
1413  ! -- dummy
1414  class(disutype) :: this
1415  !
1416  supports_layers = .false.
1417  !
1418  end function supports_layers
1419 
1420  !> @brief Get number of cells per layer (total nodes since DISU isn't layered)
1421  !<
1422  function get_ncpl(this)
1423  ! -- return
1424  integer(I4B) :: get_ncpl
1425  ! -- dummy
1426  class(disutype) :: this
1427  !
1428  get_ncpl = this%nodesuser
1429  !
1430  end function get_ncpl
1431 
1432  !> @brief Read an integer array
1433  !<
1434  subroutine read_int_array(this, line, lloc, istart, istop, iout, in, &
1435  iarray, aname)
1436  ! -- dummy
1437  class(disutype), intent(inout) :: this
1438  character(len=*), intent(inout) :: line
1439  integer(I4B), intent(inout) :: lloc
1440  integer(I4B), intent(inout) :: istart
1441  integer(I4B), intent(inout) :: istop
1442  integer(I4B), intent(in) :: in
1443  integer(I4B), intent(in) :: iout
1444  integer(I4B), dimension(:), pointer, contiguous, intent(inout) :: iarray
1445  character(len=*), intent(in) :: aname
1446  ! -- local
1447  integer(I4B) :: nval
1448  integer(I4B), dimension(:), pointer, contiguous :: itemp
1449  !
1450  ! -- Point the temporary pointer array, which is passed to the reading
1451  ! subroutine. The temporary array will point to ibuff if it is a
1452  ! reduced structured system, or to iarray if it is an unstructured
1453  ! model.
1454  if (this%nodes < this%nodesuser) then
1455  nval = this%nodesuser
1456  itemp => this%ibuff
1457  else
1458  nval = this%nodes
1459  itemp => iarray
1460  end if
1461  !
1462  ! -- Read the array
1463  ! -- Read unstructured input
1464  call readarray(in, itemp, aname, this%ndim, nval, iout, 0)
1465  !
1466  ! -- If reduced model, then need to copy from itemp(=>ibuff) to iarray
1467  if (this%nodes < this%nodesuser) then
1468  call this%fill_grid_array(itemp, iarray)
1469  end if
1470  !
1471  end subroutine read_int_array
1472 
1473  !> @brief Read a double precision array
1474  !<
1475  subroutine read_dbl_array(this, line, lloc, istart, istop, iout, in, &
1476  darray, aname)
1477  ! -- dummy
1478  class(disutype), intent(inout) :: this
1479  character(len=*), intent(inout) :: line
1480  integer(I4B), intent(inout) :: lloc
1481  integer(I4B), intent(inout) :: istart
1482  integer(I4B), intent(inout) :: istop
1483  integer(I4B), intent(in) :: in
1484  integer(I4B), intent(in) :: iout
1485  real(DP), dimension(:), pointer, contiguous, intent(inout) :: darray
1486  character(len=*), intent(in) :: aname
1487  ! -- local
1488  integer(I4B) :: nval
1489  real(DP), dimension(:), pointer, contiguous :: dtemp
1490  !
1491  ! -- Point the temporary pointer array, which is passed to the reading
1492  ! subroutine. The temporary array will point to dbuff if it is a
1493  ! reduced structured system, or to darray if it is an unstructured
1494  ! model.
1495  if (this%nodes < this%nodesuser) then
1496  nval = this%nodesuser
1497  dtemp => this%dbuff
1498  else
1499  nval = this%nodes
1500  dtemp => darray
1501  end if
1502  !
1503  ! -- Read the array
1504  call readarray(in, dtemp, aname, this%ndim, nval, iout, 0)
1505  !
1506  ! -- If reduced model, then need to copy from dtemp(=>dbuff) to darray
1507  if (this%nodes < this%nodesuser) then
1508  call this%fill_grid_array(dtemp, darray)
1509  end if
1510  !
1511  end subroutine read_dbl_array
1512 
1513  !> @brief Record a double precision array
1514  !!
1515  !! The array is written to a formatted or unformatted external file
1516  !! depending on the arguments.
1517  !<
1518  subroutine record_array(this, darray, iout, iprint, idataun, aname, &
1519  cdatafmp, nvaluesp, nwidthp, editdesc, dinact)
1520  ! -- dummy
1521  class(disutype), intent(inout) :: this
1522  real(DP), dimension(:), pointer, contiguous, intent(inout) :: darray !< double precision array to record
1523  integer(I4B), intent(in) :: iout !< ascii output unit number
1524  integer(I4B), intent(in) :: iprint !< whether to print the array
1525  integer(I4B), intent(in) :: idataun !< binary output unit number
1526  character(len=*), intent(in) :: aname !< text descriptor
1527  character(len=*), intent(in) :: cdatafmp ! write format
1528  integer(I4B), intent(in) :: nvaluesp !< values per line
1529  integer(I4B), intent(in) :: nwidthp !< number width
1530  character(len=*), intent(in) :: editdesc !< format type (I, G, F, S, E)
1531  real(DP), intent(in) :: dinact !< double precision value for cells excluded from model domain
1532  ! -- local
1533  integer(I4B) :: k, ifirst
1534  integer(I4B) :: nlay
1535  integer(I4B) :: nrow
1536  integer(I4B) :: ncol
1537  integer(I4B) :: nval
1538  integer(I4B) :: nodeu, noder
1539  integer(I4B) :: istart, istop
1540  real(DP), dimension(:), pointer, contiguous :: dtemp
1541  ! -- formats
1542  character(len=*), parameter :: fmthsv = &
1543  "(1X,/1X,a,' WILL BE SAVED ON UNIT ',I4, &
1544  &' AT END OF TIME STEP',I5,', STRESS PERIOD ',I4)"
1545  !
1546  ! -- set variables
1547  nlay = 1
1548  nrow = 1
1549  ncol = this%mshape(1)
1550  !
1551  ! -- If this is a reduced model, then copy the values from darray into
1552  ! dtemp.
1553  if (this%nodes < this%nodesuser) then
1554  nval = this%nodes
1555  dtemp => this%dbuff
1556  do nodeu = 1, this%nodesuser
1557  noder = this%get_nodenumber(nodeu, 0)
1558  if (noder <= 0) then
1559  dtemp(nodeu) = dinact
1560  cycle
1561  end if
1562  dtemp(nodeu) = darray(noder)
1563  end do
1564  else
1565  nval = this%nodes
1566  dtemp => darray
1567  end if
1568  !
1569  ! -- Print to iout if iprint /= 0
1570  if (iprint /= 0) then
1571  istart = 1
1572  do k = 1, nlay
1573  istop = istart + nrow * ncol - 1
1574  call ulaprufw(ncol, nrow, kstp, kper, k, iout, dtemp(istart:istop), &
1575  aname, cdatafmp, nvaluesp, nwidthp, editdesc)
1576  istart = istop + 1
1577  end do
1578  end if
1579  !
1580  ! -- Save array to an external file.
1581  if (idataun > 0) then
1582  ! -- write to binary file by layer
1583  ifirst = 1
1584  istart = 1
1585  do k = 1, nlay
1586  istop = istart + nrow * ncol - 1
1587  if (ifirst == 1) write (iout, fmthsv) &
1588  trim(adjustl(aname)), idataun, &
1589  kstp, kper
1590  ifirst = 0
1591  call ulasav(dtemp(istart:istop), aname, kstp, kper, &
1592  pertim, totim, ncol, nrow, k, idataun)
1593  istart = istop + 1
1594  end do
1595  elseif (idataun < 0) then
1596  !
1597  ! -- write entire array as one record
1598  call ubdsv1(kstp, kper, aname, -idataun, dtemp, ncol, nrow, nlay, &
1599  iout, delt, pertim, totim)
1600  end if
1601  !
1602  end subroutine record_array
1603 
1604  !> @brief Record list header for imeth=6
1605  !<
1606  subroutine record_srcdst_list_header(this, text, textmodel, textpackage, &
1607  dstmodel, dstpackage, naux, auxtxt, &
1608  ibdchn, nlist, iout)
1609  ! -- dummy
1610  class(disutype) :: this
1611  character(len=16), intent(in) :: text
1612  character(len=16), intent(in) :: textmodel
1613  character(len=16), intent(in) :: textpackage
1614  character(len=16), intent(in) :: dstmodel
1615  character(len=16), intent(in) :: dstpackage
1616  integer(I4B), intent(in) :: naux
1617  character(len=16), dimension(:), intent(in) :: auxtxt
1618  integer(I4B), intent(in) :: ibdchn
1619  integer(I4B), intent(in) :: nlist
1620  integer(I4B), intent(in) :: iout
1621  ! -- local
1622  integer(I4B) :: nlay, nrow, ncol
1623  !
1624  nlay = 1
1625  nrow = 1
1626  ncol = this%mshape(1)
1627  !
1628  ! -- Use ubdsv06 to write list header
1629  call ubdsv06(kstp, kper, text, textmodel, textpackage, dstmodel, dstpackage, &
1630  ibdchn, naux, auxtxt, ncol, nrow, nlay, &
1631  nlist, iout, delt, pertim, totim)
1632  !
1633  end subroutine record_srcdst_list_header
1634 
1635  !> @brief Cast base to DISU
1636  !<
1637  !> @brief Get a 2D array of polygon vertices, listed in
1638  !!
1639  !! clockwise order beginning with the lower left corner.
1640  !! The array is empty if the optional cell vertices were
1641  !! not provided.
1642  !<
1643  subroutine get_polyverts(this, ic, polyverts, closed)
1644  ! -- dummy
1645  class(disutype), intent(inout) :: this
1646  integer(I4B), intent(in) :: ic !< cell number (reduced)
1647  real(DP), allocatable, intent(out) :: polyverts(:, :) !< polygon vertices (column-major indexing)
1648  logical(LGP), intent(in), optional :: closed !< whether to close the polygon, duplicating a vertex
1649  ! -- local
1650  integer(I4B) :: icu, iavert, nverts, m, j
1651  logical(LGP) :: lclosed
1652 
1653  ! count vertices
1654  nverts = this%get_npolyverts(ic)
1655  if (nverts == 0) then
1656  allocate (polyverts(2, 0))
1657  return
1658  end if
1659 
1660  ! check closed option
1661  if (.not. (present(closed))) then
1662  lclosed = .false.
1663  else
1664  lclosed = closed
1665  end if
1666 
1667  ! allocate vertices array
1668  if (lclosed) then
1669  allocate (polyverts(2, nverts + 1))
1670  else
1671  allocate (polyverts(2, nverts))
1672  end if
1673 
1674  ! set vertices
1675  icu = this%get_nodeuser(ic)
1676  iavert = this%iavert(icu)
1677  do m = 1, nverts
1678  j = this%javert(iavert - 1 + m)
1679  polyverts(:, m) = (/this%vertices(1, j), this%vertices(2, j)/)
1680  end do
1681 
1682  ! close if enabled
1683  if (lclosed) &
1684  polyverts(:, nverts + 1) = polyverts(:, 1)
1685 
1686  end subroutine
1687 
1688  !> @brief Get the number of cell polygon vertices, 0 if none are defined.
1689  function get_npolyverts(this, ic, closed) result(npolyverts)
1690  class(disutype), intent(inout) :: this
1691  integer(I4B), intent(in) :: ic !< cell number (reduced)
1692  logical(LGP), intent(in), optional :: closed !< whether to close the polygon, duplicating a vertex
1693  integer(I4B) :: npolyverts
1694  ! local
1695  integer(I4B) :: icu
1696 
1697  ! the vertices and cell2d blocks are optional
1698  if (this%nvert < 1) then
1699  npolyverts = 0
1700  return
1701  end if
1702 
1703  icu = this%get_nodeuser(ic)
1704  npolyverts = this%iavert(icu + 1) - this%iavert(icu) - 1
1705  if (present(closed)) then
1706  if (closed) npolyverts = npolyverts + 1
1707  end if
1708  end function get_npolyverts
1709 
1710  !> @brief Get the maximum number of cell polygon vertices.
1711  function get_max_npolyverts(this, closed) result(max_npolyverts)
1712  class(disutype), intent(inout) :: this
1713  logical(LGP), intent(in), optional :: closed !< whether to close the polygon, duplicating a vertex
1714  integer(I4B) :: max_npolyverts
1715  integer(I4B) :: ic
1716 
1717  max_npolyverts = 0
1718  do ic = 1, this%nodes
1719  max_npolyverts = max(max_npolyverts, this%get_npolyverts(ic, closed))
1720  end do
1721  end function get_max_npolyverts
1722 
1723  function castasdisutype(dis) result(disu)
1724  ! -- dummy
1725  class(*), pointer :: dis !< base pointer to DISU object
1726  ! -- return
1727  class(disutype), pointer :: disu !< the resulting DISU pointer
1728  !
1729  disu => null()
1730  select type (dis)
1731  class is (disutype)
1732  disu => dis
1733  end select
1734  !
1735  end function castasdisutype
1736 
1737 end module disumodule
subroutine, public iac_to_ia(iac, ia)
Convert an iac array into an ia array.
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 lenbigline
maximum length of a big line
Definition: Constants.f90:15
@ disu
DISV6 discretization.
Definition: Constants.f90:157
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
subroutine allocate_scalars(this, name_model, input_mempath)
Allocate and initialize scalar variables.
Definition: Disu.f90:1226
subroutine write_grb(this, icelltype)
Write a binary grid file.
Definition: Disu.f90:920
subroutine allocate_arrays(this)
Allocate and initialize arrays.
Definition: Disu.f90:1253
subroutine disu_load(this)
Transfer IDM data into this discretization object.
Definition: Disu.f90:169
subroutine get_polyverts(this, ic, polyverts, closed)
Cast base to DISU.
Definition: Disu.f90:1644
subroutine source_connectivity(this)
Copy grid connectivity info from IDM into package.
Definition: Disu.f90:722
subroutine, public disu_cr(dis, name_model, input_mempath, inunit, iout)
Create a new unstructured discretization object.
Definition: Disu.f90:131
subroutine source_dimensions(this)
Copy dimensions from IDM into package.
Definition: Disu.f90:587
subroutine source_options(this)
Copy options from IDM into package.
Definition: Disu.f90:520
subroutine log_dimensions(this, found)
Write dimensions to list file.
Definition: Disu.f90:648
subroutine disu_da(this)
Deallocate variables.
Definition: Disu.f90:436
class(disutype) function, pointer, public castasdisutype(dis)
Definition: Disu.f90:1724
integer(i4b) function get_ncpl(this)
Get number of cells per layer (total nodes since DISU isn't layered)
Definition: Disu.f90:1423
subroutine define_cellverts(this, icell2d, ncvert, icvert)
Build data structures to hold cell vertex info.
Definition: Disu.f90:827
subroutine read_dbl_array(this, line, lloc, istart, istop, iout, in, darray, aname)
Read a double precision array.
Definition: Disu.f90:1477
integer(i4b) function nodeu_from_cellid(this, cellid, inunit, iout, flag_string, allow_zero)
Convert a cellid string to a user nodenumber.
Definition: Disu.f90:1360
subroutine log_options(this, found)
Write user options to list file.
Definition: Disu.f90:547
subroutine record_srcdst_list_header(this, text, textmodel, textpackage, dstmodel, dstpackage, naux, auxtxt, ibdchn, nlist, iout)
Record list header for imeth=6.
Definition: Disu.f90:1609
subroutine get_dis_type(this, dis_type)
Get the discretization type.
Definition: Disu.f90:1207
subroutine source_vertices(this)
Copy grid vertex data from IDM into package.
Definition: Disu.f90:793
integer(i4b) function get_max_npolyverts(this, closed)
Get the maximum number of cell polygon vertices.
Definition: Disu.f90:1712
subroutine source_cell2d(this)
Copy cell2d data from IDM into package.
Definition: Disu.f90:868
subroutine log_griddata(this, found)
Write griddata found to list file.
Definition: Disu.f90:693
subroutine allocate_arrays_mem(this)
Allocate arrays in memory manager.
Definition: Disu.f90:1277
subroutine source_griddata(this)
Copy grid data from IDM into package.
Definition: Disu.f90:672
subroutine nodeu_to_array(this, nodeu, arr)
Convert a user nodenumber to an array (nodenumber)
Definition: Disu.f90:497
subroutine connection_vector(this, noden, nodem, nozee, satn, satm, ihc, xcomp, ycomp, zcomp, conlen)
Get unit vector components between the cell and a given neighbor.
Definition: Disu.f90:1149
subroutine record_array(this, darray, iout, iprint, idataun, aname, cdatafmp, nvaluesp, nwidthp, editdesc, dinact)
Record a double precision array.
Definition: Disu.f90:1520
subroutine disu_df(this)
Define the discretization.
Definition: Disu.f90:196
logical function supports_layers(this)
Indicates whether the grid discretization supports layers.
Definition: Disu.f90:1413
subroutine read_int_array(this, line, lloc, istart, istop, iout, in, iarray, aname)
Read an integer array.
Definition: Disu.f90:1436
subroutine grid_finalize(this)
Finalize the grid.
Definition: Disu.f90:206
integer(i4b) function get_nodenumber_idx1(this, nodeu, icheck)
Get reduced node number from user node number.
Definition: Disu.f90:1072
subroutine nodeu_to_string(this, nodeu, str)
Convert a user nodenumber to a string (nodenumber)
Definition: Disu.f90:482
integer(i4b) function nodeu_from_string(this, lloc, istart, istop, in, iout, line, flag_string, allow_zero)
Convert a string to a user nodenumber.
Definition: Disu.f90:1300
subroutine disu_ck(this)
Check discretization info.
Definition: Disu.f90:316
integer(i4b) function get_dis_enum(this)
Get the discretization type enumeration.
Definition: Disu.f90:1217
subroutine log_connectivity(this, found, iac)
Write griddata found to list file.
Definition: Disu.f90:756
subroutine connection_normal(this, noden, nodem, ihc, xcomp, ycomp, zcomp, ipos)
Get normal vector components between the cell and a given neighbor.
Definition: Disu.f90:1102
integer(i4b) function get_npolyverts(this, ic, closed)
Get the number of cell polygon vertices, 0 if none are defined.
Definition: Disu.f90:1690
subroutine, public line_unit_vector(x0, y0, z0, x1, y1, z1, xcomp, ycomp, zcomp, vmag)
Calculate the vector components (xcomp, ycomp, and zcomp) for a line defined by two points,...
Definition: DisvGeom.f90:475
subroutine, public ubdsv1(kstp, kper, text, ibdchn, buff, ncol, nrow, nlay, iout, delt, pertim, totim)
Record cell-by-cell flow terms for one component of flow as a 3-D array with extra record to indicate...
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public ulaprufw(ncol, nrow, kstp, kper, ilay, iout, buf, text, userfmt, nvalues, nwidth, editdesc)
Print 1 layer array with user formatting in wrap format.
subroutine, public ubdsv06(kstp, kper, text, modelnam1, paknam1, modelnam2, paknam2, ibdchn, naux, auxtxt, ncol, nrow, nlay, nlist, iout, delt, pertim, totim)
Write header records for cell-by-cell flow terms for one component of flow.
subroutine, public ulasav(buf, text, kstp, kper, pertim, totim, ncol, nrow, ilay, ichn)
Save 1 layer array on disk.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
subroutine, public urword(line, icol, istart, istop, ncode, n, r, iout, in)
Extract a word from a string.
This module defines variable data types.
Definition: kind.f90:8
subroutine, public memorystore_remove(component, subcomponent, context)
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:204
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:169
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
character(len=linelength) idm_context
real(dp), pointer, public pertim
time relative to start of stress period
Definition: tdis.f90:33
real(dp), pointer, public totim
time relative to start of simulation
Definition: tdis.f90:35
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:32
Unstructured grid discretization.
Definition: Disu.f90:29