Example #1
0
 def test___eq__(self):
     atom1 = Atom("N", [0.0, 0.0, 0.0])
     atom2 = Atom("N", [0.0, 0.0, 1.1])
     pos1 = Posinp([atom1, atom2], "angstroem", "free")
     pos2 = Posinp([atom2, atom1], "angstroem", "free")
     assert pos1 == pos2  # The order of the atoms in the list do not count
     assert pos1 != 1  # No error if other object is not a posinp
Example #2
0
 def test_to_barycenter(self):
     atoms = [Atom("N", [0, 0, 0]), Atom("N", [0, 0, 1.1])]
     pos = Posinp(atoms, units="angstroem", boundary_conditions="free")
     expected_atoms = [Atom("N", [0, 0, -0.55]), Atom("N", [0, 0, 0.55])]
     expected_pos = Posinp(
         expected_atoms, units="angstroem", boundary_conditions="free"
     )
     assert pos.to_barycenter() == expected_pos
Example #3
0
 def test_positions(self):
     expected = [7.327412521, 0.0, 3.461304757]
     pos1 = Posinp(
         [Atom("C", expected)], units="angstroem", boundary_conditions="free"
     )
     pos2 = pos1.translate_atom(0, [-7.327412521, 0.0, -3.461304757])
     assert np.allclose(pos1.positions, expected)
     assert np.allclose(pos2.positions, [0, 0, 0])
 def test_convert(self):
     pos_angstrom = Posinp.from_file(
         os.path.join(pos_folder, "H2O_unrelaxed.xyz"))
     pos_atomic = Posinp.from_file(
         os.path.join(pos_folder, "H2O_atomic.xyz"))
     job1 = Job(posinp=pos_angstrom, calculator=self.calc3)
     job2 = Job(posinp=pos_atomic, calculator=self.calc3)
     job1.run("energy")
     job2.run("energy")
     assert job1.results["energy"] == job2.results["energy"]
Example #5
0
 def test_with_surface_boundary_conditions(self):
     # Two Posinp instances with surface BC are the same even if they
     # have a different cell size along y-axis
     pos_with_inf = Posinp(
         [
             Atom(
                 "N",
                 [2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779],
             ),
             Atom(
                 "N",
                 [-1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154],
             ),
         ],
         "angstroem",
         "surface",
         cell=[40, ".inf", 40],
     )
     with pytest.raises(ValueError):
         pos_wo_inf = Posinp(
             [
                 Atom(
                     "N",
                     [2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779],
                 ),
                 Atom(
                     "N",
                     [-1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154],
                 ),
             ],
             "angstroem",
             "surface",
             cell=[40, 40, 40],
         )
     # They are obviously different if the cell size along the other
     # directions are not the same
     pos2_with_inf = Posinp(
         [
             Atom(
                 "N",
                 [2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779],
             ),
             Atom(
                 "N",
                 [-1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154],
             ),
         ],
         "angstroem",
         "surface",
         cell=[20, "inf", 40],
     )
     assert pos_with_inf != pos2_with_inf
     # They still have the same BC
     assert pos2_with_inf.boundary_conditions == pos_with_inf.boundary_conditions
Example #6
0
class TestEnsemble:

    pos1 = Posinp.from_file(os.path.join(pos_folder, "H2O_unrelaxed.xyz"))
    model1 = os.path.join(model_folder, "H2O_forces_model")
    model2 = os.path.join(model_folder, "H2O_model")

    def test_both_models(self):
        ens = EnsembleCalculator(modelpaths=[self.model1, self.model2])
        job1 = Job(posinp=self.pos1, calculator=ens)
        job1.run("energy")
        assert job1.results["energy"] == np.array(-1277.0513)
        assert job1.results["energy_std"] == np.array(799.70636)

        ref_forces = np.array(
            [
                [0, 0.7647542, -7.8656354],
                [0, -2.2895808, 3.8240397],
                [0, 1.5248268, 4.0415955],
            ],
            dtype=np.float32,
        )
        ref_std = np.array(
            [
                [0, 0.03656149, 1.2570109],
                [0, 0.8168775, 0.4650414],
                [0, 0.8534391, 0.7919693],
            ],
            dtype=np.float32,
        )
        job2 = Job(posinp=self.pos1, calculator=ens)
        job2.run("forces")
        assert np.isclose(job2.results["forces"], ref_forces, atol=1e-04).all()
        assert np.isclose(job2.results["forces_std"], ref_std,
                          atol=1e-04).all()
