Beispiel #1
0
    def __init__(self, structure):
        """
        Creates a new StructureSymmetry object for a given structure
        This class allows interaction with spglib for several operations related
        to symmetry

        :param structure:

        Example:
        >>> import pychemia
        >>> a = 4.05
        >>> b = a/2
        >>> fcc = pychemia.Structure(symbols=['Au'], cell=[[0, b, b], [b, 0, b], [b, b, 0]], periodicity=True)
        >>> symm = pychemia.crystal.CrystalSymmetry(fcc)
        >>> symm.number()
        225
        >>> symm.symbol() == u'Fm-3m'
        True

        """
        assert structure.is_crystal
        assert structure.is_perfect
        self.structure = structure
        # Spglib"s convention for the lattice definition is the transpose of cell
        # self._transposed_cell = structure.cell.transpose().copy()
        self.spglib_lattice = generic_serializer(structure.cell.copy())
        # Spglib requires numpy floats.
        # self._transposed_cell = np.array(self._transposed_cell, dtype='double', order='C')
        # self._reduced = np.array(structure.reduced, dtype='double', order='C')
        self.spglib_positions = generic_serializer(structure.reduced)
        # Get a list of indices for each atom in structure
        # Indices starting in 1
        # self._numbers = np.array([structure.species.index(x) + 1 for x in structure.symbols], dtype='intc')
        self.spglib_numbers = [structure.species.index(x) + 1 for x in structure.symbols]
Beispiel #2
0
    def __init__(self, structure):
        """
        Creates a new StructureSymmetry object for a given structure
        This class allows interaction with spglib for several operations related
        to symmetry

        :param structure:

        Example:
        >>> import pychemia
        >>> a = 4.05
        >>> b = a/2
        >>> fcc = pychemia.Structure(symbols=['Au'], cell=[[0, b, b], [b, 0, b], [b, b, 0]], periodicity=True)
        >>> symm = pychemia.crystal.CrystalSymmetry(fcc)
        >>> symm.number()
        225
        >>> symm.symbol() == u'Fm-3m'
        True

        """
        assert structure.is_crystal
        assert structure.is_perfect
        self.structure = structure
        # Spglib"s convention for the lattice definition is the transpose of cell
        # self._transposed_cell = structure.cell.transpose().copy()
        self.spglib_lattice = generic_serializer(structure.cell.copy())
        # Spglib requires numpy floats.
        # self._transposed_cell = np.array(self._transposed_cell, dtype='double', order='C')
        # self._reduced = np.array(structure.reduced, dtype='double', order='C')
        self.spglib_positions = generic_serializer(structure.reduced)
        # Get a list of indices for each atom in structure
        # Indices starting in 1
        # self._numbers = np.array([structure.species.index(x) + 1 for x in structure.symbols], dtype='intc')
        self.spglib_numbers = [structure.species.index(x) + 1 for x in structure.symbols]
Beispiel #3
0
    def evaluate(self, imember):
        entry = self.population.get_entry(imember)
        pcm_structure = pychemia.Structure.from_dict(entry['structure'])

        ase_structure = pychemia.external.ase.pychemia2ase(pcm_structure)
        ase_structure.set_calculator(LennardJones())

        dyn = QuasiNewton(ase_structure)
        dyn.run()

        ase_structure.set_constraint(
            FixAtoms(mask=[True for atom in ase_structure]))
        ucf = UnitCellFilter(ase_structure)
        qn = QuasiNewton(ucf)
        qn.run()

        new_structure = pychemia.external.ase.ase2pychemia(ase_structure)
        energy = ase_structure.get_potential_energy()
        forces = ase_structure.get_forces()
        stress = ase_structure.get_stress()
        new_properties = {
            'energy': float(energy),
            'forces': generic_serializer(forces),
            'stress': generic_serializer(stress)
        }

        self.population.db.update(imember,
                                  structure=new_structure,
                                  properties=new_properties)
Beispiel #4
0
    def run(self, nparal=4):

        vj = VaspJob()
        vj.initialize(self.structure, self.workdir, self.kpoints, binary=self.binary)
        vj.clean()
        vj.job_static()
        vj.input_variables.set_density_for_restart()
        vj.input_variables.set_encut(ENCUT=self.encut, POTCAR=self.workdir + os.sep + 'POTCAR')
        vj.input_variables.variables['NBANDS'] = nparal * ((int(self.structure.valence_electrons()) +
                                                            self.structure.natom) / nparal + 1)
        vj.input_variables.set_ismear(self.kpoints)
        vj.input_variables.variables['SIGMA'] = 0.2
        vj.input_variables.variables['ISPIN'] = 2
        if self.task_params['extra_incar'] is not None:
            for i in self.task_params['extra_incar']:
                vj.input_variables.variables[i] = self.task_params['extra_incar'][i]
        vj.set_inputs()
        self.encut = vj.input_variables.variables['ENCUT']
        vj.run(use_mpi=True, mpi_num_procs=nparal)
        pcm_log.debug('Starting VASP')
        while True:
            energy_str = ''
            filename = self.workdir + os.sep + 'vasp_stdout.log'
            if os.path.exists(filename):
                vasp_stdout = read_vasp_stdout(filename=filename)
                if len(vasp_stdout['data']) > 2:
                    scf_energies = [i[2] for i in vasp_stdout['data']]
                    energy_str = ' %7.3f' % scf_energies[1]
                    for i in range(1, len(scf_energies)):
                        if scf_energies[i] < scf_energies[i - 1]:
                            energy_str += ' >'
                        else:
                            energy_str += ' <'
                    pcm_log.debug(energy_str)

            if vj.runner is not None and vj.runner.poll() is not None:
                filename = self.workdir + os.sep + 'vasp_stdout.log'
                if os.path.exists(filename):
                    vasp_stdout = read_vasp_stdout(filename=filename)
                    if len(vasp_stdout['data']) > 2:
                        scf_energies = [i[2] for i in vasp_stdout['data']]
                        energy_str += ' %7.3f' % scf_energies[-1]
                        pcm_log.debug(energy_str)
                pcm_log.debug('Execution complete')
                break
            time.sleep(5)
        vj.get_outputs()

        self.output = {'forces': generic_serializer(vj.outcar.forces), 'stress': generic_serializer(vj.outcar.stress),
                       'energy': vj.outcar.energy, 'energies': generic_serializer(vj.outcar.energies),
                       'INCAR': vj.input_variables.variables}
        if vj.outcar.is_finished:
            self.finished = True
 def test_serializer(self):
     """
     Test (pychemia.utils.serializer)                            :
     """
     a = np.array([1, 2, 3])
     assert generic_serializer(a) == [1, 2, 3]
     b = np.array([[1, 2, 3], [4, 5, 6]])
     assert generic_serializer(b) == [[1, 2, 3], [4, 5, 6]]
     c = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [0, 1, 2]]])
     assert generic_serializer(c) == [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [0, 1, 2]]]
     mydict = {'a': a, 'b': b, 'c': c}
     assert generic_serializer(mydict) == {u'a': [1, 2, 3],
                                           u'b': [[1, 2, 3], [4, 5, 6]],
                                           u'c': [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [0, 1, 2]]]}
