MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
vectorinterpolationmodule Module Reference

Functions/Subroutines

subroutine, public vector_interpolation_2d (dis, flowja, nedges, nodedge, propsedge, vcomp, vmag, flowareaja)
 Interpolate 2D vector components at cell center. More...
 

Function/Subroutine Documentation

◆ vector_interpolation_2d()

subroutine, public vectorinterpolationmodule::vector_interpolation_2d ( class(disbasetype), intent(in)  dis,
real(dp), dimension(:), intent(in)  flowja,
integer(i4b), intent(in), optional  nedges,
integer(i4b), dimension(:), intent(in), optional  nodedge,
real(dp), dimension(:, :), intent(in), optional  propsedge,
real(dp), dimension(:, :), intent(inout), optional  vcomp,
real(dp), dimension(:), intent(inout), optional  vmag,
real(dp), dimension(:), intent(in), optional  flowareaja 
)

Given a component of a vector on the edges of all cells, assumed to be normal to the edge, interpolate a 2d vector using an XT3D-like interpolation. Can be used to calculate a cell-center velocity given face flows. Routine can optionally divide the edge flow by area, if provided, to interpolate velocity, for example. Sign on flowja is assumed to be positive into the cell.

Routine requires that disconnection_vector() and disconnection_normal() are available.

Parameters
[in]disdiscretization package object
[in]flowjaflow across each face in model grid (size njas)
[in]nedgesnumber of external edges for which a flow is provided
[in]nodedgearray of node numbers that have edges
[in]propsedgeedge properties (Q, area, nx, ny, distance)
[in,out]vcompvector components: vx, vy, vz (nodes, 3)
[in,out]vmagvector magnitude (nodes)
[in]flowareajaflow area across each face in model grid

Definition at line 25 of file VectorInterpolation.f90.

