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  !-----------------------------------------------------------------------------
55  !
56  !++ Private procedure
57  !
58  !-----------------------------------------------------------------------------
59  !
60  !++ Private parameters & variables
61  !
62  !-----------------------------------------------------------------------------
63 contains
64  !-----------------------------------------------------------------------------
66  subroutine prc_setup
67  use scale_process, only: &
68  prc_mpistop, &
70  prc_mpi_alive, &
81  prc_nprocs, &
82  prc_myrank, &
84  implicit none
85 
86  logical :: PRC_PERIODIC_X = .true.
87  logical :: PRC_PERIODIC_Y = .true.
88  logical :: PRC_CART_REORDER = .false.
89 
90  namelist / param_prc / &
91  prc_num_x, &
92  prc_num_y, &
93  prc_periodic_x, &
94  prc_periodic_y, &
95  prc_cart_reorder
96 
97  logical :: period(2)
98  integer :: divide(2)
99  integer :: coords_W(2)
100  integer :: coords_N(2)
101  integer :: coords_E(2)
102  integer :: coords_S(2)
103  integer :: next_coords(2)
104  integer :: iptbl
105  integer :: next(8)
106 
107  integer :: ierr
108  integer :: p
109  !---------------------------------------------------------------------------
110 
111  if( io_l ) write(io_fid_log,*)
112  if( io_l ) write(io_fid_log,*) '++++++ Module[PROCESS] / Categ[ATMOS-RM COMM] / Origin[SCALElib]'
113 
114  if ( io_l ) then
115  write(io_fid_log,*) ''
116  write(io_fid_log,*) '++++++ Start MPI'
117  write(io_fid_log,'(1x,A,I12)') '*** UNIVERSAL_COMM_WORLD : ', prc_universal_comm_world
118  write(io_fid_log,'(1x,A,I12)') '*** total process [UNIVERSAL] : ', prc_universal_nprocs
119  write(io_fid_log,'(1x,A,I12)') '*** my process ID [UNIVERSAL] : ', prc_universal_myrank
120  write(io_fid_log,'(1x,A,L12)') '*** master rank? [UNIVERSAL] : ', prc_universal_ismaster
121  write(io_fid_log,'(1x,A,I12)') '*** GLOBAL_COMM_WORLD : ', prc_global_comm_world
122  write(io_fid_log,'(1x,A,I12)') '*** total process [GLOBAL] : ', prc_global_nprocs
123  write(io_fid_log,'(1x,A,I12)') '*** my process ID [GLOBAL] : ', prc_global_myrank
124  write(io_fid_log,'(1x,A,L12)') '*** master rank? [GLOBAL] : ', prc_global_ismaster
125  write(io_fid_log,'(1x,A,I12)') '*** LOCAL_COMM_WORLD : ', prc_local_comm_world
126  write(io_fid_log,'(1x,A,I12)') '*** total process [LOCAL] : ', prc_nprocs
127  write(io_fid_log,'(1x,A,I12)') '*** my process ID [LOCAL] : ', prc_myrank
128  write(io_fid_log,'(1x,A,L12)') '*** master rank? [LOCAL] : ', prc_ismaster
129  write(io_fid_log,'(1x,A,I12)') '*** ABORT_COMM_WORLD : ', prc_abort_comm_world
130  write(io_fid_log,'(1x,A,I12)') '*** master rank ID [each world] : ', prc_masterrank
131  endif
132 
133  !--- read namelist
134  rewind(io_fid_conf)
135  read(io_fid_conf,nml=param_prc,iostat=ierr)
136  if( ierr < 0 ) then !--- missing
137  if( io_l ) write(io_fid_log,*) '*** Not found namelist. Default used.'
138  elseif( ierr > 0 ) then !--- fatal error
139  write(*,*) 'xxx Not appropriate names in namelist PARAM_PRC. Check!'
140  call prc_mpistop
141  endif
142  if( io_lnml ) write(io_fid_log,nml=param_prc)
143 
144  if( io_l ) write(io_fid_log,*)
145  if( io_l ) write(io_fid_log,*) '*** Process Allocation ***'
146  if( io_l ) write(io_fid_log,*) '*** No. of Node :', prc_num_x," x ",prc_num_y
147 
148  if ( prc_num_x*prc_num_y /= prc_nprocs ) then
149  write(*,*) 'xxx total number of node does not match that requested. Check!'
150  call prc_mpistop
151  endif
152 
153  if ( mod(prc_nprocs,prc_num_x) /= 0 ) then
154  write(*,*) 'xxx number of requested node cannot devide to 2D. Check!'
155  call prc_mpistop
156  endif
157 
158  ! set communication topology
159  allocate( prc_2drank(-1:prc_nprocs-1,2) )
160  prc_2drank(:,:) = -1
161 
162  do p = 0, prc_nprocs-1
163  prc_2drank(p,1) = mod(p,prc_num_x)
164  prc_2drank(p,2) = (p-prc_2drank(p,1)) / prc_num_x
165  enddo
166 
167  divide(1) = prc_num_y
168  divide(2) = prc_num_x
169  period(1) = prc_periodic_y
170  period(2) = prc_periodic_x
171  if ( prc_mpi_alive ) then
172  call mpi_cart_create(prc_local_comm_world,2,divide,period,prc_cart_reorder,iptbl,ierr)
173  call mpi_cart_shift(iptbl,0,1,prc_next(prc_s),prc_next(prc_n),ierr) ! next rank search Down/Up
174  call mpi_cart_shift(iptbl,1,1,prc_next(prc_w),prc_next(prc_e),ierr) ! next rank search Left/Right
175 
176  ! get neighbor_coordinates
177  prc_has_w = prc_next(prc_w) /= mpi_proc_null
178  if( prc_has_w ) call mpi_cart_coords(iptbl,prc_next(prc_w),2,coords_w,ierr)
179  prc_has_n = prc_next(prc_n) /= mpi_proc_null
180  if( prc_has_n ) call mpi_cart_coords(iptbl,prc_next(prc_n),2,coords_n,ierr)
181  prc_has_e = prc_next(prc_e) /= mpi_proc_null
182  if( prc_has_e ) call mpi_cart_coords(iptbl,prc_next(prc_e),2,coords_e,ierr)
183  prc_has_s = prc_next(prc_s) /= mpi_proc_null
184  if( prc_has_s ) call mpi_cart_coords(iptbl,prc_next(prc_s),2,coords_s,ierr)
185  ! next rank search NorthWest
186  if ( .NOT. prc_has_n &
187  .OR. .NOT. prc_has_w ) then
188  prc_next(prc_nw) = mpi_proc_null
189  else
190  next_coords(1) = coords_n(1)
191  next_coords(2) = coords_w(2)
192  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_nw), ierr)
193  endif
194  ! next rank search NorthEast
195  if ( .NOT. prc_has_n &
196  .OR. .NOT. prc_has_e ) then
197  prc_next(prc_ne) = mpi_proc_null
198  else
199  next_coords(1) = coords_n(1)
200  next_coords(2) = coords_e(2)
201  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_ne), ierr)
202  endif
203  ! next rank search SouthWest
204  if ( .NOT. prc_has_s &
205  .OR. .NOT. prc_has_w ) then
206  prc_next(prc_sw) = mpi_proc_null
207  else
208  next_coords(1) = coords_s(1)
209  next_coords(2) = coords_w(2)
210  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_sw), ierr)
211  endif
212  ! next rank search SouthEast
213  if ( .NOT. prc_has_s &
214  .OR. .NOT. prc_has_e ) then
215  prc_next(prc_se) = mpi_proc_null
216  else
217  next_coords(1) = coords_s(1)
218  next_coords(2) = coords_e(2)
219  call mpi_cart_rank(iptbl, next_coords, prc_next(prc_se), ierr)
220  endif
221  call mpi_comm_free(iptbl,ierr)
222  endif
223 
224  next(:) = max(prc_next(:),-1) ! avoid if MPI_PROC_NULL < -1
225 
226  if( io_l ) write(io_fid_log,*) '*** Node topology :'
227  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)') &
228  '*** NW(',next(prc_nw),',',prc_2drank(next(prc_nw),1),',',prc_2drank(next(prc_nw),2),')', &
229  ' - N(',next(prc_n) ,',',prc_2drank(next(prc_n) ,1),',',prc_2drank(next(prc_n) ,2),')', &
230  ' - NE(',next(prc_ne),',',prc_2drank(next(prc_ne),1),',',prc_2drank(next(prc_ne),2),')'
231  if( io_l ) write(io_fid_log,'(1x,A)') '*** |'
232  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)') &
233  '*** W(',next(prc_w),',',prc_2drank(next(prc_w),1),',',prc_2drank(next(prc_w),2),')', &
234  ' - P(',prc_myrank ,',',prc_2drank(prc_myrank, 1),',',prc_2drank(prc_myrank, 2),')', &
235  ' - E(',next(prc_e),',',prc_2drank(next(prc_e),1),',',prc_2drank(next(prc_e),2),')'
236  if( io_l ) write(io_fid_log,'(1x,A)') '*** |'
237  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)') &
238  '*** SW(',next(prc_sw),',',prc_2drank(next(prc_sw),1),',',prc_2drank(next(prc_sw),2),')', &
239  ' - S(',next(prc_s) ,',',prc_2drank(next(prc_s) ,1),',',prc_2drank(next(prc_s) ,2),')', &
240  ' - SE(',next(prc_se),',',prc_2drank(next(prc_se),1),',',prc_2drank(next(prc_se),2),')'
241 
242  return
243  end subroutine prc_setup
244 
245 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_global_ismaster
master process in global communicator?
logical, public io_l
output log or not? (this process)
Definition: scale_stdio.F90:59
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
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?
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
logical, public io_lnml
output log or not? (for namelist, this process)
Definition: scale_stdio.F90:60
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