Example #7
0
def main(args):
    function = get_function(args.function)
    distances = np.linspace(args.range[0], args.range[1], args.ndata)
    with connect(args.dbname) as db:
        for d in distances:
            pos_dict = {
                "units":
                "angstroem",
                "boundary_conditions":
                "free",
                "positions": [
                    {
                        args.element: [0, 0, 0]
                    },
                    {
                        args.element: [d, 0, 0]
                    },
                ],
            }
            posinp = Posinp.from_dict(pos_dict)
            atoms = posinp_to_ase_atoms(posinp)
            energy = function.value(d)
            forces = np.array([
                [-1.0 * function.first_derivative(-d), 0, 0],
                [-1.0 * function.first_derivative(d), 0, 0],
            ])
            db.write(atoms, data={"energy": energy, "forces": forces})
Example #8
0
 def test_convert(self):
     pos1 = self.periodic_pos.positions
     assert self.periodic_pos.units == "angstroem"
     self.periodic_pos.convert_units("atomic")
     assert np.isclose(
         self.periodic_pos.positions,
         np.array(
             [
                 [0.15747717, 0.94486299, 0.4724315],
                 [0.78738583, 0.94486299, 0.4724315],
                 [1.10234016, 0.94486299, 1.41729449],
                 [1.73224882, 0.94486299, 1.41729449],
             ]
         ),
     ).all()
     assert self.periodic_pos.units == "atomic"
     self.periodic_pos.convert_units("angstroem")
     assert np.isclose(self.periodic_pos.positions, pos1).all()
     assert self.periodic_pos.units == "angstroem"
     self.periodic_pos.convert_units("angstroem")
     assert np.isclose(self.periodic_pos.positions, pos1).all()
     red = Posinp.from_file(tests_fol + "reduced.xyz")
     red.convert_units("angstroem")
     print(red.positions)
     assert np.isclose(
         red.positions,
         np.array(
             [
                 [0.4233418, 1.32294312, 0.95251905],
                 [3.81007619, 0.26458862, 0.47625952],
             ]
         ),
     ).all()
Example #9
0
 def test_repr(self):
     atoms = [Atom("C", [0, 0, 0]), Atom("N", [0, 0, 1])]
     new_pos = Posinp(atoms, units="angstroem", boundary_conditions="free")
     msg = (
         "Posinp([Atom('C', [0.0, 0.0, 0.0]), Atom('N', [0.0, 0.0, "
         "1.0])], 'angstroem', 'free', cell=Cell([0.0, 0.0, 0.0]), angles=[90. 90. 90.])"
     )
     assert repr(new_pos) == msg
class TestSchnetPack:

    pos1 = Posinp.from_file(os.path.join(pos_folder, "N2.xyz"))
    model1 = os.path.join(model_folder, "ani1_N2_model")
    model2 = os.path.join(model_folder, "wacsf_model")
    model3 = os.path.join(model_folder, "H2O_model")
    calc1 = SchnetPackCalculator(model_dir=model1)
    calc2 = SchnetPackCalculator(model_dir=model2)
    calc3 = SchnetPackCalculator(model_dir=model3)
    job = Job(posinp=pos1, calculator=calc1)
    jobwacsf = Job(posinp=pos1, calculator=calc2)

    def test_only_energy(self):
        self.job.run("energy")
        assert np.array(-2979.6067) == self.job.results["energy"][0]
        new_job = deepcopy(self.job)
        new_job.calculator.units = {"energy": "hartree", "positions": "atomic"}
        new_job.run("energy")
        assert new_job.results["energy"][0] == np.array(-81079.228)
        self.job.results["energy"] = None

    def test_forces_from_deriv(self):
        assert self.job.calculator.available_properties == ["energy"]
        self.job.run("forces")
        ref_forces = np.array([[-0.0, -0.0, -0.31532133],
                               [-0.0, -0.0, 0.31532133]])
        assert np.isclose(self.job.results["forces"][0], ref_forces).all()
        new_job = deepcopy(self.job)
        new_job.calculator.units = {"energy": "hartree", "positions": "atomic"}
        new_job.run("forces")
        assert np.isclose(ref_forces * 51.42206334724,
                          new_job.results["forces"][0]).all()

    def test_forces_from_finite_difference(self):
        assert self.job.calculator.available_properties == ["energy"]
        self.job.run("forces", finite_difference=True)
        ref_forces = np.array([[-0.0, -0.0, -0.32416448],
                               [-0.0, -0.0, 0.32416448]])
        assert np.isclose(self.job.results["forces"][0], ref_forces).all()

    def test_wacsf(self):
        self.jobwacsf.run("energy")
        assert self.jobwacsf.results["energy"] is not None

    def test_bad_property(self):
        with pytest.raises(ValueError):
            self.job.run("dipole")

    def test_convert(self):
        pos_angstrom = Posinp.from_file(
            os.path.join(pos_folder, "H2O_unrelaxed.xyz"))
        pos_atomic = Posinp.from_file(
            os.path.join(pos_folder, "H2O_atomic.xyz"))
        job1 = Job(posinp=pos_angstrom, calculator=self.calc3)
        job2 = Job(posinp=pos_atomic, calculator=self.calc3)
        job1.run("energy")
        job2.run("energy")
        assert job1.results["energy"] == job2.results["energy"]
