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