MODFLOW 6  version 6.7.0.dev0
USGS Modular Hydrologic Model
SparseMatrix.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, dp
3  use constantsmodule, only: dzero
7  use sparsemodule, only: sparsematrix
9  implicit none
10  private
11 
12  type, public, extends(matrixbasetype) :: sparsematrixtype
13  integer(I4B), pointer :: nrow
14  integer(I4B), pointer :: ncol
15  integer(I4B), pointer :: nja
16  integer(I4B), dimension(:), pointer, contiguous :: ia !< indexes into ja for columns, sorted: diagonal element first
17  integer(I4B), dimension(:), pointer, contiguous :: ja
18  real(dp), dimension(:), pointer, contiguous :: amat
19  contains
20  procedure :: init => spm_init
21  procedure :: destroy => spm_destroy
22  procedure :: create_vec_mm => spm_create_vec_mm
23  procedure :: create_vec => spm_create_vec
24 
25  procedure :: get_value_pos => spm_get_value_pos
26  procedure :: get_diag_value => spm_get_diag_value
27 
28  procedure :: set_diag_value => spm_set_diag_value
29  procedure :: set_value_pos => spm_set_value_pos
30  procedure :: add_value_pos => spm_add_value_pos
31  procedure :: add_diag_value => spm_add_diag_value
32  procedure :: zero_entries => spm_zero_entries
33  procedure :: zero_row_offdiag => spm_zero_row_offdiag
34 
35  procedure :: get_first_col_pos => spm_get_first_col_pos
36  procedure :: get_last_col_pos => spm_get_last_col_pos
37  procedure :: get_column => spm_get_column
38  procedure :: get_position => spm_get_position
39  procedure :: get_position_diag => spm_get_position_diag
40  procedure :: get_aij => spm_get_aij
41  procedure :: get_row_offset => spm_get_row_offset
42 
43  procedure :: multiply => spm_multiply
44 
45  procedure :: allocate_scalars
46  procedure :: allocate_arrays
47 
48  end type sparsematrixtype
49 
50 contains
51 
52  !> @brief Initialize sparse matrix from passed
53  !< sparsity structure
54  subroutine spm_init(this, sparse, mem_path)
55  class(sparsematrixtype) :: this
56  type(sparsematrix) :: sparse
57  character(len=*) :: mem_path
58  ! local
59  integer(I4B) :: ierror
60 
61  this%memory_path = mem_path
62 
63  call this%allocate_scalars()
64 
65  this%nrow = sparse%nrow
66  this%ncol = sparse%ncol
67  this%nja = sparse%nnz
68 
69  call this%allocate_arrays()
70 
71  call sparse%filliaja(this%ia, this%ja, ierror, sort=.false.)
72  call this%zero_entries()
73 
74  end subroutine spm_init
75 
76  subroutine spm_destroy(this)
77  class(sparsematrixtype) :: this
78 
79  call mem_deallocate(this%nrow)
80  call mem_deallocate(this%ncol)
81  call mem_deallocate(this%nja)
82 
83  call mem_deallocate(this%ia)
84  call mem_deallocate(this%ja)
85  call mem_deallocate(this%amat)
86 
87  end subroutine spm_destroy
88 
89  function spm_create_vec_mm(this, n, name, mem_path) result(vec)
90  class(sparsematrixtype) :: this ! this sparse matrix
91  integer(I4B) :: n !< the nr. of elements in the vector
92  character(len=*) :: name !< the variable name (for access through memory manager)
93  character(len=*) :: mem_path !< memory path for storing the underlying memory items
94  class(vectorbasetype), pointer :: vec ! the vector to create
95  ! local
96  class(seqvectortype), pointer :: seq_vec
97 
98  allocate (seq_vec)
99  call seq_vec%create_mm(n, name, mem_path)
100  vec => seq_vec
101 
102  end function spm_create_vec_mm
103 
104  function spm_create_vec(this, n) result(vec)
105  class(sparsematrixtype) :: this ! this sparse matrix
106  integer(I4B) :: n !< the nr. of elements in the vector
107  class(vectorbasetype), pointer :: vec ! the vector to create
108  ! local
109  class(seqvectortype), pointer :: seq_vec
110 
111  allocate (seq_vec)
112  call seq_vec%create(n)
113  vec => seq_vec
114 
115  end function spm_create_vec
116 
117  function spm_get_value_pos(this, ipos) result(value)
118  class(sparsematrixtype) :: this
119  integer(I4B) :: ipos
120  real(dp) :: value
121 
122  value = this%amat(ipos)
123 
124  end function spm_get_value_pos
125 
126  function spm_get_diag_value(this, irow) result(diag_value)
127  class(sparsematrixtype) :: this
128  integer(I4B) :: irow
129  real(dp) :: diag_value
130 
131  diag_value = this%amat(this%ia(irow))
132 
133  end function spm_get_diag_value
134 
135  subroutine spm_set_diag_value(this, irow, diag_value)
136  class(sparsematrixtype) :: this
137  integer(I4B) :: irow
138  real(DP) :: diag_value
139 
140  this%amat(this%ia(irow)) = diag_value
141 
142  end subroutine spm_set_diag_value
143 
144  subroutine spm_set_value_pos(this, ipos, value)
145  class(sparsematrixtype) :: this
146  integer(I4B) :: ipos
147  real(DP) :: value
148 
149  this%amat(ipos) = value
150 
151  end subroutine spm_set_value_pos
152 
153  subroutine spm_add_value_pos(this, ipos, value)
154  class(sparsematrixtype) :: this
155  integer(I4B) :: ipos
156  real(DP) :: value
157 
158  this%amat(ipos) = this%amat(ipos) + value
159 
160  end subroutine spm_add_value_pos
161 
162  subroutine spm_add_diag_value(this, irow, value)
163  class(sparsematrixtype) :: this
164  integer(I4B) :: irow
165  real(DP) :: value
166 
167  this%amat(this%ia(irow)) = this%amat(this%ia(irow)) + value
168 
169  end subroutine spm_add_diag_value
170 
171  function spm_get_first_col_pos(this, irow) result(first_col_pos)
172  class(sparsematrixtype) :: this
173  integer(I4B) :: irow
174  integer(I4B) :: first_col_pos
175 
176  first_col_pos = this%ia(irow)
177 
178  end function spm_get_first_col_pos
179 
180  function spm_get_last_col_pos(this, irow) result(last_col_pos)
181  class(sparsematrixtype) :: this
182  integer(I4B) :: irow
183  integer(I4B) :: last_col_pos
184 
185  last_col_pos = this%ia(irow + 1) - 1
186 
187  end function spm_get_last_col_pos
188 
189  function spm_get_column(this, ipos) result(icol)
190  class(sparsematrixtype) :: this
191  integer(I4B) :: ipos
192  integer(I4B) :: icol
193 
194  icol = this%ja(ipos)
195 
196  end function spm_get_column
197 
198  !> @brief Return position index for (irow,icol) element
199  !! in the matrix. This index can be used in other
200  !! routines for direct access.
201  !< Returns -1 when not found.
202  function spm_get_position(this, irow, icol) result(ipos)
203  class(sparsematrixtype) :: this
204  integer(I4B) :: irow
205  integer(I4B) :: icol
206  integer(I4B) :: ipos
207  ! local
208  integer(I4B) :: i, icol_s, icol_e
209 
210  ipos = -1
211  icol_s = this%get_first_col_pos(irow)
212  icol_e = this%get_last_col_pos(irow)
213  do i = icol_s, icol_e
214  if (this%ja(i) == icol) then
215  ipos = i
216  return
217  end if
218  end do
219 
220  end function spm_get_position
221 
222  function spm_get_position_diag(this, irow) result(ipos_diag)
223  class(sparsematrixtype) :: this
224  integer(I4B) :: irow
225  integer(I4B) :: ipos_diag
226 
227  ipos_diag = this%ia(irow)
228 
229  end function spm_get_position_diag
230 
231  subroutine allocate_scalars(this)
232  class(sparsematrixtype) :: this
233 
234  call mem_allocate(this%nrow, 'NROW', this%memory_path)
235  call mem_allocate(this%ncol, 'NCOL', this%memory_path)
236  call mem_allocate(this%nja, 'NJA', this%memory_path)
237 
238  end subroutine allocate_scalars
239 
240  subroutine allocate_arrays(this)
241  class(sparsematrixtype) :: this
242 
243  call mem_allocate(this%ia, this%nrow + 1, 'IA', this%memory_path)
244  call mem_allocate(this%ja, this%nja, 'JA', this%memory_path)
245  call mem_allocate(this%amat, this%nja, 'AMAT', this%memory_path)
246 
247  end subroutine allocate_arrays
248 
249  !> @brief Set all entries in the matrix to zero
250  !<
251  subroutine spm_zero_entries(this)
252  class(sparsematrixtype) :: this
253  ! local
254  integer(I4B) :: i
255 
256  do i = 1, this%nja
257  this%amat(i) = dzero
258  end do
259 
260  end subroutine spm_zero_entries
261 
262  !> @brief Set all off-diagonal entries in the matrix to zero
263  !<
264  subroutine spm_zero_row_offdiag(this, irow)
265  class(sparsematrixtype) :: this
266  integer(I4B) :: irow
267  ! local
268  integer(I4B) :: ipos
269 
270  do ipos = this%ia(irow) + 1, this%ia(irow + 1) - 1
271  this%amat(ipos) = dzero
272  end do
273 
274  end subroutine spm_zero_row_offdiag
275 
276  subroutine spm_get_aij(this, ia, ja, amat)
277  class(sparsematrixtype) :: this
278  integer(I4B), dimension(:), pointer, contiguous :: ia
279  integer(I4B), dimension(:), pointer, contiguous :: ja
280  real(DP), dimension(:), pointer, contiguous :: amat
281 
282  ia => this%ia
283  ja => this%ja
284  amat => this%amat
285 
286  end subroutine spm_get_aij
287 
288  function spm_get_row_offset(this) result(offset)
289  class(sparsematrixtype) :: this
290  integer(I4B) :: offset
291 
292  offset = 0
293 
294  end function spm_get_row_offset
295 
296  !> @brief Calculates the matrix vector product y = A*x
297  !<
298  subroutine spm_multiply(this, vec_x, vec_y)
299  class(sparsematrixtype) :: this
300  class(vectorbasetype), pointer :: vec_x
301  class(vectorbasetype), pointer :: vec_y
302  ! local
303  integer(I4B) :: irow, icol, ipos
304  real(DP), dimension(:), pointer, contiguous :: x, y
305 
306  x => vec_x%get_array()
307  y => vec_y%get_array()
308  do irow = 1, this%nrow
309  y(irow) = dzero
310  do ipos = this%ia(irow), this%ia(irow + 1) - 1
311  icol = this%ja(ipos)
312  y(irow) = y(irow) + this%amat(ipos) * x(icol)
313  end do
314  end do
315 
316  end subroutine spm_multiply
317 
318 end module sparsematrixmodule
subroutine init()
Definition: GridSorting.f90:24
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
This module defines variable data types.
Definition: kind.f90:8
integer(i4b) function spm_get_position(this, irow, icol)
Return position index for (irow,icol) element in the matrix. This index can be used in other routines...
integer(i4b) function spm_get_position_diag(this, irow)
subroutine allocate_scalars(this)
subroutine allocate_arrays(this)
real(dp) function spm_get_value_pos(this, ipos)
subroutine spm_multiply(this, vec_x, vec_y)
Calculates the matrix vector product y = A*x.
class(vectorbasetype) function, pointer spm_create_vec(this, n)
subroutine spm_set_value_pos(this, ipos, value)
subroutine spm_add_diag_value(this, irow, value)
subroutine spm_init(this, sparse, mem_path)
Initialize sparse matrix from passed.
class(vectorbasetype) function, pointer spm_create_vec_mm(this, n, name, mem_path)
subroutine spm_destroy(this)
subroutine spm_zero_entries(this)
Set all entries in the matrix to zero.
real(dp) function spm_get_diag_value(this, irow)
subroutine spm_set_diag_value(this, irow, diag_value)
subroutine spm_zero_row_offdiag(this, irow)
Set all off-diagonal entries in the matrix to zero.
integer(i4b) function spm_get_column(this, ipos)
integer(i4b) function spm_get_last_col_pos(this, irow)
integer(i4b) function spm_get_row_offset(this)
subroutine spm_add_value_pos(this, ipos, value)
subroutine spm_get_aij(this, ia, ja, amat)
integer(i4b) function spm_get_first_col_pos(this, irow)