Statistiques
| Branche: | Tag: | Révision :

dockonsurf / modules / calculation.py @ 2dfa562f

Historique | Voir | Annoter | Télécharger (4,94 ko)

1 3d6a9d3c Carles
import os
2 3d6a9d3c Carles
import logging
3 3d6a9d3c Carles
4 3d6a9d3c Carles
logger = logging.getLogger('DockOnSurf')
5 3d6a9d3c Carles
6 3d6a9d3c Carles
7 c3cb279a Carles
def check_bak(file_name):
8 c3cb279a Carles
    """Checks if a file already exists and backs it up if so.
9 c3cb279a Carles
    @param file_name: file to be checked if exists
10 3d6a9d3c Carles
    """
11 c3cb279a Carles
    new_name = file_name
12 3d6a9d3c Carles
    bak_num = 0
13 2dfa562f Carles Martí
    while os.path.isdir(new_name)  or os.path.isfile(new_name):
14 3d6a9d3c Carles
        bak_num += 1
15 c3cb279a Carles
        new_name = new_name.split(".bak")[0] + f".bak{bak_num}"
16 3d6a9d3c Carles
    if bak_num > 0:
17 c3cb279a Carles
        os.rename(file_name, new_name)
18 c3cb279a Carles
        logger.warning(f"'{file_name}' already present. Backed it up to "
19 c3cb279a Carles
                       f"{new_name}")
20 3d6a9d3c Carles
21 3d6a9d3c Carles
22 f3004731 Carles
def prep_cp2k(inp_file, run_type, atms_list):
23 f3004731 Carles
    """Prepares the directories to run isolated calculation with CP2K.
24 3d6a9d3c Carles

25 f3004731 Carles
    @param inp_file: CP2K Input file to run the calculations with.
26 f3004731 Carles
    @param run_type: Type of calculation. 'isolated', 'screening' or
27 f3004731 Carles
        'refinement'
28 f3004731 Carles
    @param atms_list: list of ase.Atoms objects to run the calculation of.
29 f3004731 Carles
    @return: None
30 f3004731 Carles
    """
31 f3004731 Carles
    from shutil import copy
32 f3004731 Carles
    import ase.io
33 f3004731 Carles
    from pycp2k import CP2K
34 f3004731 Carles
    cp2k = CP2K()
35 f3004731 Carles
    cp2k.parse(inp_file)
36 f3004731 Carles
    force_eval = cp2k.CP2K_INPUT.FORCE_EVAL_list[0]
37 b05058e1 Carles
    if force_eval.SUBSYS.TOPOLOGY.Coord_file_name is None:
38 2dfa562f Carles Martí
        logger.warning("'COORD_FILE_NAME' not specified on CP2K input. Using\n"
39 2dfa562f Carles Martí
                       "default name 'coord.xyz'. A new CP2K input file with "
40 2dfa562f Carles Martí
                       "the 'COORD_FILE_NAME' variable is created. If there\n"
41 2dfa562f Carles Martí
                       "is a name conflict the old file will be backed up")
42 b05058e1 Carles
        force_eval.SUBSYS.TOPOLOGY.Coord_file_name = 'coord.xyz'
43 2dfa562f Carles Martí
        print(inp_file.split('/')[-1])
44 2dfa562f Carles Martí
        check_bak(inp_file.split('/')[-1])
45 2dfa562f Carles Martí
        cp2k.write_input_file(inp_file.split('/')[-1])
46 b05058e1 Carles
47 f3004731 Carles
    coord_file = force_eval.SUBSYS.TOPOLOGY.Coord_file_name
48 f3004731 Carles
49 99afde40 Carles
    # Creating and setting up directories for every configuration.
50 f3004731 Carles
    for i, conf in enumerate(atms_list):
51 f3004731 Carles
        os.mkdir(f'{run_type}/conf_{i}')
52 f3004731 Carles
        copy(inp_file, f'{run_type}/conf_{i}/')
53 f3004731 Carles
        ase.io.write(f'{run_type}/conf_{i}/{coord_file}', conf)
54 f3004731 Carles
55 f3004731 Carles
56 670284be Carles
def get_jobs_status_sge(job_ids):  # TODO more elegant
57 670284be Carles
    """Returns a list of job status for a list of job ids.
58 99afde40 Carles

59 670284be Carles
    @param job_ids: list of all jobs to be checked their status.
60 670284be Carles
    @return: list of status for every job.
61 99afde40 Carles
    """
62 99afde40 Carles
    from gridtk.tools import qstat
63 670284be Carles
    run_chk = 'usage         1'
64 670284be Carles
    status_list = []
65 670284be Carles
    for job in job_ids:
