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

Functions/Subroutines

logical function, public between (x, a, b)
 Check if a value is between two other values (inclusive). More...
 
logical function, public point_in_polygon (x, y, poly)
 Check if a point is within a polygon. More...
 
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 invalid return -1. More...
 
subroutine, public get_ijk (nodenumber, nrow, ncol, nlay, irow, icol, ilay)
 Get row, column and layer indices from node number and grid dimensions. If nodenumber is invalid, irow, icol, and ilay are -1. More...
 
subroutine, public get_jk (nodenumber, ncpl, nlay, icpl, ilay)
 Get layer index and within-layer node index from node number and grid dimensions. If nodenumber is invalid, icpl and ilay are -1. More...
 
pure real(dp) function, dimension(2), public skew (v, s, invert)
 Skew a 2D vector along the x-axis. More...
 
subroutine, public transform (xin, yin, zin, xout, yout, zout, xorigin, yorigin, zorigin, sinrot, cosrot, invert)
 Apply a 3D translation and optional 2D rotation to coordinates. More...
 
subroutine, public compose (xorigin, yorigin, zorigin, sinrot, cosrot, xorigin_new, yorigin_new, zorigin_new, sinrot_new, cosrot_new, invert)
 Apply a 3D translation and 2D rotation to an existing transformation. More...
 
subroutine defaults (xorigin, yorigin, zorigin, sinrot, cosrot, invert, translate, rotate, xorigin_opt, yorigin_opt, zorigin_opt, sinrot_opt, cosrot_opt, invert_opt)
 Process arguments and set defaults. Internal use only. More...
 

Function/Subroutine Documentation

◆ between()

logical function, public geomutilmodule::between ( real(dp), intent(in)  x,
real(dp), intent(in)  a,
real(dp), intent(in)  b 
)

Definition at line 13 of file GeomUtil.f90.

14  real(DP), intent(in) :: x, a, b
15  between = ((x >= a .and. x <= b) .or. (x <= a .and. x >= b))
Here is the caller graph for this function:

◆ compose()

subroutine, public geomutilmodule::compose ( real(dp)  xorigin,
real(dp)  yorigin,
real(dp)  zorigin,
real(dp)  sinrot,
real(dp)  cosrot,
real(dp), optional  xorigin_new,
real(dp), optional  yorigin_new,
real(dp), optional  zorigin_new,
real(dp), optional  sinrot_new,
real(dp), optional  cosrot_new,
logical(lgp), optional  invert 
)
Parameters
zoriginorigin coordinates (original)
cosrotsine and cosine of rotation (original)
zorigin_neworigin coordinates (new)
cosrot_newsine and cosine of rotation (new)
invertwhether to invert

Definition at line 235 of file GeomUtil.f90.

240  ! -- dummy
241  real(DP) :: xorigin, yorigin, zorigin !< origin coordinates (original)
242  real(DP) :: sinrot, cosrot !< sine and cosine of rotation (original)
243  real(DP), optional :: xorigin_new, yorigin_new, zorigin_new !< origin coordinates (new)
244  real(DP), optional :: sinrot_new, cosrot_new !< sine and cosine of rotation (new)
245  logical(LGP), optional :: invert !< whether to invert
246  ! -- local
247  logical(LGP) :: ltranslate, lrotate, linvert
248  real(DP) :: xorigin_add, yorigin_add, zorigin_add
249  real(DP) :: sinrot_add, cosrot_add
250  real(DP) :: x0, y0, z0, s0, c0
251 
252  ! -- Process option arguments and set defaults and flags
253  call defaults(xorigin_add, yorigin_add, zorigin_add, &
254  sinrot_add, cosrot_add, linvert, &
255  ltranslate, lrotate, &
256  xorigin_new, yorigin_new, zorigin_new, &
257  sinrot_new, cosrot_new, invert)
258 
259  ! -- Copy existing transformation into working copy
260  x0 = xorigin
261  y0 = yorigin
262  z0 = zorigin
263  s0 = sinrot
264  c0 = cosrot
265 
266  ! -- Modify transformation
267  if (.not. linvert) then
268  ! -- Apply additional transformation to existing transformation
269  if (ltranslate) then
270  ! -- Calculate modified origin, XOrigin + R^T XOrigin_add, where
271  ! -- XOrigin and XOrigin_add are the existing and additional origin
272  ! -- vectors, respectively, and R^T is the transpose of the existing
273  ! -- rotation matrix
274  call transform(xorigin_add, yorigin_add, zorigin_add, &
275  xorigin, yorigin, zorigin, &
276  x0, y0, z0, s0, c0, .true.)
277  end if
278  if (lrotate) then
279  ! -- Calculate modified rotation matrix (represented by sinrot
280  ! -- and cosrot) as R_add R, where R and R_add are the existing
281  ! -- and additional rotation matrices, respectively
282  sinrot = cosrot_add * s0 + sinrot_add * c0
283  cosrot = cosrot_add * c0 - sinrot_add * s0
284  end if
285  else
286  ! -- Apply inverse of additional transformation to existing transformation
287  !
288  ! -- Calculate modified origin, R^T (XOrigin + R_add XOrigin_add), where
289  ! -- XOrigin and XOrigin_add are the existing and additional origin
290  ! -- vectors, respectively, R^T is the transpose of the existing rotation
291  ! -- matrix, and R_add is the additional rotation matrix
292  if (ltranslate) then
293  call transform(-xorigin_add, -yorigin_add, zorigin_add, &
294  x0, y0, z0, xorigin, yorigin, zorigin, &
295  -sinrot_add, cosrot_add, .true.)
296  end if
297  xorigin = c0 * x0 - s0 * y0
298  yorigin = s0 * x0 + c0 * y0
299  zorigin = z0
300  if (lrotate) then
301  ! -- Calculate modified rotation matrix (represented by sinrot
302  ! -- and cosrot) as R_add^T R, where R and R_add^T are the existing
303  ! -- rotation matrix and the transpose of the additional rotation
304  ! -- matrix, respectively
305  sinrot = cosrot_add * s0 - sinrot_add * c0
306  cosrot = cosrot_add * c0 + sinrot_add * s0
307  end if
308  end if
Here is the call graph for this function:
Here is the caller graph for this function:

