1# Check that atoms object mismatches are detected properly across CPUs.
2
3import pytest
4from ase.build import molecule
5from gpaw.mpi import world, synchronize_atoms
6from gpaw import GPAW
7from ase.optimize import BFGS
8
9
10@pytest.mark.ci
11def test_atoms_mismatch():
12    system = molecule('H2O')
13    synchronize_atoms(system, world)
14
15    if world.rank == 1:
16        system.positions[1, 1] += 1e-8  # fail (above tolerance)
17    if world.rank == 2:
18        system.cell[0, 0] += 1e-7  # fail (above tolerance)
19    if world.rank == 3:
20        system.positions[1, 1] += 1e-10  # pass (below tolerance)
21    if world.rank == 4:
22        system.cell[0, 1] += 1e-10  # pass (below tolerance)
23
24    expected_err_ranks = {1: [], 2: [1]}.get(world.size, [1, 2])
25
26    try:
27        synchronize_atoms(system, world, tolerance=1e-9)
28    except ValueError as e:
29        assert (expected_err_ranks == e.args[1]).all()
30    else:
31        assert world.size == 1
32
33    # Check that GPAW can handle small numerical differences within ASE
34    if world.size == 1:
35        # Test makes sense only in parallel
36        return
37
38    def mess_up_atoms(atoms):
39        if world.rank == 1:
40            atoms.positions[1, 1] += 1e-13
41
42    system = molecule('H2O')
43    system.center(3.0)
44    calc = GPAW(h=0.2,
45                convergence={'energy': 0.01, 'density': 1.0e-2,
46                             'eigenstates': 4.0e-3})
47    system.calc = calc
48    dyn = BFGS(system)
49    dyn.attach(mess_up_atoms, 1, system)
50    dyn.run(steps=2)
51