MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
CellRectQuad.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b, lgp
4  use cellmodule, only: celltype
6  use constantsmodule, only: dzero
7  implicit none
8 
9  private
10  public :: cellrectquadtype
11  public :: create_cell_rect_quad
12 
13  type, extends(celltype) :: cellrectquadtype
14  real(dp) :: dx !< dimension of cell in local x direction
15  real(dp) :: dy !< dimension of cell in local y direction
16  real(dp) :: dz !< dimension of cell in z direction
17 
18  real(dp) :: sinrot !< sine of rotation angle for local (x, y)
19  real(dp) :: cosrot !< cosine of rotation angle for local (x, y)
20 
21  integer(I4B) :: irvorigin !< origin rectangle vertex
22  real(dp) :: xorigin !< model x origin for local (x, y)
23  real(dp) :: yorigin !< model y origin for local (x, y)
24  real(dp) :: zorigin !< model z origin for local z
25 
26  real(dp) :: qextl1(4), qextl2(4), qintl(5) !< external and internal subcell flows for the cell
27  integer(I4B), allocatable :: irectvert(:) !< list of indices of the rectangle vertices
28  integer(I4B), allocatable :: ipv4irv(:, :) !< list of the polygon vertex indices that correspond to the rectangle vertex indices
29  real(dp), allocatable :: rectflow(:, :) !< flow(s) for each rectangle face
30  contains
31  procedure :: destroy => destroy_cell_rect_quad !< destructor for the cell
32  procedure :: init_from !< initializes the cell from an existing cell
33 
34  procedure :: load_rect_verts_flows ! loads list of indices of the rectangle vertices and face flows
35  procedure :: get_rect_ivert_sw ! gets index of southwest rectangle vertex
36  procedure :: get_rect_dim_rot ! gets rectangular dimensions and rotation
37  procedure :: get_rect_flow !< returns a rectangle face flow
38  procedure :: face_is_refined !< returns whether a rectangle face is refined
39  end type cellrectquadtype
40 
41 contains
42 
43  !> @brief Create a new rectangular-quad cell
44  subroutine create_cell_rect_quad(cell)
45  type(cellrectquadtype), pointer :: cell
46  allocate (cell)
47  call create_defn(cell%defn)
48  allocate (cell%irectvert(5))
49  allocate (cell%ipv4irv(2, 4))
50  allocate (cell%rectflow(2, 4))
51  allocate (cell%type)
52  cell%type = 'rectquad'
53  end subroutine create_cell_rect_quad
54 
55  !> @brief Destroy the rectangular-quad cell
56  subroutine destroy_cell_rect_quad(this)
57  class(cellrectquadtype), intent(inout) :: this
58  deallocate (this%defn)
59  deallocate (this%irectvert)
60  deallocate (this%type)
61  end subroutine destroy_cell_rect_quad
62 
63  !> @brief Initialize a rectangular-quad cell from cell definition
64  subroutine init_from(this, defn)
65  class(cellrectquadtype), intent(inout) :: this
66  type(celldefntype), pointer :: defn
67  this%defn => defn
68  call this%load_rect_verts_flows()
69  end subroutine init_from
70 
71  !> @brief Load local polygon vertex indices and rectangular
72  !> face flows
73  !!
74  !! Loads local polygon vertex indices of the four rectangle
75  !! vertices and face flows of a rectangular-quad cell.
76  !<
77  subroutine load_rect_verts_flows(this)
78  ! -- dummy
79  class(cellrectquadtype), intent(inout) :: this
80  ! -- local
81  integer(I4B) :: n, m
82 
83  n = 0
84  do m = 1, this%defn%npolyverts
85  if (.not. this%defn%get_ispv180(m)) then
86  n = n + 1
87  this%irectvert(n) = m
88  this%ipv4irv(1, n) = m
89  this%rectflow(1, n) = this%defn%get_faceflow(m)
90  this%ipv4irv(2, n) = 0
91  this%rectflow(2, n) = dzero
92  else
93  if (n .ne. 0) then
94  this%ipv4irv(2, n) = m
95  this%rectflow(2, n) = this%defn%get_faceflow(m)
96  end if
97  end if
98  end do
99 
100  ! Wrap around for convenience
101  this%irectvert(5) = this%irectvert(1)
102  end subroutine load_rect_verts_flows
103 
104  !> @brief Get index of SW rectangle vertex
105  !!
106  !! Return the index (1, 2, 3, or 4) of the southwest
107  !! rectangle vertex of a rectangular-quad cell
108  !<
109  function get_rect_ivert_sw(this) result(irv1)
110  ! -- dummy
111  class(cellrectquadtype), intent(inout) :: this
112  integer(I4B) :: irv1
113  ! -- local
114  integer(I4B) :: irv, irv2, irv4, ipv1, ipv2, ipv4
115  integer(I4B), dimension(4) :: irvnxt = (/2, 3, 4, 1/)
116  real(dp) :: x1, y1, x2, y2, x4, y4
117 
118  ! -- Find the "southwest" rectangle vertex by finding the vertex formed
119  ! -- either by (1) a rectangle edge over which x decreases (going
120  ! -- clockwise) followed by an edge over which x does not increase, or by
121  ! -- (2) a rectangle edge over which y does not decrease (again going
122  ! -- clockwise) followed by a rectangle edge over which y increases. In
123  ! -- the end, ipv1 is the index (1, 2, 3, or 4) of the southwest
124  ! -- rectangle vertex.
125  do irv = 1, 4
126  irv4 = irv
127  irv1 = irvnxt(irv4)
128  ipv4 = this%irectvert(irv4)
129  ipv1 = this%irectvert(irv1)
130  x4 = this%defn%polyvert(1, ipv4)
131  y4 = this%defn%polyvert(2, ipv4)
132  x1 = this%defn%polyvert(1, ipv1)
133  y1 = this%defn%polyvert(2, ipv1)
134  if (x1 .lt. x4) then
135  irv2 = irvnxt(irv1)
136  ipv2 = this%irectvert(irv2)
137  x2 = this%defn%polyvert(1, ipv2)
138  if (x2 .le. x1) return
139  else if (y1 .ge. y4) then
140  irv2 = irvnxt(irv1)
141  ipv2 = this%irectvert(irv2)
142  y2 = this%defn%polyvert(2, ipv2)
143  if (y2 .gt. y1) return
144  end if
145  end do
146  end function get_rect_ivert_sw
147 
148  !> @brief Get rectangular cell dimensions and rotation
149  !!
150  !! Compute rectangular dimensions and rotation of
151  !! the cell using the specified rectangle vertex
152  !! as the origin
153  !<
154  subroutine get_rect_dim_rot(this)
155  ! -- dummy
156  class(cellrectquadtype), intent(inout) :: this
157  ! -- local
158  integer(I4B) :: irv2, irv4, ipv1, ipv2, ipv4
159  integer(I4B), dimension(4) :: irvnxt = (/2, 3, 4, 1/)
160  real(DP) :: x1, y1, x2, y2, x4, y4, dx2, dy2, dx4, dy4
161 
162  ! -- Get rectangle vertex neighbors irv2 and irv4
163  irv2 = irvnxt(this%irvOrigin)
164  irv4 = irvnxt(irvnxt(irv2))
165 
166  ! -- Get model coordinates at irv1, irv2, and irv4
167  ipv1 = this%irectvert(this%irvOrigin)
168  x1 = this%defn%polyvert(1, ipv1)
169  y1 = this%defn%polyvert(2, ipv1)
170  ipv2 = this%irectvert(irv2)
171  x2 = this%defn%polyvert(1, ipv2)
172  y2 = this%defn%polyvert(2, ipv2)
173  ipv4 = this%irectvert(irv4)
174  x4 = this%defn%polyvert(1, ipv4)
175  y4 = this%defn%polyvert(2, ipv4)
176 
177  ! -- Compute rectangle dimensions
178  this%xOrigin = x1
179  this%yOrigin = y1
180  this%zOrigin = this%defn%bot
181  dx2 = x2 - this%xOrigin
182  dy2 = y2 - this%yOrigin
183  dx4 = x4 - this%xOrigin
184  dy4 = y4 - this%yOrigin
185  this%dx = dsqrt(dx4 * dx4 + dy4 * dy4)
186  this%dy = dsqrt(dx2 * dx2 + dy2 * dy2)
187  this%dz = this%defn%top - this%zOrigin
188 
189  ! -- Compute sine and cosine of rotation angle (angle between "southern"
190  ! -- rectangle side irv1-irv4 and the model x axis)
191  this%sinrot = dy4 / this%dx
192  this%cosrot = dx4 / this%dx
193  end subroutine get_rect_dim_rot
194 
195  !> @brief Return a rectangle face flow
196  function get_rect_flow(this, iq, irv) result(rectflow)
197  class(cellrectquadtype), intent(inout) :: this
198  integer(I4B) :: iq, irv
199  real(dp) :: rectflow
200  rectflow = this%rectflow(iq, irv)
201  end function get_rect_flow
202 
203  !> @brief Return whether a rectangle face is refined
204  function face_is_refined(this, i) result(is_refined)
205  ! -- dummy
206  class(cellrectquadtype), intent(inout) :: this
207  integer(I4B) :: i !< face index
208  logical(LGP) :: is_refined
209 
210  if (this%ipv4irv(2, i) .ne. 0) then
211  is_refined = .true.
212  else
213  is_refined = .false.
214  end if
215  end function face_is_refined
216 
217 end module cellrectquadmodule
subroutine, public create_defn(cellDefn)
Create a new cell definition object.
Definition: CellDefn.f90:41
subroutine, public create_cell_rect_quad(cell)
Create a new rectangular-quad cell.
subroutine init_from(this, defn)
Initialize a rectangular-quad cell from cell definition.
subroutine get_rect_dim_rot(this)
Get rectangular cell dimensions and rotation.
subroutine destroy_cell_rect_quad(this)
Destroy the rectangular-quad cell.
real(dp) function get_rect_flow(this, iq, irv)
Return a rectangle face flow.
subroutine load_rect_verts_flows(this)
Load local polygon vertex indices and rectangular face flows.
logical(lgp) function face_is_refined(this, i)
Return whether a rectangle face is refined.
integer(i4b) function get_rect_ivert_sw(this)
Get index of SW rectangle vertex.
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
This module defines variable data types.
Definition: kind.f90:8
Base grid cell definition.
Definition: CellDefn.f90:10
Base type for grid cells of a concrete type. Contains a cell-definition which is information shared b...
Definition: Cell.f90:13