66 670284be Carles
        if run_chk in qstat(job):
67 670284be Carles
            status_list.append('r')
68 670284be Carles
        elif len(qstat(job)) > 0:
69 670284be Carles
            status_list.append('q')
70 670284be Carles
        else:
71 670284be Carles
            status_list.append('f')
72 670284be Carles
    return status_list
73 99afde40 Carles
74 99afde40 Carles
75 99afde40 Carles
def submit(run_type, q_sys, sub_script, max_qw, name):
76 99afde40 Carles
    """Submits jobs to the relevant queuing system with the provided script
77 99afde40 Carles

78 99afde40 Carles
    @param run_type: Type of calculation. 'isolated', 'screening' or
79 99afde40 Carles
        'refinement'
80 99afde40 Carles
    @param q_sys: Batch queuing system used
81 99afde40 Carles
    @param sub_script: script for the job submission.
82 99afde40 Carles
    @param max_qw: Maximum number of simultaneous jobs waiting to be executed.
83 99afde40 Carles
    @param name: name of the project
84 99afde40 Carles
    """
85 99afde40 Carles
    from shutil import copy
86 99afde40 Carles
    from time import sleep
87 99afde40 Carles
    subm_jobs = []
88 bd573212 Carles
    if q_sys == 'sge': # TODO Independent functions for every batch_q_sys
89 bd573212 Carles
        from gridtk.tools import qsub  # TODO CHANGE TO DRMAA
90 277d1b39 Carles Martí
        init_dir = os.getcwd()
91 93dcefe7 Carles
        for conf in os.listdir(run_type):
92 93dcefe7 Carles
            i = conf.split('_')[1]
93 670284be Carles
            while get_jobs_status_sge(subm_jobs).count('q') >= max_qw:
94 99afde40 Carles
                sleep(30)
95 99afde40 Carles
            copy(sub_script, f"{run_type}/{conf}")
96 99afde40 Carles
            os.chdir(f"{run_type}/{conf}")
97 7fd58762 Carles
            job_name = f'{name[:6].capitalize()}{run_type[:3].capitalize()}{i}'
98 99afde40 Carles
            subm_jobs.append(qsub(sub_script, name=job_name))
99 b05058e1 Carles
            os.chdir(init_dir)
100 99afde40 Carles
101 bd573212 Carles
        logger.info('All jobs have been submitted, waiting them to finish')
102 bd573212 Carles
        while not all([stat == 'f' for stat in get_jobs_status_sge(subm_jobs)]):
103 bd573212 Carles
            sleep(30)
104 bd573212 Carles
        logger.info('All jobs have finished')
105 426c4e60 Carles
106 99afde40 Carles
107 f3004731 Carles
def run_calc(run_type, inp_vars, atms_list):
108 3d6a9d3c Carles
    """Directs the calculation run according to the provided arguments.
109 3d6a9d3c Carles

110 f3004731 Carles
    @param run_type: Type of calculation. 'isolated', 'screening' or
111 f3004731 Carles
    'refinement'
112 3d6a9d3c Carles
    @param inp_vars: Calculation parameters from input file.
113 f3004731 Carles
    @param atms_list: List of ase.Atoms objects containing the sets of atoms
114 f3004731 Carles
    aimed to run the calculations of.
115 3d6a9d3c Carles
    """
116 3d6a9d3c Carles
    run_types = ['isolated', 'screening', 'refinement']
117 bd573212 Carles
    run_type_err = f"'run_type' must be one of the following: {run_types}"
118 3d6a9d3c Carles
    if not isinstance(run_type, str) or run_type.lower() not in run_types:
119 3d6a9d3c Carles
        logger.error(run_type_err)
120 3d6a9d3c Carles
        raise ValueError(run_type_err)
121 3d6a9d3c Carles
122 3d6a9d3c Carles
    logger.info(f"Running {run_type} calculation with {inp_vars['code']} on "
123 3d6a9d3c Carles
                f"{inp_vars['batch_q_sys']}")
124 c3cb279a Carles
    check_bak(run_type)
125 c3cb279a Carles
    os.mkdir(run_type)
126 a5f73b4c Carles
    if inp_vars['code'] == 'cp2k':
127 a5f73b4c Carles
        prep_cp2k(inp_vars['isol_inp_file'], run_type, atms_list)
128 a5f73b4c Carles
    # elif: inp_vars['code'] == 'Other codes here'
129 99afde40 Carles
130 99afde40 Carles
    submit(run_type, inp_vars['batch_q_sys'], inp_vars['subm_script'],
131 99afde40 Carles
           inp_vars['max_qw'], inp_vars['project_name'])