SCALE-RM
scale_rm_process.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
11  !-----------------------------------------------------------------------------
12  !
13  !++ used modules
14  !
15  use mpi
16  use gtool_file, only: &
18  use scale_precision
19  use scale_stdio
20  !-----------------------------------------------------------------------------
21  implicit none
22  private
23  !-----------------------------------------------------------------------------
24  !
25  !++ Public procedure
26  !
27  public :: prc_setup
28 
29  !-----------------------------------------------------------------------------
30  !
31  !++ Public parameters & variables
32  !
33  !-----------------------------------------------------------------------------
34  integer, public, parameter :: prc_w = 1
35  integer, public, parameter :: prc_n = 2
36  integer, public, parameter :: prc_e = 3
37  integer, public, parameter :: prc_s = 4
38  integer, public, parameter :: prc_nw = 5
39  integer, public, parameter :: prc_ne = 6
40  integer, public, parameter :: prc_sw = 7
41  integer, public, parameter :: prc_se = 8
42 
43  integer, public :: prc_num_x = 1
44  integer, public :: prc_num_y = 1
45 
46  integer, public, allocatable :: prc_2drank(:,:)
47  integer, public :: prc_next(8) = -1
48 
49  logical, public :: prc_has_w
50  logical, public :: prc_has_n
51  logical, public :: prc_has_e
52  logical, public :: prc_has_s
53 
54  logical, public :: prc_periodic_x = .true.
55  logical, public :: prc_periodic_y = .true.
56 
57  !-----------------------------------------------------------------------------
58  !
59  !++ Private procedure
60  !
61  !-----------------------------------------------------------------------------
62  !
63  !++ Private parameters & variables
64  !
65  !-----------------------------------------------------------------------------
66 contains
67  !-----------------------------------------------------------------------------
69  subroutine prc_setup
70  use scale_process, only: &
71  prc_mpistop, &
73  prc_mpi_alive, &
84  prc_nprocs, &
85  prc_myrank, &
87  implicit none
88 
89  logical :: prc_cart_reorder = .false.
90 
91  namelist / param_prc / &
92  prc_num_x, &
93  prc_num_y, &
96  prc_cart_reorder
97 
98  logical :: period(2)
99  integer :: divide(2)
100  integer :: coords_w(2)
101  integer :: coords_n(2)
102  integer :: coords_e(2)
103  integer :: coords_s(2)
104  integer :: next_coords(2)
105  integer :: iptbl
106  integer :: next(8)
107 
108  integer :: ierr
109  integer :: p
110  !---------------------------------------------------------------------------
111 
112  if( io_l ) write(io_fid_log,*)
113  if( io_l ) write(io_fid_log,*) '++++++ Module[PROCESS] / Categ[ATMOS-RM COMM] / Origin[SCALElib]'
114 
115  if ( io_l ) then
116  write(io_fid_log,*) '++++++ Start MPI'
117  write(io_fid_log,*)
118  write(io_fid_log,*) '*** Process information ***'
119  write(io_fid_log,'(1x,A,I12)') '*** UNIVERSAL_COMM_WORLD : ', prc_universal_comm_world
120  write(io_fid_log,'(1x,A,I12)') '*** total process [UNIVERSAL] : ', prc_universal_nprocs
121  write(io_fid_log,'(1x,A,I12)') '*** my process ID [UNIVERSAL] : ', prc_universal_myrank
122  write(io_fid_log,'(1x,A,L12)') '*** master rank? [UNIVERSAL] : ', prc_universal_ismaster
123  write(io_fid_log,'(1x,A,I12)') '*** GLOBAL_COMM_WORLD : ', prc_global_comm_world
124  write(io_fid_log,'(1x,A,I12)') '*** total process [GLOBAL] : ', prc_global_nprocs
125  write(io_fid_log,'(1x,A,I12)') '*** my process ID [GLOBAL] : ', prc_global_myrank
126  write(io_fid_log,'(1x,A,L12)') '*** master rank? [GLOBAL] : ', prc_global_ismaster
127  write(io_fid_log,'(1x,A,I12)') '*** LOCAL_COMM_WORLD : ', prc_local_comm_world
128  write(io_fid_log,'(1x,A,I12)') '*** total process [LOCAL] : ', prc_nprocs
129  write(io_fid_log,'(1x,A,I12)') '*** my process ID [LOCAL] : ', prc_myrank
130  write(io_fid_log,'(1x,A,L12)') '*** master rank? [LOCAL] : ', prc_ismaster
131  write(io_fid_log,'(1x,A,I12)') '*** ABORT_COMM_WORLD : ', prc_abort_comm_world
132  write(io_fid_log,'(1x,A,I12)') '*** master rank ID [each world] : ', prc_masterrank
133  endif
134 
135  !--- read namelist
136  rewind(io_fid_conf)
137  read(io_fid_conf,nml=param_prc,iostat=ierr)
138  if( ierr < 0 ) then !--- missing
139  if( io_l ) write(io_fid_log,*) '*** Not found namelist. Default used.'
140  elseif( ierr > 0 ) then !--- fatal error
141  write(*,*) 'xxx Not appropriate names in namelist PARAM_PRC. Check!'
142  call prc_mpistop
143  endif
144  if( io_nml ) write(io_fid_nml,nml=param_prc)
145 
146  if( io_l ) write(io_fid_log,*)
147  if( io_l ) write(io_fid_log,*) '*** Process allocation ***'
148  if( io_l ) write(io_fid_log,*) '*** No. of Node :', prc_num_x," x ",prc_num_y
149 
150  if ( prc_num_x*prc_num_y /= prc_nprocs ) then
151  write(*,*) 'xxx total number of node does not match that requested. Check!'
152  call prc_mpistop
153  endif
154 
155  if ( mod(prc_nprocs,prc_num_x) /= 0 ) then
156  write(*,*) 'xxx number of requested node cannot devide to 2D. Check!'
157  call prc_mpistop
158  endif
159 
160  ! set communication topology
161  allocate( prc_2drank(-1:prc_nprocs-1,2) )
162  prc_2drank(:,:) = -1
163 
164  do p = 0, prc_nprocs-1
165  prc_2drank(p,1) = mod(p,prc_num_x)
166  prc_2drank(p,2) = (p-prc_2drank(p,1)) / prc_num_x
167  enddo
168 
169  divide(1) = prc_num_y
170  divide(2) = prc_num_x
171  period(1) = prc_periodic_y
172  period(2) = prc_periodic_x
173  if ( prc_mpi_alive ) then
174  call mpi_cart_create(prc_local_comm_world,2,divide,period,prc_cart_reorder,iptbl,ierr)
175  call mpi_cart_shift(iptbl,0,1,prc_next(prc_s),prc_next(prc_n),ierr) ! next rank search Down/Up
176  call mpi_cart_shift(iptbl,1,1,prc_next(prc_w),prc_next(prc_e),ierr) ! next rank search Left/Right
177 
178  ! get neighbor_coordinates
179  prc_has_w = prc_next(prc_w) /= mpi_proc_null
180  if( prc_has_w ) call mpi_cart_coords(iptbl,prc_next(prc_w),2,coords_w,ierr)
181  prc_has_n = prc_next(prc_n) /= mpi_proc_null
182  if( prc_has_n ) call mpi_cart_coords(iptbl,prc_next(prc_n),2,coords_n,ierr)
183  prc_has_e = prc_next(prc_e) /= mpi_proc_null
184  if( prc_has_e ) call mpi_cart_coords(iptbl,prc_next(prc_e),2,coords_e,ierr)
185  prc_has_s = prc_next(prc_s) /= mpi_proc_null
186  if( prc_has_s ) call mpi_cart_coords(iptbl,prc_next(prc_s),2,coords_s,ierr)
187  ! next rank search NorthWest
188  if ( .NOT. prc_has_n &
189  .OR. .NOT. prc_has_w ) then
190  prc_next(prc_nw) = mpi_proc_null
191  else
192  next_coords(1) = coords_n(1)
193  next_coords(2) = coords_w(2)
194  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_nw), ierr)
195  endif
196  ! next rank search NorthEast
197  if ( .NOT. prc_has_n &
198  .OR. .NOT. prc_has_e ) then
199  prc_next(prc_ne) = mpi_proc_null
200  else
201  next_coords(1) = coords_n(1)
202  next_coords(2) = coords_e(2)
203  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_ne), ierr)
204  endif
205  ! next rank search SouthWest
206  if ( .NOT. prc_has_s &
207  .OR. .NOT. prc_has_w ) then
208  prc_next(prc_sw) = mpi_proc_null
209  else
210  next_coords(1) = coords_s(1)
211  next_coords(2) = coords_w(2)
212  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_sw), ierr)
213  endif
214  ! next rank search SouthEast
215  if ( .NOT. prc_has_s &
216  .OR. .NOT. prc_has_e ) then
217  prc_next(prc_se) = mpi_proc_null
218  else
219  next_coords(1) = coords_s(1)
220  next_coords(2) = coords_e(2)
221  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_se), ierr)
222  endif
223  call mpi_comm_free(iptbl,ierr)
224  endif
225 
226  next(:) = max(prc_next(:),-1) ! avoid if MPI_PROC_NULL < -1
227 
228  if( io_l ) write(io_fid_log,*) '*** Node topology :'
229  if( io_l ) write(io_fid_log,'(1x,A,I5,A,I5,A,I5,A,A,I5,A,I5,A,I5,A,A,I5,A,I5,A,I5,A)') &
230  '*** NW(',next(prc_nw),',',prc_2drank(next(prc_nw),1),',',prc_2drank(next(prc_nw),2),')', &
231  ' - N(',next(prc_n) ,',',prc_2drank(next(prc_n) ,1),',',prc_2drank(next(prc_n) ,2),')', &
232  ' - NE(',next(prc_ne),',',prc_2drank(next(prc_ne),1),',',prc_2drank(next(prc_ne),2),')'
233  if( io_l ) write(io_fid_log,'(1x,A)') '*** | | |'
234  if( io_l ) write(io_fid_log,'(1x,A,I5,A,I5,A,I5,A,A,I5,A,I5,A,I5,A,A,I5,A,I5,A,I5,A)') &
235  '*** W(',next(prc_w),',',prc_2drank(next(prc_w),1),',',prc_2drank(next(prc_w),2),')', &
236  ' - P(',prc_myrank ,',',prc_2drank(prc_myrank, 1),',',prc_2drank(prc_myrank, 2),')', &
237  ' - E(',next(prc_e),',',prc_2drank(next(prc_e),1),',',prc_2drank(next(prc_e),2),')'
238  if( io_l ) write(io_fid_log,'(1x,A)') '*** | | |'
239  if( io_l ) write(io_fid_log,'(1x,A,I5,A,I5,A,I5,A,A,I5,A,I5,A,I5,A,A,I5,A,I5,A,I5,A)') &
240  '*** SW(',next(prc_sw),',',prc_2drank(next(prc_sw),1),',',prc_2drank(next(prc_sw),2),')', &
241  ' - S(',next(prc_s) ,',',prc_2drank(next(prc_s) ,1),',',prc_2drank(next(prc_s) ,2),')', &
242  ' - SE(',next(prc_se),',',prc_2drank(next(prc_se),1),',',prc_2drank(next(prc_se),2),')'
243 
244  return
245  end subroutine prc_setup
246 
247 end module scale_rm_process
integer, public prc_num_x
x length of 2D processor topology
module GTOOL_FILE
Definition: gtool_file.f90:17
integer, parameter, public prc_s
[node direction] south
logical, public prc_ismaster
master process in local communicator?
logical, public prc_has_n
integer, parameter, public prc_w
[node direction] west
integer, public prc_local_comm_world
local communicator
subroutine, public prc_mpistop
Abort MPI.
logical, public prc_mpi_alive
MPI is alive?
logical, public prc_periodic_y
periodic condition or not (Y)?
logical, public prc_global_ismaster
master process in global communicator?
logical, public io_l
output log or not? (this process)
Definition: scale_stdio.F90:61
subroutine, public prc_setup
Setup Processor topology.
logical, public prc_has_e
module STDIO
Definition: scale_stdio.F90:12
integer, public prc_universal_nprocs
process num in universal communicator
integer, public prc_universal_comm_world
original communicator
logical, public prc_periodic_x
periodic condition or not (X)?
subroutine, public filecloseall
integer, dimension(8), public prc_next
node ID of 8 neighbour process
logical, public prc_has_s
integer, parameter, public prc_n
[node direction] north
integer, public prc_num_y
y length of 2D processor topology
logical, public prc_universal_ismaster
master process in universal communicator?
logical, public io_nml
output log or not? (for namelist, this process)
Definition: scale_stdio.F90:62
integer, parameter, public prc_nw
[node direction] northwest
integer, public prc_global_comm_world
global communicator
module PROCESS
integer, public prc_global_myrank
myrank in global communicator
integer, parameter, public prc_e
[node direction] east
integer, parameter, public prc_masterrank
master process in each communicator
integer, public prc_myrank
process num in local communicator
module RM PROCESS
integer, parameter, public prc_sw
[node direction] southwest
integer, public prc_global_nprocs
process num in global communicator
module PRECISION
integer, dimension(:,:), allocatable, public prc_2drank
node index in 2D topology
integer, public prc_abort_comm_world
communicator for aborting
integer, parameter, public prc_ne
[node direction] northeast
integer, public io_fid_conf
Config file ID.
Definition: scale_stdio.F90:55
integer, public prc_universal_myrank
myrank in universal communicator
integer, public io_fid_log
Log file ID.
Definition: scale_stdio.F90:56
integer, parameter, public prc_se
[node direction] southeast
logical, public prc_has_w
integer, public prc_nprocs
myrank in local communicator
integer, public io_fid_nml
Log file ID (only for output namelist)
Definition: scale_stdio.F90:57