Пример #1
0
def read_geometry_gen(filename):
    rf = open(filename, 'r')
    line = rf.readline()
    natom = int(line.split()[0])
    kind = line.split()[1].strip()
    if kind in ['S', 'F']:
        periodic = True
    elif kind == 'C':
        periodic = False
    else:
        raise ValueError('Wrong type of geometry' + kind + ". Should be ('F', 'S' or 'C')")
    species = rf.readline().split()
    coords = np.zeros((natom, 3))
    symbols = []
    for i in range(natom):
        line = rf.readline()
        coords[i, :] = np.array([float(x) for x in line.split()[2:]])
        # The indices for atoms on a gen file are in the second col [1] and start in 1
        symbols.append(species[int(line.split()[1]) - 1])
    if periodic:
        line = rf.readline()
        coords_origin = np.array(line.split())
        cell = np.zeros((3, 3))
        for i in range(3):
            line = rf.readline()
            cell[i, :] = np.array([float(x) for x in line.split()])

    if kind == 'F':
        return Structure(symbols=symbols, cell=cell, reduced=coords, periodicity=True)
    elif kind == 'S':
        return Structure(symbols=symbols, cell=cell, positions=coords, periodicity=True)
    elif kind == 'C':
        return Structure(symbols=symbols, positions=coords, periodicity=False)
Пример #2
0
    def cross(self, ids):
        if len(ids) != 2:
            raise ValueError("Crossing only implemented between two clusters")

        entry0 = self.get_entry(ids[0])
        entry1 = self.get_entry(ids[1])

        pos0 = np.array(entry0['structure']['positions']).reshape((-1, 3))
        pos1 = np.array(entry1['structure']['positions']).reshape((-1, 3))

        cut = np.random.randint(1, len(pos0))

        new_pos0 = np.concatenate((pos0[:cut], pos1[cut:]))
        new_pos1 = np.concatenate((pos1[:cut], pos0[cut:]))

        new_structure = Structure(positions=new_pos0,
                                  symbols=entry0['structure']['symbols'],
                                  periodicity=False)
        entry_id = self.new_entry(structure=new_structure)
        new_structure = Structure(positions=new_pos1,
                                  symbols=entry0['structure']['symbols'],
                                  periodicity=False)
        entry_jd = self.new_entry(structure=new_structure)

        return entry_id, entry_jd
Пример #3
0
    def get_structure(self):

        natoms = self.get('NumberOfAtoms')
        nspecies = self.get('NumberOfSpecies')
        chemspecies = self.get('block+ChemicalSpeciesLabel')

        #get lattice constant
        lattice_constant = self.get('LatticeConstant')[0]

        #dot with lattice constant to scale
        cell = np.array(self.get('block+LatticeVectors'),
                        dtype=float) * float(lattice_constant)

        positions = []  #np.zeros(natoms)
        symbols = natoms * [None]

        if self.has_variable('AtomicCoordinatesFormat'):
            atomic_format = self.get('AtomicCoordinatesFormat')
        else:
            atomic_format = 'NotScaledCartesianBohr'

        atomic_coords = self.get('block+AtomicCoordinatesAndAtomicSpecies')

        # index = 0
        # for iline in atomic_coords:
        #     positions[index] = np.array(iline[:3])
        #     for i in chemspecies:
        #         if i[0] == iline[-1]:
        #             symbol = atomic_symbol(i[1])
        #     symbols[index] = symbol
        # index += 1

        #modified a bit
        index = 0
        for iline in atomic_coords:
            positions.append(
                np.array(iline[:3])
            )  #since we can't set an array element with a sequence in np
            symbols[index] = iline[-1]
            index += 1

        if atomic_format in ['Fractional', 'ScaledByLatticeVectors']:
            return Structure(symbols=symbols,
                             reduced=positions,
                             cell=cell,
                             periodicity=True)
        elif atomic_format in ['Bohr', 'NotScaledCartesianBohr']:
            return Structure(symbols=symbols,
                             positions=positions,
                             cell=cell,
                             periodicity=True)
        elif atomic_format in ['Ang', 'NotScaledCartesianAng']:
            return Structure(symbols=symbols,
                             positions=positions,
                             cell=cell,
                             periodicity=True)
    def add_random(self, random_probability=0.3):
        """
        Add one random structure to the population
        """
        entry_id = None
        structure = Structure()
        if self.composition is None:
            raise ValueError('No composition associated to this population')
        factor = np.random.randint(self.min_comp_mult, self.max_comp_mult + 1)
        comp = self.composition.composition.copy()
        # print("Initial composition: %s" % comp)
        # print(Composition(comp))
        # print(Composition(comp).symbols)
        for i in comp:
            comp[i] *= factor
        new_comp = Composition(comp)

        while True:
            rnd = random.random()
            condition = {'structure.nspecies': new_comp.nspecies,
                         'structure.natom': new_comp.natom}
            if self.pcdb_source is None:
                rnd = 0
            elif len(self.sources[factor]) == 0:
                rnd = 0
            if self.pcdb_source is None or rnd < random_probability:
                pcm_log.debug('Random Structure')
                structure = Structure.random_cell(new_comp, method='stretching', stabilization_number=5, nparal=5,
                                                  periodic=True)
                break
            else:
                pcm_log.debug('From source')
                entry_id = self.sources[factor][np.random.randint(0, len(self.sources[factor]))]
                structure = self.pcdb_source.get_structure(entry_id)
                print("chosen structure from database =", structure)
                sym = CrystalSymmetry(structure)

                scale_factor = float(np.max(covalent_radius(new_comp.species)) /
                                     np.max(covalent_radius(structure.species)))
                reduce_scale = scale_factor ** (1. / 3)    # WIH
                msg = 'Mult: %d natom: %d From source: %s Spacegroup: %d Scaling: %7.3f'
                print(msg % (factor, structure.natom, structure.formula, sym.number(), scale_factor))
                # structure.set_cell(np.dot(scale_factor * np.eye(3), structure.cell)) # WIH
                structure.set_cell(np.dot(reduce_scale * np.eye(3), structure.cell))  # WIH
                print("symbols before change = ", structure.symbols)
                structure.symbols = new_comp.symbols
                print("symbols after change = ", structure.symbols)
                self.sources[factor].remove(entry_id)
                break

        return self.new_entry(structure), entry_id
