num_matrix_block.F90 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. !
  2. ! NAME
  3. ! num_matrix_block - defines block matrix
  4. !
  5. ! USAGE
  6. !
  7. ! use num_matrix_block
  8. !
  9. ! type(TBlockMatrix) :: A
  10. !
  11. ! ! initialize matrix:
  12. ! ! o no memory allocated
  13. ! ! o zero flag
  14. ! call Init( A )
  15. !
  16. ! ! (re)allocate memory to store contents:
  17. ! call SetStorage( A, am, an )
  18. ! call ClearStorage( A )
  19. !
  20. ! ! zero flag ?
  21. ! if ( IsZero(A) ) ...
  22. !
  23. ! ! define block:
  24. ! call SetBlock( A, m, n, i1,i2, j1,j2 )
  25. ! call SetBlock( A, m, n, i1, j1, arr(:,:) )
  26. !
  27. ! ! done
  28. ! call Done( A )
  29. !
  30. module num_matrix_block
  31. implicit none
  32. ! --- in/out ------------------------------------
  33. private
  34. public :: TBlockMatrix
  35. public :: Init, Done
  36. public :: SetStorage, ClearStorage
  37. public :: IsZero
  38. public :: SetBlock
  39. ! --- const ----------------------------------
  40. character(len=*), parameter :: mname = 'module num_matrix_block'
  41. ! --- types ------------------------------------
  42. type TBlockMatrix
  43. ! key name for error mesages
  44. character(len=20) :: key
  45. ! logical matrix dimension:
  46. integer :: m, n
  47. ! contents flags
  48. logical :: zero
  49. ! physical storage:
  50. real, pointer :: a(:,:)
  51. integer :: am, an
  52. integer :: knd
  53. !
  54. ! ** block location and size:
  55. integer :: i0, j0
  56. integer :: bm, bn
  57. integer :: i1, i2, j1, j2
  58. end type TBlockMatrix
  59. ! --- interfaces ------------------------------
  60. interface Init
  61. module procedure mat_Init
  62. end interface
  63. interface Done
  64. module procedure mat_Done
  65. end interface
  66. interface SetStorage
  67. module procedure mat_SetStorage
  68. end interface
  69. interface ClearStorage
  70. module procedure mat_ClearStorage
  71. end interface
  72. interface IsZero
  73. module procedure mat_IsZero
  74. end interface
  75. interface SetBlock
  76. module procedure mat_SetBlock_range
  77. module procedure mat_SetBlock_array
  78. end interface
  79. contains
  80. ! ==============================================================
  81. subroutine mat_Init( mat, key )
  82. ! --- in/out ------------------------------
  83. type(TBlockMatrix), intent(out) :: mat
  84. character(len=*), intent(in) :: key
  85. ! --- const ----------------------------------
  86. character(len=*), parameter :: name = mname//', mat_Init'
  87. ! --- begin -------------------------------
  88. ! store key
  89. mat%key = key
  90. ! dummy size:
  91. mat%m = 0
  92. mat%n = 0
  93. ! start with zero matrix:
  94. mat%zero = .true.
  95. ! initialize physical storage
  96. nullify( mat%a )
  97. mat%knd = kind(1.0)
  98. ! dummy block
  99. mat%i0 = 0
  100. mat%j0 = 0
  101. mat%i1 = 0
  102. mat%i2 = 0
  103. mat%j1 = 0
  104. mat%j2 = 0
  105. mat%bm = 0
  106. mat%bn = 0
  107. end subroutine mat_Init
  108. ! ***
  109. subroutine mat_Done( mat )
  110. ! --- in/out ------------------------------
  111. type(TBlockMatrix), intent(inout) :: mat
  112. ! --- const ----------------------------------
  113. character(len=*), parameter :: name = mname//', mat_Done'
  114. ! --- begin -------------------------------
  115. ! clear memory ...
  116. call ClearStorage( mat )
  117. end subroutine mat_Done
  118. ! =========================================================
  119. subroutine mat_SetStorage( mat, am, an )
  120. ! --- in/out ------------------------------
  121. type(TBlockMatrix), intent(inout) :: mat
  122. integer, intent(in) :: am, an
  123. ! --- const ----------------------------------
  124. character(len=*), parameter :: name = mname//', mat_SetStorage'
  125. ! --- local -------------------------------
  126. integer :: stat
  127. ! --- begin -------------------------------
  128. ! check ...
  129. if ( (am < 1) .or. (an < 1) ) then
  130. write (*,'("ERROR - strange storage definition:")')
  131. write (*,'("ERROR - storage : ",2i7)') am, an
  132. write (*,'("ERROR - matrix key : ",a)') mat%key
  133. write (*,'("ERROR in ",a)') name; stop
  134. end if
  135. ! allocate memory:
  136. if ( associated(mat%a) ) then
  137. if ( any( shape(mat%a) /= (/am,an/) ) ) then
  138. deallocate( mat%a, stat=stat )
  139. if ( stat /= 0 ) then
  140. write (*,'("ERROR - error during deallocation of matrix;")')
  141. write (*,'("ERROR - matrix key : ",a)') mat%key
  142. write (*,'("ERROR in ",a)') name; stop
  143. end if
  144. end if
  145. end if
  146. if ( .not. associated(mat%a) ) then
  147. allocate( mat%a(am,an), stat=stat )
  148. if ( stat /= 0 ) then
  149. write (*,'("ERROR - error during allocation of matrix;")')
  150. write (*,'("ERROR - matrix key : ",a)') mat%key
  151. write (*,'("ERROR in ",a)') name; stop
  152. end if
  153. end if
  154. ! set maximum shape:
  155. mat%am = am
  156. mat%an = an
  157. end subroutine mat_SetStorage
  158. ! ***
  159. subroutine mat_ClearStorage( mat )
  160. ! --- in/out ------------------------------
  161. type(TBlockMatrix), intent(inout) :: mat
  162. ! --- const ----------------------------------
  163. character(len=*), parameter :: name = mname//', mat_ClearStorage'
  164. ! --- local -------------------------------
  165. integer :: stat
  166. ! --- begin -------------------------------
  167. ! remove physical storage ...
  168. if ( associated(mat%a) ) then
  169. deallocate( mat%a, stat=stat )
  170. if ( stat /= 0 ) then
  171. write (*,'("ERROR - error during deallocation of matrix;")')
  172. write (*,'("ERROR - matrix key : ",a)') mat%key
  173. write (*,'("ERROR in ",a)') name; stop
  174. end if
  175. nullify( mat%a )
  176. end if
  177. end subroutine mat_ClearStorage
  178. ! =========================================================
  179. logical function mat_IsZero( mat )
  180. ! --- in/out ------------------------------
  181. type(TBlockMatrix), intent(in) :: mat
  182. ! --- begin -------------------------------
  183. mat_IsZero = mat%zero
  184. end function mat_IsZero
  185. ! =========================================================
  186. subroutine mat_SetBlock_range( mat, m, n, i1, i2, j1, j2 )
  187. ! --- in/out ------------------------------
  188. type(TBlockMatrix), intent(inout) :: mat
  189. integer, intent(in) :: m, n
  190. integer, intent(in) :: i1, i2, j1, j2
  191. ! --- const ----------------------------------
  192. character(len=*), parameter :: name = mname//', mat_SetBlock_range'
  193. ! --- begin -------------------------------
  194. ! memory allocated ?
  195. if ( .not. associated(mat%a) ) then
  196. write (*,'("ERROR - no storage allocated")')
  197. write (*,'("ERROR - matrix key : ",a)') mat%key
  198. write (*,'("ERROR in ",a)') name; stop
  199. end if
  200. ! check ...
  201. if ( (m < 1) .or. (n < 1) .or. &
  202. (i1 < 1) .or. (i1 > m) .or. (i2 < i1) .or. (i2 > m) .or. &
  203. (j1 < 1) .or. (j1 > n) .or. (j2 < j1) .or. (j2 > n) .or. &
  204. (i2-i1+1 > mat%am) .or. (j2-j1+1 > mat%an) ) then
  205. write (*,'("ERROR - strange block definition:")')
  206. write (*,'("ERROR - matrix shape : ",2i6)') m, n
  207. write (*,'("ERROR - block i1, i2 : ",2i6)') i1, i2
  208. write (*,'("ERROR - j1, j2 : ",2i6)') j1, j2
  209. write (*,'("ERROR - storage : ",2i6)') mat%am, mat%an
  210. write (*,'("ERROR - matrix key : ",a)') mat%key
  211. write (*,'("ERROR in ",a)') name; stop
  212. end if
  213. ! logical shape of the matrix:
  214. mat%m = m
  215. mat%n = n
  216. ! block range:
  217. mat%i1 = i1
  218. mat%i2 = i2
  219. mat%j1 = j1
  220. mat%j2 = j2
  221. ! block base position
  222. mat%i0 = mat%i1 - 1
  223. mat%j0 = mat%j1 - 1
  224. ! block size
  225. mat%bm = mat%i2 - mat%i1 + 1
  226. mat%bn = mat%j2 - mat%j1 + 1
  227. end subroutine mat_SetBlock_range
  228. ! ***
  229. subroutine mat_SetBlock_array( mat, m, n, i1, j1, arr )
  230. ! --- in/out ------------------------------
  231. type(TBlockMatrix), intent(inout) :: mat
  232. integer, intent(in) :: m, n
  233. integer, intent(in) :: i1, j1
  234. real, intent(in) :: arr(:,:)
  235. ! --- const ----------------------------------
  236. character(len=*), parameter :: name = mname//', mat_SetBlock_array'
  237. ! --- local -------------------------------
  238. integer :: i2, j2
  239. ! --- begin -------------------------------
  240. ! end of ranges:
  241. i2 = i1 + size(arr,1) - 1
  242. j2 = j1 + size(arr,2) - 1
  243. ! set block position, checks included:
  244. call SetBlock( mat, m, n, i1, i2, j1, j2 )
  245. ! fill contents
  246. mat%a(1:mat%bm,1:mat%bn) = arr
  247. ! not zero anymore
  248. mat%zero = .false.
  249. end subroutine mat_SetBlock_array
  250. end module num_matrix_block