MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
exg-swfgwf.f90
Go to the documentation of this file.
1 !> @brief This module contains the SwfGwfExchangeModule Module
2 !!
3 !! This module contains the code for connecting a SWF model with
4 !! a GWF model.
5 !!
6 !<
8 
9  use kindmodule, only: dp, i4b, lgp
10  use constantsmodule, only: linelength, dzero
21  use obsmodule, only: obs_cr, obstype
24  use gwfmodule, only: gwfmodeltype
25  use swfmodule, only: swfmodeltype
27  use tablemodule, only: tabletype, table_cr
28 
29  private
30  public :: swfgwf_cr
31 
33 
34  class(numericalmodeltype), pointer :: model1 => null() !< model 1
35  class(numericalmodeltype), pointer :: model2 => null() !< model 2
36  class(swfmodeltype), pointer :: swfmodel1 => null() !< pointer to SWF Model 1
37  class(gwfmodeltype), pointer :: gwfmodel2 => null() !< pointer to GWF Model 2
38 
39  character(len=LINELENGTH), pointer :: filename => null() !< name of the input file
40  integer(I4B), pointer :: ipr_input => null() !< flag to print input
41  integer(I4B), pointer :: ipr_flow => null() !< print flag for cell by cell flows
42 
43  integer(I4B), pointer :: nexg => null() !< number of exchanges
44  integer(I4B), dimension(:), pointer, contiguous :: nodem1 => null() !< node numbers in model 1
45  integer(I4B), dimension(:), pointer, contiguous :: nodem2 => null() !< node numbers in model 2
46  real(dp), dimension(:), pointer, contiguous :: cond => null() !< conductance, size: nexg
47  integer(I4B), dimension(:), pointer, contiguous :: idxglo => null() !< mapping to global (solution) amat
48  integer(I4B), dimension(:), pointer, contiguous :: idxsymglo => null() !< mapping to global (solution) symmetric amat
49  real(dp), dimension(:), pointer, contiguous :: simvals => null() !< simulated flow rate for each exchange
50 
51  type(blockparsertype) :: parser !< block parser for input file (controlled from derived type)
52 
53  integer(I4B), pointer :: inobs => null() !< unit number for GWF-GWF observations
54  type(obstype), pointer :: obs => null() !< observation object
55 
56  ! -- table objects
57  type(tabletype), pointer :: outputtab1 => null()
58  type(tabletype), pointer :: outputtab2 => null()
59 
60  contains
61 
62  procedure :: exg_df => swf_gwf_df
63  procedure :: exg_ac => swf_gwf_ac
64  procedure :: exg_mc => swf_gwf_mc
65  procedure :: exg_fc => swf_gwf_fc
66  procedure :: exg_cq => swf_gwf_cq
67  procedure :: exg_bd => swf_gwf_bd
68  procedure :: exg_ot => swf_gwf_ot
69  procedure :: exg_da => swf_gwf_da
70  procedure :: allocate_scalars
71  procedure :: allocate_arrays
72  procedure :: source_options
73  !procedure :: parse_option
74  procedure :: source_dimensions
75  procedure :: source_data
76  procedure :: swf_gwf_calc_simvals
77  procedure :: swf_gwf_save_simvals
78  procedure :: qcalc
79  procedure :: swf_gwf_add_to_flowja
80  procedure, private :: swf_gwf_chd_bd
81  !todo: procedure :: swf_gwf_bdsav_model
82  procedure :: swf_gwf_bdsav
83  procedure :: connects_model => swf_gwf_connects_model
84 
85  procedure, pass(this) :: noder
86  procedure, pass(this) :: cellstr
87 
88  end type swfgwfexchangetype
89 
90 contains
91 
92  !> @ brief Create SWF GWF exchange
93  !!
94  !! Create a new SWF to GWF exchange object.
95  !<
96  subroutine swfgwf_cr(filename, name, id, m1_id, m2_id, input_mempath)
97  ! -- modules
98  ! -- dummy
99  character(len=*), intent(in) :: filename !< filename for reading
100  character(len=*) :: name !< exchange name
101  integer(I4B), intent(in) :: id !< id for the exchange
102  integer(I4B), intent(in) :: m1_id !< id for model 1
103  integer(I4B), intent(in) :: m2_id !< id for model 2
104  character(len=*), intent(in) :: input_mempath
105  ! -- local
106  type(swfgwfexchangetype), pointer :: exchange
107  class(basemodeltype), pointer :: mb
108  class(baseexchangetype), pointer :: baseexchange
109  integer(I4B) :: m1_index, m2_index
110  !
111  ! -- Create a new exchange and add it to the baseexchangelist container
112  allocate (exchange)
113  baseexchange => exchange
114  call addbaseexchangetolist(baseexchangelist, baseexchange)
115  !
116  ! -- Assign id and name
117  exchange%id = id
118  exchange%name = name
119  exchange%memoryPath = create_mem_path(exchange%name)
120  exchange%input_mempath = input_mempath
121  !
122  ! -- allocate scalars and set defaults
123  call exchange%allocate_scalars()
124  exchange%filename = filename
125  exchange%typename = 'SWF-GWF'
126  !
127  ! -- set swfmodel1
128  m1_index = model_loc_idx(m1_id)
129  if (m1_index > 0) then
130  mb => getbasemodelfromlist(basemodellist, m1_index)
131  select type (mb)
132  type is (swfmodeltype)
133  exchange%model1 => mb
134  exchange%swfmodel1 => mb
135  end select
136  end if
137  ! exchange%v_model1 => get_virtual_model(m1_id)
138  ! exchange%is_datacopy = .not. exchange%v_model1%is_local
139  !
140  ! -- set gwfmodel2
141  m2_index = model_loc_idx(m2_id)
142  if (m2_index > 0) then
143  mb => getbasemodelfromlist(basemodellist, m2_index)
144  select type (mb)
145  type is (gwfmodeltype)
146  exchange%model2 => mb
147  exchange%gwfmodel2 => mb
148  end select
149  end if
150  ! exchange%v_model2 => get_virtual_model(m2_id)
151  !
152  ! -- Verify that gwf model1 is of the correct type
153  if (.not. associated(exchange%swfmodel1) .and. m1_index > 0) then
154  write (errmsg, '(3a)') 'Problem with SWF-GWF exchange ', &
155  trim(exchange%name), &
156  '. Specified SWF Model does not appear to be of the correct type.'
157  call store_error(errmsg, terminate=.true.)
158  end if
159  !
160  ! -- Verify that gwf model2 is of the correct type
161  if (.not. associated(exchange%gwfmodel2) .and. m2_index > 0) then
162  write (errmsg, '(3a)') 'Problem with SWF-GWF exchange ', &
163  trim(exchange%name), &
164  '. Specified GWF Model does not appear to be of the correct type.'
165  call store_error(errmsg, terminate=.true.)
166  end if
167  !
168  ! -- Create the obs package
169  call obs_cr(exchange%obs, exchange%inobs)
170  !
171  ! -- Return
172  return
173  end subroutine swfgwf_cr
174 
175  !> @ brief Define SWF GWF exchange
176  !!
177  !! Define SWF to GWF exchange object.
178  !<
179  subroutine swf_gwf_df(this)
180  ! -- modules
181  ! -- dummy
182  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
183  ! -- local
184  !
185  ! -- log the exchange
186  write (iout, '(/a,a)') ' Creating exchange: ', this%name
187  !
188  ! -- Ensure models are in same solution
189  if (associated(this%swfmodel1) .and. associated(this%gwfmodel2)) then
190  if (this%swfmodel1%idsoln /= this%gwfmodel2%idsoln) then
191  call store_error('Two models are connected in a SWF-GWF '// &
192  'exchange but they are in different solutions. '// &
193  'Models must be in same solution: '// &
194  trim(this%swfmodel1%name)//' '// &
195  trim(this%gwfmodel2%name))
196  call this%parser%StoreErrorUnit()
197  end if
198  end if
199  !
200  ! -- source options
201  call this%source_options(iout)
202  !
203  ! -- source dimensions
204  call this%source_dimensions(iout)
205  !
206  ! -- allocate arrays
207  call this%allocate_arrays()
208  !
209  ! -- source exchange data
210  call this%source_data(iout)
211  !
212  ! -- Store obs
213  ! call this%swf_gwf_df_obs()
214  ! if (associated(this%swfmodel1)) then
215  ! call this%obs%obs_df(iout, this%name, 'SWF-GWF', this%swfmodel1%dis)
216  ! end if
217  ! !
218  ! ! -- validate
219  ! call this%validate_exchange()
220  !
221  ! -- Return
222  return
223  end subroutine swf_gwf_df
224 
225  !> @ brief Add connections
226  !!
227  !! Override parent exg_ac so that gnc can add connections here.
228  !<
229  subroutine swf_gwf_ac(this, sparse)
230  ! -- modules
231  use sparsemodule, only: sparsematrix
232  ! -- dummy
233  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
234  type(sparsematrix), intent(inout) :: sparse
235  ! -- local
236  integer(I4B) :: n, iglo, jglo
237  !
238  ! -- add exchange connections
239  do n = 1, this%nexg
240  iglo = this%nodem1(n) + this%swfmodel1%moffset
241  jglo = this%nodem2(n) + this%gwfmodel2%moffset
242  call sparse%addconnection(iglo, jglo, 1)
243  call sparse%addconnection(jglo, iglo, 1)
244  end do
245  !
246  ! -- Return
247  return
248  end subroutine swf_gwf_ac
249 
250  !> @ brief Map connections
251  !!
252  !! Map the connections in the global matrix
253  !<
254  subroutine swf_gwf_mc(this, matrix_sln)
255  ! -- modules
256  use sparsemodule, only: sparsematrix
257  ! -- dummy
258  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
259  class(matrixbasetype), pointer :: matrix_sln !< the system matrix
260  ! -- local
261  integer(I4B) :: n, iglo, jglo
262  !
263  ! -- map exchange connections
264  do n = 1, this%nexg
265  iglo = this%nodem1(n) + this%swfmodel1%moffset
266  jglo = this%nodem2(n) + this%gwfmodel2%moffset
267  this%idxglo(n) = matrix_sln%get_position(iglo, jglo)
268  this%idxsymglo(n) = matrix_sln%get_position(jglo, iglo)
269  end do
270  !
271  ! -- Return
272  return
273  end subroutine swf_gwf_mc
274 
275  !> @ brief Fill coefficients
276  !!
277  !! Fill conductance into coefficient matrix. For now assume
278  !! all connections are vertical and no newton correction is
279  !! needed.
280  !<
281  subroutine swf_gwf_fc(this, kiter, matrix_sln, rhs_sln, inwtflag)
282  ! -- modules
283  ! -- dummy
284  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
285  integer(I4B), intent(in) :: kiter
286  class(matrixbasetype), pointer :: matrix_sln
287  real(DP), dimension(:), intent(inout) :: rhs_sln
288  integer(I4B), optional, intent(in) :: inwtflag
289  ! -- local
290  integer(I4B) :: i, nodem1sln, nodem2sln
291  !
292  ! -- Put this%cond into amatsln
293  do i = 1, this%nexg
294  call matrix_sln%set_value_pos(this%idxglo(i), this%cond(i))
295  call matrix_sln%set_value_pos(this%idxsymglo(i), this%cond(i))
296 
297  nodem1sln = this%nodem1(i) + this%swfmodel1%moffset
298  nodem2sln = this%nodem2(i) + this%gwfmodel2%moffset
299  call matrix_sln%add_diag_value(nodem1sln, -this%cond(i))
300  call matrix_sln%add_diag_value(nodem2sln, -this%cond(i))
301  end do
302  !
303  ! -- Return
304  return
305  end subroutine swf_gwf_fc
306 
307  !> @ brief Calculate flow
308  !!
309  !! Calculate flow between two cells and store in simvals, also set
310  !! information needed for specific discharge calculation
311  !<
312  subroutine swf_gwf_cq(this, icnvg, isuppress_output, isolnid)
313  ! -- dummy
314  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
315  integer(I4B), intent(inout) :: icnvg
316  integer(I4B), intent(in) :: isuppress_output
317  integer(I4B), intent(in) :: isolnid
318  !
319  ! -- calculate flow and store in simvals
320  call this%swf_gwf_calc_simvals()
321  !
322  ! -- set flows to model edges in NPF
323  ! todo: do we add these flows for specific discharge calculation?
324  !call this%swf_gwf_set_flow_to_npf()
325  !
326  ! -- add exchange flows to model's flowja diagonal
327  call this%swf_gwf_add_to_flowja()
328  !
329  ! -- Return
330  return
331  end subroutine swf_gwf_cq
332 
333  !> @ brief Deallocate
334  !!
335  !! Deallocate memory associated with this object
336  !<
337  subroutine swf_gwf_da(this)
338  ! -- modules
340  ! -- dummy
341  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
342  !
343  ! -- objects
344  call this%obs%obs_da()
345  deallocate (this%obs)
346  !
347  ! -- arrays
348  call mem_deallocate(this%nodem1)
349  call mem_deallocate(this%nodem2)
350  call mem_deallocate(this%cond)
351  call mem_deallocate(this%idxglo)
352  call mem_deallocate(this%idxsymglo)
353  call mem_deallocate(this%simvals)
354  !
355  ! -- scalars
356  deallocate (this%filename)
357  call mem_deallocate(this%ipr_input)
358  call mem_deallocate(this%ipr_flow)
359  call mem_deallocate(this%nexg)
360  call mem_deallocate(this%inobs)
361  !
362  ! -- Return
363  return
364  end subroutine swf_gwf_da
365 
366  !> @ brief Allocate scalars
367  !!
368  !! Allocate scalar variables
369  !<
370  subroutine allocate_scalars(this)
371  ! -- modules
372  ! -- dummy
373  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
374  !
375  allocate (this%filename)
376  this%filename = ''
377  !
378  call mem_allocate(this%ipr_input, 'IPR_INPUT', this%memoryPath)
379  call mem_allocate(this%ipr_flow, 'IPR_FLOW', this%memoryPath)
380  call mem_allocate(this%nexg, 'NEXG', this%memoryPath)
381  call mem_allocate(this%inobs, 'INOBS', this%memoryPath)
382  !
383  this%ipr_input = 0
384  this%ipr_flow = 0
385  this%nexg = 0
386  this%inobs = 0
387  !
388  ! -- Return
389  return
390  end subroutine allocate_scalars
391 
392  !> @brief Allocate array data, using the number of
393  !! connected nodes @param nexg
394  !<
395  subroutine allocate_arrays(this)
396  ! -- dummy
397  class(swfgwfexchangetype) :: this !< instance of exchange object
398  !
399  call mem_allocate(this%nodem1, this%nexg, 'NODEM1', this%memoryPath)
400  call mem_allocate(this%nodem2, this%nexg, 'NODEM2', this%memoryPath)
401  call mem_allocate(this%cond, this%nexg, 'COND', this%memoryPath)
402  call mem_allocate(this%idxglo, this%nexg, 'IDXGLO', this%memoryPath)
403  call mem_allocate(this%idxsymglo, this%nexg, 'IDXSYMGLO', this%memoryPath)
404  call mem_allocate(this%simvals, this%nexg, 'SIMVALS', this%memoryPath)
405  !
406  ! -- Return
407  return
408  end subroutine allocate_arrays
409 
410  !> @ brief Source options
411  !!
412  !! Source the options block
413  !<
414  subroutine source_options(this, iout)
415  ! -- modules
416  use constantsmodule, only: lenvarname, dem6
422  ! -- dummy
423  class(swfgwfexchangetype) :: this !< GwfExchangeType
424  integer(I4B), intent(in) :: iout
425  ! -- local
426  type(exgswfgwfparamfoundtype) :: found
427  !
428  ! -- update defaults with idm sourced values
429  call mem_set_value(this%ipr_input, 'IPR_INPUT', &
430  this%input_mempath, found%ipr_input)
431  call mem_set_value(this%ipr_flow, 'IPR_FLOW', &
432  this%input_mempath, found%ipr_flow)
433  !
434  write (iout, '(1x,a)') 'PROCESSING SWF-GWF EXCHANGE OPTIONS'
435  !
436  if (found%ipr_input) then
437  write (iout, '(4x,a)') &
438  'THE LIST OF EXCHANGES WILL BE PRINTED.'
439  end if
440  !
441  if (found%ipr_flow) then
442  write (iout, '(4x,a)') &
443  'EXCHANGE FLOWS WILL BE PRINTED TO LIST FILES.'
444  end if
445  !
446  ! -- enforce 0 or 1 OBS6_FILENAME entries in option block
447  ! if (.not. this%is_datacopy) then
448  ! if (filein_fname(this%obs%inputFilename, 'OBS6_FILENAME', &
449  ! this%input_mempath, this%filename)) then
450  ! this%obs%active = .true.
451  ! this%obs%inUnitObs = GetUnit()
452  ! call openfile(this%obs%inUnitObs, iout, this%obs%inputFilename, 'OBS')
453  ! end if
454  ! end if
455  !
456  write (iout, '(1x,a)') 'END OF SWF-GWF EXCHANGE OPTIONS'
457  !
458  ! -- Return
459  return
460  end subroutine source_options
461 
462  !> @brief Source dimension from input context
463  !<
464  subroutine source_dimensions(this, iout)
465  ! -- modules
468  ! -- dummy
469  class(swfgwfexchangetype) :: this !< instance of exchange object
470  integer(I4B), intent(in) :: iout !< for logging
471  ! -- local
472  type(exgswfgwfparamfoundtype) :: found
473  !
474  ! -- update defaults with idm sourced values
475  call mem_set_value(this%nexg, 'NEXG', this%input_mempath, found%nexg)
476  !
477  write (iout, '(1x,a)') 'PROCESSING EXCHANGE DIMENSIONS'
478  !
479  if (found%nexg) then
480  write (iout, '(4x,a,i0)') 'NEXG = ', this%nexg
481  end if
482  !
483  write (iout, '(1x,a)') 'END OF EXCHANGE DIMENSIONS'
484  !
485  ! -- return
486  return
487  end subroutine source_dimensions
488 
489  !> @brief
490  !<
491  function noder(this, model, cellid, iout)
492  ! -- modules
493  use geomutilmodule, only: get_node
494  ! -- dummy
495  class(swfgwfexchangetype) :: this !< instance of exchange object
496  class(numericalmodeltype), pointer, intent(in) :: model
497  integer(I4B), dimension(:), pointer, intent(in) :: cellid
498  integer(I4B), intent(in) :: iout !< the output file unit
499  integer(I4B) :: noder, node
500  !
501  if (model%dis%ndim == 1) then
502  node = cellid(1)
503  elseif (model%dis%ndim == 2) then
504  node = get_node(cellid(1), 1, cellid(2), &
505  model%dis%mshape(1), 1, &
506  model%dis%mshape(2))
507  else
508  node = get_node(cellid(1), cellid(2), cellid(3), &
509  model%dis%mshape(1), &
510  model%dis%mshape(2), &
511  model%dis%mshape(3))
512  end if
513  noder = model%dis%get_nodenumber(node, 0)
514  !
515  ! -- return
516  return
517  end function noder
518 
519  !> @brief
520  !<
521  function cellstr(this, model, cellid, iout)
522  ! -- modules
523  ! -- dummy
524  class(swfgwfexchangetype) :: this !< instance of exchange object
525  class(numericalmodeltype), pointer, intent(in) :: model
526  integer(I4B), dimension(:), pointer, intent(in) :: cellid
527  integer(I4B), intent(in) :: iout !< the output file unit
528  character(len=20) :: cellstr
529  character(len=*), parameter :: fmtndim1 = &
530  "('(',i0,')')"
531  character(len=*), parameter :: fmtndim2 = &
532  "('(',i0,',',i0,')')"
533  character(len=*), parameter :: fmtndim3 = &
534  "('(',i0,',',i0,',',i0,')')"
535  !
536  cellstr = ''
537  !
538  select case (model%dis%ndim)
539  case (1)
540  write (cellstr, fmtndim1) cellid(1)
541  case (2)
542  write (cellstr, fmtndim2) cellid(1), cellid(2)
543  case (3)
544  write (cellstr, fmtndim3) cellid(1), cellid(2), cellid(3)
545  case default
546  end select
547  !
548  ! -- return
549  return
550  end function cellstr
551 
552  !> @brief Source exchange data from input context
553  !<
554  subroutine source_data(this, iout)
555  ! -- modules
557  ! -- dummy
558  class(swfgwfexchangetype) :: this !< instance of exchange object
559  integer(I4B), intent(in) :: iout !< the output file unit
560  ! -- local
561  integer(I4B), dimension(:, :), contiguous, pointer :: cellidm1
562  integer(I4B), dimension(:, :), contiguous, pointer :: cellidm2
563  real(DP), dimension(:), contiguous, pointer :: cond
564  character(len=20) :: cellstr1, cellstr2
565  integer(I4B) :: nerr
566  integer(I4B) :: iexg, nodem1, nodem2
567  ! -- format
568  character(len=*), parameter :: fmtexglabel = "(1x, 3a10, 50(a16))"
569  character(len=*), parameter :: fmtexgdata = &
570  "(5x, a, 1x, a ,50(1pg16.6))"
571  !
572  call mem_setptr(cellidm1, 'CELLIDM1', this%input_mempath)
573  call mem_setptr(cellidm2, 'CELLIDM2', this%input_mempath)
574  call mem_setptr(cond, 'COND', this%input_mempath)
575  !
576  write (iout, '(1x,a)') 'PROCESSING EXCHANGEDATA'
577  !
578  if (this%ipr_input /= 0) then
579  write (iout, fmtexglabel) 'NODEM1', 'NODEM2', 'COND'
580  end if
581  !
582  do iexg = 1, this%nexg
583  !
584  if (associated(this%model1)) then
585  !
586  ! -- Determine user node number
587  nodem1 = this%noder(this%model1, cellidm1(:, iexg), iout)
588  this%nodem1(iexg) = nodem1
589  !
590  else
591  this%nodem1(iexg) = -1
592  end if
593  !
594  if (associated(this%model2)) then
595  !
596  ! -- Determine user node number
597  nodem2 = this%noder(this%model2, cellidm2(:, iexg), iout)
598  this%nodem2(iexg) = nodem2
599  !
600  else
601  this%nodem2(iexg) = -1
602  end if
603  !
604  ! -- Read rest of input line
605  this%cond(iexg) = cond(iexg)
606  !
607  ! -- Write the data to listing file if requested
608  if (this%ipr_input /= 0) then
609  cellstr1 = this%cellstr(this%model1, cellidm1(:, iexg), iout)
610  cellstr2 = this%cellstr(this%model2, cellidm2(:, iexg), iout)
611  write (iout, fmtexgdata) trim(cellstr1), trim(cellstr2), &
612  this%cond(iexg)
613  end if
614  !
615  ! -- Check to see if nodem1 is outside of active domain
616  if (associated(this%model1)) then
617  if (nodem1 <= 0) then
618  cellstr1 = this%cellstr(this%model1, cellidm1(:, iexg), iout)
619  write (errmsg, *) &
620  trim(adjustl(this%model1%name))// &
621  ' Cell is outside active grid domain ('// &
622  trim(adjustl(cellstr1))//').'
623  call store_error(errmsg)
624  end if
625  end if
626  !
627  ! -- Check to see if nodem2 is outside of active domain
628  if (associated(this%model2)) then
629  if (nodem2 <= 0) then
630  cellstr2 = this%cellstr(this%model2, cellidm2(:, iexg), iout)
631  write (errmsg, *) &
632  trim(adjustl(this%model2%name))// &
633  ' Cell is outside active grid domain ('// &
634  trim(adjustl(cellstr2))//').'
635  call store_error(errmsg)
636  end if
637  end if
638  end do
639  !
640  write (iout, '(1x,a)') 'END OF EXCHANGEDATA'
641  !
642  ! -- Stop if errors
643  nerr = count_errors()
644  if (nerr > 0) then
645  call store_error('Errors encountered in exchange input file.')
646  call store_error_filename(this%filename)
647  end if
648  !
649  ! -- Return
650  return
651  end subroutine source_data
652 
653  !> @brief Calculate flow rates for the exchanges and store them in a member
654  !! array
655  !<
656  subroutine swf_gwf_calc_simvals(this)
657  ! -- modules
658  use constantsmodule, only: dzero
659  ! -- dummy
660  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
661  ! -- local
662  integer(I4B) :: i
663  integer(I4B) :: n1, n2
664  integer(I4B) :: ibdn1, ibdn2
665  real(DP) :: rrate
666  !
667  do i = 1, this%nexg
668  rrate = dzero
669  n1 = this%nodem1(i)
670  n2 = this%nodem2(i)
671  ibdn1 = this%swfmodel1%ibound(n1)
672  ibdn2 = this%gwfmodel2%ibound(n2)
673  if (ibdn1 /= 0 .and. ibdn2 /= 0) then
674  rrate = this%qcalc(i, n1, n2)
675  end if
676  this%simvals(i) = rrate
677  end do
678  !
679  ! -- Return
680  return
681  end subroutine swf_gwf_calc_simvals
682 
683  !> @ brief Calculate flow
684  !!
685  !! Calculate the flow for the specified exchange and node numbers
686  !<
687  function qcalc(this, iexg, n1, n2)
688  ! -- return
689  real(dp) :: qcalc
690  ! -- dummy
691  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
692  integer(I4B), intent(in) :: iexg
693  integer(I4B), intent(in) :: n1
694  integer(I4B), intent(in) :: n2
695  ! -- local
696  !
697  ! -- Calculate flow between nodes in the two models
698  qcalc = this%cond(iexg) * (this%gwfmodel2%x(n2) - this%swfmodel1%x(n1))
699  !
700  ! -- Return
701  return
702  end function qcalc
703 
704  !> @brief Add exchange flow to each model flowja diagonal position so that
705  !! residual is calculated correctly.
706  !<
707  subroutine swf_gwf_add_to_flowja(this)
708  ! -- modules
709  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
710  ! -- local
711  integer(I4B) :: i
712  integer(I4B) :: n
713  integer(I4B) :: idiag
714  real(DP) :: flow
715  !
716  do i = 1, this%nexg
717  !
718  if (associated(this%swfmodel1)) then
719  n = this%nodem1(i)
720  if (this%swfmodel1%ibound(n) > 0) then
721  flow = this%simvals(i)
722  idiag = this%swfmodel1%ia(n)
723  this%swfmodel1%flowja(idiag) = this%swfmodel1%flowja(idiag) + flow
724  end if
725  end if
726  !
727  if (associated(this%gwfmodel2)) then
728  n = this%nodem2(i)
729  if (this%gwfmodel2%ibound(n) > 0) then
730  flow = -this%simvals(i)
731  idiag = this%gwfmodel2%ia(n)
732  this%gwfmodel2%flowja(idiag) = this%gwfmodel2%flowja(idiag) + flow
733  end if
734  end if
735  !
736  end do
737  !
738  ! -- Return
739  return
740  end subroutine swf_gwf_add_to_flowja
741 
742  !> @ brief Budget
743  !!
744  !! Accumulate budget terms
745  !<
746  subroutine swf_gwf_bd(this, icnvg, isuppress_output, isolnid)
747  ! -- modules
749  use budgetmodule, only: rate_accumulator
750  ! -- dummy
751  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
752  integer(I4B), intent(inout) :: icnvg
753  integer(I4B), intent(in) :: isuppress_output
754  integer(I4B), intent(in) :: isolnid
755  ! -- local
756  character(len=LENBUDTXT), dimension(1) :: budtxt
757  real(DP), dimension(2, 1) :: budterm
758  real(DP) :: ratin, ratout
759  !
760  ! -- initialize
761  budtxt(1) = ' FLOW-JA-FACE'
762  !
763  ! -- Calculate ratin/ratout and pass to model budgets
764  call rate_accumulator(this%simvals, ratin, ratout)
765  !
766  ! -- Add the budget terms to model 1
767  if (associated(this%swfmodel1)) then
768  budterm(1, 1) = ratin
769  budterm(2, 1) = ratout
770  call this%swfmodel1%model_bdentry(budterm, budtxt, this%name)
771  end if
772  !
773  ! -- Add the budget terms to model 2
774  if (associated(this%gwfmodel2)) then
775  budterm(1, 1) = ratout
776  budterm(2, 1) = ratin
777  call this%gwfmodel2%model_bdentry(budterm, budtxt, this%name)
778  end if
779  !
780  ! -- Add any flows from one model into a constant head in another model
781  ! as a separate budget term called FLOW-JA-FACE-CHD
782  call this%swf_gwf_chd_bd()
783  !
784  ! -- Return
785  return
786  end subroutine swf_gwf_bd
787 
788  !> @ brief swf-gwf-chd-bd
789  !!
790  !! Account for flow from an external model into a chd cell
791  !<
792  subroutine swf_gwf_chd_bd(this)
793  ! -- modules
795  ! -- dummy
796  class(swfgwfexchangetype) :: this !< GwfExchangeType
797  ! -- local
798  character(len=LENBUDTXT), dimension(1) :: budtxt
799  integer(I4B) :: n
800  integer(I4B) :: i
801  real(DP), dimension(2, 1) :: budterm
802  real(DP) :: ratin, ratout
803  real(DP) :: q
804  !
805  ! -- initialize
806  budtxt(1) = 'FLOW-JA-FACE-CHD'
807  !
808  ! -- Add the constant-head budget terms for flow from model 2 into model 1
809  if (associated(this%swfmodel1)) then
810  ratin = dzero
811  ratout = dzero
812  do i = 1, this%nexg
813  n = this%nodem1(i)
814  if (this%swfmodel1%ibound(n) < 0) then
815  q = this%simvals(i)
816  if (q > dzero) then
817  ratout = ratout + q
818  else
819  ratin = ratin - q
820  end if
821  end if
822  end do
823  budterm(1, 1) = ratin
824  budterm(2, 1) = ratout
825  call this%swfmodel1%model_bdentry(budterm, budtxt, this%name)
826  end if
827  !
828  ! -- Add the constant-head budget terms for flow from model 1 into model 2
829  if (associated(this%gwfmodel2)) then
830  ratin = dzero
831  ratout = dzero
832  do i = 1, this%nexg
833  n = this%nodem2(i)
834  if (this%gwfmodel2%ibound(n) < 0) then
835  ! -- flip flow sign as flow is relative to model 1
836  q = -this%simvals(i)
837  if (q > dzero) then
838  ratout = ratout + q
839  else
840  ratin = ratin - q
841  end if
842  end if
843  end do
844  budterm(1, 1) = ratin
845  budterm(2, 1) = ratout
846  call this%gwfmodel2%model_bdentry(budterm, budtxt, this%name)
847  end if
848  !
849  ! -- Return
850  return
851  end subroutine swf_gwf_chd_bd
852 
853  !> @ brief Budget save
854  !!
855  !! Output individual flows to listing file and binary budget files
856  !<
857  subroutine swf_gwf_bdsav(this)
858  ! -- dummy
859  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
860  ! -- local
861  integer(I4B) :: icbcfl, ibudfl
862  ! !
863  ! ! -- budget for model1
864  ! if (associated(this%swfmodel1)) then
865  ! call this%swf_gwf_bdsav_model(this%swfmodel1, this%gwfmodel2%name)
866  ! end if
867  ! !
868  ! ! -- budget for model2
869  ! if (associated(this%gwfmodel2)) then
870  ! call this%swf_gwf_bdsav_model(this%gwfmodel2, this%swfmodel1%name)
871  ! end if
872  !
873  ! -- Set icbcfl, ibudfl to zero so that flows will be printed and
874  ! saved, if the options were set in the MVR package
875  icbcfl = 1
876  ibudfl = 1
877  !
878  ! -- Calculate and write simulated values for observations
879  if (this%inobs /= 0) then
880  call this%swf_gwf_save_simvals()
881  end if
882  !
883  ! -- Return
884  return
885  end subroutine swf_gwf_bdsav
886 
887  ! subroutine swf_gwf_bdsav_model(this, model, neighbor_name)
888  ! ! -- modules
889  ! use ConstantsModule, only: DZERO, LENBUDTXT, LENPACKAGENAME
890  ! use TdisModule, only: kstp, kper
891  ! ! -- dummy
892  ! class(SwfGwfExchangeType) :: this !< this exchange
893  ! class(NumericalModelType), pointer :: model !< the model to save budget for
894  ! character(len=*), intent(in) :: neighbor_name !< name of the connected neighbor model
895  ! ! -- local
896  ! character(len=LENPACKAGENAME + 4) :: packname
897  ! character(len=LENBUDTXT), dimension(1) :: budtxt
898  ! type(TableType), pointer :: output_tab
899  ! character(len=20) :: nodestr
900  ! character(len=LENBOUNDNAME) :: bname
901  ! integer(I4B) :: ntabrows
902  ! integer(I4B) :: nodeu
903  ! integer(I4B) :: i, n1, n2, n1u, n2u
904  ! integer(I4B) :: ibinun
905  ! real(DP) :: ratin, ratout, rrate
906  ! logical(LGP) :: is_for_model1
907  ! !
908  ! budtxt(1) = ' FLOW-JA-FACE'
909  ! packname = 'EXG '//this%name
910  ! packname = adjustr(packname)
911  ! if (associated(model, this%swfmodel1)) then
912  ! output_tab => this%outputtab1
913  ! is_for_model1 = .true.
914  ! else
915  ! output_tab => this%outputtab2
916  ! is_for_model1 = .false.
917  ! end if
918  ! !
919  ! ! -- update output tables
920  ! if (this%ipr_flow /= 0) then
921  ! !
922  ! ! -- update titles
923  ! if (model%oc%oc_save('BUDGET')) then
924  ! call output_tab%set_title(packname)
925  ! end if
926  ! !
927  ! ! -- set table kstp and kper
928  ! call output_tab%set_kstpkper(kstp, kper)
929  ! !
930  ! ! -- update maxbound of tables
931  ! ntabrows = 0
932  ! do i = 1, this%nexg
933  ! n1 = this%nodem1(i)
934  ! n2 = this%nodem2(i)
935  ! !
936  ! ! -- If both cells are active then calculate flow rate
937  ! if (this%swfmodel1%ibound(n1) /= 0 .and. &
938  ! this%gwfmodel2%ibound(n2) /= 0) then
939  ! ntabrows = ntabrows + 1
940  ! end if
941  ! end do
942  ! if (ntabrows > 0) then
943  ! call output_tab%set_maxbound(ntabrows)
944  ! end if
945  ! end if
946  ! !
947  ! ! -- Print and write budget terms
948  ! !
949  ! ! -- Set binary unit numbers for saving flows
950  ! if (this%ipakcb /= 0) then
951  ! ibinun = model%oc%oc_save_unit('BUDGET')
952  ! else
953  ! ibinun = 0
954  ! end if
955  ! !
956  ! ! -- If save budget flag is zero for this stress period, then
957  ! ! shut off saving
958  ! if (.not. model%oc%oc_save('BUDGET')) ibinun = 0
959  ! !
960  ! ! -- If cell-by-cell flows will be saved as a list, write header.
961  ! if (ibinun /= 0) then
962  ! call model%dis%record_srcdst_list_header(budtxt(1), &
963  ! model%name, &
964  ! this%name, &
965  ! neighbor_name, &
966  ! this%name, &
967  ! this%naux, this%auxname, &
968  ! ibinun, this%nexg, &
969  ! model%iout)
970  ! end if
971  ! !
972  ! ! Initialize accumulators
973  ! ratin = DZERO
974  ! ratout = DZERO
975  ! !
976  ! ! -- Loop through all exchanges
977  ! do i = 1, this%nexg
978  ! !
979  ! ! -- Assign boundary name
980  ! if (this%inamedbound > 0) then
981  ! bname = this%boundname(i)
982  ! else
983  ! bname = ''
984  ! end if
985  ! !
986  ! ! -- Calculate the flow rate between n1 and n2
987  ! rrate = DZERO
988  ! n1 = this%nodem1(i)
989  ! n2 = this%nodem2(i)
990  ! !
991  ! ! -- If both cells are active then calculate flow rate
992  ! if (this%v_model1%ibound%get(n1) /= 0 .and. &
993  ! this%v_model2%ibound%get(n2) /= 0) then
994  ! rrate = this%simvals(i)
995  ! !
996  ! ! -- Print the individual rates to model list files if requested
997  ! if (this%ipr_flow /= 0) then
998  ! if (model%oc%oc_save('BUDGET')) then
999  ! !
1000  ! ! -- set nodestr and write outputtab table
1001  ! if (is_for_model1) then
1002  ! nodeu = model%dis%get_nodeuser(n1)
1003  ! call model%dis%nodeu_to_string(nodeu, nodestr)
1004  ! call output_tab%print_list_entry(i, trim(adjustl(nodestr)), &
1005  ! rrate, bname)
1006  ! else
1007  ! nodeu = model%dis%get_nodeuser(n2)
1008  ! call model%dis%nodeu_to_string(nodeu, nodestr)
1009  ! call output_tab%print_list_entry(i, trim(adjustl(nodestr)), &
1010  ! -rrate, bname)
1011  ! end if
1012  ! end if
1013  ! end if
1014  ! if (rrate < DZERO) then
1015  ! ratout = ratout - rrate
1016  ! else
1017  ! ratin = ratin + rrate
1018  ! end if
1019  ! end if
1020  ! !
1021  ! ! -- If saving cell-by-cell flows in list, write flow
1022  ! n1u = this%v_model1%dis_get_nodeuser(n1)
1023  ! n2u = this%v_model2%dis_get_nodeuser(n2)
1024  ! if (ibinun /= 0) then
1025  ! if (is_for_model1) then
1026  ! call model%dis%record_mf6_list_entry(ibinun, n1u, n2u, rrate, &
1027  ! this%naux, this%auxvar(:, i), &
1028  ! .false., .false.)
1029  ! else
1030  ! call model%dis%record_mf6_list_entry(ibinun, n2u, n1u, -rrate, &
1031  ! this%naux, this%auxvar(:, i), &
1032  ! .false., .false.)
1033  ! end if
1034  ! end if
1035  ! !
1036  ! end do
1037  ! !
1038  ! ! -- Return
1039  ! return
1040  ! end subroutine swf_gwf_bdsav_model
1041 
1042  !> @ brief Output
1043  !!
1044  !! Write output
1045  !<
1046  subroutine swf_gwf_ot(this)
1047  ! -- modules
1048  use simvariablesmodule, only: iout
1049  use constantsmodule, only: dzero, linelength
1050  ! -- dummy
1051  class(swfgwfexchangetype) :: this !< SwfGwfExchangeType
1052  ! -- local
1053  integer(I4B) :: iexg, n1, n2
1054  real(DP) :: flow
1055  character(len=LINELENGTH) :: node1str, node2str
1056  ! -- format
1057  character(len=*), parameter :: fmtheader2 = &
1058  "(/1x, 'SUMMARY OF EXCHANGE RATES FOR EXCHANGE ', a, ' WITH ID ', i0, /, &
1059  &2a16, 4a16, /, 96('-'))"
1060  character(len=*), parameter :: fmtdata = &
1061  "(2a16, 5(1pg16.6))"
1062  !
1063  ! -- Call bdsave
1064  call this%swf_gwf_bdsav()
1065  !
1066  ! -- Write a table of exchanges
1067  if (this%ipr_flow /= 0) then
1068  write (iout, fmtheader2) trim(adjustl(this%name)), this%id, 'NODEM1', &
1069  'NODEM2', 'COND', 'X_M1', 'X_M2', 'FLOW'
1070  do iexg = 1, this%nexg
1071  n1 = this%nodem1(iexg)
1072  n2 = this%nodem2(iexg)
1073  flow = this%simvals(iexg)
1074  call this%swfmodel1%dis%noder_to_string(n1, node1str)
1075  call this%gwfmodel2%dis%noder_to_string(n2, node2str)
1076  write (iout, fmtdata) trim(adjustl(node1str)), &
1077  trim(adjustl(node2str)), &
1078  this%cond(iexg), this%swfmodel1%x(n1), &
1079  this%gwfmodel2%x(n2), flow
1080  end do
1081  end if
1082  !
1083  ! -- OBS output
1084  call this%obs%obs_ot()
1085  !
1086  ! -- Return
1087  return
1088  end subroutine swf_gwf_ot
1089 
1090  !> @ brief Save simulated flow observations
1091  !!
1092  !! Save the simulated flows for each exchange
1093  !<
1094  subroutine swf_gwf_save_simvals(this)
1095  ! -- modules
1097  use simvariablesmodule, only: errmsg
1098  use constantsmodule, only: dzero
1099  use observemodule, only: observetype
1100  ! -- dummy
1101  class(swfgwfexchangetype), intent(inout) :: this
1102  ! -- local
1103  integer(I4B) :: i
1104  integer(I4B) :: j
1105  integer(I4B) :: n1
1106  integer(I4B) :: n2
1107  integer(I4B) :: iexg
1108  real(DP) :: v
1109  type(observetype), pointer :: obsrv => null()
1110  !
1111  ! -- Write simulated values for all gwf-gwf observations
1112  if (this%obs%npakobs > 0) then
1113  call this%obs%obs_bd_clear()
1114  do i = 1, this%obs%npakobs
1115  obsrv => this%obs%pakobs(i)%obsrv
1116  do j = 1, obsrv%indxbnds_count
1117  iexg = obsrv%indxbnds(j)
1118  v = dzero
1119  select case (obsrv%ObsTypeId)
1120  case ('FLOW-JA-FACE')
1121  n1 = this%nodem1(iexg)
1122  n2 = this%nodem2(iexg)
1123  v = this%simvals(iexg)
1124  case default
1125  errmsg = 'Unrecognized observation type: '// &
1126  trim(obsrv%ObsTypeId)
1127  call store_error(errmsg)
1128  call store_error_unit(this%inobs)
1129  end select
1130  call this%obs%SaveOneSimval(obsrv, v)
1131  end do
1132  end do
1133  end if
1134  !
1135  ! -- Return
1136  return
1137  end subroutine swf_gwf_save_simvals
1138 
1139  !> @brief Should return true when the exchange should be added to the
1140  !! solution where the model resides
1141  !<
1142  function swf_gwf_connects_model(this, model) result(is_connected)
1143  ! -- dummy
1144  class(swfgwfexchangetype) :: this !< the instance of the exchange
1145  class(basemodeltype), pointer, intent(in) :: model !< the model to which the exchange might hold a connection
1146  ! -- return
1147  logical(LGP) :: is_connected !< true, when connected
1148  !
1149  is_connected = .false.
1150  select type (model)
1151  class is (gwfmodeltype)
1152  if (associated(this%gwfmodel2, model)) then
1153  is_connected = .true.
1154  end if
1155  class is (swfmodeltype)
1156  if (associated(this%swfmodel1, model)) then
1157  is_connected = .true.
1158  end if
1159  end select
1160  !
1161  ! -- Return
1162  return
1163  end function
1164 
1165 end module swfgwfexchangemodule
1166 
1167 ! module SwfGwfExchangeModule
1168 
1169 ! use KindModule, only: DP, I4B, LGP
1170 ! use SimVariablesModule, only: errmsg
1171 ! use SimModule, only: store_error
1172 ! use BaseModelModule, only: BaseModelType, GetBaseModelFromList
1173 ! use BaseExchangeModule, only: BaseExchangeType, AddBaseExchangeToList
1174 ! use ConstantsModule, only: LENBOUNDNAME, NAMEDBOUNDFLAG, LINELENGTH, &
1175 ! TABCENTER, TABLEFT, LENAUXNAME, DNODATA
1176 ! use ListModule, only: ListType
1177 ! use ListsModule, only: basemodellist
1178 ! use DisConnExchangeModule, only: DisConnExchangeType
1179 ! use GwfModule, only: GwfModelType
1180 ! use SwfModule, only: SwfModelType
1181 ! use VirtualModelModule, only: VirtualModelType
1182 ! use GhostNodeModule, only: GhostNodeType
1183 ! use GwfMvrModule, only: GwfMvrType
1184 ! use ObserveModule, only: ObserveType
1185 ! use ObsModule, only: ObsType
1186 ! use SimModule, only: count_errors, store_error, store_error_unit
1187 ! use SimVariablesModule, only: errmsg, model_loc_idx
1188 ! use BlockParserModule, only: BlockParserType
1189 ! use TableModule, only: TableType, table_cr
1190 ! use MatrixBaseModule
1191 
1192 ! implicit none
1193 
1194 ! private
1195 ! public :: SwfGwfExchangeType
1196 ! public :: swfgwf_cr
1197 ! public :: GetSwfGwfExchangeFromList
1198 ! public :: CastAsSwfGwfExchange
1199 
1200 ! !> @brief Derived type for SwfGwfExchangeType
1201 ! !!
1202 ! !! This derived type contains information and methods for
1203 ! !! connecting a SWF model with a GWF model.
1204 ! !<
1205 ! type, extends(DisConnExchangeType) :: SwfGwfExchangeType
1206 ! class(SwfModelType), pointer :: swfmodel1 => null() !< pointer to SWF Model 1
1207 ! class(GwfModelType), pointer :: gwfmodel2 => null() !< pointer to GWF Model 2
1208 ! !
1209 ! ! -- GWF specific option block:
1210 ! integer(I4B), pointer :: iprflow => null() !< print flag for cell by cell flows
1211 ! integer(I4B), pointer :: ipakcb => null() !< save flag for cell by cell flows
1212 ! integer(I4B), pointer :: inewton => null() !< newton flag (1 newton is on)
1213 ! integer(I4B), pointer :: icellavg => null() !< cell averaging
1214 ! integer(I4B), pointer :: ivarcv => null() !< variable cv
1215 ! integer(I4B), pointer :: idewatcv => null() !< dewatered cv
1216 ! integer(I4B), pointer :: ingnc => null() !< unit number for gnc (0 if off)
1217 ! type(GhostNodeType), pointer :: gnc => null() !< gnc object
1218 ! integer(I4B), pointer :: inmvr => null() !< unit number for mover (0 if off)
1219 ! type(GwfMvrType), pointer :: mvr => null() !< water mover object
1220 ! integer(I4B), pointer :: inobs => null() !< unit number for GWF-GWF observations
1221 ! type(ObsType), pointer :: obs => null() !< observation object
1222 ! !
1223 ! ! -- internal data
1224 ! real(DP), dimension(:), pointer, contiguous :: cond => null() !< conductance
1225 ! real(DP), dimension(:), pointer, contiguous :: condsat => null() !< saturated conductance
1226 ! integer(I4B), dimension(:), pointer, contiguous :: idxglo => null() !< mapping to global (solution) amat
1227 ! integer(I4B), dimension(:), pointer, contiguous :: idxsymglo => null() !< mapping to global (solution) symmetric amat
1228 ! real(DP), pointer :: satomega => null() !< saturation smoothing
1229 ! real(DP), dimension(:), pointer, contiguous :: simvals => null() !< simulated flow rate for each exchange
1230 ! !
1231 ! ! -- table objects
1232 ! type(TableType), pointer :: outputtab1 => null()
1233 ! type(TableType), pointer :: outputtab2 => null()
1234 
1235 ! contains
1236 
1237 ! procedure :: exg_df => swf_gwf_df
1238 ! procedure :: exg_ac => swf_gwf_ac
1239 ! procedure :: exg_mc => swf_gwf_mc
1240 ! procedure :: exg_ar => swf_gwf_ar
1241 ! procedure :: exg_rp => swf_gwf_rp
1242 ! procedure :: exg_ad => swf_gwf_ad
1243 ! procedure :: exg_cf => swf_gwf_cf
1244 ! procedure :: exg_fc => swf_gwf_fc
1245 ! procedure :: exg_fn => swf_gwf_fn
1246 ! procedure :: exg_cq => swf_gwf_cq
1247 ! procedure :: exg_bd => swf_gwf_bd
1248 ! procedure :: exg_ot => swf_gwf_ot
1249 ! procedure :: exg_da => swf_gwf_da
1250 ! procedure :: exg_fp => swf_gwf_fp
1251 ! procedure :: get_iasym => swf_gwf_get_iasym
1252 ! procedure :: connects_model => swf_gwf_connects_model
1253 ! procedure :: use_interface_model
1254 ! procedure :: allocate_scalars
1255 ! procedure :: allocate_arrays
1256 ! procedure :: read_options
1257 ! procedure :: parse_option
1258 ! procedure :: read_gnc
1259 ! procedure :: read_mvr
1260 ! procedure, private :: calc_cond_sat
1261 ! procedure, private :: condcalc
1262 ! procedure, private :: rewet
1263 ! procedure, private :: qcalc
1264 ! procedure :: swf_gwf_bdsav
1265 ! procedure, private :: swf_gwf_bdsav_model
1266 ! procedure, private :: swf_gwf_df_obs
1267 ! procedure, private :: swf_gwf_rp_obs
1268 ! procedure, public :: swf_gwf_save_simvals
1269 ! procedure, private :: swf_gwf_calc_simvals
1270 ! procedure, public :: swf_gwf_set_flow_to_npf
1271 ! procedure, private :: validate_exchange
1272 ! procedure :: swf_gwf_add_to_flowja
1273 ! end type SwfGwfExchangeType
1274 
1275 ! contains
1276 
1277 ! !> @ brief Create SWF GWF exchange
1278 ! !!
1279 ! !! Create a new SWF to GWF exchange object.
1280 ! !<
1281 ! subroutine swfgwf_cr(filename, name, id, m1_id, m2_id)
1282 ! ! -- modules
1283 ! use ConstantsModule, only: LINELENGTH
1284 ! use BaseModelModule, only: BaseModelType
1285 ! use VirtualModelModule, only: get_virtual_model
1286 ! use ListsModule, only: baseexchangelist
1287 ! use ObsModule, only: obs_cr
1288 ! use MemoryHelperModule, only: create_mem_path
1289 ! ! -- dummy
1290 ! character(len=*), intent(in) :: filename !< filename for reading
1291 ! character(len=*) :: name !< exchange name
1292 ! integer(I4B), intent(in) :: id !< id for the exchange
1293 ! integer(I4B), intent(in) :: m1_id !< id for model 1
1294 ! integer(I4B), intent(in) :: m2_id !< id for model 2
1295 ! ! -- local
1296 ! type(SwfGwfExchangeType), pointer :: exchange
1297 ! class(BaseModelType), pointer :: mb
1298 ! class(BaseExchangeType), pointer :: baseexchange
1299 ! integer(I4B) :: m1_index, m2_index
1300 ! !
1301 ! ! -- Create a new exchange and add it to the baseexchangelist container
1302 ! allocate (exchange)
1303 ! baseexchange => exchange
1304 ! call AddBaseExchangeToList(baseexchangelist, baseexchange)
1305 ! !
1306 ! ! -- Assign id and name
1307 ! exchange%id = id
1308 ! exchange%name = name
1309 ! exchange%memoryPath = create_mem_path(exchange%name)
1310 ! !
1311 ! ! -- allocate scalars and set defaults
1312 ! call exchange%allocate_scalars()
1313 ! exchange%filename = filename
1314 ! exchange%typename = 'GWF-GWF'
1315 ! !
1316 ! ! -- set swfmodel1
1317 ! m1_index = model_loc_idx(m1_id)
1318 ! if (m1_index > 0) then
1319 ! mb => GetBaseModelFromList(basemodellist, m1_index)
1320 ! select type (mb)
1321 ! type is (SwfModelType)
1322 ! exchange%model1 => mb
1323 ! exchange%swfmodel1 => mb
1324 ! end select
1325 ! end if
1326 ! exchange%v_model1 => get_virtual_model(m1_id)
1327 ! exchange%is_datacopy = .not. exchange%v_model1%is_local
1328 ! !
1329 ! ! -- set gwfmodel2
1330 ! m2_index = model_loc_idx(m2_id)
1331 ! if (m2_index > 0) then
1332 ! mb => GetBaseModelFromList(basemodellist, m2_index)
1333 ! select type (mb)
1334 ! type is (GwfModelType)
1335 ! exchange%model2 => mb
1336 ! exchange%gwfmodel2 => mb
1337 ! end select
1338 ! end if
1339 ! exchange%v_model2 => get_virtual_model(m2_id)
1340 ! !
1341 ! ! -- Verify that gwf model1 is of the correct type
1342 ! if (.not. associated(exchange%swfmodel1) .and. m1_index > 0) then
1343 ! write (errmsg, '(3a)') 'Problem with GWF-GWF exchange ', &
1344 ! trim(exchange%name), &
1345 ! '. First specified GWF Model does not appear to be of the correct type.'
1346 ! call store_error(errmsg, terminate=.true.)
1347 ! end if
1348 ! !
1349 ! ! -- Verify that gwf model2 is of the correct type
1350 ! if (.not. associated(exchange%gwfmodel2) .and. m2_index > 0) then
1351 ! write (errmsg, '(3a)') 'Problem with GWF-GWF exchange ', &
1352 ! trim(exchange%name), &
1353 ! '. Second specified GWF Model does not appear to be of the correct type.'
1354 ! call store_error(errmsg, terminate=.true.)
1355 ! end if
1356 ! !
1357 ! ! -- Create the obs package
1358 ! call obs_cr(exchange%obs, exchange%inobs)
1359 ! !
1360 ! ! -- Return
1361 ! return
1362 ! end subroutine swfgwf_cr
1363 
1364 ! !> @ brief Define GWF GWF exchange
1365 ! !!
1366 ! !! Define GWF to GWF exchange object.
1367 ! !<
1368 ! subroutine swf_gwf_df(this)
1369 ! ! -- modules
1370 ! use SimVariablesModule, only: iout
1371 ! use InputOutputModule, only: getunit, openfile
1372 ! use GhostNodeModule, only: gnc_cr
1373 ! ! -- dummy
1374 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1375 ! ! -- local
1376 ! integer(I4B) :: inunit
1377 ! !
1378 ! ! -- open the file
1379 ! inunit = getunit()
1380 ! write (iout, '(/a,a)') ' Creating exchange: ', this%name
1381 ! call openfile(inunit, iout, this%filename, 'GWF-GWF')
1382 ! !
1383 ! call this%parser%Initialize(inunit, iout)
1384 ! !
1385 ! ! -- Ensure models are in same solution
1386 ! if (associated(this%swfmodel1) .and. associated(this%gwfmodel2)) then
1387 ! if (this%swfmodel1%idsoln /= this%gwfmodel2%idsoln) then
1388 ! call store_error('Two models are connected in a GWF '// &
1389 ! 'exchange but they are in different solutions. '// &
1390 ! 'GWF models must be in same solution: '// &
1391 ! trim(this%swfmodel1%name)//' '// &
1392 ! trim(this%gwfmodel2%name))
1393 ! call this%parser%StoreErrorUnit()
1394 ! end if
1395 ! end if
1396 ! !
1397 ! ! -- read options
1398 ! call this%read_options(iout)
1399 ! !
1400 ! ! -- read dimensions
1401 ! call this%read_dimensions(iout)
1402 ! !
1403 ! ! -- allocate arrays
1404 ! call this%allocate_arrays()
1405 ! !
1406 ! ! -- read exchange data
1407 ! call this%read_data(iout)
1408 ! !
1409 ! ! -- call each model and increase the edge count
1410 ! ! TODO: increase edge for gwf so velocity includes vertical leakage component?
1411 ! ! if (associated(this%swfmodel1)) then
1412 ! ! call this%swfmodel1%npf%increase_edge_count(this%nexg)
1413 ! ! end if
1414 ! ! if (associated(this%gwfmodel2)) then
1415 ! ! call this%gwfmodel2%npf%increase_edge_count(this%nexg)
1416 ! ! end if
1417 ! !
1418 ! ! -- Create and read ghost node information
1419 ! if (this%ingnc > 0) then
1420 ! call gnc_cr(this%gnc, this%name, this%ingnc, iout)
1421 ! call this%read_gnc()
1422 ! end if
1423 ! !
1424 ! ! -- Read mover information
1425 ! if (this%inmvr > 0) then
1426 ! call this%read_mvr(iout)
1427 ! end if
1428 ! !
1429 ! ! -- close the file
1430 ! close (inunit)
1431 ! !
1432 ! ! -- Store obs
1433 ! call this%swf_gwf_df_obs()
1434 ! if (associated(this%swfmodel1)) then
1435 ! call this%obs%obs_df(iout, this%name, 'GWF-GWF', this%swfmodel1%dis)
1436 ! end if
1437 ! !
1438 ! ! -- validate
1439 ! call this%validate_exchange()
1440 ! !
1441 ! ! -- Return
1442 ! return
1443 ! end subroutine swf_gwf_df
1444 
1445 ! !> @brief validate exchange data after reading
1446 ! !<
1447 ! subroutine validate_exchange(this)
1448 ! ! -- modules
1449 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1450 ! ! -- local
1451 ! logical(LGP) :: has_k22, has_spdis, has_vsc
1452 ! !
1453 ! ! Periodic boundary condition in exchange don't allow XT3D (=interface model)
1454 ! if (associated(this%model1, this%model2)) then
1455 ! if (this%ixt3d > 0) then
1456 ! write (errmsg, '(3a)') 'GWF-GWF exchange ', trim(this%name), &
1457 ! ' is a periodic boundary condition which cannot'// &
1458 ! ' be configured with XT3D'
1459 ! call store_error(errmsg, terminate=.TRUE.)
1460 ! end if
1461 ! end if
1462 ! !
1463 ! ! XT3D needs angle information
1464 ! if (this%ixt3d > 0 .and. this%ianglex == 0) then
1465 ! write (errmsg, '(3a)') 'GWF-GWF exchange ', trim(this%name), &
1466 ! ' requires that ANGLDEGX be specified as an'// &
1467 ! ' auxiliary variable because XT3D is enabled'
1468 ! call store_error(errmsg, terminate=.TRUE.)
1469 ! end if
1470 ! !
1471 ! ! determine if specific functionality is demanded,
1472 ! ! in model 1 or model 2 (in parallel, only one of
1473 ! ! the models is checked, but the exchange is duplicated)
1474 ! has_k22 = .false.
1475 ! has_spdis = .false.
1476 ! has_vsc = .false.
1477 ! ! if (associated(this%swfmodel1)) then
1478 ! ! has_k22 = (this%swfmodel1%npf%ik22 /= 0)
1479 ! ! has_spdis = (this%swfmodel1%npf%icalcspdis /= 0)
1480 ! ! has_vsc = (this%swfmodel1%npf%invsc /= 0)
1481 ! ! end if
1482 ! if (associated(this%gwfmodel2)) then
1483 ! has_k22 = has_k22 .or. (this%gwfmodel2%npf%ik22 /= 0)
1484 ! has_spdis = has_spdis .or. (this%gwfmodel2%npf%icalcspdis /= 0)
1485 ! has_vsc = has_vsc .or. (this%gwfmodel2%npf%invsc /= 0)
1486 ! end if
1487 ! !
1488 ! ! If horizontal anisotropy is in either model1 or model2,
1489 ! ! ANGLDEGX must be provided as an auxiliary variable for this
1490 ! ! GWF-GWF exchange (this%ianglex > 0).
1491 ! if (has_k22) then
1492 ! if (this%ianglex == 0) then
1493 ! write (errmsg, '(3a)') 'GWF-GWF exchange ', trim(this%name), &
1494 ! ' requires that ANGLDEGX be specified as an'// &
1495 ! ' auxiliary variable because K22 was specified'// &
1496 ! ' in one or both groundwater models.'
1497 ! call store_error(errmsg, terminate=.TRUE.)
1498 ! end if
1499 ! end if
1500 ! !
1501 ! ! If specific discharge is needed for model1 or model2,
1502 ! ! ANGLDEGX must be provided as an auxiliary variable for this
1503 ! ! GWF-GWF exchange (this%ianglex > 0).
1504 ! if (has_spdis) then
1505 ! if (this%ianglex == 0) then
1506 ! write (errmsg, '(3a)') 'GWF-GWF exchange ', trim(this%name), &
1507 ! ' requires that ANGLDEGX be specified as an'// &
1508 ! ' auxiliary variable because specific discharge'// &
1509 ! ' is being calculated in one or both'// &
1510 ! ' groundwater models.'
1511 ! call store_error(errmsg, terminate=.TRUE.)
1512 ! end if
1513 ! if (this%icdist == 0) then
1514 ! write (errmsg, '(3a)') 'GWF-GWF exchange ', trim(this%name), &
1515 ! ' requires that CDIST be specified as an'// &
1516 ! ' auxiliary variable because specific discharge'// &
1517 ! ' is being calculated in one or both'// &
1518 ! ' groundwater models.'
1519 ! call store_error(errmsg, terminate=.TRUE.)
1520 ! end if
1521 ! end if
1522 ! !
1523 ! ! If viscosity is on in either model, then terminate with an
1524 ! ! error as viscosity package doesn't work yet with exchanges.
1525 ! if (has_vsc) then
1526 ! write (errmsg, '(3a)') 'GWF-GWF exchange ', trim(this%name), &
1527 ! ' requires that the Viscosity Package is inactive'// &
1528 ! ' in both of the connected models.'
1529 ! call store_error(errmsg, terminate=.TRUE.)
1530 ! end if
1531 ! !
1532 ! ! -- Return
1533 ! return
1534 ! end subroutine validate_exchange
1535 
1536 ! !> @ brief Add connections
1537 ! !!
1538 ! !! Override parent exg_ac so that gnc can add connections here.
1539 ! !<
1540 ! subroutine swf_gwf_ac(this, sparse)
1541 ! ! -- modules
1542 ! use SparseModule, only: sparsematrix
1543 ! ! -- dummy
1544 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1545 ! type(sparsematrix), intent(inout) :: sparse
1546 ! ! -- local
1547 ! integer(I4B) :: n, iglo, jglo
1548 ! !
1549 ! ! -- add exchange connections
1550 ! do n = 1, this%nexg
1551 ! iglo = this%nodem1(n) + this%swfmodel1%moffset
1552 ! jglo = this%nodem2(n) + this%gwfmodel2%moffset
1553 ! call sparse%addconnection(iglo, jglo, 1)
1554 ! call sparse%addconnection(jglo, iglo, 1)
1555 ! end do
1556 ! !
1557 ! ! -- add gnc connections
1558 ! if (this%ingnc > 0) then
1559 ! call this%gnc%gnc_ac(sparse)
1560 ! end if
1561 ! !
1562 ! ! -- Return
1563 ! return
1564 ! end subroutine swf_gwf_ac
1565 
1566 ! !> @ brief Map connections
1567 ! !!
1568 ! !! Map the connections in the global matrix
1569 ! !<
1570 ! subroutine swf_gwf_mc(this, matrix_sln)
1571 ! ! -- modules
1572 ! use SparseModule, only: sparsematrix
1573 ! ! -- dummy
1574 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1575 ! class(MatrixBaseType), pointer :: matrix_sln !< the system matrix
1576 ! ! -- local
1577 ! integer(I4B) :: n, iglo, jglo
1578 ! !
1579 ! ! -- map exchange connections
1580 ! do n = 1, this%nexg
1581 ! iglo = this%nodem1(n) + this%swfmodel1%moffset
1582 ! jglo = this%nodem2(n) + this%gwfmodel2%moffset
1583 ! this%idxglo(n) = matrix_sln%get_position(iglo, jglo)
1584 ! this%idxsymglo(n) = matrix_sln%get_position(jglo, iglo)
1585 ! end do
1586 ! !
1587 ! ! -- map gnc connections
1588 ! if (this%ingnc > 0) then
1589 ! call this%gnc%gnc_mc(matrix_sln)
1590 ! end if
1591 ! !
1592 ! ! -- Return
1593 ! return
1594 ! end subroutine swf_gwf_mc
1595 
1596 ! !> @ brief Allocate and read
1597 ! !!
1598 ! !! Allocated and read and calculate saturated conductance
1599 ! !<
1600 ! subroutine swf_gwf_ar(this)
1601 ! ! -- dummy
1602 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1603 ! !
1604 ! ! -- If mover is active, then call ar routine
1605 ! if (this%inmvr > 0) call this%mvr%mvr_ar()
1606 ! !
1607 ! ! -- Calculate the saturated conductance for all connections
1608 ! if (.not. this%use_interface_model()) call this%calc_cond_sat()
1609 ! !
1610 ! ! -- Observation AR
1611 ! call this%obs%obs_ar()
1612 ! !
1613 ! ! -- Return
1614 ! return
1615 ! end subroutine swf_gwf_ar
1616 
1617 ! !> @ brief Read and prepare
1618 ! !!
1619 ! !! Read new data for mover and obs
1620 ! !<
1621 ! subroutine swf_gwf_rp(this)
1622 ! ! -- modules
1623 ! use TdisModule, only: readnewdata
1624 ! ! -- dummy
1625 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1626 ! !
1627 ! ! -- Check with TDIS on whether or not it is time to RP
1628 ! if (.not. readnewdata) return
1629 ! !
1630 ! ! -- Read and prepare for mover
1631 ! if (this%inmvr > 0) call this%mvr%mvr_rp()
1632 ! !
1633 ! ! -- Read and prepare for observations
1634 ! call this%swf_gwf_rp_obs()
1635 ! !
1636 ! ! -- Return
1637 ! return
1638 ! end subroutine swf_gwf_rp
1639 
1640 ! !> @ brief Advance
1641 ! !!
1642 ! !! Advance mover and obs
1643 ! !<
1644 ! subroutine swf_gwf_ad(this)
1645 ! ! -- dummy
1646 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1647 ! !
1648 ! ! -- Advance mover
1649 ! if (this%inmvr > 0) call this%mvr%mvr_ad()
1650 ! !
1651 ! ! -- Push simulated values to preceding time step
1652 ! call this%obs%obs_ad()
1653 ! !
1654 ! ! -- Return
1655 ! return
1656 ! end subroutine swf_gwf_ad
1657 
1658 ! !> @ brief Calculate coefficients
1659 ! !!
1660 ! !! Rewet as necessary
1661 ! !<
1662 ! subroutine swf_gwf_cf(this, kiter)
1663 ! ! -- dummy
1664 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1665 ! integer(I4B), intent(in) :: kiter
1666 ! !
1667 ! ! -- Rewet cells across models using the wetdry parameters in each model's
1668 ! ! npf package, and the head in the connected model.
1669 ! call this%rewet(kiter)
1670 ! !
1671 ! ! -- Return
1672 ! return
1673 ! end subroutine swf_gwf_cf
1674 
1675 ! !> @ brief Fill coefficients
1676 ! !!
1677 ! !! Calculate conductance and fill coefficient matrix
1678 ! !<
1679 ! subroutine swf_gwf_fc(this, kiter, matrix_sln, rhs_sln, inwtflag)
1680 ! ! -- modules
1681 ! use ConstantsModule, only: DHALF
1682 ! use GwfConductanceUtilsModule, only: hcond, vcond
1683 ! ! -- dummy
1684 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1685 ! integer(I4B), intent(in) :: kiter
1686 ! class(MatrixBaseType), pointer :: matrix_sln
1687 ! real(DP), dimension(:), intent(inout) :: rhs_sln
1688 ! integer(I4B), optional, intent(in) :: inwtflag
1689 ! ! -- local
1690 ! integer(I4B) :: inwt, iexg
1691 ! integer(I4B) :: i, nodem1sln, nodem2sln
1692 ! !
1693 ! ! -- calculate the conductance for each exchange connection
1694 ! call this%condcalc()
1695 ! !
1696 ! ! -- if gnc is active, then copy cond into gnc cond (might consider a
1697 ! ! pointer here in the future)
1698 ! if (this%ingnc > 0) then
1699 ! do iexg = 1, this%nexg
1700 ! this%gnc%cond(iexg) = this%cond(iexg)
1701 ! end do
1702 ! end if
1703 ! !
1704 ! ! -- Put this%cond into amatsln
1705 ! do i = 1, this%nexg
1706 ! call matrix_sln%set_value_pos(this%idxglo(i), this%cond(i))
1707 ! call matrix_sln%set_value_pos(this%idxsymglo(i), this%cond(i))
1708 
1709 ! nodem1sln = this%nodem1(i) + this%swfmodel1%moffset
1710 ! nodem2sln = this%nodem2(i) + this%gwfmodel2%moffset
1711 ! call matrix_sln%add_diag_value(nodem1sln, -this%cond(i))
1712 ! call matrix_sln%add_diag_value(nodem2sln, -this%cond(i))
1713 ! end do
1714 ! !
1715 ! ! -- Fill the gnc terms in the solution matrix
1716 ! if (this%ingnc > 0) then
1717 ! call this%gnc%gnc_fc(kiter, matrix_sln)
1718 ! end if
1719 ! !
1720 ! ! -- Call mvr fc routine
1721 ! if (this%inmvr > 0) call this%mvr%mvr_fc()
1722 ! !
1723 ! ! -- Set inwt to exchange newton, but shut off if requested by caller
1724 ! inwt = this%inewton
1725 ! if (present(inwtflag)) then
1726 ! if (inwtflag == 0) inwt = 0
1727 ! end if
1728 ! if (inwt /= 0) then
1729 ! call this%exg_fn(kiter, matrix_sln)
1730 ! end if
1731 ! !
1732 ! ! -- Ghost node Newton-Raphson
1733 ! ! if (this%ingnc > 0) then
1734 ! ! if (inwt /= 0) then
1735 ! ! call this%gnc%gnc_fn(kiter, matrix_sln, this%condsat, &
1736 ! ! ihc_opt=this%ihc, ivarcv_opt=this%ivarcv, &
1737 ! ! ictm1_opt=this%swfmodel1%npf%icelltype, &
1738 ! ! ictm2_opt=this%gwfmodel2%npf%icelltype)
1739 ! ! end if
1740 ! ! end if
1741 ! !
1742 ! ! -- Return
1743 ! return
1744 ! end subroutine swf_gwf_fc
1745 
1746 ! !> @ brief Fill Newton
1747 ! !!
1748 ! !! Fill amatsln with Newton terms
1749 ! !<
1750 ! subroutine swf_gwf_fn(this, kiter, matrix_sln)
1751 ! ! -- modules
1752 ! use SmoothingModule, only: sQuadraticSaturationDerivative
1753 ! ! -- dummy
1754 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1755 ! integer(I4B), intent(in) :: kiter
1756 ! class(MatrixBaseType), pointer :: matrix_sln
1757 ! ! -- local
1758 ! logical :: nisup
1759 ! integer(I4B) :: iexg
1760 ! integer(I4B) :: n, m
1761 ! integer(I4B) :: nodensln, nodemsln
1762 ! integer(I4B) :: ibdn, ibdm
1763 ! real(DP) :: topn, topm
1764 ! real(DP) :: botn, botm
1765 ! real(DP) :: topup, botup
1766 ! real(DP) :: hn, hm
1767 ! real(DP) :: hup, hdn
1768 ! real(DP) :: cond
1769 ! real(DP) :: term
1770 ! real(DP) :: consterm
1771 ! real(DP) :: derv
1772 ! !
1773 ! do iexg = 1, this%nexg
1774 ! n = this%nodem1(iexg)
1775 ! m = this%nodem2(iexg)
1776 ! nodensln = this%nodem1(iexg) + this%swfmodel1%moffset
1777 ! nodemsln = this%nodem2(iexg) + this%gwfmodel2%moffset
1778 ! ibdn = this%swfmodel1%ibound(n)
1779 ! ibdm = this%gwfmodel2%ibound(m)
1780 ! topn = this%swfmodel1%dis%top(n)
1781 ! topm = this%gwfmodel2%dis%top(m)
1782 ! botn = this%swfmodel1%dis%bot(n)
1783 ! botm = this%gwfmodel2%dis%bot(m)
1784 ! hn = this%swfmodel1%x(n)
1785 ! hm = this%gwfmodel2%x(m)
1786 ! if (this%ihc(iexg) == 0) then
1787 ! ! -- vertical connection, newton not supported
1788 ! else
1789 ! ! ! -- determine upstream node
1790 ! ! nisup = .false.
1791 ! ! if (hm < hn) nisup = .true.
1792 ! ! !
1793 ! ! ! -- set upstream top and bot
1794 ! ! if (nisup) then
1795 ! ! topup = topn
1796 ! ! botup = botn
1797 ! ! hup = hn
1798 ! ! hdn = hm
1799 ! ! else
1800 ! ! topup = topm
1801 ! ! botup = botm
1802 ! ! hup = hm
1803 ! ! hdn = hn
1804 ! ! end if
1805 ! ! !
1806 ! ! ! -- no newton terms if upstream cell is confined
1807 ! ! if (nisup) then
1808 ! ! if (this%swfmodel1%npf%icelltype(n) == 0) cycle
1809 ! ! else
1810 ! ! if (this%gwfmodel2%npf%icelltype(m) == 0) cycle
1811 ! ! end if
1812 ! ! !
1813 ! ! ! -- set topup and botup
1814 ! ! if (this%ihc(iexg) == 2) then
1815 ! ! topup = min(topn, topm)
1816 ! ! botup = max(botn, botm)
1817 ! ! end if
1818 ! ! !
1819 ! ! ! get saturated conductivity for derivative
1820 ! ! cond = this%condsat(iexg)
1821 ! ! !
1822 ! ! ! -- TO DO deal with MODFLOW-NWT upstream weighting option
1823 ! ! !
1824 ! ! ! -- compute terms
1825 ! ! consterm = -cond * (hup - hdn)
1826 ! ! derv = sQuadraticSaturationDerivative(topup, botup, hup)
1827 ! ! if (nisup) then
1828 ! ! !
1829 ! ! ! -- fill jacobian with n being upstream
1830 ! ! term = consterm * derv
1831 ! ! this%swfmodel1%rhs(n) = this%swfmodel1%rhs(n) + term * hn
1832 ! ! this%gwfmodel2%rhs(m) = this%gwfmodel2%rhs(m) - term * hn
1833 ! ! call matrix_sln%add_diag_value(nodensln, term)
1834 ! ! if (ibdm > 0) then
1835 ! ! call matrix_sln%add_value_pos(this%idxsymglo(iexg), -term)
1836 ! ! end if
1837 ! ! else
1838 ! ! !
1839 ! ! ! -- fill jacobian with m being upstream
1840 ! ! term = -consterm * derv
1841 ! ! this%swfmodel1%rhs(n) = this%swfmodel1%rhs(n) + term * hm
1842 ! ! this%gwfmodel2%rhs(m) = this%gwfmodel2%rhs(m) - term * hm
1843 ! ! call matrix_sln%add_diag_value(nodemsln, -term)
1844 ! ! if (ibdn > 0) then
1845 ! ! call matrix_sln%add_value_pos(this%idxglo(iexg), term)
1846 ! ! end if
1847 ! ! end if
1848 ! end if
1849 ! end do
1850 ! !
1851 ! ! -- Return
1852 ! return
1853 ! end subroutine swf_gwf_fn
1854 
1855 ! !> @ brief Calculate flow
1856 ! !!
1857 ! !! Calculate flow between two cells and store in simvals, also set
1858 ! !! information needed for specific discharge calculation
1859 ! !<
1860 ! subroutine swf_gwf_cq(this, icnvg, isuppress_output, isolnid)
1861 ! ! -- dummy
1862 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1863 ! integer(I4B), intent(inout) :: icnvg
1864 ! integer(I4B), intent(in) :: isuppress_output
1865 ! integer(I4B), intent(in) :: isolnid
1866 ! !
1867 ! ! -- calculate flow and store in simvals
1868 ! call this%swf_gwf_calc_simvals()
1869 ! !
1870 ! ! -- set flows to model edges in NPF
1871 ! call this%swf_gwf_set_flow_to_npf()
1872 ! !
1873 ! ! -- add exchange flows to model's flowja diagonal
1874 ! call this%swf_gwf_add_to_flowja()
1875 ! !
1876 ! ! -- Return
1877 ! return
1878 ! end subroutine swf_gwf_cq
1879 
1880 ! !> @brief Calculate flow rates for the exchanges and store them in a member
1881 ! !! array
1882 ! !<
1883 ! subroutine swf_gwf_calc_simvals(this)
1884 ! ! -- modules
1885 ! use ConstantsModule, only: DZERO
1886 ! ! -- dummy
1887 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1888 ! ! -- local
1889 ! integer(I4B) :: i
1890 ! integer(I4B) :: n1, n2
1891 ! integer(I4B) :: ibdn1, ibdn2
1892 ! real(DP) :: rrate
1893 ! !
1894 ! do i = 1, this%nexg
1895 ! rrate = DZERO
1896 ! n1 = this%nodem1(i)
1897 ! n2 = this%nodem2(i)
1898 ! ibdn1 = this%swfmodel1%ibound(n1)
1899 ! ibdn2 = this%gwfmodel2%ibound(n2)
1900 ! if (ibdn1 /= 0 .and. ibdn2 /= 0) then
1901 ! rrate = this%qcalc(i, n1, n2)
1902 ! if (this%ingnc > 0) then
1903 ! rrate = rrate + this%gnc%deltaqgnc(i)
1904 ! end if
1905 ! end if
1906 ! this%simvals(i) = rrate
1907 ! end do
1908 ! !
1909 ! ! -- Return
1910 ! return
1911 ! end subroutine swf_gwf_calc_simvals
1912 
1913 ! !> @brief Add exchange flow to each model flowja diagonal position so that
1914 ! !! residual is calculated correctly.
1915 ! !<
1916 ! subroutine swf_gwf_add_to_flowja(this)
1917 ! ! -- modules
1918 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1919 ! ! -- local
1920 ! integer(I4B) :: i
1921 ! integer(I4B) :: n
1922 ! integer(I4B) :: idiag
1923 ! real(DP) :: flow
1924 ! !
1925 ! do i = 1, this%nexg
1926 ! !
1927 ! if (associated(this%swfmodel1)) then
1928 ! flow = this%simvals(i)
1929 ! n = this%nodem1(i)
1930 ! idiag = this%swfmodel1%ia(n)
1931 ! this%swfmodel1%flowja(idiag) = this%swfmodel1%flowja(idiag) + flow
1932 ! end if
1933 ! !
1934 ! if (associated(this%gwfmodel2)) then
1935 ! flow = -this%simvals(i)
1936 ! n = this%nodem2(i)
1937 ! idiag = this%gwfmodel2%ia(n)
1938 ! this%gwfmodel2%flowja(idiag) = this%gwfmodel2%flowja(idiag) + flow
1939 ! end if
1940 ! !
1941 ! end do
1942 ! !
1943 ! ! -- Return
1944 ! return
1945 ! end subroutine swf_gwf_add_to_flowja
1946 
1947 ! !> @brief Set flow rates to the edges in the models
1948 ! !<
1949 ! subroutine swf_gwf_set_flow_to_npf(this)
1950 ! ! -- modules
1951 ! use ConstantsModule, only: DZERO, DPIO180
1952 ! use GwfConductanceUtilsModule, only: thksatnm
1953 ! ! -- dummy
1954 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
1955 ! ! -- local
1956 ! integer(I4B) :: iusg
1957 ! integer(I4B) :: i
1958 ! integer(I4B) :: n1, n2
1959 ! integer(I4B) :: ibdn1, ibdn2
1960 ! integer(I4B) :: ictn1, ictn2
1961 ! integer(I4B) :: ihc
1962 ! real(DP) :: rrate
1963 ! real(DP) :: topn1, topn2
1964 ! real(DP) :: botn1, botn2
1965 ! real(DP) :: satn1, satn2
1966 ! real(DP) :: hn1, hn2
1967 ! real(DP) :: nx, ny
1968 ! real(DP) :: distance
1969 ! real(DP) :: dltot
1970 ! real(DP) :: hwva
1971 ! real(DP) :: area
1972 ! real(DP) :: thksat
1973 ! real(DP) :: angle
1974 ! !
1975 ! ! -- Return if neither model needs to calculate specific discharge
1976 ! ! if (this%swfmodel1%npf%icalcspdis == 0 .and. &
1977 ! ! this%gwfmodel2%npf%icalcspdis == 0) return
1978 ! ! !
1979 ! ! ! -- initialize
1980 ! ! iusg = 0
1981 ! ! !
1982 ! ! ! -- Loop through all exchanges using the flow rate
1983 ! ! ! stored in simvals
1984 ! ! do i = 1, this%nexg
1985 ! ! rrate = this%simvals(i)
1986 ! ! n1 = this%nodem1(i)
1987 ! ! n2 = this%nodem2(i)
1988 ! ! ihc = this%ihc(i)
1989 ! ! hwva = this%hwva(i)
1990 ! ! ibdn1 = this%swfmodel1%ibound(n1)
1991 ! ! ibdn2 = this%gwfmodel2%ibound(n2)
1992 ! ! ictn1 = this%swfmodel1%npf%icelltype(n1)
1993 ! ! ictn2 = this%gwfmodel2%npf%icelltype(n2)
1994 ! ! topn1 = this%swfmodel1%dis%top(n1)
1995 ! ! topn2 = this%gwfmodel2%dis%top(n2)
1996 ! ! botn1 = this%swfmodel1%dis%bot(n1)
1997 ! ! botn2 = this%gwfmodel2%dis%bot(n2)
1998 ! ! satn1 = this%swfmodel1%npf%sat(n1)
1999 ! ! satn2 = this%gwfmodel2%npf%sat(n2)
2000 ! ! hn1 = this%swfmodel1%x(n1)
2001 ! ! hn2 = this%gwfmodel2%x(n2)
2002 ! ! !
2003 ! ! ! -- Calculate face normal components
2004 ! ! if (ihc == 0) then
2005 ! ! nx = DZERO
2006 ! ! ny = DZERO
2007 ! ! area = hwva
2008 ! ! if (botn1 < botn2) then
2009 ! ! ! -- n1 is beneath n2, so rate is positive downward. Flip rate
2010 ! ! ! upward so that points in positive z direction
2011 ! ! rrate = -rrate
2012 ! ! end if
2013 ! ! else
2014 ! ! if (this%ianglex > 0) then
2015 ! ! angle = this%auxvar(this%ianglex, i) * DPIO180
2016 ! ! nx = cos(angle)
2017 ! ! ny = sin(angle)
2018 ! ! else
2019 ! ! ! error?
2020 ! ! call store_error('error in swf_gwf_cq', terminate=.TRUE.)
2021 ! ! end if
2022 ! ! !
2023 ! ! ! -- Calculate the saturated thickness at interface between n1 and n2
2024 ! ! thksat = thksatnm(ibdn1, ibdn2, ictn1, ictn2, this%inewton, ihc, &
2025 ! ! iusg, hn1, hn2, satn1, satn2, &
2026 ! ! topn1, topn2, botn1, botn2)
2027 ! ! area = hwva * thksat
2028 ! ! end if
2029 ! ! !
2030 ! ! ! -- Submit this connection and flow information to the npf
2031 ! ! ! package of swfmodel1
2032 ! ! if (this%icdist > 0) then
2033 ! ! dltot = this%auxvar(this%icdist, i)
2034 ! ! else
2035 ! ! call store_error('error in swf_gwf_cq', terminate=.TRUE.)
2036 ! ! end if
2037 ! ! distance = dltot * this%cl1(i) / (this%cl1(i) + this%cl2(i))
2038 ! ! if (this%swfmodel1%npf%icalcspdis == 1) then
2039 ! ! call this%swfmodel1%npf%set_edge_properties(n1, ihc, rrate, area, &
2040 ! ! nx, ny, distance)
2041 ! ! end if
2042 ! ! !
2043 ! ! ! -- Submit this connection and flow information to the npf
2044 ! ! ! package of gwfmodel2
2045 ! ! if (this%icdist > 0) then
2046 ! ! dltot = this%auxvar(this%icdist, i)
2047 ! ! else
2048 ! ! call store_error('error in swf_gwf_cq', terminate=.TRUE.)
2049 ! ! end if
2050 ! ! if (this%gwfmodel2%npf%icalcspdis == 1) then
2051 ! ! distance = dltot * this%cl2(i) / (this%cl1(i) + this%cl2(i))
2052 ! ! if (ihc /= 0) rrate = -rrate
2053 ! ! call this%gwfmodel2%npf%set_edge_properties(n2, ihc, rrate, area, &
2054 ! ! -nx, -ny, distance)
2055 ! ! end if
2056 ! ! !
2057 ! ! end do
2058 ! !
2059 ! ! -- Return
2060 ! return
2061 ! end subroutine swf_gwf_set_flow_to_npf
2062 
2063 ! !> @ brief Budget
2064 ! !!
2065 ! !! Accumulate budget terms
2066 ! !<
2067 ! subroutine swf_gwf_bd(this, icnvg, isuppress_output, isolnid)
2068 ! ! -- modules
2069 ! use ConstantsModule, only: DZERO, LENBUDTXT, LENPACKAGENAME
2070 ! use BudgetModule, only: rate_accumulator
2071 ! ! -- dummy
2072 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2073 ! integer(I4B), intent(inout) :: icnvg
2074 ! integer(I4B), intent(in) :: isuppress_output
2075 ! integer(I4B), intent(in) :: isolnid
2076 ! ! -- local
2077 ! character(len=LENBUDTXT), dimension(1) :: budtxt
2078 ! real(DP), dimension(2, 1) :: budterm
2079 ! real(DP) :: ratin, ratout
2080 ! !
2081 ! ! -- initialize
2082 ! budtxt(1) = ' FLOW-JA-FACE'
2083 ! !
2084 ! ! -- Calculate ratin/ratout and pass to model budgets
2085 ! call rate_accumulator(this%simvals, ratin, ratout)
2086 ! !
2087 ! ! -- Add the budget terms to model 1
2088 ! if (associated(this%swfmodel1)) then
2089 ! budterm(1, 1) = ratin
2090 ! budterm(2, 1) = ratout
2091 ! call this%swfmodel1%model_bdentry(budterm, budtxt, this%name)
2092 ! end if
2093 ! !
2094 ! ! -- Add the budget terms to model 2
2095 ! if (associated(this%gwfmodel2)) then
2096 ! budterm(1, 1) = ratout
2097 ! budterm(2, 1) = ratin
2098 ! call this%gwfmodel2%model_bdentry(budterm, budtxt, this%name)
2099 ! end if
2100 ! !
2101 ! ! -- Call mvr bd routine
2102 ! if (this%inmvr > 0) call this%mvr%mvr_bd()
2103 ! !
2104 ! ! -- Return
2105 ! return
2106 ! end subroutine swf_gwf_bd
2107 
2108 ! !> @ brief Budget save
2109 ! !!
2110 ! !! Output individual flows to listing file and binary budget files
2111 ! !<
2112 ! subroutine swf_gwf_bdsav(this)
2113 ! ! -- dummy
2114 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2115 ! ! -- local
2116 ! integer(I4B) :: icbcfl, ibudfl
2117 ! !
2118 ! ! -- budget for model1
2119 ! if (associated(this%swfmodel1)) then
2120 ! ! TODO: NEED WAY TO BDSAV FOR SWF MODEL call this%swf_gwf_bdsav_model(this%swfmodel1)
2121 ! end if
2122 ! !
2123 ! ! -- budget for model2
2124 ! if (associated(this%gwfmodel2)) then
2125 ! call this%swf_gwf_bdsav_model(this%gwfmodel2)
2126 ! end if
2127 ! !
2128 ! ! -- Set icbcfl, ibudfl to zero so that flows will be printed and
2129 ! ! saved, if the options were set in the MVR package
2130 ! icbcfl = 1
2131 ! ibudfl = 1
2132 ! !
2133 ! ! -- Call mvr bd routine
2134 ! if (this%inmvr > 0) call this%mvr%mvr_bdsav(icbcfl, ibudfl, 0)
2135 ! !
2136 ! ! -- Calculate and write simulated values for observations
2137 ! if (this%inobs /= 0) then
2138 ! call this%swf_gwf_save_simvals()
2139 ! end if
2140 ! !
2141 ! ! -- Return
2142 ! return
2143 ! end subroutine swf_gwf_bdsav
2144 
2145 ! subroutine swf_gwf_bdsav_model(this, model)
2146 ! ! -- modules
2147 ! use ConstantsModule, only: DZERO, LENBUDTXT, LENPACKAGENAME
2148 ! use TdisModule, only: kstp, kper
2149 ! ! -- dummy
2150 ! class(SwfGwfExchangeType) :: this !< this exchange
2151 ! class(GwfModelType), pointer :: model !< the model to save budget for
2152 ! ! -- local
2153 ! character(len=LENPACKAGENAME + 4) :: packname
2154 ! character(len=LENBUDTXT), dimension(1) :: budtxt
2155 ! type(TableType), pointer :: output_tab
2156 ! class(VirtualModelType), pointer :: nbr_model
2157 ! character(len=20) :: nodestr
2158 ! character(len=LENBOUNDNAME) :: bname
2159 ! integer(I4B) :: ntabrows
2160 ! integer(I4B) :: nodeu
2161 ! integer(I4B) :: i, n1, n2, n1u, n2u
2162 ! integer(I4B) :: ibinun
2163 ! real(DP) :: ratin, ratout, rrate
2164 ! logical(LGP) :: is_for_model1
2165 ! !
2166 ! budtxt(1) = ' FLOW-JA-FACE'
2167 ! packname = 'EXG '//this%name
2168 ! packname = adjustr(packname)
2169 ! ! if (associated(model, this%swfmodel1)) then
2170 ! ! output_tab => this%outputtab1
2171 ! ! nbr_model => this%v_model2
2172 ! ! is_for_model1 = .true.
2173 ! ! else
2174 ! output_tab => this%outputtab2
2175 ! nbr_model => this%v_model1
2176 ! is_for_model1 = .false.
2177 ! ! end if
2178 ! !
2179 ! ! -- update output tables
2180 ! if (this%iprflow /= 0) then
2181 ! !
2182 ! ! -- update titles
2183 ! if (model%oc%oc_save('BUDGET')) then
2184 ! call output_tab%set_title(packname)
2185 ! end if
2186 ! !
2187 ! ! -- set table kstp and kper
2188 ! call output_tab%set_kstpkper(kstp, kper)
2189 ! !
2190 ! ! -- update maxbound of tables
2191 ! ntabrows = 0
2192 ! do i = 1, this%nexg
2193 ! n1 = this%nodem1(i)
2194 ! n2 = this%nodem2(i)
2195 ! !
2196 ! ! -- If both cells are active then calculate flow rate
2197 ! if (this%v_model1%ibound%get(n1) /= 0 .and. &
2198 ! this%v_model2%ibound%get(n2) /= 0) then
2199 ! ntabrows = ntabrows + 1
2200 ! end if
2201 ! end do
2202 ! if (ntabrows > 0) then
2203 ! call output_tab%set_maxbound(ntabrows)
2204 ! end if
2205 ! end if
2206 ! !
2207 ! ! -- Print and write budget terms
2208 ! !
2209 ! ! -- Set binary unit numbers for saving flows
2210 ! if (this%ipakcb /= 0) then
2211 ! ibinun = model%oc%oc_save_unit('BUDGET')
2212 ! else
2213 ! ibinun = 0
2214 ! end if
2215 ! !
2216 ! ! -- If save budget flag is zero for this stress period, then
2217 ! ! shut off saving
2218 ! if (.not. model%oc%oc_save('BUDGET')) ibinun = 0
2219 ! !
2220 ! ! -- If cell-by-cell flows will be saved as a list, write header.
2221 ! if (ibinun /= 0) then
2222 ! call model%dis%record_srcdst_list_header(budtxt(1), &
2223 ! model%name, &
2224 ! this%name, &
2225 ! nbr_model%name, &
2226 ! this%name, &
2227 ! this%naux, this%auxname, &
2228 ! ibinun, this%nexg, &
2229 ! model%iout)
2230 ! end if
2231 ! !
2232 ! ! Initialize accumulators
2233 ! ratin = DZERO
2234 ! ratout = DZERO
2235 ! !
2236 ! ! -- Loop through all exchanges
2237 ! do i = 1, this%nexg
2238 ! !
2239 ! ! -- Assign boundary name
2240 ! if (this%inamedbound > 0) then
2241 ! bname = this%boundname(i)
2242 ! else
2243 ! bname = ''
2244 ! end if
2245 ! !
2246 ! ! -- Calculate the flow rate between n1 and n2
2247 ! rrate = DZERO
2248 ! n1 = this%nodem1(i)
2249 ! n2 = this%nodem2(i)
2250 ! !
2251 ! ! -- If both cells are active then calculate flow rate
2252 ! if (this%v_model1%ibound%get(n1) /= 0 .and. &
2253 ! this%v_model2%ibound%get(n2) /= 0) then
2254 ! rrate = this%simvals(i)
2255 ! !
2256 ! ! -- Print the individual rates to model list files if requested
2257 ! if (this%iprflow /= 0) then
2258 ! if (model%oc%oc_save('BUDGET')) then
2259 ! !
2260 ! ! -- set nodestr and write outputtab table
2261 ! if (is_for_model1) then
2262 ! nodeu = model%dis%get_nodeuser(n1)
2263 ! call model%dis%nodeu_to_string(nodeu, nodestr)
2264 ! call output_tab%print_list_entry(i, trim(adjustl(nodestr)), &
2265 ! rrate, bname)
2266 ! else
2267 ! nodeu = model%dis%get_nodeuser(n2)
2268 ! call model%dis%nodeu_to_string(nodeu, nodestr)
2269 ! call output_tab%print_list_entry(i, trim(adjustl(nodestr)), &
2270 ! -rrate, bname)
2271 ! end if
2272 ! end if
2273 ! end if
2274 ! if (rrate < DZERO) then
2275 ! ratout = ratout - rrate
2276 ! else
2277 ! ratin = ratin + rrate
2278 ! end if
2279 ! end if
2280 ! !
2281 ! ! -- If saving cell-by-cell flows in list, write flow
2282 ! n1u = this%v_model1%dis_get_nodeuser(n1)
2283 ! n2u = this%v_model2%dis_get_nodeuser(n2)
2284 ! if (ibinun /= 0) then
2285 ! if (is_for_model1) then
2286 ! call model%dis%record_mf6_list_entry(ibinun, n1u, n2u, rrate, &
2287 ! this%naux, this%auxvar(:, i), &
2288 ! .false., .false.)
2289 ! else
2290 ! call model%dis%record_mf6_list_entry(ibinun, n2u, n1u, -rrate, &
2291 ! this%naux, this%auxvar(:, i), &
2292 ! .false., .false.)
2293 ! end if
2294 ! end if
2295 ! !
2296 ! end do
2297 ! !
2298 ! ! -- Return
2299 ! return
2300 ! end subroutine swf_gwf_bdsav_model
2301 
2302 ! !> @ brief Output
2303 ! !!
2304 ! !! Write output
2305 ! !<
2306 ! subroutine swf_gwf_ot(this)
2307 ! ! -- modules
2308 ! use SimVariablesModule, only: iout
2309 ! use ConstantsModule, only: DZERO, LINELENGTH
2310 ! ! -- dummy
2311 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2312 ! ! -- local
2313 ! integer(I4B) :: iexg, n1, n2
2314 ! integer(I4B) :: ibudfl
2315 ! real(DP) :: flow, deltaqgnc
2316 ! character(len=LINELENGTH) :: node1str, node2str
2317 ! ! -- format
2318 ! character(len=*), parameter :: fmtheader = &
2319 ! "(/1x, 'SUMMARY OF EXCHANGE RATES FOR EXCHANGE ', a, ' WITH ID ', i0, /, &
2320 ! &2a16, 5a16, /, 112('-'))"
2321 ! character(len=*), parameter :: fmtheader2 = &
2322 ! "(/1x, 'SUMMARY OF EXCHANGE RATES FOR EXCHANGE ', a, ' WITH ID ', i0, /, &
2323 ! &2a16, 4a16, /, 96('-'))"
2324 ! character(len=*), parameter :: fmtdata = &
2325 ! "(2a16, 5(1pg16.6))"
2326 ! !
2327 ! ! -- Call bdsave
2328 ! call this%swf_gwf_bdsav()
2329 ! !
2330 ! ! -- Initialize
2331 ! deltaqgnc = DZERO
2332 ! !
2333 ! ! -- Write a table of exchanges
2334 ! if (this%iprflow /= 0) then
2335 ! if (this%ingnc > 0) then
2336 ! write (iout, fmtheader) trim(adjustl(this%name)), this%id, 'NODEM1', &
2337 ! 'NODEM2', 'COND', 'X_M1', 'X_M2', 'DELTAQGNC', &
2338 ! 'FLOW'
2339 ! else
2340 ! write (iout, fmtheader2) trim(adjustl(this%name)), this%id, 'NODEM1', &
2341 ! 'NODEM2', 'COND', 'X_M1', 'X_M2', 'FLOW'
2342 ! end if
2343 ! do iexg = 1, this%nexg
2344 ! n1 = this%nodem1(iexg)
2345 ! n2 = this%nodem2(iexg)
2346 ! flow = this%simvals(iexg)
2347 ! call this%v_model1%dis_noder_to_string(n1, node1str)
2348 ! call this%v_model2%dis_noder_to_string(n2, node2str)
2349 
2350 ! if (this%ingnc > 0) then
2351 ! deltaqgnc = this%gnc%deltaqgnc(iexg)
2352 ! write (iout, fmtdata) trim(adjustl(node1str)), &
2353 ! trim(adjustl(node2str)), &
2354 ! this%cond(iexg), this%v_model1%x%get(n1), &
2355 ! this%v_model2%x%get(n2), deltaqgnc, flow
2356 ! else
2357 ! write (iout, fmtdata) trim(adjustl(node1str)), &
2358 ! trim(adjustl(node2str)), &
2359 ! this%cond(iexg), this%v_model1%x%get(n1), &
2360 ! this%v_model2%x%get(n2), flow
2361 ! end if
2362 ! end do
2363 ! end if
2364 ! !
2365 ! ! -- Mover budget output
2366 ! ibudfl = 1
2367 ! if (this%inmvr > 0) call this%mvr%mvr_ot_bdsummary(ibudfl)
2368 ! !
2369 ! ! -- OBS output
2370 ! call this%obs%obs_ot()
2371 ! !
2372 ! ! -- Return
2373 ! return
2374 ! end subroutine swf_gwf_ot
2375 
2376 ! !> @ brief Read options
2377 ! !!
2378 ! !! Read the options block
2379 ! !<
2380 ! subroutine read_options(this, iout)
2381 ! ! -- modules
2382 ! use ConstantsModule, only: LINELENGTH, LENAUXNAME, DEM6
2383 ! use MemoryManagerModule, only: mem_allocate
2384 ! use SimModule, only: store_error, store_error_unit
2385 ! ! -- dummy
2386 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2387 ! integer(I4B), intent(in) :: iout
2388 ! ! -- local
2389 ! character(len=LINELENGTH) :: keyword
2390 ! logical :: isfound
2391 ! logical :: endOfBlock
2392 ! integer(I4B) :: ierr
2393 ! !
2394 ! ! -- get options block
2395 ! call this%parser%GetBlock('OPTIONS', isfound, ierr, &
2396 ! supportOpenClose=.true., blockRequired=.false.)
2397 ! !
2398 ! ! -- parse options block if detected
2399 ! if (isfound) then
2400 ! write (iout, '(1x,a)') 'PROCESSING GWF-GWF EXCHANGE OPTIONS'
2401 ! do
2402 ! call this%parser%GetNextLine(endOfBlock)
2403 ! if (endOfBlock) then
2404 ! exit
2405 ! end if
2406 ! call this%parser%GetStringCaps(keyword)
2407 ! !
2408 ! ! first parse option in base
2409 ! if (this%DisConnExchangeType%parse_option(keyword, iout)) then
2410 ! cycle
2411 ! end if
2412 ! !
2413 ! ! it's probably ours
2414 ! if (this%parse_option(keyword, iout)) then
2415 ! cycle
2416 ! end if
2417 ! !
2418 ! ! unknown option
2419 ! errmsg = "Unknown GWF-GWF exchange option '"//trim(keyword)//"'."
2420 ! call store_error(errmsg)
2421 ! call this%parser%StoreErrorUnit()
2422 ! end do
2423 ! !
2424 ! write (iout, '(1x,a)') 'END OF GWF-GWF EXCHANGE OPTIONS'
2425 ! end if
2426 ! !
2427 ! ! -- set omega value used for saturation calculations
2428 ! if (this%inewton > 0) then
2429 ! this%satomega = DEM6
2430 ! end if
2431 ! !
2432 ! ! -- Return
2433 ! return
2434 ! end subroutine read_options
2435 
2436 ! !> @brief parse option from exchange file
2437 ! !<
2438 ! function parse_option(this, keyword, iout) result(parsed)
2439 ! ! -- modules
2440 ! use InputOutputModule, only: getunit, openfile
2441 ! ! -- dummy
2442 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2443 ! character(len=LINELENGTH), intent(in) :: keyword !< the option name
2444 ! integer(I4B), intent(in) :: iout !< for logging
2445 ! logical(LGP) :: parsed !< true when parsed
2446 ! ! -- local
2447 ! character(len=LINELENGTH) :: fname
2448 ! integer(I4B) :: inobs
2449 ! character(len=LINELENGTH) :: subkey
2450 ! character(len=:), allocatable :: line
2451 ! !
2452 ! parsed = .true.
2453 ! !
2454 ! sel_opt:select case(keyword)
2455 ! case ('PRINT_FLOWS')
2456 ! this%iprflow = 1
2457 ! write (iout, '(4x,a)') &
2458 ! 'EXCHANGE FLOWS WILL BE PRINTED TO LIST FILES.'
2459 ! case ('SAVE_FLOWS')
2460 ! this%ipakcb = -1
2461 ! write (iout, '(4x,a)') &
2462 ! 'EXCHANGE FLOWS WILL BE SAVED TO BINARY BUDGET FILES.'
2463 ! case ('ALTERNATIVE_CELL_AVERAGING')
2464 ! call this%parser%GetStringCaps(subkey)
2465 ! select case (subkey)
2466 ! case ('LOGARITHMIC')
2467 ! this%icellavg = 1
2468 ! case ('AMT-LMK')
2469 ! this%icellavg = 2
2470 ! case default
2471 ! errmsg = "Unknown cell averaging method '"//trim(subkey)//"'."
2472 ! call store_error(errmsg)
2473 ! call this%parser%StoreErrorUnit()
2474 ! end select
2475 ! write (iout, '(4x,a,a)') &
2476 ! 'CELL AVERAGING METHOD HAS BEEN SET TO: ', trim(subkey)
2477 ! case ('VARIABLECV')
2478 ! this%ivarcv = 1
2479 ! write (iout, '(4x,a)') &
2480 ! 'VERTICAL CONDUCTANCE VARIES WITH WATER TABLE.'
2481 ! call this%parser%GetStringCaps(subkey)
2482 ! if (subkey == 'DEWATERED') then
2483 ! this%idewatcv = 1
2484 ! write (iout, '(4x,a)') &
2485 ! 'VERTICAL CONDUCTANCE ACCOUNTS FOR DEWATERED PORTION OF '// &
2486 ! 'AN UNDERLYING CELL.'
2487 ! end if
2488 ! case ('NEWTON')
2489 ! this%inewton = 1
2490 ! write (iout, '(4x,a)') &
2491 ! 'NEWTON-RAPHSON method used for unconfined cells'
2492 ! case ('GNC6')
2493 ! call this%parser%GetStringCaps(subkey)
2494 ! if (subkey /= 'FILEIN') then
2495 ! call store_error('GNC6 keyword must be followed by '// &
2496 ! '"FILEIN" then by filename.')
2497 ! call this%parser%StoreErrorUnit()
2498 ! end if
2499 ! call this%parser%GetString(fname)
2500 ! if (fname == '') then
2501 ! call store_error('No GNC6 file specified.')
2502 ! call this%parser%StoreErrorUnit()
2503 ! end if
2504 ! this%ingnc = getunit()
2505 ! call openfile(this%ingnc, iout, fname, 'GNC')
2506 ! write (iout, '(4x,a)') &
2507 ! 'GHOST NODES WILL BE READ FROM ', trim(fname)
2508 ! case ('MVR6')
2509 ! if (this%is_datacopy) then
2510 ! call this%parser%GetRemainingLine(line)
2511 ! exit sel_opt
2512 ! end if
2513 ! call this%parser%GetStringCaps(subkey)
2514 ! if (subkey /= 'FILEIN') then
2515 ! call store_error('MVR6 keyword must be followed by '// &
2516 ! '"FILEIN" then by filename.')
2517 ! call this%parser%StoreErrorUnit()
2518 ! end if
2519 ! call this%parser%GetString(fname)
2520 ! if (fname == '') then
2521 ! call store_error('No MVR6 file specified.')
2522 ! call this%parser%StoreErrorUnit()
2523 ! end if
2524 ! this%inmvr = getunit()
2525 ! call openfile(this%inmvr, iout, fname, 'MVR')
2526 ! write (iout, '(4x,a)') &
2527 ! 'WATER MOVER INFORMATION WILL BE READ FROM ', trim(fname)
2528 ! case ('OBS6')
2529 ! if (this%is_datacopy) then
2530 ! call this%parser%GetRemainingLine(line)
2531 ! exit sel_opt
2532 ! end if
2533 ! call this%parser%GetStringCaps(subkey)
2534 ! if (subkey /= 'FILEIN') then
2535 ! call store_error('OBS8 keyword must be followed by '// &
2536 ! '"FILEIN" then by filename.')
2537 ! call this%parser%StoreErrorUnit()
2538 ! end if
2539 ! this%obs%active = .true.
2540 ! call this%parser%GetString(this%obs%inputFilename)
2541 ! inobs = GetUnit()
2542 ! call openfile(inobs, iout, this%obs%inputFilename, 'OBS')
2543 ! this%obs%inUnitObs = inobs
2544 ! case default
2545 ! parsed = .false.
2546 ! end select sel_opt
2547 ! !
2548 ! ! -- Return
2549 ! return
2550 ! end function parse_option
2551 
2552 ! !> @ brief Read ghost nodes
2553 ! !!
2554 ! !! Read and process ghost nodes
2555 ! !<
2556 ! subroutine read_gnc(this)
2557 ! ! -- modules
2558 ! use SimModule, only: store_error, store_error_unit, count_errors
2559 ! use ConstantsModule, only: LINELENGTH
2560 ! ! -- dummy
2561 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2562 ! ! -- local
2563 ! integer(I4B) :: i, nm1, nm2, nmgnc1, nmgnc2
2564 ! character(len=*), parameter :: fmterr = &
2565 ! "('EXCHANGE NODES ', i0, ' AND ', i0,"// &
2566 ! "' NOT CONSISTENT WITH GNC NODES ', "// &
2567 ! "i0, ' AND ', i0)"
2568 ! !
2569 ! ! -- If exchange has ghost nodes, then initialize ghost node object
2570 ! ! This will read the ghost node blocks from the gnc input file.
2571 ! call this%gnc%gnc_df(this%swfmodel1, m2=this%gwfmodel2)
2572 ! !
2573 ! ! -- Verify gnc is implicit if exchange has Newton Terms
2574 ! if (.not. this%gnc%implicit .and. this%inewton /= 0) then
2575 ! call store_error('GNC is explicit, but GWF exchange has active newton.')
2576 ! call store_error('Add implicit option to GNC or remove NEWTON from '// &
2577 ! 'GWF exchange.')
2578 ! call store_error_unit(this%ingnc)
2579 ! end if
2580 ! !
2581 ! ! -- Perform checks to ensure GNCs match with GWF-GWF nodes
2582 ! if (this%nexg /= this%gnc%nexg) then
2583 ! call store_error('Number of exchanges does not match number of GNCs')
2584 ! call store_error_unit(this%ingnc)
2585 ! end if
2586 ! !
2587 ! ! -- Go through each entry and confirm
2588 ! do i = 1, this%nexg
2589 ! if (this%nodem1(i) /= this%gnc%nodem1(i) .or. &
2590 ! this%nodem2(i) /= this%gnc%nodem2(i)) then
2591 ! nm1 = this%swfmodel1%dis%get_nodeuser(this%nodem1(i))
2592 ! nm2 = this%gwfmodel2%dis%get_nodeuser(this%nodem2(i))
2593 ! nmgnc1 = this%swfmodel1%dis%get_nodeuser(this%gnc%nodem1(i))
2594 ! nmgnc2 = this%gwfmodel2%dis%get_nodeuser(this%gnc%nodem2(i))
2595 ! write (errmsg, fmterr) nm1, nm2, nmgnc1, nmgnc2
2596 ! call store_error(errmsg)
2597 ! end if
2598 ! end do
2599 ! if (count_errors() > 0) then
2600 ! call store_error_unit(this%ingnc)
2601 ! end if
2602 ! !
2603 ! ! -- close the file
2604 ! close (this%ingnc)
2605 ! !
2606 ! ! -- Return
2607 ! return
2608 ! end subroutine read_gnc
2609 
2610 ! !> @ brief Read mover
2611 ! !!
2612 ! !! Read and process movers
2613 ! !<
2614 ! subroutine read_mvr(this, iout)
2615 ! ! -- modules
2616 ! use GwfMvrModule, only: mvr_cr
2617 ! ! -- dummy
2618 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2619 ! integer(I4B), intent(in) :: iout
2620 ! !
2621 ! ! -- Create and initialize the mover object Here, dis is set to the one
2622 ! ! for swfmodel1 so that a call to save flows has an associated dis
2623 ! ! object. Because the conversion flags for the mover are both false,
2624 ! ! the dis object does not convert from reduced to user node numbers.
2625 ! ! So in this case, the dis object is just writing unconverted package
2626 ! ! numbers to the binary budget file.
2627 ! call mvr_cr(this%mvr, this%name, this%inmvr, iout, this%swfmodel1%dis, &
2628 ! iexgmvr=1)
2629 ! !
2630 ! ! -- Return
2631 ! return
2632 ! end subroutine read_mvr
2633 
2634 ! !> @ brief Rewet
2635 ! !!
2636 ! !! Check if rewetting should propagate from one model to another
2637 ! !<
2638 ! subroutine rewet(this, kiter)
2639 ! ! -- modules
2640 ! use TdisModule, only: kper, kstp
2641 ! ! -- dummy
2642 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2643 ! integer(I4B), intent(in) :: kiter
2644 ! ! -- local
2645 ! integer(I4B) :: iexg
2646 ! integer(I4B) :: n, m
2647 ! integer(I4B) :: ibdn, ibdm
2648 ! integer(I4B) :: ihc
2649 ! real(DP) :: hn, hm
2650 ! integer(I4B) :: irewet
2651 ! character(len=30) :: nodestrn, nodestrm
2652 ! character(len=*), parameter :: fmtrwt = &
2653 ! "(1x, 'CELL ',A,' REWET FROM GWF MODEL ',A,' CELL ',A, &
2654 ! &' FOR ITER. ',I0, ' STEP ',I0, ' PERIOD ', I0)"
2655 ! !
2656 ! ! -- Use model 1 to rewet model 2 and vice versa
2657 ! ! do iexg = 1, this%nexg
2658 ! ! n = this%nodem1(iexg)
2659 ! ! m = this%nodem2(iexg)
2660 ! ! hn = this%swfmodel1%x(n)
2661 ! ! hm = this%gwfmodel2%x(m)
2662 ! ! ibdn = this%swfmodel1%ibound(n)
2663 ! ! ibdm = this%gwfmodel2%ibound(m)
2664 ! ! ihc = this%ihc(iexg)
2665 ! ! call this%swfmodel1%npf%rewet_check(kiter, n, hm, ibdm, ihc, &
2666 ! ! this%swfmodel1%x, irewet)
2667 ! ! if (irewet == 1) then
2668 ! ! call this%swfmodel1%dis%noder_to_string(n, nodestrn)
2669 ! ! call this%gwfmodel2%dis%noder_to_string(m, nodestrm)
2670 ! ! write (this%swfmodel1%iout, fmtrwt) trim(nodestrn), &
2671 ! ! trim(this%gwfmodel2%name), trim(nodestrm), kiter, kstp, kper
2672 ! ! end if
2673 ! ! call this%gwfmodel2%npf%rewet_check(kiter, m, hn, ibdn, ihc, &
2674 ! ! this%gwfmodel2%x, irewet)
2675 ! ! if (irewet == 1) then
2676 ! ! call this%swfmodel1%dis%noder_to_string(n, nodestrm)
2677 ! ! call this%gwfmodel2%dis%noder_to_string(m, nodestrn)
2678 ! ! write (this%gwfmodel2%iout, fmtrwt) trim(nodestrn), &
2679 ! ! trim(this%swfmodel1%name), trim(nodestrm), kiter, kstp, kper
2680 ! ! end if
2681 ! ! !
2682 ! ! end do
2683 ! !
2684 ! ! -- Return
2685 ! return
2686 ! end subroutine rewet
2687 
2688 ! subroutine calc_cond_sat(this)
2689 ! ! -- modules
2690 ! use ConstantsModule, only: LINELENGTH, DZERO, DHALF, DONE, DPIO180
2691 ! use GwfConductanceUtilsModule, only: condmean, vcond, hcond
2692 ! ! -- dummy
2693 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2694 ! ! -- local
2695 ! integer(I4B) :: iexg
2696 ! integer(I4B) :: n, m, ihc
2697 ! real(DP) :: topn, topm
2698 ! real(DP) :: botn, botm
2699 ! real(DP) :: satn, satm
2700 ! real(DP) :: thickn, thickm
2701 ! real(DP) :: angle, hyn, hym
2702 ! real(DP) :: csat
2703 ! real(DP) :: fawidth
2704 ! real(DP), dimension(3) :: vg
2705 ! !
2706 ! do iexg = 1, this%nexg
2707 ! !
2708 ! ihc = this%ihc(iexg)
2709 ! n = this%nodem1(iexg)
2710 ! m = this%nodem2(iexg)
2711 ! topn = this%swfmodel1%dis%top(n)
2712 ! topm = this%gwfmodel2%dis%top(m)
2713 ! botn = this%swfmodel1%dis%bot(n)
2714 ! botm = this%gwfmodel2%dis%bot(m)
2715 ! satn = DONE ! cdl this%swfmodel1%npf%sat(n)
2716 ! satm = this%gwfmodel2%npf%sat(m)
2717 ! thickn = (topn - botn) * satn
2718 ! thickm = (topm - botm) * satm
2719 ! !
2720 ! ! -- Calculate conductance depending on connection orientation
2721 ! if (ihc == 0) then
2722 ! !
2723 ! ! -- Vertical conductance for fully saturated conditions
2724 ! vg(1) = DZERO
2725 ! vg(2) = DZERO
2726 ! vg(3) = DONE
2727 ! hyn = DONE ! cdl this%swfmodel1%npf%hy_eff(n, 0, ihc, vg=vg)
2728 ! hym = this%gwfmodel2%npf%hy_eff(m, 0, ihc, vg=vg)
2729 ! csat = vcond(1, 1, 1, 1, 0, 1, 1, DONE, &
2730 ! botn, botm, &
2731 ! hyn, hym, &
2732 ! satn, satm, &
2733 ! topn, topm, &
2734 ! botn, botm, &
2735 ! this%hwva(iexg))
2736 ! else
2737 ! !
2738 ! ! -- Calculate horizontal conductance
2739 ! hyn = DONE ! cdl this%swfmodel1%npf%k11(n)
2740 ! hym = this%gwfmodel2%npf%k11(m)
2741 ! !
2742 ! ! -- Check for anisotropy in models, and recalculate hyn and hym
2743 ! if (this%ianglex > 0) then
2744 ! angle = this%auxvar(this%ianglex, iexg) * DPIO180
2745 ! vg(1) = abs(cos(angle))
2746 ! vg(2) = abs(sin(angle))
2747 ! vg(3) = DZERO
2748 ! !
2749 ! ! -- anisotropy in model 1
2750 ! ! if (this%swfmodel1%npf%ik22 /= 0) then
2751 ! ! hyn = this%swfmodel1%npf%hy_eff(n, 0, ihc, vg=vg)
2752 ! ! end if
2753 ! !
2754 ! ! -- anisotropy in model 2
2755 ! if (this%gwfmodel2%npf%ik22 /= 0) then
2756 ! hym = this%gwfmodel2%npf%hy_eff(m, 0, ihc, vg=vg)
2757 ! end if
2758 ! end if
2759 ! !
2760 ! fawidth = this%hwva(iexg)
2761 ! csat = hcond(1, 1, 1, 1, 0, ihc, &
2762 ! this%icellavg, 0, 0, DONE, &
2763 ! topn, topm, satn, satm, hyn, hym, &
2764 ! topn, topm, &
2765 ! botn, botm, &
2766 ! this%cl1(iexg), this%cl2(iexg), &
2767 ! fawidth)
2768 ! end if
2769 ! !
2770 ! ! -- store csat in condsat
2771 ! this%condsat(iexg) = csat
2772 ! end do
2773 ! !
2774 ! ! -- Return
2775 ! return
2776 ! end subroutine calc_cond_sat
2777 
2778 ! !> @ brief Calculate the conductance
2779 ! !!
2780 ! !! Calculate the conductance based on state
2781 ! !<
2782 ! subroutine condcalc(this)
2783 ! ! -- modules
2784 ! use ConstantsModule, only: DHALF, DZERO, DONE
2785 ! use GwfConductanceUtilsModule, only: hcond, vcond
2786 ! ! -- dummy
2787 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2788 ! ! -- local
2789 ! integer(I4B) :: iexg
2790 ! integer(I4B) :: n, m, ihc
2791 ! integer(I4B) :: ibdn, ibdm
2792 ! integer(I4B) :: ictn, ictm
2793 ! real(DP) :: topn, topm
2794 ! real(DP) :: botn, botm
2795 ! real(DP) :: satn, satm
2796 ! real(DP) :: hyn, hym
2797 ! real(DP) :: angle
2798 ! real(DP) :: hn, hm
2799 ! real(DP) :: cond
2800 ! real(DP) :: fawidth
2801 ! real(DP), dimension(3) :: vg
2802 ! !
2803 ! ! -- Calculate conductance and put into amat
2804 ! do iexg = 1, this%nexg
2805 ! ihc = this%ihc(iexg)
2806 ! n = this%nodem1(iexg)
2807 ! m = this%nodem2(iexg)
2808 ! ibdn = this%swfmodel1%ibound(n)
2809 ! ibdm = this%gwfmodel2%ibound(m)
2810 ! ictn = 1 ! cdl this%swfmodel1%npf%icelltype(n)
2811 ! ictm = this%gwfmodel2%npf%icelltype(m)
2812 ! topn = this%swfmodel1%dis%top(n)
2813 ! topm = this%gwfmodel2%dis%top(m)
2814 ! botn = this%swfmodel1%dis%bot(n)
2815 ! botm = this%gwfmodel2%dis%bot(m)
2816 ! satn = DONE ! cdl this%swfmodel1%npf%sat(n)
2817 ! satm = this%gwfmodel2%npf%sat(m)
2818 ! hn = this%swfmodel1%x(n)
2819 ! hm = this%gwfmodel2%x(m)
2820 ! !
2821 ! ! -- Calculate conductance depending on connection orientation
2822 ! if (ihc == 0) then
2823 ! !
2824 ! ! -- Vertical connection
2825 ! vg(1) = DZERO
2826 ! vg(2) = DZERO
2827 ! vg(3) = DONE
2828 ! hyn = DONE ! cdl this%swfmodel1%npf%hy_eff(n, 0, ihc, vg=vg)
2829 ! hym = this%gwfmodel2%npf%hy_eff(m, 0, ihc, vg=vg)
2830 ! cond = vcond(ibdn, ibdm, ictn, ictm, this%inewton, this%ivarcv, &
2831 ! this%idewatcv, this%condsat(iexg), hn, hm, hyn, hym, &
2832 ! satn, satm, topn, topm, botn, botm, this%hwva(iexg))
2833 ! else
2834 ! ! !
2835 ! ! ! -- Horizontal Connection
2836 ! ! hyn = this%swfmodel1%npf%k11(n)
2837 ! ! hym = this%gwfmodel2%npf%k11(m)
2838 ! ! !
2839 ! ! ! -- Check for anisotropy in models, and recalculate hyn and hym
2840 ! ! if (this%ianglex > 0) then
2841 ! ! angle = this%auxvar(this%ianglex, iexg)
2842 ! ! vg(1) = abs(cos(angle))
2843 ! ! vg(2) = abs(sin(angle))
2844 ! ! vg(3) = DZERO
2845 ! ! !
2846 ! ! ! -- anisotropy in model 1
2847 ! ! if (this%swfmodel1%npf%ik22 /= 0) then
2848 ! ! hyn = this%swfmodel1%npf%hy_eff(n, 0, ihc, vg=vg)
2849 ! ! end if
2850 ! ! !
2851 ! ! ! -- anisotropy in model 2
2852 ! ! if (this%gwfmodel2%npf%ik22 /= 0) then
2853 ! ! hym = this%gwfmodel2%npf%hy_eff(m, 0, ihc, vg=vg)
2854 ! ! end if
2855 ! ! end if
2856 ! ! !
2857 ! ! fawidth = this%hwva(iexg)
2858 ! ! cond = hcond(ibdn, ibdm, ictn, ictm, this%inewton, &
2859 ! ! this%ihc(iexg), this%icellavg, 0, 0, this%condsat(iexg), &
2860 ! ! hn, hm, satn, satm, hyn, hym, topn, topm, botn, botm, &
2861 ! ! this%cl1(iexg), this%cl2(iexg), fawidth)
2862 ! end if
2863 ! !
2864 ! this%cond(iexg) = cond
2865 ! !
2866 ! end do
2867 ! !
2868 ! ! -- Return
2869 ! return
2870 ! end subroutine condcalc
2871 
2872 ! !> @ brief Allocate scalars
2873 ! !!
2874 ! !! Allocate scalar variables
2875 ! !<
2876 ! subroutine allocate_scalars(this)
2877 ! ! -- modules
2878 ! use MemoryManagerModule, only: mem_allocate
2879 ! use ConstantsModule, only: DZERO
2880 ! ! -- dummy
2881 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2882 ! !
2883 ! call this%DisConnExchangeType%allocate_scalars()
2884 ! !
2885 ! call mem_allocate(this%iprflow, 'IPRFLOW', this%memoryPath)
2886 ! call mem_allocate(this%ipakcb, 'IPAKCB', this%memoryPath)
2887 ! this%iprpak = 0
2888 ! this%iprflow = 0
2889 ! this%ipakcb = 0
2890 ! !
2891 ! call mem_allocate(this%icellavg, 'ICELLAVG', this%memoryPath)
2892 ! call mem_allocate(this%ivarcv, 'IVARCV', this%memoryPath)
2893 ! call mem_allocate(this%idewatcv, 'IDEWATCV', this%memoryPath)
2894 ! call mem_allocate(this%inewton, 'INEWTON', this%memoryPath)
2895 ! call mem_allocate(this%ingnc, 'INGNC', this%memoryPath)
2896 ! call mem_allocate(this%inmvr, 'INMVR', this%memoryPath)
2897 ! call mem_allocate(this%inobs, 'INOBS', this%memoryPath)
2898 ! call mem_allocate(this%satomega, 'SATOMEGA', this%memoryPath)
2899 ! this%icellavg = 0
2900 ! this%ivarcv = 0
2901 ! this%idewatcv = 0
2902 ! this%inewton = 0
2903 ! this%ingnc = 0
2904 ! this%inmvr = 0
2905 ! this%inobs = 0
2906 ! this%satomega = DZERO
2907 ! !
2908 ! ! -- Return
2909 ! return
2910 ! end subroutine allocate_scalars
2911 
2912 ! !> @ brief Deallocate
2913 ! !!
2914 ! !! Deallocate memory associated with this object
2915 ! !<
2916 ! subroutine swf_gwf_da(this)
2917 ! ! -- modules
2918 ! use MemoryManagerModule, only: mem_deallocate
2919 ! ! -- dummy
2920 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2921 ! !
2922 ! ! -- objects
2923 ! if (this%ingnc > 0) then
2924 ! call this%gnc%gnc_da()
2925 ! deallocate (this%gnc)
2926 ! end if
2927 ! if (this%inmvr > 0) then
2928 ! call this%mvr%mvr_da()
2929 ! deallocate (this%mvr)
2930 ! end if
2931 ! call this%obs%obs_da()
2932 ! deallocate (this%obs)
2933 ! !
2934 ! ! -- arrays
2935 ! call mem_deallocate(this%cond)
2936 ! call mem_deallocate(this%condsat)
2937 ! call mem_deallocate(this%idxglo)
2938 ! call mem_deallocate(this%idxsymglo)
2939 ! call mem_deallocate(this%simvals)
2940 ! !
2941 ! ! -- output table objects
2942 ! if (associated(this%outputtab1)) then
2943 ! call this%outputtab1%table_da()
2944 ! deallocate (this%outputtab1)
2945 ! nullify (this%outputtab1)
2946 ! end if
2947 ! if (associated(this%outputtab2)) then
2948 ! call this%outputtab2%table_da()
2949 ! deallocate (this%outputtab2)
2950 ! nullify (this%outputtab2)
2951 ! end if
2952 ! !
2953 ! ! -- scalars
2954 ! deallocate (this%filename)
2955 ! call mem_deallocate(this%iprflow)
2956 ! call mem_deallocate(this%ipakcb)
2957 ! !
2958 ! call mem_deallocate(this%icellavg)
2959 ! call mem_deallocate(this%ivarcv)
2960 ! call mem_deallocate(this%idewatcv)
2961 ! call mem_deallocate(this%inewton)
2962 ! call mem_deallocate(this%ingnc)
2963 ! call mem_deallocate(this%inmvr)
2964 ! call mem_deallocate(this%inobs)
2965 ! call mem_deallocate(this%satomega)
2966 ! !
2967 ! ! -- deallocate base
2968 ! call this%DisConnExchangeType%disconnex_da()
2969 ! !
2970 ! ! -- Return
2971 ! return
2972 ! end subroutine swf_gwf_da
2973 
2974 ! !> @ brief Allocate arrays
2975 ! !!
2976 ! !! Allocate arrays
2977 ! !<
2978 ! subroutine allocate_arrays(this)
2979 ! ! -- modules
2980 ! use MemoryManagerModule, only: mem_allocate
2981 ! ! -- dummy
2982 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
2983 ! ! -- local
2984 ! character(len=LINELENGTH) :: text
2985 ! integer(I4B) :: ntabcol, i
2986 ! !
2987 ! call this%DisConnExchangeType%allocate_arrays()
2988 ! !
2989 ! call mem_allocate(this%cond, this%nexg, 'COND', this%memoryPath)
2990 ! call mem_allocate(this%idxglo, this%nexg, 'IDXGLO', this%memoryPath)
2991 ! call mem_allocate(this%idxsymglo, this%nexg, 'IDXSYMGLO', this%memoryPath) !
2992 ! call mem_allocate(this%condsat, this%nexg, 'CONDSAT', this%memoryPath)
2993 ! call mem_allocate(this%simvals, this%nexg, 'SIMVALS', this%memoryPath)
2994 ! !
2995 ! ! -- Initialize
2996 ! do i = 1, this%nexg
2997 ! this%cond(i) = DNODATA
2998 ! end do
2999 ! !
3000 ! ! -- allocate and initialize the output table
3001 ! if (this%iprflow /= 0) then
3002 ! !
3003 ! ! -- dimension table
3004 ! ntabcol = 3
3005 ! if (this%inamedbound > 0) then
3006 ! ntabcol = ntabcol + 1
3007 ! end if
3008 ! !
3009 ! ! -- initialize the output table objects
3010 ! ! outouttab1
3011 ! if (this%v_model1%is_local) then
3012 ! call table_cr(this%outputtab1, this%name, ' ')
3013 ! call this%outputtab1%table_df(this%nexg, ntabcol, this%swfmodel1%iout, &
3014 ! transient=.TRUE.)
3015 ! text = 'NUMBER'
3016 ! call this%outputtab1%initialize_column(text, 10, alignment=TABCENTER)
3017 ! text = 'CELLID'
3018 ! call this%outputtab1%initialize_column(text, 20, alignment=TABLEFT)
3019 ! text = 'RATE'
3020 ! call this%outputtab1%initialize_column(text, 15, alignment=TABCENTER)
3021 ! if (this%inamedbound > 0) then
3022 ! text = 'NAME'
3023 ! call this%outputtab1%initialize_column(text, 20, alignment=TABLEFT)
3024 ! end if
3025 ! end if
3026 ! ! outouttab2
3027 ! if (this%v_model2%is_local) then
3028 ! call table_cr(this%outputtab2, this%name, ' ')
3029 ! call this%outputtab2%table_df(this%nexg, ntabcol, this%gwfmodel2%iout, &
3030 ! transient=.TRUE.)
3031 ! text = 'NUMBER'
3032 ! call this%outputtab2%initialize_column(text, 10, alignment=TABCENTER)
3033 ! text = 'CELLID'
3034 ! call this%outputtab2%initialize_column(text, 20, alignment=TABLEFT)
3035 ! text = 'RATE'
3036 ! call this%outputtab2%initialize_column(text, 15, alignment=TABCENTER)
3037 ! if (this%inamedbound > 0) then
3038 ! text = 'NAME'
3039 ! call this%outputtab2%initialize_column(text, 20, alignment=TABLEFT)
3040 ! end if
3041 ! end if
3042 ! end if
3043 ! !
3044 ! ! -- Return
3045 ! return
3046 ! end subroutine allocate_arrays
3047 
3048 ! !> @ brief Define observations
3049 ! !!
3050 ! !! Define the observations associated with this object
3051 ! !<
3052 ! subroutine swf_gwf_df_obs(this)
3053 ! ! -- dummy
3054 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3055 ! ! -- local
3056 ! integer(I4B) :: indx
3057 ! !
3058 ! ! -- Store obs type and assign procedure pointer
3059 ! ! for gwf-gwf observation type.
3060 ! call this%obs%StoreObsType('flow-ja-face', .true., indx)
3061 ! this%obs%obsData(indx)%ProcessIdPtr => swf_gwf_process_obsID
3062 ! !
3063 ! ! -- Return
3064 ! return
3065 ! end subroutine swf_gwf_df_obs
3066 
3067 ! !> @ brief Read and prepare observations
3068 ! !!
3069 ! !! Handle observation exchanges exchange-boundary names.
3070 ! !<
3071 ! subroutine swf_gwf_rp_obs(this)
3072 ! ! -- modules
3073 ! use ConstantsModule, only: DZERO
3074 ! ! -- dummy
3075 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3076 ! ! -- local
3077 ! integer(I4B) :: i
3078 ! integer(I4B) :: j
3079 ! class(ObserveType), pointer :: obsrv => null()
3080 ! character(len=LENBOUNDNAME) :: bname
3081 ! logical :: jfound
3082 ! ! -- formats
3083 ! 10 format('Exchange "', a, '" for observation "', a, &
3084 ! '" is invalid in package "', a, '"')
3085 ! 20 format('Exchange id "', i0, '" for observation "', a, &
3086 ! '" is invalid in package "', a, '"')
3087 ! !
3088 ! do i = 1, this%obs%npakobs
3089 ! obsrv => this%obs%pakobs(i)%obsrv
3090 ! !
3091 ! ! -- indxbnds needs to be reset each stress period because
3092 ! ! list of boundaries can change each stress period.
3093 ! ! -- Not true for exchanges, but leave this in for now anyway.
3094 ! call obsrv%ResetObsIndex()
3095 ! obsrv%BndFound = .false.
3096 ! !
3097 ! bname = obsrv%FeatureName
3098 ! if (bname /= '') then
3099 ! ! -- Observation location(s) is(are) based on a boundary name.
3100 ! ! Iterate through all boundaries to identify and store
3101 ! ! corresponding index(indices) in bound array.
3102 ! jfound = .false.
3103 ! do j = 1, this%nexg
3104 ! if (this%boundname(j) == bname) then
3105 ! jfound = .true.
3106 ! obsrv%BndFound = .true.
3107 ! obsrv%CurrentTimeStepEndValue = DZERO
3108 ! call obsrv%AddObsIndex(j)
3109 ! end if
3110 ! end do
3111 ! if (.not. jfound) then
3112 ! write (errmsg, 10) trim(bname), trim(obsrv%ObsTypeId), trim(this%name)
3113 ! call store_error(errmsg)
3114 ! end if
3115 ! else
3116 ! ! -- Observation location is a single exchange number
3117 ! if (obsrv%intPak1 <= this%nexg .and. obsrv%intPak1 > 0) then
3118 ! jfound = .true.
3119 ! obsrv%BndFound = .true.
3120 ! obsrv%CurrentTimeStepEndValue = DZERO
3121 ! call obsrv%AddObsIndex(obsrv%intPak1)
3122 ! else
3123 ! jfound = .false.
3124 ! end if
3125 ! if (.not. jfound) then
3126 ! write (errmsg, 20) obsrv%intPak1, trim(obsrv%ObsTypeId), trim(this%name)
3127 ! call store_error(errmsg)
3128 ! end if
3129 ! end if
3130 ! end do
3131 ! !
3132 ! ! -- write summary of error messages
3133 ! if (count_errors() > 0) then
3134 ! call store_error_unit(this%inobs)
3135 ! end if
3136 ! !
3137 ! ! -- Return
3138 ! return
3139 ! end subroutine swf_gwf_rp_obs
3140 
3141 ! !> @ brief Final processing
3142 ! !!
3143 ! !! Conduct any final processing
3144 ! !<
3145 ! subroutine swf_gwf_fp(this)
3146 ! ! -- dummy
3147 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3148 ! !
3149 ! ! -- Return
3150 ! return
3151 ! end subroutine swf_gwf_fp
3152 
3153 ! !> @ brief Calculate flow
3154 ! !!
3155 ! !! Calculate the flow for the specified exchange and node numbers
3156 ! !<
3157 ! function qcalc(this, iexg, n1, n2)
3158 ! ! -- return
3159 ! real(DP) :: qcalc
3160 ! ! -- dummy
3161 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3162 ! integer(I4B), intent(in) :: iexg
3163 ! integer(I4B), intent(in) :: n1
3164 ! integer(I4B), intent(in) :: n2
3165 ! ! -- local
3166 ! !
3167 ! ! -- Calculate flow between nodes in the two models
3168 ! qcalc = this%cond(iexg) * (this%gwfmodel2%x(n2) - this%swfmodel1%x(n1))
3169 ! !
3170 ! ! -- Return
3171 ! return
3172 ! end function qcalc
3173 
3174 ! !> @ brief Set symmetric flag
3175 ! !!
3176 ! !! Return flag indicating whether or not this exchange will cause the
3177 ! !! coefficient matrix to be asymmetric.
3178 ! !<
3179 ! function swf_gwf_get_iasym(this) result(iasym)
3180 ! ! -- dummy
3181 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3182 ! ! -- local
3183 ! integer(I4B) :: iasym
3184 ! !
3185 ! ! -- Start by setting iasym to zero
3186 ! iasym = 0
3187 ! !
3188 ! ! -- Groundwater flow
3189 ! if (this%inewton /= 0) iasym = 1
3190 ! !
3191 ! ! -- GNC
3192 ! if (this%ingnc > 0) then
3193 ! if (this%gnc%iasym /= 0) iasym = 1
3194 ! end if
3195 ! !
3196 ! ! -- Return
3197 ! return
3198 ! end function swf_gwf_get_iasym
3199 
3200 ! !> @brief Return true when this exchange provides matrix
3201 ! !! coefficients for solving @param model
3202 ! !<
3203 ! function swf_gwf_connects_model(this, model) result(is_connected)
3204 ! ! -- dummy
3205 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3206 ! class(BaseModelType), pointer, intent(in) :: model !< the model to which the exchange might hold a connection
3207 ! ! -- return
3208 ! logical(LGP) :: is_connected !< true, when connected
3209 ! !
3210 ! is_connected = .false.
3211 ! !
3212 ! ! only connected when model is GwfModelType of course
3213 ! select type (model)
3214 ! class is (GwfModelType)
3215 ! ! if (associated(this%swfmodel1, model)) then
3216 ! ! is_connected = .true.
3217 ! if (associated(this%gwfmodel2, model)) then
3218 ! is_connected = .true.
3219 ! end if
3220 ! class is (SwfModelType)
3221 ! if (associated(this%swfmodel1, model)) then
3222 ! is_connected = .true.
3223 ! end if
3224 ! end select
3225 ! !
3226 ! ! -- Return
3227 ! return
3228 ! end function swf_gwf_connects_model
3229 
3230 ! !> @brief Should interface model be used for this exchange
3231 ! !<
3232 ! function use_interface_model(this) result(use_im)
3233 ! ! -- dummy
3234 ! class(SwfGwfExchangeType) :: this !< SwfGwfExchangeType
3235 ! ! -- return
3236 ! logical(LGP) :: use_im !< true when interface model should be used
3237 ! !
3238 ! use_im = this%DisConnExchangeType%use_interface_model()
3239 ! use_im = use_im .or. (this%ixt3d > 0)
3240 ! !
3241 ! ! -- Return
3242 ! return
3243 ! end function
3244 
3245 ! !> @ brief Save simulated flow observations
3246 ! !!
3247 ! !! Save the simulated flows for each exchange
3248 ! !<
3249 ! subroutine swf_gwf_save_simvals(this)
3250 ! ! -- modules
3251 ! use SimModule, only: store_error, store_error_unit
3252 ! use SimVariablesModule, only: errmsg
3253 ! use ConstantsModule, only: DZERO
3254 ! use ObserveModule, only: ObserveType
3255 ! ! -- dummy
3256 ! class(SwfGwfExchangeType), intent(inout) :: this
3257 ! ! -- local
3258 ! integer(I4B) :: i
3259 ! integer(I4B) :: j
3260 ! integer(I4B) :: n1
3261 ! integer(I4B) :: n2
3262 ! integer(I4B) :: iexg
3263 ! real(DP) :: v
3264 ! type(ObserveType), pointer :: obsrv => null()
3265 ! !
3266 ! ! -- Write simulated values for all gwf-gwf observations
3267 ! if (this%obs%npakobs > 0) then
3268 ! call this%obs%obs_bd_clear()
3269 ! do i = 1, this%obs%npakobs
3270 ! obsrv => this%obs%pakobs(i)%obsrv
3271 ! do j = 1, obsrv%indxbnds_count
3272 ! iexg = obsrv%indxbnds(j)
3273 ! v = DZERO
3274 ! select case (obsrv%ObsTypeId)
3275 ! case ('FLOW-JA-FACE')
3276 ! n1 = this%nodem1(iexg)
3277 ! n2 = this%nodem2(iexg)
3278 ! v = this%simvals(iexg)
3279 ! case default
3280 ! errmsg = 'Unrecognized observation type: '// &
3281 ! trim(obsrv%ObsTypeId)
3282 ! call store_error(errmsg)
3283 ! call store_error_unit(this%inobs)
3284 ! end select
3285 ! call this%obs%SaveOneSimval(obsrv, v)
3286 ! end do
3287 ! end do
3288 ! end if
3289 ! !
3290 ! ! -- Return
3291 ! return
3292 ! end subroutine swf_gwf_save_simvals
3293 
3294 ! !> @ brief Obs ID processor
3295 ! !!
3296 ! !! Process observations for this exchange
3297 ! !<
3298 ! subroutine swf_gwf_process_obsID(obsrv, dis, inunitobs, iout)
3299 ! ! -- modules
3300 ! use ConstantsModule, only: LINELENGTH
3301 ! use InputOutputModule, only: urword
3302 ! use ObserveModule, only: ObserveType
3303 ! use BaseDisModule, only: DisBaseType
3304 ! ! -- dummy
3305 ! type(ObserveType), intent(inout) :: obsrv
3306 ! class(DisBaseType), intent(in) :: dis
3307 ! integer(I4B), intent(in) :: inunitobs
3308 ! integer(I4B), intent(in) :: iout
3309 ! ! -- local
3310 ! integer(I4B) :: n, iexg, istat
3311 ! integer(I4B) :: icol, istart, istop
3312 ! real(DP) :: r
3313 ! character(len=LINELENGTH) :: string
3314 ! !
3315 ! string = obsrv%IDstring
3316 ! icol = 1
3317 ! ! -- get exchange index
3318 ! call urword(string, icol, istart, istop, 1, n, r, iout, inunitobs)
3319 ! read (string(istart:istop), '(i10)', iostat=istat) iexg
3320 ! if (istat == 0) then
3321 ! obsrv%intPak1 = iexg
3322 ! else
3323 ! ! Integer can't be read from string; it's presumed to be an exchange
3324 ! ! boundary name (already converted to uppercase)
3325 ! obsrv%FeatureName = trim(adjustl(string))
3326 ! ! -- Observation may require summing rates from multiple exchange
3327 ! ! boundaries, so assign intPak1 as a value that indicates observation
3328 ! ! is for a named exchange boundary or group of exchange boundaries.
3329 ! obsrv%intPak1 = NAMEDBOUNDFLAG
3330 ! end if
3331 ! !
3332 ! ! -- Return
3333 ! return
3334 ! end subroutine swf_gwf_process_obsID
3335 
3336 ! !> @ brief Cast polymorphic object as exchange
3337 ! !!
3338 ! !! Cast polymorphic object as exchange
3339 ! !<
3340 ! function CastAsSwfGwfExchange(obj) result(res)
3341 ! implicit none
3342 ! ! -- dummy
3343 ! class(*), pointer, intent(inout) :: obj
3344 ! ! -- return
3345 ! class(SwfGwfExchangeType), pointer :: res
3346 ! !
3347 ! res => null()
3348 ! if (.not. associated(obj)) return
3349 ! !
3350 ! select type (obj)
3351 ! class is (SwfGwfExchangeType)
3352 ! res => obj
3353 ! end select
3354 ! !
3355 ! ! -- Return
3356 ! return
3357 ! end function CastAsSwfGwfExchange
3358 
3359 ! !> @ brief Get exchange from list
3360 ! !!
3361 ! !! Return an exchange from the list for specified index
3362 ! !<
3363 ! function GetSwfGwfExchangeFromList(list, idx) result(res)
3364 ! implicit none
3365 ! ! -- dummy
3366 ! type(ListType), intent(inout) :: list
3367 ! integer(I4B), intent(in) :: idx
3368 ! ! -- return
3369 ! class(SwfGwfExchangeType), pointer :: res
3370 ! ! -- local
3371 ! class(*), pointer :: obj
3372 ! !
3373 ! obj => list%GetItem(idx)
3374 ! res => CastAsSwfGwfExchange(obj)
3375 ! !
3376 ! ! -- Return
3377 ! return
3378 ! end function GetSwfGwfExchangeFromList
3379 
3380 ! end module SwfGwfExchangeModule
3381 
subroutine, public addbaseexchangetolist(list, exchange)
Add the exchange object (BaseExchangeType) to a list.
class(basemodeltype) function, pointer, public getbasemodelfromlist(list, idx)
Definition: BaseModel.f90:172
This module contains block parser methods.
Definition: BlockParser.f90:7
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
Definition: Budget.f90:664
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:44
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:22
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:108
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:64
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:36
integer(i4b) function, public get_node(ilay, irow, icol, nlay, nrow, ncol)
Get node number, given layer, row, and column indices for a structured grid. If any argument is inval...
Definition: GeomUtil.f90:81
Definition: gwf.f90:1
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
type(listtype), public basemodellist
Definition: mf6lists.f90:16
type(listtype), public baseexchangelist
Definition: mf6lists.f90:25
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains the derived types ObserveType and ObsDataType.
Definition: Observe.f90:15
This module contains the derived type ObsType.
Definition: Obs.f90:127
subroutine, public obs_cr(obs, inobs)
@ brief Create a new ObsType object
Definition: Obs.f90:225
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:203
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:168
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
integer(i4b), dimension(:), allocatable model_loc_idx
equals the local index into the basemodel list (-1 when not available)
integer(i4b) iout
file unit number for simulation output
This module contains the SourceCommonModule.
Definition: SourceCommon.f90:7
logical(lgp) function, public filein_fname(filename, tagname, input_mempath, input_fname)
enforce and set a single input filename provided via FILEIN keyword
This module contains the SwfGwfExchangeModule Module.
Definition: exg-swfgwf.f90:7
integer(i4b) function noder(this, model, cellid, iout)
Definition: exg-swfgwf.f90:492
subroutine swf_gwf_df(this)
@ brief Define SWF GWF exchange
Definition: exg-swfgwf.f90:180
character(len=20) function cellstr(this, model, cellid, iout)
Definition: exg-swfgwf.f90:522
subroutine swf_gwf_mc(this, matrix_sln)
@ brief Map connections
Definition: exg-swfgwf.f90:255
real(dp) function qcalc(this, iexg, n1, n2)
@ brief Calculate flow
Definition: exg-swfgwf.f90:688
subroutine swf_gwf_fc(this, kiter, matrix_sln, rhs_sln, inwtflag)
@ brief Fill coefficients
Definition: exg-swfgwf.f90:282
subroutine swf_gwf_ac(this, sparse)
@ brief Add connections
Definition: exg-swfgwf.f90:230
subroutine swf_gwf_cq(this, icnvg, isuppress_output, isolnid)
@ brief Calculate flow
Definition: exg-swfgwf.f90:313
subroutine source_options(this, iout)
@ brief Source options
Definition: exg-swfgwf.f90:415
subroutine swf_gwf_save_simvals(this)
@ brief Save simulated flow observations
subroutine swf_gwf_add_to_flowja(this)
Add exchange flow to each model flowja diagonal position so that residual is calculated correctly.
Definition: exg-swfgwf.f90:708
subroutine swf_gwf_ot(this)
@ brief Output
subroutine allocate_scalars(this)
@ brief Allocate scalars
Definition: exg-swfgwf.f90:371
subroutine swf_gwf_da(this)
@ brief Deallocate
Definition: exg-swfgwf.f90:338
subroutine swf_gwf_bd(this, icnvg, isuppress_output, isolnid)
@ brief Budget
Definition: exg-swfgwf.f90:747
logical(lgp) function swf_gwf_connects_model(this, model)
Should return true when the exchange should be added to the solution where the model resides.
subroutine swf_gwf_bdsav(this)
@ brief Budget save
Definition: exg-swfgwf.f90:858
subroutine swf_gwf_calc_simvals(this)
Calculate flow rates for the exchanges and store them in a member array.
Definition: exg-swfgwf.f90:657
subroutine, public swfgwf_cr(filename, name, id, m1_id, m2_id, input_mempath)
@ brief Create SWF GWF exchange
Definition: exg-swfgwf.f90:97
subroutine allocate_arrays(this)
Allocate array data, using the number of connected nodes.
Definition: exg-swfgwf.f90:396
subroutine source_dimensions(this, iout)
Source dimension from input context.
Definition: exg-swfgwf.f90:465
subroutine swf_gwf_chd_bd(this)
@ brief swf-gwf-chd-bd
Definition: exg-swfgwf.f90:793
subroutine source_data(this, iout)
Source exchange data from input context.
Definition: exg-swfgwf.f90:555
Stream Network Flow (SWF) Module.
Definition: swf.f90:38
subroutine, public table_cr(this, name, title)
Definition: Table.f90:85
Highest level model type. All models extend this parent type.
Definition: BaseModel.f90:13
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23