17 real(dp),
intent(in) :: x, a, b
18 between = ((x >= a .and. x <= b) .or. (x <= a .and. x >= b))
32 real(dp),
intent(in) :: x
33 real(dp),
intent(in) :: y
34 real(dp),
allocatable,
intent(in) :: poly(:, :)
35 real(dp),
intent(in),
optional :: tol
37 integer(I4B) :: i, ii, num_verts
38 real(dp) :: xa, xb, ya, yb, c
42 if (
present(tol)) ltol = tol
45 num_verts =
size(poly, 2)
46 xa = poly(1, num_verts)
47 ya = poly(2, num_verts)
49 do i = 0, num_verts - 1
50 ii = mod(i, num_verts) + 1
54 if ((x == xa .and. y == ya) .or. &
55 (x == xb .and. y == yb))
then
59 else if (ya == yb .and. &
60 abs(y - ya) * abs(xb - xa) <= ltol .and. &
65 else if (
between(y, ya, yb))
then
66 if ((y == ya .and. yb >= ya) .or. &
67 (y == yb .and. ya >= yb))
then
73 c = (xa - x) * (yb - y) - (xb - x) * (ya - y)
74 if (abs(c) <= ltol)
then
78 else if ((ya < yb) .eqv. (c > 0))
then
91 function get_node(ilay, irow, icol, nlay, nrow, ncol)
92 integer(I4B),
intent(in) :: ilay, irow, icol, nlay, nrow, ncol
95 if (nlay > 0 .and. nrow > 0 .and. ncol > 0 .and. &
96 ilay > 0 .and. ilay <= nlay .and. &
97 irow > 0 .and. irow <= nrow .and. &
98 icol > 0 .and. icol <= ncol)
then
100 icol + ncol * (irow - 1) + (ilay - 1) * nrow * ncol
108 subroutine get_ijk(nodenumber, nrow, ncol, nlay, irow, icol, ilay)
110 integer(I4B),
intent(in) :: nodenumber
111 integer(I4B),
intent(in) :: nrow
112 integer(I4B),
intent(in) :: ncol
113 integer(I4B),
intent(in) :: nlay
114 integer(I4B),
intent(out) :: irow
115 integer(I4B),
intent(out) :: icol
116 integer(I4B),
intent(out) :: ilay
118 integer(I4B) :: nodes
121 nodes = nlay * nrow * ncol
122 if (nodenumber < 1 .or. nodenumber > nodes)
then
127 ilay = (nodenumber - 1) / (ncol * nrow) + 1
128 ij = nodenumber - (ilay - 1) * ncol * nrow
129 irow = (ij - 1) / ncol + 1
130 icol = ij - (irow - 1) * ncol
136 subroutine get_jk(nodenumber, ncpl, nlay, icpl, ilay)
138 integer(I4B),
intent(in) :: nodenumber
139 integer(I4B),
intent(in) :: ncpl
140 integer(I4B),
intent(in) :: nlay
141 integer(I4B),
intent(out) :: icpl
142 integer(I4B),
intent(out) :: ilay
144 integer(I4B) :: nodes
147 if (nodenumber < 1 .or. nodenumber > nodes)
then
151 ilay = (nodenumber - 1) / ncpl + 1
152 icpl = nodenumber - (ilay - 1) * ncpl
157 pure function skew(v, s, invert)
result(res)
159 real(dp),
intent(in) :: v(2)
160 real(dp),
intent(in) :: s(3)
161 logical(LGP),
intent(in),
optional :: invert
164 logical(LGP) :: linvert
165 real(dp) :: sxx, sxy, syy
168 if (
present(invert))
then
177 if (.not. linvert)
then
178 res(1) = sxx * v(1) + sxy * v(2)
182 res(1) = (v(1) - sxy * res(2)) / sxx
189 xorigin, yorigin, zorigin, &
193 real(dp) :: xin, yin, zin
194 real(dp) :: xout, yout, zout
195 real(dp),
optional :: xorigin, yorigin, zorigin
196 real(dp),
optional :: sinrot, cosrot
197 logical(LGP),
optional :: invert
199 logical(LGP) :: ltranslate, lrotate, linvert
201 real(dp) :: lxorigin, lyorigin, lzorigin
202 real(dp) :: lsinrot, lcosrot
205 call defaults(lxorigin, lyorigin, lzorigin, &
206 lsinrot, lcosrot, linvert, &
207 ltranslate, lrotate, &
208 xorigin, yorigin, zorigin, &
209 sinrot, cosrot, invert)
212 if (.not. linvert)
then
215 xout = xin - lxorigin
216 yout = yin - lyorigin
217 zout = zin - lzorigin
226 xout = x * lcosrot + y * lsinrot
227 yout = -x * lsinrot + y * lcosrot
232 x = xin * lcosrot - yin * lsinrot
233 y = xin * lsinrot + yin * lcosrot
241 zout = zin + lzorigin
247 subroutine compose(xorigin, yorigin, zorigin, &
249 xorigin_new, yorigin_new, zorigin_new, &
250 sinrot_new, cosrot_new, &
253 real(dp) :: xorigin, yorigin, zorigin
254 real(dp) :: sinrot, cosrot
255 real(dp),
optional :: xorigin_new, yorigin_new, zorigin_new
256 real(dp),
optional :: sinrot_new, cosrot_new
257 logical(LGP),
optional :: invert
259 logical(LGP) :: ltranslate, lrotate, linvert
260 real(dp) :: xa, ya, za, sa, ca
261 real(dp) :: x0, y0, z0, s0, c0
264 call defaults(xa, ya, za, sa, ca, linvert, &
265 ltranslate, lrotate, &
266 xorigin_new, yorigin_new, zorigin_new, &
267 sinrot_new, cosrot_new, invert)
279 if (.not. linvert)
then
282 sinrot = ca * s0 + sa * c0
283 cosrot = ca * c0 - sa * s0
287 xorigin = x0 + (c0 * xa - s0 * ya)
288 yorigin = y0 + (s0 * xa + c0 * ya)
295 sinrot = ca * s0 - sa * c0
296 cosrot = ca * c0 + sa * s0
301 xorigin = x0 - (cosrot * xa - sinrot * ya)
302 yorigin = y0 - (sinrot * xa + cosrot * ya)
311 invert, translate, rotate, &
312 xorigin_opt, yorigin_opt, zorigin_opt, &
313 sinrot_opt, cosrot_opt, invert_opt)
315 real(DP) :: xorigin, yorigin, zorigin
316 real(DP) :: sinrot, cosrot
317 logical(LGP) :: invert, translate, rotate
318 real(DP),
optional :: xorigin_opt, yorigin_opt, zorigin_opt
319 real(DP),
optional :: sinrot_opt, cosrot_opt
320 logical(LGP),
optional :: invert_opt
324 if (
present(xorigin_opt))
then
325 xorigin = xorigin_opt
329 if (
present(yorigin_opt))
then
330 yorigin = yorigin_opt
334 if (
present(zorigin_opt))
then
335 zorigin = zorigin_opt
341 if (
present(sinrot_opt))
then
343 if (
present(cosrot_opt))
then
348 cosrot = dsqrt(
done - sinrot * sinrot)
351 else if (
present(cosrot_opt))
then
355 sinrot = dsqrt(
done - cosrot * cosrot)
359 if (
present(invert_opt)) invert = invert_opt
363 function area(xv, yv, cw)
result(a)
365 real(dp),
dimension(:),
intent(in) :: xv
366 real(dp),
dimension(:),
intent(in) :: yv
367 logical(LGP),
intent(in),
optional :: cw
372 if (
present(cw))
then
382 a = -
dhalf * sum(xv(:) * cshift(yv(:), s) - cshift(xv(:), s) * yv(:))
389 real(dp),
dimension(:),
intent(in) :: xv
390 real(dp),
dimension(:),
intent(in) :: yv
400 do i = 1,
size(xv) - 1
401 do j = i + 1,
size(xv)
404 e = max(e, dx * dx + dy * dy)
422 integer(I4B),
dimension(:) :: iverts1
423 integer(I4B),
dimension(:) :: iverts2
424 integer(I4B),
intent(out) :: iface
427 integer(I4B) :: il1, iil1
428 integer(I4B) :: il2, iil2
429 logical(LGP) :: found
430 logical(LGP) :: wrapped
436 wrapped = iverts1(1) == iverts1(nv1)
443 outerloop:
do il1 = 1, nv1 - 1
445 if (iverts1(il1) == iverts2(il2))
then
450 if (wrapped) iil2 = iil2 - 1
454 if (iverts1(iil1) == iverts2(iil2))
then
463 if (wrapped) iil1 = iil1 - 1
467 if (iverts1(iil1) == iverts2(iil2))
then
486 real(dp),
intent(inout) :: alpha
487 real(dp),
intent(inout) :: beta
488 real(dp),
intent(out) :: gamma
489 real(dp),
intent(in),
optional :: pad
496 if (
present(pad))
then
499 call pstop(1,
"pad must be between 0 and 1/3, inclusive")
504 gamma =
done - alpha - beta
508 if (alpha < lolimit)
then
512 gamma =
done - alpha - beta
516 if (beta < lolimit)
then
524 else if (beta > hilimit)
then
536 if (beta < lolimit)
then
540 gamma =
done - alpha - beta
544 if (alpha < lolimit)
then
552 else if (alpha > hilimit)
then
564 if (gamma < lolimit)
then
567 delta =
dhalf * (lolimit - gamma)
569 alpha = alpha - delta
574 if (beta < lolimit)
then
578 alpha =
done - beta - gamma
582 else if (beta > hilimit)
then
586 alpha =
done - beta - gamma
This module contains simulation constants.
real(dp), parameter dep3
real constant 1000
real(dp), parameter donethird
real constant 1/3
real(dp), parameter dhalf
real constant 1/2
real(dp), parameter dzero
real constant zero
real(dp), parameter dtwo
real constant 2
real(dp), parameter done
real constant 1
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
subroutine, public shared_face(iverts1, iverts2, iface)
Find the lateral face shared by two cells.
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.
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...
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.
logical function, public between(x, a, b)
Check if a value is between two other values (inclusive).
logical function, public point_in_polygon(x, y, poly, tol)
Check if a point is within a polygon.
subroutine, public clamp_bary(alpha, beta, gamma, pad)
Clamp barycentric coordinates to the interior of a triangle, with optional padding some minimum dista...
real(dp) function, public area(xv, yv, cw)
Calculate polygon area, with vertices given in CW or CCW order.
pure real(dp) function, public polygon_extent(xv, yv)
Calculate the maximum distance between two polygon vertices.
subroutine, public compose(xorigin, yorigin, zorigin, sinrot, cosrot, xorigin_new, yorigin_new, zorigin_new, sinrot_new, cosrot_new, invert)
Compose an affine transform onto an existing one, or remove (invert) it.
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,...
pure real(dp) function, dimension(2), public skew(v, s, invert)
Skew a 2D vector along the x-axis.
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 in...
This module defines variable data types.