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