10#include "scaleFElib.h"
34 module procedure linalgebra_solvelineq_b1d
35 module procedure linalgebra_solvelineq_b2d
65 private :: precondstep_ilu0_constructmat
66 private :: precondstep_ilu0_solve
67 private :: precondstep_ptjacobi
78 real(rp),
intent(in) :: a(:,:)
79 real(rp) :: ainv(size(a,1),size(a,2))
81 real(rp) :: work(size(a,1))
82 integer :: ipiv(size(a,1))
90 call dgetrf(n, n, ainv, n, ipiv, info)
92 log_error(
"linalgebra_inv",*)
"Matrix is singular"
96 call dgetri(n, ainv, n, ipiv, work, n, info)
98 log_error(
"linalgebra_inv",*)
"Matrix inversion is failed"
107 subroutine linalgebra_solvelineq_b1d(A, b, x)
109 real(RP),
intent(in) :: A(:,:)
110 real(RP),
intent(in) :: b(:)
111 real(RP),
intent(out) :: x(size(b))
113 real(RP) :: A_lu(size(A,1),size(A,2))
114 integer :: ipiv(size(A,1))
122 call dgetrf(n, n, a_lu, n, ipiv, info)
124 log_error(
"linalgebra_SolveLinEq",*)
"Matrix is singular"
129 call dgetrs(
'N', n, 1, a_lu, n, ipiv, x, n, info)
131 log_error(
"linalgebra_SolveLinEq",*)
"Matrix inversion is failed"
136 end subroutine linalgebra_solvelineq_b1d
140 subroutine linalgebra_solvelineq_b2d(A, b, x)
142 real(RP),
intent(in) :: A(:,:)
143 real(RP),
intent(in) :: b(:,:)
144 real(RP),
intent(out) :: x(size(b,1),size(b,2))
146 real(RP) :: A_lu(size(A,1),size(A,2))
147 integer :: ipiv(size(A,1))
155 call dgetrf(n, n, a_lu, n, ipiv, info)
157 log_error(
"linalgebra_SolveLinEq",*)
"Matrix is singular"
162 call dgetrs(
'N', n,
size(b,2), a_lu, n, ipiv, x, n, info)
164 log_error(
"linalgebra_SolveLinEq",*)
"Matrix inversion is failed"
169 end subroutine linalgebra_solvelineq_b2d
175 real(rp),
intent(inout) :: a_lu(:,:)
176 integer,
intent(out) :: ipiv(size(a_lu,1))
184 call dgetrf(n, n, a_lu, n, ipiv, info)
186 log_error(
"linalgebra_LU",*)
"Matrix is singular"
209 N, KL, KU, NRHS, use_lapack )
211 integer,
intent(in) :: n
212 integer,
intent(in) :: kl
213 integer,
intent(in) :: ku
214 integer,
intent(in) :: nrhs
215 real(rp),
intent(inout) :: a(2*kl+ku+1,n)
216 real(rp),
intent(inout) :: b(n,nrhs)
217 integer,
intent(out) :: ipiv(n)
218 logical,
intent(in),
optional :: use_lapack
220 integer :: i, j, l, lm, p
226 logical :: use_lapack_
231 if (
present(use_lapack))
then
232 use_lapack_ = use_lapack
234 use_lapack_ = .false.
237 if ( use_lapack_ )
then
238 call dgbsv( n, kl, ku, nrhs, a, 2*kl+ku+1, ipiv, b, n, info)
247 do j=ku+2, min(kv, n)
255 if ( j+kv <= n )
then
262 call my_idamax( km+1, a(kv+1,j), &
266 if ( a(kv+jp,j) /= 0.0_rp )
then
267 ju = max( ju, min(j+ku+jp-1,n) )
270 call my_swap( ju-j+1, a(kv+jp,j), lda-1, &
275 tmp = 1.0_rp / a(kv+1,j)
277 a(l,j) = tmp * a(l,j)
279 call my_dger( km, ju-j, &
294 if ( l /= j )
call my_swap( nrhs, b(l,1), ldb, b(j,1), ldb )
295 call my_dger( lm, nrhs, &
307 b(j,p) = b(j,p) / a(kv+1,j)
309 do i=j-1, max(1,j-kv),-1
310 b(i,p) = b(i,p) - tmp * a(l+i,j)
325 real(rp),
intent(in) :: b(:)
326 real(rp),
intent(inout) :: x(:)
327 integer,
intent(in) :: m
328 integer,
intent(in) ::restart_num
329 real(rp),
intent(in) :: conv_crit
331 real(rp) :: x0(size(x))
332 real(rp) :: w(size(x))
333 real(rp) :: v(size(x),m+1)
334 real(rp) :: z(size(x),m+1)
335 real(rp) :: av(size(x))
336 real(rp) :: g(size(x)+1)
337 real(rp) :: r0_l2, r0_l2_new
340 real(rp) :: c(m), s(m)
342 real(rp) :: tmp, tmp1, tmp2
350 call precondstep_ilu0_constructmat(a, m_pc)
353 do restart_i=1, restart_num
355 if (restart_i == 1)
then
358 r0_l2 = sqrt(sum(v(:,1)**2))
360 v(:,1) = v(:,1)/r0_l2
365 call precondstep_ilu0_solve(m_pc, v(:,j), z(:,j))
370 h(i,j) = sum(w*v(:,i))
371 w(:) = w - h(i,j)*v(:,i)
373 h(j+1,j) = sqrt(sum(w**2))
374 v(:,j+1) = w(:)/h(j+1,j)
378 tmp1 = c(i)*r(i,j) + s(i)*h(i+1,j)
379 tmp2 = -s(i)*r(i,j) + c(i)*h(i+1,j)
384 tmp = sqrt(r(j,j)**2 + h(j+1,j)**2)
390 r(j,j) = c(j)*r(j,j) + s(j)*h(j+1,j)
395 y(i) = (g(i) - sum(r(i,i+1:m)*y(i+1:m)))/r(i,i)
398 x(:) = x + matmul(z(:,1:m),y)
405 r0_l2_new = sqrt(sum(v(:,1)**2))
408 if (r0_l2_new < conv_crit)
exit
418 subroutine my_idamax( N, DX, ind )
420 integer,
intent(in) :: n
421 real(rp),
intent(in) :: dx(*)
422 integer,
intent(out) :: ind
430 if ( abs(dx(i)) > dmax )
then
436 end subroutine my_idamax
440 subroutine my_dger( m, n, x, y, incy, A, LDA)
442 integer,
intent(in) :: m
443 integer,
intent(in) :: n
444 integer,
intent(in) :: lda
445 real(rp),
intent(inout) :: a(lda,*)
446 real(rp),
intent(in) :: x(*)
447 real(rp),
intent(in) :: y(*)
448 integer,
intent(in) :: incy
457 if ( tmp /= 0.0_rp )
then
459 a(i,j) = a(i,j) - tmp * x(i)
465 end subroutine my_dger
471 subroutine my_swap( n, dx, incx, dy, incy )
473 integer,
intent(in) :: n
474 real(rp),
intent(inout) :: dx(*)
475 integer,
intent(in) :: incx
476 real(rp),
intent(inout) :: dy(*)
477 integer,
intent(in) :: incy
483 if ( incx==1 .and. incy==1 )
then
515 end subroutine my_swap
518 subroutine precondstep_ptjacobi(A, b, x)
520 type(sparsemat),
intent(in) :: a
521 real(rp),
intent(in) :: b(:)
522 real(rp),
intent(out) :: x(size(b))
528 x(n) = b(n) / a%GetVal(n, n)
532 end subroutine precondstep_ptjacobi
535 subroutine precondstep_ilu0_constructmat(A, M)
536 use scale_const,
only: &
540 type(sparsemat),
intent(in) :: a
541 type(sparsemat),
intent(inout) :: m
543 integer :: i, j, k, n
544 real(rp) :: mij, m_ik, m_kk
554 if ( abs(m_ik) < eps .and. abs(m_kk) < eps )
then
556 call m%ReplaceVal( i, k, m_ik )
560 if ( abs(mij) < eps )
then
561 call m%ReplaceVal( i, j, mij - m%GetVal(i,k) * m%GetVal(k,j) )
569 end subroutine precondstep_ilu0_constructmat
572 subroutine precondstep_ilu0_solve(M, b, x)
578 real(rp),
intent(in) :: b(:)
579 real(rp),
intent(out) :: x(size(b))
589 log_error(
"linalgebra_PreCondStep_ILU0_solve",*)
"The strorge type of specified sparse matrix is not supported. Check!"
601 if (m%colIdx(j) <= i-1) &
602 x(i) = x(i) - m%val(j)*x(m%colIdx(j))
606 x(n) = x(n) / m%GetVal(n,n)
611 if (m%colIdx(j) >= i+1) &
612 x(i) = x(i) - m%val(j)*x(m%colIdx(j))
614 x(i) = x(i)/m%GetVal(i,i)
618 end subroutine precondstep_ilu0_solve
Solve a linear equation Ax=b using a direct solver.
Module common / Linear algebra.
real(rp) function, dimension(size(a, 1), size(a, 2)), public linalgebra_inv(a)
Calculate a inversion of matrix A.
subroutine, public linalgebra_solvelineq_gmres(a, b, x, m, restart_num, conv_crit)
Solve a linear equation Ax=b using the Generalized Minimal Residual solver (GMRES)
subroutine, public linalgebra_solvelineq_bndmat(a, b, ipiv, n, kl, ku, nrhs, use_lapack)
Calculate the solution of linear equations with a band matrix.
subroutine, public linalgebra_lu(a_lu, ipiv)
Perform LU factorization.
Module common / sparsemat.
integer, parameter, public sparsemat_storage_typeid_csr
Derived type to manage a sparse matrix.