00001 module seq_comm_mct
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 use mct_mod, only : mct_world_init, mct_die
00013 use shr_sys_mod, only : shr_sys_abort, shr_sys_flush
00014 use shr_mpi_mod, only : shr_mpi_chkerr, shr_mpi_bcast
00015 use shr_file_mod, only : shr_file_getUnit, shr_file_freeUnit
00016
00017 implicit none
00018 save
00019 private
00020
00021
00022
00023
00024
00025 public seq_comm_init
00026 public seq_comm_iamin
00027 public seq_comm_iamroot
00028 public seq_comm_mpicom
00029 public seq_comm_iam
00030 public seq_comm_gloiam
00031 public seq_comm_cplpe
00032 public seq_comm_cmppe
00033 public seq_comm_setptrs
00034 public seq_comm_setnthreads
00035 public seq_comm_getnthreads
00036 public seq_comm_printcomms
00037
00038
00039
00040
00041
00042 integer, public :: logunit = 6
00043 integer, public :: loglevel = 1
00044
00045
00046
00047
00048
00049 integer, parameter, public :: ncomps = 12
00050 integer, parameter, public :: LNDID = 1
00051 integer, parameter, public :: ATMID = 2
00052 integer, parameter, public :: OCNID = 3
00053 integer, parameter, public :: ICEID = 4
00054 integer, parameter, public :: GLCID = 5
00055 integer, parameter, public :: CPLID = 6
00056 integer, parameter, public :: GLOID = 7
00057 integer, parameter, public :: CPLATMID = 8
00058 integer, parameter, public :: CPLLNDID = 9
00059 integer, parameter, public :: CPLICEID = 10
00060 integer, parameter, public :: CPLOCNID = 11
00061 integer, parameter, public :: CPLGLCID = 12
00062
00063 character(len=8),parameter,private :: IDname(ncomps) =
00064 (/ ' LND ',' ATM ',' OCN ',' ICE ',' GLC ',
00065 ' CPL ',' GLOBAL ',' CPLATM ',' CPLLND ',' CPLICE ',
00066 ' CPLOCN ',' CPLGLC ' /)
00067
00068 type seq_comm_type
00069 character(len=8) :: name
00070 integer :: ID
00071 integer :: mpicom
00072 integer :: mpigrp
00073 integer :: npes
00074 integer :: nthreads
00075 integer :: iam
00076 logical :: iamroot
00077 integer :: gloiam
00078 integer :: pethreads
00079 integer :: cplpe
00080 integer :: cmppe
00081 logical :: set
00082 end type seq_comm_type
00083
00084 type(seq_comm_type) :: seq_comms(ncomps)
00085
00086 character(*),parameter :: F11 = "(a,a,'(',i3,a,')',a, 3i6,' (',a,i6,')',' (',a,i3,')')"
00087 character(*),parameter :: F12 = "(a,a,'(',i3,a,')',a,2i6,6x,' (',a,i6,')',' (',a,i3,')','(',a,2i6,')')"
00088 character(*),parameter :: F13 = "(a,a,'(',i3,a,')',a,2i6,6x,' (',a,i6,')',' (',a,i3,')')"
00089
00090 #include <mpif.h>
00091
00092
00093 contains
00094
00095
00096 subroutine seq_comm_init(nmlfile, atm_petlist, lnd_petlist, ice_petlist, ocn_petlist, glc_petlist)
00097
00098
00099
00100 implicit none
00101 character(len=*), intent(IN) :: nmlfile
00102 integer, pointer, optional :: atm_petlist(:)
00103 integer, pointer, optional :: lnd_petlist(:)
00104 integer, pointer, optional :: ice_petlist(:)
00105 integer, pointer, optional :: ocn_petlist(:)
00106 integer, pointer, optional :: glc_petlist(:)
00107
00108
00109
00110 integer :: ierr,n
00111 character(*),parameter :: subName = '(seq_comm_init) '
00112 integer :: mpi_group_world
00113 integer :: mype,numpes,myncomps,max_threads
00114 integer :: amin,amax,astr
00115 integer :: lmin,lmax,lstr
00116 integer :: imin,imax,istr
00117 integer :: omin,omax,ostr
00118 integer :: gmin,gmax,gstr
00119 integer :: cmin,cmax,cstr
00120 integer :: pelist(3,1)
00121 integer, pointer :: comps(:)
00122 integer, pointer :: comms(:)
00123 integer :: onecomm
00124 integer :: nu, i
00125 logical,save :: first_pass = .true.
00126 integer ::
00127 atm_ntasks, atm_rootpe, atm_pestride, atm_nthreads,
00128 lnd_ntasks, lnd_rootpe, lnd_pestride, lnd_nthreads,
00129 ice_ntasks, ice_rootpe, ice_pestride, ice_nthreads,
00130 glc_ntasks, glc_rootpe, glc_pestride, glc_nthreads,
00131 ocn_ntasks, ocn_rootpe, ocn_pestride, ocn_nthreads,
00132 cpl_ntasks, cpl_rootpe, cpl_pestride, cpl_nthreads
00133 namelist /ccsm_pes/ &
00134 atm_ntasks, atm_rootpe, atm_pestride, atm_nthreads, &
00135 lnd_ntasks, lnd_rootpe, lnd_pestride, lnd_nthreads, &
00136 ice_ntasks, ice_rootpe, ice_pestride, ice_nthreads, &
00137 glc_ntasks, glc_rootpe, glc_pestride, glc_nthreads, &
00138 ocn_ntasks, ocn_rootpe, ocn_pestride, ocn_nthreads, &
00139 cpl_ntasks, cpl_rootpe, cpl_pestride, cpl_nthreads
00140
00141
00142
00143 if (.not. first_pass) then
00144 write(logunit,*) trim(subname),' ERROR seq_comm_init already called '
00145 call shr_sys_abort()
00146 endif
00147 first_pass = .false.
00148
00149 do n = 1,ncomps
00150 seq_comms(n)%set = .false.
00151 seq_comms(n)%mpicom = MPI_COMM_NULL
00152 seq_comms(n)%iam = -1
00153 seq_comms(n)%iamroot = .false.
00154 seq_comms(n)%npes = -1
00155 seq_comms(n)%nthreads = -1
00156 seq_comms(n)%gloiam = -1
00157 seq_comms(n)%pethreads = -1
00158 seq_comms(n)%cplpe = -1
00159 seq_comms(n)%cmppe = -1
00160 enddo
00161
00162
00163
00164
00165 call mpi_init(ierr)
00166 call shr_mpi_chkerr(ierr,subname//' mpi_init')
00167 call mpi_comm_rank(MPI_COMM_WORLD, mype , ierr)
00168 call shr_mpi_chkerr(ierr,subname//' mpi_comm_rank comm_world')
00169 call mpi_comm_size(MPI_COMM_WORLD, numpes, ierr)
00170 call shr_mpi_chkerr(ierr,subname//' mpi_comm_size comm_world')
00171
00172
00173
00174 do n = 1,ncomps
00175 seq_comms(n)%gloiam = mype
00176 enddo
00177
00178
00179
00180 if (mype == 0) then
00181
00182
00183 atm_ntasks=numpes; atm_rootpe=0; atm_pestride=1; atm_nthreads=1
00184 lnd_ntasks=numpes; lnd_rootpe=0; lnd_pestride=1; lnd_nthreads=1
00185 ice_ntasks=numpes; ice_rootpe=0; ice_pestride=1; ice_nthreads=1
00186 glc_ntasks=numpes; glc_rootpe=0; glc_pestride=1; glc_nthreads=1
00187 ocn_ntasks=numpes; ocn_rootpe=0; ocn_pestride=1; ocn_nthreads=1
00188 cpl_ntasks=numpes; cpl_rootpe=0; cpl_pestride=1; cpl_nthreads=1
00189
00190
00191 nu = shr_file_getUnit()
00192 open(nu,file=trim(nmlfile),status='old', iostat=ierr)
00193 if (ierr == 0) then
00194 ierr = 1
00195 do while( ierr > 0 )
00196 read(nu, nml=ccsm_pes, iostat=ierr)
00197 end do
00198 close(nu)
00199 end if
00200 call shr_file_freeUnit(nu)
00201
00202
00203
00204 if (atm_rootpe < 0 .or. lnd_rootpe < 0 .or. ice_rootpe < 0 .or. &
00205 ocn_rootpe < 0 .or. glc_rootpe < 0 .or. cpl_rootpe < 0) then
00206 write(logunit,*) trim(subname),' ERROR: rootpes must be >= 0'
00207 call shr_sys_abort()
00208 endif
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 endif
00234
00235
00236
00237 if (mype == 0) then
00238 amin = atm_rootpe
00239 amax = atm_rootpe + (atm_ntasks-1)*atm_pestride
00240 astr = atm_pestride
00241
00242 lmin = lnd_rootpe
00243 lmax = lnd_rootpe + (lnd_ntasks-1)*lnd_pestride
00244 lstr = lnd_pestride
00245
00246 imin = ice_rootpe
00247 imax = ice_rootpe + (ice_ntasks-1)*ice_pestride
00248 istr = ice_pestride
00249
00250 omin = ocn_rootpe
00251 omax = ocn_rootpe + (ocn_ntasks-1)*ocn_pestride
00252 ostr = ocn_pestride
00253
00254 gmin = glc_rootpe
00255 gmax = glc_rootpe + (glc_ntasks-1)*glc_pestride
00256 gstr = glc_pestride
00257
00258 cmin = cpl_rootpe
00259 cmax = cpl_rootpe + (cpl_ntasks-1)*cpl_pestride
00260 cstr = cpl_pestride
00261 end if
00262
00263
00264 if(present(atm_petlist)) then
00265 call shr_mpi_bcast(atm_ntasks, MPI_COMM_WORLD, 'atm_ntasks')
00266 call shr_mpi_bcast(atm_rootpe, MPI_COMM_WORLD, 'atm_rootpe')
00267 call shr_mpi_bcast(atm_pestride, MPI_COMM_WORLD, 'atm_pestride')
00268 allocate(atm_petlist(atm_ntasks))
00269 do i = 1, atm_ntasks
00270 atm_petlist(i) = atm_rootpe + (i-1)*atm_pestride
00271 enddo
00272 endif
00273
00274 if(present(lnd_petlist)) then
00275 call shr_mpi_bcast(lnd_ntasks, MPI_COMM_WORLD, 'lnd_ntasks')
00276 call shr_mpi_bcast(lnd_rootpe, MPI_COMM_WORLD, 'lnd_rootpe')
00277 call shr_mpi_bcast(lnd_pestride, MPI_COMM_WORLD, 'lnd_pestride')
00278 allocate(lnd_petlist(lnd_ntasks))
00279 do i = 1, lnd_ntasks
00280 lnd_petlist(i) = lnd_rootpe + (i-1)*lnd_pestride
00281 enddo
00282 endif
00283
00284 if(present(ice_petlist)) then
00285 call shr_mpi_bcast(ice_ntasks, MPI_COMM_WORLD, 'ice_ntasks')
00286 call shr_mpi_bcast(ice_rootpe, MPI_COMM_WORLD, 'ice_rootpe')
00287 call shr_mpi_bcast(ice_pestride, MPI_COMM_WORLD, 'ice_pestride')
00288 allocate(ice_petlist(ice_ntasks))
00289 do i = 1, ice_ntasks
00290 ice_petlist(i) = ice_rootpe + (i-1)*ice_pestride
00291 enddo
00292 endif
00293
00294 if(present(ocn_petlist)) then
00295 call shr_mpi_bcast(ocn_ntasks, MPI_COMM_WORLD, 'ocn_ntasks')
00296 call shr_mpi_bcast(ocn_rootpe, MPI_COMM_WORLD, 'ocn_rootpe')
00297 call shr_mpi_bcast(ocn_pestride, MPI_COMM_WORLD, 'ocn_pestride')
00298 allocate(ocn_petlist(ocn_ntasks))
00299 do i = 1, ocn_ntasks
00300 ocn_petlist(i) = ocn_rootpe + (i-1)*ocn_pestride
00301 enddo
00302 endif
00303
00304 if(present(glc_petlist)) then
00305 call shr_mpi_bcast(glc_ntasks, MPI_COMM_WORLD, 'glc_ntasks')
00306 call shr_mpi_bcast(glc_rootpe, MPI_COMM_WORLD, 'glc_rootpe')
00307 call shr_mpi_bcast(glc_pestride, MPI_COMM_WORLD, 'glc_pestride')
00308 allocate(glc_petlist(glc_ntasks))
00309 do i = 1, glc_ntasks
00310 glc_petlist(i) = glc_rootpe + (i-1)*glc_pestride
00311 enddo
00312 endif
00313
00314 call shr_mpi_bcast(atm_nthreads,MPI_COMM_WORLD,'atm_nthreads')
00315 call shr_mpi_bcast(lnd_nthreads,MPI_COMM_WORLD,'lnd_nthreads')
00316 call shr_mpi_bcast(ocn_nthreads,MPI_COMM_WORLD,'ocn_nthreads')
00317 call shr_mpi_bcast(ice_nthreads,MPI_COMM_WORLD,'ice_nthreads')
00318 call shr_mpi_bcast(glc_nthreads,MPI_COMM_WORLD,'glc_nthreads')
00319 call shr_mpi_bcast(cpl_nthreads,MPI_COMM_WORLD,'cpl_nthreads')
00320
00321
00322
00323 if (mype == 0) then
00324 pelist(1,1) = 0
00325 pelist(2,1) = numpes-1
00326 pelist(3,1) = 1
00327 end if
00328 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00329 call seq_comm_setcomm(GLOID,pelist)
00330
00331 if (mype == 0) then
00332 pelist(1,1) = amin
00333 pelist(2,1) = amax
00334 pelist(3,1) = astr
00335 end if
00336 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00337 call seq_comm_setcomm(ATMID,pelist,atm_nthreads)
00338
00339 if (mype == 0) then
00340 pelist(1,1) = lmin
00341 pelist(2,1) = lmax
00342 pelist(3,1) = lstr
00343 end if
00344 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00345 call seq_comm_setcomm(LNDID,pelist,lnd_nthreads)
00346
00347 if (mype == 0) then
00348 pelist(1,1) = imin
00349 pelist(2,1) = imax
00350 pelist(3,1) = istr
00351 end if
00352 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00353 call seq_comm_setcomm(ICEID,pelist,ice_nthreads)
00354
00355 if (mype == 0) then
00356 pelist(1,1) = gmin
00357 pelist(2,1) = gmax
00358 pelist(3,1) = gstr
00359 end if
00360 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00361 call seq_comm_setcomm(GLCID,pelist,glc_nthreads)
00362
00363 if (mype == 0) then
00364 pelist(1,1) = omin
00365 pelist(2,1) = omax
00366 pelist(3,1) = ostr
00367 end if
00368 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00369 call seq_comm_setcomm(OCNID,pelist,ocn_nthreads)
00370
00371 if (mype == 0) then
00372 pelist(1,1) = cmin
00373 pelist(2,1) = cmax
00374 pelist(3,1) = cstr
00375 end if
00376 call mpi_bcast(pelist, size(pelist), MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
00377 call seq_comm_setcomm(CPLID,pelist,cpl_nthreads)
00378
00379 call seq_comm_joincomm(CPLID,ATMID,CPLATMID)
00380 call seq_comm_joincomm(CPLID,LNDID,CPLLNDID)
00381 call seq_comm_joincomm(CPLID,ICEID,CPLICEID)
00382 call seq_comm_joincomm(CPLID,OCNID,CPLOCNID)
00383 call seq_comm_joincomm(CPLID,GLCID,CPLGLCID)
00384
00385 max_threads = -1
00386 do n = 1,ncomps
00387 max_threads = max(max_threads,seq_comms(n)%nthreads)
00388 enddo
00389 do n = 1,ncomps
00390 seq_comms(n)%pethreads = max_threads
00391 enddo
00392
00393
00394
00395
00396
00397 myncomps = 0
00398 do n = 1,ncomps
00399 if (seq_comms(n)%mpicom /= MPI_COMM_NULL) then
00400 myncomps = myncomps + 1
00401 endif
00402 enddo
00403
00404
00405
00406 allocate(comps(myncomps),comms(myncomps),stat=ierr)
00407 if(ierr/=0) call mct_die(subName,'allocate comps comms',ierr)
00408
00409 myncomps = 0
00410 do n = 1,ncomps
00411 if (seq_comms(n)%mpicom /= MPI_COMM_NULL) then
00412 myncomps = myncomps + 1
00413 if (myncomps > size(comps)) then
00414 write(logunit,*) trim(subname),' ERROR in myncomps ',myncomps,size(comps)
00415 call shr_sys_abort()
00416 endif
00417 comps(myncomps) = seq_comms(n)%ID
00418 comms(myncomps) = seq_comms(n)%mpicom
00419 onecomm = seq_comms(n)%mpicom
00420 endif
00421 enddo
00422
00423 if (myncomps /= size(comps)) then
00424 write(logunit,*) trim(subname),' ERROR in myncomps ',myncomps,size(comps)
00425 call shr_sys_abort()
00426 endif
00427
00428 call mct_world_init(ncomps, MPI_COMM_WORLD, comms, comps)
00429
00430 deallocate(comps,comms)
00431
00432 call seq_comm_printcomms()
00433
00434 end subroutine seq_comm_init
00435
00436
00437 subroutine seq_comm_setcomm(ID,pelist,nthreads)
00438
00439 implicit none
00440 integer,intent(IN) :: ID
00441 integer,intent(IN) :: pelist(:,:)
00442 integer,intent(IN),optional :: nthreads
00443
00444 integer :: mpigrp_world
00445 integer :: mpigrp
00446 integer :: mpicom
00447 integer :: ierr
00448 character(*),parameter :: subName = '(seq_comm_setcomm) '
00449
00450 if (ID < 1 .or. ID > ncomps) then
00451 write(logunit,*) subname,' ID out of range, abort ',ID
00452 call shr_sys_abort()
00453 endif
00454
00455 call mpi_comm_group(MPI_COMM_WORLD, mpigrp_world, ierr)
00456 call shr_mpi_chkerr(ierr,subname//' mpi_comm_group mpigrp_world')
00457 call mpi_group_range_incl(mpigrp_world, 1, pelist, mpigrp,ierr)
00458 call shr_mpi_chkerr(ierr,subname//' mpi_group_range_incl mpigrp')
00459 call mpi_comm_create(MPI_COMM_WORLD, mpigrp, mpicom, ierr)
00460 call shr_mpi_chkerr(ierr,subname//' mpi_comm_create mpigrp')
00461
00462 seq_comms(ID)%set = .true.
00463 seq_comms(ID)%ID = ID
00464 seq_comms(ID)%name = IDname(ID)
00465 seq_comms(ID)%mpicom = mpicom
00466 seq_comms(ID)%mpigrp = mpigrp
00467 if (present(nthreads)) then
00468 seq_comms(ID)%nthreads = nthreads
00469 else
00470 seq_comms(ID)%nthreads = 1
00471 endif
00472
00473 if (mpicom /= MPI_COMM_NULL) then
00474 call mpi_comm_size(mpicom,seq_comms(ID)%npes,ierr)
00475 call shr_mpi_chkerr(ierr,subname//' mpi_comm_size')
00476 call mpi_comm_rank(mpicom,seq_comms(ID)%iam,ierr)
00477 call shr_mpi_chkerr(ierr,subname//' mpi_comm_rank')
00478 if (seq_comms(ID)%iam == 0) then
00479 seq_comms(ID)%iamroot = .true.
00480 else
00481 seq_comms(ID)%iamroot = .false.
00482 endif
00483 else
00484 seq_comms(ID)%npes = -1
00485 seq_comms(ID)%iam = -1
00486 seq_comms(ID)%nthreads = 1
00487 seq_comms(ID)%iamroot = .false.
00488 endif
00489
00490 if (seq_comms(ID)%iamroot) then
00491 write(logunit,F11) trim(subname),' initialize ID ',ID,seq_comms(ID)%name, &
00492 ' pelist =',pelist,' npes =',seq_comms(ID)%npes,' nthreads =',seq_comms(ID)%nthreads
00493 endif
00494
00495 end subroutine seq_comm_setcomm
00496
00497
00498 subroutine seq_comm_joincomm(ID1,ID2,ID)
00499
00500 implicit none
00501 integer,intent(IN) :: ID1
00502 integer,intent(IN) :: ID2
00503 integer,intent(IN) :: ID
00504
00505 integer :: mpigrp
00506 integer :: mpicom
00507 integer :: ierr
00508 integer :: n,nsize
00509 integer,allocatable :: pe_t1(:),pe_t2(:)
00510 character(*),parameter :: subName = '(seq_comm_joincomm) '
00511
00512
00513
00514
00515 if (ID1 < 1 .or. ID1 > ncomps) then
00516 write(logunit,*) subname,' ID1 out of range, abort ',ID1
00517 call shr_sys_abort()
00518 endif
00519 if (ID2 < 1 .or. ID2 > ncomps) then
00520 write(logunit,*) subname,' ID2 out of range, abort ',ID2
00521 call shr_sys_abort()
00522 endif
00523 if (ID < 1 .or. ID > ncomps) then
00524 write(logunit,*) subname,' ID out of range, abort ',ID
00525 call shr_sys_abort()
00526 endif
00527 if (.not. seq_comms(ID1)%set .or. .not. seq_comms(ID2)%set) then
00528 write(logunit,*) subname,' ID1 or ID2 not set ',ID1,ID2
00529 call shr_sys_abort()
00530 endif
00531 if (seq_comms(ID)%set) then
00532 write(logunit,*) subname,' ID already set ',ID
00533 call shr_sys_abort()
00534 endif
00535
00536 call mpi_group_union(seq_comms(ID1)%mpigrp,seq_comms(ID2)%mpigrp,mpigrp,ierr)
00537 call shr_mpi_chkerr(ierr,subname//' mpi_comm_union mpigrp')
00538 call mpi_comm_create(MPI_COMM_WORLD, mpigrp, mpicom, ierr)
00539 call shr_mpi_chkerr(ierr,subname//' mpi_comm_create mpigrp')
00540
00541 seq_comms(ID)%set = .true.
00542 seq_comms(ID)%ID = ID
00543 seq_comms(ID)%name = IDname(ID)
00544 seq_comms(ID)%mpicom = mpicom
00545 seq_comms(ID)%mpigrp = mpigrp
00546 seq_comms(ID)%nthreads = max(seq_comms(ID1)%nthreads,seq_comms(ID2)%nthreads)
00547 seq_comms(ID)%nthreads = max(seq_comms(ID)%nthreads,1)
00548
00549 if (mpicom /= MPI_COMM_NULL) then
00550 call mpi_comm_size(mpicom,seq_comms(ID)%npes,ierr)
00551 call shr_mpi_chkerr(ierr,subname//' mpi_comm_size')
00552 call mpi_comm_rank(mpicom,seq_comms(ID)%iam,ierr)
00553 call shr_mpi_chkerr(ierr,subname//' mpi_comm_rank')
00554 if (seq_comms(ID)%iam == 0) then
00555 seq_comms(ID)%iamroot = .true.
00556 else
00557 seq_comms(ID)%iamroot = .false.
00558 endif
00559 else
00560 seq_comms(ID)%npes = -1
00561 seq_comms(ID)%iam = -1
00562 seq_comms(ID)%iamroot = .false.
00563 endif
00564
00565
00566 #if (1 == 0)
00567 if (loglevel > 3) then
00568
00569
00570
00571 call mpi_group_size(seq_comms(ID1)%mpigrp,nsize,ierr)
00572 allocate(pe_t1(nsize),pe_t2(nsize))
00573 do n = 1,nsize
00574 pe_t1(n) = n-1
00575 pe_t2(n) = -1
00576 enddo
00577 call mpi_group_translate_ranks(seq_comms(ID1)%mpigrp, nsize, pe_t1, mpigrp, pe_t2, ierr)
00578 write(logunit,*) 'ID1 ranks ',pe_t1
00579 write(logunit,*) 'ID1-JOIN ranks ',pe_t2
00580 deallocate(pe_t1,pe_t2)
00581
00582 call mpi_group_size(seq_comms(ID2)%mpigrp,nsize,ierr)
00583 allocate(pe_t1(nsize),pe_t2(nsize))
00584 do n = 1,nsize
00585 pe_t1(n) = n-1
00586 pe_t2(n) = -1
00587 enddo
00588 call mpi_group_translate_ranks(seq_comms(ID2)%mpigrp, nsize, pe_t1, mpigrp, pe_t2, ierr)
00589 write(logunit,*) 'ID2 ranks ',pe_t1
00590 write(logunit,*) 'ID2-JOIN ranks ',pe_t2
00591 deallocate(pe_t1,pe_t2)
00592 endif
00593 #endif
00594
00595 allocate(pe_t1(1),pe_t2(1))
00596 pe_t1(1) = 0
00597 call mpi_group_translate_ranks(seq_comms(ID1)%mpigrp, 1, pe_t1, mpigrp, pe_t2, ierr)
00598 seq_comms(ID)%cplpe = pe_t2(1)
00599 pe_t1(1) = 0
00600 call mpi_group_translate_ranks(seq_comms(ID2)%mpigrp, 1, pe_t1, mpigrp, pe_t2, ierr)
00601 seq_comms(ID)%cmppe = pe_t2(1)
00602 deallocate(pe_t1,pe_t2)
00603
00604 if (seq_comms(ID)%iamroot) then
00605 if (loglevel > 1) then
00606 write(logunit,F12) trim(subname),' initialize ID ',ID,seq_comms(ID)%name, &
00607 ' join IDs =',ID1,ID2,' npes =',seq_comms(ID)%npes, &
00608 ' nthreads =',seq_comms(ID)%nthreads, &
00609 ' cpl/cmp pes =',seq_comms(ID)%cplpe,seq_comms(ID)%cmppe
00610 else
00611 write(logunit,F13) trim(subname),' initialize ID ',ID,seq_comms(ID)%name, &
00612 ' join IDs =',ID1,ID2,' npes =',seq_comms(ID)%npes, &
00613 ' nthreads =',seq_comms(ID)%nthreads
00614 endif
00615 endif
00616
00617 end subroutine seq_comm_joincomm
00618
00619
00620 subroutine seq_comm_printcomms()
00621
00622 implicit none
00623 character(*),parameter :: subName = '(seq_comm_printcomms) '
00624 integer :: m,n,mype,npes,cpes,ierr
00625 character(len=256) :: iamstring
00626 character(*),parameter :: F01 = "(4x,a4,4x ,40(1x,a8))"
00627 character(*),parameter :: F02 = "(4x,i4,3x,a1,40(2x,i6,1x))"
00628 character(*),parameter :: F03 = "(4x,i4,3x,a1,a)"
00629
00630 call mpi_comm_size(MPI_COMM_WORLD, npes , ierr)
00631 call shr_mpi_chkerr(ierr,subname//' mpi_comm_size comm_world')
00632 call mpi_comm_rank(MPI_COMM_WORLD, mype , ierr)
00633 call shr_mpi_chkerr(ierr,subname//' mpi_comm_rank comm_world')
00634
00635 call shr_sys_flush(logunit)
00636 call mpi_barrier(MPI_COMM_WORLD,ierr)
00637 if (mype == 0) then
00638
00639
00640
00641
00642
00643
00644 write(logunit,*) ' '
00645 write(logunit,*) trim(subName),' ID layout : global pes vs local pe for each ID'
00646 write(logunit,F01) ' gpe',(seq_comms(n)%name,n=1,ncomps),'nthrds'
00647 write(logunit,F01) ' ---',(' ------ ' ,n=1,ncomps),'------'
00648 call shr_sys_flush(logunit)
00649 endif
00650 iamstring = ' '
00651 do n = 1,ncomps
00652 if (seq_comms(n)%iam >= 0) then
00653 write(iamstring((n-1)*9+1:n*9),"(2x,i6,1x)") seq_comms(n)%iam
00654 endif
00655 enddo
00656 n = ncomps + 1
00657 write(iamstring((n-1)*9+1:n*9),"(2x,i6,1x)") seq_comms(GLOID)%pethreads
00658
00659 call shr_sys_flush(logunit)
00660 call mpi_barrier(MPI_COMM_WORLD,ierr)
00661 do m = 0,npes-1
00662 if (mype == m) then
00663
00664 write(logunit,F03) mype,':',trim(iamstring)
00665 if (m == npes-1) then
00666 write(logunit,*) ' '
00667 endif
00668 endif
00669 call shr_sys_flush(logunit)
00670 call mpi_barrier(MPI_COMM_WORLD,ierr)
00671 enddo
00672
00673 end subroutine seq_comm_printcomms
00674
00675
00676 subroutine seq_comm_setptrs(ID,mpicom,mpigrp,npes,nthreads,iam,iamroot,gloiam,cplpe,cmppe,pethreads)
00677
00678 implicit none
00679 integer,intent(in) :: ID
00680 integer,intent(out),optional :: mpicom
00681 integer,intent(out),optional :: mpigrp
00682 integer,intent(out),optional :: npes
00683 integer,intent(out),optional :: nthreads
00684 integer,intent(out),optional :: iam
00685 logical,intent(out),optional :: iamroot
00686 integer,intent(out),optional :: gloiam
00687 integer,intent(out),optional :: cplpe
00688 integer,intent(out),optional :: cmppe
00689 integer,intent(out),optional :: pethreads
00690
00691 character(*),parameter :: subName = '(seq_comm_setptrs) '
00692
00693 if (ID < 1 .or. ID > ncomps) then
00694 write(logunit,*) subname,' ID out of range, return ',ID
00695 return
00696 endif
00697
00698 if (present(mpicom)) then
00699 mpicom = seq_comms(ID)%mpicom
00700 endif
00701
00702 if (present(mpigrp)) then
00703 mpigrp = seq_comms(ID)%mpigrp
00704 endif
00705
00706 if (present(npes)) then
00707 npes = seq_comms(ID)%npes
00708 endif
00709
00710 if (present(nthreads)) then
00711 nthreads = seq_comms(ID)%nthreads
00712 endif
00713
00714 if (present(iam)) then
00715 iam = seq_comms(ID)%iam
00716 endif
00717
00718 if (present(iamroot)) then
00719 iamroot = seq_comms(ID)%iamroot
00720 endif
00721
00722 if (present(gloiam)) then
00723 gloiam = seq_comms(ID)%gloiam
00724 endif
00725
00726 if (present(cplpe)) then
00727 cplpe = seq_comms(ID)%cplpe
00728 endif
00729
00730 if (present(cmppe)) then
00731 cmppe = seq_comms(ID)%cmppe
00732 endif
00733
00734 if (present(pethreads)) then
00735 pethreads = seq_comms(ID)%pethreads
00736 endif
00737
00738 end subroutine seq_comm_setptrs
00739
00740 subroutine seq_comm_setnthreads(nthreads)
00741
00742 implicit none
00743 integer,intent(in) :: nthreads
00744 character(*),parameter :: subName = '(seq_comm_setnthreads) '
00745
00746 #ifdef _OPENMP
00747 if (nthreads < 1) then
00748 call shr_sys_abort(subname//' ERROR: nthreads less than one')
00749 endif
00750 call omp_set_num_threads(nthreads)
00751 #endif
00752
00753 end subroutine seq_comm_setnthreads
00754
00755 integer function seq_comm_getnthreads()
00756
00757 implicit none
00758 integer :: omp_get_num_threads
00759 character(*),parameter :: subName = '(seq_comm_getnthreads) '
00760
00761 seq_comm_getnthreads = -1
00762 #ifdef _OPENMP
00763
00764 seq_comm_getnthreads = omp_get_num_threads()
00765
00766 #endif
00767
00768 end function seq_comm_getnthreads
00769
00770 logical function seq_comm_iamin(ID)
00771
00772 implicit none
00773 integer,intent(in) :: ID
00774 character(*),parameter :: subName = '(seq_comm_iamin) '
00775
00776 if (seq_comms(ID)%iam >= 0) then
00777 seq_comm_iamin = .true.
00778 else
00779 seq_comm_iamin = .false.
00780 endif
00781
00782 end function seq_comm_iamin
00783
00784 logical function seq_comm_iamroot(ID)
00785
00786 implicit none
00787 integer,intent(in) :: ID
00788 character(*),parameter :: subName = '(seq_comm_iamroot) '
00789
00790 seq_comm_iamroot = seq_comms(ID)%iamroot
00791
00792 end function seq_comm_iamroot
00793
00794 integer function seq_comm_mpicom(ID)
00795
00796 implicit none
00797 integer,intent(in) :: ID
00798 character(*),parameter :: subName = '(seq_comm_mpicom) '
00799
00800 seq_comm_mpicom = seq_comms(ID)%mpicom
00801
00802 end function seq_comm_mpicom
00803
00804 integer function seq_comm_iam(ID)
00805
00806 implicit none
00807 integer,intent(in) :: ID
00808 character(*),parameter :: subName = '(seq_comm_iam) '
00809
00810 seq_comm_iam = seq_comms(ID)%iam
00811
00812 end function seq_comm_iam
00813
00814 integer function seq_comm_gloiam(ID)
00815
00816 implicit none
00817 integer,intent(in) :: ID
00818 character(*),parameter :: subName = '(seq_comm_gloiam) '
00819
00820 seq_comm_gloiam = seq_comms(ID)%gloiam
00821
00822 end function seq_comm_gloiam
00823
00824 integer function seq_comm_cplpe(ID)
00825
00826 implicit none
00827 integer,intent(in) :: ID
00828 character(*),parameter :: subName = '(seq_comm_cplpe) '
00829
00830 seq_comm_cplpe = seq_comms(ID)%cplpe
00831
00832 end function seq_comm_cplpe
00833
00834 integer function seq_comm_cmppe(ID)
00835
00836 implicit none
00837 integer,intent(in) :: ID
00838 character(*),parameter :: subName = '(seq_comm_cmppe) '
00839
00840 seq_comm_cmppe = seq_comms(ID)%cmppe
00841
00842 end function seq_comm_cmppe
00843
00844 end module seq_comm_mct