Krylov subspace iterative solvers in Fortran, working in serial and in parallel. The name comes from Helsinki University of Technology, where Jouni Malinen wrote the first version.
This is the library Elmer has carried in its fhutiter/ directory. Here it builds on its own, with a test suite, CI across six platform and compiler combinations, and released binaries. It still builds unchanged as a subdirectory of Elmer, which is how Elmer consumes it.
Given a matrix you supply only through a matrix-vector product, HUTIter solves A x = b. You never hand it a matrix: you pass a subroutine that multiplies by one, which is what makes it usable on matrix formats it knows nothing about.
Seven methods, each in four precisions — s real, d double, c complex, z double complex, giving 28 entry points:
| Method | Entry point |
|---|---|
| Conjugate gradient | huti_d_cg |
| Conjugate gradient squared | huti_d_cgs |
| BiCGStab | huti_d_bicgstab |
| BiCGStab(2) | huti_d_bicgstab_2 |
| Quasi-minimal residual | huti_d_qmr |
| GMRES | huti_d_gmres |
| Transpose-free QMR | huti_d_tfqmr |
The manual is doc/hutidoc.tex.
USE huti_sfe
USE huti_interfaces
PROCEDURE(mv_iface_d), POINTER :: matvec => NULL()
INTEGER :: ipar(50)
DOUBLE PRECISION :: dpar(10)
matvec => my_matrix_times_vector
ipar = 0 ; dpar = 0.0d0
ipar(3) = n ! problem size
ipar(4) = 4 ! work array columns, method dependent
ipar(10) = 100 ! iteration limit
ipar(14) = 1 ! use the x passed in as the initial guess
dpar(1) = 1.0d-12 ! convergence tolerance
dpar(2) = 1.0d10 ! residual above which it declares divergence
CALL huti_d_cg(x, b, ipar, dpar, work, matvec, pcondl, pcondr, &
dotprod, normfun, mstopf)
! ipar(30) is the outcome. 1 is convergence.Two of those lines are worth the warning. dpar(2) is the divergence threshold, and leaving it at zero means every residual is above it, so the solver gives up after one step and reports failure on a problem it was solving correctly. The result code is ipar(30), not ipar(1). Both are in tests/cg_solves.F90, which exists partly to pin them down.
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failureYou need a Fortran compiler and, on Windows and macOS, BLAS. Tests are built when HUTIter is the top-level project and not when it is a subdirectory, so adding it to a parent project changes nothing about that project's configuration:
add_subdirectory(fhutiter)
target_link_libraries(my_solver PRIVATE fhuti)tests/cg_solves.F90 solves the 1D Laplacian on four interior points, A = tridiag(-1, 2, -1) with b = (1, 0, 0, 1), whose exact solution is x = (1, 1, 1, 1). Conjugate gradient reaches it in two iterations with an error of zero, so the check is an identity rather than a tolerance chosen to make the test pass.
Before this there were no tests. A library of iterative solvers nobody runs is a library nobody can change safely, and "it links" says nothing about whether it converges to the right answer.
Each archive on the releases page holds the shared library, the Fortran .mod files and the headers for one platform and compiler.
There is no single artifact that works everywhere. A .mod file is readable only by the compiler that wrote it — not merely the same vendor, but a compatible version — so every archive names its compiler as well as its platform. If yours is not listed, build from source; it takes under a minute.
No Windows arm64 archive: MSYS2 packages no Fortran compiler for that environment, and MSVC ships none either. That is a toolchain gap, not a limitation of this library.
Every push builds and tests on Linux x86-64 and arm64, macOS arm64 and x86-64, Windows x86-64 through MSYS2, and Linux again under Intel's ifx. A seventh job adds the repository to a throwaway parent project to confirm the subdirectory path still works and that it contributes no tests to its parent.
The Git history reaches back to 28 February 2014 and the commit that generated the Fortran version of HUTIter. Elmer's development before its 2014 move to GitHub is on SourceForge at svn.code.sf.net/p/elmerfem/code, and that import squashed what came before; where earlier history has been recoverable for a component it has been recovered and grafted on, verified by tree-hash identity at the join.
LGPL-2.1. See COPYING and LGPL-2.1.
It is one piece of ElmerCSC/elmerfem#202, on breaking Elmer's tree into components that build, test and release on their own. Work happens under github.com/AltElmer and is offered upstream from there; nothing here is a fork intended to diverge.