Beispiel #6
0
 def test_serializer(self):
     """
     Tests (pychemia.utils.serializer)                            :
     """
     a = np.array([1, 2, 3])
     assert generic_serializer(a) == [1, 2, 3]
     b = np.array([[1, 2, 3], [4, 5, 6]])
     assert generic_serializer(b) == [[1, 2, 3], [4, 5, 6]]
     c = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [0, 1, 2]]])
     assert generic_serializer(c) == [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [0, 1, 2]]]
     mydict = {'a': a, 'b': b, 'c': c}
     generic_serializer(mydict) == {u'a': [1, 2, 3],
                                    u'b': [[1, 2, 3], [4, 5, 6]],
                                    u'c': [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [0, 1, 2]]]}
Beispiel #7
0
    def set_kpoints_list(self, kpoints_list, weights=None):
        """
        Set an explicit list of kpoints with a proper check of correct arguments

        :param kpoints_list: Explicit list of k-points (Only for 'cartesian' and 'reduced')
        :param weights: List of weights associated to each k-point (Only for 'cartesian' and 'reduced')
        """
        assert (self.kmode in ['cartesian', 'reduced'])
        if kpoints_list is None:
            self.kpoints_list = [[0, 0, 0]]
        else:
            if np.array(kpoints_list).shape == (3, ):
                self.kpoints_list = np.array(kpoints_list).reshape((-1, 3))
            elif np.array(kpoints_list).shape[1] == 3:
                self.kpoints_list = np.array(kpoints_list)
            else:
                raise ValueError(
                    "Wrong value for kpoints_list, should be an array with shape (nkpt,3)"
                )
        self.kpoints_list = generic_serializer(self.kpoints_list)
        nkpt = len(self.kpoints_list)
        if weights is None:
            self.weights = np.ones(nkpt)
        elif len(np.array(weights)) == nkpt:
            self.weights = np.array(weights)
        else:
            raise ValueError(
                "Wrong value for weights, should be an array with shape (nkpt,)"
            )
        self.weights = list(self.weights)
def cluster_fb_worker(db_settings):
    while True:
        pcdb = pychemia.db.get_database(db_settings)
        population = pychemia.population.LJCluster(pcdb)

        entry = population.pcdb.db.pychemia_entries.find_one({'status.' + population.tag: True,
                                                              'status.lock': {'$exists': False},
                                                              'properties': {}}, {'_id': 1})
        if entry is not None:
            population.pcdb.lock(entry['_id'])
            structure = population.pcdb.get_structure(entry['_id'])

            fb = pychemia.code.fireball.FireBall(fdata_path='../Fdata')
            fb.initialize(structure, workdir=str(entry['_id']))
            fb.cluster_relaxation()
            fb.set_inputs()
            sp = fb.run()
            sp.wait()
            so = pychemia.code.fireball.read_fireball_stdout(fb.workdir + os.sep + 'fireball.log')
            forces = generic_serializer(so['forces'][-1])
            energy = so['energy'][-1]['ETOT']
            properties = {'forces': forces, 'energy': energy}
            structure = pychemia.code.fireball.read_geometry_bas(fb.workdir + os.sep + 'answer.bas')
            population.pcdb.update(entry['_id'], structure=structure, properties=properties)
            population.pcdb.unlock(entry['_id'])
        else:
            break
Beispiel #9
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 = pychemia.utils.mathematics.unit_vectors(
            2 * np.random.rand(*pos.shape) - 1)
        new_pos = generic_serializer(pos + factor * uv)

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

        if in_place:
            return self.pcdb.db.pychemia_entries.update_one(
                {'_id': entry_id},
                {'$set': {
                    'structure': structure.to_dict,
                    'properties': {}
                }})
        else:
            structure = pychemia.Structure(
                positions=new_pos,
                symbols=entry['structure']['symbols'],
                periodicity=False)
            return self.new_entry(structure, active=False)
Beispiel #10
0
    def set_kpoints_list(self, kpoints_list, weights=None):
        """
        Set an explicit list of kpoints with a proper check of correct arguments

        :param kpoints_list: Explicit list of k-points (Only for 'cartesian' and 'reduced')
        :param weights: List of weights associated to each k-point (Only for 'cartesian' and 'reduced')
        """
        assert (self.kmode in ['cartesian', 'reduced'])
        if kpoints_list is None:
            self.kpoints_list = [[0, 0, 0]]
        else:
            if np.array(kpoints_list).shape == (3,):
                self.kpoints_list = np.array(kpoints_list).reshape((-1, 3))
            elif np.array(kpoints_list).shape[1] == 3:
                self.kpoints_list = np.array(kpoints_list)
            else:
                raise ValueError("Wrong value for kpoints_list, should be an array with shape (nkpt,3)")
        self.kpoints_list = generic_serializer(self.kpoints_list)
        nkpt = len(self.kpoints_list)
        if weights is None:
            self.weights = np.ones(nkpt)
        elif len(np.array(weights)) == nkpt:
            self.weights = np.array(weights)
        else:
            raise ValueError("Wrong value for weights, should be an array with shape (nkpt,)")
        self.weights = list(self.weights)
