def test_find_match2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si'], [[0, 0, 0.1], [0, 0, 0.2]]) s2 = Structure(l, ['Si', 'Si'], [[0, 0.1, 0], [0, 0.1, -0.95]]) s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False) match = sm._strict_match(s1, s2, fu, s1_supercell=False, use_rms=True, break_on_match=False) scale_matrix = match[2] s2.make_supercell(scale_matrix) s2.translate_sites(range(len(s2)), match[3]) self.assertAlmostEqual(np.sum(s2.frac_coords), 0.3) self.assertAlmostEqual(np.sum(s2.frac_coords[:, :2]), 0)
def center_structure(structure: Structure) -> Structure: structure = structure.copy() avg_pos = np.average(structure.frac_coords, axis=0) structure.translate_sites( np.arange(0, structure.num_sites), np.array([0.5, 0.5, 0.5]) - avg_pos, frac_coords=True, to_unit_cell=True, ) return structure
def test_find_match2(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Si', 'Si'], [[0, 0, 0.1], [0, 0, 0.2]]) s2 = Structure(l, ['Si', 'Si'], [[0, 0.1, 0], [0, 0.1, -0.95]]) s1, s2, fu, s1_supercell = sm._preprocess(s1, s2, False) match = sm._strict_match(s1, s2, fu, s1_supercell=False, use_rms=True, break_on_match=False) scale_matrix = match[2] s2.make_supercell(scale_matrix) s2.translate_sites(range(len(s2)), match[3]) self.assertAlmostEqual(np.sum(s2.frac_coords) % 1, 0.3) self.assertAlmostEqual(np.sum(s2.frac_coords[:, :2]) % 1, 0)
def get_wf_surface(slabs, molecules=[], bulk_structure=None, slab_gen_params=None, vasp_cmd="vasp", db_file=None, ads_structures_params={}, add_molecules_in_box=False): """ Args: slabs (list of Slabs or Structures): slabs to calculate molecules (list of Molecules): molecules to place as adsorbates bulk_structure (Structure): bulk structure from which generate slabs after reoptimization. If supplied, workflow will begin with bulk structure optimization. slab_gen_params (dict): dictionary of slab generation parameters used to generate the slab, necessary to get the slab that corresponds to the bulk structure if in that mode ads_structures_params (dict): parameters to be supplied as kwargs to AdsorbateSiteFinder.generate_adsorption_structures add_molecules_in_box (boolean): flag to add calculation of molecule energies to the workflow db_file (string): path to database file vasp_cmd (string): vasp command Returns: Workflow """ fws, parents = [], [] if bulk_structure: vis = MVLSlabSet(bulk_structure, bulk=True) fws.append( OptimizeFW(bulk_structure, vasp_input_set=vis, vasp_cmd="vasp", db_file=db_file)) parents = fws[0] for slab in slabs: name = slab.composition.reduced_formula if getattr(slab, "miller_index", None): name += "_{}".format(slab.miller_index) fws.append( get_slab_fw(slab, bulk_structure, slab_gen_params, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, name=name + " slab optimization")) for molecule in molecules: ads_slabs = AdsorbateSiteFinder( slab).generate_adsorption_structures(molecule, **ads_structures_params) for n, ads_slab in enumerate(ads_slabs): ads_name = "{}-{} adsorbate optimization {}".format( molecule.composition.formula, name, n) fws.append( get_slab_fw(ads_slab, bulk_structure, slab_gen_params, db_file=db_file, vasp_cmd=vasp_cmd, parents=parents, name=ads_name)) if add_molecules_in_box: for molecule in molecules: # molecule in box m_struct = Structure(Lattice.cubic(10), molecule.species_and_occu, molecule.cart_coords, coords_are_cartesian=True) m_struct.translate_sites( list(range(len(m_struct))), np.array([0.5] * 3) - np.average(m_struct.frac_coords, axis=0)) vis = MVLSlabSet(m_struct) fws.append( OptimizeFW(molecule, job_type="normal", vasp_input_set=vis, db_file=db_file, vasp_cmd=vasp_cmd)) # TODO: add analysis framework return Workflow(fws, name="")