C and Fortran interfaces
This interface is still in early development. Not all Krylov.jl features are exposed yet (for example shifts and GPU devices). The API may change in future releases.
Krylov.jl ships libkrylov, a native shared library that exposes its solvers to languages that can call C code.
Pre-built artifacts for Linux (x86-64, aarch64), macOS (arm64, x86-64) and Windows (x86-64) are available on the Releases page. To build the library yourself, see Building libkrylov.
How it works
libkrylov is the whole of Krylov.jl compiled ahead of time into a shared library, with the Julia runtime embedded in the bundle. From the caller's point of view it is an ordinary C library. There is no Julia process to start and no .jl file to ship, only libkrylov.so (or .dylib / .dll) and the two headers krylov.h / krylov.f90.
The design rests on three ideas:
Opaque workspace handle.
krylov_workspace_createallocates a typed Krylov workspace and hands back avoid *. The workspace holds all the internal vectors a solver needs. You never dereference the pointer; you pass it to the other functions. The library keeps it alive (rooted against the Julia garbage collector) until you callkrylov_workspace_free.Matrix-free by callbacks. Krylov methods only touch the operator through products
A * x(and possiblyAᴴ * xorM⁻¹ * x). You never pass a matrix. You pass C function pointers that compute those products. The same interface drives a dense matrix, a sparse matrix, a stencil, or a fully matrix-free operator, in any language with a C ABI.Concrete types, no dynamic dispatch. A workspace is created for one
(solver, precision)pair. Every product, dot, and axpy then runs through statically-typed, fully specialised Julia code.
The lifecycle is always the same, regardless of the solver:
- Create a workspace with
krylov_workspace_create. - Solve with
krylov_solve, passing matrix-vector product callbacks. - Retrieve the solution with
krylov_get_x(andkrylov_get_yfor two-solution solvers). - Free the workspace with
krylov_workspace_free.
Quickstart
A complete C program solving a small SPD system with CG (the Fortran equivalent is on the Fortran interface page):
#include <stdio.h>
#include "krylov.h"
/* y = A*x for A = tridiag(-1, 2, -1); userdata carries the dimension n */
static void matvec_A(const void *xv, void *yv, void *userdata)
{
const double *x = (const double *)xv;
double *y = (double *)yv;
int n = *(const int *)userdata;
for (int i = 0; i < n; i++) {
y[i] = 2.0 * x[i];
if (i > 0) y[i] -= x[i-1];
if (i < n - 1) y[i] -= x[i+1];
}
}
int main(void)
{
int n = 5;
double b[5] = {1, 0, 0, 0, 1}, x[5];
void *ws = NULL;
krylov_workspace_create(KRYLOV_CG, n, n, KRYLOV_FLOAT64, KRYLOV_CPU, NULL, &ws);
krylov_solve(ws, matvec_A, NULL, NULL, NULL, b, NULL, &n, NULL); /* NULL opts = defaults */
krylov_get_x(ws, x, n);
printf("converged: %s niter: %d\n",
krylov_is_solved(ws) ? "yes" : "no", krylov_niter(ws));
krylov_workspace_free(ws);
return 0;
}Where to go next
The Reference page documents the full API:
- API overview, the complete list of functions, and the workspace lifetime.
- The matvec callbacks, how the operator and preconditioners are passed.
- Data types and precision.
- Choosing a solver: does it need the adjoint, a second right-hand side, or produce a second solution?
- Options and return codes.
- Error handling and safety, including thread safety.
- Warm start, preconditioning, and block Krylov solvers.
For runnable programs, see the C interface and Fortran interface pages.