Algebraic Multigrid (AMG) solvers for large sparse linear systems with Python interface
—
Methods for determining the strength of connections between unknowns, fundamental to AMG coarsening strategies. Strength of connection measures identify which matrix entries represent strong coupling that must be preserved during coarsening.
Traditional strength of connection measures based on matrix entry magnitudes.
def classical_strength_of_connection(A, theta=0.25):
"""
Classical strength of connection measure.
Determines strong connections based on ratio of off-diagonal
entries to diagonal entries. Entry A[i,j] is strong if
|A[i,j]| >= theta * max{|A[i,k]| : k != i}.
Parameters:
- A: sparse matrix, coefficient matrix
- theta: float, strength threshold (0 < theta <= 1):
* 0.25: standard choice, moderate strength
* 0.5: stricter strength requirement
* 0.1: weaker strength, more connections
Returns:
sparse matrix: strength matrix S where S[i,j] != 0
indicates strong connection from i to j
Notes:
- Most common strength measure for Classical AMG
- Works well for M-matrices and diagonally dominant systems
- May not be suitable for systems matrices or indefinite problems
"""
def symmetric_strength_of_connection(A, theta=0.0):
"""
Symmetric strength of connection measure.
Creates symmetric strength matrix by taking maximum of
classical strength in both directions. Suitable for
symmetric matrices and Smoothed Aggregation AMG.
Parameters:
- A: sparse matrix, coefficient matrix (preferably symmetric)
- theta: float, strength threshold (default 0.0)
Returns:
sparse matrix: symmetric strength matrix where
S[i,j] = S[j,i] and represents strong coupling
Notes:
- Default choice for Smoothed Aggregation AMG
- Preserves symmetry of strength pattern
- theta=0.0 includes all matrix connections
"""Usage Examples:
import pyamg
import numpy as np
# Classical strength for Poisson problem
A = pyamg.gallery.poisson((50, 50))
S_classical = pyamg.strength.classical_strength_of_connection(A, theta=0.25)
print(f"Classical SOC: {S_classical.nnz} strong connections")
# Symmetric strength for elasticity
A_elastic = pyamg.gallery.linear_elasticity((30, 30))
S_symmetric = pyamg.strength.symmetric_strength_of_connection(A_elastic)
print(f"Symmetric SOC: {S_symmetric.nnz} strong connections")
# Different strength thresholds
S_weak = pyamg.strength.classical_strength_of_connection(A, theta=0.1)
S_strong = pyamg.strength.classical_strength_of_connection(A, theta=0.5)
print(f"Weak ({S_weak.nnz}) vs Strong ({S_strong.nnz}) connections")Sophisticated measures for challenging problems and special matrix types.
def energy_based_strength_of_connection(A, theta=0.0, **kwargs):
"""
Energy-based strength of connection measure.
Determines strength based on energy contribution of connections
rather than algebraic magnitude. More robust for systems with
complex coupling patterns.
Parameters:
- A: sparse matrix, coefficient matrix
- theta: float, energy threshold
- B: array, near-nullspace vectors (optional)
- BtBinv: array, inverse of B^T B (optional)
Returns:
sparse matrix: energy-based strength matrix
Notes:
- Accounts for near-nullspace in strength computation
- More expensive than classical measures
- Better for elasticity and other systems problems
"""
def evolution_strength_of_connection(A, B=None, epsilon=4.0, k=2, proj_type='l2'):
"""
Evolution-based strength of connection measure.
Uses evolution process to determine strength based on
how connections affect error evolution. Most sophisticated
strength measure available.
Parameters:
- A: sparse matrix, coefficient matrix
- B: array, near-nullspace vectors (default: constant)
- epsilon: float, evolution parameter (default 4.0)
- k: int, number of evolution steps (default 2)
- proj_type: str, projection type ('l2', 'D_A')
Returns:
sparse matrix: evolution-based strength matrix
Notes:
- Most robust strength measure for difficult problems
- Higher computational cost than other measures
- Automatically adapts to problem characteristics
"""
def distance_strength_of_connection(A, theta=2.0):
"""
Distance-based strength of connection measure.
Determines strength based on geometric or algebraic
distance between degrees of freedom.
Parameters:
- A: sparse matrix, coefficient matrix
- theta: float, distance threshold
Returns:
sparse matrix: distance-based strength matrix
Notes:
- Useful when geometric information is available
- Can incorporate coordinate data
- Less common than algebraic measures
"""Usage Examples:
# Energy-based strength for elasticity
A = pyamg.gallery.linear_elasticity((25, 25))
B = np.ones((A.shape[0], 3)) # Rigid body modes
S_energy = pyamg.strength.energy_based_strength_of_connection(A, B=B)
# Evolution-based strength (most robust)
S_evolution = pyamg.strength.evolution_strength_of_connection(A, B=B, epsilon=4.0)
# Compare different measures
print(f"Energy SOC: {S_energy.nnz} connections")
print(f"Evolution SOC: {S_evolution.nnz} connections")Specialized measures for geometric and graph-based strength computation.
def algebraic_distance(A, B=None, distance='unit', **kwargs):
"""
Compute algebraic distance between degrees of freedom.
Measures algebraic distance based on how connections
propagate through the matrix graph structure.
Parameters:
- A: sparse matrix, coefficient matrix
- B: array, near-nullspace vectors
- distance: str, distance measure:
* 'unit': unit distance (default)
* 'abs': absolute value distance
* 'min': minimum distance
- **kwargs: distance-specific parameters
Returns:
array: distance matrix or distance values
Notes:
- Fundamental component of many strength measures
- Used internally by other strength functions
- Can be used standalone for analysis
"""
def affinity_distance(A, B=None, distance='unit', **kwargs):
"""
Compute affinity-based distance measure.
Measures strength based on affinity (similarity) of
connections rather than direct algebraic relationships.
Parameters:
- A: sparse matrix, coefficient matrix
- B: array, near-nullspace vectors
- distance: str, affinity measure type
- **kwargs: affinity-specific parameters
Returns:
sparse matrix: affinity-based strength matrix
Notes:
- Useful for graph-based problems
- Can incorporate problem-specific similarity measures
- Experimental, less established than classical measures
"""Usage Examples:
# Algebraic distance computation
A = pyamg.gallery.poisson((40, 40))
distances = pyamg.strength.algebraic_distance(A, distance='unit')
# Affinity-based strength
S_affinity = pyamg.strength.affinity_distance(A)# Conservative (many connections)
S_conservative = pyamg.strength.classical_strength_of_connection(A, theta=0.1)
# Standard (balanced)
S_standard = pyamg.strength.classical_strength_of_connection(A, theta=0.25)
# Aggressive (fewer connections)
S_aggressive = pyamg.strength.classical_strength_of_connection(A, theta=0.5)# Use custom strength in solver construction
def custom_strength(A):
return pyamg.strength.evolution_strength_of_connection(A, epsilon=6.0)
ml = pyamg.ruge_stuben_solver(A, strength=custom_strength)
# Or pass strength parameters directly
ml = pyamg.smoothed_aggregation_solver(A, strength=('evolution', {'epsilon': 4.0}))# Analyze strength connectivity
A = pyamg.gallery.poisson((30, 30))
S = pyamg.strength.classical_strength_of_connection(A, theta=0.25)
# Connection statistics
print(f"Matrix nnz: {A.nnz}")
print(f"Strong connections: {S.nnz}")
print(f"Strength ratio: {S.nnz / A.nnz:.2f}")
# Visualize strength pattern (for small problems)
import matplotlib.pyplot as plt
plt.spy(S, markersize=1)
plt.title("Strength of Connection Pattern")
plt.show()Install with Tessl CLI
npx tessl i tessl/pypi-pyamg