MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
Mover.f90
Go to the documentation of this file.
1 !> @brief This module contains the MvrModule Module
2 !!
3 !! This module contains the code for the low-level MvrType
4 !! object.
5 !!
6 !<
7 module mvrmodule
8 
9  use kindmodule, only: dp, i4b, lgp
13  use simvariablesmodule, only: errmsg
15 
16  implicit none
17  private
18  public :: mvrtype
19 
20  character(len=12), dimension(4) :: mvrtypes = &
21  &[character(len=12) :: 'FACTOR', 'EXCESS', 'THRESHOLD', 'UPTO']
22 
23  !> @brief Derived type for MvrType
24  !!
25  !! This derived type contains information and methods for
26  !! moving water between packages.
27  !!
28  !<
29  type mvrtype
30  character(len=LENMEMPATH) :: mem_path_src = '' !< provider package name
31  character(len=LENMEMPATH) :: mem_path_tgt = '' !< receiver package name
32  integer(I4B), pointer :: irchnrsrc => null() !< provider reach number
33  integer(I4B) :: irchnrsrcmapped !< mapped provider reach number (currently for lake outlet)
34  integer(I4B), pointer :: irchnrtgt => null() !< receiver reach number
35  integer(I4B), pointer :: imvrtype => null() !< mover type (1, 2, 3, 4) corresponds to mvrtypes
36  real(dp), pointer :: value => null() !< factor or rate depending on mvrtype
37  logical(LGP) :: is_provider_active = .true.
38  logical(LGP) :: is_receiver_active = .true.
39  real(dp) :: qpactual = dzero !< rate provided to the receiver
40  real(dp) :: qavailable = dzero !< rate available at time of providing
41  real(dp), pointer :: qtformvr_ptr => null() !< pointer to total available flow (qtformvr)
42  real(dp), pointer :: qformvr_ptr => null() !< pointer to available flow after consumed (qformvr)
43  real(dp), pointer :: qtomvr_ptr => null() !< pointer to provider flow rate (qtomvr)
44  real(dp), pointer :: qfrommvr_ptr => null() !< pointer to receiver flow rate (qfrommvr)
45  contains
46  procedure :: set_values
47  procedure :: prepare
48  procedure :: echo
49  procedure :: advance
50  procedure :: update_provider
51  procedure :: update_receiver
52  procedure :: qrcalc
53  procedure :: writeflow
54  end type mvrtype
55 
56 contains
57 
58  !> @ brief Set values from input data
59  !!
60  !! Set values and pointers for mover object.
61  !!
62  !<
63  subroutine set_values(this, mname1, pname1, id1, mname2, pname2, &
64  id2, imvrtype, value)
66  class(mvrtype) :: this
67  character(len=*), intent(in) :: mname1
68  character(len=*), intent(in) :: pname1
69  integer(I4B), intent(in), target :: id1
70  character(len=*), intent(in) :: mname2
71  character(len=*), intent(in) :: pname2
72  integer(I4B), intent(in), target :: id2
73  integer(I4B), intent(in), target :: imvrtype
74  real(DP), intent(in), target :: value
75 
76  this%mem_path_src = create_mem_path(mname1, pname1)
77  this%iRchNrSrc => id1
78  this%mem_path_tgt = create_mem_path(mname2, pname2)
79  this%iRchNrTgt => id2
80  this%imvrtype => imvrtype
81  this%value => value
82 
83  ! to be set later
84  this%iRchNrSrcMapped = -1
85  end subroutine set_values
86 
87  !> @ brief Prepare object
88  !!
89  !! Set values and pointers for mover object.
90  !! pckMemPaths is an array of strings which are the memory paths for those
91  !! packages. They are composed of model names and package names. The mover
92  !! entries must be in pckMemPaths, or this routine will terminate with an error.
93  !<
94  subroutine prepare(this, inunit, pckMemPaths, pakmovers)
95  ! -- modules
97  ! -- dummy
98  class(mvrtype) :: this !< MvrType object
99  integer(I4B), intent(in) :: inunit !< input file unit number
100  character(len=LENMEMPATH), &
101  dimension(:), pointer, contiguous :: pckMemPaths !< array of strings
102  type(packagemovertype), dimension(:), pointer, contiguous :: pakmovers !< Array of package mover objects
103  ! -- local
104  real(DP), dimension(:), pointer, contiguous :: temp_ptr => null()
105  logical :: found
106  integer(I4B) :: i
107  integer(I4B) :: ipakloc1, ipakloc2
108  !
109  ! -- Check to make sure provider and receiver are not the same
110  if (this%mem_path_src == this%mem_path_tgt .and. &
111  this%iRchNrSrc == this%iRchNrTgt) then
112  call store_error('Provider and receiver are the same: '// &
113  trim(this%mem_path_src)//' : '//trim(this%mem_path_tgt))
114  call store_error_unit(inunit)
115  end if
116  !
117  ! -- Check to make sure pname1 and pname2 are both listed in pckMemPaths
118  ! pname1 is the provider package; pname2 is the receiver package
119  found = .false.
120  ipakloc1 = 0
121  do i = 1, size(pckmempaths)
122  if (this%mem_path_src == pckmempaths(i)) then
123  found = .true.
124  ipakloc1 = i
125  exit
126  end if
127  end do
128  if (.not. found) then
129  call store_error('Mover capability not activated in '//this%mem_path_src)
130  call store_error('Add "MOVER" keyword to package options block.')
131  end if
132  found = .false.
133  ipakloc2 = 0
134  do i = 1, size(pckmempaths)
135  if (this%mem_path_tgt == pckmempaths(i)) then
136  found = .true.
137  ipakloc2 = i
138  exit
139  end if
140  end do
141  if (.not. found) then
142  call store_error('Mover capability not activated in '//this%mem_path_tgt)
143  call store_error('Add "MOVER" keyword to package options block.')
144  end if
145  if (count_errors() > 0) then
146  call store_error_unit(inunit)
147  end if
148 
149  if (this%is_provider_active) then
150  !
151  ! -- Set pointer to QTOMVR array in the provider boundary package
152  temp_ptr => pakmovers(ipakloc1)%qtomvr
153  if (this%iRchNrSrc < 1 .or. this%iRchNrSrc > size(temp_ptr)) then
154  call store_error('Provider ID < 1 or greater than package size ')
155  write (errmsg, '(a,i0,a,i0)') 'Provider ID = ', this%iRchNrSrc, &
156  '; Package size = ', size(temp_ptr)
157  call store_error(trim(errmsg))
158  call store_error_unit(inunit)
159  end if
160  this%qtomvr_ptr => temp_ptr(this%iRchNrSrc)
161  !
162  ! -- Set pointer to QFORMVR array in the provider boundary package
163  temp_ptr => pakmovers(ipakloc1)%qformvr
164  this%qformvr_ptr => temp_ptr(this%iRchNrSrc)
165  !
166  ! -- Set pointer to QTFORMVR array in the provider boundary package
167  temp_ptr => pakmovers(ipakloc1)%qtformvr
168  this%qtformvr_ptr => temp_ptr(this%iRchNrSrc)
169  end if
170 
171  if (this%is_receiver_active) then
172  !
173  ! -- Set pointer to QFROMMVR array in the receiver boundary package
174  temp_ptr => pakmovers(ipakloc2)%qfrommvr
175  if (this%iRchNrTgt < 1 .or. this%iRchNrTgt > size(temp_ptr)) then
176  call store_error('Receiver ID < 1 or greater than package size ')
177  write (errmsg, '(a,i0,a,i0)') 'Receiver ID = ', this%iRchNrTgt, &
178  '; package size = ', size(temp_ptr)
179  call store_error(trim(errmsg))
180  call store_error_unit(inunit)
181  end if
182  this%qfrommvr_ptr => temp_ptr(this%iRchNrTgt)
183  end if
184  end subroutine prepare
185 
186  !> @ brief Echo data to list file
187  !!
188  !! Write mover values to output file.
189  !!
190  !<
191  subroutine echo(this, iout)
192  ! -- modules
193  ! -- dummy
194  class(mvrtype) :: this !< MvrType
195  integer(I4B), intent(in) :: iout !< unit number for output file
196  ! -- local
197  !
198  write (iout, '(4x, a, a, a, i0)') 'FROM PACKAGE: ', trim(this%mem_path_src), &
199  ' FROM ID: ', this%iRchNrSrc
200  write (iout, '(4x, a, a, a, i0)') 'TO PACKAGE: ', trim(this%mem_path_tgt), &
201  ' TO ID: ', this%iRchNrTgt
202  write (iout, '(4x, a, a, a, 1pg15.6,/)') 'MOVER TYPE: ', &
203  trim(mvrtypes(this%imvrtype)), ' ', this%value
204  end subroutine echo
205 
206  !> @ brief Advance
207  !!
208  !! Advance mover object. Does nothing now.
209  !!
210  !<
211  subroutine advance(this)
212  ! -- modules
213  ! -- dummy
214  class(mvrtype) :: this
215  ! -- local
216  end subroutine advance
217 
218  !> @ brief Formulate coefficients
219  !!
220  !! Make mover calculations for provider.
221  !!
222  !<
223  subroutine update_provider(this)
224  ! -- modules
225  ! -- dummy
226  class(mvrtype) :: this !< MvrType
227  ! -- local
228  real(DP) :: qavailable, qtanew, qpactual
229  !
230  ! -- Set qa and this%qavailable equal to available water in package (qtomvr)
231  qavailable = this%qformvr_ptr
232  qtanew = this%qtformvr_ptr
233  this%qavailable = qavailable
234  !
235  ! -- Using the mover rules, calculate how much of the available water will
236  ! be provided from the mover to the receiver.
237  qpactual = this%qrcalc(qavailable, qtanew)
238  !
239  ! -- Store qpactual
240  this%qpactual = qpactual
241  !
242  ! -- Add the calculated qpactual term directly into the provider package
243  ! qtomvr array.
244  this%qtomvr_ptr = this%qtomvr_ptr + qpactual
245  !
246  ! -- Reduce the amount of water that is available in the provider package
247  ! qformvr array.
248  this%qformvr_ptr = this%qformvr_ptr - qpactual
249  end subroutine update_provider
250 
251  !> @ brief Formulate coefficients
252  !!
253  !! Make mover calculations for receiver.
254  !!
255  !<
256  subroutine update_receiver(this)
257  class(mvrtype) :: this !< MvrType
258  ! -- Add the calculated qpactual term directly into the receiver package
259  ! qfrommvr array.
260  this%qfrommvr_ptr = this%qfrommvr_ptr + this%qpactual
261  end subroutine update_receiver
262 
263  !> @ brief Flow to receiver
264  !!
265  !! Calculate the rate of water provided to receiver.
266  !!
267  !<
268  function qrcalc(this, qa, qta) result(qr)
269  ! -- modules
270  ! -- return
271  real(dp) :: qr
272  ! -- dummy
273  class(mvrtype) :: this !< MvrType
274  real(dp), intent(in) :: qa !< actual flow
275  real(dp), intent(in) :: qta !< total available flow
276  ! -- local
277  ! -- Using the mover rules, calculate how much of the available water will
278  ! go to the receiver.
279  qr = dzero
280  ! -- Calculate qr
281  select case (this%imvrtype)
282  case (1)
283  ! -- FACTOR uses total available to make calculation, and then
284  ! limits qr by consumed available
285  if (qta > dzero) qr = qta * this%value
286  qr = min(qr, qa)
287  case (2)
288  ! -- EXCESS
289  if (qa > this%value) then
290  qr = qa - this%value
291  else
292  qr = dzero
293  end if
294  case (3)
295  ! -- THRESHOLD
296  if (this%value > qa) then
297  qr = dzero
298  else
299  qr = this%value
300  end if
301  case (4)
302  ! -- UPTO
303  if (qa > this%value) then
304  qr = this%value
305  else
306  qr = qa
307  end if
308  end select
309  end function qrcalc
310 
311  !> @ brief Write flow
312  !!
313  !! Write a line of output for this mover object.
314  !!
315  !<
316  subroutine writeflow(this, iout)
317  ! -- modules
318  ! -- dummy
319  class(mvrtype) :: this !< MvrType
320  integer(I4B), intent(in) :: iout !< output file unit number
321  ! -- local
322  character(len=*), parameter :: fmt = &
323  "(1x, a, ' ID ', i0, ' AVAILABLE ', 1(1pg15.6), &
324  &' PROVIDED ', 1(1pg15.6), ' TO ', a, ' ID ', i0)"
325  !
326  write (iout, fmt) trim(this%mem_path_src), this%iRchNrSrc, this%qavailable, &
327  this%qpactual, trim(this%mem_path_tgt), this%iRchNrTgt
328  end subroutine writeflow
329 
330 end module mvrmodule
331 
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition: Constants.f90:22
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition: Constants.f90:35
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:36
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains the MvrModule Module.
Definition: Mover.f90:7
subroutine prepare(this, inunit, pckMemPaths, pakmovers)
@ brief Prepare object
Definition: Mover.f90:95
subroutine echo(this, iout)
@ brief Echo data to list file
Definition: Mover.f90:192
character(len=12), dimension(4) mvrtypes
Definition: Mover.f90:20
subroutine update_receiver(this)
@ brief Formulate coefficients
Definition: Mover.f90:257
real(dp) function qrcalc(this, qa, qta)
@ brief Flow to receiver
Definition: Mover.f90:269
subroutine set_values(this, mname1, pname1, id1, mname2, pname2, id2, imvrtype, value)
@ brief Set values from input data
Definition: Mover.f90:65
subroutine writeflow(this, iout)
@ brief Write flow
Definition: Mover.f90:317
subroutine update_provider(this)
@ brief Formulate coefficients
Definition: Mover.f90:224
subroutine advance(this)
@ brief Advance
Definition: Mover.f90:212
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_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
Derived type for MvrType.
Definition: Mover.f90:29