Пример #5
0
    def add_random(self, random_probability=0.3):
        """
        Add one random structure to the population
        """
        structure = Structure()
        if self.composition is None:
            raise ValueError('No composition associated to this population')
        comp = self.composition.composition.copy()
        rnd = random.random()
        natom_limit = self.max_comp_mult * self.composition.natom / self.composition.gcd
        condition = {'structure.nspecies': self.composition.nspecies,
                     'structure.natom': {'$lte': natom_limit}}

        if self.pcdb_source is None or self.pcdb_source.entries.find(condition).count() <= len(self.source_blacklist):
            rnd = 0
        origin = None

        if self.pcdb_source is None or rnd < random_probability or self.composition.nspecies > 1:
            pcm_log.debug('Random Structure')
            factor = np.random.randint(self.min_comp_mult, self.max_comp_mult + 1)
            for i in comp:
                comp[i] *= factor
            structure = Structure.random_cell(comp, method='stretching', stabilization_number=5, nparal=5,
                                              periodic=True)
        else:
            pcm_log.debug('From source')
            while True:

                entry = None
                condition['properties.spacegroup'] = random.randint(1, 230)
                print('Trying', condition['properties.spacegroup'])
                for ientry in self.pcdb_source.entries.find(condition):
                    if ientry['_id'] not in self.source_blacklist:
                        entry = ientry
                        break
                if entry is not None:
                    origin = entry['_id']
                    structure = self.pcdb_source.get_structure(entry['_id'])
                    factor = covalent_radius(self.composition.species[0]) / covalent_radius(structure.species[0])
                    print('From source: %s Spacegroup: %d Scaling: %7.3f' % (structure.formula,
                                                                             entry['properties']['spacegroup'],
                                                                             factor))
                    structure.set_cell(np.dot(factor * np.eye(3), structure.cell))
                    structure.symbols = structure.natom * self.composition.species
                    self.source_blacklist.append(entry['_id'])
                    break

        return self.new_entry(structure), origin
Пример #6
0
def Si():
    return Structure(symbols=['Si', 'Si'],
                     cell=[[0.0, 2.733099,
                            2.733099], [2.733099, 0.0, 2.733099],
                           [2.733099, 2.733099, 0.0]],
                     reduced=[[0.875, 0.875, 0.875], [0.125, 0.125, 0.125]],
                     periodicity=True)
Пример #7
0
 def get_structure(self, entry_id):
     entry = self.get_entry(entry_id)
     if 'structure' not in entry:
         raise ValueError('structure is not present on %s' % entry_id)
     if entry['structure'] is None:
         raise ValueError('structure is None for %s' % entry_id)
     return Structure.from_dict(entry['structure'])
Пример #8
0
def CaTiO3():
    return Structure(symbols=['Ca', 'Ti', 'O', 'O', 'O'],
                     cell=3.885326,
                     reduced=[[0.0, 0.0, 0.0], [0.5, 0.5,
                                                0.5], [0.0, 0.5, 0.5],
                              [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]],
                     periodicity=True)
Пример #9
0
    def find_composition(self, composition):
        """
        Search for structures with a pseudo-composition expressed as dictionary
        where symbols that are not atomic symbols such as A or X can be used to
        represent arbitrary atoms

        :return: (list) List of ids for all the structures that fulfill
                 the conditions
        """
        ret = []
        for entry in self.entries.find({'nspecies': len(composition)}):
            comp = Structure.from_dict(entry['structure']).get_composition()
            valid = True
            if sum(comp.composition.values()) % sum(composition.values()) != 0:
                valid = False
            vect1 = np.float64(np.sort(comp.composition.values()))
            vect2 = np.float64(np.sort(composition.values()))
            v12 = vect1 / vect2
            if not np.all(v12 == v12[0]):
                valid = False
            for ispecie in composition:
                if ispecie in atomic_symbols and ispecie not in comp.species:
                    valid = False

            if valid:
                print(comp.composition)
                ret.append(entry['_id'])
        return ret
Пример #10
0
 def get_structure(self, entry_id):
     entry = self.get_entry(entry_id)
     if 'structure' not in entry:
         raise ValueError('structure is not present on %s' % entry_id)
     if entry['structure'] is None:
         raise ValueError('structure is None for %s' % entry_id)
     return Structure.from_dict(entry['structure'])
Пример #11
0
def pymatgen2pychemia(pmg_struct):
    """
    Converts a pymatgen structure object into a pychemia
    structure object

    :param pmg_struct: (pymatgen.Structure) Structure from pymatgen that will be converted
    :return:
    """

    # if not pmg_struct.is_ordered:
    #     return None

    cell = pmg_struct.lattice_vectors()
    reduced = np.array([])
    sites = []
    symbols = []
    occupancies = []
    index = 0
    for i in pmg_struct:
        for j in i.species_and_occu:
            symbols.append(j.symbol)
            occupancies.append(i.species_and_occu[j])
            sites.append(index)
        reduced = np.concatenate((reduced, i.frac_coords))
        index += 1

    reduced.reshape((-1, 3))
    return Structure(cell=cell,
                     reduced=reduced,
                     symbols=symbols,
                     sites=sites,
                     occupancies=occupancies)
Пример #12
0
def MgB2():
    return Structure(symbols=['Mg', 'B', 'B'],
                     cell=[[3.075169, 0.0, 0.0], [-1.537585, 2.663175, 0.0],
                           [0.0, 0.0, 3.527008]],
                     reduced=[[0.0, 0.0, 0.0], [0.333333, 0.666667, 0.5],
                              [0.666667, 0.333333, 0.5]],
                     periodicity=True)
