MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_functions_forest.t
Go to the documentation of this file.
2
3 implicit none
4 private
5
6 public :: write_forest
7 public :: read_forest
8 public :: coarsen_tree_leaf
9 public :: refine_tree_leaf
10 public :: change_ipe_tree_leaf
11 public :: init_forest_root
12
13
14contains
15
16
17 !> build root forest
19 use mod_forest
24
25 integer :: ig^d, level, igrid, ipe
26 integer :: iside, i^d, morton_no, isfc
27
28
29 level=1
30 morton_no=0
31 ipe=0
32 nparents=0
33 nleafs={ng^d(1)*}
35 nleafs_level(1)={ng^d(1)*}
38 ! Generate Morton-order space-filling curve to connect level 1 blocks
40 do isfc=1,nglev1
41 ig^d=sfc_iglevel1(^d,isfc)\
42 morton_no=morton_no+1
43 if (morton_no>morton_stop(ipe)) ipe=ipe+1
44 igrid=getnode(ipe)
45 if (ipe==mype) then
46 sfc_to_igrid(morton_no)=igrid
47 igrid_to_sfc(igrid)=morton_no
48 end if
49 call init_tree_leaf(tree_root(ig^d),ig^d,level,igrid,ipe,.true.)
50 end do
51
52 ! update root neighbor
53 {do ig^db=1,ng^db(1)\}
54 {do iside=1,2
55 i^dd=kr(^dd,^d)*(2*iside-3);
56 call find_root_neighbor(tree_root(ig^dd)%node%neighbor(iside,^d), &
57 tree_root(ig^dd),i^dd)
58 end do\}
59 {end do\}
60
61 ! This call is here to ensure the sfc array is initialized
62 call amr_morton_order()
63
64 end subroutine init_forest_root
65
66 subroutine init_tree_leaf(tree,ig^D,level,igrid,ipe,active)
67 use mod_forest
68 implicit none
69
70 type(tree_node_ptr) :: tree
71 integer, intent(in) :: ig^d, level, igrid, ipe
72 logical, intent(in) :: active
73 integer :: ic^d
74
76 allocate(tree%node)
77
78 tree%node%ig^d=ig^d;
79 tree%node%level=level
80 tree%node%igrid=igrid
81 tree%node%ipe=ipe
82
83 tree%node%leaf=.true.
84 tree%node%active=active
85
86 nullify(tree%node%parent%node)
87 {do ic^db=1,2\}
88 nullify(tree%node%child(ic^d)%node)
89 {end do\}
90
91 call add_to_linked_list(level,tree)
92
93 ! initialize neighbor pointers
94 nullify({tree%node%neighbor(1,^d)%node},{tree%node%neighbor(2,^d)%node})
95
96 igrid_to_node(igrid,ipe)%node => tree%node
97
98 end subroutine init_tree_leaf
99
100 subroutine coarsen_tree_leaf(igrid,ipe,child_igrid,child_ipe,active)
101 use mod_forest
102 implicit none
103
104 integer, intent(in) :: igrid, ipe
105 integer, dimension(2^D&), intent(in) :: child_igrid, child_ipe
106 logical, intent(out) :: active
107
108
109 integer :: level, ic^d, child_level, iside, iotherside, vote
110 type(tree_node_ptr) :: tree, child, child_neighbor
111
113 tree%node => igrid_to_node(child_igrid(1^d&),child_ipe(1^d&))%node%parent%node
114 level=tree%node%level
115
116 call add_to_linked_list(level,tree)
117
118 child_level=level+1
119 vote=0
120
121 {do ic^db=1,2\}
122 child%node => tree%node%child(ic^d)%node
123
124 ! vote for active:
125 if(child%node%active) vote=vote+1
126
127 call delete_from_linked_list(child_level,child)
128
129 ! update neighbor pointers
130 {iside=ic^d
131 child_neighbor%node => child%node%neighbor(iside,^d)%node
132 if (associated(child_neighbor%node)) then
133 if (child%node%ig^d==child_neighbor%node%ig^d) then ! pole
134 nullify(child_neighbor%node%neighbor(iside,^d)%node)
135 else
136 iotherside=3-iside
137 nullify(child_neighbor%node%neighbor(iotherside,^d)%node)
138 end if
139 end if\}
140
141 nullify(tree%node%child(ic^d)%node)
142 deallocate(igrid_to_node(child_igrid(ic^d),child_ipe(ic^d))%node)
143 {end do\}
144
145 tree%node%leaf=.true.
146 tree%node%igrid=igrid
147 tree%node%ipe=ipe
148 igrid_to_node(igrid,ipe)%node => tree%node
149
150 ! Count the vote and set active/passive state:
151
152 if (vote /= 2**^nd) then
153 !if (vote == 0) then
154 tree%node%active = .false.
155 nleafs_active = nleafs_active - vote
156 else
157 tree%node%active = .true.
158 nleafs_active = nleafs_active - vote + 1
159 end if
160 active = tree%node%active
161
162 nleafs=nleafs-2**^nd+1
163 nparents=nparents-1
164 nleafs_level(child_level)=nleafs_level(child_level)-2**^nd
165 nleafs_level(level)=nleafs_level(level)+1
166
167 end subroutine coarsen_tree_leaf
168
169 subroutine refine_tree_leaf(child_igrid,child_ipe,igrid,ipe,active)
170 use mod_forest
173
174 integer, dimension(2^D&), intent(in) :: child_igrid, child_ipe
175 integer, intent(in) :: igrid, ipe
176 logical, intent(out):: active
177
178 integer :: ig^d, level, i^d, ic^d, child_ig^d, child_level, iside
179 integer :: my_neighbor_type
180 logical, dimension(ndim) :: pole
181 type(tree_node_ptr) :: tree, child, my_neighbor
182
184 tree%node => igrid_to_node(igrid,ipe)%node
185 ig^d=tree%node%ig^d;
186 level=tree%node%level
187 active=tree%node%active
188
189 tree%node%ipe=-1
190 tree%node%igrid=0
191 tree%node%leaf=.false.
192 tree%node%active=.true.
193
194 call delete_from_linked_list(level,tree)
195
196 child_level=level+1
197
198 {do ic^db=1,2\}
199 child_ig^d=2*(ig^d-1)+ic^d;
200 call init_tree_leaf(child,child_ig^d,child_level, &
201 child_igrid(ic^d),child_ipe(ic^d),active)
202
203 igrid_to_node(child_igrid(ic^d),child_ipe(ic^d))%node => child%node
204
205 tree%node%child(ic^d)%node => child%node
206 child%node%parent%node => tree%node
207 {end do\}
208
209 ! update neighbor pointers
210 {do ic^db=1,2\}
211 child%node => tree%node%child(ic^d)%node
212 {iside=ic^d
213 i^dd=kr(^dd,^d)*(2*iside-3);
214 call find_neighbor(my_neighbor,my_neighbor_type,child,i^dd,pole)
215 select case (my_neighbor_type)
216 case (neighbor_sibling, neighbor_fine)
217 child%node%neighbor(iside,^d)%node => my_neighbor%node
218 if (pole(^d)) then
219 my_neighbor%node%neighbor(iside,^d)%node => child%node
220 else
221 my_neighbor%node%neighbor(3-iside,^d)%node => child%node
222 end if
223 case default
224 nullify(child%node%neighbor(iside,^d)%node)
225 end select
226 child%node%neighbor(3-ic^d,^d)%node=>tree%node%child(3-ic^d^d%ic^dd)%node\}
227 {end do\}
228
229 nleafs=nleafs+2**^nd-1
230 nparents=nparents+1
231 nleafs_level(child_level)=nleafs_level(child_level)+2**^nd
232 nleafs_level(level)=nleafs_level(level)-1
233
234 if (active) nleafs_active = nleafs_active + 2**^nd-1
235
236 end subroutine refine_tree_leaf
237
238 subroutine change_ipe_tree_leaf(recv_igrid,recv_ipe,send_igrid,send_ipe)
239 use mod_forest
240 implicit none
241
242 integer, intent(in) :: recv_igrid, recv_ipe, send_igrid, send_ipe
243
244 type(tree_node_ptr) :: tree
245
247 tree%node => igrid_to_node(send_igrid,send_ipe)%node
248
249 tree%node%igrid=recv_igrid
250 tree%node%ipe=recv_ipe
251
252 nullify(igrid_to_node(send_igrid,send_ipe)%node)
253 igrid_to_node(recv_igrid,recv_ipe)%node => tree%node
254
255 end subroutine change_ipe_tree_leaf
256
257 subroutine add_to_linked_list(level,tree)
258 use mod_forest
259 implicit none
260
261 integer, intent(in) :: level
262 type(tree_node_ptr) :: tree
263
264 nullify(tree%node%next%node)
265 if (associated(level_head(level)%node)) then
266 tree%node%prev%node => level_tail(level)%node
267 level_tail(level)%node%next%node => tree%node
268 level_tail(level)%node => tree%node
269 else
270 level_head(level)%node => tree%node
271 level_tail(level)%node => tree%node
272 nullify(tree%node%prev%node)
273 end if
274
275 end subroutine add_to_linked_list
276
277 subroutine delete_from_linked_list(level,tree)
278 use mod_forest
279 implicit none
280
281 integer, intent(in) :: level
282 type(tree_node_ptr) :: tree
283
284 type(tree_node_ptr) :: next, prev
285
286 prev%node => tree%node%prev%node
287 next%node => tree%node%next%node
288 if (associated(next%node).and.associated(prev%node)) then
289 prev%node%next%node => next%node
290 next%node%prev%node => prev%node
291 else if (associated(prev%node)) then
292 level_tail(level)%node => prev%node
293 nullify(prev%node%next%node)
294 else if (associated(next%node)) then
295 level_head(level)%node => next%node
296 nullify(next%node%prev%node)
297 else
298 nullify(level_head(level)%node)
299 nullify(level_tail(level)%node)
300 end if
301
302 end subroutine delete_from_linked_list
303
304 subroutine write_forest(file_handle)
305 use mod_forest
307
308 integer, intent(in) :: file_handle
309
310 integer, dimension(MPI_STATUS_SIZE) :: status
311 integer :: ig^d,isfc
312
313 do isfc=1,nglev1
314 ig^d=sfc_iglevel1(^d,isfc)\
315 call write_node(tree_root(ig^d))
316 end do
317
318 contains
319
320 recursive subroutine write_node(tree)
321 implicit none
322
323 type(tree_node_ptr) :: tree
324
325 integer :: ic^d
326
327 call mpi_file_write(file_handle,tree%node%leaf,1,mpi_logical,status,ierrmpi)
328
329 if (.not.tree%node%leaf) then
330 {do ic^db=1,2\}
331 call write_node(tree%node%child(ic^d))
332 {end do\}
333 end if
334
335 end subroutine write_node
336
337 end subroutine write_forest
338
339 subroutine read_forest(file_handle)
340 use mod_forest
346
347 integer, intent(in) :: file_handle
348
349 integer, dimension(MPI_STATUS_SIZE) :: status
350 !integer :: ig^D, level, size_logical, Morton_no, igrid, ipe
351 integer :: ig^d, level, morton_no, igrid, ipe, isfc
352
354 morton_no=0
355 ipe=0
356 level=1
358 nparents = 0
359
362 do isfc=1,nglev1
363 ig^d=sfc_iglevel1(^d,isfc)\
364 allocate(tree_root(ig^d)%node)
365 nullify(tree_root(ig^d)%node%parent%node)
366 call read_node(tree_root(ig^d),ig^d,level)
367 end do
368
369 call get_level_range
370
371 ! Rebuild tree connectivity
372 call getigrids
374
375 ! This call is here to ensure the sfc array is initialized
376 call amr_morton_order()
377
378 contains
379
380 recursive subroutine read_node(tree,ig^D,level)
381 implicit none
382
383 type(tree_node_ptr) :: tree
384 integer, intent(in) :: ig^d, level
385
386 integer :: ic^d, child_ig^d, child_level
387 logical :: leaf
388
389 if (mype==0) then
390 call mpi_file_read(file_handle,leaf,1,mpi_logical, &
391 status,ierrmpi)
392 end if
393 if (npe>1) call mpi_bcast(leaf,1,mpi_logical,0,icomm,ierrmpi)
394
395 tree%node%leaf=leaf
396 tree%node%ig^d=ig^d;
397 tree%node%level=level
398 tree%node%active=.true. .and. leaf
399
400 {do ic^db=1,2\}
401 nullify(tree%node%child(ic^d)%node)
402 {end do\}
403 nullify({tree%node%neighbor(1,^d)%node},{tree%node%neighbor(2,^d)%node})
404 nullify(tree%node%next%node,tree%node%prev%node)
405
406 call asign_tree_neighbor(tree)
407
408 if (leaf) then
409 call add_to_linked_list(level,tree)
410 nleafs_level(level) = nleafs_level(level) + 1
411
412 morton_no=morton_no+1
413 if (morton_no>morton_stop(ipe)) ipe=ipe+1
414 igrid=getnode(ipe)
415 tree%node%igrid=igrid
416 tree%node%ipe=ipe
417 igrid_to_node(igrid,ipe)%node => tree%node
418 if (ipe==mype) sfc_to_igrid(morton_no)=igrid
419 else
420 nparents = nparents + 1
421 tree%node%igrid=0
422 tree%node%ipe=-1
423 child_level=level+1
424 {do ic^db=1,2\}
425 child_ig^d=2*(ig^d-1)+ic^d;
426 allocate(tree%node%child(ic^d)%node)
427 tree%node%child(ic^d)%node%parent%node => tree%node
428 call read_node(tree%node%child(ic^d),child_ig^d,child_level)
429 {end do\}
430 end if
431
432 end subroutine read_node
433
434 end subroutine read_forest
435
436
437end module mod_functions_forest
recursive subroutine write_node(tree)
recursive subroutine read_node(tree, igd, level)
subroutine, public find_neighbor(my_neighbor, my_neighbor_type, tree, id, pole)
find neighors of all blocks
subroutine, public asign_tree_neighbor(tree)
asign tree node neighor
subroutine, public find_root_neighbor(tree_neighbor, tree, id)
find neighors of level-one root blocks
integer function, public getnode(ipe)
Get first available igrid on processor ipe.
Module with basic grid data structures.
Definition mod_forest.t:2
integer(kind=8) particle_mesh_epoch
Replicated forest generation: topology or ownership changes invalidate cached particle locations and ...
Definition mod_forest.t:6
integer, dimension(:), allocatable, save nleafs_level
How many leaves are present per refinement level.
Definition mod_forest.t:84
integer, dimension(:), allocatable, save sfc_to_igrid
Go from a Morton number to an igrid index (for a single processor).
Definition mod_forest.t:56
integer nleafs_active
Definition mod_forest.t:81
integer, save nleafs
Number of leaf block.
Definition mod_forest.t:79
integer, dimension(:), allocatable, save igrid_to_sfc
Go from a grid index to Morton number (for a single processor).
Definition mod_forest.t:59
integer nglev1
Definition mod_forest.t:81
integer, dimension(:,:), allocatable, save sfc_iglevel1
Space filling curve for level 1 grid. sfc_iglevel1(^D, MN) gives ig^D (the spatial index of the grid)...
Definition mod_forest.t:50
type(tree_node_ptr), dimension(:), allocatable, save level_tail
The tail pointer of the linked list per refinement level.
Definition mod_forest.t:41
integer, dimension(:), allocatable, save morton_stop
Last Morton number per processor.
Definition mod_forest.t:68
type(tree_node_ptr), dimension(:^d &), allocatable, save tree_root
Pointers to the coarse grid.
Definition mod_forest.t:32
integer, save nparents
Number of parent blocks.
Definition mod_forest.t:76
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
Definition mod_forest.t:35
type(tree_node_ptr), dimension(:), allocatable, save level_head
The head pointer of the linked list per refinement level.
Definition mod_forest.t:38
subroutine, public change_ipe_tree_leaf(recv_igrid, recv_ipe, send_igrid, send_ipe)
subroutine, public write_forest(file_handle)
subroutine, public read_forest(file_handle)
subroutine, public refine_tree_leaf(child_igrid, child_ipe, igrid, ipe, active)
subroutine, public coarsen_tree_leaf(igrid, ipe, child_igrid, child_ipe, active)
subroutine, public init_forest_root
build root forest
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer, parameter nlevelshi
The maximum number of levels in the grid refinement.
integer icomm
The MPI communicator.
integer, dimension(:), allocatable ng
number of grid blocks in domain per dimension, in array over levels
integer mype
The rank of the current MPI task.
integer ierrmpi
A global MPI error return code.
double precision, dimension(:), allocatable, parameter d
integer npe
The number of MPI tasks.
subroutine get_morton_range
Set the Morton range for each processor.
subroutine amr_morton_order
Construct Morton-order as a global recursive lexicographic ordering.
subroutine level1_morton_order
build Morton space filling curve for level 1 grid
Pointer to a tree_node.
Definition mod_forest.t:9