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) :: xorigin_add, yorigin_add, zorigin_add
261 real(dp) :: sinrot_add, cosrot_add
262 real(dp) :: x0, y0, z0, s0, c0
265 call defaults(xorigin_add, yorigin_add, zorigin_add, &
266 sinrot_add, cosrot_add, linvert, &
267 ltranslate, lrotate, &
268 xorigin_new, yorigin_new, zorigin_new, &
269 sinrot_new, cosrot_new, invert)
279 if (.not. linvert)
then
286 call transform(xorigin_add, yorigin_add, zorigin_add, &
287 xorigin, yorigin, zorigin, &
288 x0, y0, z0, s0, c0, .true.)
294 sinrot = cosrot_add * s0 + sinrot_add * c0
295 cosrot = cosrot_add * c0 - sinrot_add * s0
305 call transform(-xorigin_add, -yorigin_add, zorigin_add, &
306 x0, y0, z0, xorigin, yorigin, zorigin, &
307 -sinrot_add, cosrot_add, .true.)
309 xorigin = c0 * x0 - s0 * y0
310 yorigin = s0 * x0 + c0 * y0
312 else if (ltranslate)
then
313 xorigin = x0 - xorigin_add
314 yorigin = y0 - yorigin_add
315 zorigin = z0 - zorigin_add
322 sinrot = cosrot_add * s0 - sinrot_add * c0
323 cosrot = cosrot_add * c0 + sinrot_add * s0
331 invert, translate, rotate, &
332 xorigin_opt, yorigin_opt, zorigin_opt, &
333 sinrot_opt, cosrot_opt, invert_opt)
335 real(DP) :: xorigin, yorigin, zorigin
336 real(DP) :: sinrot, cosrot
337 logical(LGP) :: invert, translate, rotate
338 real(DP),
optional :: xorigin_opt, yorigin_opt, zorigin_opt
339 real(DP),
optional :: sinrot_opt, cosrot_opt
340 logical(LGP),
optional :: invert_opt
344 if (
present(xorigin_opt))
then
345 xorigin = xorigin_opt
349 if (
present(yorigin_opt))
then
350 yorigin = yorigin_opt
354 if (
present(zorigin_opt))
then
355 zorigin = zorigin_opt
361 if (
present(sinrot_opt))
then
363 if (
present(cosrot_opt))
then
368 cosrot = dsqrt(
done - sinrot * sinrot)
371 else if (
present(cosrot_opt))
then
375 sinrot = dsqrt(
done - cosrot * cosrot)
379 if (
present(invert_opt)) invert = invert_opt
383 function area(xv, yv, cw)
result(a)
385 real(dp),
dimension(:),
intent(in) :: xv
386 real(dp),
dimension(:),
intent(in) :: yv
387 logical(LGP),
intent(in),
optional :: cw
392 if (
present(cw))
then
402 a = -
dhalf * sum(xv(:) * cshift(yv(:), s) - cshift(xv(:), s) * yv(:))
417 integer(I4B),
dimension(:) :: iverts1
418 integer(I4B),
dimension(:) :: iverts2
419 integer(I4B),
intent(out) :: iface
422 integer(I4B) :: il1, iil1
423 integer(I4B) :: il2, iil2
424 logical(LGP) :: found
425 logical(LGP) :: wrapped
431 wrapped = iverts1(1) == iverts1(nv1)
438 outerloop:
do il1 = 1, nv1 - 1
440 if (iverts1(il1) == iverts2(il2))
then
445 if (wrapped) iil2 = iil2 - 1
449 if (iverts1(iil1) == iverts2(iil2))
then
458 if (wrapped) iil1 = iil1 - 1
462 if (iverts1(iil1) == iverts2(iil2))
then
481 real(dp),
intent(inout) :: alpha
482 real(dp),
intent(inout) :: beta
483 real(dp),
intent(out) :: gamma
484 real(dp),
intent(in),
optional :: pad
491 if (
present(pad))
then
494 call pstop(1,
"pad must be between 0 and 1/3, inclusive")
499 gamma =
done - alpha - beta
503 if (alpha < lolimit)
then
507 gamma =
done - alpha - beta
511 if (beta < lolimit)
then
519 else if (beta > hilimit)
then
531 if (beta < lolimit)
then
535 gamma =
done - alpha - beta
539 if (alpha < lolimit)
then
547 else if (alpha > hilimit)
then
559 if (gamma < lolimit)
then
562 delta =
dhalf * (lolimit - gamma)
564 alpha = alpha - delta
569 if (beta < lolimit)
then
573 alpha =
done - beta - gamma
577 else if (beta > hilimit)
then
581 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.
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.
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.