def main(args): param = InputParams() for filename in [f for f in os.listdir() if f.endswith(".yaml")]: try: param = InputParams.from_file(filename) break except: continue pseudos = not (args.no_pseudos) positions = [ Posinp.from_file(args.positions_dir + file) for file in os.listdir(args.positions_dir) if file.endswith(".xyz") ] # Create directories os.makedirs("run_dir/", exist_ok=True) os.makedirs("saved_results/", exist_ok=True) os.chdir("run_dir/") for i in range(args.n_structs): j = int(np.random.choice(len(positions), 1)) posinp = generate_random_structure(positions[j]) run(posinp, i, args, param, pseudos)
def test_run(self): atoms = [Atom('N', [0, 0, 0]), Atom('N', [0, 0, 1.1])] pos = Posinp(atoms, units="angstroem", boundary_conditions="free") inp = InputParams({"dft": {"rmult": [5, 7]}}) base = Job(inputparams=inp, posinp=pos, name="N2", run_dir="tests/hgrids_convergence_N2") hgc = HgridsConvergence(base, 0.36, 0.02, n_jobs=8, precision_per_atom=0.01 * EV_TO_HA) assert not hgc.is_completed hgc.run(nmpi=6, nomp=3) assert hgc.is_completed # The correct maximum hgrids is found assert hgc.converged.param == [0.38] * 3 # The output energies are correct expected_energies = [-19.888197, -19.887715, -19.887196, 0, 0, 0, 0, 0] energies = [ job.logfile.energy if job.is_completed else 0 for job in hgc.queue ] np.testing.assert_array_almost_equal(energies, expected_energies) # Print the summary of the workflow hgc.summary() # Test that running the workflow again warns a UserWarning with pytest.warns(UserWarning): hgc.run()
def test_run(self): atoms = [Atom('N', [0, 0, 0]), Atom('N', [0, 0, 1.1])] pos = Posinp(atoms, units="angstroem", boundary_conditions="free") inp = InputParams({"dft": {"rmult": [5, 7], "hgrids": 0.55}}) base = Job(posinp=pos, inputparams=inp, name="N2", run_dir="tests/rmult_convergence_N2") rmc = RmultConvergence(base, [8, 11], [-1, -1], n_jobs=4, precision_per_atom=0.01 * EV_TO_HA) assert not rmc.is_completed rmc.run(nmpi=6, nomp=3) assert rmc.is_completed # The correct minimum rmult is found assert rmc.converged.param == [6., 9.] # The output energies are correct expected_energies = [-19.871104, -19.871032, -19.870892, -19.869907] energies = [job.logfile.energy for job in rmc.queue] np.testing.assert_array_almost_equal(energies, expected_energies) # Print the summary of the workflow rmc.summary() # Test that running the workflow again warns a UserWarning with pytest.warns(UserWarning): rmc.run()
def test_inputparams(self): inp = log.inputparams expected = InputParams({ 'dft': { 'rmult': [2, 4], 'hgrids': 2.5, 'itermax': 1, 'disablesym': True }, 'posinp': { 'units': 'angstroem', 'positions': [{ 'N': [ 2.9763078243490115e-23, 6.872205952043537e-23, 0.01071619987487793 ] }, { 'N': [ -1.1043449194501671e-23, -4.873421744830746e-23, 1.104273796081543 ] }], 'properties': { 'format': 'xyz', 'source': 'N2.xyz' } } }) assert inp == expected
def test__check_logfile_inputparams(self): with pytest.raises(UserWarning): with Job(inputparams=InputParams(), posinp=self.pos, name="warnings", run_dir="tests") as job: job.run()
def test_dry_run_raises_RuntimeError(self): # Error because two ".inf" in cell new_inp = InputParams({ "posinp": { "units": "angstroem", "cell": [40, ".inf", ".inf"], "positions": [ { 'N': [ 2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779 ] }, { 'N': [ -1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154 ] }, ] } }) with pytest.raises(RuntimeError): with Job(inputparams=new_inp, run_dir="tests/dummy") as job: job.run(dry_run=True)
def test_posinp_with_inf(self): new_inp = InputParams({ "posinp": { "units": "angstroem", "cell": [40, ".inf", 40], "positions": [ { 'N': [ 2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779 ] }, { 'N': [ -1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154 ] }, ] } }) with Job(inputparams=new_inp, name="test") as job: job.run(nmpi=6, nomp=3, dry_run=True) job.clean() assert job.logfile.boundary_conditions == 'surface'
def test_run_exceeds_timeout_raises_RuntimeError(self): inp = InputParams({"dft": {"rmult": [9, 12], "hgrids": 0.25}}) with Job(inputparams=inp, posinp=self.pos, run_dir="tests", name="long-run") as job: job.clean() assert not job.is_completed with pytest.raises(RuntimeError): job.run(timeout=1.5 / 60, force_run=True)
def test_run_warns_UserWarning_too_low_energy(self): atoms = [Atom('N', [0, 0, 0]), Atom('N', [0, 0, 1.1])] pos = Posinp(atoms, units="angstroem", boundary_conditions="free") inp = InputParams({"dft": {"rmult": [5, 7], "hgrids": 0.55}}) base = Job(posinp=pos, inputparams=inp, name="N2", run_dir="tests/rmult_convergence_N2") rmc = RmultConvergence(base, [9, 12], [-1, -1], n_jobs=2, precision_per_atom=0.01 * EV_TO_HA) with pytest.warns(UserWarning): rmc.run(nmpi=6, nomp=3)
def test_run_with_dry_run(self): with Job(inputparams=self.inp, name="dry_run", run_dir="tests") as job: # Run the calculation job.clean() assert not job.is_completed job.run(dry_run=True, nmpi=2, nomp=4) assert job.is_completed # There must be input and output files afterwards new_inp = InputParams.from_file(job.input_name) assert new_inp == self.inp new_pos = Posinp.from_file(job.posinp_name) assert new_pos == self.pos bigdft_tool_log = Logfile.from_file(job.logfile_name) assert bigdft_tool_log.energy is None
def prepare_calculations(overwrite=False): r""" Determines which files are present and which need to be generated. Parameters: ------------- overwrite : bool (default : False) if True, the present files are ignored Returns: base_inp : InputParams base input parameters for the calculation base_pos : Posinp base atomic positions for the calculation jobname : string Name of the calculation if there is a pos file, string "jobname" if no position file. """ files = [f for f in os.listdir() if f.endswith((".xyz", ".yaml"))] posinp_is_present, jobname = verify_posinp(files) if verify_input(files): base_inp = InputParams.from_file("input.yaml") else: base_inp = InputParams() if posinp_is_present: base_pos = Posinp.from_file(jobname + ".xyz") elif base_inp.posinp is not None: base_pos = base_inp.posinp jobname = "jobname" base_pos.write(jobname + ".xyz") else: raise ValueError("No atomic positions are available.") return base_inp, base_pos, jobname
def test_set_posinp_key(self): inp = InputParams() inp["posinp"] = { "units": "angstroem", "positions": [{ 'N': [0.0, 0.0, 0.0] }, { 'N': [0.0, 0.0, 1.1] }] } assert inp.posinp == Posinp( [Atom('N', [0, 0, 0]), Atom('N', [0, 0, 1.1])], units="angstroem", boundary_conditions="free")
def test_run_with_dry_run_with_posinp(self): with Job(inputparams=self.inp, posinp=self.pos, name="dry_run", run_dir="tests") as job: job.clean() assert not job.is_completed job.run(dry_run=True, nmpi=2, nomp=4) assert job.is_completed # Make sure that input, posinp and output files are created new_inp = InputParams.from_file(job.input_name) assert new_inp == self.inp new_pos = Posinp.from_file(job.posinp_name) assert new_pos == self.pos bigdft_tool_log = Logfile.from_file(job.logfile_name) assert bigdft_tool_log.energy is None
def test_write(self): inp = InputParams() inp.write(self.filename) assert inp == {}
def test_len(self): assert len(InputParams()) == 0
def test_from_file(self): inp = InputParams.from_file(self.filename) assert inp == {}
def test_init_warns_UserWarning(self): test_inp = InputParams({'dft': {'elecfield': [0.1]*3}}) job = Job(inputparams=test_inp, posinp=pos) with pytest.warns(UserWarning): PolTensor(job)
class TestPolTensor: # Polarizibility tensor workflow which is not run inp = InputParams({'dft': {'hgrids': [0.55]*3}}) gs = Job(inputparams=inp, posinp=pos, name='N2', run_dir='pol_tensor_N2') pt = PolTensor(gs) @pytest.mark.parametrize("value, expected", [ (pt.ground_state, gs), (pt.is_completed, False), (pt.ef_amplitudes, [1.e-4]*3), (os.path.basename(pt.ground_state.run_dir), "pol_tensor_N2"), ]) def test_init(self, value, expected): assert value == expected def test_init_warns_UserWarning(self): test_inp = InputParams({'dft': {'elecfield': [0.1]*3}}) job = Job(inputparams=test_inp, posinp=pos) with pytest.warns(UserWarning): PolTensor(job) @pytest.mark.parametrize("to_evaluate", [ 'PolTensor(self.gs, ef_amplitudes=0.0)', 'PolTensor(self.gs, ef_amplitudes=[0.0])', 'PolTensor(self.gs, ef_amplitudes=[0.1]*4)', ]) def test_init_ef_amplitudes_raises_ValueError(self, to_evaluate): with pytest.raises(ValueError): eval(to_evaluate) def test_init_raises_NotImplementedError(self): with pytest.raises(NotImplementedError): PolTensor(self.gs, order=-1) def test_run_first_order(self): # Run a pol. tensor calculation gs2 = Job(posinp=pos, name='N2', run_dir='tests/pol_tensor_N2') pt2 = PolTensor(gs2, order=1) assert not pt2.is_completed pt2.run() assert pt2.is_completed # Test the computed polarizability tensor expected = [ [1.05558000e+01, -2.00000000e-04, 0.00000000e+00], [-2.00000000e-04, 1.05558000e+01, 0.00000000e+00], [-2.00000000e-04, -2.00000000e-04, 1.50535000e+01] ] np.testing.assert_almost_equal(pt2.pol_tensor, expected) np.testing.assert_almost_equal(pt2.mean_polarizability, 12.05503333333) # Test that running the workflow again warns a UserWarning with pytest.warns(UserWarning): pt2.run() def test_run_second_order(self): # Run a pol. tensor calculation gs2 = Job(posinp=pos, name='N2', run_dir='tests/pol_tensor_N2') pt2 = PolTensor(gs2, order=2) assert not pt2.is_completed pt2.run() assert pt2.is_completed # Test the computed polarizability tensor expected = [ [1.055590e+01, -3.000000e-04, 0.000000e+00], [-3.000000e-04, 1.055590e+01, 0.000000e+00], [-3.500000e-04, -3.500000e-04, 1.505375e+01] ] np.testing.assert_almost_equal(pt2.pol_tensor, expected) np.testing.assert_almost_equal(pt2.mean_polarizability, 12.05518333333) # Test that running the workflow again warns a UserWarning with pytest.warns(UserWarning): pt2.run()
def test_set_with_default_values(self): inp = InputParams({"dft": {"hgrids": 0.45}}) inp["dft"] = {"hgrids": [0.45] * 3} assert inp == {}
def test_from_string(self): inp_str = "{'dft': {'hgrids': 0.3, 'rmult': [5, 7]}}" inp = InputParams.from_string(inp_str) assert inp == {'dft': {'hgrids': 0.3, 'rmult': [5, 7]}}
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) # 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 0.000000000 3.461304757 C 7.327412521 0.000000000 3.461304757""" str_pos = Posinp.from_string(string) # Posinp read from an N2 calculation of bad quality log_pos = Logfile.from_file(logname).posinp # Posinp read from an InputParams instance with surface BC surf_inp = InputParams({ 'posinp': { 'units': 'angstroem', 'cell': [8.0, '.inf', 8.0], 'positions': [{ 'C': [0.0, 0.0, 0.0] }] } }) surf_pos = surf_inp.posinp # Posinp read from an InputParams instance with periodic BC per_inp = InputParams({ 'posinp': { 'units': 'angstroem', 'cell': [8.0, 1.0, 8.0], 'positions': [{ 'C': [0.0, 0.0, 0.0] }] } }) per_pos = per_inp.posinp @pytest.mark.parametrize("value, expected", [ (len(pos), 4), (pos.units, "reduced"), (len(pos), 4), (pos.boundary_conditions, "surface"), (pos.cell, [8.07007483423, 'inf', 4.65925987792]), (pos[0], Atom('C', [0.08333333333, 0.5, 0.25])), ]) def test_from_file(self, value, expected): assert value == expected @pytest.mark.parametrize("value, expected", [ (len(log_pos), 2), (log_pos.units, "angstroem"), (len(log_pos), 2), (log_pos.boundary_conditions, "free"), (log_pos.cell, None), (log_pos[0], Atom('N', [ 2.9763078243490115e-23, 6.872205952043537e-23, 0.01071619987487793 ])), ]) def test_from_Logfile(self, value, expected): assert value == expected @pytest.mark.parametrize("value, expected", [ (len(surf_pos), 1), (surf_pos.units, "angstroem"), (len(surf_pos), 1), (surf_pos.boundary_conditions, "surface"), (surf_pos.cell, [8, "inf", 8]), (surf_pos[0], Atom('C', [0, 0, 0])), ]) def test_from_surface_InputParams(self, value, expected): assert value == expected @pytest.mark.parametrize("value, expected", [ (len(per_pos), 1), (per_pos.units, "angstroem"), (len(per_pos), 1), (per_pos.boundary_conditions, "periodic"), (per_pos.cell, [8, 1.0, 8]), (per_pos[0], Atom('C', [0, 0, 0])), ]) def test_from_periodic_InputParams(self, value, expected): assert value == expected 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=None)" 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 is None 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]) 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]) assert pos_with_inf == pos_wo_inf # They are obviously different if the cell size along the other # directions are not the same pos2_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=[20, "inf", 40]) assert pos_with_inf != pos2_wo_inf # They still have the same BC assert \ pos2_wo_inf.boundary_conditions == pos_with_inf.boundary_conditions # You can only have a cell with ".inf" in 2nd positiion to # initialize a calculation with surface BC without using a # Posinp instance inp_with_inf = InputParams({ "posinp": { "units": "angstroem", "cell": [40, ".inf", 40], "positions": [ { 'N': [ 2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779 ] }, { 'N': [ -1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154 ] }, ] } }) assert pos_with_inf == inp_with_inf.posinp 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_init(self, params, expected): inp = InputParams(params=params) assert inp == expected
def test_set_two_keys_raises_KeyError(self, k1, k2, value): inp = InputParams() with pytest.raises(KeyError): inp[k1][k2] = value
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]) 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]) assert pos_with_inf == pos_wo_inf # They are obviously different if the cell size along the other # directions are not the same pos2_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=[20, "inf", 40]) assert pos_with_inf != pos2_wo_inf # They still have the same BC assert \ pos2_wo_inf.boundary_conditions == pos_with_inf.boundary_conditions # You can only have a cell with ".inf" in 2nd positiion to # initialize a calculation with surface BC without using a # Posinp instance inp_with_inf = InputParams({ "posinp": { "units": "angstroem", "cell": [40, ".inf", 40], "positions": [ { 'N': [ 2.97630782434901e-23, 6.87220595204354e-23, 0.0107161998748779 ] }, { 'N': [ -1.10434491945017e-23, -4.87342174483075e-23, 1.10427379608154 ] }, ] } }) assert pos_with_inf == inp_with_inf.posinp
def test_set_posinp_raises_ValueError(self): inp = InputParams() with pytest.raises(ValueError): inp.posinp = 1
def test_del(self): inp = InputParams({"dft": {"hgrids": 0.45}}) del inp["dft"] assert inp == {}
def main(args): initpos = generate_graphene_cell(args.xsize, args.zsize) param = InputParams() for filename in [f for f in os.listdir() if f.endswith(".yaml")]: try: param = InputParams.from_file(filename) break except: continue pseudos = not (args.no_pseudos) # Create directories os.makedirs("run_dir/", exist_ok=True) os.makedirs("saved_results/", exist_ok=True) os.chdir("run_dir/") if args.n_defects == 0: for i in range(1, args.n_structs + 1): posinp = generate_random_structure(initpos) run(posinp, i, args, param, pseudos) elif args.n_defects == 1: initpos, _ = place_first_nitrogen(initpos) for i in range(1, args.n_structs + 1): posinp = generate_random_structure(initpos) run(posinp, i, args, param, pseudos) elif args.n_defects == 2: initpos, first_idx = place_first_nitrogen(initpos) root = np.sqrt(args.n_structs) if root % 1 == 0: n_angle, n_radius = root, root else: n_angle, n_radius = np.ceil(root), np.floor(root) max_radius = np.max(np.array(initpos.cell) / 2) radiuses = np.linspace(1.0, max_radius, n_radius) angles = np.linspace(0, 2 * np.pi, n_angle) i = 0 # distances = np.zeros(int(n_angle * n_radius)) for theta in angles: for r in radiuses: i += 1 posinp, second_idx = place_second_nitrogen( initpos, theta, r, first_idx) # distances[i-1] = np.linalg.norm(posinp.positions[first_idx] - posinp.positions[second_idx]) run(posinp, i, args, param, pseudos) # np.savetxt("distances.data", distances) elif args.n_defects == 3: root = np.sqrt(args.n_structs) if root % 1 == 0: n_angle, n_radius = root, root else: n_angle, n_radius = np.ceil(root), np.floor(root) else: raise NotImplementedError("No method for this number of defects.")
def test_set(self): inp = InputParams() inp["dft"] = {"hgrids": 0.45} assert inp == {"dft": {"hgrids": 0.45}}
def test_set_warns_UserWarning(self): inp = InputParams() with pytest.warns(UserWarning): inp["dft"] = {"hgrids": [0.45] * 3} assert inp == {}
def test_set_raises_KeyError(self, key, value): inp = InputParams() with pytest.raises(KeyError): inp[key] = value