Example #11
0
class TestGeopt:

    posN2 = Posinp.from_file(os.path.join(pos_folder, "N2_unrelaxed.xyz"))
    posH2O = Posinp.from_file(os.path.join(pos_folder, "H2O_unrelaxed.xyz"))
    calcN2 = SchnetPackCalculator(os.path.join(model_folder, "ani1_N2_model"))
    calcH2O = SchnetPackCalculator(os.path.join(model_folder, "H2O_model"))

    def test_N2(self, capsys):
        init = Job(posinp=self.posN2, calculator=self.calcN2)
        init.run("energy")
        assert init.results["energy"][0] == -2978.2354
        geo = Geopt(posinp=self.posN2, calculator=self.calcN2)
        geo.run(recenter=True, verbose=2)
        output = capsys.readouterr()
        assert 1.101 < geo.final_posinp.distance(0, 1) < 1.103
        assert np.isclose(
            geo.final_posinp.positions[0, 2],
            -geo.final_posinp.positions[1, 2],
            atol=1e-6,
        )
        assert output.out is not None
        final = Job(posinp=geo.final_posinp, calculator=self.calcN2)
        final.run("energy")
        assert final.results["energy"][0] == -2979.6070

    def test_H2O(self):
        init = Job(posinp=self.posH2O, calculator=self.calcH2O)
        init.run("energy")
        assert np.isclose(init.results["energy"][0], -2076.7576, atol=1e-4)
        geo = Geopt(posinp=self.posH2O, calculator=self.calcH2O)
        geo.run()
        assert 0.964 < geo.final_posinp.distance(0, 1) < 0.965
        assert (geo.final_posinp.distance(0, 1) -
                geo.final_posinp.distance(0, 2)) < 0.0001
        # TODO Check the angle
        final = Job(posinp=geo.final_posinp, calculator=self.calcH2O)
        final.run("energy")
        assert np.isclose(final.results["energy"][0], -2078.6301, atol=1e-4)

    def test_errors(self):
        with pytest.raises(ValueError):
            geo = Geopt(posinp=None, calculator=self.calcN2)

        with pytest.raises(TypeError):
            geo = Geopt(posinp=self.posN2, calculator=1)
Example #12
0
class TestJob:

    file1, file2, file3 = (
        os.path.join(pos_folder, "free.xyz"),
        os.path.join(pos_folder, "surface.xyz"),
        os.path.join(pos_folder, "N2.xyz"),
    )
    pos1, pos2, pos3 = (
        Posinp.from_file(file1),
        Posinp.from_file(file2),
        Posinp.from_file(file3),
    )
    dummy = Calculator(available_properties="",
                       units={
                           "positions": "atomic",
                           "energy": "eV"
                       })
    badCalc = dict()
    job = Job(name="test", posinp=[pos1, pos2, pos3], calculator=dummy)

    def test_raises_no_positions(self):
        with pytest.raises(ValueError):
            j = Job(calculator=self.dummy)

    def test_raises_posinp_types(self):
        with pytest.raises(TypeError):
            j = Job(posinp=[self.pos1, 1], calculator=self.dummy)

    def test_raises_bad_calc(self):
        with pytest.raises(TypeError):
            j = Job(posinp=[self.pos1], calculator=self.badCalc)

    def test_posinp_types(self):
        job1 = Job(posinp=self.pos1, calculator=self.dummy)
        job2 = Job(posinp=[self.pos1], calculator=self.dummy)
        assert job1.posinp == job2.posinp

    @pytest.mark.parametrize(
        "value, expected",
        [(job.name, "test"), (job.num_struct, 3), (job.posinp[1], pos2)],
    )
    def test_values(self, value, expected):
        assert value == expected
