m_SparseMatrixToMaps.F90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. ! Math and Computer Science Division, Argonne National Laboratory !
  3. !-----------------------------------------------------------------------
  4. ! CVS m_SparseMatrixToMaps.F90,v 1.13 2007-05-11 02:09:48 rloy Exp
  5. ! CVS MCT_2_8_0
  6. !BOP -------------------------------------------------------------------
  7. !
  8. ! !MODULE: m_SparseMatrixToMaps -- Maps from the Sparse Matrix
  9. !
  10. ! !DESCRIPTION:
  11. ! The {\tt SparseMatrix} provides consolidated (on one process) or
  12. ! distributed sparse matrix storage for the operation
  13. ! ${\bf y} = {\bf M} {\bf x}$, where {\bf x} and {\bf y} are vectors,
  14. ! and {\bf M} is a matrix. In performing parallel matrix-vector
  15. ! multiplication, one has numerous options regarding the decomposition
  16. ! of the matrix {\bf M}, and the vectors {\bf y} and {\bf x}.
  17. ! This module provides services to generate mct mapping components---the
  18. ! {\tt GlobalMap} and {\tt GlobalSegMap} for the vectors {\bf y} and/or
  19. ! {\bf x} based on the decomposition of the sparse matrix {\bf M}.
  20. !
  21. ! !INTERFACE:
  22. module m_SparseMatrixToMaps
  23. !
  24. ! !USES:
  25. !
  26. use m_SparseMatrix, only : SparseMatrix
  27. implicit none
  28. private ! except
  29. public :: SparseMatrixToXGlobalSegMap
  30. public :: SparseMatrixToYGlobalSegMap
  31. interface SparseMatrixToXGlobalSegMap ; module procedure &
  32. SparseMatrixToXGlobalSegMap_
  33. end interface
  34. interface SparseMatrixToYGlobalSegMap ; module procedure &
  35. SparseMatrixToYGlobalSegMap_
  36. end interface
  37. ! !REVISION HISTORY:
  38. ! 13Apr01 - J.W. Larson <larson@mcs.anl.gov> - initial prototype
  39. ! and API specifications.
  40. !EOP ___________________________________________________________________
  41. character(len=*),parameter :: myname='MCT::m_SparseMatrixToMaps'
  42. contains
  43. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  44. ! Math and Computer Science Division, Argonne National Laboratory !
  45. !BOP -------------------------------------------------------------------
  46. !
  47. ! !IROUTINE: SparseMatrixToXGlobalSegMap_ - Generate X GlobalSegmap.
  48. !
  49. ! !DESCRIPTION: Given an input {\tt SparseMatrix} argument {\tt sMat},
  50. ! this routine generates an output {\tt GlobalSegMap} variable
  51. ! {\tt xGSMap}, which describes the domain decomposition of the vector
  52. ! {\bf x} in the distributed matrix-vector multiplication
  53. ! $${\bf y} = {\bf M} {\bf x}.$$
  54. !
  55. ! !INTERFACE:
  56. subroutine SparseMatrixToXGlobalSegMap_(sMat, xGSMap, root, comm, comp_id)
  57. !
  58. ! !USES:
  59. !
  60. use m_stdio, only : stderr
  61. use m_die, only : die
  62. use m_mpif90
  63. use m_List, only : List
  64. use m_List, only : List_init => init
  65. use m_List, only : List_clean => clean
  66. use m_SparseMatrix, only : SparseMatrix
  67. use m_SparseMatrix, only : SparseMatrix_nCols => nCols
  68. use m_SparseMatrix, only : SparseMatrix_lsize => lsize
  69. use m_SparseMatrix, only : SparseMatrix_indexIA => indexIA
  70. use m_SparseMatrix, only : SparseMatrix_SortPermute => SortPermute
  71. use m_GlobalSegMap, only : GlobalSegMap
  72. use m_GlobalSegMap, only : GlobalSegMap_init => init
  73. implicit none
  74. ! !INPUT PARAMETERS:
  75. !
  76. integer, intent(in) :: root ! communicator root
  77. integer, intent(in) :: comm ! communicator handle
  78. integer, intent(in) :: comp_id ! component id
  79. ! !INPUT/OUTPUT PARAMETERS:
  80. !
  81. type(SparseMatrix), intent(inout) :: sMat ! input SparseMatrix
  82. ! !OUTPUT PARAMETERS:
  83. !
  84. type(GlobalSegMap), intent(out) :: xGSMap ! segmented decomposition
  85. ! for x
  86. ! !REVISION HISTORY:
  87. ! 13Apr01 - J.W. Larson <larson@mcs.anl.gov> - API specification.
  88. ! 25Apr01 - J.W. Larson <larson@mcs.anl.gov> - First version.
  89. ! 27Apr01 - J.W. Larson <larson@mcs.anl.gov> - Bug fix--intent of
  90. ! argument sMat changed from (IN) to (INOUT)
  91. ! 27Apr01 - R.L. Jacob <jacob@mcs.anl.gov> - bug fix-- add use
  92. ! statement for SortPermute
  93. ! 01May01 - R.L. Jacob <jacob@mcs.anl.gov> - make comp_id an
  94. ! input argument
  95. !EOP ___________________________________________________________________
  96. character(len=*),parameter :: myname_=myname//'::SparseMatrixToXGlobalSegMap_'
  97. ! SparseMatrix attributes:
  98. integer :: lsize
  99. ! GlobalSegMap input attributes:
  100. integer :: gsize, ngseg
  101. integer, dimension(:), pointer :: starts, lengths
  102. ! Temporary array for identifying each matrix element column and
  103. ! process ID destination
  104. integer, dimension(:), allocatable :: gCol, element_pe_locs
  105. ! Index to identify the gcol attribute in sMat:
  106. integer :: igCol
  107. ! Matrix element sorting keys list:
  108. type(List) :: sort_keys
  109. ! Loop index and error flag:
  110. integer :: i, ierr
  111. ! Determine he local number of matrix elements lsize
  112. lsize = SparseMatrix_lsize(sMat)
  113. ! The value of gsize is taken from the number of columns in sMat:
  114. gsize = SparseMatrix_nCols(sMat)
  115. ! Sort SparseMatrix entries by global column index gcol, then
  116. ! global row index.
  117. ! Create Sort keys list
  118. call List_init(sort_keys,'gcol:grow')
  119. ! Sort and permute the entries of sMat into lexicographic order
  120. ! by global column, then global row.
  121. call SparseMatrix_SortPermute(sMat, sort_keys)
  122. ! Clean up sort keys list
  123. call List_clean(sort_keys)
  124. ! Allocate storage space for matrix element column indices and
  125. ! process ID destinations
  126. allocate(gCol(lsize), stat=ierr)
  127. if(ierr /= 0) then
  128. call die(myname_,'allocate(gCol...',ierr)
  129. endif
  130. ! Extract global column information and place in array gCol
  131. igCol = SparseMatrix_indexIA(sMat, 'gcol', dieWith=myname_)
  132. do i=1, lsize
  133. gCol(i) = sMat%data%iAttr(igCol,i)
  134. end do
  135. ! Scan sorted entries of gCol to count segments (ngseg), and
  136. ! their starting indices and lengths (returned in the arrays
  137. ! starts(:) and lengths(:), respectively)
  138. call ComputeSegments_(gCol, lsize, ngseg, starts, lengths)
  139. ! Now we have sufficient data to call the GlobalSegMap
  140. ! initialization using distributed data:
  141. call GlobalSegMap_init(xGSMap, starts, lengths, root, comm, &
  142. comp_id, gsize=gsize)
  143. ! clean up temporary arrays gCol(:), starts(:) and lengths(:),
  144. ! (the latter two were allocated in the call to the routine
  145. ! ComputeSegments_())
  146. deallocate(gCol, starts, lengths, stat=ierr)
  147. if(ierr /= 0) then
  148. call die(myname_,'deallocate(gCol...',ierr)
  149. endif
  150. end subroutine SparseMatrixToXGlobalSegMap_
  151. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  152. ! Math and Computer Science Division, Argonne National Laboratory !
  153. !BOP -------------------------------------------------------------------
  154. !
  155. ! !IROUTINE: SparseMatrixToYGlobalSegMap_ - Generate Y GlobalSegmap.
  156. !
  157. ! !DESCRIPTION: Given an input {\tt SparseMatrix} argument {\tt sMat},
  158. ! this routine generates an output {\tt GlobalSegMap} variable
  159. ! {\tt yGSMap}, which describes the domain decomposition of the vector
  160. ! {\bf y} in the distributed matrix-vector multiplication
  161. ! ${\bf y} = {\bf M} {\bf x}$.
  162. !
  163. ! !INTERFACE:
  164. subroutine SparseMatrixToYGlobalSegMap_(sMat, yGSMap, root, comm, comp_id)
  165. !
  166. ! !USES:
  167. !
  168. use m_stdio, only : stderr
  169. use m_die, only : die
  170. use m_List, only : List
  171. use m_List, only : List_init => init
  172. use m_List, only : List_clean => clean
  173. use m_SparseMatrix, only : SparseMatrix
  174. use m_SparseMatrix, only : SparseMatrix_nRows => nRows
  175. use m_SparseMatrix, only : SparseMatrix_lsize => lsize
  176. use m_SparseMatrix, only : SparseMatrix_indexIA => indexIA
  177. use m_SparseMatrix, only : SparseMatrix_SortPermute => SortPermute
  178. use m_GlobalSegMap, only : GlobalSegMap
  179. use m_GlobalSegMap, only : GlobalSegMap_init => init
  180. implicit none
  181. ! !INPUT PARAMETERS:
  182. !
  183. integer, intent(in) :: root ! communicator root
  184. integer, intent(in) :: comm ! communicator handle
  185. integer, intent(in) :: comp_id ! component id
  186. ! !INPUT/OUTPUT PARAMETERS:
  187. !
  188. type(SparseMatrix), intent(inout) :: sMat ! input SparseMatrix
  189. ! !OUTPUT PARAMETERS:
  190. !
  191. type(GlobalSegMap), intent(out) :: yGSMap ! segmented decomposition
  192. ! for y
  193. ! !REVISION HISTORY:
  194. ! 13Apr01 - J.W. Larson <larson@mcs.anl.gov> - API specification.
  195. ! 25Apr01 - J.W. Larson <larson@mcs.anl.gov> - initial code.
  196. ! 27Apr01 - J.W. Larson <larson@mcs.anl.gov> - Bug fix--intent of
  197. ! argument sMat changed from (IN) to (INOUT)
  198. ! 27Apr01 - R.L. Jacob <jacob@mcs.anl.gov> - bug fix-- add use
  199. ! statement for SortPermute
  200. ! 01May01 - R.L. Jacob <jacob@mcs.anl.gov> - make comp_id an
  201. ! input argument
  202. ! 07May02 - J.W. Larson <larson@mcs.anl.gov> - Changed interface to
  203. ! make it consistent with SparseMatrixToXGlobalSegMap_().
  204. !EOP ___________________________________________________________________
  205. character(len=*),parameter :: myname_=myname//'::SparseMatrixToYGlobalSegMap_'
  206. ! SparseMatrix attributes:
  207. integer :: lsize
  208. ! GlobalSegMap input attributes:
  209. integer :: gsize, ngseg
  210. integer, dimension(:), pointer :: starts, lengths
  211. ! Temporary array for identifying each matrix element column and
  212. ! process ID destination
  213. integer, dimension(:), allocatable :: gRow, element_pe_locs
  214. ! Index to identify the gRow attribute in sMat:
  215. integer :: igRow
  216. ! Matrix element sorting keys list:
  217. type(List) :: sort_keys
  218. ! Loop index and error flag:
  219. integer :: i, ierr
  220. ! Determine he local number of matrix elements lsize
  221. lsize = SparseMatrix_lsize(sMat)
  222. ! The value of gsize is taken from the number of columns in sMat:
  223. gsize = SparseMatrix_nRows(sMat)
  224. ! Sort SparseMatrix entries by global column index grow, then
  225. ! global row index.
  226. ! Create Sort keys list
  227. call List_init(sort_keys,'grow:gcol')
  228. ! Sort and permute the entries of sMat into lexicographic order
  229. ! by global column, then global row.
  230. call SparseMatrix_SortPermute(sMat, sort_keys)
  231. ! Clean up sort keys list
  232. call List_clean(sort_keys)
  233. ! Allocate storage space for matrix element column indices and
  234. ! process ID destinations
  235. allocate(gRow(lsize), stat=ierr)
  236. if(ierr /= 0) then
  237. call die(myname_,'allocate(gRow...',ierr)
  238. endif
  239. ! Extract global column information and place in array gRow
  240. igRow = SparseMatrix_indexIA(sMat,'grow', dieWith=myname_)
  241. do i=1, lsize
  242. gRow(i) = sMat%data%iAttr(igRow,i)
  243. end do
  244. ! Scan sorted entries of gRow to count segments (ngseg), and
  245. ! their starting indices and lengths (returned in the arrays
  246. ! starts(:) and lengths(:), respectively)
  247. call ComputeSegments_(gRow, lsize, ngseg, starts, lengths)
  248. ! Now we have sufficient data to call the GlobalSegMap
  249. ! initialization using distributed data:
  250. call GlobalSegMap_init(yGSMap, starts, lengths, root, comm, &
  251. comp_id, gsize=gsize)
  252. ! clean up temporary arrays gRow(:), starts(:) and lengths(:),
  253. ! (the latter two were allocated in the call to the routine
  254. ! ComputeSegments_())
  255. deallocate(gRow, starts, lengths, stat=ierr)
  256. if(ierr /= 0) then
  257. call die(myname_,'deallocate(gRow...',ierr)
  258. endif
  259. end subroutine SparseMatrixToYGlobalSegMap_
  260. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  261. ! Math and Computer Science Division, Argonne National Laboratory !
  262. !BOP -------------------------------------------------------------------
  263. !
  264. ! !IROUTINE: CreateSegments_ - Generate segment information.
  265. !
  266. ! !DESCRIPTION: This routine examines an input {\tt INTEGER} list of
  267. ! numbers {\tt indices} (of length {\tt num\_indices}), determines the
  268. ! number of segments of consecutive numbers (or runs) {\tt nsegs}. The
  269. ! starting indices for each run, and their lengths are returned in the
  270. ! {\tt INTEGER} arrays {\tt starts(:)} and {\tt lengths(:)}, respectively.
  271. !
  272. ! !INTERFACE:
  273. subroutine ComputeSegments_(indices, num_indices, nsegs, starts, lengths)
  274. !
  275. ! !USES:
  276. !
  277. use m_stdio, only : stderr
  278. use m_die, only : die
  279. implicit none
  280. !
  281. ! !INPUT PARAMETERS:
  282. !
  283. integer, dimension(:), intent(in) :: indices
  284. integer, intent(in) :: num_indices
  285. !
  286. ! !OUTPUT PARAMETERS:
  287. !
  288. integer, intent(out) :: nsegs
  289. integer, dimension(:), pointer :: starts
  290. integer, dimension(:), pointer :: lengths
  291. ! !REVISION HISTORY:
  292. ! 19Apr01 - J.W. Larson <larson@mcs.anl.gov> - API specification.
  293. ! 25Apr01 - J.W. Larson <larson@mcs.anl.gov> - Initial code.
  294. ! 27Apr01 - J.W. Larson <larson@mcs.anl.gov> - Bug fix--error in
  295. ! computation of segment starts/lengths.
  296. ! 27Nov01 - E.T. Ong <eong@mcs.anl.gov> - Bug fix--initialize
  297. ! nsegs=0 in case num_indices=0.
  298. !EOP ___________________________________________________________________
  299. character(len=*),parameter :: myname_=myname//'::ComputeSegments_'
  300. integer :: i, ierr
  301. ! First pass: count the segments
  302. nsegs = 0
  303. do i=1,num_indices
  304. if(i == 1) then ! bootstrap segment counting process
  305. nsegs = 1
  306. else
  307. if(indices(i) > indices(i-1) + 1) then ! new segment
  308. nsegs = nsegs + 1
  309. endif
  310. endif ! if(i==1)
  311. end do ! do i=1, num_indices
  312. ! Allocate storage space for starts(:) and lengths(:)
  313. allocate(starts(nsegs), lengths(nsegs), stat=ierr)
  314. if(ierr /= 0) then
  315. call die(myname_,'allocate(starts...',ierr)
  316. endif
  317. ! Second pass: compute segment start/length info
  318. do i=1,num_indices
  319. select case(i)
  320. case(1) ! bootstrap segment counting process
  321. nsegs = 1
  322. starts(nsegs) = indices(i)
  323. ! rml patch
  324. lengths(nsegs) = 1
  325. case default
  326. if(i == num_indices) then ! last point
  327. if(indices(i) > indices(i-1) + 1) then ! new segment with 1 pt.
  328. ! first, close the books on the penultimate segment:
  329. lengths(nsegs) = indices(i-1) - starts(nsegs) + 1
  330. nsegs = nsegs + 1
  331. starts(nsegs) = indices(i)
  332. lengths(nsegs) = 1 ! (just one point)
  333. else
  334. lengths(nsegs) = indices(i) - starts(nsegs) + 1
  335. endif
  336. else
  337. if(indices(i) > indices(i-1) + 1) then ! new segment
  338. lengths(nsegs) = indices(i-1) - starts(nsegs) + 1
  339. nsegs = nsegs + 1
  340. starts(nsegs) = indices(i)
  341. endif
  342. endif
  343. end select ! select case(i)
  344. end do ! do i=1, num_indices
  345. end subroutine ComputeSegments_
  346. end module m_SparseMatrixToMaps