◆ defaults()

subroutine geomutilmodule::defaults ( real(dp)  xorigin,
real(dp)  yorigin,
real(dp)  zorigin,
real(dp)  sinrot,
real(dp)  cosrot,
logical(lgp)  invert,
logical(lgp)  translate,
logical(lgp)  rotate,
real(dp), optional  xorigin_opt,
real(dp), optional  yorigin_opt,
real(dp), optional  zorigin_opt,
real(dp), optional  sinrot_opt,
real(dp), optional  cosrot_opt,
logical(lgp), optional  invert_opt 
)
private

Definition at line 312 of file GeomUtil.f90.

317  ! -- dummy
318  real(DP) :: xorigin, yorigin, zorigin
319  real(DP) :: sinrot, cosrot
320  logical(LGP) :: invert, translate, rotate
321  real(DP), optional :: xorigin_opt, yorigin_opt, zorigin_opt
322  real(DP), optional :: sinrot_opt, cosrot_opt
323  logical(LGP), optional :: invert_opt
324 
325  translate = .false.
326  xorigin = dzero
327  if (present(xorigin_opt)) then
328  xorigin = xorigin_opt
329  translate = .true.
330  end if
331  yorigin = dzero
332  if (present(yorigin_opt)) then
333  yorigin = yorigin_opt
334  translate = .true.
335  end if
336  zorigin = dzero
337  if (present(zorigin_opt)) then
338  zorigin = zorigin_opt
339  translate = .true.
340  end if
341  rotate = .false.
342  sinrot = dzero
343  cosrot = done
344  if (present(sinrot_opt)) then
345  sinrot = sinrot_opt
346  if (present(cosrot_opt)) then
347  cosrot = cosrot_opt
348  else
349  ! -- If sinrot_opt is specified but cosrot_opt is not,
350  ! -- default to corresponding non-negative cosrot_add
351  cosrot = dsqrt(done - sinrot * sinrot)
352  end if
353  rotate = .true.
354  else if (present(cosrot_opt)) then
355  cosrot = cosrot_opt
356  ! -- cosrot_opt is specified but sinrot_opt is not, so
357  ! -- default to corresponding non-negative sinrot_add
358  sinrot = dsqrt(done - cosrot * cosrot)
359  rotate = .true.
360  end if
361  invert = .false.
362  if (present(invert_opt)) invert = invert_opt
Here is the caller graph for this function:

◆ get_ijk()

subroutine, public geomutilmodule::get_ijk ( integer(i4b), intent(in)  nodenumber,
integer(i4b), intent(in)  nrow,
integer(i4b), intent(in)  ncol,
integer(i4b), intent(in)  nlay,
integer(i4b), intent(out)  irow,
integer(i4b), intent(out)  icol,
integer(i4b), intent(out)  ilay 
)

Definition at line 96 of file GeomUtil.f90.