Beispiel #11
0
def read_fireball_stdout(filename):
    rf = open(filename, 'r')
    data = rf.read()

    atom_data = re.findall(r'Atom Coordinates from Basis File:([\d\w\s=\-\.#]+)===\n', data)[0]

    symbols = []
    positions = []
    for iline in atom_data.split('\n'):
        # print iline
        tmp = iline.split()
        if len(tmp) == 6 and tmp[0].isdigit():
            symbols.append(tmp[1])
            positions.append([float(x) for x in tmp[2:5]])

    natom = len(symbols)
    initial_positions = np.array(positions)
    # print symbols
    # print initial_positions

    forces_data = re.findall(r'The grand total force \(eV/A\):([\w\d\s\.\-=\+]*)Cartesian', data)
    # print len(forces_data)

    forces = np.zeros((len(forces_data), natom, 3))
    # print forces.shape

    iteration = 0
    for idata in forces_data:
        for iline in idata.split('\n'):
            if 'iatom' in iline:
                fields = iline.split()
                forces[iteration, int(fields[2]) - 1] = np.array(fields[-3:], dtype=float)
        iteration += 1

    ret = re.findall('Cartesian Forces:\s*Max = ([=\w\s\d.]*)RMS = ([\s\d.]*)\n', data)
    ret = [[float(x) for x in y] for y in ret]
    max_force = [x[0] for x in ret]
    rms = [x[1] for x in ret]

    energy_data = re.findall(r'---------- T H E  T O T A L  E N E R G Y -----------([\s\w\d\.\-=/]+)--- \n', data)

    energy = []
    for idata in energy_data:
        for iline in idata.split('\n'):
            if 'Time step' in iline:
                tmp = iline.split()
                ienergy = {'Time_step': int(tmp[3]), 'SCF_step': int(tmp[7]), 'etot/atom': float(tmp[10])}
            elif len(iline.split('=')) == 2:
                tmp = iline.split('=')
                ienergy[tmp[0].strip()] = float(tmp[1])
        energy.append(ienergy)

    ret = {'symbols': symbols,
           'initial_positions': initial_positions,
           'forces': generic_serializer(forces),
           'energetics': energy,
           'max_force': max_force,
           'rms_force': rms}
    return ret
Beispiel #12
0
def read_fireball_stdout(filename):
    rf = open(filename, 'r')
    data = rf.read()

    atom_data = re.findall(r'Atom Coordinates from Basis File:([\d\w\s=\-\.#]+)===\n', data)[0]

    symbols = []
    positions = []
    for iline in atom_data.split('\n'):
        # print iline
        tmp = iline.split()
        if len(tmp) == 6 and tmp[0].isdigit():
            symbols.append(tmp[1])
            positions.append([float(x) for x in tmp[2:5]])

    natom = len(symbols)
    initial_positions = np.array(positions)
    # print symbols
    # print initial_positions

    forces_data = re.findall(r'The grand total force \(eV/A\):([\w\d\s\.\-=\+]*)Cartesian', data)
    # print len(forces_data)

    forces = np.zeros((len(forces_data), natom, 3))
    # print forces.shape

    iteration = 0
    for idata in forces_data:
        for iline in idata.split('\n'):
            if 'iatom' in iline:
                fields = iline.split()
                forces[iteration, int(fields[2]) - 1] = np.array(fields[-3:], dtype=float)
        iteration += 1

    ret = re.findall('Cartesian Forces:\s*Max = ([=\w\s\d.]*)RMS = ([\s\d.]*)\n', data)
    ret = [[float(x) for x in y] for y in ret]
    max_force = [x[0] for x in ret]
    rms = [x[1] for x in ret]

    energy_data = re.findall(r'---------- T H E  T O T A L  E N E R G Y -----------([\s\w\d\.\-=/]+)--- \n', data)

    energy = []
    for idata in energy_data:
        for iline in idata.split('\n'):
            if 'Time step' in iline:
                tmp = iline.split()
                ienergy = {'Time_step': int(tmp[3]), 'SCF_step': int(tmp[7]), 'etot/atom': float(tmp[10])}
            elif len(iline.split('=')) == 2:
                tmp = iline.split('=')
                ienergy[tmp[0].strip()] = float(tmp[1])
        energy.append(ienergy)

    ret = {'symbols': symbols,
           'initial_positions': initial_positions,
           'forces': generic_serializer(forces),
           'energetics': energy,
           'max_force': max_force,
           'rms_force': rms}
    return ret
Beispiel #13
0
    def to_dict(self):
        ret = {}
        for i in ['charge', 'energy', 'forces', 'stress']:
            ret[i] = eval('self.' + i)

        for i in ret:
            if isinstance(ret[i], np.ndarray):
                ret[i] = generic_serializer(ret[i])
        return ret
Beispiel #14
0
    def to_dict(self):
        ret = {}
        for i in ['charge', 'energy', 'forces', 'stress']:
            ret[i] = eval('self.' + i)

        for i in ret:
            if isinstance(ret[i], np.ndarray):
                ret[i] = generic_serializer(ret[i])
        return ret