Example #13
0
class TestGrapheneAngles:

    graphene2_name = os.path.join(pos_folder, "gra2.xyz")
    pos_2at = Posinp.from_file(graphene2_name)

    graphene4_name = os.path.join(pos_folder, "gra4_red.xyz")
    pos_4at_red = Posinp.from_file(graphene4_name)

    calc = SchnetPackCalculator(os.path.join(model_folder, "H2O_model"))

    def test_same_result(self):
        j1 = Job(posinp=self.pos_2at, calculator=self.calc)
        j1.run("energy")
        e1 = j1.results["energy"]

        j2 = Job(posinp=self.pos_4at_red, calculator=self.calc)
        j2.run("energy")
        e2 = j2.results["energy"]

        pos_4at = deepcopy(self.pos_4at_red)
        pos_4at.convert_units("angstroem")
        j3 = Job(posinp=pos_4at, calculator=self.calc)
        j3.run("energy")
        e3 = j3.results["energy"]

        assert e2 == e3
        assert np.isclose(e2, 2 * e1, atol=0.0002)

    def test_cell_with_angles(self):
        assert np.isclose(
            self.pos_2at.cell.array,
            np.array([[2.46, 0.0, 0.0], [0.0, 0.0, 0.0],
                      [1.23, 0.0, 2.13042249]]),
        ).all()

    def test_verify_values(self):

        assert np.isclose(self.pos_2at.angles, np.array([90.0, 60.0,
                                                         90.0])).all()
        assert self.pos_4at_red.orthorhombic
        assert not self.pos_2at.orthorhombic
        assert np.isclose(self.pos_2at.cell.lengths(),
                          np.array([2.46, 0.0, 2.46])).all()
Example #14
0
def main(args):

    eval_name = args.modelpath.split("/")[-1]
    eval_file = "evaluation_" + eval_name + ".txt"
    if os.path.exists(eval_file):
        if args.overwrite:
            os.remove(eval_file)
        else:
            raise Exception(
                "The evaluation file already exists. Delete it or add the overwrite flag."
            )
    device = "cuda" if args.cuda else "cpu"
    calculator = mlcalcdriver.calculators.SchnetPackCalculator(args.modelpath,
                                                               device=device)

    with connect(args.dbpath) as db:
        answers, results = (
            [[] for _ in range(len(args.properties))],
            [[] for _ in range(len(args.properties))],
        )
        posinp = []
        for row in db.select():
            for i, prop in enumerate(args.properties):
                answers[i].append(row.data[prop])
            posinp.append(Posinp.from_ase(row.toatoms()))

            if len(posinp) == args.batch_size:
                job = Job(posinp=posinp, calculator=calculator)
                for i, prop in enumerate(args.properties):
                    job.run(prop, batch_size=args.batch_size)
                    results[i].append(job.results[prop].tolist())
                posinp = []
        if len(posinp) > 0:
            job = Job(posinp=posinp, calculator=calculator)
            for i, prop in enumerate(args.properties):
                job.run(prop, batch_size=args.batch_size)
                results[i].append(job.results[prop])
            posinp = []

    header, error = [], []
    for prop in args.properties:
        header += ["MAE_" + prop, "%Error_" + prop, "RMSE_" + prop]
    for l1, l2 in zip(answers, results):
        an, re = np.array(l1).flatten(), np.concatenate(l2).flatten()
        error.append(np.abs(an - re).mean())
        error.append(np.abs((an - re) / an).mean() * 100)
        error.append(np.sqrt(np.mean((an - re)**2)))

    with open(eval_file, "w") as file:
        wr = csv.writer(file)
        wr.writerow(header)
        wr.writerow(error)
Example #15
0
def get_dos(
        model,
        posinp,
        device="cpu",
        supercell=(6, 6, 6),
        qpoints=[30, 30, 30],
        npts=1000,
        width=0.004,
):
    if isinstance(posinp, str):
        atoms = posinp_to_ase_atoms(Posinp.from_file(posinp))
    elif isinstance(posinp, Posinp):
        atoms = posinp_to_ase_atoms(posinp)
    else:
        raise ValueError("The posinp variable is not recognized.")

    if isinstance(model, str):
        model = load_model(model, map_location=device)
    elif isinstance(model, torch.nn.Module):
        pass
    else:
        raise ValueError("The model variable is not recognized.")

    # Bugfix to make older models work with PyTorch 1.6
    # Hopefully temporary
    for mod in model.modules():
        if not hasattr(mod, "_non_persistent_buffers_set"):
            mod._non_persistent_buffers_set = set()

    assert len(supercell) == 3, "Supercell should be a length 3 object."
    assert len(qpoints) == 3, "Qpoints should be a length 3 object."
    supercell = tuple(supercell)

    cutoff = float(model.state_dict()
                   ["representation.interactions.0.cutoff_network.cutoff"])
    calculator = SpkCalculator(
        model,
        device=device,
        energy="energy",
        forces="forces",
        environment_provider=AseEnvironmentProvider(cutoff),
    )
    ph = Phonons(atoms, calculator, supercell=supercell, delta=0.02)
    ph.run()
    ph.read(acoustic=True)
    dos = ph.get_dos(kpts=qpoints).sample_grid(npts=npts, width=width)
    ph.clean()
    return Dos(dos.energy * 8065.6, dos.weights[0])
