FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_precond_SAAMG.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 !-------------------------------------------------------------------------------
13  use hecmw_util
17  use hecmw_precond_saamg_comm, only: hecmwst_saamg_comm, hecmw_saamg_comm_free, &
20  use hecmw_precond_saamg_core, only: hecmwst_saamg_hier, hecmw_saamg_setup, &
24  use hecmw_precond_saamg_matrix, only: hecmwst_saamg_bcsr, hecmw_saamg_bcsr_free
25  use hecmw_precond_saamg_param, only: hecmwst_saamg_params
30  use hecmw_mat_id
31  implicit none
32 
33  private
37 
38  type(hecmwST_saamg_hier), save :: g_dh
39  type(hecmwST_saamg_comm), save :: g_cmt
40  logical, save :: INITIALIZED = .false.
41  integer(kind=kint), save :: g_n = 0
42  integer(kind=kint), save :: g_id = 0
43  ! Size part of the structure signature of the matrix the hierarchy was built
44  ! from. The recycling flags (Iarray(98)/(97)) are a caller-side CONTRACT:
45  ! structure changes must be reported via Iarray(98). The one known caller whose
46  ! structure can change under a values-only flag -- the contact-elimination path,
47  ! whose reduced system depends on a value-driven slave-dof choice -- now detects
48  ! this itself and raises Iarray(98) at the source (notify_structure_change in
49  ! solve_LINEQ_contact_elim; full pattern hash there). This O(1) size check is
50  ! kept as a last-resort safety net against OTHER contract violations: a stale
51  ! hierarchy applied to a matrix of different size corrupts memory (observed on
52  ! mobile_case np=8 before the fixes). On mismatch we fall through to a full
53  ! rebuild (notice under LOGLEVEL>=1).
54  integer(kind=kint), save :: g_sig(4) = 0
55 
56 contains
57 
58  subroutine hecmw_precond_saamg_setup(hecMAT, hecMESH, sym)
59  implicit none
60  type(hecmwst_matrix), intent(inout) :: hecmat
61  type(hecmwst_local_mesh), intent(inout) :: hecmesh
62  integer(kind=kint), intent(in) :: sym
63  type(hecmwst_saamg_bcsr) :: a
64  type(hecmwst_saamg_params) :: prm
65  real(kind=kreal), allocatable :: b(:,:)
66  integer(kind=kint) :: ndof, nint, iopt(10), m, astat, myrank, sig_bad
67  real(kind=kreal) :: ropt(10)
68  logical :: will_use_mumps
69 
70  ! SA-AMG's setup needs LAPACK (dense coarsest factorization, per-aggregate QR,
71  ! Lanczos tridiagonal eigenvalue). LAPACK is optional in FrontISTR, so fail
72  ! early with a clear message rather than at an obscure link/runtime point.
73  if (.not. hecmw_saamg_lapack_available()) then
74  if (hecmw_comm_get_rank() == 0) write(*,'(a)') &
75  '#### SA-AMG (PRECOND=22) requires a LAPACK-enabled build. Rebuild with '// &
76  '--with-lapack (setup.sh) or -DWITH_LAPACK=ON (cmake), or select another preconditioner.'
78  end if
79 
80  ! Recycle-flag branches below are guarded by the structure signature (g_sig):
81  ! the flags are a caller-side contract that some callers break (see g_sig
82  ! comment). The verdict MUST be identical on every rank -- reuse / refresh /
83  ! rebuild all execute different collective patterns, so a per-rank decision
84  ! deadlocks (one rank's contact state can change while another's does not).
85  ! Hence the local check is allreduced before branching.
86  if (initialized .and. hecmat%Iarray(98) == 0) then
87  sig_bad = 0
88  if (.not. sig_sizes_match(hecmat)) sig_bad = 1
89  call hecmw_saamg_comm_allreduce_sum_int(g_cmt, sig_bad)
90  if (sig_bad > 0) then
91  if (hecmw_mat_get_loglevel(hecmat) >= 1 .and. hecmw_comm_get_rank() == 0) write(*,'(a)') &
92  '#### SA-AMG: matrix structure changed under a values-only recycle flag -- full rebuild'
93  else if (hecmat%Iarray(97) == 0) then
94  ! nothing changed -> reuse the hierarchy as-is (also covers precond recycling)
95  call saamg_register_mat(hecmat, hecmesh) ! keep the matvec hook pointing at the current matrix
96  return
97  else
98  ! structure unchanged, values changed -> numeric-only refresh (Newton reuse):
99  ! reuse aggregation / coarse comm table / tentative P-hat, recompute the rest.
100  call saamg_register_mat(hecmat, hecmesh) ! refresh the fine-level matvec hook to the new values
101  call hecmw_saamg_from_hecmat(hecmat, a, include_halo=.true.)
102  call hecmw_saamg_refresh(g_dh, a)
103  call hecmw_saamg_bcsr_free(a)
104  hecmat%Iarray(97) = 0
105  return
106  end if
107  end if
108 
109  ! structure changed -> full rebuild
110  if (initialized) call hecmw_precond_saamg_clear(hecmat%NDOF)
111  call saamg_register_mat(hecmat, hecmesh) ! register for the fine-level matvec hook (HEC-MW matvec)
112 
113  ndof = hecmat%NDOF
114  ! near-kernel size m by problem type: 1=heat(const), 2=plane(2D RBM, 3 modes),
115  ! 3=solid / 6=shell (3D RBM, 6 modes).
116  select case (ndof)
117  case (1); m = 1
118  case (2); m = 3
119  case (3, 6); m = 6
120  case default
121  write(*,'(a)') '#### SA-AMG (PRECOND=22): only NDOF=1 (heat) / 2 (plane) / 3 (solid) / 6 (shell) supported'
123  end select
124  nint = hecmat%N
125 
126  ! map control-file options; 0 = keep default. Integer line (Iarray 41:50) and
127  ! real line (Rarray 41:50). Integer slots 1-7 mirror the ML (PRECOND=5) layout
128  ! so ML users can reuse the same option line (see fstr_ctrl_common precond==22
129  ! and hecmw_ML_wrapper.c, which reads opt[0..6] = slots 1-7); slots 8-10 are
130  ! outside what ML reads and hold SA-AMG-specific knobs. The real line is not
131  ! read by ML at all, so it carries the remaining knobs (including a few integer
132  ! ones, rounded on read).
133  ! 1 = coarsest solver (ML CoarseSolver: 0=auto, 1=Smoother, 2=dense, 3=MUMPS)
134  ! 2 = smoother type (ML SmootherType: 0/1=Chebyshev; 2/3 N/A -> Chebyshev)
135  ! 3 = cycle (ML MGType: 0=default(=W)/1=V, 2=W; 3=FullV N/A -> W)
136  ! 4 = max levels (ML MaxLevels)
137  ! 5 = RESERVED (ML CoarsenScheme; SA-AMG is always uncoupled -> warn
138  ! and ignore. Deliberately kept unused: an ML deck
139  ! carries 1..5 here, which used to be silently taken as
140  ! max_size and wrecked the hierarchy)
141  ! 6 = Chebyshev degree (ML NumSweeps)
142  ! 7 = coarse size (ML MaxCoarseSize)
143  ! 8 = max aggregate size (SA-AMG-specific: the aggressive-coarsening lever)
144  ! 9 = galerkin_lowmem (Ac=P^T A P: 0 = default (2-stage everywhere, faster),
145  ! > 0 = low-memory (fuse the finest level only, same
146  ! peak as fully fused but faster; deep levels 2-stage))
147  ! 10 = RESERVED (free slot for future SA-AMG-specific knobs)
148  ! Real line: 1 = theta (strength threshold), 2 = cheb_alpha, 3 = safety,
149  ! 4 = taper_k (coarsening taper, 3-1: 0 = default 100, > 0 = use as K,
150  ! < 0 = disable the taper / legacy behavior)
151  ! 5 = agg_order (aggregation seed-scan ordering: 0 = default (BFS),
152  ! < 0 = natural node order / legacy, 1..4 = explicit mode
153  ! (1=bfs, 2=gid-hash, 3=mindeg, 4=maxdeg))
154  ! 6 = min aggregate size (0 = default 3)
155  ! 7 = verify (0 = off, > 0 = on) / 8 = dump_vtk (0 = off, > 0 = on)
156  call hecmw_mat_get_solver_opt(hecmat, iopt)
157  myrank = hecmw_comm_get_rank()
158  ! slot 1: coarsest solver. The external encoding (ML CoarseSolver-compatible)
159  ! and the internal prm%coarsest_solver share the SAME numbering, so no
160  ! translation is needed: 0=auto, 1=smoother, 2=dense, 3=MUMPS.
161  select case (iopt(1))
162  case (0, 1, 2, 3) ; prm%coarsest_solver = iopt(1)
163  case default ; if (myrank == 0) write(*,'(a,i0,a)') &
164  '#### SA-AMG: invalid coarse solver ', iopt(1), ' (ignored) -- using auto'
165  end select
166  ! slot 2: smoother type -- SA-AMG only implements Chebyshev
167  select case (iopt(2))
168  case (0, 1) ; ! Chebyshev (only supported smoother)
169  case default ; if (myrank == 0) write(*,'(a,i0,a)') &
170  '#### SA-AMG: smoother type ', iopt(2), ' not supported -- using Chebyshev'
171  end select
172  ! slot 3: multigrid cycle order gamma (ML MGType-compatible: 1=V, 2=W).
173  ! 0 = keep default = W (prm%ncycle=2): never slower than V and markedly fewer
174  ! iterations on deep hierarchies; nlevel=2 degenerates to V (is_coarsest guard).
175  select case (iopt(3))
176  case (0) ; ! default -> keep prm%ncycle (=2, W-cycle)
177  case (1) ; prm%ncycle = 1 ! V-cycle (explicit)
178  case (2) ; prm%ncycle = 2 ! W-cycle
179  case (3) ; prm%ncycle = 2 ; if (myrank == 0) write(*,'(a)') &
180  '#### SA-AMG: Full-V cycle not supported -- using W-cycle'
181  case default ; if (myrank == 0) write(*,'(a,i0,a)') &
182  '#### SA-AMG: invalid cycle ', iopt(3), ' (ignored) -- using default (W)'
183  end select
184  if (iopt(4) > 0) prm%max_level = iopt(4) ! ML MaxLevels
185  ! slot 5: reserved. ML puts CoarsenScheme here (1..5 = UncoupledMIS/METIS/
186  ! ParMETIS/Zoltan/DD); SA-AMG always uses uncoupled aggregation, so the value is
187  ! ignored -- but say so, otherwise a reused ML option line looks like it selects
188  ! a coarsening scheme.
189  if (iopt(5) /= 0 .and. myrank == 0) then
190  write(*,'(a,i0,a)') '#### SA-AMG: int slot5 (ML CoarsenScheme) = ', iopt(5), &
191  ' is ignored -- SA-AMG always uses uncoupled aggregation'
192  write(*,'(a)') '#### (max aggregate size is int slot8)'
193  end if
194  if (iopt(6) > 0) prm%cheb_deg = iopt(6) ! ML NumSweeps (Chebyshev degree)
195  if (iopt(7) > 0) prm%coarse_size = iopt(7) ! ML MaxCoarseSize
196  if (iopt(8) > 0) prm%max_size = iopt(8) ! SA-AMG-specific (aggressive coarsening lever)
197  if (iopt(9) > 0) prm%galerkin_lowmem = .true. ! SA-AMG-specific (fuse the finest level only)
198  ! verbose has no iopt slot: enable it via !SOLVER LOGLEVEL>=1 (independent of
199  ! TIMELOG; LOGLEVEL unset = -1 leaves verbose off).
200  prm%loglevel = hecmw_mat_get_loglevel(hecmat) ! independent LOGLEVEL (-1 if unset); >=2 -> [mem] probes
201  prm%verbose = (prm%loglevel >= 1)
202  prm%timelog = hecmw_mat_get_timelog(hecmat) ! !SOLVER TIMELOG (2=VERBOSE -> per-section [time] probes)
203  call hecmw_mat_get_solver_ropt(hecmat, ropt)
204  if (ropt(1) > 0.0d0) prm%theta = ropt(1)
205  if (ropt(2) > 0.0d0) prm%cheb_alpha = ropt(2)
206  if (ropt(3) > 0.0d0) prm%safety = ropt(3)
207  ! real slot 4: coarsening-taper K (an integer carried on the real line: the int
208  ! line is reserved for the ML-compatible and high-traffic knobs, and the taper is
209  ! rarely touched). 0 = default (prm%taper_k = 100), > 0 = use as K,
210  ! < 0 = disable the taper (legacy pre-taper coarsening).
211  ! (int(x+0.5), not the intrinsic nint(): a local variable `nint` shadows it.)
212  if (ropt(4) > 0.0d0) prm%taper_k = int(ropt(4) + 0.5d0, kind=kint)
213  if (ropt(4) < 0.0d0) prm%taper_k = 0
214  ! real slot 5: aggregation seed-scan ordering. 0 = default (BFS), < 0 = natural
215  ! (legacy), 1..4 = explicit mode.
216  if (ropt(5) > 0.0d0 .and. ropt(5) < 4.5d0) prm%agg_order = int(ropt(5) + 0.5d0, kind=kint)
217  if (ropt(5) < 0.0d0) prm%agg_order = 0
218  ! real slot 6: min aggregate size (integer carried on the real line; rarely
219  ! touched -- it only sets the forced-merge threshold for leftover aggregates).
220  if (ropt(6) > 0.0d0) prm%min_size = int(ropt(6) + 0.5d0, kind=kint)
221  ! real slots 7/8: diagnostics (0 = off, > 0 = on), alongside LOGLEVEL/TIMELOG.
222  prm%verify = (ropt(7) > 0.0d0)
223  prm%dump_vtk = (ropt(8) > 0.0d0) ! write finest aggregation to saamg_agg.<rank>.vtk
224  ! symmetric (CG, sym=1) vs non-symmetric (BiCGSTAB/GMRES, sym=0): the latter uses a
225  ! general (SYM=0 / LU) coarsest so the actual non-symmetric coarse is factored exactly.
226  prm%symmetric = (sym == 1)
227 
228  ! coarse_size auto-default by coarsest solver (only when the user left it unset):
229  ! dense LDL^T is O(N^3) so keep the coarsest small (100 dof); a distributed sparse
230  ! MUMPS coarsest is cheap at tens of thousands of dof -> use a much larger default
231  ! so the hierarchy stays shallow (matches the ML+MUMPS convention of 50000).
232  if (iopt(7) == 0) then
233  will_use_mumps = (prm%coarsest_solver == 3) .or. &
234  (prm%coarsest_solver == 0 .and. hecmw_saamg_cmumps_available())
235  if (will_use_mumps) prm%coarse_size = 50000
236  end if
237 
238  ! finest-level communication table (empty on 1 rank -> sequential behavior)
239  call hecmw_saamg_comm_from_mesh(hecmesh, ndof, g_cmt)
240  ! F4a: verify the distributed (halo-aware) matvec is consistent across ranks
241  if (prm%verify) call hecmw_saamg_verify_matvec(hecmat, hecmesh, g_cmt, ndof)
242  ! F4b: verify uncoupled aggregation + coarse comm-table construction
243  if (prm%verify) call hecmw_saamg_verify_coarsen(hecmat, g_cmt, m, prm)
244  ! F4b-2: verify halo-extended tentative P-hat (P-hat * B_coarse = B_fine, all rows)
245  if (prm%verify) call hecmw_saamg_verify_prolong(hecmat, hecmesh, g_cmt, ndof, m, prm)
246  ! F4c-1: verify the distributed smoothed prolongator (global ||P B_c - B_f|| rank-independent)
247  if (prm%verify) call hecmw_saamg_verify_smoothp(hecmat, hecmesh, g_cmt, ndof, m, prm)
248 
249  ! fully-distributed multilevel hierarchy: finest operator keeps halo columns
250  call hecmw_saamg_from_hecmat(hecmat, a, include_halo=.true.)
251  allocate(b(nint*ndof, m), stat=astat)
252  call hecmw_saamg_check_alloc(astat, 'near-kernel B (rigid-body modes)')
253  ! shared rigid-body near-kernel (with ML)
254  call hecmw_precond_rbm_from_mesh(hecmesh, ndof, b)
255  ! move A into the hierarchy (no redundant copy) unless verify still needs it
256  call hecmw_saamg_setup(a, g_cmt, b, m, prm, g_dh, saamg_fine_matvec, &
257  move_in=(.not. prm%verify))
258  ! verify: a numeric refresh reproduces (a) the full build for the SAME A and
259  ! (b) a fresh full build for a value-perturbed A' (same pattern) -- S4 routing
260  if (prm%verify) call hecmw_saamg_verify_refresh(g_dh, a, g_cmt, b, m, prm, nint*ndof)
261  if (prm%dump_vtk) call dump_agg_vtk(g_dh, hecmesh, ndof, nint)
262  call hecmw_saamg_bcsr_free(a)
263  deallocate(b)
264 
265  g_n = nint*ndof
266  g_sig = (/ hecmat%N, hecmat%NP, hecmat%NPL, hecmat%NPU /)
267  initialized = .true.
268  hecmat%Iarray(98) = 0
269  hecmat%Iarray(97) = 0
270  end subroutine hecmw_precond_saamg_setup
271 
273  logical function sig_sizes_match(hecMAT) result(ok)
274  implicit none
275  type(hecmwst_matrix), intent(in) :: hecmat
276  ok = (g_sig(1) == hecmat%N .and. g_sig(2) == hecmat%NP .and. &
277  g_sig(3) == hecmat%NPL .and. g_sig(4) == hecmat%NPU)
278  end function sig_sizes_match
279 
280 
285  subroutine dump_agg_vtk(dh, hecMESH, ndof, nint)
286  implicit none
287  type(hecmwst_saamg_hier), intent(in) :: dh
288  type(hecmwst_local_mesh), intent(in) :: hecmesh
289  integer(kind=kint), intent(in) :: ndof, nint
290  character(len=128) :: fname
291  integer(kind=kint) :: rank, idummy
292  idummy = ndof
293  if (.not. allocated(dh%aggr_fine)) return
294  rank = hecmw_comm_get_rank()
295  write(fname,'(a,i0,a)') 'saamg_agg.', rank, '.vtk'
296  ! hecMESH%node is 3*n_node interleaved; internal nodes are 1..nint
297  call hecmw_saamg_write_vtk(trim(fname), hecmesh%node, nint, dh%aggr_fine)
298  if (rank == 0) write(*,'(a)') &
299  '#### SA-AMG: wrote finest aggregation to saamg_agg.<rank>.vtk (ParaView)'
300  end subroutine dump_agg_vtk
301 
302  subroutine hecmw_precond_saamg_apply(ZP, NDOF)
303  implicit none
304  real(kind=kreal), intent(inout) :: zp(:)
305  integer(kind=kint), intent(in) :: ndof
306  real(kind=kreal), allocatable :: r(:), z(:)
307  allocate(r(g_n), z(g_n))
308  r(1:g_n) = zp(1:g_n)
309  z(1:g_n) = 0.0d0
310  call hecmw_saamg_apply(g_dh, r, z) ! z = M^{-1} r (one distributed V-cycle)
311  zp(1:g_n) = z(1:g_n)
312  deallocate(r, z)
313  end subroutine hecmw_precond_saamg_apply
314 
315  subroutine hecmw_precond_saamg_clear(NDOF)
316  implicit none
317  integer(kind=kint), intent(in) :: ndof
318  if (initialized) then
319  call hecmw_saamg_free(g_dh)
320  call hecmw_saamg_comm_free(g_cmt)
321  initialized = .false.
322  g_n = 0
323  g_sig = 0
324  end if
325  if (g_id > 0) then; call hecmw_mat_id_clear(g_id); g_id = 0; end if
326  end subroutine hecmw_precond_saamg_clear
327 
331  subroutine saamg_register_mat(hecMAT, hecMESH)
332  implicit none
333  type(hecmwst_matrix), intent(in), target :: hecmat
334  type(hecmwst_local_mesh), intent(in), target :: hecmesh
335  if (g_id > 0) call hecmw_mat_id_clear(g_id)
336  call hecmw_mat_id_set(hecmat, hecmesh, g_id)
337  end subroutine saamg_register_mat
338 
343  subroutine saamg_fine_matvec(x, y)
344  implicit none
345  real(kind=kreal), intent(inout) :: x(:)
346  real(kind=kreal), intent(out) :: y(:)
347  type(hecmwst_matrix), pointer :: mat
348  type(hecmwst_local_mesh), pointer :: mesh
349  call hecmw_mat_id_get(g_id, mat, mesh)
350  call hecmw_matvec(mesh, mat, x, y)
351  end subroutine saamg_fine_matvec
352 
353 end module hecmw_precond_saamg
subroutine, public hecmw_mat_id_set(hecMAT, hecMESH, id)
subroutine, public hecmw_mat_id_get(id, hecMAT, hecMESH)
subroutine, public hecmw_mat_id_clear(id)
subroutine, public hecmw_mat_get_solver_opt(hecMAT, solver_opt)
integer(kind=kint) function, public hecmw_mat_get_timelog(hecMAT)
integer(kind=kint) function, public hecmw_mat_get_loglevel(hecMAT)
subroutine, public hecmw_mat_get_solver_ropt(hecMAT, solver_ropt)
Rigid-body / near-kernel modes from mesh coordinates.
subroutine, public hecmw_precond_rbm_from_mesh(hecMESH, ndof, rbm)
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 : node graph + aggregation.
subroutine, public hecmw_saamg_write_vtk(fname, coord, nnode, aggr)
Write a legacy-VTK point cloud colored by aggregate id (ParaView diagnostic). coord is (x,...
Smoothed Aggregation AMG preconditioner : distributed MUMPS coarsest solver.
logical function, public hecmw_saamg_cmumps_available()
.true. only when compiled with MUMPS; the caller uses the dense coarsest else.
Smoothed Aggregation AMG preconditioner : lightweight comm table.
logical function, public hecmw_saamg_lapack_available()
Whether this build links LAPACK (SA-AMG's setup needs it: dense coarsest factorization,...
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_allreduce_sum_r(cmt, s)
Global sum-reduction of a scalar over the communicator (no-op when serial).
subroutine, public hecmw_saamg_comm_allreduce_sum_int(cmt, n)
Global sum-reduction of an integer over the communicator (no-op when serial).
subroutine, public hecmw_saamg_comm_free(cmt)
Smoothed Aggregation AMG preconditioner : distributed coarsening.
subroutine, public hecmw_saamg_free(dh)
subroutine, public hecmw_saamg_setup(A, cmt, bfine_int, m, prm, dh, fine_matvec, move_in)
Build a fully-distributed multilevel SA-AMG hierarchy. bfine_int is the near-kernel on internal nodes...
subroutine, public hecmw_saamg_refresh(dh, A_new)
Numeric-only refresh (Newton): reuse each level's aggregation / comm table / tentative P-hat AND the ...
subroutine, public hecmw_saamg_apply(dh, r, z)
Apply one distributed multilevel V-cycle: z = M^{-1} r (internal, length nint*nb).
Smoothed Aggregation AMG preconditioner : internal block-CSR matrix.
subroutine, public hecmw_saamg_bcsr_free(A)
Release the storage held by a hecmwST_saamg_bcsr.
Smoothed Aggregation AMG preconditioner : tunable parameters.
Smoothed Aggregation AMG preconditioner : distributed self-checks.
subroutine, public hecmw_saamg_verify_coarsen(hecMAT, cmt, m, prm)
F4b self-check: build the uncoupled aggregation and the coarse comm table on the distributed finest o...
subroutine, public hecmw_saamg_verify_prolong(hecMAT, hecMESH, cmt, ndof, m, prm)
F4b-2 self-check: build the halo-extended tentative prolongator P-hat_ext on the distributed operator...
subroutine, public hecmw_saamg_verify_refresh(dh, A, cmt, B, m, prm, n)
Verify the distributed numeric refresh: refreshing with the SAME operator A must reproduce the freshl...
subroutine, public hecmw_saamg_verify_matvec(hecMAT, hecMESH, cmt, ndof)
F4a self-check: the distributed (halo-aware) matvec applied to a globally consistent vector x (define...
subroutine, public hecmw_saamg_verify_smoothp(hecMAT, hecMESH, cmt, ndof, m, prm)
F4c-1 self-check: build the distributed SMOOTHED prolongator P and confirm the global near-kernel res...
Smoothed Aggregation AMG preconditioner : FrontISTR backend (id 22)
subroutine, public hecmw_precond_saamg_setup(hecMAT, hecMESH, sym)
subroutine, public hecmw_precond_saamg_apply(ZP, NDOF)
subroutine, public hecmw_precond_saamg_clear(NDOF)
subroutine, public hecmw_matvec(hecMESH, hecMAT, X, Y, COMMtime)
I/O and Utility.
Definition: hecmw_util_f.F90:7
subroutine hecmw_abort(comm, code)
integer(kind=4), parameter kint
integer(kind=kint) function hecmw_comm_get_comm()
integer(kind=4), parameter kreal
integer(kind=kint) function hecmw_comm_get_rank()