Beispiel #15
0
def elastic_moduli(filename='OUTCAR'):
    ret = {}
    rf = open(filename)
    data = rf.read()

    subblock = re.findall('ELASTIC MODULI CONTR FROM IONIC RELAXATION \(kBar\)[\s\d\w]*-*([\s\d\w.-]*)\n\n\n',
                          data)
    ret['elastic_moduli_contr'] = np.array(np.array(subblock[0].split()[:42]).reshape(6, -1)[:, 1:], dtype=float)

    subblock = re.findall('TOTAL ELASTIC MODULI \(kBar\)[\s\d\w]*-*([\s\d\w.-]*)\n\n\n', data)
    ret['total_elastic_moduli'] = np.array(np.array(subblock[0].split()[:42]).reshape(6, -1)[:, 1:], dtype=float)

    return generic_serializer(ret)
Beispiel #16
0
    def evaluate(self, imember):
        entry = self.population.get_entry(imember)
        pcm_structure = pychemia.Structure.from_dict(entry['structure'])

        ase_structure = pychemia.external.ase.pychemia2ase(pcm_structure)
        ase_structure.set_calculator(LennardJones())

        dyn = QuasiNewton(ase_structure)
        dyn.run()

        ase_structure.set_constraint(FixAtoms(mask=[True for atom in ase_structure]))
        ucf = UnitCellFilter(ase_structure)
        qn = QuasiNewton(ucf)
        qn.run()

        new_structure = pychemia.external.ase.ase2pychemia(ase_structure)
        energy = ase_structure.get_potential_energy()
        forces = ase_structure.get_forces()
        stress = ase_structure.get_stress()
        new_properties = {'energy': float(energy), 'forces': generic_serializer(forces),
                          'stress': generic_serializer(stress)}

        self.population.db.update(imember, structure=new_structure, properties=new_properties)
    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)
    def evaluate(self, structure, gtol=None):

        if gtol is None:
            gtol = self.target_forces

        positions, forces, energy = lj_compact_evaluate(structure, gtol, self.minimal_density)

        structure.set_positions(positions)
        structure.relocate_to_cm()
        if structure.natom > 2:
            structure.align_inertia_momenta()
        sorted_indices = structure.sort_sites()
        forces = forces[sorted_indices]
        pg = get_point_group(structure, executable='symmol')
        properties = {'forces': generic_serializer(forces), 'energy': energy, 'point_group': pg}
        return structure, properties
Beispiel #19
0
    def evaluate(self, entry_id, gtol=None):

        if gtol is None:
            gtol = self.target_forces

        print('Evaluating %s target density= %7.3F' % (entry_id, self.minimal_density))
        structure = self.get_structure(entry_id)

        positions, forces, energy = lj_compact_evaluate(structure, gtol, self.minimal_density)

        structure.set_positions(positions)
        structure.relocate_to_cm()
        if structure.natom > 2:
            structure.align_inertia_momenta()
        sorted_indices = structure.sort_sites()
        forces = forces[sorted_indices]
        properties = {'forces': generic_serializer(forces), 'energy': energy}
        return structure, properties, energy
Beispiel #20
0
    def set_grid(self, grid, shifts=None):
        """
        Set a grid of kpoints with a proper check of correct arguments

        :param grid: Number of kpoints on each direction (Only for 'gamma' and 'monkhorst-pack')
        :param shifts: Shift applied to the grid (Only for 'gamma' and 'monkhorst-pack')
        """

        assert (self.kmode in ['gamma', 'monkhorst-pack'])
        if grid is None:
            self.grid = [1, 1, 1]
        elif len(grid) == 3:
            self.grid = [int(x) for x in grid]
        else:
            raise ValueError("Wrong value for grid, should be an array with shape (-1,3)")
        if shifts is None:
            self.shifts = [0, 0, 0]
        else:
            self.shifts = generic_serializer(np.array(shifts).reshape(3))
Beispiel #21
0
    def set_grid(self, grid, shifts=None):
        """
        Set a grid of kpoints with a proper check of correct arguments

        :param grid: Number of kpoints on each direction (Only for 'gamma' and 'monkhorst-pack')
        :param shifts: Shift applied to the grid (Only for 'gamma' and 'monkhorst-pack')
        """

        assert (self.kmode in ['gamma', 'monkhorst-pack'])
        if grid is None:
            self.grid = [1, 1, 1]
        elif len(grid) == 3:
            self.grid = [int(x) for x in grid]
        else:
            raise ValueError(
                "Wrong value for grid, should be an array with shape (-1,3)")
        if shifts is None:
            self.shifts = [0, 0, 0]
        else:
            self.shifts = generic_serializer(np.array(shifts).reshape((-1, 3)))
Beispiel #22
0
    def evaluate(self, entry_id, gtol=None):

        if gtol is None:
            gtol = self.target_forces

        print('Evaluating %s target density= %7.3F' %
              (entry_id, self.minimal_density))
        structure = self.get_structure(entry_id)

        positions, forces, energy = lj_compact_evaluate(
            structure, gtol, self.minimal_density)

        structure.set_positions(positions)
        structure.relocate_to_cm()
        if structure.natom > 2:
            structure.align_inertia_momenta()
        sorted_indices = structure.sort_sites()
        forces = forces[sorted_indices]
        properties = {'forces': generic_serializer(forces), 'energy': energy}
        return structure, properties, energy
Beispiel #23
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)
Beispiel #24
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 = pychemia.utils.mathematics.unit_vectors(2 * np.random.rand(*pos.shape) - 1)
        new_pos = generic_serializer(pos + factor * uv)

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

        if in_place:
            return self.pcdb.db.pychemia_entries.update_one({'_id': entry_id},
                                                            {'$set': {'structure': structure.to_dict,
                                                                      'properties': {}}})
        else:
            structure = pychemia.Structure(positions=new_pos,
                                           symbols=entry['structure']['symbols'],
                                           periodicity=False)
            return self.new_entry(structure, active=False)
Beispiel #25
0
    def evaluate(self, structure, gtol=None):

        if gtol is None:
            gtol = self.target_forces

        positions, forces, energy = lj_compact_evaluate(
            structure, gtol, self.minimal_density)

        structure.set_positions(positions)
        structure.relocate_to_cm()
        if structure.natom > 2:
            structure.align_inertia_momenta()
        sorted_indices = structure.sort_sites()
        forces = forces[sorted_indices]
        pg = get_point_group(structure, executable='symmol')
        properties = {
            'forces': generic_serializer(forces),
            'energy': energy,
            'point_group': pg
        }
        return structure, properties
