FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SAAMG_coarse.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2026 FrontISTR Commons
3 ! This software is released under the MIT License, see License.txt
4 !-------------------------------------------------------------------------------
18  implicit none
19 
20  private
21  public :: hecmwst_saamg_coarse
22  public :: hecmw_saamg_coarse_setup
23  public :: hecmw_saamg_coarse_solve
24  public :: hecmw_saamg_coarse_free
25 
28  type hecmwst_saamg_coarse
29  integer(kind=kint) :: n = 0
30  logical :: symmetric = .true.
31  real(kind=kreal), allocatable :: ldl(:,:)
32  integer(kind=kint), allocatable :: ipiv(:)
33  integer(kind=kint) :: n_neg = 0
34  end type hecmwst_saamg_coarse
35 
36 contains
37 
41  subroutine hecmw_saamg_coarse_setup(Ac, symmetric, cs)
42  implicit none
43  type(hecmwst_saamg_bcsr), intent(in) :: ac
44  logical, intent(in) :: symmetric
45  type(hecmwst_saamg_coarse), intent(out) :: cs
46  real(kind=kreal), allocatable :: work(:)
47  real(kind=kreal) :: wq(1)
48  integer(kind=kint) :: n, lwork, info, astat
49 #ifdef HECMW_WITH_LAPACK
50  external :: dsytrf, dgetrf
51 
52  n = ac%n
54  cs%n = n; cs%symmetric = symmetric
55  allocate(cs%ldl(n,n), cs%ipiv(n), stat=astat)
56  call hecmw_saamg_check_alloc(astat, 'coarse_setup dense factor (ldl: n*n)')
57  call hecmw_saamg_to_dense_blk(ac, cs%ldl) ! densify directly from block storage
58 
59  if (symmetric) then
60  call dsytrf('L', n, cs%ldl, n, cs%ipiv, wq, -1, info); lwork = max(int(wq(1)), 1)
61  allocate(work(lwork))
62  call dsytrf('L', n, cs%ldl, n, cs%ipiv, work, lwork, info)
63  deallocate(work)
64  if (info /= 0) then
65  write(*,'(a,i0)') 'hecmw_saamg_coarse_setup: dsytrf info=', info
66  call hecmw_saamg_abort('coarse_setup: dense LDL^T factorization failed (dsytrf)')
67  end if
68  cs%n_neg = ldlt_n_negative(cs)
69  else
70  call dgetrf(n, n, cs%ldl, n, cs%ipiv, info)
71  if (info /= 0) then
72  write(*,'(a,i0)') 'hecmw_saamg_coarse_setup: dgetrf info=', info
73  call hecmw_saamg_abort('coarse_setup: dense LU factorization failed (dgetrf)')
74  end if
75  cs%n_neg = 0
76  end if
77 #else
78  call hecmw_saamg_require_lapack('dense coarsest factorization (dsytrf/dgetrf)')
79 #endif
80  end subroutine hecmw_saamg_coarse_setup
81 
86  function ldlt_n_negative(cs) result(nneg)
87  type(hecmwst_saamg_coarse), intent(in) :: cs
88  integer(kind=kint) :: nneg, k
89  real(kind=kreal) :: a, b, c, det, tr
90  nneg = 0
91  k = 1
92  do while (k <= cs%n)
93  if (cs%ipiv(k) > 0) then ! 1x1 pivot
94  if (cs%ldl(k,k) < 0.0d0) nneg = nneg + 1
95  k = k + 1
96  else ! 2x2 pivot on (k, k+1)
97  a = cs%ldl(k,k); b = cs%ldl(k+1,k); c = cs%ldl(k+1,k+1)
98  det = a*c - b*b; tr = a + c
99  if (det < 0.0d0) then
100  nneg = nneg + 1 ! one positive, one negative
101  else if (tr < 0.0d0) then
102  nneg = nneg + 2 ! both negative
103  end if
104  k = k + 2
105  end if
106  end do
107  end function ldlt_n_negative
108 
110  subroutine hecmw_saamg_coarse_solve(cs, b, x)
111  implicit none
112  type(hecmwst_saamg_coarse), intent(in) :: cs
113  real(kind=kreal), intent(in) :: b(:)
114  real(kind=kreal), intent(out) :: x(:)
115  integer(kind=kint) :: info
116 #ifdef HECMW_WITH_LAPACK
117  external :: dsytrs, dgetrs
118  x(1:cs%n) = b(1:cs%n)
119  if (cs%symmetric) then
120  call dsytrs('L', cs%n, 1, cs%ldl, cs%n, cs%ipiv, x, cs%n, info)
121  else
122  call dgetrs('N', cs%n, 1, cs%ldl, cs%n, cs%ipiv, x, cs%n, info)
123  end if
124  if (info /= 0) then
125  write(*,'(a,i0)') 'hecmw_saamg_coarse_solve: trs info=', info
126  call hecmw_saamg_abort('coarse_solve: dense triangular solve failed')
127  end if
128 #else
129  x(1:cs%n) = b(1:cs%n)
130  call hecmw_saamg_require_lapack('dense coarsest solve (dsytrs/dgetrs)')
131 #endif
132  end subroutine hecmw_saamg_coarse_solve
133 
134  subroutine hecmw_saamg_coarse_free(cs)
135  implicit none
136  type(hecmwst_saamg_coarse), intent(inout) :: cs
137  if (allocated(cs%ldl)) deallocate(cs%ldl)
138  if (allocated(cs%ipiv)) deallocate(cs%ipiv)
139  cs%n = 0
140  end subroutine hecmw_saamg_coarse_free
141 
Smoothed Aggregation AMG preconditioner : coarsest-level solver.
subroutine, public hecmw_saamg_coarse_solve(cs, b, x)
Solve Ac x = b using the stored LDL^T factors.
subroutine, public hecmw_saamg_coarse_setup(Ac, symmetric, cs)
Densify Ac and factor it: symmetric -> LDL^T (dsytrf), else -> LU (dgetrf, for a non-symmetric coarse...
subroutine, public hecmw_saamg_coarse_free(cs)
Smoothed Aggregation AMG preconditioner : lightweight comm table.
subroutine, public hecmw_saamg_check_alloc(ier, what)
Report a failed allocation (stat /= 0) with a clear message and a collective abort,...
subroutine, public hecmw_saamg_abort(msg)
Fatal-error termination with a clear message. Under MPI this is a COLLECTIVE abort (hecmw_abort -> MP...
subroutine, public hecmw_saamg_require_lapack(site)
Abort with a uniform message when a LAPACK-only code path is reached in a build without LAPACK....
Smoothed Aggregation AMG preconditioner : internal block-CSR matrix.
subroutine, public hecmw_saamg_to_dense_blk(A, dense)
Densify from the block-CSR storage.
Smoothed Aggregation AMG preconditioner : kind parameters.
integer(kind=4), parameter kreal