Back to OASIS3-MCT home
In
oasis3-mct/lib/mct/mct :
m_GlobalSegMap.F90
:
CONTAINS
SUBROUTINE initd_(GSMap=prism_part(m)%gsmap,
start=start,
length=length, root=mpi_root_local,
my_comm=mpi_comm_local, comp_id=compid, pe_loc, gsize, numel) ! arguments in italic are optional but we
put numel
! This routine takes the {\em scattered} input {\tt INTEGER} arrays
! {\tt start}, {\tt length}, and {\tt pe\_loc}, gathers these data to
! the {\tt root} process, and from them creates a {\em global} set of
! segment information for the output {\tt GlobalSegMap} argument
! {\tt GSMap}. The input {\tt INTEGER} arguments {\tt comp\_id},
! {\tt gsize} provide the {\tt GlobalSegMap} component ID number and
! global grid size, respectively. The input argument {\tt
my\_comm} is
! the F90 {\tt INTEGER} handle for the MPI communicator. If the
input
! arrays are overdimensioned, optional argument {\em numel} can be
! used to specify how many elements should be used.
=> MP_COMM_RANK(my_comm, myID, ier)
if(present(numel)) then
nlseg=numel
else
nlseg = size(start)
endif
if(present(pe_loc)) then
my_pe_loc
=> pe_loc
else
allocate(my_pe_loc(nlseg), stat=ier)
! our case
if(ier /= 0)
call die(myname_,'allocate(my_pe_loc)',ier)
my_pe_loc =
myID
endif
=> MPI_COMM_SIZE(my_comm, npes, ier)
nlseg_tmp(1) = nlseg
=> fc_gather_int(nlseg_tmp,
1,
MP_INTEGER, counts, 1, MP_INTEGER, root, my_comm)
if(myID == root) then
ngseg = 0
do i=0,npes-1
ngseg = ngseg + counts(i)
if(i
== 0) then
displs(i) = 0
else
displs(i) = displs(i-1) + counts(i-1)
endif
end do
endif
if(myID == root) then
allocate(root_start(ngseg), root_length(ngseg), &
root_pe_loc(ngseg), stat=ier)
if (ier /=
0) then
call die(myname_,
'allocate(root_start...',ier)
endif
else
allocate(root_start(1), root_length(1), &
root_pe_loc(1), stat=ier)
if (ier /=
0) then
call die(myname_,
'allocate((non)root_start...',ier)
endif
endif
=> fc_gatherv_int(start, nlseg, MP_INTEGER, root_start, counts,
displs, MP_INTEGER, root, my_comm) ! each process sends its values of
start(:) to fill in the appropriate portion of root_start(:y)
=> fc_gatherv_int(length, nlseg, MP_INTEGER, root_length, counts,
displs, MP_INTEGER, root, my_comm) ! each process sends its values of
length(:) to fill in the appropriate portion of root_length(:)
=> fc_gatherv_int(my_pe_loc, nlseg, MP_INTEGER, root_pe_loc, counts,
displs, MP_INTEGER, root, my_comm) ! to fill in the appropriate portion of
root_pe_loc(:) and make the correspondance between the nsegs and the
proc that owns them (because the root
has only a 1D array with all the segments indenpendently from the
process)
=> MPI_BARRIER(my_comm, ier)
if(present(gsize)) then
=> initr_(GSMap, ngseg, root_start, root_length, root_pe_loc, root,
my_comm, comp_id, gsize)
else
=> initr_(GSMap, ngseg, root_start, root_length, root_pe_loc, root,
my_comm, comp_id)
if(myID == root) then
GSMap%ngseg
= ngseg
GSMap%comp_id = comp_id
endif
SUBROUTINE initr_(GSMap,
ngseg, start, length, pe_loc, root, my_comm, comp_id, gsize)
! This routine takes the input {\tt INTEGER} arrays {\tt start},
! {\tt length}, and {\tt pe\_loc} (all valid only on the {\tt root}
! process), and from them creates a {\em global} set of segment
! information for the output {\tt GlobalSegMap} argument
! {\tt GSMap}. The input {\tt INTEGER} arguments {\tt ngseg},
! {\tt comp\_id}, {\tt gsize} (again, valid only on the {\tt root}
! process) provide the {\tt GlobalSegMap} global segment count,
component
! ID number, and global grid size, respectively. The input
argument
! {\tt my\_comm} is the F90 {\tt INTEGER} handle for the MPI
communicator.
! If the argument gsize is present, use the root value to
! set GSMap%gsize and broadcast it. If it is not present,
! this will be computed by summing the entries of GSM%length(:).
! Again, note that if one is storing halo points, the sum will
! produce a result larger than the actual global vector. If
! halo points are to be used in the mapping we advise strongly
! that the user specify the value gsize as an argument.
=> MPI_COMM_RANK(my_comm, myID, ier)
if(myID == root) then
GSMap%ngseg
= ngseg
GSMap%comp_id = comp_id
endif
=> MPI_BCAST(GSMap%ngseg, 1, MP_INTEGER, root, my_comm, ier)
=> MPI_BCAST(GSMap%comp_id, 1, MP_INTEGER, root, my_comm, ier)
if(myID == root) then
GSMap%start(1:GSMap%ngseg) = start(1:GSMap%ngseg)
GSMap%length(1:GSMap%ngseg) = length(1:GSMap%ngseg)
GSMap%pe_loc(1:GSMap%ngseg) = pe_loc(1:GSMap%ngseg)
endif
=> MPI_BCAST(GSMap%start, GSMap%ngseg, MP_INTEGER, root, my_comm,
ier)
=> MPI_BCAST(GSMap%length, GSMap%ngseg, MP_INTEGER, root, my_comm,
ier)
=> MPI_BCAST(GSMap%pe_loc, GSMap%ngseg, MP_INTEGER, root, my_comm,
ier)
if (present(gsize)) then
if(myID ==
root) then
GSMap%gsize = gsize
endif
call
MPI_BCAST(GSMap%gsize, 1, MP_INTEGER, root, my_comm, ier)
if(ier/=0)
call MP_perr_die(myname_, 'MPI_BCAST(GSMap%gsize)', ier)
else
GSMap%gsize
= 0
do
i=1,GSMap%ngseg
GSMap%gsize =
GSMap%gsize + GSMap%length(i)
end do
endif
Function gsize_(GSMap)
! !IROUTINE: gsize_ - Return the global vector size from the
GlobalSegMap.
!
! !DESCRIPTION:
! The function {\tt gsize\_()} takes the input {\tt GlobalSegMap}
! arguement {\tt GSMap} and returns the global vector length stored
! in {\tt GlobalSegMap\%gsize}.
gsize_=GSMap%gsize