Beispiel #26
0
def cluster_fb_worker(db_settings):
    while True:
        pcdb = pychemia.db.get_database(db_settings)
        population = pychemia.population.LJCluster(pcdb)

        entry = population.pcdb.db.pychemia_entries.find_one(
            {
                'status.' + population.tag: True,
                'status.lock': {
                    '$exists': False
                },
                'properties': {}
            }, {'_id': 1})
        if entry is not None:
            population.pcdb.lock(entry['_id'])
            structure = population.pcdb.get_structure(entry['_id'])

            fb = pychemia.code.fireball.FireBall(fdata_path='../Fdata')
            fb.initialize(structure, workdir=str(entry['_id']))
            fb.cluster_relaxation()
            fb.set_inputs()
            sp = fb.run()
            sp.wait()
            so = pychemia.code.fireball.read_fireball_stdout(fb.workdir +
                                                             os.sep +
                                                             'fireball.log')
            forces = generic_serializer(so['forces'][-1])
            energy = so['energy'][-1]['ETOT']
            properties = {'forces': forces, 'energy': energy}
            structure = pychemia.code.fireball.read_geometry_bas(fb.workdir +
                                                                 os.sep +
                                                                 'answer.bas')
            population.pcdb.update(entry['_id'],
                                   structure=structure,
                                   properties=properties)
            population.pcdb.unlock(entry['_id'])
        else:
            break
    def test_orbital(self):
        """
        Test (pychemia.population.OrbitalDFTU)                      :
        """
        if not pychemia.db.has_connection():
            return

        pychemia_path = pychemia.__path__[0]
        abiinput = pychemia.code.abinit.AbinitInput('tests/data/abinit_dmatpawu/abinit.in')
        dmatpawu = np.array(abiinput['dmatpawu']).reshape(-1, 5, 5)
        params = pychemia.population.orbitaldftu.dmatpawu2params(dmatpawu, 5)
        dmatpawu_new = pychemia.population.orbitaldftu.params2dmatpawu(params)

        self.assertLess(np.min(dmatpawu-dmatpawu_new), 0.01)

        with self.assertRaises(ValueError) as context:
            pychemia.population.orbitaldftu.OrbitalDFTU('test', '/tmp/no_abinit.in')

        with self.assertRaises(ValueError) as context:
            pychemia.population.orbitaldftu.OrbitalDFTU('test', input_path='tests/data/abinit_01/abinit.in')

        popu = pychemia.population.orbitaldftu.OrbitalDFTU('test', input_path='tests/data/abinit_dmatpawu/abinit.in')
        popu.pcdb.clean()

        ea = [[-0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -1.0],
              [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
        params['euler_angles'] = ea
        params = generic_serializer(params)
        entry_id = popu.new_entry(params)

        ea = [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
              [-0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -1.0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
        params['euler_angles'] = ea
        params = generic_serializer(params)
        entry_jd = popu.new_entry(params)

        popu.add_random()
        popu.random_population(16)
        print(popu)

        self.assertFalse(popu.is_evaluated(entry_id))

        for entry_id in popu.members:
            params = popu.get_correlation_params(entry_id, final=False)
            popu.set_final_results(entry_id, params, 0.0, 1E-13)

        self.assertTrue(popu.is_evaluated(entry_id))

        popu.get_duplicates(popu.members, tolerance=0.1)

        popu.cross([entry_id, entry_jd])

        entry_idm = popu.move_random(entry_id)
        popu.get_entry(entry_idm, {'properties': 1})

        entry_imj = popu.move(entry_id, entry_jd)
        popu.get_entry(entry_imj, {'properties': 1})

        # pd = popu.to_dict
        # popu.from_dict(pd)

        tmpdir = tempfile.mkdtemp()

        for i in popu.members:
            popu.prepare_folder(i, workdir=tmpdir, source_dir=pychemia_path + 'tests/data/abinit_dmatpawu')

        popu.pcdb.clean()
        shutil.rmtree(tmpdir)
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)
Beispiel #29
0
    def run(self, nparal=1):

        self.started = True
        self.cleaner()
        vj = self.vaspjob
        ncalls = 1
        self.first_run(nparal)

        while True:
            if vj.runner is not None and vj.runner.poll() is not None:
                pcm_log.info('Execution completed. Return code %d' % vj.runner.returncode)

                filename = self.workdir + os.sep + 'vasp_stdout.log'
                if os.path.exists(filename):
                    read_vasp_stdout(filename=filename)

                ncalls += 1
                va = VaspAnalyser(self.workdir)
                va.run()

                max_force, max_stress = self.get_max_force_stress()
                print('Max Force: %9.3E Stress: %9.3E (target forces= %E)' %
                      (max_force, max_stress, self.target_forces))

                if max_force is not None and max_force < self.target_forces:

                    # Conditions to finish the run
                    if max_stress < self.target_forces:
                        self.success = True
                        break
                    elif not self.relax_cell:
                        self.success = True
                        break
                    elif ncalls >= self.max_calls:
                        self.success = False
                        break

                self.update()

                vj.run(use_mpi=True, mpi_num_procs=nparal)
                if self.waiting:
                    vj.runner.wait()
            else:
                filename = self.workdir + os.sep + 'vasp_stdout.log'
                if os.path.exists(filename):
                    vasp_stdout = read_vasp_stdout(filename=filename)
                    if len(vasp_stdout['iterations']) > 0:
                        pcm_log.debug('[%s] SCF: %s' % (os.path.basename(self.workdir), str(vasp_stdout['iterations'])))
                        # if len(vasp_stdout['energies']) > 2:
                        #     energy_str = ' %9.3E' % vasp_stdout['energies'][0]
                        #     for i in range(1, len(vasp_stdout['energies'])):
                        #         if vasp_stdout['energies'][i] < vasp_stdout['energies'][i-1]:
                        #             energy_str += ' >'
                        #         else:
                        #             energy_str += ' <'
                        #     pcm_log.debug(energy_str)

                time.sleep(30)

        outcars = sorted([x for x in os.listdir(self.workdir) if x.startswith('OUTCAR')])[::-1]
        vo = VaspOutput(self.workdir + os.sep + outcars[0])
        forces = vo.forces
        stress = vo.stress
        if len(outcars) > 1:
            for i in outcars[1:]:
                vo = VaspOutput(self.workdir + os.sep + i)
                forces = np.concatenate((forces, vo.forces))
                stress = np.concatenate((stress, vo.stress))

        vj.get_outputs()
        self.output = {'forces': generic_serializer(forces), 'stress': generic_serializer(stress),
                       'energy': vj.outcar.energy, 'energies': generic_serializer(vj.outcar.energies)}
        if vj.outcar.is_finished:
            self.finished = True
def worker(db_settings, entry_id, workdir, target_forces, relaxator_params):
    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)
    structure = structure.scale()
    print('relaxator_params', relaxator_params)
    relaxer = IonRelaxation2(structure, workdir=workdir, target_forces=target_forces, waiting=False,
                             binary=relaxator_params['binary'], encut=1.3, kp_grid=None, kp_density=1E4,
                             relax_cell=True)
    print('relaxing on:', relaxer.workdir)
    relaxer.run(relaxator_params['nmpiparal'])
    pcm_log.info('[%s]: Finished relaxation. Target forces: %7.3e' % (str(entry_id), target_forces))

    filename = workdir + os.sep + 'OUTCAR'
    if os.path.isfile(filename):

        forces, stress, total_energy = relaxer.get_forces_stress_energy()

        if forces is not None:
            magnitude_forces = np.apply_along_axis(np.linalg.norm, 1, forces)
            print('Forces: Max: %9.3e Avg: %9.3e' % (np.max(magnitude_forces), np.average(magnitude_forces)))
            print('Stress: ', np.max(np.abs(stress.flatten())))

        if forces is None:
            pcm_log.error('No forces found on %s' % filename)
        if stress is None:
            pcm_log.error('No stress found on %s' % filename)
        if total_energy is None:
            pcm_log.error('No total_energy found on %s' % filename)

        new_structure = relaxer.get_final_geometry()

        if forces is not None and stress is not None and total_energy is not None and new_structure is not None:
            pcm_log.info('[%s]: Updating properties' % str(entry_id))
            pcdb.update(entry_id, structure=new_structure)
            te = total_energy
            pcdb.entries.update({'_id': entry_id},
                                {'$set': {'status.relaxation': 'succeed',
                                          'status.target_forces': target_forces,
                                          'properties.forces': generic_serializer(forces),
                                          'properties.stress': generic_serializer(stress),
                                          'properties.energy': te,
                                          'properties.energy_pa': te / new_structure.natom,
                                          'properties.energy_pf': te / new_structure.get_composition().gcd}})

            # Fingerprint
            # Update the fingerprints only if the two structures are really different
            diffnatom = structure.natom != new_structure.natom
            diffcell = np.max(np.abs((structure.cell - new_structure.cell).flatten()))
            diffreduced = np.max(np.abs((structure.reduced - new_structure.reduced).flatten()))
            if diffnatom != 0 or diffcell > 1E-7 or diffreduced > 1E-7:
                analysis = StructureAnalysis(new_structure, radius=50)
                x, ys = analysis.fp_oganov(delta=0.01, sigma=0.01)
                fingerprint = {'_id': entry_id}
                for k in ys:
                    atomic_number1 = atomic_number(new_structure.species[k[0]])
                    atomic_number2 = atomic_number(new_structure.species[k[1]])
                    pair = '%06d' % min(atomic_number1 * 1000 + atomic_number2,
                                        atomic_number2 * 1000 + atomic_number1)
                    fingerprint[pair] = list(ys[k])

                if pcdb.db.fingerprints.find_one({'_id': entry_id}) is None:
                    pcdb.db.fingerprints.insert(fingerprint)
                else:
                    pcdb.db.fingerprints.update({'_id': entry_id}, fingerprint)
            else:
                pcm_log.debug('Original and new structures are very similar.')
                pcm_log.debug('Max diff cell: %10.3e' % np.max(np.absolute((structure.cell -
                                                                            new_structure.cell).flatten())))
                if structure.natom == new_structure.natom:
                    pcm_log.debug('Max diff reduced coordinates: %10.3e' %
                                  np.max(np.absolute((structure.reduced - new_structure.reduced).flatten())))

        else:
            pcdb.entries.update({'_id': entry_id}, {'$set': {'status.relaxation': 'failed'}})
            pcm_log.error('Bad data after relaxation. Tagging relaxation as failed')
    else:
        pcm_log.error('ERROR: File not found %s' % filename)
    pcm_log.info('[%s]: Unlocking the entry' % str(entry_id))
    pcdb.unlock(entry_id)
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)
Beispiel #32
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)
Beispiel #33
0
def worker(db_settings, entry_id, workdir, target_forces, relaxator_params):
    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)
    structure = structure.scale()
    print('relaxator_params', relaxator_params)
    relaxer = IonRelaxation(structure,
                            workdir=workdir,
                            target_forces=target_forces,
                            waiting=False,
                            binary=relaxator_params['binary'],
                            encut=1.3,
                            kp_grid=None,
                            kp_density=1E4,
                            relax_cell=True,
                            max_calls=10)
    print('relaxing on:', relaxer.workdir)
    relaxer.run(relaxator_params['nmpiparal'])
    pcm_log.info('[%s]: Finished relaxation. Target forces: %7.3e' %
                 (str(entry_id), target_forces))

    filename = workdir + os.sep + 'OUTCAR'
    if os.path.isfile(filename):

        forces, stress, total_energy = relaxer.get_forces_stress_energy()

        if forces is not None:
            magnitude_forces = np.apply_along_axis(np.linalg.norm, 1, forces)
            print('Forces: Max: %9.3e Avg: %9.3e' %
                  (np.max(magnitude_forces), np.average(magnitude_forces)))
            print('Stress: ', np.max(np.abs(stress.flatten())))

        if forces is None:
            pcm_log.error('No forces found on %s' % filename)
        if stress is None:
            pcm_log.error('No stress found on %s' % filename)
        if total_energy is None:
            pcm_log.error('No total_energy found on %s' % filename)

        new_structure = relaxer.get_final_geometry()

        if forces is not None and stress is not None and total_energy is not None and new_structure is not None:
            pcm_log.info('[%s]: Updating properties' % str(entry_id))
            pcdb.update(entry_id, structure=new_structure)
            te = total_energy
            pcdb.entries.update({'_id': entry_id}, {
                '$set': {
                    'status.relaxation':
                    'succeed',
                    'status.target_forces':
                    target_forces,
                    'properties.forces':
                    generic_serializer(forces),
                    'properties.stress':
                    generic_serializer(stress),
                    'properties.energy':
                    te,
                    'properties.energy_pa':
                    te / new_structure.natom,
                    'properties.energy_pf':
                    te / new_structure.get_composition().gcd
                }
            })

            # Fingerprint
            # Update the fingerprints only if the two structures are really different
            diffnatom = structure.natom != new_structure.natom
            diffcell = np.max(
                np.abs((structure.cell - new_structure.cell).flatten()))
            diffreduced = np.max(
                np.abs((structure.reduced - new_structure.reduced).flatten()))
            if diffnatom != 0 or diffcell > 1E-7 or diffreduced > 1E-7:
                analysis = StructureAnalysis(new_structure, radius=50)
                x, ys = analysis.fp_oganov(delta=0.01, sigma=0.01)
                fingerprint = {'_id': entry_id}
                for k in ys:
                    atomic_number1 = atomic_number(new_structure.species[k[0]])
                    atomic_number2 = atomic_number(new_structure.species[k[1]])
                    pair = '%06d' % min(atomic_number1 * 1000 + atomic_number2,
                                        atomic_number2 * 1000 + atomic_number1)
                    fingerprint[pair] = list(ys[k])

                if pcdb.db.fingerprints.find_one({'_id': entry_id}) is None:
                    pcdb.db.fingerprints.insert(fingerprint)
                else:
                    pcdb.db.fingerprints.update({'_id': entry_id}, fingerprint)
            else:
                pcm_log.debug('Original and new structures are very similar.')
                pcm_log.debug('Max diff cell: %10.3e' % np.max(
                    np.absolute(
                        (structure.cell - new_structure.cell).flatten())))
                if structure.natom == new_structure.natom:
                    pcm_log.debug(
                        'Max diff reduced coordinates: %10.3e' % np.max(
                            np.absolute((structure.reduced -
                                         new_structure.reduced).flatten())))

        else:
            pcdb.entries.update({'_id': entry_id},
                                {'$set': {
                                    'status.relaxation': 'failed'
                                }})
            pcm_log.error(
                'Bad data after relaxation. Tagging relaxation as failed')
    else:
        pcm_log.error('ERROR: File not found %s' % filename)
    pcm_log.info('[%s]: Unlocking the entry' % str(entry_id))
    pcdb.unlock(entry_id)