Пример #13
0
    def find_composition(self, composition):
        """
        Search for structures with a pseudo-composition expressed as dictionary
        where symbols that are not atomic symbols such as A or X can be used to
        represent arbitrary atoms

        :return: (list) List of ids for all the structures that fulfill
                 the conditions
        """
        ret = []
        for entry in self.entries.find({'nspecies': len(composition)}):
            comp = Structure.from_dict(entry['structure']).get_composition()
            valid = True
            if sum(comp.composition.values()) % sum(composition.values()) != 0:
                valid = False
            vect1 = np.float64(np.sort(comp.composition.values()))
            vect2 = np.float64(np.sort(composition.values()))
            v12 = vect1 / vect2
            if not np.all(v12 == v12[0]):
                valid = False
            for ispecie in composition:
                if ispecie in atomic_symbols and ispecie not in comp.species:
                    valid = False

            if valid:
                print(comp.composition)
                ret.append(entry['_id'])
        return ret
Пример #14
0
    def get_structure(self, entry_id):
        """
        Return the structure in the entry with id 'entry_id'

        :rtype : Structure
        """
        entry = self.entries.find_one({'_id': entry_id})
        return Structure.from_dict(entry['structure'])
Пример #15
0
    def get_structure(self, entry_id):
        """
        Return the structure in the entry with id 'entry_id'

        :rtype : Structure
        """
        entry = self.entries.find_one({'_id': entry_id})
        return Structure.from_dict(entry['structure'])
Пример #16
0
    def get_structure(self, entry_id, location):
        """
        Return the structure in the entry with id 'entry_id'

        :rtype : Structure
        """
        assert (location in ['input', 'output'])
        entry = self.db.pychemia_entries.find_one({'_id': entry_id}, {location: 1})
        return Structure.from_dict(entry[location]['structure'])
Пример #17
0
 def fromdict(self, vj_dict):
     self.structure = Structure.from_dict(vj_dict['structure'])
     self.potcar_pspfiles = vj_dict['potcar_pspfiles']
     self.potcar_setup = vj_dict['potcar_setup']
     self.workdir = vj_dict['workdir']
     self.input_variables = InputVariables(variables=vj_dict['variables'])
     self.kpoints = vj_dict['kpoints']
     self.poscar_setup = vj_dict['poscar_setup']
     self.potcar_pspdir = vj_dict['potcar_pspdir']
Пример #18
0
def NaCl():
    return Structure(symbols=['Na', 'Na', 'Na', 'Na', 'Cl', 'Cl', 'Cl', 'Cl'],
                     cell=5.690301,
                     reduced=[[0.0, 0.0, 0.0], [0.0, 0.5,
                                                0.5], [0.5, 0.0, 0.5],
                              [0.5, 0.5, 0.0], [0.5, 0.5,
                                                0.5], [0.5, 0.0, 0.0],
                              [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]],
                     periodicity=True)
Пример #19
0
def MgO():
    return Structure(symbols=['Mg', 'Mg', 'Mg', 'Mg', 'O', 'O', 'O', 'O'],
                     cell=4.255556,
                     reduced=[[0.0, 0.0, 0.0], [0.0, 0.5,
                                                0.5], [0.5, 0.0, 0.5],
                              [0.5, 0.5, 0.0], [0.5, 0.5,
                                                0.5], [0.5, 0.0, 0.0],
                              [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]],
                     periodicity=True)
Пример #20
0
def LiF():
    return Structure(symbols=['Li', 'Li', 'Li', 'Li', 'F', 'F', 'F', 'F'],
                     cell=4.061103,
                     reduced=[[0.0, 0.0, 0.0], [0.0, 0.5,
                                                0.5], [0.5, 0.0, 0.5],
                              [0.5, 0.5, 0.0], [0.5, 0.5,
                                                0.5], [0.5, 0.0, 0.0],
                              [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]],
                     periodicity=True)
Пример #21
0
    def get_structure(self, entry_id, location):
        """
        Return the structure in the entry with id 'entry_id'

        :rtype : Structure
        """
        assert (location in ['input', 'output'])
        entry = self.db.pychemia_entries.find_one({'_id': entry_id}, {location: 1})
        return Structure.from_dict(entry[location]['structure'])
Пример #22
0
def SnO2():
    return Structure(symbols=['Sn', 'Sn', 'O', 'O', 'O', 'O'],
                     cell=[4.830595, 4.830595, 3.243083],
                     reduced=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5],
                              [0.306537, 0.306537, 0.0],
                              [0.693463, 0.693463, 0.0],
                              [0.193463, 0.806537, 0.5],
                              [0.806537, 0.193463, 0.5]],
                     periodicity=True)
Пример #23
0
def SiO2():
    return Structure(symbols=['Si', 'Si', 'O', 'O', 'O', 'O'],
                     cell=[4.044448, 4.044448, 2.621168],
                     reduced=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5],
                              [0.303008, 0.303008, 0.0],
                              [0.696992, 0.696992, 0.0],
                              [0.196992, 0.803008, 0.5],
                              [0.803008, 0.196992, 0.5]],
                     periodicity=True)
Пример #24
0
 def fromdict(self, vj_dict):
     self.structure = Structure.from_dict(vj_dict['structure'])
     self.potcar_pspfiles = vj_dict['potcar_pspfiles']
     self.potcar_setup = vj_dict['potcar_setup']
     self.workdir = vj_dict['workdir']
     self.input_variables = VaspInput(variables=vj_dict['variables'])
     self.kpoints = vj_dict['kpoints']
     self.poscar_setup = vj_dict['poscar_setup']
     self.potcar_pspdir = vj_dict['potcar_pspdir']
