LinearSolver¶
LinearSolver assembles the linear PDE system, applies boundary conditions, and solves the
resulting sparse linear system.
from gbmsc_pde import LinearSolver
solution = LinearSolver(pde, boundary_conditions).solve()
Constructor¶
LinearSolver(pde, bcs)
Parameters:
pde: configuredLinearPDEinstance.bcs: configuredBoundaryConditionsinstance.
Direct Solve¶
u = LinearSolver(pde, boundary_conditions).solve(solver="direct")
The direct path uses:
scipy.sparse.linalg.spsolve
This is the default solver.
Iterative Solves¶
u = LinearSolver(pde, boundary_conditions).solve(
solver="gmres",
tol=1e-8,
maxiter=1000,
)
Supported iterative methods:
"cg""gmres""bicgstab"
Optional preconditioners may be passed through preconditioner.
Use preconditioner="jacobi" for a diagonal Jacobi preconditioner.
Returning Assembly Data¶
For assembly data:
u, data = LinearSolver(pde, boundary_conditions).solve(return_data=True)
The returned data dictionary contains:
A: boundary-modified sparse system matrix,b: boundary-modified right-hand side,first_derivatives:(Mx, My),second_derivatives:(Mxx, Myy),nnz: number of nonzero entries inA,sparsity: percentage of zero entries,(1 - A.nnz / (A.shape[0] * A.shape[1])) * 100,solve_time: linear solve time in seconds,assembly_time: assembly and boundary-application time in seconds,solver_info: SciPy iterative solver info, or0for direct solves.
This is useful for measuring sparsity, conditioning estimates, or residuals.
Diagnostics Example¶
u, data = LinearSolver(pde, boundary_conditions).solve(return_data=True)
A = data["A"]
b = data["b"]
Mx, My = data["first_derivatives"]
Mxx, Myy = data["second_derivatives"]
sparsity = data["sparsity"]
residual = A.dot(u) - b
cpu_time = data["assembly_time"] + data["solve_time"]