num_matrix.F90 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. !
  2. ! NAME
  3. ! num_matrix - matrix tools
  4. !
  5. ! USAGE
  6. !
  7. ! use num_matrix
  8. !
  9. ! type(TFullMatrix) :: A, U, Vt
  10. ! type(TDiagMatrix) :: S
  11. ! type(TBlockMatrix) :: B, C
  12. !
  13. !
  14. ! ! matrix-matrix multiplications:
  15. ! !
  16. ! ! A * B =: C
  17. ! !
  18. ! call Multiply( A, B, C )
  19. !
  20. ! ! singular value decomposition:
  21. ! !
  22. ! ! A = U S V'
  23. ! !
  24. ! call SVD( A, U, S, Vt )
  25. !
  26. ! ! eigen value decomposition:
  27. ! !
  28. ! ! A = Q D Q'
  29. ! !
  30. ! call EVD( A, D, Q [,vrange=] [,irange=] )
  31. !
  32. ! ***********
  33. !
  34. ! matrix clasifications:
  35. ! rectangular | square
  36. ! symmetric | asymmetric
  37. ! band
  38. ! diagonal
  39. ! identity
  40. ! upper triangular | lower triangular
  41. !
  42. module num_matrix
  43. use num_matrix_full
  44. use num_matrix_block
  45. use num_matrix_diag
  46. implicit none
  47. ! --- in/out ------------------------------------
  48. private
  49. public :: Init, Done
  50. public :: SetStorage, ClearStorage
  51. public :: IsZero
  52. public :: TFullMatrix
  53. public :: SetFull
  54. public :: TBlockMatrix
  55. public :: SetBlock
  56. public :: TDiagMatrix
  57. public :: SetDiag
  58. public :: Multiply
  59. ! public :: MultiplyX
  60. public :: SVD
  61. public :: EVD
  62. ! --- const ----------------------------------
  63. character(len=*), parameter :: mname = 'module num_matrix'
  64. ! --- interfaces ------------------------------
  65. interface SVD
  66. module procedure mat_SVD
  67. end interface
  68. interface EVD
  69. module procedure mat_EVD
  70. end interface
  71. interface Multiply
  72. module procedure mat_Multiply_full_block
  73. end interface
  74. ! interface MultiplyX
  75. ! module procedure mat_MultiplyX_full_block
  76. ! end interface
  77. contains
  78. ! ==============================================================
  79. !
  80. ! A * B + 0.0 * C =: C
  81. !
  82. ! B j1 j2
  83. ! [ ]
  84. ! i1 [ xxxxx ]
  85. ! i2 [ xxxxx ]
  86. ! [ ]
  87. ! A C
  88. ! [xxxxxxxx] [ xxxxx ]
  89. ! [xxxxxxxx] [ xxxxx ]
  90. !
  91. ! A(:,i1:i2) B(i1:i2,j1:j2) = C(:,j1:j2)
  92. subroutine mat_Multiply_full_block( A, B, C )
  93. ! --- in/out -------------------------------
  94. type(TFullMatrix), intent(in) :: A
  95. type(TBlockMatrix), intent(in) :: B
  96. type(TBlockMatrix), intent(inout) :: C
  97. ! --- const ----------------------------------
  98. character(len=*), parameter :: name = mname//', mat_Multiply_full_block'
  99. ! --- begin --------------------------------
  100. ! set shape of output matrix and ranges of non-zero block:
  101. call SetBlock( C, A%m, B%n, 1, A%m, B%j1, B%j2 )
  102. #ifdef with_lapack
  103. ! call BLAS level 3 routine:
  104. !
  105. ! 1.0 * A * B + 0.0 * C =: C
  106. !
  107. select case ( A%knd )
  108. case ( 4 )
  109. call sGeMM( 'N', 'N', A%m, B%bn, B%bm, &
  110. 1.0, A%a(1,B%i1), size(A%a,1), B%a, size(B%a,1), &
  111. 0.0, C%a, size(C%a,1) )
  112. case ( 8 )
  113. call dGeMM( 'N', 'N', A%m, B%bn, B%bm, &
  114. 1.0, A%a(1,B%i1), size(A%a,1), B%a, size(B%a,1), &
  115. 0.0, C%a, size(C%a,1) )
  116. case default
  117. write (*,'("ERROR - blas routine ?GeMM not implemented for kind ",i2)') A%knd
  118. write (*,'("ERROR in ",a)') name; stop
  119. end select
  120. #else
  121. write (*,'("ERROR - program should be compiled with lapack")')
  122. write (*,'("ERROR in ",a)') name; stop
  123. #endif
  124. end subroutine mat_Multiply_full_block
  125. !
  126. ! subroutine mat_MultiplyX_full_block( A, B, C )
  127. !
  128. ! ! --- in/out -------------------------------
  129. !
  130. ! type(TFullMatrix), intent(in) :: A
  131. ! type(TBlockMatrix), intent(in) :: B
  132. ! type(TBlockMatrix), intent(inout) :: C
  133. !
  134. ! ! --- const ----------------------------------
  135. !
  136. ! character(len=*), parameter :: name = mname//', mat_Multiply_full_block'
  137. !
  138. ! ! --- begin --------------------------------
  139. !
  140. ! write (1357,*) ' Multiply:'
  141. ! write (1357,*) ' A : ',A%m, A%n
  142. ! write (1357,*) ' ',shape(A%a)
  143. ! write (1357,*) ' B : ',B%m, B%n
  144. ! write (1357,*) ' ',B%i1, B%i2
  145. ! write (1357,*) ' ',B%j1, B%j2
  146. ! write (1357,*) ' ',shape(B%a)
  147. !
  148. ! write (1357,*) ' set C ...'
  149. ! ! set shape of output matrix and ranges of non-zero block:
  150. ! call SetBlock( C, A%m, B%n, 1, A%m, B%j1, B%j2 )
  151. !
  152. ! ! call BLAS level 3 routine:
  153. ! !
  154. ! ! 1.0 * A * B + 0.0 * C =: C
  155. ! !
  156. ! select case ( A%knd )
  157. ! case ( 4 )
  158. ! write (1357,*) ' sGeMM ...'
  159. ! call sGeMM( 'N', 'N', A%m, B%bn, B%bm, &
  160. ! 1.0, A%a(1,B%i1), size(A%a,1), B%a, size(B%a,1), &
  161. ! 0.0, C%a, size(C%a,1) )
  162. ! write (1357,*) ' ok'
  163. ! case ( 8 )
  164. ! write (1357,*) ' dGeMM ...'
  165. ! call dGeMM( 'N', 'N', A%m, B%bn, B%bm, &
  166. ! 1.0, A%a(1,B%i1), size(A%a,1), B%a, size(B%a,1), &
  167. ! 0.0, C%a, size(C%a,1) )
  168. ! write (1357,*) ' ok'
  169. ! case default
  170. ! write (*,'("ERROR - blas routine ?GeMM not implemented for kind ",i)') A%knd
  171. ! write (*,'("ERROR in ",a)') name; stop
  172. ! end select
  173. ! write (1357,*) ' done'
  174. !
  175. ! end subroutine mat_MultiplyX_full_block
  176. ! ================================================================
  177. !
  178. ! Singular value decomposition:
  179. !
  180. ! A = U S V'
  181. !
  182. ! m x n m x s s x s s x n
  183. !
  184. subroutine mat_SVD( AA, U, S, Vt )
  185. ! --- in/out ---------------------------------
  186. type(TFullMatrix), intent(in) :: AA
  187. type(TFullMatrix), intent(out) :: U
  188. type(TDiagMatrix), intent(out) :: S
  189. type(TFullMatrix), intent(out) :: Vt
  190. ! --- const ----------------------------------
  191. character(len=*), parameter :: name = mname//', mat_SVD'
  192. ! --- local ----------------------------------
  193. integer :: m, n, ns
  194. type(TFullMatrix) :: A
  195. real, allocatable :: work(:)
  196. integer, allocatable :: iwork(:)
  197. integer :: info
  198. ! --- begin ----------------------------------
  199. ! copy of input matrix:
  200. call Init( A, '(mat_SVD) A' )
  201. call SetStorage( A, AA%m, AA%n )
  202. call SetFull( A, AA%a, 'N' )
  203. ! input size:
  204. m = A%m
  205. n = A%n
  206. ! number of singular values:
  207. ns = max(1,min(m,n))
  208. ! setup output:
  209. call SetStorage( U , m , ns )
  210. call SetStorage( S , ns )
  211. call SetStorage( Vt, ns, n )
  212. ! work space
  213. allocate( work(4*(ns)**2+max(m,n)+9*ns) )
  214. allocate( iwork(8*ns) )
  215. !
  216. ! decompose
  217. !
  218. #ifdef with_lapack
  219. select case ( A%knd )
  220. case ( 4 )
  221. call sGeSdD( 'S', m, n, A%a, size(A%a,1), &
  222. S%a, U%a, size(U%a,1), Vt%a, size(Vt%a,1), &
  223. work, size(work), iwork, info )
  224. case ( 8 )
  225. call dGeSdD( 'S', m, n, A%a, size(A%a,1), &
  226. S%a, U%a, size(U%a,1), Vt%a, size(Vt%a,1), &
  227. work, size(work), iwork, info )
  228. case default
  229. write (*,'("ERROR - lapack routine ?GeSvdD not implemented for kind ",i2)') A%knd
  230. write (*,'("ERROR in ",a)') name; stop
  231. end select
  232. if ( info /= 0 ) then
  233. write (*,'("ERROR - from ?GeSvdD; info=",i6)') info
  234. write (*,'("ERROR in ",a)') name; stop
  235. end if
  236. #else
  237. write (*,'("ERROR - program should be compiled with lapack")')
  238. write (*,'("ERROR in ",a)') name; stop
  239. #endif
  240. ! output filled now ...
  241. S%zero = .false.
  242. U%zero = .false.
  243. Vt%zero = .false.
  244. ! done
  245. call Done( A )
  246. deallocate( work )
  247. deallocate( iwork )
  248. end subroutine mat_SVD
  249. ! ====================================================
  250. subroutine mat_EVD( AA, DD, QQ, vrange, irange )
  251. ! --- in/out ---------------------------------
  252. type(TFullMatrix), intent(in) :: AA
  253. type(TDiagMatrix), intent(out) :: DD
  254. type(TFullMatrix), intent(out) :: QQ
  255. real, intent(in), optional :: vrange(2)
  256. integer, intent(in), optional :: irange(2)
  257. ! --- const ----------------------------------
  258. character(len=*), parameter :: name = mname//', mat_EVD'
  259. ! --- local ----------------------------------
  260. real, allocatable :: A(:,:)
  261. integer :: n
  262. character(len=1) :: range
  263. real :: vl, vu
  264. integer :: il, iu
  265. real :: abstol
  266. integer :: neigval
  267. real, allocatable :: work(:)
  268. integer, allocatable :: iwork(:)
  269. integer, allocatable :: ifail(:)
  270. integer :: info
  271. ! --- begin ----------------------------------
  272. ! check ...
  273. if ( (AA%m < 1) .or. (AA%n < 1) .or. (AA%m /= AA%n) ) then
  274. write (*,'("ERROR - matrix strange or not square:")')
  275. write (*,'("ERROR - m,n : ",2i6)') AA%m, AA%n
  276. write (*,'("ERROR in ",a)') name; stop
  277. end if
  278. ! input size:
  279. n = AA%n
  280. ! copy input
  281. allocate( A(n,n) )
  282. A = AA%a
  283. ! eigenvalues and vectors:
  284. call SetStorage( DD, n )
  285. call SetStorage( QQ, n, n )
  286. ! work space
  287. allocate( work(8*n) ) ; work = 0.0
  288. allocate( iwork(5*n) ) ; iwork = 0
  289. allocate( ifail( n) ) ; ifail = 0
  290. if ( present(vrange) ) then
  291. range = 'V'
  292. vl = vrange(1)
  293. vu = vrange(2)
  294. il = 1
  295. iu = n
  296. else if ( present(irange) ) then
  297. range = 'I'
  298. vl = -huge(1.0)
  299. vu = huge(1.0)
  300. il = irange(1)
  301. iu = irange(2)
  302. else
  303. range = 'A'
  304. vl = -huge(1.0)
  305. vu = huge(1.0)
  306. il = 1
  307. iu = n
  308. end if
  309. ! default tolerance
  310. abstol = -1.0
  311. ! decompose:
  312. #ifdef with_lapack
  313. select case ( kind(A) )
  314. case ( 4 )
  315. call sSyEvX ( 'V', range, 'U', n, A, size(A,1), vl, vu, il, iu, abstol, &
  316. neigval, DD%a, QQ%a, size(QQ%a,1), &
  317. work, size(work), iwork, ifail, info)
  318. case ( 8 )
  319. call dSyEvX ( 'V', range, 'U', n, A, size(A,1), vl, vu, il, iu, abstol, &
  320. neigval, DD%a, QQ%a, size(QQ%a,1), &
  321. work, size(work), iwork, ifail, info)
  322. case default
  323. write (*,'("ERROR - lapack routine ?SyEvX not implemented for kind ",i6)') kind(A)
  324. write (*,'("ERROR in ",a)') name; stop
  325. end select
  326. if ( info /= 0 ) then
  327. write (*,'("ERROR - from ?SyEvX; info=",i6)') info
  328. write (*,'("ERROR - ifail=",i6)') ifail(1:neigval)
  329. write (*,'("ERROR in ",a)') name; stop
  330. end if
  331. #else
  332. write (*,'("ERROR - program should be compiled with lapack")')
  333. write (*,'("ERROR in ",a)') name; stop
  334. #endif
  335. ! 'truncate' diagonal matrix (acutal storage is unchanged):
  336. DD%m = neigval
  337. DD%n = neigval
  338. ! 'truncate' eigenvector matrix (acutal storage is unchanged):
  339. QQ%m = n
  340. QQ%n = neigval
  341. ! ok
  342. deallocate( A )
  343. deallocate( work )
  344. deallocate( iwork )
  345. deallocate( ifail )
  346. end subroutine mat_EVD
  347. end module num_matrix