or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aggregation-methods.mdgallery.mdhigh-level-interface.mdindex.mdkrylov-methods.mdmultilevel-solver.mdrelaxation-methods.mdsolver-constructors.mdstrength-of-connection.mdutilities.md

utilities.mddocs/

0

# Utilities and Linear Algebra

1

2

Helper functions for matrix operations, norms, and linear algebra utilities supporting AMG algorithms. These functions provide essential computational building blocks for PyAMG.

3

4

## Capabilities

5

6

### Linear System Utilities

7

8

Functions for creating and manipulating linear systems.

9

10

```python { .api }

11

def make_system(A, b, x0=None, formats=None):

12

"""

13

Create consistent linear system with proper formats.

14

15

Ensures that matrix and vectors are in compatible formats

16

and have consistent dimensions for PyAMG solvers.

17

18

Parameters:

19

- A: array-like or sparse matrix, coefficient matrix

20

- b: array-like, right-hand side vector

21

- x0: array-like, initial guess (optional)

22

- formats: dict, desired matrix formats:

23

* {'A': 'csr', 'b': 'array'}: format specifications

24

* None: use default formats (CSR for A, array for vectors)

25

26

Returns:

27

tuple: (A, b, x0) in consistent, compatible formats

28

- A: sparse matrix in specified format (default CSR)

29

- b: numpy array, right-hand side

30

- x0: numpy array, initial guess (zero if not provided)

31

32

Raises:

33

ValueError: if dimensions are incompatible

34

TypeError: if formats cannot be converted

35

"""

36

37

def upcast(*args):

38

"""

39

Type upcasting for numerical arrays.

40

41

Determines common floating point type for multiple arrays,

42

ensuring numerical computations use adequate precision.

43

44

Parameters:

45

- *args: array-like objects to upcast

46

47

Returns:

48

numpy.dtype: common floating point type (float32, float64,

49

complex64, or complex128)

50

51

Notes:

52

- Promotes to higher precision when mixed types present

53

- Handles real/complex promotion appropriately

54

- Used internally by PyAMG for type consistency

55

"""

56

```

57

58

**Usage Examples:**

59

60

```python

61

import pyamg

62

import numpy as np

63

from scipy import sparse

64

65

# Create consistent linear system

66

A_dense = np.array([[2, -1, 0], [-1, 2, -1], [0, -1, 2]])

67

b_list = [1, 0, 1]

68

A, b, x0 = pyamg.util.make_system(A_dense, b_list)

69

print(f"A type: {type(A)}, b type: {type(b)}")

70

71

# Specify formats

72

A, b, x0 = pyamg.util.make_system(A_dense, b_list,

73

formats={'A': 'csc', 'b': 'array'})

74

75

# Type upcasting

76

x_float32 = np.array([1.0, 2.0], dtype=np.float32)

77

x_float64 = np.array([3.0, 4.0], dtype=np.float64)

78

common_type = pyamg.util.upcast(x_float32, x_float64)

79

print(f"Common type: {common_type}")

80

```

81

82

### Vector and Matrix Norms

83

84

Comprehensive norm computations for vectors and matrices.

85

86

```python { .api }

87

def norm(x, ord=None):

88

"""

89

Compute vector or matrix norm.

90

91

Unified interface for computing various norms of vectors

92

and matrices, with automatic handling of sparse matrices.

93

94

Parameters:

95

- x: array-like or sparse matrix, input object

96

- ord: norm type:

97

* None: 2-norm for vectors, Frobenius norm for matrices

98

* 'fro': Frobenius norm (matrices)

99

* 1, 2, np.inf: vector p-norms

100

* -1, -2, -np.inf: negative vector p-norms

101

* 'nuc': nuclear norm (matrices)

102

103

Returns:

104

float: computed norm value

105

106

Notes:

107

- Handles both dense and sparse matrices efficiently

108

- Sparse matrices use optimized algorithms

109

- Compatible with NumPy norm interface

110

"""

111

112

def infinity_norm(x):

113

"""

114

Compute infinity norm (maximum absolute value).

115

116

Specialized function for infinity norm computation,

117

optimized for both dense and sparse arrays.

118

119

Parameters:

120

- x: array-like or sparse matrix

121

122

Returns:

123

float: infinity norm ||x||_∞ = max|x_i|

124

"""

125

```