97  ! -- dummy variables
98  integer(I4B), intent(in) :: nodenumber
99  integer(I4B), intent(in) :: nrow
100  integer(I4B), intent(in) :: ncol
101  integer(I4B), intent(in) :: nlay
102  integer(I4B), intent(out) :: irow
103  integer(I4B), intent(out) :: icol
104  integer(I4B), intent(out) :: ilay
105  ! -- local variables
106  integer(I4B) :: nodes
107  integer(I4B) :: ij
108 
109  nodes = nlay * nrow * ncol
110  if (nodenumber < 1 .or. nodenumber > nodes) then
111  irow = -1
112  icol = -1
113  ilay = -1
114  else
115  ilay = (nodenumber - 1) / (ncol * nrow) + 1
116  ij = nodenumber - (ilay - 1) * ncol * nrow
117  irow = (ij - 1) / ncol + 1
118  icol = ij - (irow - 1) * ncol
119  end if
Here is the caller graph for this function:

◆ get_jk()

subroutine, public geomutilmodule::get_jk ( integer(i4b), intent(in)  nodenumber,
integer(i4b), intent(in)  ncpl,
integer(i4b), intent(in)  nlay,
integer(i4b), intent(out)  icpl,
integer(i4b), intent(out)  ilay 
)

Definition at line 124 of file GeomUtil.f90.

125  ! -- dummy variables
126  integer(I4B), intent(in) :: nodenumber
127  integer(I4B), intent(in) :: ncpl
128  integer(I4B), intent(in) :: nlay
129  integer(I4B), intent(out) :: icpl
130  integer(I4B), intent(out) :: ilay
131  ! -- local variables
132  integer(I4B) :: nodes
133 
134  nodes = ncpl * nlay
135  if (nodenumber < 1 .or. nodenumber > nodes) then
136  icpl = -1
137  ilay = -1
138  else
139  ilay = (nodenumber - 1) / ncpl + 1
140  icpl = nodenumber - (ilay - 1) * ncpl
141  end if
Here is the caller graph for this function:

◆ get_node()

integer(i4b) function, public geomutilmodule::get_node ( integer(i4b), intent(in)  ilay,
integer(i4b), intent(in)  irow,
integer(i4b), intent(in)  icol,
integer(i4b), intent(in)  nlay,
integer(i4b), intent(in)  nrow,
integer(i4b), intent(in)  ncol 
)

Definition at line 79 of file GeomUtil.f90.

80  integer(I4B), intent(in) :: ilay, irow, icol, nlay, nrow, ncol
81  integer(I4B) :: get_node
82 
83  if (nlay > 0 .and. nrow > 0 .and. ncol > 0 .and. &
84  ilay > 0 .and. ilay <= nlay .and. &
85  irow > 0 .and. irow <= nrow .and. &
86  icol > 0 .and. icol <= ncol) then
87  get_node = &
88  icol + ncol * (irow - 1) + (ilay - 1) * nrow * ncol
89  else
90  get_node = -1
91  end if
Here is the caller graph for this function:

◆ point_in_polygon()

logical function, public geomutilmodule::point_in_polygon ( real(dp), intent(in)  x,
real(dp), intent(in)  y,
real(dp), dimension(:, :), intent(in), allocatable  poly 
)

Vertices and edge points are considered in the polygon. Adapted from https://stackoverflow.com/a/63436180/6514033,

Parameters
[in]xx point coordinate
[in]yy point coordinate
[in]polypolygon vertices (column-major indexing)

Definition at line 23 of file GeomUtil.f90.

24  ! dummy
25  real(DP), intent(in) :: x !< x point coordinate
26  real(DP), intent(in) :: y !< y point coordinate
27  real(DP), allocatable, intent(in) :: poly(:, :) !< polygon vertices (column-major indexing)
28  ! local
29  integer(I4B) :: i, ii, num_verts
30  real(DP) :: xa, xb, ya, yb, c = 0.0_dp
31 
32  point_in_polygon = .false.
33  num_verts = size(poly, 2)
34  xa = poly(1, num_verts)
35  ya = poly(2, num_verts)
36 
37  do i = 0, num_verts - 1
38  ii = mod(i, num_verts) + 1
39  xb = poly(1, ii)
40  yb = poly(2, ii)
41 
42  if ((x == xa .and. y == ya) .or. &
43  (x == xb .and. y == yb)) then
44  ! on vertex
45  point_in_polygon = .true.
46  exit
47  else if (ya == yb .and. &
48  y == ya .and. &
49  between(x, xa, xb)) then
50  ! on horizontal edge
51  point_in_polygon = .true.
52  exit
53  else if (between(y, ya, yb)) then
54  if ((y == ya .and. yb >= ya) .or. &
55  (y == yb .and. ya >= yb)) then
56  xa = xb
57  ya = yb
58  cycle
59  end if
60  ! cross product
61  c = (xa - x) * (yb - y) - (xb - x) * (ya - y)
62  if (c == 0.0_dp) then
63  ! on edge
64  point_in_polygon = .true.
65  exit
66  else if ((ya < yb) .eqv. (c > 0)) then
67  ! ray intersection
68  point_in_polygon = .not. point_in_polygon
69  end if
70  end if
71 
72  xa = xb
73  ya = yb
74  end do
Here is the call graph for this function:
Here is the caller graph for this function:

