Solver backends
The built-in solver (CHOLMOD Cholesky with LDLᵀ fallback) needs nothing and is the default — most users never think about this. Loading LinearSolve.jl unlocks its entire algorithm collection through one keyword:
using LinearSolve
solve!(model; solver = KLUFactorization()) # alternative direct solver
solve!(model) # choice is remembered on the model
model.cache.factorization.solverKLUFactorization(true, true)Iterative solvers suit large models:
p1 = Node([0.0, 0.0, 0.0], :fixed)
p2 = Node([0.0, 0.0, 3.0], :free)
pm = Model([p1, p2], [FrameElement(p1, p2, wshape)],
[NodeForce(p2, [10.0, 0.0, 0.0])])
solve!(pm; solver = KrylovJL_CG()) # iterative — large models
displacement(pm.results, p2)6-element StaticArraysCore.SVector{6, Float64} with indices SOneTo(6):
0.005624999999999998
7.175664838754022e-20
0.0
1.0763497258131032e-19
0.0028124999999999995
0.0Repeated solves reuse the factorization's symbolic analysis (numeric-only refactorization on the frozen sparsity pattern) on every backend, including the default. Two notes: unpreconditioned iterative solvers want reasonably conditioned systems — supply a preconditioner for large/stiff models; and on the differentiable path, iterative solvers make gradients inexact adjoints (accuracy follows the solve tolerance) while direct factorizations stay exact.
(solve!/solve extend the CommonSolve verbs, so loading LinearSolve or other SciML packages never shadows Asap's API.)