Example #16
0
def generate_graphene_cell(xsize, zsize):
    base_cell = np.array([2.4674318, 0, 4.2737150])
    positions = []
    reduced_pos = np.array([[0, 0, 0], [0, 0, 1.0 / 3], [0.5, 0, 0.5],
                            [0.5, 0, 5.0 / 6]])
    for i in range(xsize):
        for j in range(zsize):
            p = (np.array([i, 0, j]) + reduced_pos) * base_cell
            for pi in p:
                positions.append({"C": pi})

    pos_dict = {
        "units": "angstroem",
        "cell": base_cell * np.array([xsize, 0, zsize]),
        "positions": positions,
    }
    pos = Posinp.from_dict(pos_dict)
    return pos
Example #17
0
class TestPhononAutoGrad:

    posH2O = Posinp.from_file(os.path.join(pos_folder, "H2Orelaxed.xyz"))
    calc_ener = SchnetPackCalculator(os.path.join(model_folder, "H2O_model"))
    calc_for = SchnetPackCalculator(
        os.path.join(model_folder, "H2O_forces_model"))

    def test_ph_h2o_autograd_2nd_derivative(self):
        ph1 = Phonon(posinp=self.posH2O, calculator=self.calc_ener)
        ph1.run()
        ph1.energies.sort()
        assert np.allclose(ph1.energies[6:9], [1726, 3856, 3942], atol=1)

    def test_ph_h2o_autograd_1st_derivative(self):
        ph1 = Phonon(posinp=self.posH2O, calculator=self.calc_for)
        ph1.run()
        ph1.energies.sort()
        assert np.allclose(ph1.energies[6:9], [1589, 3703, 3812], atol=1)
def get_orthonormal_basis(modes=None, model=None, posinp=None, write=False):
    if modes:
        with h5py.File(modes, "r") as f:
            normal_modes = f["modes"][:]
            orthonormal_basis = gramschmidt(normal_modes)
    else:
        calculator = SchnetPackCalculator(model)
        posinp = Posinp.from_file(posinp)
        ph = Phonon(posinp=posinp, calculator=calculator)
        ph.run()

        normal_modes = ph.normal_modes.copy()
        orthonormal_basis = gramschmidt(normal_modes)
    if write:
        fx = h5py.File("orthonormal_basis.h5", "w")
        fx.create_dataset("basis", data=orthonormal_basis)
        fx.close()
    return orthonormal_basis
Example #19
0
class TestPhononFinite:

    posN2 = Posinp.from_file(os.path.join(pos_folder, "N2_unrelaxed.xyz"))
    calcN2 = SchnetPackCalculator(os.path.join(model_folder, "myN2_model"))

    def test_ph_N2(self):
        ph1 = Phonon(posinp=self.posN2,
                     calculator=self.calcN2,
                     finite_difference=True)
        ph1.run(batch_size=1)
        assert np.isclose(ph1.energies.max(), 2339.53, atol=0.01)
        assert all(
            np.abs(np.delete(ph1.energies, np.argmax(ph1.energies))) < 30)

        ph2 = Phonon(
            posinp=ph1._ground_state,
            calculator=ph1.calculator,
            relax=False,
            finite_difference=True,
            translation_amplitudes=0.03,
        )
        ph2.run()
        assert np.allclose(ph1.energies, ph2.energies)

        ph3 = Phonon(
            posinp=self.posN2,
            calculator=self.calcN2,
            finite_difference=True,
            relax=False,
        )
        ph3.run()
        assert not np.allclose(ph3.energies, ph1.energies, atol=100)

    def test_phonon_posinp_error(self):
        with pytest.raises(TypeError):
            ph = Phonon(posinp=None, calculator=self.calcN2)

    def test_phonon_calc_error(self):
        with pytest.raises(TypeError):
            ph = Phonon(posinp=self.posN2, calculator=None)