◆ skew()

pure real(dp) function, dimension(2), public geomutilmodule::skew ( real(dp), dimension(2), intent(in)  v,
real(dp), dimension(3), intent(in)  s,
logical(lgp), intent(in), optional  invert 
)
Parameters
[in]vvector
[in]sskew matrix entries (top left, top right, bottom right)

Definition at line 145 of file GeomUtil.f90.

146  ! -- dummy
147  real(DP), intent(in) :: v(2) !< vector
148  real(DP), intent(in) :: s(3) !< skew matrix entries (top left, top right, bottom right)
149  logical(LGP), intent(in), optional :: invert
150  real(DP) :: res(2)
151  ! -- local
152  logical(LGP) :: linvert
153  real(DP) :: sxx, sxy, syy
154 
155  ! -- process optional arguments
156  if (present(invert)) then
157  linvert = invert
158  else
159  linvert = .false.
160  end if
161 
162  sxx = s(1)
163  sxy = s(2)
164  syy = s(3)
165  if (.not. linvert) then
166  res(1) = sxx * v(1) + sxy * v(2)
167  res(2) = syy * v(2)
168  else
169  res(2) = v(2) / syy
170  res(1) = (v(1) - sxy * res(2)) / sxx
171  end if
Here is the caller graph for this function:

◆ transform()

subroutine, public geomutilmodule::transform ( real(dp)  xin,
real(dp)  yin,
real(dp)  zin,
real(dp)  xout,
real(dp)  yout,
real(dp)  zout,
real(dp), optional  xorigin,
real(dp), optional  yorigin,
real(dp), optional  zorigin,
real(dp), optional  sinrot,
real(dp), optional  cosrot,
logical(lgp), optional  invert 
)
Parameters
zininput coordinates
zoutoutput coordinates
zoriginorigin coordinates
cosrotsine and cosine of rotation
invertwhether to invert

Definition at line 175 of file GeomUtil.f90.

180  ! -- dummy
181  real(DP) :: xin, yin, zin !< input coordinates
182  real(DP) :: xout, yout, zout !< output coordinates
183  real(DP), optional :: xorigin, yorigin, zorigin !< origin coordinates
184  real(DP), optional :: sinrot, cosrot !< sine and cosine of rotation
185  logical(LGP), optional :: invert !< whether to invert
186  ! -- local
187  logical(LGP) :: ltranslate, lrotate, linvert
188  real(DP) :: x, y
189  real(DP) :: lxorigin, lyorigin, lzorigin
190  real(DP) :: lsinrot, lcosrot
191 
192  ! -- Process option arguments and set defaults and flags
193  call defaults(lxorigin, lyorigin, lzorigin, &
194  lsinrot, lcosrot, linvert, &
195  ltranslate, lrotate, &
196  xorigin, yorigin, zorigin, &
197  sinrot, cosrot, invert)
198 
199  ! -- Apply transformation or its inverse
200  if (.not. linvert) then
201  ! -- Apply transformation to coordinates
202  if (ltranslate) then
203  xout = xin - lxorigin
204  yout = yin - lyorigin
205  zout = zin - lzorigin
206  else
207  xout = lxorigin
208  yout = lyorigin
209  zout = lzorigin
210  end if
211  if (lrotate) then
212  x = xout
213  y = yout
214  xout = x * lcosrot + y * lsinrot
215  yout = -x * lsinrot + y * lcosrot
216  end if
217  else
218  ! -- Apply inverse of transformation to coordinates
219  if (lrotate) then
220  x = xin * lcosrot - yin * lsinrot
221  y = xin * lsinrot + yin * lcosrot
222  else
223  x = xin
224  y = yin
225  end if
226  if (ltranslate) then
227  xout = x + lxorigin
228  yout = y + lyorigin
229  zout = zin + lzorigin
230  end if
231  end if
Here is the call graph for this function:
Here is the caller graph for this function: