def save_muonconf_dftb(a, folder, params, dftbargs={}): from pymuonsuite.data.dftb_pars import DFTBArgs name = os.path.split(folder)[-1] a.set_pbc(params['dftb_pbc']) dargs = DFTBArgs(params['dftb_set']) custom_species = a.get_array('castep_custom_species') muon_index = np.where(custom_species == params['mu_symbol'])[0][0] is_spinpol = params.get('spin_polarized', False) if is_spinpol: dargs.set_optional('spinpol.json', True) # Add muon mass args = dargs.args args['Driver_'] = 'ConjugateGradient' args['Driver_Masses_'] = '' args['Driver_Masses_Mass_'] = '' args['Driver_Masses_Mass_Atoms'] = '{}'.format(muon_index) args['Driver_Masses_Mass_MassPerAtom [amu]'] = '0.1138' args['Driver_MaxForceComponent [eV/AA]'] = params['geom_force_tol'] args['Driver_MaxSteps'] = params['geom_steps'] args['Driver_MaxSccIterations'] = params['max_scc_steps'] if is_spinpol: # Configure initial spins spins = np.array(a.get_initial_magnetic_moments()) args['Hamiltonian_SpinPolarisation_InitialSpins'] = '{' args['Hamiltonian_SpinPolarisation_' + 'InitialSpins_AllAtomSpins'] = '{' + '\n'.join( map(str, spins)) + '}' args['Hamiltonian_SpinPolarisation_UnpairedElectrons'] = str( np.sum(spins)) # Add any custom arguments if isinstance(dftbargs, DFTBArgs): args.update(dftbargs.args) else: args.update(dftbargs) if params['dftb_pbc']: dcalc = Dftb(label=name, atoms=a, kpts=params['k_points_grid'], run_manyDftb_steps=True, **args) else: dcalc = Dftb(label=name, atoms=a, run_manyDftb_steps=True, **args) dcalc.directory = folder dcalc.write_input(a)
def asephonons_entry(): from ase import io from ase.calculators.dftb import Dftb from pymuonsuite.data.dftb_pars import DFTBArgs parser = ap.ArgumentParser(description="Compute phonon modes with ASE and" " DFTB+ for reuse in quantum effects " "calculations.") parser.add_argument('structure_file', type=str, help="Structure for which to compute the phonons") parser.add_argument('parameter_file', type=str, help="YAML file containing relevant input parameters") args = parser.parse_args() # Load parameters params = load_input_file(args.parameter_file, AsePhononsSchema) fname, fext = os.path.splitext(args.structure_file) if params['name'] is None: params['name'] = fname # Load structure a = io.read(args.structure_file) # Create a Dftb calculator dargs = DFTBArgs(params['dftb_set']) # Is it periodic? if params['pbc']: a.set_pbc(True) calc = Dftb(atoms=a, label='asephonons', kpts=params['kpoint_grid'], **dargs.args) ph_kpts = params['phonon_kpoint_grid'] else: a.set_pbc(False) calc = Dftb(atoms=a, label='asephonons', **dargs.args) ph_kpts = None a.set_calculator(calc) phdata = ase_phonon_calc(a, kpoints=ph_kpts, ftol=params['force_tol'], force_clean=params['force_clean'], name=params['name']) # Save optimised structure io.write(params['name'] + '_opt' + fext, phdata.structure) # And write out the phonons outf = params['name'] + '_opt.phonons.pkl' pickle.dump(phdata, open(outf, 'wb')) write_phonon_report(args, params, phdata)
def create_spinpol_dftbp_calculator(calc=None, param_set='3ob-3-1', kpts=None): """Create a calculator containing all necessary parameters for a DFTB+ SCC spin polarised calculation""" from pymuonsuite.data.dftb_pars import DFTBArgs if not isinstance(calc, Dftb): calc = Dftb() else: calc = deepcopy(calc) # A bit of a hack for the k-points if kpts is not None: kc = Dftb(kpts=kpts) kargs = {k: v for k, v in kc.parameters.items() if 'KPoints' in k} calc.parameters.update(kargs) # Create the arguments dargs = DFTBArgs(param_set) # Make it spin polarised try: dargs.set_optional('spinpol.json', True) except KeyError: raise ValueError('DFTB+ parameter set does not allow spin polarised' ' calculations') # Fix a few things, and add a spin on the muon args = dargs.args del (args['Hamiltonian_SpinPolarisation']) args['Hamiltonian_SpinPolarisation_'] = 'Colinear' args['Hamiltonian_SpinPolarisation_UnpairedElectrons'] = 1 args['Hamiltonian_SpinPolarisation_InitialSpins_'] = '' args['Hamiltonian_SpinPolarisation_InitialSpins_Atoms'] = '-1' args['Hamiltonian_SpinPolarisation_InitialSpins_SpinPerAtom'] = 1 calc.parameters.update(args) calc.do_forces = True return calc
def test_create_calc(self): # Tests whether the correct values of the parameters are set # when creating a calculator that would be used for writing # a dftb input file. def check_geom_opt_params(params, calc_params): self.assertEqual(calc_params["Hamiltonian_Charge"], params["charged"] * 1.0) self.assertEqual(calc_params["Driver_MaxSteps"], params["geom_steps"]) self.assertEqual( calc_params["Driver_MaxForceComponent [eV/AA]"], params["geom_force_tol"], ) self.assertEqual( calc_params["Hamiltonian_MaxSccIterations"], params["max_scc_steps"], ) # In the case that a params dict is provided, the values for the # parameters should be taken from here. params = { "k_points_grid": [2, 2, 2], "geom_force_tol": 0.01, "dftb_set": "pbc-0-3", "dftb_optionals": [], "geom_steps": 500, "max_scc_steps": 150, "charged": False, "dftb_pbc": True, } reader = ReadWriteDFTB(params=params) # First test a geom opt calculator: calc_geom_opt = reader._create_calculator(calc_type="GEOM_OPT") calc_params = calc_geom_opt.parameters check_geom_opt_params(params, calc_params) self.assertEqual(calc_geom_opt.kpts, params["k_points_grid"]) # Next a spinpol calculator: calc_magres = reader._create_calculator(calc_type="SPINPOL") self.assertEqual(calc_magres.kpts, params["k_points_grid"]) # In the case that a calculator is provided, the new calculator should # retain the same properties. args = { "Hamiltonian_Charge": params["charged"] * 1.0, "Driver_MaxSteps": params["geom_steps"], "Driver_MaxForceComponent [eV/AA]": params["geom_force_tol"], "Hamiltonian_MaxSccIterations": params["max_scc_steps"], } dargs = DFTBArgs(params["dftb_set"]) dargs.set_optional("spinpol.json", True) args.update(dargs.args) calc = Dftb(kpts=params["k_points_grid"], **args) reader = ReadWriteDFTB(calc=calc) # First test a geom opt calculator: calc_geom_opt = reader._create_calculator(calc_type="GEOM_OPT") calc_params = calc_geom_opt.parameters check_geom_opt_params(params, calc_params) self.assertEqual(calc_geom_opt.kpts, params["k_points_grid"]) # Next a spinpol calculator: calc_magres = reader._create_calculator(calc_type="SPINPOL") self.assertEqual(calc_magres.kpts, params["k_points_grid"]) # In the case that we do not supply a params dict or a calculator, # the new calculator should get the default settings: params = { "k_points_grid": None, "geom_force_tol": 0.05, "dftb_set": "3ob-3-1", "geom_steps": 30, "max_scc_steps": 200, "charged": False, } reader = ReadWriteDFTB() # First test a geom opt calculator: calc_geom_opt = reader._create_calculator(calc_type="GEOM_OPT") calc_params = calc_geom_opt.parameters self.assertEqual(calc_geom_opt.kpts, params["k_points_grid"]) check_geom_opt_params(params, calc_params) # Next a spinpol calculator: calc_magres = reader._create_calculator(calc_type="SPINPOL") self.assertEqual(calc_magres.kpts, params["k_points_grid"])
def asephonons_entry(): from ase import io from ase.calculators.dftb import Dftb from pymuonsuite.data.dftb_pars import DFTBArgs parser = ap.ArgumentParser( description="Compute phonon modes with ASE and" " DFTB+ for reuse in quantum effects " "calculations." ) parser.add_argument( "structure_file", type=str, help="Structure for which to compute the phonons", ) parser.add_argument( "parameter_file", type=str, help="YAML file containing relevant input parameters", ) args = parser.parse_args() # Load parameters params = load_input_file(args.parameter_file, AsePhononsSchema) fname, fext = os.path.splitext(args.structure_file) if params["name"] is None: params["name"] = fname # Load structure with silence_stdio(): a = io.read(args.structure_file) # Create a Dftb calculator dargs = DFTBArgs(params["dftb_set"]) # Is it periodic? if params["pbc"]: a.set_pbc(True) calc = Dftb( atoms=a, label="asephonons", kpts=params["kpoint_grid"], **dargs.args ) ph_kpts = params["phonon_kpoint_grid"] else: a.set_pbc(False) calc = Dftb(atoms=a, label="asephonons", **dargs.args) ph_kpts = None a.calc = calc try: phdata = ase_phonon_calc( a, kpoints=ph_kpts, ftol=params["force_tol"], force_clean=params["force_clean"], name=params["name"], ) except Exception as e: print(e) print("Error: Could not write phonons file, see asephonons.out for" " details.") sys.exit(1) # Save optimised structure with silence_stdio(): io.write(params["name"] + "_opt" + fext, phdata.structure) # And write out the phonons outf = params["name"] + "_opt.phonons.pkl" pickle.dump(phdata, open(outf, "wb")) write_phonon_report(args, params, phdata)