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