-
Notifications
You must be signed in to change notification settings - Fork 14
/
MODULE_QUADTREE.f90
349 lines (274 loc) · 13.5 KB
/
MODULE_QUADTREE.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
!=================================================================================================
!> CARTESIAN QUADTREE ADAPTIVE MESH REFINEMENT LIBRARY
!> AUTHOR: VAN-DAT THANG
!> E-MAIL: [email protected]
!> E-MAIL: [email protected]
!> SOURCE CODE LINK: https://github.com/dattv/QTAdaptive
!=================================================================================================
MODULE MODULE_QUADTREE
use MODULE_PRECISION
use MODULE_CONSTANTS
use MODULE_NODECOORD
use MODULE_CFD_DATA
type :: quadtree
integer(ip) :: index
integer(ip) :: m_level
real(rp) :: halfDim
type(nodeCoord), dimension(5) :: pts
type(quadtree), pointer :: adj_west
type(quadtree), pointer :: adj_east
type(quadtree), pointer :: adj_north
type(quadtree), pointer :: adj_south
type(cfd_data) :: data
reaL(rp) :: vol
type(quadtree), pointer :: father
type(quadtree), pointer :: north_west
type(quadtree), pointer :: north_east
type(quadtree), pointer :: south_west
type(quadtree), pointer :: south_east
logical :: is_leaf
contains
procedure :: new => new_quadtree
procedure :: delete => delete_quatree
procedure :: insert => insert_point_2_quadtree
procedure :: subdivide => subdivide_quadtree
end type quadtree
contains
!==================================================================================================
subroutine new_quadtree(this, index, m_level, halfDim, points, nq)
implicit none
class(quadtree), intent(inout), target :: this
integer(ip), intent(in) :: index, m_level
real(rp), intent(in) :: halfDim
type(nodeCoord), dimension(5), intent(in) :: points
integer(ip), intent(in) :: nq
integer(ip) :: i
! body
this%index = index
this%m_level = m_level
this%halfDim = halfDim
do i = 1, 5
this%pts(i) = points(i)
end do
call this%data%new(nq)
this%is_leaf = .true.
return
end subroutine new_quadtree
!==================================================================================================
subroutine delete_quatree(this)
implicit none
class(quadtree), intent(inout) :: this
integer(ip) :: i
do i = 1, 5
call this%pts(i)%delete()
end do
call this%data%delete()
this%is_leaf = .false.
return
end subroutine delete_quatree
!==================================================================================================
subroutine subdivide_quadtree(this)
implicit none
class(quadtree), intent(inout), target :: this
real(rp) :: halfDim
type(nodeCoord), dimension(5) :: points
integer(ip) :: i
type(quadtree), pointer :: child_NW, child_NE, child_SE, child_SW, temp_cell
logical :: keep_going
! body
! CHANGE CURRENT CELL NOT LEAF CELL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
this%is_leaf = .false.
! DECLARE FOUR CHILDS CELL OF CURRENT CELL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
allocate(this%north_west); this%north_west%father => this
allocate(this%north_east); this%north_east%father => this
allocate(this%south_west); this%south_west%father => this
allocate(this%south_east); this%south_east%father => this
! DECLARE FIVE POINT OF EACH CHILD NODE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
do i = 1, 5
call points(i)%new(2, (/zero, zero/))
end do
child_NW => this%north_west
child_NE => this%north_east
child_SE => this%south_east
child_SW => this%south_west
halfDim = this%halfDim*half
! MAKE CHILD CELL NORTH WEST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
points(5)%coord(1) = this%pts(5)%coord(1) - halfDim
points(5)%coord(2) = this%pts(5)%coord(2) + halfDim
points(1)%coord(1) = this%pts(1)%coord(1)
points(1)%coord(2) = this%pts(1)%coord(2)
points(2)%coord(1) = points(5)%coord(1) + halfDim
points(2)%coord(2) = points(5)%coord(2) + halfDim
points(3)%coord(1) = this%pts(5)%coord(1)
points(3)%coord(2) = this%pts(5)%coord(2)
points(4)%coord(1) = this%pts(1)%coord(1)
points(4)%coord(2) = this%pts(5)%coord(2)
call child_NW%new(0, this%m_level+1, halfDim, points, this%data%nq)
child_NW%data = this%data
! >> SET ELEMENT ADJOINT OF CELL NORTH WEST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
if (associated(this%adj_north)) then
temp_cell => this%adj_north
do while(.not. temp_cell%is_leaf .and. temp_cell%m_level < child_NW%m_level)
temp_cell => temp_cell%south_West
end do
child_NW%adj_north => temp_cell
if (temp_cell%m_level == child_NW%m_level) temp_cell%adj_south => child_NW
! AT THIS POINT, I DEVELOPED THIS CODE WITH AN SIMPLE ASSUME
end if
child_NW%adj_east => child_NE
child_NW%adj_south => child_SW
if (associated(this%adj_west)) then
temp_cell => this%adj_west
do while(.not. temp_cell%is_leaf .and. temp_cell%m_level < child_NW%m_level)
temp_cell => temp_cell%north_east
end do
child_NW%adj_west => temp_cell
if (temp_cell%m_level == child_NW%m_level) temp_cell%adj_east => child_NW
! AT THIS POINT, I DEVELOPED THIS CODE WITH AN SIMPLE ASSUME
end if
! MAKE CHILD CELL NORTH EAST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
points(5)%coord(1) = this%pts(5)%coord(1) + halfDim
points(5)%coord(2) = this%pts(5)%coord(2) + halfDim
points(1)%coord(1) = child_NW%pts(2)%coord(1)
points(1)%coord(2) = child_NW%pts(2)%coord(2)
points(2)%coord(1) = this%pts(2)%coord(1)
points(2)%coord(2) = this%pts(2)%coord(2)
points(3)%coord(1) = points(5)%coord(1) + halfDim
points(3)%coord(2) = points(5)%coord(2) - halfDim
points(4)%coord(1) = this%pts(5)%coord(1)
points(4)%coord(2) = this%pts(5)%coord(2)
call child_NE%new(0, this%m_level+1, halfDim, points, this%data%nq)
child_NE%data = this%data
! >> SET ELEMENT ADJOINT OF CELL NORTH EAST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
if (associated(this%adj_north)) then
temp_cell => this%adj_north
do while(.not. temp_cell%is_leaf .and. temp_cell%m_level < child_NE%m_level)
temp_cell => temp_cell%south_east
end do
child_NE%adj_north => temp_cell
if (temp_Cell%m_level == child_NE%m_level) temp_cell%adj_south => child_NE
end if
if (associated(this%adj_east)) then
temp_cell => this%adj_east
do while(.not. temp_cell%is_leaf .and. temp_cell%m_level < child_NE%m_level)
temp_cell => temp_cell%north_west
end do
child_NE%adj_east => temp_Cell
if (temp_Cell%m_level == child_NE%m_level) temp_cell%adj_west => child_NE
end if
child_NE%adj_south => child_SE
child_NE%adj_west => child_NW
! MAKE CHILD CELL SOURTH EAST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
points(5)%coord(1) = this%pts(5)%coord(1) + halfDim
points(5)%coord(2) = this%pts(5)%coord(2) - halfDim
points(1)%coord(1) = this%pts(5)%coord(1)
points(1)%coord(2) = this%pts(5)%coord(2)
points(2)%coord(1) = child_NE%pts(3)%coord(1)
points(2)%coord(2) = child_NE%pts(3)%coord(2)
points(3)%coord(1) = this%pts(3)%coord(1)
points(3)%coord(2) = this%pts(3)%coord(2)
points(4)%coord(1) = this%pts(5)%coord(1)
points(4)%coord(2) = points(5)%coord(2) - halfDim
call child_SE%new(0, this%m_level+1, halfDim, points, this%data%nq)
child_SE%data = this%data
! >> SET ELEMENT ADJOINT OF CELL SOUTH EAST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
child_SE%adj_north => child_NE
if (associated(this%adj_east)) then
temp_cell => this%adj_east
do while(.not. temp_cell%is_leaf .and. temp_cell%m_level < child_SE%m_level)
temp_cell => temp_cell%south_west
end do
child_SE%adj_east => temp_cell
if (temp_Cell%m_level == child_SE%m_level) temp_Cell%adj_west => child_SE
end if
if (associated(this%adj_south)) then
temp_cell => this%adj_south
do while (.not. temp_Cell%is_leaf .and. temp_cell%m_level < child_NE%m_level)
temp_cell => temp_cell%north_east
end do
child_SE%adj_south => temp_cell
if (temp_cell%m_level == child_SE%m_level) temp_cell%adj_north => child_SE
end if
child_SE%adj_West => child_SW
! MAKE CHILD CELL SOUTH WES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
points(5)%coord(1) = this%pts(5)%coord(1) - halfDim
points(5)%coord(2) = this%pts(5)%coord(2) - halfDim
points(1)%coord(1) = child_NW%pts(4)%coord(1)
points(1)%coord(2) = child_NW%pts(4)%coord(2)
points(2)%coord(1) = this%pts(5)%coord(1)
points(2)%coord(2) = this%pts(5)%coord(2)
points(3)%coord(1) = child_SE%pts(4)%coord(1)
points(3)%coord(2) = child_SE%pts(4)%coord(2)
points(4)%coord(1) = this%pts(4)%coord(1)
points(4)%coord(2) = this%pts(4)%coord(2)
call child_SW%new(0, this%m_level+1, halfDim, points, this%data%nq)
child_SW%data = this%data
! >> SET ELEMENT ADJOINT OF CELL SOUTH WEST <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
child_SW%adj_north => child_NW
child_SW%adj_east => child_SE
if(associated(this%adj_south)) then
temp_Cell => this%adj_south
do while( .not. temp_Cell%is_leaf .and. temp_Cell%m_level < child_SW%m_level)
temp_Cell => temp_Cell%north_West
end do
child_SW%adj_south => temp_Cell
if (temp_Cell%m_level == child_SW%m_level) temp_cell%adj_north => child_SW
end if
if (associated(this%adj_west)) then
temp_cell => this%adj_west
do while(.not. temp_cell%is_leaf .and. temp_cell%m_level < child_SW%m_level)
temp_cell => temp_cell%south_east
end do
child_SW%adj_west => temp_cell
if (temp_cell%m_level == child_SW%m_level) temp_cell%adj_east => child_SW
end if
! DELETE FIVE POINT
do i = 1, 5
call points(i)%delete()
end do
return
end subroutine subdivide_quadtree
!==================================================================================================
subroutine insert_point_2_quadtree(this, index, point)
implicit none
class(quadtree), intent(inout), target :: this
integer(ip), intent(in) :: index
type(nodecoord), intent(in) :: point
call this%pts(index)%new(point%ndim, point%coord)
return
end subroutine insert_point_2_quadtree
!==================================================================================================
subroutine update_back_whole_domain(first, last, tree)
implicit none
integer(ip), intent(in) :: first, last
type(quadtree), dimension(first:last), intent(inout), target :: tree
integer(ip) :: i
do i = first, last
call update_back_single_cell(tree(i))
end do
return
end subroutine update_back_whole_domain
!==================================================================================================
recursive subroutine update_back_single_cell(tree)
implicit none
type(quadtree), intent(inout), target :: tree
if (.not. tree%is_leaf) then
call update_back_single_cell(tree%north_west)
call update_back_single_cell(tree%north_east)
call update_back_single_cell(tree%south_east)
call update_back_single_cell(tree%south_west)
tree%data%u = (tree%north_west%data%u + tree%north_east%data%u + tree%south_east%data%u + tree%south_west%data%u )/four
tree%data%u_old = (tree%north_west%data%u_old + tree%north_east%data%u_old + tree%south_east%data%u_old + tree%south_west%data%u_old )/four
tree%data%u_new = (tree%north_west%data%u_new + tree%north_east%data%u_new + tree%south_east%data%u_new + tree%south_west%data%u_new )/four
tree%data%w = (tree%north_west%data%w + tree%north_east%data%w + tree%south_east%data%w + tree%south_west%data%w )/four
tree%data%res = (tree%north_west%data%res + tree%north_east%data%res + tree%south_east%data%res + tree%south_west%data%res )/four
tree%data%wsn = (tree%north_west%data%wsn + tree%north_east%data%wsn + tree%south_east%data%wsn + tree%south_west%data%wsn )/four
else
return
end if
return
end subroutine update_back_single_cell
!==================================================================================================
!==================================================================================================
!==================================================================================================
END MODULE MODULE_QUADTREE