126

127

**Usage Examples:**

128

129

```python

130

# Vector norms

131

x = np.array([3, 4, 0])

132

norm_2 = pyamg.util.norm(x) # 2-norm

133

norm_1 = pyamg.util.norm(x, ord=1) # 1-norm

134

norm_inf = pyamg.util.infinity_norm(x) # infinity norm

135

print(f"2-norm: {norm_2}, 1-norm: {norm_1}, inf-norm: {norm_inf}")

136

137

# Matrix norms

138

A = pyamg.gallery.poisson((20, 20))

139

frobenius_norm = pyamg.util.norm(A, ord='fro')

140

print(f"Frobenius norm: {frobenius_norm}")

141

```

142

143

### Spectral Analysis

144

145

Functions for eigenvalue estimation and spectral properties.

146

147

```python { .api }

148

def approximate_spectral_radius(A, tol=0.1, maxiter=10):

149

"""

150

Estimate spectral radius of matrix.

151

152

Uses power iteration to estimate the largest eigenvalue

153

magnitude (spectral radius) without computing all eigenvalues.

154

155

Parameters:

156

- A: sparse matrix, input matrix

157

- tol: float, tolerance for power iteration convergence

158

- maxiter: int, maximum power iterations

159

160

Returns:

161

float: estimated spectral radius ρ(A) ≈ |λ_max|

162

163

Notes:

164

- Much faster than full eigenvalue computation

165

- Accuracy depends on eigenvalue separation

166

- Used internally for relaxation parameter optimization

167

"""

168

169

def condest(A, t=2):

170

"""

171

Estimate condition number of matrix.

172

173

Computes 1-norm condition number estimate using

174

block 1-norm estimation algorithm.

175

176

Parameters:

177

- A: sparse matrix, input matrix (should be square)

178

- t: int, number of columns in estimation (higher = more accurate)

179

180

Returns:

181

float: estimated condition number κ₁(A) = ||A||₁ ||A⁻¹||₁

182

183

Notes:

184

- Much cheaper than computing exact condition number

185

- Provides reasonable estimate for most matrices

186

- Used for solver diagnostics and parameter selection

187

"""

188

189

def cond(A, p=None):

190

"""

191

Compute exact condition number.

192

193

Computes condition number using matrix factorization

194

or singular value decomposition.

195

196

Parameters:

197

- A: array-like, input matrix

198

- p: norm type (1, 2, 'fro', np.inf)

199

200

Returns:

201

float: exact condition number

202

203

Notes:

204

- Expensive for large matrices

205

- Provides exact result unlike condest

206

- Use condest for large sparse matrices

207

"""

208

```

209

210

**Usage Examples:**

211

212

```python

213

# Spectral radius estimation

214

A = pyamg.gallery.poisson((50, 50))

215

rho = pyamg.util.approximate_spectral_radius(A)

216

print(f"Spectral radius: {rho:.3f}")

217

218

# Condition number estimation

219

kappa_est = pyamg.util.condest(A)

220

print(f"Estimated condition number: {kappa_est:.2e}")

221

222

# Use for relaxation parameter selection

223

omega_optimal = 2.0 / (1.0 + rho) # Optimal Jacobi parameter

224

print(f"Optimal Jacobi omega: {omega_optimal:.3f}")

225

```

226

227

### Basic Linear Algebra Operations

228

229

Fundamental linear algebra operations optimized for sparse matrices.

230

231

```python { .api }

232

def axpy(a, x, y):

233

"""

234

AXPY operation: y = a*x + y.

235

236

Efficient implementation of scaled vector addition,

237

fundamental building block for iterative methods.

238

239

Parameters:

240

- a: scalar, scaling factor

241

- x: array-like, input vector

242

- y: array-like, accumulation vector (modified in-place)

243

244

Returns:

245

None (y is modified in-place)

246

247

Notes:

248

- Optimized for cache efficiency

249

- Used extensively in Krylov methods

250

- Handles both real and complex arithmetic

251

"""

252

253

def ishermitian(A, tol=1e-8):

254

"""

255

Check if matrix is Hermitian (or symmetric for real matrices).

256

257

Tests whether A = A^H within specified tolerance,

258

important for selecting appropriate algorithms.

259

260

Parameters:

261

- A: sparse or dense matrix

262

- tol: float, tolerance for symmetry test

263

264

Returns:

265

bool: True if matrix is Hermitian/symmetric

266

267

Notes:

268

- Returns True for symmetric real matrices

269

- Handles complex matrices (Hermitian test)

270

- Uses efficient sparse matrix operations

271

"""

272

273

def pinv_array(A, tol=None):

274

"""

275

Pseudoinverse of dense arrays.

276

277

Computes Moore-Penrose pseudoinverse using SVD,

278

handling singular and rectangular matrices.

279

280

Parameters:

281

- A: array-like, input matrix (can be rectangular)

282

- tol: float, tolerance for rank determination (optional)

283

284

Returns:

285

array: pseudoinverse A⁺ such that AA⁺A = A

286

287

Notes:

288

- Handles rank-deficient matrices robustly

289

- Used for coarse grid solvers in AMG

290

- More expensive than direct solvers for nonsingular matrices

291

"""

292

```