Пример #25
0
def ZnO():
    return Structure(symbols=['Zn', 'Zn', 'O', 'O'],
                     cell=[[3.287169, 0.0, 0.0], [-1.643584, 2.846772, 0.0],
                           [0.0, 0.0, 5.304577]],
                     reduced=[[0.333333, 0.666667, 0.999681],
                              [0.666667, 0.333333, 0.499681],
                              [0.333333, 0.666667, 0.378762],
                              [0.666667, 0.333333, 0.878762]],
                     periodicity=True)
Пример #26
0
    def add_random(self):
        """
        Add one random structure to the population
        """
        if self.composition is None:
            raise ValueError('No composition associated to this population')
        comp = self.composition.composition.copy()
        structure = Structure.random_cluster(composition=comp)

        return self.new_entry(structure), None
Пример #27
0
    def add_random(self):
        """
        Add one random structure to the population
        """
        if self.composition is None:
            raise ValueError('No composition associated to this population')
        comp = self.composition.composition.copy()
        structure = Structure.random_cluster(composition=comp)

        return self.new_entry(structure), None
Пример #28
0
    def move_random(self, entry_id, factor=0.2, in_place=False, kind='move'):

        entry = self.get_entry(entry_id)
        pos = np.array(entry['structure']['positions']).reshape((-1, 3))
        # Unit Vectors
        uv = unit_vectors(2 * np.random.rand(*pos.shape) - 1)
        new_pos = generic_serializer(pos + factor * uv)

        structure = Structure(positions=new_pos,
                              symbols=entry['structure']['symbols'],
                              periodicity=False)

        if in_place:
            self.update_properties(entry_id=entry_id, new_properties={})
            return self.set_structure(entry_id, structure)
        else:
            structure = Structure(positions=new_pos,
                                  symbols=entry['structure']['symbols'],
                                  periodicity=False)
            return self.new_entry(structure, active=False)
Пример #29
0
 def replace_failed(self):
     for entry in self.entries.find({'status.relaxation': 'failed'}):
         st = self.get_structure(entry['_id'])
         comp = st.composition
         new_structure = Structure.random_cell(comp)
         self.entries.update({'_id': entry['_id']}, {'$unset': {'status.relaxation': 1,
                                                                'status.target_forces': 1,
                                                                'properties.energy': 1,
                                                                'properties.forces': 1,
                                                                'properties.stress': 1}})
         self.update(entry['_id'], structure=new_structure)
Пример #30
0
 def replace_failed(self):
     for entry in self.entries.find({'status.relaxation': 'failed'}):
         st = self.get_structure(entry['_id'])
         comp = st.composition
         new_structure = Structure.random_cell(comp)
         self.entries.update({'_id': entry['_id']}, {'$unset': {'status.relaxation': 1,
                                                                'status.target_forces': 1,
                                                                'properties.energy': 1,
                                                                'properties.forces': 1,
                                                                'properties.stress': 1}})
         self.update(entry['_id'], structure=new_structure)
Пример #31
0
def TiO2_anatase():
    return Structure(symbols=[
        'Ti', 'Ti', 'Ti', 'Ti', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'
    ],
                     cell=[3.826325, 3.826325, 9.657949],
                     reduced=[[0.5, 0.75, 0.875], [0.5, 0.25, 0.125],
                              [0.0, 0.25, 0.375], [0.0, 0.75, 0.625],
                              [0.0, 0.25, 0.167606], [0.0, 0.75, 0.832394],
                              [0.5, 0.25, 0.917606], [0.5, 0.75, 0.082394],
                              [0.5, 0.75, 0.667606], [0.5, 0.25, 0.332394],
                              [0.0, 0.75, 0.417606], [0.0, 0.25, 0.582394]],
                     periodicity=True)
Пример #32
0
    def add_random(self, random_probability=0.3):
        """
        Add one random structure to the population
        """
        entry_id = None
        structure = Structure()
        if self.composition is None:
            raise ValueError('No composition associated to this population')
        factor = np.random.randint(self.min_comp_mult, self.max_comp_mult + 1)
        comp = self.composition.composition.copy()
        #print("Initial composition: %s" % comp)
        #print(Composition(comp))
        #print(Composition(comp).symbols)
        for i in comp:
            comp[i] *= factor
        new_comp = Composition(comp)

        while True:
            rnd = random.random()
            condition = {
                'structure.nspecies': new_comp.nspecies,
                'structure.natom': new_comp.natom
            }
            if self.pcdb_source is None:
                rnd = 0
            elif len(self.sources[factor]) == 0:
                rnd = 0
            if self.pcdb_source is None or rnd < random_probability:
                pcm_log.debug('Random Structure')
                structure = Structure.random_cell(new_comp,
                                                  method='stretching',
                                                  stabilization_number=5,
                                                  nparal=5,
                                                  periodic=True)
                break
            else:
                pcm_log.debug('From source')
                entry_id = self.sources[factor][np.random.randint(
                    0, len(self.sources[factor]))]
                structure = self.pcdb_source.get_structure(entry_id)
                print("chosen structure from database =", structure)
                sym = CrystalSymmetry(structure)

                scale_factor = float(
                    np.max(covalent_radius(new_comp.species)) /
                    np.max(covalent_radius(structure.species)))
                reduce_scale = scale_factor**(1. / 3)  # WIH
                msg = 'Mult: %d natom: %d From source: %s Spacegroup: %d Scaling: %7.3f'
                print(msg % (factor, structure.natom, structure.formula,
                             sym.number(), scale_factor))
                # structure.set_cell(np.dot(scale_factor * np.eye(3), structure.cell)) # WIH
                structure.set_cell(
                    np.dot(reduce_scale * np.eye(3), structure.cell))  # WIH
                print("symbols before change = ", structure.symbols)
                structure.symbols = new_comp.symbols
                print("symbols after change = ", structure.symbols)
                self.sources[factor].remove(entry_id)
                break

        return self.new_entry(structure), entry_id
