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"]
def run(self, batch_size=128, **kwargs): r""" Parameters ---------- batch_size : int Batch size used when passing the structures to the model **kwargs : Optional arguments for the geometry optimization. Only useful if the relaxation is unstable. """ if self.relax: geopt = Geopt(posinp=self.posinp, calculator=self.calculator, **kwargs) geopt.run(batch_size=batch_size) self._ground_state = deepcopy(geopt.final_posinp) if self.finite_difference: job = Job(posinp=self._create_displacements(), calculator=self.calculator) job.run(property="forces", batch_size=batch_size) else: job = Job(posinp=self._ground_state, calculator=self.calculator) job.run(property="hessian", batch_size=batch_size) self._post_proc(job)
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()
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"]
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)
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_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
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
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
def test_raises_bad_calc(self): with pytest.raises(TypeError): j = Job(posinp=[self.pos1], calculator=self.badCalc)
def test_raises_posinp_types(self): with pytest.raises(TypeError): j = Job(posinp=[self.pos1, 1], calculator=self.dummy)
def test_raises_no_positions(self): with pytest.raises(ValueError): j = Job(calculator=self.dummy)
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("angstrom") 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)