Coverage for ase / _4 / symopt / test_structures.py: 100.00%

47 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-05-21 15:52 +0000

1import numpy as np 

2import pytest 

3 

4from ase.build import bulk 

5from ase.calculators.emt import EMT 

6from ase.data import chemical_symbols 

7 

8pytestmark = pytest.mark.calculator_lite 

9 

10 

11def generate_all_bulk_structures(): 

12 cases = [] 

13 

14 for Z in range(1, len(chemical_symbols)): 

15 symbol = chemical_symbols[Z] 

16 if symbol in {'Np', 'U', 'Sb', 'As', 'Bi'}: 

17 continue 

18 try: 

19 atoms = bulk(symbol) 

20 from ase.build import niggli_reduce 

21 

22 niggli_reduce(atoms) 

23 print(atoms.cell.angles()) 

24 except Exception: 

25 continue # lattice not valid for this element 

26 cases.append((symbol, atoms)) 

27 return cases 

28 

29 

30@pytest.fixture(scope='session', params=generate_all_bulk_structures()) 

31def system(request): 

32 symbol, atoms = request.param 

33 atoms = atoms.copy() 

34 atoms.set_chemical_symbols(['Au'] * len(atoms)) 

35 return symbol, atoms 

36 

37 

38def test_symmetry_constrained_relaxation_emt(system): 

39 symbol, atoms_ref = system 

40 atoms_ref = atoms_ref.copy() 

41 atoms = atoms_ref.copy() 

42 

43 # Symmetry adapted relaxation 

44 from ase._4.symopt.relax import Relax 

45 from ase.optimize.bfgs import BFGS 

46 from ase.parallel import world 

47 

48 relax = Relax( 

49 atoms=atoms, 

50 calc=EMT, 

51 optimizer_factory=lambda atoms: BFGS(atoms, alpha=100.0), 

52 symprec=0.01, 

53 comm=world, 

54 ) 

55 relax.run(fmax=0.0001, smax=0.00001) 

56 

57 print('Relax complete', atoms.get_stress()) 

58 from ase.filters import FrechetCellFilter 

59 from ase.optimize.cellawarebfgs import CellAwareBFGS 

60 

61 atoms_ref.calc = EMT() 

62 relax = CellAwareBFGS(FrechetCellFilter(atoms_ref, exp_cell_factor=1.0)) 

63 relax.run(fmax=0.0001, smax=0.00001) 

64 print('Ref relax complete', atoms_ref.get_stress()) 

65 

66 print(atoms.cell.lengths(), atoms_ref.cell.lengths()) 

67 print(atoms.cell.angles(), atoms_ref.cell.angles()) 

68 

69 assert np.allclose( 

70 atoms.cell.lengths(), atoms_ref.cell.lengths(), atol=0.01 

71 ) 

72 assert np.allclose(atoms.cell.angles(), atoms_ref.cell.angles(), atol=0.01)