Пример #33
0
    def add_random(self, random_probability=0.3):
        """
        Add one random structure to the population
        """
        structure = Structure()
        if self.composition is None:
            raise ValueError('No composition associated to this population')
        comp = self.composition.composition.copy()
        rnd = random.random()
        natom_limit = self.max_comp_mult * self.composition.natom / self.composition.gcd
        condition = {
            'structure.nspecies': self.composition.nspecies,
            'structure.natom': {
                '$lte': natom_limit
            }
        }

        if self.pcdb_source is None or self.pcdb_source.entries.find(
                condition).count() <= len(self.source_blacklist):
            rnd = 0
        origin = None

        if self.pcdb_source is None or rnd < random_probability or self.composition.nspecies > 1:
            pcm_log.debug('Random Structure')
            factor = np.random.randint(self.min_comp_mult,
                                       self.max_comp_mult + 1)
            for i in comp:
                comp[i] *= factor
            structure = Structure.random_cell(comp,
                                              method='stretching',
                                              stabilization_number=5,
                                              nparal=5,
                                              periodic=True)
        else:
            pcm_log.debug('From source')
            while True:

                entry = None
                condition['properties.spacegroup'] = random.randint(1, 230)
                print('Trying', condition['properties.spacegroup'])
                for ientry in self.pcdb_source.entries.find(condition):
                    if ientry['_id'] not in self.source_blacklist:
                        entry = ientry
                        break
                if entry is not None:
                    origin = entry['_id']
                    structure = self.pcdb_source.get_structure(entry['_id'])
                    factor = covalent_radius(
                        self.composition.species[0]) / covalent_radius(
                            structure.species[0])
                    print('From source: %s Spacegroup: %d Scaling: %7.3f' %
                          (structure.formula,
                           entry['properties']['spacegroup'], factor))
                    structure.set_cell(
                        np.dot(factor * np.eye(3), structure.cell))
                    structure.symbols = structure.natom * self.composition.species
                    self.source_blacklist.append(entry['_id'])
                    break

        return self.new_entry(structure), origin
Пример #34
0
def read_geometry_bas(filename):
    rf = open(filename, 'r')

    natom = int(rf.readline())
    symbols = []
    positions = np.zeros((natom, 3))

    for i in range(natom):
        line = rf.readline().split()
        symbols.append(atomic_symbol(int(line[0])))
        positions[i] = np.array(line[1:])

    return Structure(symbols=symbols, positions=positions, periodicity=False)
Пример #35
0
def do_mixing(structure1, structure2, cut_planes1, cut_planes2, matching, match_index):
    # Getting the atoms involved in both partitions:
    dim1 = matching[match_index]['dim1']
    partition1 = get_split_sites(structure1, dim1, cut_planes1, matching[match_index]['plane_indices1'])
    dim2 = matching[match_index]['dim2']
    partition2 = get_split_sites(structure1, dim2, cut_planes2, matching[match_index]['plane_indices2'])

    index1 = matching[match_index]['plane_indices1'][0]
    index2 = matching[match_index]['plane_indices1'][1]

    reduced11 = np.array([structure1.reduced[x] for x in partition1[0]])
    reduced11[:, dim1] = (reduced11[:, dim1] - cut_planes1[dim1][index1] + 1.0) % 1.0
    reduced11[:, dim1] -= np.min(reduced11[:, dim1])
    symbols = [structure1.symbols[x] for x in partition1[0]]
    st11 = Structure(reduced=reduced11, cell=structure1.cell, symbols=symbols)

    reduced12 = np.array([structure1.reduced[x] for x in partition1[1]])
    reduced12[:, dim1] = (reduced12[:, dim1] - cut_planes1[dim1][index2] + 1.0) % 1.0
    reduced12[:, dim1] -= np.min(reduced12[:, dim1])
    symbols = [structure1.symbols[x] for x in partition1[1]]
    st12 = Structure(reduced=reduced12, cell=structure1.cell, symbols=symbols)

    index1 = matching[match_index]['plane_indices2'][0]
    index2 = matching[match_index]['plane_indices2'][1]

    reduced21 = np.array([structure2.reduced[x] for x in partition2[0]])
    reduced21[:, dim2] = (reduced21[:, dim2] - cut_planes2[dim2][index1] + 1.0) % 1.0
    reduced21[:, dim2] -= np.min(reduced21[:, dim2])
    symbols = [structure2.symbols[x] for x in partition2[0]]
    st21 = Structure(reduced=reduced21, cell=structure2.cell, symbols=symbols)

    reduced22 = np.array([structure2.reduced[x] for x in partition2[1]])
    reduced22[:, dim2] = (reduced22[:, dim2] - cut_planes2[dim2][index2] + 1.0) % 1.0
    reduced22[:, dim2] -= np.min(reduced22[:, dim2])
    symbols = [structure2.symbols[x] for x in partition2[1]]
    st22 = Structure(reduced=reduced22, cell=structure2.cell, symbols=symbols)

    return st11, st12, st21, st22
Пример #36
0
def load(filename):
    symbols = loadtxt(filename, skiprows=2, usecols=[0], dtype='|S2', ndmin=1)
    symbols = [x.decode('utf-8') for x in symbols]

    for i in range(len(symbols)):
        if symbols[i].isdigit():
            symbols[i] = atomic_symbol(int(symbols[i]))

    positions = loadtxt(filename, skiprows=2, usecols=(1, 2, 3), ndmin=2)
    natom = len(symbols)
    periodicity = 3 * [False]
    return Structure(symbols=symbols,
                     positions=positions,
                     periodicity=periodicity,
                     natom=natom)