def get_normal_modes(posinp, model, device="cpu", rotate=False):
    calculator = SchnetPackCalculator(model, device=device)
    posinp = Posinp.from_file(posinp)
    ph = Phonon(posinp=posinp, calculator=calculator)
    ph.run()

    if rotate:
        ndim = 3 * len(posinp)
        final_modes = np.zeros((ndim, ndim))

        idx = np.arange(ndim)
        for i in range(ndim):
            init = ph.normal_modes[:, i]
            final = np.empty_like(init)
            final[np.where(idx % 3 == 0)[0]] = init[np.where(idx % 3 == 0)[0]]
            final[np.where(idx % 3 == 1)[0]] = init[np.where(idx % 3 == 2)[0]]
            final[np.where(idx %
                           3 == 2)[0]] = -1.0 * init[np.where(idx % 3 == 1)[0]]
            final_modes[:, i] = final
        return ph.energies, final_modes

    else:
        return ph.energies, ph.normal_modes
def main(args):
    with connect(args.dbname) as db:
        db.metadata = DEFAULT_METADATA
        if args.run_mode == "bigdft":
            files = [f for f in os.listdir() if f.endswith(".xyz")]
            for f in files:
                atoms = posinp_to_ase_atoms(Posinp.from_file(f))
                with open(f, "r") as posinp_file:
                    energy = float(
                        posinp_file.readline().split()[2]) * 27.21138602
                    forces = None
                    for line in posinp_file:
                        if "forces" not in line:
                            continue
                        else:
                            forces = []
                            for _ in range(len(atoms)):
                                forces.append([
                                    float(force) for force in
                                    posinp_file.readline().split()[-3:]
                                ])
                            forces = np.array(
                                forces) * 27.21138602 / 0.529177249
                            break
                db.write(atoms, data={"energy": energy, "forces": forces})

        elif args.run_mode == "abinit":
            files = [f for f in os.listdir() if f.endswith(".out")]
            for f in files:
                atoms = read(f, format="abinit-out")
                about = AbinitOutputFile(f)
                energy = float(about.final_vars_global["etotal"]) * 27.21138602
                forces = (np.array([
                    float(g) for g in about.final_vars_global["fcart"].split()
                ]).reshape(-1, 3) * 27.21138602 / 0.529177249)
                db.write(atoms, data={"energy": energy, "forces": forces})
Example #22
0
 def test_surface(self):
     pos1 = Posinp.from_file(os.path.join(pos_folder, "surface2.xyz"))
     atoms = posinp_to_ase_atoms(pos1)
     pos2 = Posinp.from_ase(atoms)
     assert pos1 == pos2