293

294

**Usage Examples:**

295

296

```python

297

# AXPY operation

298

x = np.array([1.0, 2.0, 3.0])

299

y = np.array([4.0, 5.0, 6.0])

300

pyamg.util.axpy(2.0, x, y) # y = 2*x + y

301

print(f"Result: {y}") # [6, 9, 12]

302

303

# Symmetry test

304

A_sym = pyamg.gallery.poisson((30, 30))

305

A_nonsym = A_sym + 0.1 * sparse.triu(A_sym, k=1)

306

print(f"Poisson symmetric: {pyamg.util.ishermitian(A_sym)}")

307

print(f"Modified symmetric: {pyamg.util.ishermitian(A_nonsym)}")

308

309

# Pseudoinverse for singular matrix

310

A_sing = np.array([[1, 1], [1, 1]]) # Rank 1 matrix

311

A_pinv = pyamg.util.pinv_array(A_sing)

312

print(f"Pseudoinverse: \n{A_pinv}")

313

```

314

315

### Matrix Manipulation Utilities

316

317

Functions for matrix format conversion and manipulation.

318

319

```python { .api }

320

def get_blocksize(A):

321

"""

322

Determine block size of block-structured matrix.

323

324

Analyzes matrix structure to detect consistent block pattern,

325

important for block-based AMG methods.

326

327

Parameters:

328

- A: sparse matrix, input matrix to analyze

329

330

Returns:

331

int: detected block size (1 if no block structure found)

332

333

Notes:

334

- Heuristic detection based on nonzero pattern

335

- Used automatically by block smoothers

336

- Returns 1 for general unstructured matrices

337

"""

338

339

def scale_rows(A, x):

340

"""

341

Scale matrix rows by vector elements.

342

343

Multiplies each row i of matrix A by scalar x[i],

344

creating row-scaled matrix.

345

346

Parameters:

347

- A: sparse matrix, input matrix

348

- x: array-like, row scaling factors

349

350

Returns:

351

sparse matrix: row-scaled matrix where row i is multiplied by x[i]

352

"""

353

354

def scale_columns(A, x):

355

"""

356

Scale matrix columns by vector elements.

357

358

Multiplies each column j of matrix A by scalar x[j],

359

creating column-scaled matrix.

360

361

Parameters:

362

- A: sparse matrix, input matrix

363

- x: array-like, column scaling factors

364

365

Returns:

366

sparse matrix: column-scaled matrix where column j is multiplied by x[j]

367

"""

368

369

def symmetric_rescaling(A, x):

370

"""

371

Apply symmetric scaling to matrix.

372

373

Computes X^{-1} A X where X = diag(x), preserving

374

eigenvalue structure while improving conditioning.

375

376

Parameters:

377

- A: sparse matrix, input matrix (preferably symmetric)

378

- x: array-like, scaling factors

379

380

Returns:

381

sparse matrix: symmetrically scaled matrix

382

383

Notes:

384

- Preserves symmetry and definiteness

385

- Can improve condition number

386

- Used in preconditioning strategies

387

"""

388

```

389

390

**Usage Examples:**

391

392