Пример #37
0
def spglib_version():
    from pychemia import Structure
    from . import CrystalSymmetry

    # Testing version of spglib
    st = Structure(symbols=['H'])
    symm = CrystalSymmetry(st)
    ret = spg.spglib.spg.dataset(symm.transposed, symm.reduced, symm.numbers, 1e-5, -1.0)
    if type(ret[3]) is list:
        HAS_SPGLIB = False
        version = "%d.%d.%d" % spg.get_version()
        print('SPGLIB current version is %s, please install spglib > 1.9' % version)
    else:
        HAS_SPGLIB = True
    return HAS_SPGLIB
Пример #38
0
    def find_AnBm(self, specie_a=None, specie_b=None, n=1, m=1):
        """
        Search for structures with a composition expressed as AnBm
        where one and only one between A or B is fixed and the numbers
        amounts n and m are both fixed

        :param specie_a: (str) atom symbol for the first specie
        :param specie_b: (str) atom symbol for the second specie
        :param n: number of atoms for specie 'a'
        :param m: number of atoms for specie 'b'
        :return:
        :return: (list) List of ids for all the structures that fulfill
                 the conditions
        """
        if specie_a is None and specie_b is None:
            raise ValueError("Enter a specie for A or B")
        elif specie_a is not None and specie_b is not None:
            raise ValueError("Only enter A or B, not both")
        elif specie_a is not None:
            atom_fixed = specie_a
            number_fixed = n
            number_unfixed = m
            assert (specie_a in atomic_symbols)
        else:
            atom_fixed = specie_b
            number_fixed = m
            number_unfixed = n
            assert (specie_b in atomic_symbols)

        ret = []
        for entry in self.entries.find({
                'structure.nspecies': 2,
                'structure.formula': {
                    '$regex': atom_fixed
                }
        }):
            comp = Structure.from_dict(entry['structure']).get_composition()
            if atom_fixed in comp.composition and comp.composition[
                    atom_fixed] % number_fixed == 0:
                species = comp.species
                species.remove(atom_fixed)
                other_specie = species[0]
                # See if the fraction n/m is correct for A and B
                if number_unfixed * float(
                        comp.composition[atom_fixed]) == number_fixed * float(
                            comp.composition[other_specie]):
                    ret.append(entry['_id'])
        return ret
Пример #39
0
    def move(self, entry_id, entry_jd, factor=0.2, in_place=False):
        """
        Moves entry_id in the direction of entry_jd
        If in_place is True the movement occurs on the
        same address as entry_id

        :param factor:
        :param entry_id:
        :param entry_jd:
        :param in_place:
        :return:
        """
        structure_mobile = self.get_structure(entry_id)
        structure_target = self.get_structure(entry_jd)

        if structure_mobile.natom != structure_target.natom:
            # Moving structures with different number of atoms is only implemented for smaller structures moving
            # towards bigger ones by making a super-cell and only if their size is smaller that 'max_comp_mult'

            mult1 = structure_mobile.get_composition().gcd
            mult2 = structure_target.get_composition().gcd
            lcd = mult1 * mult2 / gcd(mult1, mult2)
            if lcd > self.max_comp_mult:
                # The resulting structure is bigger than the limit
                # cannot move
                if not in_place:
                    return self.new_entry(structure_mobile)
                else:
                    return entry_id

        # We will move structure1 in the direction of structure2
        match = StructureMatch(structure_target, structure_mobile)
        match.match_size()
        match.match_shape()
        match.match_atoms()
        displacements = match.reduced_displacement()

        new_reduced = match.structure2.reduced + factor * displacements
        new_cell = match.structure2.cell
        new_symbols = match.structure2.symbols
        new_structure = Structure(reduced=new_reduced,
                                  symbols=new_symbols,
                                  cell=new_cell)
        if in_place:
            return self.set_structure(entry_id, new_structure)
        else:
            return self.new_entry(new_structure, active=False)
Пример #40
0
    def find_AnBm(self, specie_a=None, specie_b=None, n=1, m=1):
        """
        Search for structures with a composition expressed as AnBm
        where one and only one between A or B is fixed and the numbers
        amounts n and m are both fixed

        :param specie_a: (str) atom symbol for the first specie
        :param specie_b: (str) atom symbol for the second specie
        :param n: number of atoms for specie 'a'
        :param m: number of atoms for specie 'b'
        :return:
        :return: (list) List of ids for all the structures that fulfill
                 the conditions
        """
        if specie_a is None and specie_b is None:
            raise ValueError("Enter a specie for A or B")
        elif specie_a is not None and specie_b is not None:
            raise ValueError("Only enter A or B, not both")
        elif specie_a is not None:
            atom_fixed = specie_a
            number_fixed = n
            number_unfixed = m
            assert (specie_a in atomic_symbols)
        else:
            atom_fixed = specie_b
            number_fixed = m
            number_unfixed = n
            assert (specie_b in atomic_symbols)

        ret = []
        for entry in self.entries.find({'nspecies': 2, 'formula': {'$regex': atom_fixed}}):
            comp = Structure.from_dict(entry['structure']).get_composition()
            if atom_fixed in comp.composition and comp.composition[atom_fixed] % number_fixed == 0:
                species = comp.species
                species.remove(atom_fixed)
                other_specie = species[0]
                # See if the fraction n/m is correct for A and B
                if number_unfixed * float(comp.composition[atom_fixed]) == number_fixed * float(
                        comp.composition[other_specie]):
                    ret.append(entry['_id'])
        return ret
Пример #41
0
def kpoint_convergence():
    st = Structure.load_json('structure.json')
    job = KPointConvergence(st)
    job.run()
    job.save_json()
Пример #42
0
 def get_structure(self, entry_id):
     entry = self.get_entry(entry_id)
     return Structure.from_dict(entry['structure'])
