Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
parallel_mod.F90
Go to the documentation of this file.
1 
2 module parallel
3 ! Communication information
4 ! NOTE: NID is stored in 'SIZE' for greater accessibility
5  use size_m, only : nid
6  implicit none
7 
8  INTEGER :: node,pid,np,nullpid,node0
9 
10 ! Maximum number of elements (limited to 2**31/12, at least for now)
11  !integer, parameter :: NELGT_MAX = 178956970
12 
13  integer, allocatable :: nelg(:)
14  integer :: nvtot, nelgv, nelgt
15 
16  LOGICAL :: ifgprnt
17  INTEGER :: wdsize,isize,lsize,csize,wdsizi
18  LOGICAL :: ifdblas
19 
20 ! crystal-router, gather-scatter, and xxt handles (xxt=csr grid solve)
21 
22  integer :: cr_h, gsh
23  integer, allocatable :: gsh_fld(:), xxth(:)
24 
25  integer :: nekcomm, nekgroup, nekreal
26 
27  ! map information
28  integer, private :: queue_dim(30)
29  integer, private :: queue_fac(30)
30  integer, private :: queue_div(30)
31  integer, private :: num_queue
32  integer :: proc_pos(3)
33  integer :: proc_shape(3)
34 
35 
36  contains
37 
38  subroutine init_parallel()
39  use size_m
40  implicit none
41 
42  allocate(nelg(0:ldimt1))
43  allocate(gsh_fld(0:ldimt3), xxth(ldimt3))
44 
45  end subroutine init_parallel
46 
47  subroutine init_gllnid()
48  use mesh, only : shape_x
49  use size_m, only : lelt
50  use input, only : param
51  implicit none
52 
53  integer :: i, l, iel, ieg
54  integer :: np_targ
55  integer :: my_shape(3), my_nid
56  integer :: factors(30), num_fac
57  integer :: largest_idx
58  integer :: queue_pos
59 
60  factors = -1
61  np_targ = np
62  num_fac = 0
63  do while (np_targ > 1)
64  do i = 2, np_targ
65  if ((np_targ / i) * i == np_targ) then
66  num_fac = num_fac + 1
67  factors(num_fac) = i
68  np_targ = np_targ / i
69  exit
70  endif
71  enddo
72  enddo
73 
74  my_shape = shape_x
75  num_queue = 0
76  do while (num_fac > 0)
77  largest_idx = 3
78  if (my_shape(2) > my_shape(largest_idx)) largest_idx = 2
79  if (my_shape(1) > my_shape(largest_idx)) largest_idx = 1
80 
81  if ((my_shape(largest_idx) / factors(num_fac)) * factors(num_fac) /= my_shape(largest_idx)) then
82  if (nid == 0) write(*,*) "Largest dimension isn't divisible by largest factor"
83  endif
84 
85  my_shape(largest_idx) = my_shape(largest_idx) / factors(num_fac)
86  num_queue = num_queue + 1
87  queue_dim(num_queue) = largest_idx
88  queue_fac(num_queue) = factors(num_fac)
89  queue_div(num_queue) = my_shape(largest_idx)
90  num_fac = num_fac - 1
91  enddo
92  proc_shape = my_shape
93 
94  proc_pos = 0
95  my_nid = nid
96  do queue_pos = num_queue, 1, -1
97  l = queue_dim(queue_pos)
98  proc_pos(l) = proc_pos(l) + mod(my_nid, queue_fac(queue_pos)) * my_shape(l)
99  my_shape(l) = my_shape(l) * queue_fac(queue_pos)
100  my_nid = my_nid / queue_fac(queue_pos)
101  enddo
102 
103  if (param(75) < 1) then
104  do iel = 1, lelt
105  ieg = lglel(iel)
106  if (gllnid(ieg) /= nid .or. gllel(ieg) /= iel) then
107  write(*,*) "LGL/GLL mismatch", nid, gllnid(ieg), iel, gllel(ieg)
108  endif
109  enddo
110  if (nid == 0) write(*,*) "LGL/GLL checks out"
111  endif
112 
113  end subroutine init_gllnid
114 
115  integer function gllnid(ieg)
116  use mesh, only : ieg_to_xyz
117  implicit none
118  integer, intent(in) :: ieg
119 
120  integer :: queue_pos
121  integer :: ix(3)
122 
123  ix = ieg_to_xyz(ieg)
124  gllnid = 0
125  do queue_pos = 1, num_queue
126  gllnid = queue_fac(queue_pos) * gllnid + ix(queue_dim(queue_pos)) / queue_div(queue_pos)
127  ix(queue_dim(queue_pos)) = mod(ix(queue_dim(queue_pos)), queue_div(queue_pos))
128  enddo
129 
130  return
131  end function gllnid
132 
133  logical function my_ieg(ieg)
134  use mesh, only : ieg_to_xyz
135  integer, intent(in) :: ieg
136 
137  integer, save :: my_seq(30) = -1
138  integer :: ix(3)
139  integer :: queue_pos
140 
141  if (my_seq(1) < 0) then
142  ix = ieg_to_xyz(lglel(1))
143  do queue_pos = 1, num_queue
144  my_seq(queue_pos) = ix(queue_dim(queue_pos)) / queue_div(queue_pos)
145  ix(queue_dim(queue_pos)) = mod(ix(queue_dim(queue_pos)), queue_div(queue_pos))
146  enddo
147  endif
148 
149  ix = ieg_to_xyz(ieg)
150  do queue_pos = 1, num_queue
151  if (my_seq(queue_pos) /= ix(queue_dim(queue_pos)) / queue_div(queue_pos)) then
152  my_ieg = .false.
153  return
154  endif
155  ix(queue_dim(queue_pos)) = mod(ix(queue_dim(queue_pos)), queue_div(queue_pos))
156  enddo
157 
158  my_ieg = .true.
159  return
160  end function my_ieg
161 
162  integer function gllel(ieg)
163  use mesh, only : ieg_to_xyz
164  implicit none
165  integer, intent(in) :: ieg
166 
167  integer :: ix(3)
168  ix = ieg_to_xyz(ieg)
169  ix(1) = mod(ix(1), proc_shape(1))
170  ix(2) = mod(ix(2), proc_shape(2))
171  ix(3) = mod(ix(3), proc_shape(3))
172  gllel = 1 + ix(1) + ix(2)*proc_shape(1) + ix(3)*proc_shape(1)*proc_shape(2)
173  return
174  end function gllel
175 
176  integer function lglel(iel)
177  use mesh, only : xyz_to_ieg
178  implicit none
179  integer, intent(in) :: iel
180 
181  integer :: my_pos(3)
182 
183  my_pos(1) = proc_pos(1) + mod((iel - 1), proc_shape(1))
184  my_pos(2) = proc_pos(2) + mod((iel - 1)/(proc_shape(1)), proc_shape(2))
185  my_pos(3) = proc_pos(3) + mod((iel - 1)/(proc_shape(1)*proc_shape(2)), proc_shape(3))
186 
187  lglel = xyz_to_ieg(my_pos)
188  return
189 
190  end function lglel
191 
192 end module parallel
193 
integer function gllel(ieg)
logical function my_ieg(ieg)
Input parameters from preprocessors.
Definition: input_mod.F90:11
integer function xyz_to_ieg(xyz)
Definition: mesh_mod.F90:42
integer function, dimension(3) ieg_to_xyz(ieg)
Definition: mesh_mod.F90:32
subroutine init_gllnid()
subroutine init_parallel()
cleaned
Definition: mesh_mod.F90:2
integer function lglel(iel)
integer function gllnid(ieg)
cleaned
Definition: parallel_mod.F90:2
static uint np
Definition: findpts_test.c:63