modgrids.F90 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. module Agrif_Grids
  2. use Agrif_Types
  3. !
  4. implicit none
  5. !
  6. !===================================================================================================
  7. type Agrif_Grid_List
  8. !---------------------------------------------------------------------------------------------------
  9. !< List of grids.
  10. !
  11. integer :: nitems = 0 !< Number of elements in the list
  12. type(Agrif_PGrid), pointer :: first => NULL() !< Pointer to the first grid in the list
  13. type(Agrif_PGrid), pointer :: last => NULL() !< Pointer to the last grid inserted in the list
  14. !---------------------------------------------------------------------------------------------------
  15. end type Agrif_Grid_List
  16. !===================================================================================================
  17. !
  18. !===================================================================================================
  19. type Agrif_PGrid
  20. !---------------------------------------------------------------------------------------------------
  21. !< Data type to go over the grid hierarchy (used for the creation of this grid hierarchy
  22. !< and during the time integration).
  23. !
  24. type(Agrif_Grid) , pointer :: gr => NULL() !< Pointer to the actual grid data structure
  25. type(Agrif_PGrid), pointer :: next => NULL() !< Next grid in the list
  26. !
  27. !---------------------------------------------------------------------------------------------------
  28. end type Agrif_PGrid
  29. !===================================================================================================
  30. !
  31. !===================================================================================================
  32. type Agrif_Grid
  33. !---------------------------------------------------------------------------------------------------
  34. !< Data type to define a grid (position, space and time refinement factors).
  35. !
  36. type(Agrif_Grid) , pointer :: parent => NULL() !< pointer on the parent grid
  37. type(Agrif_Grid) , pointer :: save_grid => NULL() !< pointer on the save grid
  38. type(Agrif_Grid_List) :: child_list !< List of child grids
  39. type(Agrif_Variable), dimension(:), allocatable :: tabvars !< List of grid variables
  40. type(Agrif_Variable_c), dimension(:), allocatable :: tabvars_c !< List of character grid variables
  41. type(Agrif_Variable_r), dimension(:), allocatable :: tabvars_r !< List of real grid variables
  42. type(Agrif_Variable_l), dimension(:), allocatable :: tabvars_l !< List of logical grid variables
  43. type(Agrif_Variable_i), dimension(:), allocatable :: tabvars_i !< List of integer grid variables
  44. !
  45. real , dimension(3) :: Agrif_x !< global x, y and z position
  46. real , dimension(3) :: Agrif_dx !< global space step in the x, y and z direction
  47. real , dimension(3) :: Agrif_dt !< global time step in the x, y and z direction
  48. integer, dimension(3) :: nb !< number of cells in the x, y and z direction
  49. integer, dimension(3) :: ix !< minimal position in the x, y and z direction
  50. integer, dimension(3) :: spaceref !< space refinement factor in the x, y and z direction
  51. integer, dimension(3) :: timeref !< Time refinement factor in the x, y and z direction
  52. integer :: ngridstep !< number of time steps
  53. integer :: rank
  54. integer :: grid_id !< moving grid id
  55. integer :: fixedrank !< number of the grid
  56. logical :: fixed !< fixed or moving grid ?
  57. logical :: oldgrid
  58. !> \name Logicals indicating if the current grid has a common border with the root coarse grid
  59. !> @{
  60. logical, dimension(3) :: NearRootBorder
  61. logical, dimension(3) :: DistantRootBorder
  62. !> @}
  63. !> \name Arrays for adaptive grid refinement
  64. !> @{
  65. integer, dimension(:) , allocatable :: tabpoint1D
  66. integer, dimension(:,:) , allocatable :: tabpoint2D
  67. integer, dimension(:,:,:), allocatable :: tabpoint3D
  68. !> @}
  69. !> \name Members for parallel integration
  70. !> @{
  71. type(Agrif_Rectangle), pointer :: rect_in_parent => NULL()
  72. type(Agrif_Grid_List) :: neigh_list !< List of neighboring grids (ie. connected through a common proc)
  73. type(Agrif_Proc_List) :: proc_def_list !< List of procs that will integrate this grid
  74. type(Agrif_Proc_List) :: proc_def_in_parent_list !< List of procs that will integrate this grid (defined as in the parent grid)
  75. type(Agrif_Proc_List) :: required_proc_list !< List of procs that are required for this grid
  76. type(Agrif_Sequence_List), pointer :: child_seq => NULL() !< Sequence for childs
  77. integer :: seq_num = 0
  78. integer :: size = 0
  79. integer :: dsat = 0
  80. #if defined AGRIF_MPI
  81. integer :: communicator = -1
  82. #endif
  83. !> @}
  84. type(Agrif_Variables_List), pointer :: variables => NULL()
  85. integer :: NbVariables = 0
  86. integer :: level !< level of the grid in the hierarchy
  87. logical :: allocation_is_done = .false.
  88. logical :: grand_mother_grid = .false.
  89. !---------------------------------------------------------------------------------------------------
  90. end type Agrif_Grid
  91. !===================================================================================================
  92. !
  93. !> this pointer always points on the root grid of the grid hierarchy
  94. type(Agrif_Grid) , pointer :: Agrif_Mygrid => NULL()
  95. !> this pointer always points on the grand mother grid of the grid hierarchy (if any)
  96. type(Agrif_Grid) , pointer :: Agrif_Coarsegrid => NULL()
  97. !> Grid list used in the \link Agrif_Util::Agrif_Regrid() Agrif_regrid \endlink subroutine.
  98. !> It contains the safeguard of the grid hierarchy.
  99. type(Agrif_Grid_List), pointer :: Agrif_oldmygrid => NULL()
  100. !> Pointer to the current grid (the link is done by using the Agrif_Instance procedure (\see module Agrif_Init))
  101. type(Agrif_Grid) , pointer :: Agrif_Curgrid => NULL()
  102. !
  103. !===================================================================================================
  104. type Agrif_Sequence
  105. !---------------------------------------------------------------------------------------------------
  106. type(Agrif_Grid_List) :: gridlist
  107. type(Agrif_Proc_List) :: proclist
  108. !---------------------------------------------------------------------------------------------------
  109. end type Agrif_Sequence
  110. !===================================================================================================
  111. !
  112. !===================================================================================================
  113. type Agrif_Sequence_List
  114. !---------------------------------------------------------------------------------------------------
  115. integer :: nb_seqs
  116. type(Agrif_Sequence), dimension(:), allocatable :: sequences
  117. !---------------------------------------------------------------------------------------------------
  118. end type Agrif_Sequence_List
  119. !===================================================================================================
  120. !
  121. interface
  122. function compare_grids ( grid1, grid2 ) result( res )
  123. import Agrif_Grid
  124. type(Agrif_Grid), intent(in) :: grid1
  125. type(Agrif_Grid), intent(in) :: grid2
  126. integer :: res !< Result of the comparison :
  127. !! - res < 0 if grid1 < grid2
  128. !! - res == 0 if grid1 == grid2
  129. !! - res > 0 if grid1 > grid2
  130. end function compare_grids
  131. end interface
  132. !
  133. contains
  134. !
  135. !===================================================================================================
  136. subroutine Agrif_gl_print ( gridlist )
  137. !
  138. !< DEBUG : a virer à terme.
  139. !---------------------------------------------------------------------------------------------------
  140. type(Agrif_Grid_List), intent(in) :: gridlist
  141. !
  142. type(Agrif_PGrid), pointer :: gridp
  143. type(Agrif_Grid), pointer :: grid
  144. !
  145. gridp => gridlist % first
  146. do while ( associated(gridp) )
  147. grid => gridp % gr
  148. write(*,'("G",i0,", ")', advance='no') grid % fixedrank
  149. gridp => gridp % next
  150. enddo
  151. write(*,*)
  152. !---------------------------------------------------------------------------------------------------
  153. end subroutine Agrif_gl_print
  154. !===================================================================================================
  155. !
  156. !===================================================================================================
  157. subroutine Agrif_gl_print_debug ( gridlist )
  158. !
  159. !< DEBUG : a virer à terme.
  160. !---------------------------------------------------------------------------------------------------
  161. type(Agrif_Grid_List), intent(in) :: gridlist
  162. !
  163. type(Agrif_PGrid), pointer :: gridp
  164. type(Agrif_Grid), pointer :: grid
  165. !
  166. write(*,'(" (nitems=",i2,"), (id,neighs,color,dsat,size) = ")', advance='no') gridlist % nitems
  167. gridp => gridlist % first
  168. do while ( associated(gridp) )
  169. grid => gridp % gr
  170. write(*,'("(G",i0,4(",",i0),"), ")', advance='no') grid % fixedrank, &
  171. grid % neigh_list % nitems, grid % seq_num, grid % dsat, grid % size
  172. gridp => gridp % next
  173. enddo
  174. write(*,*)
  175. !---------------------------------------------------------------------------------------------------
  176. end subroutine Agrif_gl_print_debug
  177. !===================================================================================================
  178. !
  179. !===================================================================================================
  180. subroutine Agrif_gl_append ( gridlist, grid )
  181. !---------------------------------------------------------------------------------------------------
  182. type(Agrif_Grid_List), intent(inout) :: gridlist
  183. type(Agrif_Grid), pointer, intent(in) :: grid
  184. !
  185. type(Agrif_PGrid), pointer :: new_gp
  186. !
  187. allocate( new_gp )
  188. !
  189. new_gp % gr => grid
  190. new_gp % next => NULL()
  191. !
  192. if ( associated(gridlist % last) ) then
  193. ! the list is not empty, append the new pointer at the end
  194. gridlist % last % next => new_gp
  195. else
  196. ! the list is empty, the new pointer is the first one
  197. gridlist % first => new_gp
  198. endif
  199. ! anyway, for next time 'grid' will be the last one.
  200. gridlist % last => new_gp
  201. gridlist % nitems = gridlist % nitems + 1
  202. !---------------------------------------------------------------------------------------------------
  203. end subroutine Agrif_gl_append
  204. !===================================================================================================
  205. !
  206. !===================================================================================================
  207. function Agrif_gl_popfirst ( gridlist ) result ( grid )
  208. !
  209. !< Removes the first item of the list and returns it.
  210. !---------------------------------------------------------------------------------------------------
  211. type(Agrif_Grid_List), intent(inout) :: gridlist
  212. !
  213. type(Agrif_PGrid), pointer :: grid_p
  214. type(Agrif_Grid), pointer :: grid
  215. !
  216. grid_p => gridlist % first
  217. !
  218. if ( .not. associated( grid_p ) ) then
  219. grid => NULL()
  220. return
  221. endif
  222. !
  223. grid => grid_p % gr
  224. gridlist % first => grid_p % next
  225. gridlist % nitems = gridlist % nitems - 1
  226. if ( .not. associated(gridlist % first) ) then
  227. nullify(gridlist % last)
  228. endif
  229. deallocate(grid_p)
  230. !---------------------------------------------------------------------------------------------------
  231. end function Agrif_gl_popfirst
  232. !===================================================================================================
  233. !
  234. !===================================================================================================
  235. subroutine Agrif_gl_copy ( new_gl, model )
  236. !---------------------------------------------------------------------------------------------------
  237. type(Agrif_Grid_List), intent(out) :: new_gl
  238. type(Agrif_Grid_List), intent(in) :: model
  239. !
  240. type(Agrif_PGrid), pointer :: gp
  241. !
  242. call Agrif_gl_clear(new_gl)
  243. gp => model % first
  244. !
  245. do while( associated(gp) )
  246. call Agrif_gl_append( new_gl, gp % gr )
  247. gp => gp % next
  248. enddo
  249. !---------------------------------------------------------------------------------------------------
  250. end subroutine Agrif_gl_copy
  251. !===================================================================================================
  252. !
  253. !===================================================================================================
  254. function Agrif_gl_build_from_gp ( gridp ) result ( gridlist )
  255. !---------------------------------------------------------------------------------------------------
  256. type(Agrif_PGrid), pointer, intent(in) :: gridp
  257. !
  258. type(Agrif_Grid_List), pointer :: gridlist
  259. type(Agrif_PGrid), pointer :: gp
  260. !
  261. allocate(gridlist)
  262. !
  263. gp => gridp
  264. !
  265. do while ( associated( gp ) )
  266. call Agrif_gl_append( gridlist, gp % gr )
  267. gp => gp % next
  268. enddo
  269. !---------------------------------------------------------------------------------------------------
  270. end function Agrif_gl_build_from_gp
  271. !===================================================================================================
  272. !
  273. !===================================================================================================
  274. subroutine Agrif_gp_delete ( gridp )
  275. !---------------------------------------------------------------------------------------------------
  276. type(Agrif_PGrid), pointer, intent(inout) :: gridp
  277. !
  278. type(Agrif_PGrid), pointer :: gp, gpd
  279. !
  280. if ( .not. associated( gridp ) ) return
  281. !
  282. gp => gridp
  283. !
  284. do while( associated(gp) )
  285. gpd => gp
  286. gp => gp % next
  287. deallocate(gpd)
  288. enddo
  289. !---------------------------------------------------------------------------------------------------
  290. end subroutine Agrif_gp_delete
  291. !===================================================================================================
  292. !
  293. !===================================================================================================
  294. subroutine Agrif_gl_clear ( gridlist )
  295. !---------------------------------------------------------------------------------------------------
  296. type(Agrif_Grid_List), intent(inout) :: gridlist
  297. !
  298. call Agrif_gp_delete(gridlist % first)
  299. gridlist % first => NULL()
  300. gridlist % last => NULL()
  301. gridlist % nitems = 0
  302. !---------------------------------------------------------------------------------------------------
  303. end subroutine Agrif_gl_clear
  304. !===================================================================================================
  305. !
  306. !===================================================================================================
  307. subroutine Agrif_gl_delete ( gridlist )
  308. !---------------------------------------------------------------------------------------------------
  309. type(Agrif_Grid_List), pointer, intent(inout) :: gridlist
  310. !
  311. if ( .not. associated( gridlist ) ) return
  312. !
  313. call Agrif_gp_delete(gridlist % first)
  314. deallocate( gridlist )
  315. !---------------------------------------------------------------------------------------------------
  316. end subroutine Agrif_gl_delete
  317. !===================================================================================================
  318. !
  319. !===================================================================================================
  320. recursive function Agrif_gl_merge_sort ( gridlist, compare_func, compare_func_opt ) result( gl_sorted )
  321. !---------------------------------------------------------------------------------------------------
  322. type(Agrif_Grid_List), intent(in) :: gridlist
  323. procedure(compare_grids) :: compare_func
  324. procedure(compare_grids), optional :: compare_func_opt
  325. !
  326. type(Agrif_Grid_List), pointer :: gl_sorted
  327. type(Agrif_Grid_List), pointer :: gl_left, gl_sorted_left
  328. type(Agrif_Grid_List), pointer :: gl_right, gl_sorted_right
  329. type(Agrif_PGrid), pointer :: grid_p
  330. integer :: n, middle
  331. !
  332. ! if list size is 1, consider it sorted and return it
  333. if ( (gridlist % nitems <= 1) ) then
  334. gl_sorted => Agrif_gl_build_from_gp(gridlist % first)
  335. return
  336. endif
  337. !
  338. ! else split the list into two sublists
  339. n = 1
  340. middle = gridlist % nitems / 2
  341. grid_p => gridlist % first
  342. !
  343. allocate( gl_left, gl_right )
  344. !
  345. do while ( associated(grid_p) )
  346. if ( n <= middle ) then
  347. call Agrif_gl_append(gl_left, grid_p % gr)
  348. else
  349. call Agrif_gl_append(gl_right, grid_p % gr)
  350. endif
  351. grid_p => grid_p % next
  352. n = n+1
  353. enddo
  354. !
  355. ! recursively call Agrif_gl_merge_sort() to further split each sublist until sublist size is 1
  356. gl_sorted_left => Agrif_gl_merge_sort(gl_left, compare_func, compare_func_opt)
  357. gl_sorted_right => Agrif_gl_merge_sort(gl_right, compare_func, compare_func_opt)
  358. !
  359. ! merge the sublists returned from prior calls to gl_merge_sort() and return the resulting merged sublist
  360. gl_sorted => Agrif_gl_merge(gl_sorted_left, gl_sorted_right, compare_func, compare_func_opt)
  361. !
  362. call Agrif_gl_delete( gl_left )
  363. call Agrif_gl_delete( gl_right )
  364. call Agrif_gl_delete( gl_sorted_left )
  365. call Agrif_gl_delete( gl_sorted_right )
  366. !---------------------------------------------------------------------------------------------------
  367. end function Agrif_gl_merge_sort
  368. !===================================================================================================
  369. !
  370. !===================================================================================================
  371. function Agrif_gl_merge ( gl_left, gl_right, compare_func, compare_func_opt ) result( gl_merged )
  372. !---------------------------------------------------------------------------------------------------
  373. type(Agrif_Grid_List), intent(inout) :: gl_left
  374. type(Agrif_Grid_List), intent(inout) :: gl_right
  375. procedure(compare_grids) :: compare_func
  376. procedure(compare_grids), optional :: compare_func_opt
  377. !
  378. type(Agrif_Grid_List), pointer :: gl_merged
  379. type(Agrif_Grid), pointer :: poped_grid
  380. integer :: comp_value
  381. !
  382. allocate( gl_merged )
  383. !
  384. do while ( gl_left % nitems > 0 .or. gl_right % nitems > 0 )
  385. !
  386. if ( gl_left % nitems > 0 .and. gl_right % nitems > 0 ) then
  387. !
  388. ! Let.s compare both items with the first compare function
  389. comp_value = compare_func( gl_left % first % gr, gl_right % first % gr )
  390. !
  391. if ( comp_value < 0 ) then ; poped_grid => Agrif_gl_popfirst(gl_left)
  392. elseif ( comp_value > 0 ) then ; poped_grid => Agrif_gl_popfirst(gl_right)
  393. else ! ( comp_value == 0 )
  394. !
  395. ! Both items are equal, let.s use the second criterion if the optional
  396. ! compare function is present.
  397. if ( present(compare_func_opt) ) then
  398. !
  399. comp_value = compare_func_opt( gl_left % first % gr, gl_right % first % gr )
  400. !
  401. if ( comp_value <= 0 ) then ; poped_grid => Agrif_gl_popfirst(gl_left)
  402. else ; poped_grid => Agrif_gl_popfirst(gl_right)
  403. endif
  404. else
  405. ! If the second criterion is not present, let.s just pick the left item
  406. poped_grid => Agrif_gl_popfirst(gl_left)
  407. endif
  408. endif
  409. !
  410. ! If one of the lists is empty, we just have to pick in the other one.
  411. elseif ( gl_left % nitems > 0 ) then ; poped_grid => Agrif_gl_popfirst(gl_left)
  412. elseif ( gl_right % nitems > 0 ) then ; poped_grid => Agrif_gl_popfirst(gl_right)
  413. endif
  414. !
  415. call Agrif_gl_append( gl_merged, poped_grid )
  416. !
  417. enddo
  418. !---------------------------------------------------------------------------------------------------
  419. end function Agrif_gl_merge
  420. !===================================================================================================
  421. !
  422. !===================================================================================================
  423. function compare_grid_degrees ( grid1, grid2 ) result( res )
  424. !---------------------------------------------------------------------------------------------------
  425. type(Agrif_Grid), intent(in) :: grid1
  426. type(Agrif_Grid), intent(in) :: grid2
  427. !
  428. integer :: res
  429. !
  430. res = grid2 % neigh_list % nitems - grid1 % neigh_list % nitems
  431. !---------------------------------------------------------------------------------------------------
  432. end function compare_grid_degrees
  433. !===================================================================================================
  434. !
  435. !===================================================================================================
  436. function compare_colors ( grid1, grid2 ) result( res )
  437. !---------------------------------------------------------------------------------------------------
  438. type(Agrif_Grid), intent(in) :: grid1
  439. type(Agrif_Grid), intent(in) :: grid2
  440. !
  441. integer :: res
  442. !
  443. res = grid1 % seq_num - grid2 % seq_num
  444. !---------------------------------------------------------------------------------------------------
  445. end function compare_colors
  446. !===================================================================================================
  447. !
  448. !===================================================================================================
  449. function compare_dsat_values ( grid1, grid2 ) result( res )
  450. !---------------------------------------------------------------------------------------------------
  451. type(Agrif_Grid), intent(in) :: grid1
  452. type(Agrif_Grid), intent(in) :: grid2
  453. !
  454. integer :: res
  455. !
  456. res = grid2 % dsat - grid1 % dsat
  457. !---------------------------------------------------------------------------------------------------
  458. end function compare_dsat_values
  459. !===================================================================================================
  460. !
  461. !===================================================================================================
  462. function compare_size_values ( grid1, grid2 ) result( res )
  463. !---------------------------------------------------------------------------------------------------
  464. type(Agrif_Grid), intent(in) :: grid1
  465. type(Agrif_Grid), intent(in) :: grid2
  466. !
  467. integer :: res
  468. !
  469. res = grid2 % size - grid1 % size
  470. !---------------------------------------------------------------------------------------------------
  471. end function compare_size_values
  472. !===================================================================================================
  473. !
  474. end module Agrif_Grids