Coverage for gpaw/test/test_diagonalizer_backend.py: 96%
51 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-08 00:17 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-08 00:17 +0000
1import numpy as np
2import pytest
3from ase.parallel import world
4from gpaw.utilities import compiled_with_sl
5from gpaw.utilities.elpa import LibElpa
6from gpaw.eigensolvers.diagonalizerbackend import (
7 DistributedBlacsDiagonalizer,
8 ScipyDiagonalizer,
9 ScalapackDiagonalizer,
10 ElpaDiagonalizer)
13def prepare_eigensolver_matrices(size_of_matrices, dtype):
15 matrix_dimensions = [size_of_matrices, size_of_matrices]
16 rng = np.random.Generator(np.random.PCG64(24589246))
17 A = rng.random(matrix_dimensions).astype(dtype)
18 B = rng.random(matrix_dimensions).astype(dtype)
20 if dtype == complex:
21 A += 1j * rng.random(matrix_dimensions)
22 B += 1j * rng.random(matrix_dimensions)
23 A = A + A.T.conj()
24 B = B + B.T.conj()
25 # Make sure B is positive definite
26 B += np.eye(size_of_matrices) * size_of_matrices
28 return A, B
31@pytest.fixture(params=['eigh', 'scalapack', 'elpa'])
32def backend_problemsize_kwargs(request):
33 name = request.param
34 eigenproblem_size = world.size * 64
35 if name == 'eigh':
36 return ScipyDiagonalizer, eigenproblem_size, {'comm': world}
37 elif name == 'scalapack' or name == 'elpa':
38 if not compiled_with_sl():
39 pytest.skip()
41 nrows = 2 if world.size > 1 else 1
42 ncols = world.size // 2 if nrows > 1 else 1
44 scalapack_kwargs = {
45 'arraysize': eigenproblem_size,
46 'grid_nrows': nrows,
47 'grid_ncols': ncols,
48 'scalapack_communicator': world,
49 'blocksize': 32 if world.size == 1 else 64}
51 if name == 'scalapack':
52 return ScalapackDiagonalizer, eigenproblem_size, scalapack_kwargs
54 if name == 'elpa':
55 if not LibElpa.have_elpa():
56 pytest.skip()
57 return ElpaDiagonalizer, eigenproblem_size, scalapack_kwargs
60@pytest.mark.parametrize('dtype,', [float, complex])
61def test_diagonalizer_eigenproblem_correctness(backend_problemsize_kwargs,
62 dtype):
63 is_master_rank = world.rank == 0
64 (
65 diagonalizer_class,
66 eigenproblem_size,
67 diagonalizer_kwargs) = backend_problemsize_kwargs
69 if diagonalizer_class is ScipyDiagonalizer:
70 diagonalizer = diagonalizer_class(**diagonalizer_kwargs)
71 elif issubclass(diagonalizer_class, DistributedBlacsDiagonalizer):
72 diagonalizer = diagonalizer_class(**diagonalizer_kwargs, dtype=dtype)
74 a, b = prepare_eigensolver_matrices(eigenproblem_size, dtype=dtype)
75 eps = np.zeros(eigenproblem_size)
76 a_copy = a.copy()
77 b_copy = b.copy()
79 # a_copy contains eigenvectors after this.
80 diagonalizer.diagonalize(
81 a_copy,
82 b_copy,
83 eps,
84 debug=False)
86 if is_master_rank:
87 assert np.allclose(a @ a_copy, b @ a_copy @ np.diag(eps))