Example #23
0
class TestPosinp:

    # Posinp with surface boundary conditions
    surface_filename = os.path.join(tests_fol, "surface.xyz")
    pos = Posinp.from_file(surface_filename)
    # Posinp with free boundary conditions
    free_filename = os.path.join(tests_fol, "free.xyz")
    free_pos = Posinp.from_file(free_filename)
    periodic_filename = os.path.join(tests_fol, "periodic.xyz")
    periodic_pos = Posinp.from_file(periodic_filename)
    # Posinp read from a string
    string = """\
4   atomic
free
C    0.6661284109   0.000000000   1.153768252
C    3.330642055    0.000000000   1.153768252
C    4.662898877    1.000000000   3.461304757
C    7.327412521    0.000000000   3.461304757"""
    str_pos = Posinp.from_string(string)

    value = [len(pos), pos.units, pos.boundary_conditions, pos.cell, pos[0], pos.angles]
    expected = [
        4,
        "reduced",
        "surface",
        Cell.new(np.array([8.07007483423, 0.0, 4.65925987792])),
        Atom("C", [0.08333333333, 0.5, 0.25]),
        np.array([90.0, 90.0, 90.0]),
    ]

    def test_from_file(self):
        for v, e in zip(self.value, self.expected):
            if isinstance(v, np.ndarray) or isinstance(v, Cell):
                assert np.allclose(v, e)
            else:
                assert v == e

    def test_from_string(self):
        assert self.str_pos == self.free_pos

    def test_repr(self):
        atoms = [Atom("C", [0, 0, 0]), Atom("N", [0, 0, 1])]
        new_pos = Posinp(atoms, units="angstroem", boundary_conditions="free")
        msg = (
            "Posinp([Atom('C', [0.0, 0.0, 0.0]), Atom('N', [0.0, 0.0, "
            "1.0])], 'angstroem', 'free', cell=Cell([0.0, 0.0, 0.0]), angles=[90. 90. 90.])"
        )
        assert repr(new_pos) == msg

    def test_write(self):
        fname = os.path.join(tests_fol, "test.xyz")
        self.pos.write(fname)
        assert self.pos == Posinp.from_file(fname)
        os.remove(fname)

    def test_free_boundary_conditions_has_no_cell(self):
        assert (self.free_pos.cell == Cell.new()).all()

    def test_translate_atom(self):
        new_pos = self.pos.translate_atom(0, [0.5, 0, 0])
        assert new_pos != self.pos
        assert new_pos[0] == Atom("C", [0.58333333333, 0.5, 0.25])

    @pytest.mark.parametrize(
        "fname", ["free_reduced.xyz", "missing_atom.xyz", "additional_atom.xyz"]
    )
    def test_init_raises_ValueError(self, fname):
        with pytest.raises(ValueError):
            Posinp.from_file(os.path.join(tests_fol, fname))

    @pytest.mark.parametrize(
        "to_evaluate",
        [
            "Posinp([Atom('C', [0, 0, 0])], 'bohr', 'periodic')",
            "Posinp([Atom('C', [0, 0, 0])], 'bohr', 'periodic', cell=[1, 1])",
            "Posinp([Atom('C', [0, 0, 0])], 'bohr', 'periodic', cell=[1,'inf',1])",
        ],
    )
    def test_init_raises_ValueError2(self, to_evaluate):
        with pytest.raises(ValueError):
            eval(to_evaluate)

    def test_positions(self):
        expected = [7.327412521, 0.0, 3.461304757]
        pos1 = Posinp(
            [Atom("C", expected)], units="angstroem", boundary_conditions="free"
        )
        pos2 = pos1.translate_atom(0, [-7.327412521, 0.0, -3.461304757])
        assert np.allclose(pos1.positions, expected)
        assert np.allclose(pos2.positions, [0, 0, 0])

    def test___eq__(self):
        atom1 = Atom("N", [0.0, 0.0, 0.0])
        atom2 = Atom("N", [0.0, 0.0, 1.1])
        pos1 = Posinp([atom1, atom2], "angstroem", "free")
        pos2 = Posinp([atom2, atom1], "angstroem", "free")
        assert pos1 == pos2  # The order of the atoms in the list do not count
        assert pos1 != 1  # No error if other object is not a posinp

    def test_with_surface_boundary_conditions(self):
        # Two Posinp instances with surface BC are the same even if they
        # have a different cell size along y-axis
        pos_with_inf = Posinp(
            [
                Atom(
                    "N",
                    [2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779],
                ),
                Atom(
                    "N",
                    [-1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154],
                ),
            ],
            "angstroem",
            "surface",
            cell=[40, ".inf", 40],
        )
        with pytest.raises(ValueError):
            pos_wo_inf = Posinp(
                [
                    Atom(
                        "N",
                        [2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779],
                    ),
                    Atom(
                        "N",
                        [-1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154],
                    ),
                ],
                "angstroem",
                "surface",
                cell=[40, 40, 40],
            )
        # They are obviously different if the cell size along the other
        # directions are not the same
        pos2_with_inf = Posinp(
            [
                Atom(
                    "N",
                    [2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779],
                ),
                Atom(
                    "N",
                    [-1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154],
                ),
            ],
            "angstroem",
            "surface",
            cell=[20, "inf", 40],
        )
        assert pos_with_inf != pos2_with_inf
        # They still have the same BC
        assert pos2_with_inf.boundary_conditions == pos_with_inf.boundary_conditions

    def test_to_centroid(self):
        atoms = [Atom("N", [0, 0, 0]), Atom("N", [0, 0, 1.1])]
        pos = Posinp(atoms, units="angstroem", boundary_conditions="free")
        expected_atoms = [Atom("N", [0, 0, -0.55]), Atom("N", [0, 0, 0.55])]
        expected_pos = Posinp(
            expected_atoms, units="angstroem", boundary_conditions="free"
        )
        assert pos.to_centroid() == expected_pos

    def test_to_barycenter(self):
        atoms = [Atom("N", [0, 0, 0]), Atom("N", [0, 0, 1.1])]
        pos = Posinp(atoms, units="angstroem", boundary_conditions="free")
        expected_atoms = [Atom("N", [0, 0, -0.55]), Atom("N", [0, 0, 0.55])]
        expected_pos = Posinp(
            expected_atoms, units="angstroem", boundary_conditions="free"
        )
        assert pos.to_barycenter() == expected_pos

    def test_distance(self):
        assert np.isclose(self.free_pos.distance(0, 2), 4.722170992308181)

    def test_convert(self):
        pos1 = self.periodic_pos.positions
        assert self.periodic_pos.units == "angstroem"
        self.periodic_pos.convert_units("atomic")
        assert np.isclose(
            self.periodic_pos.positions,
            np.array(
                [
                    [0.15747717, 0.94486299, 0.4724315],
                    [0.78738583, 0.94486299, 0.4724315],
                    [1.10234016, 0.94486299, 1.41729449],
                    [1.73224882, 0.94486299, 1.41729449],
                ]
            ),
        ).all()
        assert self.periodic_pos.units == "atomic"
        self.periodic_pos.convert_units("angstroem")
        assert np.isclose(self.periodic_pos.positions, pos1).all()
        assert self.periodic_pos.units == "angstroem"
        self.periodic_pos.convert_units("angstroem")
        assert np.isclose(self.periodic_pos.positions, pos1).all()
        red = Posinp.from_file(tests_fol + "reduced.xyz")
        red.convert_units("angstroem")
        print(red.positions)
        assert np.isclose(
            red.positions,
            np.array(
                [
                    [0.4233418, 1.32294312, 0.95251905],
                    [3.81007619, 0.26458862, 0.47625952],
                ]
            ),
        ).all()

    def test_angles(self):
        h2o = Posinp.from_file(tests_fol + "H2Orelaxed.xyz")
        a = h2o.angle(1, 0, 2) * 180 / np.pi
        assert np.isclose(a, 104.1219, atol=10 ** -4)
        a1, a2 = h2o.angle(0, 1, 2), h2o.angle(2, 1, 0)
        assert a1 == a2