Пример #43
0
def worker_maise(db_settings, entry_id, workdir, target_forces, relaxator_params):

    max_ncalls = 6
    pcdb = get_database(db_settings)
    pcm_log.info('[%s]: Starting relaxation. Target forces: %7.3e' % (str(entry_id), target_forces))

    if pcdb.is_locked(entry_id):
        return
    else:
        pcdb.lock(entry_id)
    structure = pcdb.get_structure(entry_id)
    status = pcdb.get_dicts(entry_id)[2]

    if 'ncalls' in status:
        ncalls = status['ncalls'] + 1 
    else:
        ncalls = 1 

    #print('Current directory: '+os.getcwd() )
    #print('Working directory: '+workdir)
    write_poscar(structure,workdir+os.sep+'POSCAR')
    if not os.path.exists(workdir+os.sep+'setup'):
        shutil.copy2('setup', workdir)
    if not os.path.exists(workdir+os.sep+'INI'):
        os.symlink(os.getcwd()+os.sep+'INI', workdir+os.sep+'INI')
    if not os.path.exists(workdir+os.sep+'maise'):
        os.symlink(os.getcwd()+os.sep+'maise', workdir+os.sep+'maise')
    cwd=os.getcwd()
    os.chdir(workdir)
    wf=open('maise.stdout','w')
    subprocess.call(['./maise'], stdout=wf)
    wf.close()
    if os.path.isfile('OSZICAR'):
        energies=np.loadtxt('OSZICAR')
    else:
        energies=None
    if os.path.isfile('OUTCAR'):
        rf = open('OUTCAR', 'r')
        data = rf.read()
        
        pos_forces = re.findall(r'TOTAL-FORCE \(eV/Angst\)\s*-*\s*([-.\d\s]+)\s+-{2}', data)
        pos_forces = np.array([x.split() for x in pos_forces], dtype=float)

        if len(pos_forces) > 0 and len(pos_forces[-1]) % 7 == 0:
            pos_forces.shape = (len(pos_forces), -1, 7)
            forces = pos_forces[:, :, 3:6]
            positions = pos_forces[:, :, :3]
        else:
            print('Forces and Positions could not be parsed : ', pos_forces.shape)
            print('pos_forces =\n%s ' % pos_forces)
            
        str_stress=re.findall('Total([\.\d\s-]*)in',data)
        if len(str_stress)==2:
            stress = np.array([[float(y) for y in x.split()] for x in str_stress])
        str_stress=re.findall('in kB([\.\d\s-]*)energy',data)
        if len(str_stress)==2:
            stress_kB = np.array([[float(y) for y in x.split()] for x in str_stress])
    else:
        forces=None
        stress=None
        stress_kB=None

    new_structure=read_poscar('CONTCAR')
    if np.min(new_structure.distance_matrix()+np.eye(new_structure.natom))<0.23:
        print('WARNING: Structure collapse 2 atoms, creating a new random structure')
        new_structure=Structure.random_cell(new_structure.composition)
    if ncalls > max_ncalls:
        print('WARNING: Too many calls to MAISE and no relaxation succeeded, replacing structure')
        new_structure=Structure.random_cell(new_structure.composition)
        pcdb.entries.update({'_id': entry_id}, {'$set': {'status.ncalls': 0}})
    else:
        pcdb.entries.update({'_id': entry_id}, {'$set': {'status.ncalls': ncalls}})
    pcdb.update(entry_id, structure=new_structure)

    
    if energies is not None and forces is not None and stress is not None:

        te = energies[1]
        pcdb.entries.update({'_id': entry_id},
                            {'$set': {'status.relaxation': 'succeed',
                                      'status.target_forces': target_forces,
                                      'properties.initial_forces': generic_serializer(forces[0]),
                                      'properties.initial_stress': generic_serializer(stress[0]),
                                      'properties.initial_stress_kB': generic_serializer(stress_kB[0]),
                                      'properties.forces': generic_serializer(forces[1]),
                                      'properties.stress': generic_serializer(stress[1]),
                                      'properties.stress_kB': generic_serializer(stress_kB[1]),
                                      'properties.energy': te,
                                      'properties.energy_pa': te / new_structure.natom,
                                      'properties.energy_pf': te / new_structure.get_composition().gcd}})

    for ifile in ['POSCAR', 'CONTCAR', 'setup', 'OUTCAR', 'maise.stdout', 'list.dat']:
        if not os.path.exists(ifile):
            wf = open(ifile, 'w')
            wf.write('')
            wf.close()
        n=1
        while True:
           if os.path.exists(ifile+ ('_%03d' % n)):
               n+=1
           else:
               break
        os.rename(ifile,ifile+('_%03d' % n))


    pcm_log.info('[%s]: Unlocking the entry' % str(entry_id))
    pcdb.unlock(entry_id)