27  ! modules
28  ! dummy
29  class(DisBaseType), intent(in) :: dis !< discretization package object
30  real(DP), intent(in), dimension(:) :: flowja !< flow across each face in model grid (size njas)
31  integer(I4B), intent(in), optional :: nedges !< number of external edges for which a flow is provided
32  integer(I4B), dimension(:), intent(in), optional :: nodedge !< array of node numbers that have edges
33  real(DP), dimension(:, :), intent(in), optional :: propsedge !< edge properties (Q, area, nx, ny, distance)
34  real(DP), dimension(:, :), intent(inout), optional :: vcomp !< vector components: vx, vy, vz (nodes, 3)
35  real(DP), dimension(:), intent(inout), optional :: vmag !< vector magnitude (nodes)
36  real(DP), intent(in), dimension(:), optional :: flowareaja !< flow area across each face in model grid
37  ! local
38  integer(I4B) :: n
39  integer(I4B) :: m
40  integer(I4B) :: ipos
41  integer(I4B) :: isympos
42  integer(I4B) :: ihc
43  integer(I4B) :: ic
44  integer(I4B) :: iz
45  integer(I4B) :: nc
46  real(DP) :: vx
47  real(DP) :: vy
48  real(DP) :: vz
49  real(DP) :: xn
50  real(DP) :: yn
51  real(DP) :: zn
52  real(DP) :: xc
53  real(DP) :: yc
54  real(DP) :: zc
55  real(DP) :: cl1
56  real(DP) :: cl2
57  real(DP) :: dltot
58  real(DP) :: ooclsum
59  real(DP) :: q
60  real(DP) :: dsumx
61  real(DP) :: dsumy
62  real(DP) :: dsumz
63  real(DP) :: denom
64  real(DP) :: area
65  real(DP) :: axy
66  real(DP) :: ayx
67  real(DP), allocatable, dimension(:) :: vi
68  real(DP), allocatable, dimension(:) :: di
69  real(DP), allocatable, dimension(:) :: viz
70  real(DP), allocatable, dimension(:) :: diz
71  real(DP), allocatable, dimension(:) :: nix
72  real(DP), allocatable, dimension(:) :: niy
73  real(DP), allocatable, dimension(:) :: wix
74  real(DP), allocatable, dimension(:) :: wiy
75  real(DP), allocatable, dimension(:) :: wiz
76  real(DP), allocatable, dimension(:) :: bix
77  real(DP), allocatable, dimension(:) :: biy
78  logical :: nozee = .true.
79  !
80  ! -- Ensure dis has necessary information
81  ! todo: do we need this? this needs to be done outside of this routine
82  ! if (this%icalcvelocity /= 0 .and. this%dis%con%ianglex == 0) then
83  ! call store_error('Error. ANGLDEGX not provided in '// &
84  ! 'discretization file. ANGLDEGX required for '// &
85  ! 'calculation of velocity.', terminate=.TRUE.)
86  ! end if
87  !
88  ! -- Find max number of connections and allocate weight arrays
89  nc = 0
90  do n = 1, dis%nodes
91  !
92  ! -- Count internal model connections
93  ic = dis%con%ia(n + 1) - dis%con%ia(n) - 1
94  !
95  ! -- Count edge connections
96  if (present(nedges)) then
97  do m = 1, nedges
98  if (nodedge(m) == n) then
99  ic = ic + 1
100  end if
101  end do
102  end if
103  !
104  ! -- Set max number of connections for any cell
105  if (ic > nc) nc = ic
106  end do
107  !
108  ! -- Allocate storage arrays needed for cell-centered calculation
109  allocate (vi(nc))
110  allocate (di(nc))
111  allocate (viz(nc))
112  allocate (diz(nc))
113  allocate (nix(nc))
114  allocate (niy(nc))
115  allocate (wix(nc))
116  allocate (wiy(nc))
117  allocate (wiz(nc))
118  allocate (bix(nc))
119  allocate (biy(nc))
120  !
121  ! -- Go through each cell and calculate specific discharge
122  do n = 1, dis%nodes
123  !
124  ! -- first calculate geometric properties for x and y directions and
125  ! the specific discharge at a face (vi)
126  ic = 0
127  iz = 0
128  vi(:) = dzero
129  di(:) = dzero
130  viz(:) = dzero
131  diz(:) = dzero
132  nix(:) = dzero
133  niy(:) = dzero
134  do ipos = dis%con%ia(n) + 1, dis%con%ia(n + 1) - 1
135  m = dis%con%ja(ipos)
136  isympos = dis%con%jas(ipos)
137  ihc = 1
138  ic = ic + 1
139 
140  ! Find the normal components (xn, yn, zn) for this connection
141  call dis%connection_normal(n, m, ihc, xn, yn, zn, ipos)
142 
143  ! Find the straight-line distance between n and m and put
144  ! in dltot
145  call dis%connection_vector(n, m, nozee, done, done, &
146  ihc, xc, yc, zc, dltot)
147 
148  ! Find the connection lengths, cl1 and cl2, adjusting for the
149  ! n, m symmetry
150  cl1 = dis%con%cl1(isympos)
151  cl2 = dis%con%cl2(isympos)
152  if (m < n) then
153  cl1 = dis%con%cl2(isympos)
154  cl2 = dis%con%cl1(isympos)
155  end if
156 
157  ! Set the normal components and distance for this connection
158  ooclsum = done / (cl1 + cl2)
159  nix(ic) = -xn
160  niy(ic) = -yn
161  di(ic) = dltot * cl1 * ooclsum
162 
163  ! Set vi to flow area and divide by area if present
164  q = flowja(isympos)
165  if (n < m) then
166  vi(ic) = q
167  else
168  vi(ic) = -q
169  end if
170  if (present(flowareaja)) then
171  area = flowareaja(isympos)
172  if (area > dzero) then
173  vi(ic) = vi(ic) / area
174  else
175  vi(ic) = dzero
176  end if
177  end if
178 
179  end do
180  !
181  ! -- Look through edge flows that may have been provided by an exchange
182  ! and incorporate them into the averaging arrays
183  if (present(nedges)) then
184  do m = 1, nedges
185  if (nodedge(m) == n) then
186  ic = ic + 1
187  nix(ic) = -propsedge(3, m)
188  niy(ic) = -propsedge(4, m)
189  di(ic) = propsedge(5, m)
190  vi(ic) = propsedge(1, m)
191  if (present(flowareaja)) then
192  area = propsedge(2, m)
193  if (area > dzero) then
194  vi(ic) = vi(ic) / area
195  else
196  vi(ic) = dzero
197  end if
198  end if
199  end if
200  end do
201  end if
202 
203  ! Set vz to zero
204  vz = dzero
205 
206  ! -- distance-based weighting
207  nc = ic
208  dsumx = dzero
209  dsumy = dzero
210  dsumz = dzero
211  do ic = 1, nc
212  wix(ic) = di(ic) * abs(nix(ic))
213  wiy(ic) = di(ic) * abs(niy(ic))
214  dsumx = dsumx + wix(ic)
215  dsumy = dsumy + wiy(ic)
216  end do
217  !
218  ! -- Finish computing omega weights. Add a tiny bit
219  ! to dsum so that the normalized omega weight later
220  ! evaluates to (essentially) 1 in the case of a single
221  ! relevant connection, avoiding 0/0.
222  dsumx = dsumx + dem10 * dsumx
223  dsumy = dsumy + dem10 * dsumy
224  do ic = 1, nc
225  wix(ic) = (dsumx - wix(ic)) * abs(nix(ic))
226  wiy(ic) = (dsumy - wiy(ic)) * abs(niy(ic))
227  end do
228  !
229  ! -- compute B weights
230  dsumx = dzero
231  dsumy = dzero
232  do ic = 1, nc
233  bix(ic) = wix(ic) * sign(done, nix(ic))
234  biy(ic) = wiy(ic) * sign(done, niy(ic))
235  dsumx = dsumx + wix(ic) * abs(nix(ic))
236  dsumy = dsumy + wiy(ic) * abs(niy(ic))
237  end do
238  if (dsumx > dzero) dsumx = done / dsumx
239  if (dsumy > dzero) dsumy = done / dsumy
240  axy = dzero
241  ayx = dzero
242  do ic = 1, nc
243  bix(ic) = bix(ic) * dsumx
244  biy(ic) = biy(ic) * dsumy
245  axy = axy + bix(ic) * niy(ic)
246  ayx = ayx + biy(ic) * nix(ic)
247  end do
248  !
249  ! -- Calculate vector components at cell center. The divide by zero checking
250  ! below is problematic for cells with only one flow, such as can happen
251  ! with triangular cells in corners. In this case, the resulting
252  ! cell velocity will be calculated as zero. The method should be
253  ! improved so that edge flows of zero are included in these
254  ! calculations. But this needs to be done with consideration for LGR
255  ! cases in which flows are submitted from an exchange.
256  vx = dzero
257  vy = dzero
258  do ic = 1, nc
259  vx = vx + (bix(ic) - axy * biy(ic)) * vi(ic)
260  vy = vy + (biy(ic) - ayx * bix(ic)) * vi(ic)
261  end do
262  denom = done - axy * ayx
263  if (denom /= dzero) then
264  vx = vx / denom
265  vy = vy / denom
266  end if
267 
268  ! Store velocity components
269  if (present(vcomp)) then
270  vcomp(1, n) = vx
271  vcomp(2, n) = vy
272  vcomp(3, n) = vz
273  end if
274 
275  ! Store velocity magnitude
276  if (present(vmag)) then
277  vmag(n) = sqrt(vx**2 + vy**2 + vz**2)
278  end if
279 
280  end do
281 
282  ! cleanup
283  deallocate (vi)
284  deallocate (di)
285  deallocate (nix)
286  deallocate (niy)
287  deallocate (wix)
288  deallocate (wiy)
289  deallocate (wiz)
290  deallocate (bix)
291  deallocate (biy)
292