FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SAAMG_adapt.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 !-------------------------------------------------------------------------------
15  use hecmw_util
16  use hecmw_precond_saamg_matrix, only: hecmwst_saamg_bcsr, hecmw_saamg_bcsr_free
17  use hecmw_precond_saamg_comm, only: hecmwst_saamg_comm, hecmw_saamg_comm_free, &
19  implicit none
20 
21  private
22  public :: hecmw_saamg_from_hecmat
24 
25 contains
26 
34  subroutine hecmw_saamg_from_hecmat(hecMAT, A, include_halo)
35  implicit none
36  type(hecmwst_matrix), intent(in) :: hecmat
37  type(hecmwst_saamg_bcsr), intent(out) :: a
38  logical, optional, intent(in) :: include_halo
39  integer(kind=kint) :: ndof, ndof2, nnode, ncolnode, i, ii, kk, j, jn, pos, cnt, b0, astat
40  logical :: halo
41 
42  halo = .false.
43  if (present(include_halo)) halo = include_halo
44 
45  ndof = hecmat%NDOF
46  ndof2 = ndof*ndof
47  nnode = hecmat%N ! internal rows
48  if (halo) then
49  ncolnode = hecmat%NP ! columns reference internal + halo
50  else
51  ncolnode = hecmat%N
52  end if
53 
54  ! Build the block-CSR directly from the hecMAT BCRS (diagonal D + lower AL +
55  ! upper AU, one nb x nb block per neighbor) WITHOUT an intermediate triplet
56  ! buffer -- avoids holding the operator twice (critical for large meshes).
57  ! hecMAT stores each block row-major ((ii-1)*ndof+kk); transpose to col-major.
58  call hecmw_saamg_bcsr_free(a)
59  a%n = nnode*ndof; a%ncol = ncolnode*ndof; a%nb = ndof; a%mb = ndof
60  a%nbrow = nnode; a%nbcol = ncolnode
61  allocate(a%browptr(nnode+1))
62 
63  ! pass 1: count blocks per row (diagonal + kept L + kept U)
64  a%browptr(1) = 1
65  do i = 1, nnode
66  cnt = 1 ! diagonal block
67  do j = hecmat%indexL(i-1)+1, hecmat%indexL(i)
68  if (halo .or. hecmat%itemL(j) <= nnode) cnt = cnt + 1
69  end do
70  do j = hecmat%indexU(i-1)+1, hecmat%indexU(i)
71  if (halo .or. hecmat%itemU(j) <= nnode) cnt = cnt + 1
72  end do
73  a%browptr(i+1) = a%browptr(i) + cnt
74  end do
75  a%nnzb = a%browptr(nnode+1) - 1
76  a%nnz = ndof2 * a%nnzb
77  allocate(a%bcol(a%nnzb), a%bval(ndof2*a%nnzb), stat=astat)
78  call hecmw_saamg_check_alloc(astat, operator'from_hecmat finest (bcol/bval)')
79 
80  ! pass 2: fill blocks in place (diagonal first, then L, then U)
81  do i = 1, nnode
82  pos = a%browptr(i)
83  a%bcol(pos) = i; b0 = (pos-1)*ndof2 ! diagonal block
84  do ii = 1, ndof
85  do kk = 1, ndof
86  a%bval(b0 + (kk-1)*ndof+ii) = hecmat%D(ndof2*(i-1) + (ii-1)*ndof + kk)
87  end do
88  end do
89  pos = pos + 1
90  do j = hecmat%indexL(i-1)+1, hecmat%indexL(i)
91  jn = hecmat%itemL(j)
92  if (.not. halo .and. jn > nnode) cycle
93  a%bcol(pos) = jn; b0 = (pos-1)*ndof2
94  do ii = 1, ndof
95  do kk = 1, ndof
96  a%bval(b0 + (kk-1)*ndof+ii) = hecmat%AL(ndof2*(j-1) + (ii-1)*ndof + kk)
97  end do
98  end do
99  pos = pos + 1
100  end do
101  do j = hecmat%indexU(i-1)+1, hecmat%indexU(i)
102  jn = hecmat%itemU(j)
103  if (.not. halo .and. jn > nnode) cycle
104  a%bcol(pos) = jn; b0 = (pos-1)*ndof2
105  do ii = 1, ndof
106  do kk = 1, ndof
107  a%bval(b0 + (kk-1)*ndof+ii) = hecmat%AU(ndof2*(j-1) + (ii-1)*ndof + kk)
108  end do
109  end do
110  pos = pos + 1
111  end do
112  end do
113  end subroutine hecmw_saamg_from_hecmat
114 
118  subroutine hecmw_saamg_comm_from_mesh(hecMESH, ndof, cmt)
119  implicit none
120  type(hecmwst_local_mesh), intent(in) :: hecmesh
121  integer(kind=kint), intent(in) :: ndof
122  type(hecmwst_saamg_comm), intent(out) :: cmt
123  integer(kind=kint) :: nnb, nimp, nexp
124 
125  call hecmw_saamg_comm_free(cmt)
126  cmt%comm = hecmesh%MPI_COMM
127  cmt%my_rank = hecmesh%my_rank
128  cmt%nint = hecmesh%nn_internal
129  cmt%nnode = hecmesh%n_node
130  cmt%nb = ndof
131  cmt%n_neighbor = hecmesh%n_neighbor_pe
132  ! global node id per local node (for partition-invariant Lanczos seeds)
133  allocate(cmt%gnode(hecmesh%n_node))
134  cmt%gnode(1:hecmesh%n_node) = hecmesh%global_node_ID(1:hecmesh%n_node)
135  nnb = cmt%n_neighbor
136  if (nnb == 0) return
137 
138  nimp = hecmesh%import_index(nnb)
139  nexp = hecmesh%export_index(nnb)
140  allocate(cmt%neighbor(nnb))
141  allocate(cmt%import_index(0:nnb), cmt%import_item(nimp))
142  allocate(cmt%export_index(0:nnb), cmt%export_item(nexp))
143  cmt%neighbor(1:nnb) = hecmesh%neighbor_pe(1:nnb)
144  cmt%import_index(0:nnb) = hecmesh%import_index(0:nnb)
145  cmt%export_index(0:nnb) = hecmesh%export_index(0:nnb)
146  if (nimp > 0) cmt%import_item(1:nimp) = hecmesh%import_item(1:nimp)
147  if (nexp > 0) cmt%export_item(1:nexp) = hecmesh%export_item(1:nexp)
148  end subroutine hecmw_saamg_comm_from_mesh
149 
150 end module hecmw_precond_saamg_adapt
Smoothed Aggregation AMG preconditioner : FrontISTR adapter.
subroutine, public hecmw_saamg_from_hecmat(hecMAT, A, include_halo)
Convert hecmwST_matrix (FrontISTR block storage) -> internal block-CSR. Rows are always internal only...
subroutine, public hecmw_saamg_comm_from_mesh(hecMESH, ndof, cmt)
Build the finest-level communication table from the FrontISTR mesh. Copies the node-based halo descri...
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_comm_free(cmt)
Smoothed Aggregation AMG preconditioner : internal block-CSR matrix.
subroutine, public hecmw_saamg_bcsr_free(A)
Release the storage held by a hecmwST_saamg_bcsr.
I/O and Utility.
Definition: hecmw_util_f.F90:7