Révision 1d8c374e modules/formats.py

b/modules/formats.py
166 166
    force_eval = cp2k.CP2K_INPUT.FORCE_EVAL_list[0]
167 167
    raw_coords = force_eval.SUBSYS.COORD.Default_keyword
168 168
    symbols = [atom.split()[0] for atom in raw_coords]
169
    positions = np.array([atom.split()[1:] for atom in raw_coords])
169
    positions = np.array([[float(coord) for coord in atom.split()[1:]]
170
                          for atom in raw_coords])
170 171
    if len(spec_atoms) > 0:
171 172
        add_special_atoms(spec_atoms)
172 173
    return Atoms(symbols=symbols, positions=positions)
......
190 191
    return ase.io.read(file)
191 192

  
192 193

  
193
def collect_coords(conf_list, code, run_type, spec_atms=tuple()):
194
    """Directs the reading of coordinates on a set of subdirectories.
195

  
196
    Given a dockonsurf directory hierarchy: project/run_type/conf_X
197
    (run_type = ['isolated', 'screening' or 'refinement']) with finished
198
    calculations produced by a given code, stored in every conf_X subdirectory,
199
    it collects the coordinates of the specified conf_X subdirectories in a
200
    single run_type by calling the adequate function (depending on the code) and
201
    returns a list of ase.Atoms objects.
202

  
203
    @param conf_list: List of directories where to read the coords from.
204
    @param code: the code that produced the calculation results files.
205
    @param run_type: the type of calculation (and also the name of the folder)
206
                     containing the calculation subdirectories.
207
    @param spec_atms: List of tuples containing pairs of new/traditional
208
        chemical symbols.
209
    @return: list of ase.Atoms objects.
210
    """
211
    from glob import glob
212
    atoms_list = []
213
    for conf in conf_list:
214
        if code == 'cp2k':
215
            atoms_list.append(read_coords_cp2k(glob(f"{run_type}/{conf}/*-1"
216
                                                    f".restart")[0], spec_atms))
217
        elif code == 'vasp':
218
            atoms_list.append(read_coords_vasp(f"{run_type}/{conf}/OUTCAR",
219
                                               spec_atms))
220
        else:
221
            err_msg = f"Collect coordinates not implemented for '{code}'."
222
            logger.error(err_msg)
223
            raise NotImplementedError(err_msg)
224
    return atoms_list
225

  
226

  
227 194
def read_energy_cp2k(file):
228
    """Reads the CP2K out file and returns its final energy.
195
    """Reads the CP2K output file and returns its final energy.
229 196

  
230 197
    @param file: The file from which the energy should be read.
231
    @return: The last energy on the out file.
198
    @return: The last energy on the out file in eV.
232 199
    """
233 200
    out_fh = open(file, 'r')
234 201
    energy = None
......
239 206
    return energy
240 207

  
241 208

  
242
def collect_energies(conf_list, code, run_type):
243
    """Directs the reading of energies on a set of subdirectories.
209
def collect_confs(dir_list, code, run_type, spec_atms=tuple()):
210
    """Reads the coordinates and energies of a list of finished calculations.
244 211

  
245 212
    Given a dockonsurf directory hierarchy: project/run_type/conf_X
246
    (run_type = ['isolated', 'screening' or 'refinement']) with finished
247
    calculations produced by a given code, stored in every conf_X subdirectory,
248
    it collects the energies of the specified conf_X subdirectories in a
249
    single run_type by calling the adequate function (depending on the code) and
250
    returns a list of energies.
251

  
252
    @param conf_list: List of directories where to read the energy.
253
    @param code: The code that produced the calculation output files.
254
    @param run_type: The type of calculation (and also the name of the folder)
255
                     containing the calculation subdirectories.
256
    @return: List of energies
213
    (run_type = ['isolated', 'screening' or 'refinement']) it reads the
214
    coordinates of each conf_X, it assigns its total energy from the calculation
215
    and assigns the conf_X label to track its origin. Finally it returns the
216
    ase.Atoms object.
217

  
218
    @param dir_list: List of directories where to read the coords from.
219
    @param code: the code that produced the calculation results files.
220
    @param run_type: the type of calculation (and also the name of the folder)
221
        containing the calculation subdirectories.
222
    @param spec_atms: List of tuples containing pairs of new/traditional
223
        chemical symbols.
224
    @return: list of ase.Atoms objects.
257 225
    """
258 226
    from glob import glob
259
    import numpy as np
260

  
261
    energies = []
262
    for conf in conf_list:
227
    import os
228
    from modules.utilities import is_binary
229
    atoms_list = []
230
    for conf_dir in dir_list:
231
        conf_path = f"{run_type}/{conf_dir}/"
263 232
        if code == 'cp2k':
264
            energies.append(read_energy_cp2k(
265
                glob(f"{run_type}/{conf}/*.out")[0]))
233
            ase_atms = read_coords_cp2k(glob(f"{conf_path}/*-1.restart")[0],
234
                                        spec_atms)
235
            # Assign energy
236
            for fil in os.listdir(conf_path):
237
                if is_binary(conf_path+fil):
238
                    continue
239
                conf_energy = read_energy_cp2k(conf_path+fil)
240
                if conf_energy is not None:
241
                    ase_atms.info["energy"] = conf_energy
242
                    break
243
            ase_atms.info[run_type[:3]] = conf_dir
244
            atoms_list.append(ase_atms)
245
        elif code == 'vasp':
246
            ase_atms = read_coords_vasp(f"{conf_path}/OUTCAR", spec_atms)
247
            ase_atms.info["energy"] = ase_atms.get_total_energy() * 27.2113845
248
            ase_atms.info[run_type[:3]] = conf_dir
249
            atoms_list.append(ase_atms)
266 250
        else:
267
            err_msg = f"Collect energies not implemented for '{code}'."
251
            err_msg = f"Collect coordinates not implemented for '{code}'."
268 252
            logger.error(err_msg)
269 253
            raise NotImplementedError(err_msg)
254
    return atoms_list
270 255

  
271
    if len(energies) == 0:
272
        err = f"No results found on {run_type}"
273
        logger.error(err)
274
        raise FileNotFoundError(err)
275

  
276
    return np.array(energies)

Formats disponibles : Unified diff