Пример #44
0
def worker_maise(db_settings, entry_id, workdir, relaxator_params):
    """
    Relax and return evaluate the energy of the structure stored with identifier 'entry_id'
     using the MAISE code

    :param db_settings: (dict) Dictionary of DB parameters needed to create a PyChemiaDB object
    :param entry_id: MongoDB identifier of one entry of the database created from db_settings
    :param workdir: (str) Working directory where input and output from MAISE is written
    :param relaxator_params: (dict) Arguments needed to control the relaxation using MAISE
                                Arguments are store as keys and they include:
                                'target_forces' : Used to defined the tolerance to consider one candidate as relaxed.
                                'source_dir': Directory with executable maise and directory INI
    :return:
    """
    max_ncalls = 6
    pcdb = get_database(db_settings)
    target_forces = relaxator_params['target_forces']
    source_dir = relaxator_params['source_dir']

    pcm_log.info('[%s]: Starting relaxation. Target forces: %7.3e' % (str(entry_id), target_forces))

    if pcdb.is_locked(entry_id):
        return
    else:
        pcdb.lock(entry_id)
    structure = pcdb.get_structure(entry_id)
    status = pcdb.get_dicts(entry_id)[2]

    if 'ncalls' in status and status['ncalls'] > 0:
        ncalls = status['ncalls'] + 1
        print('ncalls = ', status['ncalls'])
    else:
        ncalls = 1
    print('Verifing initial structure...')
    while np.min(structure.distance_matrix()+(np.eye(structure.natom)*5)) < 1.9:
        print('ERROR: Bad initial guess, two atoms are to close. Creating new random structure for id: %s' %
              str(entry_id))
        write_poscar(structure, workdir + os.sep + 'Fail_initial_POSCAR')  # WIH
        structure = Structure.random_cell(structure.composition)

    write_poscar(structure, workdir + os.sep + 'POSCAR')
    if not os.path.exists(workdir + os.sep + 'setup') and ncalls == 1:     # WIH
        print('First run.')  # WIH
        #   print('Verifying that everything runs smoothly') # WIH
        print(workdir + os.sep + 'setup')
        shutil.copy2(source_dir + os.sep + 'setup_1', workdir + os.sep + 'setup')   # WIH
    elif ncalls > 1:  # WIH
        shutil.copy2(source_dir + os.sep + 'setup_2', workdir + os.sep + 'setup')   # WIH
    if not os.path.exists(workdir + os.sep + 'INI'):
        os.symlink(source_dir + os.sep + 'INI', workdir + os.sep + 'INI')
    if not os.path.exists(workdir + os.sep + 'maise'):
        os.symlink(source_dir + os.sep + 'maise', workdir + os.sep + 'maise')

    # Get the Current Working Directory
    # cwd = os.getcwd()

    # Move to the actual directory where maise will run
    os.chdir(workdir)

    wf = open('maise.stdout', 'w')
    subprocess.call(['./maise'], stdout=wf)
    wf.close()

    if os.path.isfile('OSZICAR'):
        energies = np.loadtxt('OSZICAR')
    else:
        energies = None

    forces = None
    stress = None
    stress_kb = None
    if os.path.isfile('OUTCAR'):
        rf = open('OUTCAR', 'r')
        data = rf.read()

        pos_forces = re.findall(r'TOTAL-FORCE \(eV/Angst\)\s*-*\s*([-.\d\s]+)\s+-{2}', data)
        pos_forces = np.array([x.split() for x in pos_forces], dtype=float)

        if len(pos_forces) > 0 and len(pos_forces[-1]) % 7 == 0:
            pos_forces.shape = (len(pos_forces), -1, 7)
            forces = pos_forces[:, :, 3:6]
            # positions = pos_forces[:, :, :3]
        else:
            print('Forces and Positions could not be parsed : ', pos_forces.shape)
            print('pos_forces =\n%s ' % pos_forces)

        str_stress = re.findall('Total([.\d\s-]*)in', data)
        if len(str_stress) == 2:
            stress = np.array([[float(y) for y in x.split()] for x in str_stress])
        str_stress = re.findall('in kB([.\d\s-]*)energy', data)
        if len(str_stress) == 2:
            stress_kb = np.array([[float(y) for y in x.split()] for x in str_stress])

    create_new = False
    if not os.path.isfile('CONTCAR') or os.path.getsize("CONTCAR") == 0:
        create_new = True
        print('CONTCAR not found in entry: %s' % str(entry_id))
        i = 1
        while True:
            if not os.path.isfile('POSCAR-failed-%03s' % str(i)):
                os.rename('POSCAR', 'POSCAR-failed-%03s' % str(i))
                break
            else:
                i += 1
    else:
        new_structure = read_poscar('CONTCAR')
        # min_dist = np.min(new_structure.distance_matrix+np.ones((new_structure.natom,new_structure.natom)))
    min_dist = np.min(new_structure.distance_matrix()+(np.eye(new_structure.natom)*5))   # WIH
    print('Minimal distance= %8.7f' % min_dist)   # WIH

    if min_dist < 2.0:
        print('ERROR: MAISE finished with and structure with distances too close:', entry_id)  # WIH
        write_poscar(new_structure, workdir + os.sep + 'Collapsed_CONTCAR')  # WIH
        create_new = True   # WIH

    if create_new:
        new_structure = Structure.random_cell(structure.composition)
        ncalls = 0    # WIH

    if ncalls > max_ncalls:
        print('WARNING: Too many calls to MAISE and no relaxation succeeded, replacing structure: ', entry_id)    # WIH
        new_structure = Structure.random_cell(structure.composition)
        pcdb.entries.update({'_id': entry_id}, {'$set': {'status.ncalls': 0}})
        create_new = True
    else:
        pcdb.entries.update({'_id': entry_id}, {'$set': {'status.ncalls': ncalls}})
    pcdb.update(entry_id, structure=new_structure, properties={})

    # if not create_new and energies is not None and forces is not None and stress is not None:
    if energies is not None and forces is not None and stress is not None:

        te = energies[1]
        pcdb.entries.update({'_id': entry_id},
                            {'$set': {'status.relaxation': 'succeed',
                                      'status.target_forces': target_forces,
                                      'properties.initial_forces': generic_serializer(forces[0]),
                                      'properties.initial_stress': generic_serializer(stress[0]),
                                      'properties.initial_stress_kB': generic_serializer(stress_kb[0]),
                                      'properties.forces': generic_serializer(forces[1]),
                                      'properties.stress': generic_serializer(stress[1]),
                                      'properties.stress_kB': generic_serializer(stress_kb[1]),
                                      'properties.energy': te,
                                      'properties.energy_pa': te / new_structure.natom,
                                      'properties.energy_pf': te / new_structure.get_composition().gcd}})

    for ifile in ['POSCAR', 'CONTCAR', 'setup', 'OUTCAR', 'maise.stdout', 'list.dat']:
        if not os.path.exists(ifile):
            wf = open(ifile, 'w')
            wf.write('')
            wf.close()
        n = 1
        while True:
            if os.path.exists(ifile + ('_%03d' % n)):
                n += 1
            else:
                break
        os.rename(ifile, ifile+('_%03d' % n))

    pcm_log.info('[%s]: Unlocking the entry' % str(entry_id))
    pcdb.unlock(entry_id)