Example #24
0
 def test_periodic(self):
     pos1 = Posinp.from_file(os.path.join(pos_folder, "periodic.xyz"))
     atoms = posinp_to_ase_atoms(pos1)
     pos2 = Posinp.from_ase(atoms)
     assert pos1 == pos2
def get_normal_modes(posinp, model, device="cpu"):
    calculator = SchnetPackCalculator(model, device=device)
    posinp = Posinp.from_file(posinp)
    ph = Phonon(posinp=posinp, calculator=calculator)
    ph.run()
    return ph.energies, ph.normal_modes
Example #26
0
import numpy as np
from mlcalcdriver import Posinp
import matplotlib.pyplot as plt


pos = Posinp.from_file("data/posinp.xyz")

translations = (
    np.array(
        [
            [0, 0, 0],
            [1, 0, 0],
            [-1, 0, 0],
            [0, 0, 1],
            [0, 0, -1],
            [1, 0, 1],
            [1, 0, -1],
            [-1, 0, 1],
            [-1, 0, -1],
        ]
    )
    * pos.cell
)

results = []
n = 50000
n_at = len(pos)

for _ in range(n):
    i,j = np.random.choice(n_at, 2, replace=False)
    atom1, atom2 = pos[i], pos[j]
Example #27
0
 def test_init_raises_ValueError(self, fname):
     with pytest.raises(ValueError):
         Posinp.from_file(os.path.join(tests_fol, fname))
Example #28
0
 def test_write(self):
     fname = os.path.join(tests_fol, "test.xyz")
     self.pos.write(fname)
     assert self.pos == Posinp.from_file(fname)
     os.remove(fname)
Example #29
0
 def test_angles(self):
     h2o = Posinp.from_file(tests_fol + "H2Orelaxed.xyz")
     a = h2o.angle(1, 0, 2) * 180 / np.pi
     assert np.isclose(a, 104.1219, atol=10 ** -4)
     a1, a2 = h2o.angle(0, 1, 2), h2o.angle(2, 1, 0)
     assert a1 == a2
Example #30
0
from mlcalcdriver import Posinp
import numpy as np
import os
from copy import copy
import matplotlib.pyplot as plt

pos_folder = "positions/"

positions = [
    Posinp.from_file(pos_folder + file) for file in os.listdir(pos_folder)
    if file.endswith(".xyz")
]

distances, angles = [], []
for pos in positions:
    az_idx = [i for i, at in enumerate(pos) if at.type == "N"]
    if len(az_idx) == 2:
        distances.append(pos.distance(az_idx[0], az_idx[1]))
        angles.append(np.pi)
    elif len(az_idx) == 3:
        mid = np.array(pos.cell) / 2
        d = np.array(
            [np.linalg.norm(pos[idx].position - mid) for idx in az_idx])
        mid_idx = az_idx[np.argmin(d)]
        other_idx = copy(az_idx)
        del other_idx[np.argmin(d)]

        distances.append(pos.distance(mid_idx, other_idx[0]))
        distances.append(pos.distance(mid_idx, other_idx[1]))
        angles.append(pos.angle(other_idx[0], mid_idx, other_idx[1]))
    else: