SCALE-RM
scale_prc.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
10 #include "scalelib.h"
11 module scale_prc
12  !-----------------------------------------------------------------------------
13  !
14  !++ used modules
15  !
16  use mpi
17  use scale_precision
18  use scale_io
19  use scale_fpm, only: &
20  fpm_alive, &
22  use scale_sigvars
23  !-----------------------------------------------------------------------------
24  implicit none
25  private
26  !-----------------------------------------------------------------------------
27  !
28  !++ Public procedure
29  !
30  public :: prc_mpistart
31  public :: prc_universal_setup
32  public :: prc_global_setup
33  public :: prc_local_setup
34  public :: prc_singlecom_setup
35  public :: prc_abort
36  public :: prc_mpifinish
37  public :: prc_mpisplit
38 
39  public :: prc_mpibarrier
40  public :: prc_mpitime
41  public :: prc_mpitimestat
42 
43  public :: prc_set_file_closer
44 
45  public :: prc_errhandler_setup
46 
47  abstract interface
48  subroutine closer( skip_abort )
49  logical, intent(in), optional :: skip_abort
50  end subroutine closer
51  end interface
52 
53  !-----------------------------------------------------------------------------
54  !
55  !++ Public parameters & variables
56  !
57  !-----------------------------------------------------------------------------
58  ! [ communicator system ]
59  ! MPI_COMM_WORLD
60  ! |
61  ! PRC_UNIVERSAL_COMM_WORLD --split--> BULK_COMM_WORLD
62  ! |
63  ! PRC_GLOBAL_COMM_WORLD --split--> PRC_LOCAL_COMM_WORLD
64  !-----------------------------------------------------------------------------
65  integer, public, parameter :: prc_masterrank = 0
66  integer, public, parameter :: prc_domain_nlim = 10000
67  integer, public, parameter :: prc_comm_null = mpi_comm_null
68 
69  ! universal world
70  integer, public :: prc_universal_comm_world = -1
71  integer, public :: prc_universal_myrank = -1
72  integer, public :: prc_universal_nprocs = -1
73  logical, public :: prc_universal_ismaster = .false.
74 
75  integer, public :: prc_universal_jobid = 0
76 
77  ! global world
78  integer, public :: prc_global_comm_world = -1
79  integer, public :: prc_global_myrank = -1
80  integer, public :: prc_global_nprocs = -1
81  logical, public :: prc_global_ismaster = .false.
82 
83  integer, public :: prc_global_domainid = 0
84  integer, public :: prc_global_root(prc_domain_nlim+1)
85 
86  ! local world
87  integer, public :: prc_local_comm_world = -1
88  integer, public :: prc_nprocs = 1
89  integer, public :: prc_myrank = 0
90  logical, public :: prc_ismaster = .false.
91 
92  ! error handling
93  logical, public :: prc_mpi_alive = .false.
94  integer, public :: prc_universal_handler
95  integer, public :: prc_abort_comm_world
96  integer, public :: prc_abort_handler
97 
98  !-----------------------------------------------------------------------------
99  !
100  !++ Private procedure
101  !
102  private :: prc_mpicoloring
103  private :: prc_sort_ascd
104 
105  !-----------------------------------------------------------------------------
106  !
107  !++ Private parameters & variables
108  !
109  integer, private, parameter :: prc_abort_code = -1
110 ! integer, private, parameter :: PRC_ABORT_code_p = 2 !< mpi abort code in error handler from parent
111 ! integer, private, parameter :: PRC_ABORT_code_d = 3 !< mpi abort code in error handler from daughter
112 
113  procedure(closer), pointer :: prc_file_closer => null()
114 
115  !-----------------------------------------------------------------------------
116 contains
117  !-----------------------------------------------------------------------------
119  subroutine prc_mpistart( &
120  comm )
121  implicit none
122 
123  integer, intent(out) :: comm ! communicator
124 
125  integer :: ierr
126  !---------------------------------------------------------------------------
127 
128  call mpi_init(ierr)
129 
130  prc_mpi_alive = .true.
131 ! PRC_UNIVERSAL_handler = MPI_ERRHANDLER_NULL
132 ! call MPI_COMM_CREATE_ERRHANDLER( PRC_MPI_errorhandler, PRC_UNIVERSAL_handler, ierr )
133 
134  comm = mpi_comm_world
135  prc_abort_comm_world = comm
136 
137  return
138  end subroutine prc_mpistart
139 
140  !-----------------------------------------------------------------------------
142  subroutine prc_universal_setup( &
143  comm, &
144  nprocs, &
145  ismaster )
146  implicit none
147 
148  integer, intent(in) :: comm ! communicator
149  integer, intent(out) :: nprocs ! number of procs in this communicator
150  logical, intent(out) :: ismaster ! master process in this communicator?
151 
152  integer :: ierr
153  !---------------------------------------------------------------------------
154 
156 
157  call mpi_comm_size(prc_universal_comm_world,prc_universal_nprocs,ierr)
158  call mpi_comm_rank(prc_universal_comm_world,prc_universal_myrank,ierr)
159 
160  if ( prc_universal_myrank == prc_masterrank ) then
161  prc_universal_ismaster = .true.
162  else
163  prc_universal_ismaster = .false.
164  endif
165 
166  nprocs = prc_universal_nprocs
167  ismaster = prc_universal_ismaster
168 
169 
170 
171 ! PRC_ABORT_COMM_WORLD = PRC_UNIVERSAL_COMM_WORLD
172 !
173 ! call MPI_Comm_set_errhandler(PRC_ABORT_COMM_WORLD,PRC_UNIVERSAL_handler,ierr)
174 ! call MPI_Comm_get_errhandler(PRC_ABORT_COMM_WORLD,PRC_ABORT_handler ,ierr)
175 
176  return
177  end subroutine prc_universal_setup
178 
179  !-----------------------------------------------------------------------------
181  subroutine prc_global_setup( &
182  abortall, &
183  comm )
184  implicit none
185 
186  logical, intent(in) :: abortall ! abort all jobs?
187  integer, intent(in) :: comm ! communicator
188 
189  integer :: ierr
190  !---------------------------------------------------------------------------
191 
192  prc_global_comm_world = comm
193 
194  call mpi_comm_size(prc_global_comm_world,prc_global_nprocs,ierr)
195  call mpi_comm_rank(prc_global_comm_world,prc_global_myrank,ierr)
196 
197  if ( prc_global_myrank == prc_masterrank ) then
198  prc_global_ismaster = .true.
199  else
200  prc_global_ismaster = .false.
201  endif
202 
203 ! if ( .NOT. abortall ) then
204 ! PRC_ABORT_COMM_WORLD = PRC_GLOBAL_COMM_WORLD
205 !
206 ! call MPI_COMM_SET_ERRHANDLER(PRC_ABORT_COMM_WORLD,PRC_UNIVERSAL_handler,ierr)
207 ! call MPI_COMM_GET_ERRHANDLER(PRC_ABORT_COMM_WORLD,PRC_ABORT_handler ,ierr)
208 ! endif
209 
210  return
211  end subroutine prc_global_setup
212 
213  !-----------------------------------------------------------------------------
215  subroutine prc_local_setup( &
216  comm, &
217  myrank, &
218  ismaster )
219  implicit none
220 
221  integer, intent(in) :: comm ! communicator
222  integer, intent(out) :: myrank ! myrank in this communicator
223  logical, intent(out) :: ismaster ! master process in this communicator?
224 
225  integer :: ierr
226  !---------------------------------------------------------------------------
227 
228  prc_local_comm_world = comm
229 
230  call mpi_comm_rank(prc_local_comm_world,prc_myrank,ierr)
231  call mpi_comm_size(prc_local_comm_world,prc_nprocs,ierr)
232 
233  if ( prc_myrank == prc_masterrank ) then
234  prc_ismaster = .true.
235  else
236  prc_ismaster = .false.
237  endif
238 
239  myrank = prc_myrank
240  ismaster = prc_ismaster
241 
242  return
243  end subroutine prc_local_setup
244 
245  !-----------------------------------------------------------------------------
247  subroutine prc_singlecom_setup( &
248  comm, &
249  nprocs, &
250  myrank, &
251  ismaster )
252  implicit none
253 
254  integer, intent(in) :: comm ! communicator
255  integer, intent(out) :: nprocs ! number of procs
256  integer, intent(out) :: myrank ! myrank
257  logical, intent(out) :: ismaster ! master process?
258 
259  integer :: ierr
260  !---------------------------------------------------------------------------
261 
262  call mpi_comm_size(comm,nprocs,ierr)
263  call mpi_comm_rank(comm,myrank,ierr)
264 
265  if ( myrank == prc_masterrank ) then
266  ismaster = .true.
267  else
268  ismaster = .false.
269  endif
270 
272  prc_universal_nprocs = nprocs
273  prc_universal_myrank = myrank
274  prc_universal_ismaster = ismaster
275 
276  prc_global_comm_world = comm
277  prc_global_nprocs = nprocs
278  prc_global_myrank = myrank
279  prc_global_ismaster = ismaster
280 
281  prc_local_comm_world = comm
282  prc_nprocs = nprocs
283  prc_myrank = myrank
284  prc_ismaster = ismaster
285 
286 
287 
288  prc_abort_comm_world = comm
289 
290 ! call MPI_Comm_set_errhandler(PRC_ABORT_COMM_WORLD,PRC_UNIVERSAL_handler,ierr)
291 ! call MPI_Comm_get_errhandler(PRC_ABORT_COMM_WORLD,PRC_ABORT_handler ,ierr)
292 
293  return
294  end subroutine prc_singlecom_setup
295 
296  !-----------------------------------------------------------------------------
298  subroutine prc_errhandler_setup( &
299  use_fpm, &
300  master )
301  implicit none
302 
303  logical, intent(in) :: use_fpm ! fpm switch
304  logical, intent(in) :: master ! master flag
305 
306  integer :: ierr
307  !---------------------------------------------------------------------------
308 
309  call mpi_comm_create_errhandler(prc_mpi_errorhandler,prc_universal_handler,ierr)
310 
311  call mpi_comm_set_errhandler(prc_abort_comm_world,prc_universal_handler,ierr)
312  call mpi_comm_get_errhandler(prc_abort_comm_world,prc_abort_handler ,ierr)
313 
315  if( prc_universal_ismaster ) write(*,*) ""
316  if( prc_universal_ismaster ) write(*,*) "ERROR: MPI HANDLER is INCONSISTENT"
317  if( prc_universal_ismaster ) write(*,*) " PRC_UNIVERSAL_handler = ", prc_universal_handler
318  if( prc_universal_ismaster ) write(*,*) " PRC_ABORT_handler = ", prc_abort_handler
319  call prc_abort
320  endif
321 
322  if ( use_fpm ) then
323  call sigvars_get_all( master )
324  call signal( sigint, prc_abort )
325  call signal( sigquit, prc_abort )
326  call signal( sigabrt, prc_abort )
327  call signal( sigfpe, prc_abort )
328  call signal( sigsegv, prc_abort )
329  call signal( sigterm, prc_abort )
330  endif
331 
332  return
333  end subroutine prc_errhandler_setup
334 
335  !-----------------------------------------------------------------------------
337  subroutine prc_abort
338  implicit none
339 
340  integer :: ierr
341  !---------------------------------------------------------------------------
342 
343  if ( prc_mpi_alive ) then
344  ! tentative approach; input "PRC_UNIVERSAL_COMM_WORLD".
345  call mpi_comm_call_errhandler(prc_universal_comm_world,prc_abort_code,ierr)
346  endif
347 
348  stop
349  end subroutine prc_abort
350 
351  !-----------------------------------------------------------------------------
353  subroutine prc_mpifinish
354  implicit none
355 
356  integer :: ierr
357  logical :: sign_status
358  logical :: sign_exit
359  !---------------------------------------------------------------------------
360 
361  ! FPM polling
362  if ( fpm_alive ) then
363  sign_status = .false.
364  sign_exit = .false.
365  do while ( .NOT. sign_exit )
366  call fpm_polling( sign_status, sign_exit )
367  enddo
368  endif
369 
370  if (prc_universal_handler .NE. mpi_errhandler_null) then
371  call mpi_errhandler_free(prc_universal_handler, ierr)
372  endif
373  if (prc_abort_handler .NE. mpi_errhandler_null) then
374  call mpi_errhandler_free(prc_abort_handler, ierr)
375  endif
376 
377  ! Stop MPI
378  if ( prc_mpi_alive ) then
379  log_newline
380  log_progress(*) 'finalize MPI...'
381 
382  ! free splitted communicator
384  call mpi_comm_free(prc_local_comm_world,ierr)
385  endif
386 
387  call mpi_barrier(prc_universal_comm_world,ierr)
388 
389  call mpi_finalize(ierr)
390  log_progress(*) 'MPI is peacefully finalized'
391  endif
392 
393  ! Close logfile, configfile
394  if ( io_l ) then
395  if( io_fid_log /= io_fid_stdout ) close(io_fid_log)
396  endif
397  close(io_fid_conf)
398 
399  return
400  end subroutine prc_mpifinish
401 
402  !-----------------------------------------------------------------------------
404  subroutine prc_mpisplit( &
405  ORG_COMM, & ! [in ]
406  NUM_DOMAIN, & ! [in ]
407  PRC_DOMAINS, & ! [in ]
408  CONF_FILES, & ! [in ]
409  LOG_SPLIT, & ! [in ]
410  bulk_split, & ! [in ]
411  color_reorder, & ! [in ]
412  INTRA_COMM, & ! [out]
413  inter_parent, & ! [out]
414  inter_child, & ! [out]
415  fname_local ) ! [out]
416  implicit none
417 
418  integer, intent(in) :: ORG_COMM
419  integer, intent(in) :: NUM_DOMAIN
420  integer, intent(in) :: PRC_DOMAINS(:)
421  character(len=*), intent(in) :: CONF_FILES(:)
422  logical, intent(in) :: LOG_SPLIT
423  logical, intent(in) :: bulk_split
424  logical, intent(in) :: color_reorder
425  integer, intent(out) :: intra_comm
426  integer, intent(out) :: inter_parent
427  integer, intent(out) :: inter_child
428  character(len=H_LONG), intent(out) :: fname_local
429 
430  integer :: PARENT_COL(prc_domain_nlim) ! parent color number
431  integer :: CHILD_COL(prc_domain_nlim) ! child color number
432  integer :: PRC_ROOT(0:prc_domain_nlim) ! root process in the color
433  integer, allocatable :: COLOR_LIST(:) ! member list in each color
434  integer, allocatable :: KEY_LIST(:) ! local process number in each color
435 
436  integer :: total_nmax
437  integer :: ORG_myrank ! my rank number in the original communicator
438  integer :: ORG_nmax ! total rank number in the original communicator
439 
440  logical :: do_create_p(prc_domain_nlim)
441  logical :: do_create_c(prc_domain_nlim)
442  logical :: reordering
443 
444  character(len=H_LONG) :: COL_FILE(0:prc_domain_nlim)
445  character(len=4) :: col_num
446 
447  integer :: i, ii
448  integer :: itag, ierr
449  !---------------------------------------------------------------------------
450 
451  intra_comm = org_comm
452  inter_parent = mpi_comm_null
453  inter_child = mpi_comm_null
454  fname_local = conf_files(1)
455 
456  if ( num_domain > 1 ) then ! multi domain run
457  call mpi_comm_rank(org_comm,org_myrank,ierr)
458  call mpi_comm_size(org_comm,org_nmax, ierr)
459  allocate( color_list(0:org_nmax-1) )
460  allocate( key_list(0:org_nmax-1) )
461 
462  total_nmax = 0
463  do i = 1, num_domain
464  total_nmax = total_nmax + prc_domains(i)
465  enddo
466  if ( total_nmax /= org_nmax ) then
467  if( prc_universal_ismaster ) then
468  log_error("PRC_MPIsplit",*) "MPI PROCESS NUMBER is INCONSISTENT"
469  log_error_cont(*) " REQUESTED NPROCS = ", total_nmax, " LAUNCHED NPROCS = ", org_nmax
470  end if
471  call prc_abort
472  endif
473 
474  reordering = color_reorder
475  if ( bulk_split ) then
476  reordering = .false.
477  endif
478  call prc_mpicoloring( org_comm, & ! [IN]
479  num_domain, & ! [IN]
480  prc_domains, & ! [IN]
481  conf_files, & ! [IN]
482  reordering, & ! [IN]
483  log_split, & ! [IN]
484  color_list, & ! [OUT]
485  prc_root, & ! [OUT]
486  key_list, & ! [OUT]
487  parent_col, & ! [OUT]
488  child_col, & ! [OUT]
489  col_file ) ! [OUT]
490 
491  if ( bulk_split ) then
492  ii = 1
493  do i=0, prc_domain_nlim
494  prc_global_root(ii) = prc_root(i)
495  ii = ii + 1
496  enddo
497  endif
498 
499  ! split comm_world
500  call mpi_comm_split(org_comm, &
501  color_list(org_myrank), &
502  key_list(org_myrank), &
503  intra_comm, ierr)
504  if ( bulk_split ) then
505  write(col_num,'(I4.4)') color_list(org_myrank)
506  fname_local = col_num
507  prc_universal_jobid = color_list(org_myrank)
508  else
509  fname_local = col_file(color_list(org_myrank))
510  endif
511 
512  ! set parent-child relationship
513  do_create_p(:) = .false.
514  do_create_c(:) = .false.
515  if ( .NOT. bulk_split ) then
516  if ( prc_universal_ismaster ) write(*,*)
517  if ( prc_universal_ismaster ) write(*,*) "INFO [PRC_MPIsplit] Inter-domain relationship information"
518  do i = 1, num_domain-1
519  if ( prc_universal_ismaster ) write(*,'(5x,A,I2.2)') "Relationship No. ", i
520  if ( prc_universal_ismaster ) write(*,'(5x,2(A,I2))') "Parent color = ", parent_col(i), &
521  " <=> child color = ", child_col(i)
522  if ( color_list(org_myrank) == parent_col(i) ) then
523  do_create_p(i) = .true.
524  elseif ( color_list(org_myrank) == child_col(i) ) then
525  do_create_c(i) = .true.
526  endif
527  enddo
528  endif
529 
530  ! create inter-commnunicator
531  inter_parent = mpi_comm_null
532  inter_child = mpi_comm_null
533  if ( .NOT. bulk_split ) then
534  do i = 1, num_domain-1
535  itag = i*100
536  if ( do_create_p(i) ) then ! as a parent
537  call mpi_intercomm_create( intra_comm, prc_masterrank, &
538  org_comm, prc_root(child_col(i)), &
539  itag, inter_child, ierr )
540  elseif( do_create_c(i) ) then ! as a child
541  call mpi_intercomm_create( intra_comm, prc_masterrank, &
542  org_comm, prc_root(parent_col(i)), &
543  itag, inter_parent, ierr )
544  endif
545  call mpi_barrier(org_comm, ierr)
546  enddo
547  endif
548 
549  deallocate( color_list, key_list )
550 
551  elseif ( num_domain == 1 ) then ! single domain run
552  ! if ( PRC_UNIVERSAL_IsMaster ) write (*,*) "INFO [PRC_MPIsplit] a single communicator"
553  else
554  if ( prc_universal_ismaster ) then
555  write(*,*)"ERROR [RPC_MPIsplit] REQUESTED DOMAIN NUMBER IS NOT ACCEPTABLE"
556  end if
557  call prc_abort
558  endif
559 
560  return
561  end subroutine prc_mpisplit
562 
563  !-----------------------------------------------------------------------------
565  subroutine prc_mpicoloring( &
566  ORG_COMM, & ! [in ]
567  NUM_DOMAIN, & ! [in ]
568  PRC_DOMAINS, & ! [in ]
569  CONF_FILES, & ! [in ]
570  color_reorder, & ! [in ]
571  LOG_SPLIT, & ! [in ]
572  COLOR_LIST, & ! [out]
573  PRC_ROOT, & ! [out]
574  KEY_LIST, & ! [out]
575  PARENT_COL, & ! [out]
576  CHILD_COL, & ! [out]
577  COL_FILE ) ! [out]
578  implicit none
579 
580  integer, intent(in) :: ORG_COMM
581  integer, intent(in) :: NUM_DOMAIN
582  integer, intent(in) :: PRC_DOMAINS(:)
583  character(len=*), intent(in) :: CONF_FILES(:)
584  logical, intent(in) :: color_reorder
585  logical, intent(in) :: LOG_SPLIT
586  integer, intent(out) :: COLOR_LIST(:) ! member list in each color
587  integer, intent(out) :: PRC_ROOT(0:prc_domain_nlim) ! root process in each color
588  integer, intent(out) :: KEY_LIST(:) ! local process number in each color
589  integer, intent(out) :: PARENT_COL(:) ! parent color number
590  integer, intent(out) :: CHILD_COL(:) ! child color number
591  character(len=H_LONG), intent(out) :: COL_FILE(0:prc_domain_nlim) ! conf file in each color
592 
593  integer :: touch ( prc_domain_nlim)
594  integer :: PRC_ORDER ( prc_domain_nlim) ! reordered number of process
595  integer :: ORDER2DOM ( prc_domain_nlim) ! get domain number by order number
596  integer :: DOM2ORDER ( prc_domain_nlim) ! get order number by domain number
597  integer :: DOM2COL ( prc_domain_nlim) ! get color number by domain number
598  integer :: COL2DOM (0:prc_domain_nlim) ! get domain number by color number
599 
600  integer :: RO_PRC_DOMAINS( prc_domain_nlim) ! reordered values
601  integer :: RO_DOM2COL ( prc_domain_nlim) ! reordered values
602  integer :: RO_PARENT_COL ( prc_domain_nlim) ! reordered values
603  integer :: RO_CHILD_COL ( prc_domain_nlim) ! reordered values
604  character(len=H_LONG) :: RO_CONF_FILES ( prc_domain_nlim) ! reordered values
605 
606  integer :: ORG_nmax ! parent domain number
607  integer :: id_parent ! parent domain number
608  integer :: id_child ! child domain number
609  integer :: dnum, nprc, order, key
610  integer :: i, j
611  integer :: ierr
612  !---------------------------------------------------------------------------
613 
614  order2dom(:) = -1
615  dom2order(:) = -1
616  ro_prc_domains(:) = -1
617  ro_dom2col(:) = -1
618  ro_conf_files(:) = ""
619  ro_parent_col(:) = -1
620  ro_child_col(:) = -1
621 
622  call mpi_comm_size(org_comm,org_nmax, ierr)
623 
624  if ( color_reorder ) then
625  !--- make color order
626  ! domain num is counted from 1
627  ! color num is counted from 0
628  touch(:) = -1
629  prc_order(:) = prc_domains(:)
630 
631  call prc_sort_ascd( prc_order(1:num_domain), 1, num_domain )
632 
633  do i = 1, num_domain
634  do j = num_domain, 1, -1
635  if ( prc_domains(i) == prc_order(j) .AND. touch(j) < 0 ) then
636  dom2col(i ) = j-1 ! domain_num --> color_num
637  col2dom(j-1) = i ! color_num --> domain_num
638  touch(j ) = 1
639  exit
640  endif
641  enddo
642  enddo
643 
644  parent_col(:) = -1
645  child_col(:) = -1
646  do i = 1, num_domain
647  id_parent = i - 1
648  id_child = i + 1
649 
650  if ( 1 <= id_parent .AND. id_parent <= num_domain ) then
651  parent_col(i) = dom2col(id_parent)
652  endif
653  if ( 1 <= id_child .AND. id_child <= num_domain ) then
654  child_col(i) = dom2col(id_child)
655  endif
656 
657  if ( prc_universal_ismaster .AND. log_split ) then
658  write(*,'(1x,A,I2,1x,A,I2,2(2x,A,I2))') &
659  "DOMAIN: ", i, "MY_COL: ", dom2col(i), "PARENT: COL= ", parent_col(i), "CHILD: COL= ", child_col(i)
660  endif
661  enddo
662 
663  !--- reorder following color order
664  do i = 1, num_domain
665  dnum = col2dom(i-1)
666 
667  order2dom(i) = dnum
668  dom2order(dnum) = i
669  ro_prc_domains(i) = prc_domains(dnum)
670  ro_dom2col(dnum) = dom2col(dnum)
671  ro_conf_files(i) = conf_files(dnum)
672  ro_parent_col(i) = parent_col(dnum)
673  ro_child_col(i) = child_col(dnum)
674  enddo
675 
676  !--- set relationship by ordering of relationship number
677  parent_col(:) = -1
678  child_col(:) = -1
679  do i = 1, num_domain-1
680  parent_col(i) = ro_parent_col(dom2order(i+1)) ! from child to parent
681  child_col(i) = ro_child_col(dom2order(i) ) ! from parent to child
682  enddo
683 
684  if( prc_universal_ismaster ) write(*,*)
685  if( prc_universal_ismaster ) write(*,*) 'INFO [PRC_MPIcoloring] Domain information (with reordering)'
686  do i = 1, num_domain
687  if( prc_universal_ismaster ) write(*,*)
688  if( prc_universal_ismaster ) write(*,'(5x,2(A,I2.2))') "Order No. ",i," -> Domain No. ", order2dom(i)
689  if( prc_universal_ismaster ) write(*,'(5x,A,I5)') "Number of process = ", ro_prc_domains(i)
690  if( prc_universal_ismaster ) write(*,'(5x,A,I5)') "Color of this domain = ", ro_dom2col(order2dom(i))
691  if ( ro_parent_col(i) >= 0 ) then
692  if( prc_universal_ismaster ) write(*,'(5x,A,I5)') "Color of parent domain = ", ro_parent_col(i)
693  else
694  if( prc_universal_ismaster ) write(*,'(5x,A)' ) "Color of parent domain = no parent"
695  endif
696  if ( ro_child_col(i) >= 0 ) then
697  if( prc_universal_ismaster ) write(*,'(5x,A,I5)') "Color of child domain = ", ro_child_col(i)
698  else
699  if( prc_universal_ismaster ) write(*,'(5x,A)' ) "Color of child domain = no child"
700  endif
701  if( prc_universal_ismaster ) write(*,'(5x,A,A)') "Name of config file = ", trim(ro_conf_files(i))
702  enddo
703 
704  do i = 1, num_domain
705  col_file(i-1) = ro_conf_files(i) ! final copy
706  enddo
707 
708  else !--- without reordering of colors
709 
710  do i = 1, num_domain
711  order2dom(i) = i
712  ro_prc_domains(i) = prc_domains(i)
713  ro_dom2col(i) = i-1
714  ro_conf_files(i) = conf_files(i)
715  enddo
716 
717  do i = 1, num_domain
718  id_parent = i - 1
719  id_child = i + 1
720 
721  if ( 1 <= id_parent .AND. id_parent <= num_domain ) then
722  ro_parent_col(i) = ro_dom2col(id_parent)
723  endif
724  if ( 1 <= id_child .AND. id_child <= num_domain ) then
725  ro_child_col(i) = ro_dom2col(id_child)
726  endif
727  enddo
728 
729  ! make relationship
730  do i = 1, num_domain-1
731  parent_col(i) = ro_parent_col(i+1) ! from child to parent
732  child_col(i) = ro_child_col(i ) ! from parent to child
733  enddo
734 
735  endif
736 
737  ! make a process table
738  order = 1
739  key = 0
740  nprc = ro_prc_domains(order)
741  prc_root(:) = -999
742 
743  do i = 0, org_nmax-1
744  color_list(i+1) = ro_dom2col(order2dom(order))
745  key_list(i+1) = key
746 
747  if ( key == 0 ) then
748  prc_root(color_list(i+1)) = i
749  col_file(color_list(i+1)) = ro_conf_files(order)
750  endif
751 
752  if ( log_split .AND. prc_universal_ismaster ) then
753  write(*,'(5x,4(A,I5))') &
754  "PE:", i, " COLOR:", color_list(i+1), " KEY:", key_list(i+1), " PRC_ROOT:", prc_root(color_list(i+1))
755  endif
756 
757  key = key + 1
758  if ( key >= nprc ) then
759  order = order + 1
760  key = 0
761  nprc = ro_prc_domains(order)
762  endif
763  enddo
764 
765  return
766  end subroutine prc_mpicoloring
767 
768  !-----------------------------------------------------------------------------
770  recursive subroutine prc_sort_ascd(a, top, bottom)
771  implicit none
772  integer, intent(inout) :: a(:)
773  integer, intent(in) :: top, bottom
774  integer :: i, j, cnt, trg
775  !---------------------------------------------------------------------------
776  cnt = a( (top+bottom) / 2 )
777  i = top; j = bottom
778  do
779  do while ( a(i) > cnt ) !ascending evaluation
780  i = i + 1
781  enddo
782  do while ( cnt > a(j) ) !ascending evaluation
783  j = j - 1
784  enddo
785  if ( i >= j ) exit
786  trg = a(i); a(i) = a(j); a(j) = trg
787  i = i + 1
788  j = j - 1
789  enddo
790  if ( top < i-1 ) call prc_sort_ascd( a, top, i-1 )
791  if ( j+1 < bottom ) call prc_sort_ascd( a, j+1, bottom )
792  return
793  end subroutine prc_sort_ascd
794 
795  !-----------------------------------------------------------------------------
797  subroutine prc_mpibarrier
798  implicit none
799 
800  integer :: ierr
801  !---------------------------------------------------------------------------
802 
803  if ( prc_mpi_alive ) then
804  call mpi_barrier(prc_local_comm_world,ierr)
805  endif
806 
807  end subroutine prc_mpibarrier
808 
809  !-----------------------------------------------------------------------------
812  function prc_mpitime() result(time)
813  implicit none
814 
815  real(DP) :: time
816  !---------------------------------------------------------------------------
817 
818  if ( prc_mpi_alive ) then
819  time = real(MPI_WTIME(), kind=dp)
820  else
821  call cpu_time(time)
822  endif
823 
824  end function prc_mpitime
825 
826  !-----------------------------------------------------------------------------
828  subroutine prc_mpitimestat( &
829  avgvar, &
830  maxvar, &
831  minvar, &
832  maxidx, &
833  minidx, &
834  var )
835  implicit none
836 
837  real(DP), intent(out) :: avgvar(:)
838  real(DP), intent(out) :: maxvar(:)
839  real(DP), intent(out) :: minvar(:)
840  integer, intent(out) :: maxidx(:)
841  integer, intent(out) :: minidx(:)
842  real(DP), intent(in) :: var(:)
843 
844  real(DP), allocatable :: statval(:,:)
845  integer :: vsize
846 
847  real(DP) :: totalvar
848  integer :: ierr
849  integer :: v, p
850  !---------------------------------------------------------------------------
851 
852  vsize = size(var(:))
853 
854  allocate( statval(vsize,0:prc_nprocs-1) )
855  statval(:,:) = 0.0_dp
856 
857  do v = 1, vsize
858  statval(v,prc_myrank) = var(v)
859  enddo
860 
861  ! MPI broadcast
862  do p = 0, prc_nprocs-1
863  call mpi_bcast( statval(1,p), &
864  vsize, &
865  mpi_double_precision, &
866  p, &
868  ierr )
869  enddo
870 
871  do v = 1, vsize
872  totalvar = 0.0_dp
873  do p = 0, prc_nprocs-1
874  totalvar = totalvar + statval(v,p)
875  enddo
876  avgvar(v) = totalvar / prc_nprocs
877 
878  maxvar(v) = maxval(statval(v,:))
879  minvar(v) = minval(statval(v,:))
880  maxidx(v:v) = maxloc(statval(v,:))
881  minidx(v:v) = minloc(statval(v,:))
882  enddo
883 
884  deallocate( statval )
885 
886  return
887  end subroutine prc_mpitimestat
888 
889  !-----------------------------------------------------------------------------
891  subroutine prc_mpi_errorhandler( &
892  comm, &
893  errcode )
894  implicit none
895 
896  ! attributes are needed to be the same with COMM_ERRHANDLER function
897  integer :: comm
898  integer :: errcode
899 
900  character(len=MPI_MAX_ERROR_STRING) :: msg
901  integer :: len
902  integer :: ierr
903  logical :: sign_status
904  logical :: sign_exit
905  !---------------------------------------------------------------------------
906 
907 !print *, "into errhandler:", PRC_UNIVERSAL_myrank
908 
909  ! FPM polling
910  if ( fpm_alive ) then
911  sign_status = .false.
912  sign_exit = .false.
913  do while ( .NOT. sign_exit )
914  call fpm_polling( sign_status, sign_exit )
915  enddo
916  endif
917 
918  ! Print Error Messages
919  if ( prc_mpi_alive ) then
920  ! flush 1kbyte
921  if ( io_l ) then
922  log_progress(*) 'abort MPI'
923  flush(io_fid_log)
924  endif
925 
926  if ( prc_ismaster ) then
927  write(*,*) '+++++ BULK ID : ', prc_universal_jobid
928  write(*,*) '+++++ DOMAIN ID : ', prc_global_domainid
929  write(*,*) '+++++ MASTER LOCATION : ', prc_universal_myrank,'/',prc_universal_nprocs
930  write(*,*) '+++++ GLOBAL LOCATION : ', prc_global_myrank,'/',prc_global_nprocs
931  write(*,*) '+++++ LOCAL LOCATION : ', prc_myrank,'/',prc_nprocs
932  write(*,*) ''
933  endif
934 
935  if ( errcode == prc_abort_code ) then ! called from PRC_abort
936  ! do nothing
937  elseif( errcode <= mpi_err_lastcode ) then
938  call mpi_error_string(errcode, msg, len, ierr)
939  if( io_l ) write(io_fid_log,*) '+++++ ', errcode, trim(msg)
940  write(*,*) '+++++ ', errcode, trim(msg)
941  else
942  if( io_l ) write(io_fid_log,*) '+++++ Unexpected error code', errcode
943  write(*,*) '+++++ Unexpected error code', errcode
944  endif
945 
946  if ( comm /= prc_abort_comm_world ) then
947  if( io_l ) write(io_fid_log,*) '+++++ Unexpected communicator'
948  write(*,*) '+++++ Unexpected communicator'
949  endif
950  if( io_l ) write(io_fid_log,*) ''
951  write(*,*) ''
952  endif
953 
954  if ( associated( prc_file_closer ) ) call prc_file_closer( .true. )
955 
956  ! Close logfile, configfile
957  if ( io_l ) then
958  if( io_fid_log /= io_fid_stdout ) close(io_fid_log)
959  endif
960  close(io_fid_conf)
961 
962  ! Abort MPI
963  if ( prc_mpi_alive ) then
964  call sleep(5)
965  call mpi_abort(prc_abort_comm_world, prc_abort_code, ierr)
966  endif
967 
968  stop
969  end subroutine prc_mpi_errorhandler
970 
971  subroutine prc_set_file_closer( routine )
972  procedure(closer) :: routine
973 
974  prc_file_closer => routine
975 
976  return
977  end subroutine prc_set_file_closer
978 
979 end module scale_prc
integer, parameter, public prc_domain_nlim
max depth of domains
Definition: scale_prc.F90:66
integer, public prc_universal_nprocs
process num in universal communicator
Definition: scale_prc.F90:72
integer, public prc_global_domainid
my domain ID in global communicator
Definition: scale_prc.F90:83
subroutine, public prc_mpistart(comm)
Start MPI.
Definition: scale_prc.F90:121
subroutine, public prc_mpisplit(ORG_COMM, NUM_DOMAIN, PRC_DOMAINS, CONF_FILES, LOG_SPLIT, bulk_split, color_reorder, INTRA_COMM, inter_parent, inter_child, fname_local)
MPI Communicator Split.
Definition: scale_prc.F90:416
subroutine, public prc_set_file_closer(routine)
Definition: scale_prc.F90:972
subroutine, public prc_global_setup(abortall, comm)
setup MPI in global communicator
Definition: scale_prc.F90:184
integer, public prc_abort_handler
error handler communicator for aborting
Definition: scale_prc.F90:96
logical, public prc_global_ismaster
master process in global communicator?
Definition: scale_prc.F90:81
integer, parameter, public prc_comm_null
Definition: scale_prc.F90:67
subroutine, public sigvars_get_all(master)
Get signal values.
integer, public prc_global_myrank
myrank in global communicator
Definition: scale_prc.F90:79
integer(c_int), public sigterm
module sigvars
integer(c_int), public sigquit
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:55
logical, public prc_mpi_alive
MPI is alive?
Definition: scale_prc.F90:93
logical, public fpm_alive
Definition: scale_fpm.F90:32
integer, public prc_universal_comm_world
original communicator
Definition: scale_prc.F90:70
integer, public prc_nprocs
myrank in local communicator
Definition: scale_prc.F90:88
integer(c_int), public sigint
integer, public prc_universal_myrank
myrank in universal communicator
Definition: scale_prc.F90:71
integer(c_int), public sigabrt
integer, public prc_universal_handler
error handler in universal communicator
Definition: scale_prc.F90:94
logical, public io_l
output log or not? (this process)
Definition: scale_io.F90:61
subroutine, public prc_universal_setup(comm, nprocs, ismaster)
setup MPI in universal communicator
Definition: scale_prc.F90:146
integer, parameter, public io_fid_stdout
Definition: scale_io.F90:54
module PROCESS
Definition: scale_prc.F90:11
integer, public prc_universal_jobid
my job ID in universal communicator
Definition: scale_prc.F90:75
real(dp) function, public prc_mpitime()
Get MPI time.
Definition: scale_prc.F90:813
integer, parameter, public prc_masterrank
master process in each communicator
Definition: scale_prc.F90:65
integer, public prc_global_nprocs
process num in global communicator
Definition: scale_prc.F90:80
integer, public prc_myrank
process num in local communicator
Definition: scale_prc.F90:89
subroutine, public fpm_polling(run_stat, stop_signal)
Main system of FPM.
Definition: scale_fpm.F90:176
subroutine, public prc_singlecom_setup(comm, nprocs, myrank, ismaster)
Setup MPI single communicator (not use universal-global-local setting)
Definition: scale_prc.F90:252
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:338
subroutine, public prc_local_setup(comm, myrank, ismaster)
Setup MPI in local communicator.
Definition: scale_prc.F90:219
module FPM
Definition: scale_fpm.F90:10
subroutine, public prc_mpibarrier
Barrier MPI.
Definition: scale_prc.F90:798
logical, public prc_ismaster
master process in local communicator?
Definition: scale_prc.F90:90
integer, public prc_global_comm_world
global communicator
Definition: scale_prc.F90:78
subroutine, public prc_errhandler_setup(use_fpm, master)
Setup MPI error handler.
Definition: scale_prc.F90:301
subroutine, public prc_mpifinish
Stop MPI peacefully.
Definition: scale_prc.F90:354
module PRECISION
logical, public prc_universal_ismaster
master process in universal communicator?
Definition: scale_prc.F90:73
integer, public prc_local_comm_world
local communicator
Definition: scale_prc.F90:87
integer, public prc_abort_comm_world
communicator for aborting
Definition: scale_prc.F90:95
integer(c_int), public sigsegv
module STDIO
Definition: scale_io.F90:10
integer, public io_fid_log
Log file ID.
Definition: scale_io.F90:56
integer, dimension(prc_domain_nlim+1), public prc_global_root
root processes in global members
Definition: scale_prc.F90:84
subroutine, public prc_mpitimestat(avgvar, maxvar, minvar, maxidx, minidx, var)
Calc global statistics for timer.
Definition: scale_prc.F90:835
integer, parameter, public dp
integer(c_int), public sigfpe