def create_hfine_castep_calculator(mu_symbol='H:mu', calc=None, param_file=None, kpts=[1, 1, 1]): """Create a calculator containing all the necessary parameters for a hyperfine calculation.""" if not isinstance(calc, Castep): calc = Castep() else: calc = deepcopy(calc) gamma_block = calc.cell.species_gamma.value calc.cell.species_gamma = add_to_castep_block(gamma_block, mu_symbol, constants.m_gamma, 'gamma') calc.cell.kpoint_mp_grid = kpts if param_file is not None: calc.param = read_param(param_file).param calc.param.task = 'Magres' calc.param.magres_task = 'Hyperfine' return calc
def _create_calculator(self, calc_type=None): with silence_stdio(): if self._calc is not None and isinstance(self._calc, Castep): calc = deepcopy(self._calc) else: calc = Castep() mu_symbol = self.params.get('mu_symbol', 'H:mu') # Start by ensuring that the muon mass and gyromagnetic ratios are # included gamma_block = calc.cell.species_gamma.value if gamma_block is None: calc.cell.species_gamma = add_to_castep_block( gamma_block, mu_symbol, constants.m_gamma, 'gamma') mass_block = calc.cell.species_mass.value calc.cell.species_mass = add_to_castep_block( mass_block, mu_symbol, constants.m_mu_amu, 'mass') # Now assign the k-points k_points_param = self.params.get('k_points_grid') if k_points_param is not None: calc.cell.kpoint_mp_grid = list_to_string(k_points_param) else: if calc.cell.kpoint_mp_grid is None: calc.cell.kpoint_mp_grid = list_to_string([1, 1, 1]) # Read the parameters pfile = self.params.get('castep_param', None) if pfile is not None: with silence_stdio(): calc.param = read_param(self.params['castep_param']).param self._calc = calc if calc_type == "MAGRES": calc = self._create_hfine_castep_calculator() elif calc_type == "GEOM_OPT": calc = self._create_geom_opt_castep_calculator() return self._calc
def _create_hfine_castep_calculator(self): """Update calculator to contain all the necessary parameters for a hyperfine calculation.""" # Remove settings for geom_opt calculator: self._calc.param.geom_max_iter = None self._calc.param.geom_force_tol = None self._calc.param.max_scf_cycles = None self._calc.param.write_cell_structure = None self._calc.param.charge = None self._calc.cell.fix_all_cell = None pfile = self.params.get('castep_param', None) if pfile is not None: with silence_stdio(): self._calc.param = read_param( self.params['castep_param']).param self._calc.param.task = 'Magres' self._calc.param.magres_task = 'Hyperfine' return self._calc
def create_muairss_castep_calculator(a, params={}, calc=None): """Create a calculator containing all the necessary parameters for a geometry optimization.""" if not isinstance(calc, Castep): calc = Castep() else: calc = deepcopy(calc) musym = params.get('mu_symbol', 'H:mu') # Start by ensuring that the muon mass and gyromagnetic ratios are included mass_block = calc.cell.species_mass.value calc.cell.species_mass = add_to_castep_block(mass_block, musym, cnst.m_mu_amu, 'mass') gamma_block = calc.cell.species_gamma.value calc.cell.species_gamma = add_to_castep_block(gamma_block, musym, 851586494.1, 'gamma') # Now assign the k-points calc.cell.kpoint_mp_grid = list_to_string( params.get('k_points_grid', [1, 1, 1])) calc.cell.fix_all_cell = True # Necessary for older CASTEP versions calc.param.charge = params.get('charged', False)*1.0 # Read the parameters pfile = params.get('castep_param', None) if pfile is not None: calc.param = read_param(params['castep_param']).param calc.param.task = 'GeometryOptimization' calc.param.geom_max_iter = params.get('geom_steps', 30) calc.param.geom_force_tol = params.get('geom_force_tol', 0.05) calc.param.max_scf_cycles = params.get('max_scc_steps', 30) return calc
def convert_single_structure(gen_file, param_file, directory="."): atoms = io.read(gen_file) params = load_input_file(param_file) # Muon mass and gyromagnetic ratio mass_block = 'AMU\n{0} 0.1138' gamma_block = 'radsectesla\n{0} 851586494.1' ccalc = Castep(castep_command=params['castep_command']) ccalc.cell.kpoint_mp_grid.value = list_to_string(params['k_points_grid']) ccalc.cell.species_mass = mass_block.format( params['mu_symbol']).split('\n') ccalc.cell.species_gamma = gamma_block.format( params['mu_symbol']).split('\n') ccalc.cell.fix_all_cell = True # To make sure for older CASTEP versions atoms.set_calculator(ccalc) symbols = atoms.get_chemical_symbols() symbols[-1] = params['mu_symbol'] atoms.set_array('castep_custom_species', np.array(symbols)) name = "{}.cell".format(params['name']) cell_file = os.path.join(directory, name) io.write(cell_file, atoms) # Param file? if params['castep_param'] is not None: p = read_param(params['castep_param']).param # Set up task and geometry optimization steps p.task.value = 'GeometryOptimization' p.geom_max_iter.value = params['geom_steps'] p.geom_force_tol.value = params['geom_force_tol'] param_file = os.path.join(directory, "{}.param".format(params['name'])) write_param(param_file, p, force_write=True)
def main(seedname, cmdline_task): seedpath, basename = os.path.split(seedname) utils.check_pyversion() print(__intromsg__) print('Reading {0}.conv'.format(seedname)) try: with open('{0}.conv'.format(seedname)) as f: convpars = parse_convfile(f.read()) except IOError: utils.warn('.conv file not found - using default parameters') convpars = parse_convfile() task = cmdline_task if cmdline_task is not None else convpars['ctsk'] # Now open the base cell and param files cname = '{0}.cell'.format(seedname) print('Reading ' + cname) # Necessary because of ASE's annoying messages... cfile = read_castep_cell(open(cname), calculator_args={'keyword_tolerance': 3}) pname = '{0}.param'.format(seedname) print('Reading ' + pname) try: read_param(pname, calc=cfile.calc) except FileNotFoundError: print('File {0} not found, skipping'.format(pname)) print('') # Now go for clearing if task == 'clear': to_del = [basename + f for f in [_in_dir, _out_dir, _json_file]] print('The following files and folders will be removed:\n\t' + '\n\t'.join(to_del)) ans = utils.safe_input('Continue (y/N)? ') if ans.lower() == 'y': for f in to_del: if not os.path.exists(f): continue try: os.remove(f) except OSError: shutil.rmtree(f) return # Strip the files cfile.calc.param.task = 'SinglePoint' cfile.calc.param.calculate_stress = convpars['cnvstr'] # Clean up all references to kpoints kclean = [ 'kpoints_mp_grid', 'kpoint_mp_grid', 'kpoints_mp_spacing', 'kpoint_mp_spacing', 'kpoints_list', 'kpoint_list' ] # These, clean up only in the presence of the relevant option if convpars['gamma']: kclean += ['kpoints_mp_offset', 'kpoint_mp_offset'] for k in kclean: cfile.calc.cell.__setattr__(k, None) # Get the kpoint basis invcell = cfile.get_reciprocal_cell() kpnbase = np.linalg.norm(invcell, axis=1) kpnbase = kpnbase / min(kpnbase) # Convergence ranges? convranges = make_ranges(convpars, kpnbase) # Ask for confirmation if task in ('input', 'inputrun', 'all'): try: os.mkdir(basename + _in_dir) except OSError: utils.warn('Input directory existing - some files could be ' 'overwritten.') ans = utils.safe_input('Continue (y/N)? ') if ans.lower() != 'y': return if task in ('output', 'all'): try: os.mkdir(basename + _out_dir) except OSError: utils.warn('Output directory existing - some files could be ' 'overwritten.') ans = utils.safe_input('Continue (y/N)? ') if ans.lower() != 'y': return # The Worktree object is useful for a number of things in all tasks wtree = Worktree(basename, convpars, convranges) ### PHASE 1: Input ### if task in ('input', 'inputrun', 'all'): # Now look for pseudopotentials find_pspots(cfile, basename, seedpath) add_castepopts(cfile, convpars['c8plus']) # If required, rattle the atoms if convpars['displ'] != 0: cfile.rattle(abs(convpars['displ'])) cfile.calc.cell.symmetry_generate = None cfile.calc.cell.symmetry_ops = None wtree.write(cfile) ### PHASE 2: Running ### if task in ('inputrun', 'all'): # Not waiting only makes sense for inputrun wait = convpars['jwait'] or (task == 'all') wtree.run(convpars['rcmd'], wait) ### PHASE 3: Output processing ### if task in ('output', 'all'): data_curves = wtree.read_data() print('Writing output to ' + basename + _out_dir) write_dat(basename, data_curves, basename + _out_dir) write_report(basename, data_curves, convpars['nrgtol'], convpars['fortol'], convpars['strtol'], basename + _out_dir) if convpars['outp'] == 'gnuplot': gp_plot(basename, data_curves, basename + _out_dir) elif convpars['outp'] == 'grace': agr_plot(basename, data_curves, basename + _out_dir)
def testCASTEP(self): try: yaml_file = os.path.join(_TESTDATA_DIR, "Si2-muairss-castep.yaml") cell_file = os.path.join(_TESTDATA_DIR, "Si2.cell") param_file = os.path.join(_TESTDATA_DIR, "Si2.param") input_params = load_input_file(yaml_file, MuAirssSchema) with silence_stdio(True, True): castep_param = read_param(param_file).param # Run Muairss write: sys.argv[1:] = ["-tw", cell_file, yaml_file] os.chdir(_TESTDATA_DIR) run_muairss() # Check all folders contain a yaml file for (rootDir, subDirs, files) in os.walk("muon-airss-out-castep/castep/"): for s in subDirs: expected_file = os.path.join( "muon-airss-out-castep/castep/" + s, s + ".cell" ) script_file = input_params["script_file"] if script_file is not None: expected_script = os.path.join( "muon-airss-out-castep/castep/" + s, "script.sh" ) self.assertTrue(os.path.exists(expected_script)) self.assertTrue(os.path.exists(expected_file)) with silence_stdio(): atoms = io.read(expected_file) self.assertEqual( atoms.calc.cell.kpoint_mp_grid.value, list_to_string(input_params["k_points_grid"]), ) expected_param_file = os.path.join( "muon-airss-out-castep/castep/" + s, s + ".param" ) self.assertTrue(os.path.exists(expected_param_file)) with silence_stdio(): output_castep_param = read_param(expected_param_file).param self.assertEqual( output_castep_param.cut_off_energy, castep_param.cut_off_energy, ) self.assertEqual( output_castep_param.elec_energy_tol, castep_param.elec_energy_tol, ) # below test didn't work as cell positions get rounded... # equal = atoms.cell == input_atoms.cell # self.assertTrue(equal.all()) yaml_file = os.path.join(_TESTDATA_DIR, "Si2-muairss-castep-read.yaml") sys.argv[1:] = [cell_file, yaml_file] run_muairss() self.assertTrue(os.path.exists("Si2_clusters.txt")) self.assertTrue(os.path.exists("Si2_Si2_castep_clusters.dat")) # Test clustering_write_input has produced files we expect: self.assertTrue(os.path.exists("Si2_clusters")) calc_folder = "Si2_clusters/castep/" for (rootDir, subDirs, files) in os.walk(calc_folder): for s in subDirs: expected_file = os.path.join(calc_folder + s, s + ".cell") self.assertTrue(os.path.exists(expected_file)) with silence_stdio(): atoms = io.read(expected_file) self.assertEqual( atoms.calc.cell.kpoint_mp_grid.value, list_to_string(input_params["k_points_grid"]), ) expected_param_file = os.path.join(calc_folder + s, s + ".param") self.assertTrue(os.path.exists(expected_param_file)) with silence_stdio(): output_castep_param = read_param(expected_param_file).param self.assertEqual( output_castep_param.cut_off_energy, castep_param.cut_off_energy, ) self.assertEqual( output_castep_param.elec_energy_tol, castep_param.elec_energy_tol, ) finally: # Remove all created files and folders _clean_testdata_dir()
def test_write(self): # read in cell file to get atom try: input_folder = _TESTDATA_DIR + "/Si2" output_folder = os.path.join(_TESTDATA_DIR, "test_save") os.mkdir(output_folder) os.chdir(input_folder) yaml_file = os.path.join(input_folder, "Si2-muairss-castep.yaml") cell_file = os.path.join(input_folder, "Si2.cell") param_file = os.path.join(input_folder, "Si2.param") input_params = load_input_file(yaml_file, MuAirssSchema) with silence_stdio(): castep_param = read_param(param_file).param atoms = io.read(cell_file) # test writing geom_opt output reader = ReadWriteCastep(params=input_params) reader.write( atoms, output_folder, sname="Si2_geom_opt", calc_type="GEOM_OPT", ) reader.write(atoms, output_folder, sname="Si2_magres", calc_type="MAGRES") # # read back in and check that atom locations are preserved with silence_stdio(): geom_opt_atoms = io.read( os.path.join(output_folder, "Si2_geom_opt.cell") ) magres_atoms = io.read(os.path.join(output_folder, "Si2_magres.cell")) equal = atoms.positions == geom_opt_atoms.positions # self.assertTrue(equal.all()) # is not true due to to rounding equal = geom_opt_atoms.positions == magres_atoms.positions self.assertTrue(equal.all()) self.assertEqual( geom_opt_atoms.calc.cell.kpoint_mp_grid.value, list_to_string(input_params["k_points_grid"]), ) self.assertEqual( magres_atoms.calc.cell.kpoint_mp_grid.value, list_to_string(input_params["k_points_grid"]), ) # Test if parameters file have correct tasks: with silence_stdio(): geom_params = read_param( os.path.join(output_folder, "Si2_geom_opt.param") ).param magres_params = read_param( os.path.join(output_folder, "Si2_magres.param") ).param self.assertEqual(geom_params.task.value, "GeometryOptimization") self.assertEqual(magres_params.task.value, "Magres") self.assertEqual(magres_params.magres_task.value, "Hyperfine") # These are only set in the param file only so should equal # the value in the param file: self.assertEqual(geom_params.geom_max_iter, castep_param.geom_max_iter) self.assertEqual(geom_params.cut_off_energy, castep_param.cut_off_energy) self.assertEqual(geom_params.elec_energy_tol, castep_param.elec_energy_tol) # This is set in the input yaml and param file so should equal # the value in the yaml file: self.assertEqual( geom_params.geom_force_tol.value, str(input_params["geom_force_tol"]), ) self.assertEqual(magres_params.cut_off_energy, castep_param.cut_off_energy) self.assertEqual( magres_params.elec_energy_tol, castep_param.elec_energy_tol ) finally: shutil.rmtree(output_folder)