Beispiel #34
0
def read_dftb_stdout(filename='dftb_stdout.log'):
    """
    Read the standard output stored in a file
    (by default 'dftb_stdout.log') and extract
    relevant information useful for a relaxation
    procedure

    :param filename: The standard output stored in a file
    :return:
    """

    rf = open(filename, 'r')
    data = rf.read()

    ret = {}

    start_ini = re.findall(r'Starting initialization...[\s-]+([.\s\d\w\-:\(\),+]+)---', data)
    if len(start_ini) == 1:
        start_ini = start_ini[0].replace('\n  ', '  ').split('\n')
        ret['Starting_Initialization'] = {}
        for line in start_ini:
            if len(line.split(':')) == 2:
                left, right = line.split(':')
            elif line[:3] != '---':
                left = line[:29].replace(':', '')
                right = line[29:]
            ret['Starting_Initialization'][left.strip()] = parse_value(right.strip())

            if left.strip() == 'K-points and weights':
                right = right.replace(':', '')
                right = np.array(right.split(), dtype=float).reshape((-1, 5))
                ret['Starting_Initialization'][left.strip()] = {'kpoints': generic_serializer(right[:, 1:-1]),
                                                                'weights': generic_serializer(right[:, -1])}

    geom_blocks = re.findall(r'Geometry step:([\^*.\s\d\w\-:\(\),+]+)Pa', data)

    ret['Geometry_Steps'] = []
    for iblock in geom_blocks:
        ib = iblock.split('\n')
        if 'Lattice' in ib[0]:
            tmp = {'iter': int(ib[0].split(',')[0]), 'scc': {}}
        else:
            tmp = {'iter': int(ib[0]), 'scc': {}}
        tmp['scc']['tot_electronic'] = []
        tmp['scc']['diff_electronic'] = []
        tmp['scc']['scc_error'] = []
        for iline in ib[4:]:
            fields = iline.split()
            if len(fields) > 0 and fields[0].strip().isdigit():
                tmp['scc']['tot_electronic'].append(float(fields[1]))
                tmp['scc']['diff_electronic'].append(float(fields[2]))
                tmp['scc']['scc_error'].append(float(fields[3]))
            elif len(iline.split(':')) == 2:
                left, right = iline.split(':')
                tmp[left.strip()] = {'value': float(right.split()[0]), 'units': right.split()[1]}

        ret['Geometry_Steps'].append(tmp)

    max_force = re.findall(r'Maximal force component:\s*([\s\dE+-.]+)\s*\n', data)
    if len(max_force) > 0:
        ret['max_force'] = float(max_force[-1])

    if re.findall('Geometry did NOT converge', data):
        pcm_log.debug('Convergence not achieved!')
        ret['ion_convergence'] = False
    else:
        ret['ion_convergence'] = True

    if re.findall('Geometry converged', data):
        pcm_log.debug('Convergence achieved!')
        ret['ion_convergence'] = True
    else:
        ret['ion_convergence'] = False
    return ret