```python

393

# Block size detection

394

A_block = pyamg.gallery.linear_elasticity((20, 20))

395

blocksize = pyamg.util.get_blocksize(A_block)

396

print(f"Detected block size: {blocksize}")

397

398

# Matrix scaling

399

A = pyamg.gallery.poisson((10, 10))

400

row_scales = np.random.uniform(0.5, 2.0, A.shape[0])

401

A_row_scaled = pyamg.util.scale_rows(A, row_scales)

402

403

# Symmetric scaling for preconditioning

404

diag_A = np.array(A.diagonal())

405

sqrt_diag = np.sqrt(np.abs(diag_A))

406

A_scaled = pyamg.util.symmetric_rescaling(A, sqrt_diag)

407

```

408

409

### Diagnostic and Analysis Tools

410

411

Functions for solver performance analysis and debugging.

412

413

```python { .api }

414

def profile_solver(ml, b, cycles=10):

415

"""

416

Profile solver performance characteristics.

417

418

Analyzes solver performance including timing, convergence,

419

and memory usage for given problem size.

420

421

Parameters:

422

- ml: MultilevelSolver, AMG solver to profile

423

- b: array, right-hand side vector for testing

424

- cycles: int, number of test cycles

425

426

Returns:

427

dict: performance profile including:

428

* 'setup_time': solver construction time

429

* 'solve_time': average solve time per cycle

430

* 'convergence_factor': average convergence factor

431

* 'memory_usage': estimated memory usage

432

"""

433

434

def print_table(data, headers=None, title=None):

435

"""

436

Print formatted table of data.

437

438

Creates nicely formatted ASCII table for displaying

439

solver statistics, convergence history, etc.

440

441

Parameters:

442

- data: list of lists, table data (rows × columns)

443

- headers: list, column headers (optional)

444

- title: str, table title (optional)

445

446

Returns:

447

None (prints formatted table)

448

"""

449

450

def asfptype(x):

451

"""

452

Convert to floating point type.

453

454

Ensures input is appropriate floating point type

455

for numerical computations, with proper precision.

456

457

Parameters:

458

- x: array-like, input to convert

459

460

Returns:

461

array: converted to appropriate floating point type

462

463

Notes:

464

- Promotes integers to float64

465

- Preserves existing floating point types

466

- Handles complex types appropriately

467

"""

468

```

469

470

**Usage Examples:**

471

472

```python

473

# Solver profiling

474

A = pyamg.gallery.poisson((100, 100))

475

ml = pyamg.smoothed_aggregation_solver(A)

476

b = np.random.rand(A.shape[0])

477

478

profile = pyamg.util.profile_solver(ml, b, cycles=5)

479

for key, value in profile.items():

480

print(f"{key}: {value}")

481

482

# Formatted output table

483

convergence_data = [

484

[1, 1.0e-1, 0.15],

485

[2, 1.5e-3, 0.20],

486

[3, 2.3e-5, 0.18]

487

]

488

headers = ['Iteration', 'Residual', 'Rate']

489

pyamg.util.print_table(convergence_data, headers=headers,

490

title='Convergence History')

491

```

492

493

## Usage Guidelines

494

495

### Performance Optimization

496

497

- Use `make_system()` to ensure optimal matrix formats

498

- Check matrix properties with `ishermitian()` before solver selection

499

- Profile solvers with `profile_solver()` for performance analysis

500

- Use `condest()` rather than exact condition numbers for large matrices

501

502

### Numerical Stability

503

504

- Apply `symmetric_rescaling()` for poorly conditioned symmetric problems

505

- Use `upcast()` to ensure adequate precision in mixed-type computations

506

- Monitor spectral radius with `approximate_spectral_radius()` for parameter tuning

507

508

### Common Patterns

509

510

```python

511

# Standard solver setup with utilities

512

def setup_solver(A_input, b_input):

513

# Ensure consistent formats

514

A, b, x0 = pyamg.util.make_system(A_input, b_input)

515

516

# Check matrix properties

517

is_symmetric = pyamg.util.ishermitian(A)

518

condition_est = pyamg.util.condest(A)

519

520

# Select solver based on properties

521

if is_symmetric and condition_est < 1e12:

522

ml = pyamg.smoothed_aggregation_solver(A)

523

else:

524

ml = pyamg.ruge_stuben_solver(A)

525

526

return ml, b, x0

527

528

# Example usage

529

A = pyamg.gallery.linear_elasticity((30, 30))

530

b = np.random.rand(A.shape[0])

531

ml, b_formatted, x0 = setup_solver(A, b)

532

x = ml.solve(b_formatted, x0=x0)

533

```