m_GlobalToLocal.F90 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! Math and Computer Science Division, Argonne National Laboratory !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_GlobalToLocal.F90,v 1.16 2006-04-20 23:54:48 rloy Exp
  5. ! CVS MCT_2_8_0
  6. !BOP -------------------------------------------------------------------
  7. !
  8. ! !MODULE: m_GlobalToLocal - Global to Local Index Translation
  9. !
  10. ! !DESCRIPTION:
  11. ! This module contains routines for translating global array indices
  12. ! into their local counterparts (that is, the indices into the local
  13. ! data structure holding a given process' chunk of a distributed array).
  14. ! The MCT domain decomposition descriptors {\tt GlobalMap} and
  15. ! {\tt GlobalSegMap} are both supported. Indices can be translated
  16. ! one-at-a-time using the {\tt GlobalToLocalIndex} routine or many
  17. ! at once using the {\tt GlobalToLocalIndices} routine.
  18. !
  19. ! This module also provides facilities for setting the local row and
  20. ! column indices for a {\tt SparseMatrix} through the
  21. ! {\tt GlobalToLocalMatrix} routines.
  22. !
  23. ! !INTERFACE:
  24. module m_GlobalToLocal
  25. ! !USES:
  26. ! No external modules are used in the declaration section of this module.
  27. implicit none
  28. private ! except
  29. ! !PUBLIC MEMBER FUNCTIONS:
  30. public :: GlobalToLocalIndex ! Translate Global to Local index
  31. ! (i.e. recover local index for a
  32. ! point from its global index).
  33. public :: GlobalToLocalIndices ! Translate Global to Local indices
  34. ! (i.e. recover local starts/lengths
  35. ! of distributed data segments).
  36. public :: GlobalToLocalMatrix ! Re-indexing of row or column
  37. ! indices for a SparseMatrix
  38. interface GlobalToLocalIndices ; module procedure &
  39. GlobalSegMapToIndices_, & ! local arrays of starts/lengths
  40. GlobalSegMapToNavigator_, & ! return local indices as Navigator
  41. GlobalSegMapToIndexArr_
  42. end interface
  43. interface GlobalToLocalIndex ; module procedure &
  44. GlobalSegMapToIndex_, &
  45. GlobalMapToIndex_
  46. end interface
  47. interface GlobalToLocalMatrix ; module procedure &
  48. GlobalSegMapToLocalMatrix_
  49. end interface
  50. ! !SEE ALSO:
  51. !
  52. ! The MCT modules {\tt m\_GlobalMap} and {m\_GlobalSegMap} for more
  53. ! information regarding MCT's domain decomposition descriptors.
  54. !
  55. ! The MCT module {\tt m\_SparseMatrix} for more information regarding
  56. ! the {\tt SparseMatrix} datatype.
  57. !
  58. ! !REVISION HISTORY:
  59. ! 2Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
  60. !EOP ___________________________________________________________________
  61. character(len=*),parameter :: myname='MCT::m_GlobalToLocal'
  62. contains
  63. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  64. ! Math and Computer Science Division, Argonne National Laboratory !
  65. !BOP -------------------------------------------------------------------
  66. !
  67. ! !IROUTINE: GlobalSegMapToIndices_ - Return _local_ indices in arrays.
  68. !
  69. ! !DESCRIPTION: {\tt GlobalSegMapToIndices\_()} takes a user-supplied
  70. ! {\tt GlobalSegMap} data type {\tt GSMap}, which desribes a decomposition
  71. ! on the input MPI communicator corresponding to the Fortran {\tt INTEGER}
  72. ! handle {\tt comm} to translate the global directory of segment locations
  73. ! into local indices for referencing the on-pe storage of the mapped
  74. ! distributed data.
  75. !
  76. ! {\bf N.B.:} This routine returns two allocated arrays---{\tt start(:)}
  77. ! and {\tt length(:)}---which must be deallocated once the user no longer
  78. ! needs them. Failure to do this will create a memory leak.
  79. !
  80. ! !INTERFACE:
  81. subroutine GlobalSegMapToIndices_(GSMap, comm, start, length)
  82. !
  83. ! !USES:
  84. !
  85. use m_mpif90
  86. use m_die, only : MP_perr_die, die, warn
  87. use m_GlobalSegMap, only : GlobalSegMap
  88. use m_GlobalSegMap, only : GlobalSegMap_ngseg => ngseg
  89. use m_GlobalSegMap, only : GlobalSegMap_nlseg => nlseg
  90. implicit none
  91. ! !INPUT PARAMETERS:
  92. type(GlobalSegMap), intent(in) :: GSMap ! Output GlobalSegMap
  93. integer, intent(in) :: comm ! communicator handle
  94. ! !OUTPUT PARAMETERS:
  95. integer,dimension(:), pointer :: start ! local segment start indices
  96. integer,dimension(:), pointer :: length ! local segment sizes
  97. ! !REVISION HISTORY:
  98. ! 2Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
  99. !EOP ___________________________________________________________________
  100. character(len=*),parameter :: myname_=myname//'::GlobalSegMapToIndices_'
  101. integer :: myID, ierr, ngseg, nlseg, n, count
  102. ! determine local process id myID
  103. call MP_COMM_RANK(comm, myID, ierr)
  104. if(ierr /= 0) call MP_perr_die(myname_,'MP_COMM_RANK',ierr)
  105. ! determine number of global segments ngseg:
  106. ngseg = GlobalSegMap_ngseg(GSMap)
  107. ! determine number of local segments on process myID nlseg:
  108. nlseg = GlobalSegMap_nlseg(GSMap, myID)
  109. ! allocate arrays start(:) and length(:) to store local
  110. ! segment information.
  111. allocate(start(nlseg), length(nlseg), stat=ierr)
  112. if(ierr /= 0) call die(myname_,'allocate(start...',ierr)
  113. ! Loop over GlobalSegMap%pe_loc(:) values to isolate
  114. ! global index values of local data. Record number of
  115. ! matches in the INTEGER count.
  116. count = 0
  117. do n=1, ngseg
  118. if(GSMap%pe_loc(n) == myID) then
  119. count = count + 1
  120. if(count > nlseg) then
  121. ierr = 2
  122. call die(myname_,'too many pe matches',ierr)
  123. endif
  124. start(count) = GSMap%start(n)
  125. length(count) = GSMap%length(n)
  126. endif
  127. end do
  128. if(count < nlseg) then
  129. ierr = 3
  130. call die(myname_,'too few pe matches',ierr)
  131. endif
  132. ! translate global start indices to their local
  133. ! values, based on their storage order and number
  134. ! of elements in each segment
  135. do n=1, count
  136. if(n == 1) then
  137. start(n) = 1
  138. else
  139. start(n) = start(n-1) + length(n-1)
  140. endif
  141. end do
  142. end subroutine GlobalSegMapToIndices_
  143. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  144. ! Math and Computer Science Division, Argonne National Laboratory !
  145. !BOP -------------------------------------------------------------------
  146. !
  147. ! !IROUTINE: GlobalSegMapToIndex_ - Global to Local Index Translation
  148. !
  149. ! !DESCRIPTION: This {\tt INTEGER} query function takes a user-supplied
  150. ! {\tt GlobalSegMap} data type {\tt GSMap}, which desribes a decomposition
  151. ! on the input MPI communicator corresponding to the Fortran {\tt INTEGER}
  152. ! handle {\tt comm}, and the input global index value {\tt i\_g}, and
  153. ! returns a positive local index value if the datum {\tt i\_g}. If
  154. ! the datum {\tt i\_g} is not stored on the local process ID, a value
  155. ! of {\tt -1} is returned.
  156. !
  157. ! !INTERFACE:
  158. integer function GlobalSegMapToIndex_(GSMap, i_g, comm)
  159. !
  160. ! !USES:
  161. !
  162. use m_mpif90
  163. use m_die, only : MP_perr_die, die, warn
  164. use m_GlobalSegMap, only : GlobalSegMap
  165. use m_GlobalSegMap, only : GlobalSegMap_ngseg => ngseg
  166. use m_GlobalSegMap, only : GlobalSegMap_nlseg => nlseg
  167. implicit none
  168. ! !INPUT PARAMETERS:
  169. type(GlobalSegMap), intent(in) :: GSMap ! Output GlobalSegMap
  170. integer, intent(in) :: i_g ! global index
  171. integer, intent(in) :: comm ! communicator handle
  172. ! !REVISION HISTORY:
  173. ! 2Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
  174. !EOP ___________________________________________________________________
  175. character(len=*),parameter :: myname_=myname//'::GlobalSegMapToIndex_'
  176. integer :: myID
  177. integer :: count, ierr, ngseg, nlseg, n
  178. integer :: lower_bound, upper_bound
  179. integer :: local_start, local_index
  180. logical :: found
  181. ! Determine local process id myID:
  182. call MP_COMM_RANK(comm, myID, ierr)
  183. if(ierr /= 0) call MP_perr_die(myname_,'MP_COMM_RANK()',ierr)
  184. ! Extract the global number of segments in GSMap
  185. ngseg = GlobalSegMap_ngseg(GSMap)
  186. ! Extract the global number of segments in GSMap for myID
  187. nlseg = GlobalSegMap_nlseg(GSMap, myID)
  188. ! set the counter count, which records the number of times myID
  189. ! matches entries in GSMap%pe_loc(:)
  190. count = 0
  191. ! set local_start, which is the current local storage segment
  192. ! starting position
  193. local_start = 1
  194. ! set logical flag found to signify we havent found i_g:
  195. found = .false.
  196. n = 0
  197. SEARCH_LOOP: do
  198. n = n+1
  199. if (n > ngseg) EXIT
  200. if(GSMap%pe_loc(n) == myID) then
  201. ! increment / check the pe_loc match counter
  202. count = count + 1
  203. if(count > nlseg) then
  204. ierr = 2
  205. call die(myname_,'too many pe matches',ierr)
  206. endif
  207. ! is i_g in this segment?
  208. lower_bound = GSMap%start(n)
  209. upper_bound = GSMap%start(n) + GSMap%length(n) - 1
  210. if((lower_bound <= i_g) .and. (i_g <= upper_bound)) then
  211. local_index = local_start + (i_g - GSMap%start(n))
  212. found = .true.
  213. EXIT
  214. else
  215. local_start = local_start + GSMap%length(n)
  216. endif
  217. endif
  218. end do SEARCH_LOOP
  219. ! We either found the local index, or have exhausted our options.
  220. if(found) then
  221. GlobalSegMapToIndex_ = local_index
  222. else
  223. GlobalSegMapToIndex_ = -1
  224. endif
  225. end function GlobalSegMapToIndex_
  226. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  227. ! Math and Computer Science Division, Argonne National Laboratory !
  228. !BOP -------------------------------------------------------------------
  229. !
  230. ! !IROUTINE: GlobalSegMapToIndexArr_ - Global to Local Index Array Translation
  231. !
  232. ! !DESCRIPTION: Given a {\tt GlobalSegMap} data type {\tt GSMap}
  233. ! and MPI communicator corresponding to the Fortran {\tt INTEGER}
  234. ! handle {\tt comm}, convert an array of global index values
  235. ! {\tt i\_global()} to an array of local index values {\tt i\_local()}. If
  236. ! the datum {\tt i\_global(j)} is not stored on the local process ID,
  237. ! then {\tt i\_local(j)} will be set to {\tt -1}/
  238. !
  239. ! !INTERFACE:
  240. subroutine GlobalSegMapToIndexArr_(GSMap, i_global, i_local, nindex, comm)
  241. !
  242. ! !USES:
  243. !
  244. use m_stdio
  245. use m_mpif90
  246. use m_die, only : MP_perr_die, die, warn
  247. use m_GlobalSegMap, only : GlobalSegMap
  248. use m_GlobalSegMap, only : GlobalSegMap_ngseg => ngseg
  249. use m_GlobalSegMap, only : GlobalSegMap_nlseg => nlseg
  250. implicit none
  251. ! !INPUT PARAMETERS:
  252. type(GlobalSegMap), intent(in) :: GSMap ! Output GlobalSegMap
  253. integer, intent(in) :: i_global(:) ! global index
  254. integer, intent(out) :: i_local(:) ! local index
  255. integer, intent(in) :: nindex ! size of i_global()
  256. integer, intent(in) :: comm ! communicator handle
  257. ! !REVISION HISTORY:
  258. ! 12-apr-2006 R. Loy <rloy@mcs.anl.gov> - initial version
  259. !EOP ___________________________________________________________________
  260. character(len=*),parameter :: myname_=myname//'::GlobalSegMapToIndexArr_'
  261. integer :: myID
  262. integer :: count, ierr, ngseg, nlseg
  263. integer,allocatable :: mygs_lb(:),mygs_ub(:),mygs_len(:),mygs_lstart(:)
  264. integer :: i,j,n,startj
  265. ! Determine local process id myID:
  266. call MP_COMM_RANK(comm, myID, ierr)
  267. if(ierr /= 0) call MP_perr_die(myname_,'MP_COMM_RANK()',ierr)
  268. ngseg = GlobalSegMap_ngseg(GSMap)
  269. nlseg = GlobalSegMap_nlseg(GSMap, myID)
  270. if (nlseg <= 0) return;
  271. allocate( mygs_lb(nlseg), mygs_ub(nlseg), mygs_len(nlseg) )
  272. allocate( mygs_lstart(nlseg) )
  273. !!
  274. !! determine the global segments on this processor
  275. !! just once, so the info be used repeatedly below
  276. !!
  277. n = 0
  278. do i=1,ngseg
  279. if (GSMap%pe_loc(i) == myID ) then
  280. n=n+1
  281. mygs_lb(n)=GSMap%start(i)
  282. mygs_ub(n)=GSMap%start(i) + GSMap%length(i) -1
  283. mygs_len(n)=GSMap%length(i)
  284. endif
  285. enddo
  286. if (n .ne. nlseg) then
  287. write(stderr,*) myname_,"mismatch nlseg",n,nlseg
  288. call die(myname)
  289. endif
  290. mygs_lstart(1)=1
  291. do j=2,nlseg
  292. mygs_lstart(j)=mygs_lstart(j-1)+mygs_len(j-1)
  293. enddo
  294. !!
  295. !! this loop is optimized for the case that the indices in iglobal()
  296. !! are in the same order that they appear in the global segments,
  297. !! which seems usually (always?) to be the case.
  298. !!
  299. !! note that the j loop exit condition is only executed when the index
  300. !! is not found in the current segment, which saves a factor of 2
  301. !! since many consecutive indices are in the same segment.
  302. !!
  303. j=1
  304. do i=1,nindex
  305. i_local(i)= -1
  306. startj=j
  307. SEARCH_LOOP: do
  308. if ( (mygs_lb(j) <= i_global(i)) .and. &
  309. (i_global(i) <= mygs_ub(j))) then
  310. i_local(i) = mygs_lstart(j) + (i_global(i) - mygs_lb(j))
  311. EXIT SEARCH_LOOP
  312. else
  313. j=j+1
  314. if (j > nlseg) j=1 ! wrap around
  315. if (j == startj) EXIT SEARCH_LOOP
  316. endif
  317. end do SEARCH_LOOP
  318. end do
  319. !!!! this version vectorizes (outer loop)
  320. !!!! performance for in-order input is slightly slower than the above
  321. !!!! but performance on out-of-order input is probably much better
  322. !!!! at the moment we are going on the assumption that caller is
  323. !!!! likely providing in-order, so we won't use this version.
  324. !!
  325. !! do i=1,nindex
  326. !!
  327. !! i_local(i)= -1
  328. !!
  329. !! SEARCH_LOOP: do j=1,nlseg
  330. !!
  331. !! if ( (mygs_lb(j) <= i_global(i)) .and. &
  332. !! (i_global(i) <= mygs_ub(j))) then
  333. !! i_local(i) = mygs_lstart(j) + (i_global(i) - mygs_lb(j))
  334. !! endif
  335. !!
  336. !! end do SEARCH_LOOP
  337. !!
  338. !! end do
  339. deallocate( mygs_lb, mygs_ub, mygs_len, mygs_lstart )
  340. end subroutine GlobalSegMapToIndexArr_
  341. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  342. ! Math and Computer Science Division, Argonne National Laboratory !
  343. !BOP -------------------------------------------------------------------
  344. !
  345. ! !IROUTINE: GlobalMapToIndex_ - Global to Local Index Translation
  346. !
  347. ! !DESCRIPTION:
  348. ! This {\tt INTEGER} query function takes as its input a user-supplied
  349. ! {\tt GlobalMap} data type {\tt GMap}, which desribes a decomposition
  350. ! on the input MPI communicator corresponding to the Fortran {\tt INTEGER}
  351. ! handle {\tt comm}, and the input global index value {\tt i\_g}, and
  352. ! returns a positive local index value if the datum {\tt i\_g}. If
  353. ! the datum {\tt i\_g} is not stored on the local process ID, a value
  354. ! of {\tt -1} is returned.
  355. !
  356. ! !INTERFACE:
  357. integer function GlobalMapToIndex_(GMap, i_g, comm)
  358. !
  359. ! !USES:
  360. !
  361. use m_mpif90
  362. use m_die, only : MP_perr_die, die, warn
  363. use m_GlobalMap, only : GlobalMap
  364. implicit none
  365. ! !INPUT PARAMETERS:
  366. type(GlobalMap), intent(in) :: GMap ! Input GlobalMap
  367. integer, intent(in) :: i_g ! global index
  368. integer, intent(in) :: comm ! communicator handle
  369. ! !REVISION HISTORY:
  370. ! 2Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
  371. !EOP ___________________________________________________________________
  372. character(len=*),parameter :: myname_=myname//'::GlobalMapToIndex_'
  373. integer :: myID
  374. integer :: count, ierr, ngseg, nlseg, n
  375. integer :: lower_bound, upper_bound
  376. integer :: local_start, local_index
  377. logical :: found
  378. ! Determine local process id myID:
  379. call MP_COMM_RANK(comm, myID, ierr)
  380. if(ierr /= 0) call MP_perr_die(myname_,'MP_COMM_RANK()',ierr)
  381. ! Initialize logical "point located" flag found as false
  382. found = .false.
  383. lower_bound = GMap%displs(myID) + 1
  384. upper_bound = GMap%displs(myID) + GMap%counts(myID)
  385. if((lower_bound <= i_g) .and. (i_g <= upper_bound)) then
  386. found = .true.
  387. local_index = i_g - lower_bound + 1
  388. endif
  389. if(found) then
  390. GlobalMapToIndex_ = local_index
  391. else
  392. GlobalMapToIndex_ = -1
  393. endif
  394. end function GlobalMapToIndex_
  395. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  396. ! Math and Computer Science Division, Argonne National Laboratory !
  397. !BOP -------------------------------------------------------------------
  398. !
  399. ! !IROUTINE: GlobalSegMapToNavigator_ - Return Navigator to Local Segments
  400. !
  401. ! !DESCRIPTION:
  402. ! This routine takes as its input takes a user-supplied
  403. ! {\tt GlobalSegMap} data type {\tt GSMap}, which desribes a decomposition
  404. ! on the input MPI communicator corresponding to the Fortran {\tt INTEGER}
  405. ! handle {\tt comm}, and returns the local segment start index and length
  406. ! information for referencing the on-pe storage of the mapped distributed
  407. ! data. These data are returned in the form of the output {\tt Navigator}
  408. ! argument {Nav}.
  409. !
  410. ! {\bf N.B.:} This routine returns a {\tt Navigator} variable {\tt Nav},
  411. ! which must be deallocated once the user no longer needs it. Failure to
  412. ! do this will create a memory leak.
  413. !
  414. ! !INTERFACE:
  415. subroutine GlobalSegMapToNavigator_(GSMap, comm, oNav)
  416. !
  417. ! !USES:
  418. !
  419. use m_mpif90
  420. use m_die, only : MP_perr_die, die, warn
  421. use m_GlobalSegMap, only : GlobalSegMap
  422. use m_GlobalSegMap, only : GlobalSegMap_ngseg => ngseg
  423. use m_GlobalSegMap, only : GlobalSegMap_nlseg => nlseg
  424. use m_Navigator, only : Navigator
  425. use m_Navigator, only : Navigator_init => init
  426. implicit none
  427. ! !INPUT PARAMETERS:
  428. type(GlobalSegMap), intent(in) :: GSMap ! Input GlobalSegMap
  429. integer, intent(in) :: comm ! communicator handle
  430. ! !OUTPUT PARAMETERS:
  431. type(Navigator), intent(out) :: oNav ! Output Navigator
  432. ! !REVISION HISTORY:
  433. ! 2Feb01 - J.W. Larson <larson@mcs.anl.gov> - initial version
  434. !EOP ___________________________________________________________________
  435. character(len=*),parameter :: myname_=myname//'::GlobalSegMapToNavigator_'
  436. integer :: myID, ierr, ngseg, nlseg, n, count
  437. ! determine local process id myID
  438. call MP_COMM_RANK(comm, myID, ierr)
  439. if(ierr /= 0) call MP_perr_die(myname_,'MP_COMM_RANK',ierr)
  440. ! determine number of global segments ngseg:
  441. ngseg = GlobalSegMap_ngseg(GSMap)
  442. ! determine number of local segments on process myID nlseg:
  443. nlseg = GlobalSegMap_nlseg(GSMap, myID)
  444. ! Allocate space for the Navigator oNav:
  445. call Navigator_init(oNav, nlseg, ierr)
  446. if(ierr /= 0) call die(myname_,'Navigator_init',ierr)
  447. call GlobalSegMapToIndices_(GSMap, comm, oNav%displs, oNav%counts)
  448. end subroutine GlobalSegMapToNavigator_
  449. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  450. ! Math and Computer Science Division, Argonne National Laboratory !
  451. !BOP -------------------------------------------------------------------
  452. !
  453. ! !IROUTINE: GlobalSegMapToLocalMatrix_ - Set Local SparseMatrix Indices
  454. !
  455. ! !DESCRIPTION:
  456. ! This routine takes as its input a user-supplied {\tt GlobalSegMap}
  457. ! domain decomposition {\tt GSMap}, which describes the decomposition of
  458. ! either the rows or columns of the input/output {\tt SparseMatrix}
  459. ! argument {\tt sMat} on the communicator associated with the {\tt INTEGER}
  460. ! handle {\tt comm}, and to translate the global row or column indices
  461. ! of {\tt sMat} into their local counterparts. The choice of either row
  462. ! or column is governed by the value of the input {\tt CHARACTER}
  463. ! argument {\tt RCFlag}. One sets this variable to either {\tt 'ROW'} or
  464. ! {\tt 'row'} to specify row re-indexing (which are stored in
  465. ! {\tt sMat} and retrieved by indexing the attribute {\tt lrow}), and
  466. ! {\tt 'COLUMN'} or {\tt 'column'} to specify column re-indexing (which
  467. ! are stored in {\tt sMat} and retrieved by indexing the {\tt SparseMatrix}
  468. ! attribute {\tt lcol}).
  469. !
  470. ! !INTERFACE:
  471. subroutine GlobalSegMapToLocalMatrix_(sMat, GSMap, RCFlag, comm)
  472. !
  473. ! !USES:
  474. !
  475. use m_stdio
  476. use m_die, only : die
  477. use m_SparseMatrix, only : SparseMatrix
  478. use m_SparseMatrix, only : SparseMatrix_indexIA => indexIA
  479. use m_SparseMatrix, only : SparseMatrix_lsize => lsize
  480. use m_GlobalSegMap, only : GlobalSegMap
  481. implicit none
  482. ! !INPUT PARAMETERS:
  483. type(GlobalSegMap), intent(in) :: GSMap ! Input GlobalSegMap
  484. character(len=*), intent(in) :: RCFlag ! 'row' or 'column'
  485. integer, intent(in) :: comm ! communicator handle
  486. ! !INPUT/OUTPUT PARAMETERS:
  487. type(SparseMatrix), intent(inout) :: sMat
  488. ! !SEE ALSO:
  489. ! The MCT module m_SparseMatrix for more information about the
  490. ! SparseMatrix type and its storage of global and local row-and
  491. ! column indices.
  492. !
  493. ! !REVISION HISTORY:
  494. ! 3May01 - J.W. Larson <larson@mcs.anl.gov> - initial version, which
  495. ! is _extremely_ slow, but safe. This must be re-examined
  496. ! later.
  497. !EOP ___________________________________________________________________
  498. character(len=*),parameter :: myname_=myname//'::GlobalSegMapToLocalMatrix_'
  499. integer :: i, GlobalIndex, gindex, lindex, lsize
  500. integer, allocatable :: temp_gindex(:) !! rml
  501. integer, allocatable :: temp_lindex(:) !! rml
  502. ! What are we re-indexing, rows or columns?
  503. select case(RCFlag)
  504. case('ROW','row')
  505. gindex = SparseMatrix_indexIA(sMat, 'grow', dieWith=myname_)
  506. lindex = SparseMatrix_indexIA(sMat,'lrow', dieWith=myname_)
  507. case('COLUMN','column')
  508. gindex = SparseMatrix_indexIA(sMat,'gcol', dieWith=myname_)
  509. lindex = SparseMatrix_indexIA(sMat,'lcol', dieWith=myname_)
  510. case default
  511. write(stderr,'(3a)') myname_,":: unrecognized value of RCFLag ",RCFlag
  512. call die(myname)
  513. end select
  514. ! How many matrix elements are there?
  515. lsize = SparseMatrix_lsize(sMat)
  516. !! rml new code from here down - do the mapping all in one
  517. !! function call which has been tuned for speed
  518. allocate( temp_gindex(lsize) )
  519. allocate( temp_lindex(lsize) )
  520. do i=1,lsize
  521. temp_gindex(i) = sMat%data%iAttr(gindex,i)
  522. end do
  523. call GlobalSegMapToIndexArr_(GSMap, temp_gindex, temp_lindex, lsize, comm)
  524. do i=1,lsize
  525. sMat%data%iAttr(lindex,i) = temp_lindex(i)
  526. end do
  527. deallocate(temp_gindex) ! rml
  528. deallocate(temp_lindex) ! rml
  529. end subroutine GlobalSegMapToLocalMatrix_
  530. end module m_GlobalToLocal