Beispiel #35
0
    def run(self, nparal=1):

        self.started = True
        self.cleaner()
        vj = self.vaspjob
        ncalls = 1
        self.first_run(nparal)

        while True:
            if vj.runner is not None and vj.runner.poll() is not None:
                pcm_log.info('Execution completed. Return code %d' %
                             vj.runner.returncode)

                filename = self.workdir + os.sep + 'vasp_stdout.log'
                if os.path.exists(filename):
                    read_vasp_stdout(filename=filename)

                ncalls += 1
                va = VaspAnalyser(self.workdir)
                va.run()

                max_force, max_stress = self.get_max_force_stress()
                print('Max Force: %9.3E Stress: %9.3E (target forces= %E)' %
                      (max_force, max_stress, self.target_forces))

                if max_force is not None and max_force < self.target_forces:

                    # Conditions to finish the run
                    if max_stress < self.target_forces:
                        self.success = True
                        break
                    elif not self.relax_cell:
                        self.success = True
                        break
                    elif ncalls >= self.max_calls:
                        self.success = False
                        break

                self.update()

                vj.run(use_mpi=True, mpi_num_procs=nparal)
                if self.waiting:
                    vj.runner.wait()
            else:
                filename = self.workdir + os.sep + 'vasp_stdout.log'
                if os.path.exists(filename):
                    vasp_stdout = read_vasp_stdout(filename=filename)
                    if len(vasp_stdout['iterations']) > 0:
                        pcm_log.debug('[%s] SCF: %s' % (os.path.basename(
                            self.workdir), str(vasp_stdout['iterations'])))
                        # if len(vasp_stdout['energies']) > 2:
                        #     energy_str = ' %9.3E' % vasp_stdout['energies'][0]
                        #     for i in range(1, len(vasp_stdout['energies'])):
                        #         if vasp_stdout['energies'][i] < vasp_stdout['energies'][i-1]:
                        #             energy_str += ' >'
                        #         else:
                        #             energy_str += ' <'
                        #     pcm_log.debug(energy_str)

                time.sleep(30)

        outcars = sorted([
            x for x in os.listdir(self.workdir) if x.startswith('OUTCAR')
        ])[::-1]
        vo = VaspOutput(self.workdir + os.sep + outcars[0])
        forces = vo.forces
        stress = vo.stress
        if len(outcars) > 1:
            for i in outcars[1:]:
                vo = VaspOutput(self.workdir + os.sep + i)
                forces = np.concatenate((forces, vo.forces))
                stress = np.concatenate((stress, vo.stress))

        vj.get_outputs()
        self.output = {
            'forces': generic_serializer(forces),
            'stress': generic_serializer(stress),
            'energy': vj.outcar.energy,
            'energies': generic_serializer(vj.outcar.energies)
        }
        if vj.outcar.is_finished:
            self.finished = True
    def test_orbital(self):
        """
        Tests (pychemia.population.OrbitalDFTU)                      :
        """
        if not pychemia.db.has_connection():
            return

        pychemia_path = pychemia.__path__[0]
        abiinput = pychemia.code.abinit.AbinitInput('tests/data/abinit_dmatpawu/abinit.in')
        dmatpawu = np.array(abiinput['dmatpawu']).reshape(-1, 5, 5)
        params = pychemia.population.orbitaldftu.dmatpawu2params(dmatpawu, 5)
        dmatpawu_new = pychemia.population.orbitaldftu.params2dmatpawu(params)

        self.assertLess(np.min(dmatpawu-dmatpawu_new), 0.01)

        with self.assertRaises(ValueError) as context:
            pychemia.population.orbitaldftu.OrbitalDFTU('test', '/tmp/no_abinit.in')

        with self.assertRaises(ValueError) as context:
            pychemia.population.orbitaldftu.OrbitalDFTU('test', input_path='tests/data/abinit_01/abinit.in')

        popu = pychemia.population.orbitaldftu.OrbitalDFTU('test', input_path='tests/data/abinit_dmatpawu/abinit.in')
        popu.pcdb.clean()

        ea = [[-0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -1.0],
              [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
        params['euler_angles'] = ea
        params = generic_serializer(params)
        entry_id = popu.new_entry(params)

        ea = [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
              [-0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -1.0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
        params['euler_angles'] = ea
        params = generic_serializer(params)
        entry_jd = popu.new_entry(params)

        popu.add_random()
        popu.random_population(16)
        print(popu)

        self.assertFalse(popu.is_evaluated(entry_id))

        for entry_id in popu.members:
            params = popu.get_correlation_params(entry_id, final=False)
            popu.set_final_results(entry_id, params, 0.0, 1E-13)

        self.assertTrue(popu.is_evaluated(entry_id))

        popu.get_duplicates(popu.members, tolerance=0.1)

        popu.cross([entry_id, entry_jd])

        entry_idm = popu.move_random(entry_id)
        popu.get_entry(entry_idm, {'properties': 1})

        entry_imj = popu.move(entry_id, entry_jd)
        popu.get_entry(entry_imj, {'properties': 1})

        # pd = popu.to_dict
        # popu.from_dict(pd)

        tmpdir = tempfile.mkdtemp()

        for i in popu.members:
            popu.prepare_folder(i, workdir=tmpdir, source_dir=pychemia_path + 'tests/data/abinit_dmatpawu')

        popu.pcdb.clean()
        shutil.rmtree(tmpdir)