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

dockonsurf / modules / dos_input.py @ 4e82c425

Historique | Voir | Annoter | Télécharger (43,75 ko)

1 b77be9ad Carles
"""Functions to deal with DockOnSurf input files.
2 b77be9ad Carles

3 4e82c425 Carles Martí
List of functions:
4 4e82c425 Carles Martí

5 4e82c425 Carles Martí
Auxiliary functions
6 4e82c425 Carles Martí
-------------------
7 0e83e6a6 Carles
str2lst: Converts a string of integers, and groups of them, to a list of lists.
8 0e83e6a6 Carles
check_expect_val: Checks whether the value of an option has an adequate value.
9 4e82c425 Carles Martí
check_inp_files: Checks if the CP2K/VASP input files are consistent.
10 4e82c425 Carles Martí

11 4e82c425 Carles Martí
Functions to read parameters in the Global section
12 4e82c425 Carles Martí
--------------------------------------------------
13 0e83e6a6 Carles
get_run_type: Gets 'run_type' value and checks that its value is acceptable.
14 0e83e6a6 Carles
get_code: Gets 'code' value and checks that its value is acceptable.
15 0e83e6a6 Carles
get_batch_q_sys: Gets 'batch_q_sys' value and checks that its value is
16 4e82c425 Carles Martí
    acceptable.
17 4e82c425 Carles Martí
get_pbc_cell: Gets 'pbc_cell' value and checks that its value is acceptable.
18 4e82c425 Carles Martí
get_subm_script: Gets 'subm_script' value and checks that its value is
19 4e82c425 Carles Martí
    acceptable.
20 4e82c425 Carles Martí
get_project_name: Gets 'project_name' value and checks that its value is
21 4e82c425 Carles Martí
    acceptable.
22 0e83e6a6 Carles
get_relaunch_err: Gets 'relaunch_err' value and checks that its value is
23 4e82c425 Carles Martí
    acceptable. # WARNING: OPTION NOT IMPLEMENTED
24 09c3325a Carles Marti
get_max_jobs: Gets 'max_jobs' value and checks that its value is acceptable.
25 0e83e6a6 Carles
get_special_atoms: Gets 'special_atoms' value and checks that its value is
26 4e82c425 Carles Martí
    acceptable.
27 4e82c425 Carles Martí
get_potcar_dir: Gets 'potcar_dir' value and checks that its value is
28 4e82c425 Carles Martí
    acceptable.
29 4e82c425 Carles Martí

30 4e82c425 Carles Martí
Functions to read parameters in the Isolated section
31 4e82c425 Carles Martí
----------------------------------------------------
32 0e83e6a6 Carles
get_isol_inp_file: Gets 'isol_inp_file' value and checks that its value is
33 4e82c425 Carles Martí
    acceptable.
34 4e82c425 Carles Martí
get_molec_file: Gets 'molec_file' value and checks that its value is acceptable.
35 0e83e6a6 Carles
get_num_conformers: Gets 'num_conformers' value and checks that its value is
36 4e82c425 Carles Martí
    acceptable.
37 4670488d Carles Marti
get_pre_opt: Gets 'pre_opt' value and checks that its value is acceptable.
38 4e82c425 Carles Martí

39 4e82c425 Carles Martí
Functions to read parameters in the Screening section
40 4e82c425 Carles Martí
-----------------------------------------------------
41 0e83e6a6 Carles
get_screen_inp_file: Gets 'screen_inp_file' value and checks that its value is
42 4e82c425 Carles Martí
    acceptable.
43 4e82c425 Carles Martí
get_surf_file: Gets 'surf_file' value and checks that its value is acceptable.
44 0e83e6a6 Carles
get_sites: Gets 'sites' value and checks that its value is acceptable.
45 4e82c425 Carles Martí
get_surf_ctrs2: Gets 'surf_ctrs2' value and checks that its value is acceptable.
46 4e82c425 Carles Martí
get_molec_ctrs: Gets 'molec_ctrs' value and checks that its value is acceptable.
47 4e82c425 Carles Martí
get_molec_ctrs2: Gets 'molec_ctrs2' value and checks that its value is
48 4e82c425 Carles Martí
    acceptable.
49 4e82c425 Carles Martí
get_molec_ctrs3: Gets 'molec_ctrs3' value and checks that its value is
50 4e82c425 Carles Martí
    acceptable.
51 4e82c425 Carles Martí
get_max_helic_angle: Gets 'max_helic_angle' value and checks that its value is
52 4e82c425 Carles Martí
    acceptable.
53 4e82c425 Carles Martí
get_select_magns: Gets 'select_magns' value and checks that its value is
54 4e82c425 Carles Martí
    acceptable.
55 4e82c425 Carles Martí
get_confs_per_magn: Gets 'confs_per_magn' value and checks that its value is
56 4e82c425 Carles Martí
    acceptable.
57 4e82c425 Carles Martí
get_surf_norm_vect: Gets 'surf_norm_vect' value and checks that its value is
58 4e82c425 Carles Martí
    acceptable.
59 4e82c425 Carles Martí
get_adsorption_height: Gets 'adsorption_height' value and checks that its value
60 4e82c425 Carles Martí
    is acceptable.
61 4e82c425 Carles Martí
get_set_angles: Gets 'set_angles' value and checks that its value is
62 4e82c425 Carles Martí
    acceptable.
63 0e83e6a6 Carles
get_pts_per_angle: Gets 'pts_per_angle' value and checks that its value is
64 4e82c425 Carles Martí
    acceptable.
65 4e82c425 Carles Martí
get_max_structures: Gets 'max_structures' value and checks that its value is
66 4e82c425 Carles Martí
    acceptable.
67 0e83e6a6 Carles
get_coll_thrsld: Gets 'coll_thrsld' value and checks that its value is
68 4e82c425 Carles Martí
    acceptable.
69 4e82c425 Carles Martí
get_min_coll_height: Gets 'coll_bottom_z' value and checks that its value is
70 4e82c425 Carles Martí
    acceptable.
71 4e82c425 Carles Martí
get_exclude_ads_ctr: Gets 'exclude_ads_ctr' value and checks that its value is
72 4e82c425 Carles Martí
    acceptable.
73 4e82c425 Carles Martí
get_H_donor: Gets 'H_donor' value and checks that its value is
74 4e82c425 Carles Martí
    acceptable.
75 4e82c425 Carles Martí
get_H_acceptor: Gets 'H_acceptor' value and checks that its value is
76 4e82c425 Carles Martí
    acceptable.
77 4e82c425 Carles Martí
get_use_molec_file: Gets 'use_molec_file' value and checks that its value is
78 4e82c425 Carles Martí
    acceptable.
79 4e82c425 Carles Martí

80 4e82c425 Carles Martí
Functions to read parameters in the Refinement section
81 4e82c425 Carles Martí
------------------------------------------------------
82 0e83e6a6 Carles
get_refine_inp_file: Gets 'refine_inp_file' value and checks that its value is
83 4e82c425 Carles Martí
    acceptable.
84 0e83e6a6 Carles
get_energy_cutoff: Gets 'energy_cutoff' value and checks that its value is
85 4e82c425 Carles Martí
    acceptable.
86 4e82c425 Carles Martí

87 4e82c425 Carles Martí
read_input: Directs the reading of the parameters in the input file
88 17e72a49 Carles
"""
89 8887f41d Carles
import os.path
90 b5b2af64 Carles
import logging
91 8887f41d Carles
from configparser import ConfigParser, NoSectionError, NoOptionError, \
92 8887f41d Carles
    MissingSectionHeaderError, DuplicateOptionError
93 5fb01677 Carles Marti
import numpy as np
94 af3e2441 Carles Marti
from modules.utilities import try_command
95 8887f41d Carles
96 8887f41d Carles
logger = logging.getLogger('DockOnSurf')
97 8887f41d Carles
98 8887f41d Carles
dos_inp = ConfigParser(inline_comment_prefixes='#',
99 8887f41d Carles
                       empty_lines_in_values=False)
100 4e82c425 Carles Martí
# Define new answers to be interpreted as True or False.
101 8887f41d Carles
new_answers = {'n': False, 'none': False, 'nay': False,
102 8887f41d Carles
               'y': True, '': True, 'aye': True, 'sure': True}
103 8887f41d Carles
for answer, val in new_answers.items():
104 9cd032cf Carles Marti
    dos_inp.BOOLEAN_STATES[answer] = val  # TODO Check value 0
105 8887f41d Carles
turn_false_answers = [answer for answer in dos_inp.BOOLEAN_STATES
106 8887f41d Carles
                      if dos_inp.BOOLEAN_STATES[answer] is False]
107 9cd032cf Carles Marti
turn_true_answers = [answer for answer in dos_inp.BOOLEAN_STATES
108 9cd032cf Carles Marti
                     if dos_inp.BOOLEAN_STATES[answer]]
109 8887f41d Carles
110 4e82c425 Carles Martí
# Template error messages to be customized in place.
111 8887f41d Carles
no_sect_err = "Section '%s' not found on input file"
112 8887f41d Carles
no_opt_err = "Option '%s' not found on section '%s'"
113 8887f41d Carles
num_error = "'%s' value must be a %s"
114 8887f41d Carles
115 4533134f Carles Marti
116 14e0b660 Carles Martí
# Auxilary functions
117 14e0b660 Carles Martí
118 4533134f Carles Marti
def str2lst(cmplx_str, func=int):  # TODO: enable deeper level of nested lists
119 a7128ce1 Carles Marti
    # TODO Treat all-enclosing parenthesis as a list instead of list of lists.
120 4e82c425 Carles Martí
    """Converts a string of integers/floats, and groups of them, to a list.
121 b77be9ad Carles

122 b77be9ad Carles
    Keyword arguments:
123 4533134f Carles Marti
    @param cmplx_str: str, string of integers (or floats) and groups of them
124 4533134f Carles Marti
    enclosed by parentheses-like characters.
125 b77be9ad Carles
    - Group enclosers: '()' '[]' and '{}'.
126 4533134f Carles Marti
    - Separators: ',' ';' and ' '.
127 b77be9ad Carles
    - Nested groups are not allowed: '3 ((6 7) 8) 4'.
128 4533134f Carles Marti
    @param func: either to use int or float
129 b77be9ad Carles

130 4533134f Carles Marti
    @return list, list of integers (or floats), or list of integers (or floats)
131 4533134f Carles Marti
    in the case they were grouped. First, the singlets are placed, and then the
132 4533134f Carles Marti
    groups in input order.
133 b77be9ad Carles

134 b77be9ad Carles
    eg. '128,(135 138;141] 87 {45, 68}' -> [128, 87, [135, 138, 141], [45, 68]]
135 17e72a49 Carles
    """
136 b77be9ad Carles
137 8887f41d Carles
    # Checks
138 5261a07f Carles Marti
    error_msg = "Function argument should be a str, sequence of " \
139 8887f41d Carles
                "numbers separated by ',' ';' or ' '." \
140 79e3db42 Carles
                "\nThey can be grouped in parentheses-like enclosers: '()', " \
141 79e3db42 Carles
                "'[]' or {}. Nested groups are not allowed. \n" \
142 79e3db42 Carles
                "eg. 128,(135 138;141) 87 {45, 68}"
143 8887f41d Carles
    cmplx_str = try_command(cmplx_str.replace, [(AttributeError, error_msg)],
144 8887f41d Carles
                            ',', ' ')
145 8887f41d Carles
146 8887f41d Carles
    cmplx_str = cmplx_str.replace(';', ' ').replace('[', '(').replace(
147 8887f41d Carles
        ']', ')').replace('{', '(').replace('}', ')')
148 8887f41d Carles
149 4533134f Carles Marti
    try_command(list, [(ValueError, error_msg)], map(func, cmplx_str.replace(
150 8887f41d Carles
        ')', '').replace('(', '').split()))
151 8887f41d Carles
152 b5b2af64 Carles
    deepness = 0
153 b5b2af64 Carles
    for el in cmplx_str.split():
154 b5b2af64 Carles
        if '(' in el:
155 b5b2af64 Carles
            deepness += 1
156 b5b2af64 Carles
        if ')' in el:
157 b5b2af64 Carles
            deepness += -1
158 b5b2af64 Carles
        if deepness > 1 or deepness < 0:
159 9f7bb440 Carles
            logger.error(error_msg)
160 b5b2af64 Carles
            raise ValueError(error_msg)
161 17e72a49 Carles
162 772b40e5 Carles
    init_list = cmplx_str.split()
163 772b40e5 Carles
    start_group = []
164 772b40e5 Carles
    end_group = []
165 772b40e5 Carles
    for i, element in enumerate(init_list):
166 73402e22 Carles
        if '(' in element:
167 772b40e5 Carles
            start_group.append(i)
168 17e72a49 Carles
            init_list[i] = element.replace('(', '')
169 73402e22 Carles
        if ')' in element:
170 772b40e5 Carles
            end_group.append(i)
171 17e72a49 Carles
            init_list[i] = element.replace(')', '')
172 772b40e5 Carles
173 4533134f Carles Marti
    init_list = list(map(func, init_list))
174 772b40e5 Carles
175 17e72a49 Carles
    new_list = []
176 772b40e5 Carles
    for start_el, end_el in zip(start_group, end_group):
177 17e72a49 Carles
        new_list.append(init_list[start_el:end_el + 1])
178 772b40e5 Carles
179 772b40e5 Carles
    for v in new_list:
180 772b40e5 Carles
        for el in v:
181 772b40e5 Carles
            init_list.remove(el)
182 772b40e5 Carles
    return init_list + new_list
183 772b40e5 Carles
184 17e72a49 Carles
185 5f9f1400 Carles Marti
def check_expect_val(value, expect_vals, err_msg=None):
186 b77be9ad Carles
    """Checks whether an option lies within its expected values.
187 b77be9ad Carles

188 b77be9ad Carles
    Keyword arguments:
189 b77be9ad Carles
    @param value: The variable to check if its value lies within the expected
190 b77be9ad Carles
    ones
191 b77be9ad Carles
    @param expect_vals: list, list of values allowed for the present option.
192 5f9f1400 Carles Marti
    @param err_msg: The error message to be prompted in both log and screen.
193 b77be9ad Carles
    @raise ValueError: if the value is not among the expected ones.
194 b77be9ad Carles
    @return True if the value is among the expected ones.
195 b77be9ad Carles
    """
196 5f9f1400 Carles Marti
    if err_msg is None:
197 5f9f1400 Carles Marti
        err_msg = f"'{value}' is not an adequate value.\n" \
198 5f9f1400 Carles Marti
                  f"Adequate values: {expect_vals}"
199 821dca42 Carles Marti
    if not any([exp_val == value for exp_val in expect_vals]):
200 5f9f1400 Carles Marti
        logger.error(err_msg)
201 5f9f1400 Carles Marti
        raise ValueError(err_msg)
202 b77be9ad Carles
203 b77be9ad Carles
    return True
204 b77be9ad Carles
205 b77be9ad Carles
206 4e82c425 Carles Martí
def check_inp_files(inp_files, code: str, potcar_dir=None):
207 4e82c425 Carles Martí
    """Checks if the CP2K/VASP input files are consistent.
208 4e82c425 Carles Martí

209 4e82c425 Carles Martí
    @param inp_files: List of input files
210 4e82c425 Carles Martí
    @param code: The code for which the input files are for (VASP or CP2K).
211 4e82c425 Carles Martí
    @param potcar_dir: The path where POTCARs are found
212 4e82c425 Carles Martí
    @return: None
213 4e82c425 Carles Martí
    """
214 03fab2dd Carles
    if code == 'cp2k':
215 03fab2dd Carles
        from pycp2k import CP2K
216 9d3b680c Carles Martí
        if not isinstance(inp_files, str):
217 9d3b680c Carles Martí
            err_msg = "When using CP2K, only one input file is allowed"
218 9d3b680c Carles Martí
            logger.error(err_msg)
219 9d3b680c Carles Martí
            ValueError(err_msg)
220 9d3b680c Carles Martí
        elif not os.path.isfile(inp_files):
221 9d3b680c Carles Martí
            err_msg = f"Input file {inp_files} was not found."
222 9d3b680c Carles Martí
            logger.error(err_msg)
223 9d3b680c Carles Martí
            raise FileNotFoundError(err_msg)
224 03fab2dd Carles
        cp2k = CP2K()
225 03fab2dd Carles
        try_command(cp2k.parse,
226 9d3b680c Carles Martí
                    [(UnboundLocalError, "Invalid CP2K input file")], inp_files)
227 9d3b680c Carles Martí
    elif code == "vasp":
228 f349bb54 Carles
        if not potcar_dir:
229 f349bb54 Carles
            mand_files = ["INCAR", "KPOINTS", "POTCAR"]
230 f349bb54 Carles
        else:
231 f349bb54 Carles
            mand_files = ["INCAR", "KPOINTS"]
232 f349bb54 Carles
            if any("POTCAR" in inp_file for inp_file in inp_files):
233 f349bb54 Carles
                logger.warning("A POTCAR file was specified as input file "
234 f349bb54 Carles
                               "while the automatic generation of POTCAR was "
235 f349bb54 Carles
                               "also enabled via the 'potcar_dir' keyword. The "
236 f349bb54 Carles
                               "POTCAR specified as input_file will be used "
237 f349bb54 Carles
                               "instead of the auto-generated one.")
238 4e82c425 Carles Martí
        # Check that if inp_files is a list of file paths
239 9d3b680c Carles Martí
        if not isinstance(inp_files, list) and all(isinstance(inp_file, str)
240 9d3b680c Carles Martí
                                                   for inp_file in inp_files):
241 9d3b680c Carles Martí
            err_msg = "'inp_files' should be a list of file names/paths"
242 9d3b680c Carles Martí
            logger.error(err_msg)
243 f349bb54 Carles
            raise ValueError(err_msg)
244 9d3b680c Carles Martí
        # Check that all mandatory files are defined once and just once.
245 9d3b680c Carles Martí
        elif [[mand_file in inp_file for inp_file in inp_files].count(True)
246 9d3b680c Carles Martí
              for mand_file in mand_files].count(1) != len(mand_files):
247 9d3b680c Carles Martí
            err_msg = f"Each of the mandatory files {mand_files} must be " \
248 9d3b680c Carles Martí
                      f"defined once and just once."
249 9d3b680c Carles Martí
            logger.error(err_msg)
250 9d3b680c Carles Martí
            raise FileNotFoundError(err_msg)
251 9d3b680c Carles Martí
        # Check that the defined files exist
252 9d3b680c Carles Martí
        elif any(not os.path.isfile(inp_file) for inp_file in inp_files):
253 9d3b680c Carles Martí
            err_msg = f"At least one of the mandatory files {mand_files} was " \
254 9d3b680c Carles Martí
                      "not found."
255 9d3b680c Carles Martí
            logger.error(err_msg)
256 9d3b680c Carles Martí
            raise FileNotFoundError(err_msg)
257 9d3b680c Carles Martí
        # Check that mandatory files are actual vasp files.
258 9d3b680c Carles Martí
        else:
259 9d3b680c Carles Martí
            from pymatgen.io.vasp.inputs import Incar, Kpoints, Potcar
260 9d3b680c Carles Martí
            for inp_file in inp_files:
261 9d3b680c Carles Martí
                file_name = inp_file.split("/")[-1]
262 9d3b680c Carles Martí
                if not any(mand_file in file_name for mand_file in mand_files):
263 9d3b680c Carles Martí
                    continue
264 9d3b680c Carles Martí
                file_type = ""
265 9d3b680c Carles Martí
                for mand_file in mand_files:
266 9d3b680c Carles Martí
                    if mand_file in inp_file:
267 9d3b680c Carles Martí
                        file_type = mand_file
268 9d3b680c Carles Martí
                err = False
269 9d3b680c Carles Martí
                err_msg = f"'{inp_file}' is not a valid {file_name} file."
270 9d3b680c Carles Martí
                try:
271 9d3b680c Carles Martí
                    eval(file_type.capitalize()).from_file(inp_file)
272 9d3b680c Carles Martí
                except ValueError:
273 9d3b680c Carles Martí
                    logger.error(err_msg)
274 9d3b680c Carles Martí
                    err = ValueError(err_msg)
275 9d3b680c Carles Martí
                except IndexError:
276 9d3b680c Carles Martí
                    logger.error(err_msg)
277 9d3b680c Carles Martí
                    err = IndexError(err_msg)
278 9d3b680c Carles Martí
                else:
279 9d3b680c Carles Martí
                    if file_name == "INCAR":
280 9d3b680c Carles Martí
                        Incar.from_file("INCAR").check_params()
281 9d3b680c Carles Martí
                finally:
282 9d3b680c Carles Martí
                    if isinstance(err, BaseException):
283 9d3b680c Carles Martí
                        raise err
284 03fab2dd Carles
285 03fab2dd Carles
286 a7128ce1 Carles Marti
# Global
287 a7128ce1 Carles Marti
288 8887f41d Carles
def get_run_type():
289 b1d27be5 Carles
    isolated, screening, refinement = (False, False, False)
290 5cc4994b Carles
    run_type_vals = ['isolated', 'screening', 'refinement', 'adsorption',
291 5cc4994b Carles
                     'full']
292 081548a0 Carles Marti
    run_types = dos_inp.get('Global', 'run_type').split()
293 081548a0 Carles Marti
    for run_type in run_types:
294 081548a0 Carles Marti
        check_expect_val(run_type.lower(), run_type_vals)
295 081548a0 Carles Marti
        if 'isol' in run_type.lower():
296 081548a0 Carles Marti
            isolated = True
297 081548a0 Carles Marti
        if 'screen' in run_type.lower():
298 081548a0 Carles Marti
            screening = True
299 081548a0 Carles Marti
        if 'refine' in run_type.lower():
300 081548a0 Carles Marti
            refinement = True
301 081548a0 Carles Marti
        if 'adsor' in run_type.lower():
302 081548a0 Carles Marti
            screening, refinement = (True, True)
303 081548a0 Carles Marti
        if 'full' in run_type.lower():
304 081548a0 Carles Marti
            isolated, screening, refinement = (True, True, True)
305 5cc4994b Carles
306 8887f41d Carles
    return isolated, screening, refinement
307 17e72a49 Carles
308 8887f41d Carles
309 8887f41d Carles
def get_code():
310 9d3b680c Carles Martí
    code_vals = ['cp2k', 'vasp']
311 5cc4994b Carles
    check_expect_val(dos_inp.get('Global', 'code').lower(), code_vals)
312 5cc4994b Carles
    code = dos_inp.get('Global', 'code').lower()
313 8887f41d Carles
    return code
314 8887f41d Carles
315 17e72a49 Carles
316 8887f41d Carles
def get_batch_q_sys():
317 ec5bba46 Carles Marti
    batch_q_sys_vals = ['sge', 'lsf', 'irene', 'local'] + turn_false_answers
318 5cc4994b Carles
    check_expect_val(dos_inp.get('Global', 'batch_q_sys').lower(),
319 5cc4994b Carles
                     batch_q_sys_vals)
320 5cc4994b Carles
    batch_q_sys = dos_inp.get('Global', 'batch_q_sys').lower()
321 821dca42 Carles Marti
    if batch_q_sys.lower() in turn_false_answers:
322 821dca42 Carles Marti
        return False
323 821dca42 Carles Marti
    else:
324 821dca42 Carles Marti
        return batch_q_sys
325 17e72a49 Carles
326 8887f41d Carles
327 9d3b680c Carles Martí
def get_pbc_cell():
328 a5d76bfb Carles Martí
    from ase.atoms import Cell
329 9d3b680c Carles Martí
    err_msg = "'pbc_cell' must be either 3 vectors of size 3 or False."
330 9d3b680c Carles Martí
    pbc_cell_str = dos_inp.get('Global', 'pbc_cell', fallback="False")
331 9d3b680c Carles Martí
    if pbc_cell_str.lower() in turn_false_answers:
332 9d3b680c Carles Martí
        return False
333 9d3b680c Carles Martí
    else:
334 9d3b680c Carles Martí
        pbc_cell = np.array(try_command(str2lst, [(ValueError, err_msg)],
335 9d3b680c Carles Martí
                                        pbc_cell_str, float))
336 9d3b680c Carles Martí
        if pbc_cell.shape != (3, 3):
337 9d3b680c Carles Martí
            logger.error(err_msg)
338 9d3b680c Carles Martí
            raise ValueError(err_msg)
339 9d3b680c Carles Martí
        if np.linalg.det(pbc_cell) == 0.0:
340 9d3b680c Carles Martí
            err_msg = "The volume of the defined cell is 0"
341 9d3b680c Carles Martí
            logger.error(err_msg)
342 9d3b680c Carles Martí
            raise ValueError(err_msg)
343 a5d76bfb Carles Martí
        return Cell(pbc_cell)
344 9d3b680c Carles Martí
345 9d3b680c Carles Martí
346 99afde40 Carles
def get_subm_script():
347 14e0b660 Carles Martí
    subm_script = dos_inp.get('Global', 'subm_script')
348 14e0b660 Carles Martí
    if not os.path.isfile(subm_script):
349 695dcff8 Carles Marti
        logger.error(f'File {subm_script} not found.')
350 99afde40 Carles
        raise FileNotFoundError(f'File {subm_script} not found')
351 99afde40 Carles
    return subm_script
352 99afde40 Carles
353 99afde40 Carles
354 99afde40 Carles
def get_project_name():
355 bd573212 Carles
    project_name = dos_inp.get('Global', 'project_name', fallback='')
356 99afde40 Carles
    return project_name
357 99afde40 Carles
358 99afde40 Carles
359 8887f41d Carles
def get_relaunch_err():
360 4e82c425 Carles Martí
    # WARNING: OPTION NOT IMPLEMENTED
361 09c3325a Carles Marti
    relaunch_err_vals = ['geo_not_conv']
362 b1d27be5 Carles
    relaunch_err = dos_inp.get('Global', 'relaunch_err',
363 17e72a49 Carles
                               fallback="False")
364 b1d27be5 Carles
    if relaunch_err.lower() in turn_false_answers:
365 8887f41d Carles
        return False
366 79e3db42 Carles
    else:
367 79e3db42 Carles
        check_expect_val(relaunch_err.lower(), relaunch_err_vals)
368 8887f41d Carles
    return relaunch_err
369 8887f41d Carles
370 8887f41d Carles
371 09c3325a Carles Marti
def get_max_jobs():
372 b6b1b03e Carles Marti
    import re
373 b6b1b03e Carles Marti
    err_msg = "'max_jobs' must be a list of, number plus 'p', 'q' or 'r', or " \
374 b6b1b03e Carles Marti
              "a combination of them without repeating letters.\n" \
375 b6b1b03e Carles Marti
              "eg: '2r 3p 4pr', '5q' or '3r 3p'"
376 b6b1b03e Carles Marti
    max_jobs_str = dos_inp.get('Global', 'max_jobs', fallback="inf").lower()
377 b6b1b03e Carles Marti
    str_vals = ["r", "p", "q", "rp", "rq", "pr", "qr"]
378 b6b1b03e Carles Marti
    max_jobs = {"r": np.inf, "p": np.inf, "rp": np.inf}
379 b6b1b03e Carles Marti
    if "inf" == max_jobs_str:
380 b6b1b03e Carles Marti
        return {"r": np.inf, "p": np.inf, "rp": np.inf}
381 b6b1b03e Carles Marti
    # Iterate over the number of requirements:
382 b6b1b03e Carles Marti
    for req in max_jobs_str.split():
383 b6b1b03e Carles Marti
        # Split numbers from letters into a list
384 b6b1b03e Carles Marti
        req_parts = re.findall(r'[a-z]+|\d+', req)
385 b6b1b03e Carles Marti
        if len(req_parts) != 2:
386 b6b1b03e Carles Marti
            logger.error(err_msg)
387 b6b1b03e Carles Marti
            raise ValueError(err_msg)
388 b6b1b03e Carles Marti
        if req_parts[0].isdecimal():
389 b6b1b03e Carles Marti
            req_parts[1] = req_parts[1].replace('q', 'p').replace('pr', 'rp')
390 b6b1b03e Carles Marti
            if req_parts[1] in str_vals and max_jobs[req_parts[1]] == np.inf:
391 b6b1b03e Carles Marti
                max_jobs[req_parts[1]] = int(req_parts[0])
392 b6b1b03e Carles Marti
        elif req_parts[1].isdecimal():
393 b6b1b03e Carles Marti
            req_parts[0] = req_parts[0].replace('q', 'p').replace('pr', 'rp')
394 b6b1b03e Carles Marti
            if req_parts[0] in str_vals and max_jobs[req_parts[0]] == np.inf:
395 b6b1b03e Carles Marti
                max_jobs[req_parts[0]] = int(req_parts[1])
396 b6b1b03e Carles Marti
        else:
397 b6b1b03e Carles Marti
            logger.error(err_msg)
398 b6b1b03e Carles Marti
            raise ValueError(err_msg)
399 09c3325a Carles Marti
400 09c3325a Carles Marti
    return max_jobs
401 09c3325a Carles Marti
402 09c3325a Carles Marti
403 8887f41d Carles
def get_special_atoms():
404 8887f41d Carles
    from ase.data import chemical_symbols
405 17e72a49 Carles
406 5cc4994b Carles
    spec_at_err = '\'special_atoms\' does not have an adequate format.\n' \
407 5cc4994b Carles
                  'Adequate format: (Fe1 Fe) (O1 O)'
408 5cc4994b Carles
    special_atoms = dos_inp.get('Global', 'special_atoms', fallback="False")
409 b1d27be5 Carles
    if special_atoms.lower() in turn_false_answers:
410 90819cc3 Carles Marti
        special_atoms = []
411 b1d27be5 Carles
    else:
412 8949edd0 Carles
        # Converts the string into a list of tuples
413 8949edd0 Carles
        lst_tple = [tuple(pair.replace("(", "").split()) for pair in
414 b1d27be5 Carles
                    special_atoms.split(")")[:-1]]
415 5cc4994b Carles
        if len(lst_tple) == 0:
416 9f7bb440 Carles
            logger.error(spec_at_err)
417 5cc4994b Carles
            raise ValueError(spec_at_err)
418 9f7bb440 Carles
        for i, tup in enumerate(lst_tple):
419 90819cc3 Carles Marti
            if not isinstance(tup, tuple) or len(tup) != 2:
420 9f7bb440 Carles
                logger.error(spec_at_err)
421 5cc4994b Carles
                raise ValueError(spec_at_err)
422 5cc4994b Carles
            if tup[1].capitalize() not in chemical_symbols:
423 5cc4994b Carles
                elem_err = "The second element of the couple should be an " \
424 9f7bb440 Carles
                           "actual element of the periodic table"
425 9f7bb440 Carles
                logger.error(elem_err)
426 5cc4994b Carles
                raise ValueError(elem_err)
427 9f7bb440 Carles
            if tup[0].capitalize() in chemical_symbols:
428 9f7bb440 Carles
                elem_err = "The first element of the couple is already an " \
429 9f7bb440 Carles
                           "actual element of the periodic table, "
430 9f7bb440 Carles
                logger.error(elem_err)
431 9f7bb440 Carles
                raise ValueError(elem_err)
432 9f7bb440 Carles
            for j, tup2 in enumerate(lst_tple):
433 9f7bb440 Carles
                if j <= i:
434 9f7bb440 Carles
                    continue
435 9f7bb440 Carles
                if tup2[0] == tup[0]:
436 9f7bb440 Carles
                    label_err = f'You have specified the label {tup[0]} to ' \
437 8887f41d Carles
                                f'more than one special atom'
438 9f7bb440 Carles
                    logger.error(label_err)
439 9f7bb440 Carles
                    raise ValueError(label_err)
440 b1d27be5 Carles
        special_atoms = lst_tple
441 8887f41d Carles
    return special_atoms
442 8887f41d Carles
443 8887f41d Carles
444 f349bb54 Carles
def get_potcar_dir():
445 f349bb54 Carles
    potcar_dir = dos_inp.get('Global', 'potcar_dir', fallback="False")
446 f349bb54 Carles
    if potcar_dir.lower() in turn_false_answers:
447 f349bb54 Carles
        return False
448 f349bb54 Carles
    elif not os.path.isdir(potcar_dir):
449 f349bb54 Carles
        err_msg = "'potcar_dir' must be either False or a directory."
450 f349bb54 Carles
        logger.error(err_msg)
451 f349bb54 Carles
        raise ValueError(err_msg)
452 f349bb54 Carles
    else:
453 f349bb54 Carles
        return potcar_dir
454 f349bb54 Carles
455 f349bb54 Carles
456 a7128ce1 Carles Marti
# Isolated
457 a7128ce1 Carles Marti
458 7d37379d Carles Martí
def get_isol_inp_file(code, potcar_dir=None):  # TODO allow spaces in path names
459 9d3b680c Carles Martí
    inp_file_lst = dos_inp.get('Isolated', 'isol_inp_file').split()
460 f349bb54 Carles
    check_inp_files(inp_file_lst[0] if len(inp_file_lst) == 1 else inp_file_lst,
461 f349bb54 Carles
                    code, potcar_dir)
462 9d3b680c Carles Martí
    return inp_file_lst[0] if len(inp_file_lst) == 1 else inp_file_lst
463 8887f41d Carles
464 8887f41d Carles
465 95dc2c8e Carles
def get_molec_file():
466 95dc2c8e Carles
    molec_file = dos_inp.get('Isolated', 'molec_file')
467 95dc2c8e Carles
    if not os.path.isfile(molec_file):
468 695dcff8 Carles Marti
        logger.error(f'File {molec_file} not found.')
469 95dc2c8e Carles
        raise FileNotFoundError(f'File {molec_file} not found')
470 95dc2c8e Carles
    return molec_file
471 95dc2c8e Carles
472 95dc2c8e Carles
473 8887f41d Carles
def get_num_conformers():
474 8887f41d Carles
    err_msg = num_error % ('num_conformers', 'positive integer')
475 8887f41d Carles
    num_conformers = try_command(dos_inp.getint, [(ValueError, err_msg)],
476 8887f41d Carles
                                 'Isolated', 'num_conformers', fallback=100)
477 8887f41d Carles
    if num_conformers < 1:
478 8887f41d Carles
        logger.error(err_msg)
479 8887f41d Carles
        raise ValueError(err_msg)
480 8887f41d Carles
    return num_conformers
481 8887f41d Carles
482 8887f41d Carles
483 4670488d Carles Marti
def get_pre_opt():
484 4670488d Carles Marti
    pre_opt_vals = ['uff', 'mmff'] + turn_false_answers
485 4670488d Carles Marti
    check_expect_val(dos_inp.get('Isolated', 'pre_opt').lower(), pre_opt_vals)
486 ad57fd42 Carles Marti
    pre_opt = dos_inp.get('Isolated', 'pre_opt').lower()
487 ad57fd42 Carles Marti
    if pre_opt in turn_false_answers:
488 4670488d Carles Marti
        return False
489 4670488d Carles Marti
    else:
490 4670488d Carles Marti
        return pre_opt
491 b1f6e69d Carles
492 70fa4e74 Carles Marti
493 a7128ce1 Carles Marti
# Screening
494 a7128ce1 Carles Marti
495 7d37379d Carles Martí
def get_screen_inp_file(code,
496 7d37379d Carles Martí
                        potcar_dir=None):  # TODO allow spaces in path names
497 9d3b680c Carles Martí
    inp_file_lst = dos_inp.get('Screening', 'screen_inp_file').split()
498 f349bb54 Carles
    check_inp_files(inp_file_lst[0] if len(inp_file_lst) == 1 else inp_file_lst,
499 f349bb54 Carles
                    code, potcar_dir)
500 9d3b680c Carles Martí
    return inp_file_lst[0] if len(inp_file_lst) == 1 else inp_file_lst
501 8887f41d Carles
502 8887f41d Carles
503 a765b11c Carles Marti
def get_surf_file():
504 a765b11c Carles Marti
    surf_file = dos_inp.get('Screening', 'surf_file')
505 a765b11c Carles Marti
    if not os.path.isfile(surf_file):
506 695dcff8 Carles Marti
        logger.error(f'File {surf_file} not found.')
507 a765b11c Carles Marti
        raise FileNotFoundError(f'File {surf_file} not found')
508 a765b11c Carles Marti
    return surf_file
509 a765b11c Carles Marti
510 a765b11c Carles Marti
511 8887f41d Carles
def get_sites():
512 8887f41d Carles
    err_msg = 'The value of sites should be a list of atom numbers ' \
513 8887f41d Carles
              '(ie. positive integers) or groups of atom numbers ' \
514 8887f41d Carles
              'grouped by parentheses-like enclosers. \n' \
515 8887f41d Carles
              'eg. 128,(135 138;141) 87 {45, 68}'
516 8887f41d Carles
    # Convert the string into a list of lists
517 8887f41d Carles
    sites = try_command(str2lst,
518 8887f41d Carles
                        [(ValueError, err_msg), (AttributeError, err_msg)],
519 8887f41d Carles
                        dos_inp.get('Screening', 'sites'))
520 8887f41d Carles
    # Check all elements of the list (of lists) are positive integers
521 8887f41d Carles
    for site in sites:
522 8887f41d Carles
        if type(site) is list:
523 8887f41d Carles
            for atom in site:
524 8887f41d Carles
                if atom < 0:
525 8887f41d Carles
                    logger.error(err_msg)
526 8887f41d Carles
                    raise ValueError(err_msg)
527 8887f41d Carles
        elif type(site) is int:
528 8887f41d Carles
            if site < 0:
529 8887f41d Carles
                logger.error(err_msg)
530 8887f41d Carles
                raise ValueError(err_msg)
531 8887f41d Carles
        else:
532 8887f41d Carles
            logger.error(err_msg)
533 8887f41d Carles
            raise ValueError(err_msg)
534 8887f41d Carles
535 8887f41d Carles
    return sites
536 8887f41d Carles
537 8887f41d Carles
538 7dd94df7 Carles Marti
def get_surf_ctrs2():
539 7dd94df7 Carles Marti
    err_msg = 'The value of surf_ctrs2 should be a list of atom numbers ' \
540 7dd94df7 Carles Marti
              '(ie. positive integers) or groups of atom numbers ' \
541 7dd94df7 Carles Marti
              'grouped by parentheses-like enclosers. \n' \
542 7dd94df7 Carles Marti
              'eg. 128,(135 138;141) 87 {45, 68}'
543 7dd94df7 Carles Marti
    # Convert the string into a list of lists
544 7dd94df7 Carles Marti
    surf_ctrs2 = try_command(str2lst,
545 7dd94df7 Carles Marti
                             [(ValueError, err_msg), (AttributeError, err_msg)],
546 7dd94df7 Carles Marti
                             dos_inp.get('Screening', 'surf_ctrs2'))
547 7dd94df7 Carles Marti
    # Check all elements of the list (of lists) are positive integers
548 7dd94df7 Carles Marti
    for ctr in surf_ctrs2:
549 7dd94df7 Carles Marti
        if type(ctr) is list:
550 7dd94df7 Carles Marti
            for atom in ctr:
551 7dd94df7 Carles Marti
                if atom < 0:
552 7dd94df7 Carles Marti
                    logger.error(err_msg)
553 7dd94df7 Carles Marti
                    raise ValueError(err_msg)
554 7dd94df7 Carles Marti
        elif type(ctr) is int:
555 7dd94df7 Carles Marti
            if ctr < 0:
556 7dd94df7 Carles Marti
                logger.error(err_msg)
557 7dd94df7 Carles Marti
                raise ValueError(err_msg)
558 7dd94df7 Carles Marti
        else:
559 7dd94df7 Carles Marti
            logger.error(err_msg)
560 7dd94df7 Carles Marti
            raise ValueError(err_msg)
561 7dd94df7 Carles Marti
562 7dd94df7 Carles Marti
    return surf_ctrs2
563 7dd94df7 Carles Marti
564 7dd94df7 Carles Marti
565 7dd94df7 Carles Marti
def get_molec_ctrs():
566 7dd94df7 Carles Marti
    err_msg = 'The value of molec_ctrs should be a list of atom' \
567 8887f41d Carles
              ' numbers (ie. positive integers) or groups of atom ' \
568 8887f41d Carles
              'numbers enclosed by parentheses-like characters. \n' \
569 8887f41d Carles
              'eg. 128,(135 138;141) 87 {45, 68}'
570 8887f41d Carles
    # Convert the string into a list of lists
571 7dd94df7 Carles Marti
    molec_ctrs = try_command(str2lst,
572 7dd94df7 Carles Marti
                             [(ValueError, err_msg),
573 7dd94df7 Carles Marti
                              (AttributeError, err_msg)],
574 7dd94df7 Carles Marti
                             dos_inp.get('Screening', 'molec_ctrs'))
575 7dd94df7 Carles Marti
    # Check all elements of the list (of lists) are positive integers
576 7dd94df7 Carles Marti
    for ctr in molec_ctrs:
577 7dd94df7 Carles Marti
        if isinstance(ctr, list):
578 7dd94df7 Carles Marti
            for atom in ctr:
579 7dd94df7 Carles Marti
                if atom < 0:
580 7dd94df7 Carles Marti
                    logger.error(err_msg)
581 7dd94df7 Carles Marti
                    raise ValueError(err_msg)
582 7dd94df7 Carles Marti
        elif isinstance(ctr, int):
583 7dd94df7 Carles Marti
            if ctr < 0:
584 7dd94df7 Carles Marti
                logger.error(err_msg)
585 7dd94df7 Carles Marti
                raise ValueError(err_msg)
586 7dd94df7 Carles Marti
        else:
587 7dd94df7 Carles Marti
            logger.error(err_msg)
588 7dd94df7 Carles Marti
            raise ValueError(err_msg)
589 7dd94df7 Carles Marti
590 7dd94df7 Carles Marti
    return molec_ctrs
591 7dd94df7 Carles Marti
592 7dd94df7 Carles Marti
593 7dd94df7 Carles Marti
def get_molec_ctrs2():
594 7dd94df7 Carles Marti
    err_msg = 'The value of molec_ctrs2 should be a list of atom ' \
595 7dd94df7 Carles Marti
              'numbers (ie. positive integers) or groups of atom ' \
596 7dd94df7 Carles Marti
              'numbers enclosed by parentheses-like characters. \n' \
597 7dd94df7 Carles Marti
              'eg. 128,(135 138;141) 87 {45, 68}'
598 7dd94df7 Carles Marti
    # Convert the string into a list of lists
599 7dd94df7 Carles Marti
    molec_ctrs2 = try_command(str2lst, [(ValueError, err_msg),
600 7dd94df7 Carles Marti
                                        (AttributeError, err_msg)],
601 7dd94df7 Carles Marti
                              dos_inp.get('Screening', 'molec_ctrs2'))
602 7dd94df7 Carles Marti
603 8887f41d Carles
    # Check all elements of the list (of lists) are positive integers
604 7dd94df7 Carles Marti
    for ctr in molec_ctrs2:
605 c845c6f2 Carles Marti
        if isinstance(ctr, list):
606 8887f41d Carles
            for atom in ctr:
607 8887f41d Carles
                if atom < 0:
608 8887f41d Carles
                    logger.error(err_msg)
609 8887f41d Carles
                    raise ValueError(err_msg)
610 c845c6f2 Carles Marti
        elif isinstance(ctr, int):
611 8887f41d Carles
            if ctr < 0:
612 8887f41d Carles
                logger.error(err_msg)
613 8887f41d Carles
                raise ValueError(err_msg)
614 8887f41d Carles
        else:
615 8887f41d Carles
            logger.error(err_msg)
616 8887f41d Carles
            raise ValueError(err_msg)
617 8887f41d Carles
618 7dd94df7 Carles Marti
    return molec_ctrs2
619 8887f41d Carles
620 8887f41d Carles
621 7dd94df7 Carles Marti
def get_molec_ctrs3():
622 7dd94df7 Carles Marti
    err_msg = 'The value of molec_ctrs3 should be a list of atom ' \
623 c845c6f2 Carles Marti
              'numbers (ie. positive integers) or groups of atom ' \
624 c845c6f2 Carles Marti
              'numbers enclosed by parentheses-like characters. \n' \
625 c845c6f2 Carles Marti
              'eg. 128,(135 138;141) 87 {45, 68}'
626 c845c6f2 Carles Marti
    # Convert the string into a list of lists
627 7dd94df7 Carles Marti
    molec_ctrs3 = try_command(str2lst, [(ValueError, err_msg),
628 7dd94df7 Carles Marti
                                        (AttributeError, err_msg)],
629 7dd94df7 Carles Marti
                              dos_inp.get('Screening', 'molec_ctrs3'))
630 c845c6f2 Carles Marti
631 c845c6f2 Carles Marti
    # Check all elements of the list (of lists) are positive integers
632 7dd94df7 Carles Marti
    for ctr in molec_ctrs3:
633 c845c6f2 Carles Marti
        if isinstance(ctr, list):
634 c845c6f2 Carles Marti
            for atom in ctr:
635 c845c6f2 Carles Marti
                if atom < 0:
636 c845c6f2 Carles Marti
                    logger.error(err_msg)
637 c845c6f2 Carles Marti
                    raise ValueError(err_msg)
638 c845c6f2 Carles Marti
        elif isinstance(ctr, int):
639 c845c6f2 Carles Marti
            if ctr < 0:
640 c845c6f2 Carles Marti
                logger.error(err_msg)
641 c845c6f2 Carles Marti
                raise ValueError(err_msg)
642 c845c6f2 Carles Marti
        else:
643 c845c6f2 Carles Marti
            logger.error(err_msg)
644 c845c6f2 Carles Marti
            raise ValueError(err_msg)
645 c845c6f2 Carles Marti
646 7dd94df7 Carles Marti
    return molec_ctrs3
647 c845c6f2 Carles Marti
648 c845c6f2 Carles Marti
649 a98d4172 Carles Marti
def get_max_helic_angle():
650 a98d4172 Carles Marti
    err_msg = "'max_helic_angle' must be a positive number in degrees"
651 a98d4172 Carles Marti
    max_helic_angle = try_command(dos_inp.getfloat, [(ValueError, err_msg)],
652 a98d4172 Carles Marti
                                  'Screening', 'max_helic_angle',
653 a98d4172 Carles Marti
                                  fallback=180.0)
654 a98d4172 Carles Marti
    if max_helic_angle < 0:
655 a98d4172 Carles Marti
        logger.error(err_msg)
656 a98d4172 Carles Marti
        raise ValueError(err_msg)
657 a98d4172 Carles Marti
658 a98d4172 Carles Marti
    return max_helic_angle
659 a98d4172 Carles Marti
660 a98d4172 Carles Marti
661 8af49f6d Carles Marti
def get_select_magns():
662 8af49f6d Carles Marti
    select_magns_vals = ['energy', 'moi']
663 8af49f6d Carles Marti
    select_magns_str = dos_inp.get('Screening', 'select_magns',
664 14e0b660 Carles Martí
                                   fallback='moi')
665 8af49f6d Carles Marti
    select_magns_str.replace(',', ' ').replace(';', ' ')
666 8af49f6d Carles Marti
    select_magns = select_magns_str.split(' ')
667 8af49f6d Carles Marti
    select_magns = [m.lower() for m in select_magns]
668 8af49f6d Carles Marti
    for m in select_magns:
669 8af49f6d Carles Marti
        check_expect_val(m, select_magns_vals)
670 8af49f6d Carles Marti
    return select_magns
671 8af49f6d Carles Marti
672 8af49f6d Carles Marti
673 af2bf62f Carles Marti
def get_confs_per_magn():
674 af2bf62f Carles Marti
    err_msg = num_error % ('confs_per_magn', 'positive integer')
675 af2bf62f Carles Marti
    confs_per_magn = try_command(dos_inp.getint, [(ValueError, err_msg)],
676 af2bf62f Carles Marti
                                 'Screening', 'confs_per_magn', fallback=2)
677 af2bf62f Carles Marti
    if confs_per_magn <= 0:
678 af2bf62f Carles Marti
        logger.error(err_msg)
679 af2bf62f Carles Marti
        raise ValueError(err_msg)
680 af2bf62f Carles Marti
    return confs_per_magn
681 af2bf62f Carles Marti
682 af2bf62f Carles Marti
683 c845c6f2 Carles Marti
def get_surf_norm_vect():
684 d6da8693 Carles Marti
    err = "'surf_norm_vect' must be a 3 component vector, 'x', 'y' or 'z', " \
685 d6da8693 Carles Marti
          "'auto' or 'asann'."
686 9c16a7e2 Carles Marti
    cart_axes = {'x': [1.0, 0.0, 0.0], '-x': [-1.0, 0.0, 0.0],
687 9c16a7e2 Carles Marti
                 'y': [0.0, 1.0, 0.0], '-y': [0.0, -1.0, 0.0],
688 9c16a7e2 Carles Marti
                 'z': [0.0, 0.0, 1.0], '-z': [0.0, 0.0, -1.0]}
689 c845c6f2 Carles Marti
    surf_norm_vect_str = dos_inp.get('Screening', 'surf_norm_vect',
690 d6da8693 Carles Marti
                                     fallback="auto").lower()
691 d6da8693 Carles Marti
    if surf_norm_vect_str == "asann" or surf_norm_vect_str == "auto":
692 d6da8693 Carles Marti
        return 'auto'
693 9c16a7e2 Carles Marti
    if surf_norm_vect_str in cart_axes:
694 d6da8693 Carles Marti
        return np.array(cart_axes[surf_norm_vect_str])
695 d6da8693 Carles Marti
    surf_norm_vect = try_command(str2lst, [(ValueError, err)],
696 d6da8693 Carles Marti
                                 surf_norm_vect_str, float)
697 d6da8693 Carles Marti
    if len(surf_norm_vect) != 3:
698 d6da8693 Carles Marti
        logger.error(err)
699 d6da8693 Carles Marti
        raise ValueError(err)
700 3d56e566 Carles Marti
701 b6b1b03e Carles Marti
    return np.array(surf_norm_vect) / np.linalg.norm(surf_norm_vect)
702 c845c6f2 Carles Marti
703 c845c6f2 Carles Marti
704 fe91ddb2 Carles Marti
def get_adsorption_height():
705 fe91ddb2 Carles Marti
    err_msg = num_error % ('adsorption_height', 'positive number')
706 fe91ddb2 Carles Marti
    ads_height = try_command(dos_inp.getfloat, [(ValueError, err_msg)],
707 fe91ddb2 Carles Marti
                             'Screening', 'adsorption_height', fallback=2.5)
708 fe91ddb2 Carles Marti
    if ads_height <= 0:
709 fe91ddb2 Carles Marti
        logger.error(err_msg)
710 fe91ddb2 Carles Marti
        raise ValueError(err_msg)
711 fe91ddb2 Carles Marti
    return ads_height
712 fe91ddb2 Carles Marti
713 fe91ddb2 Carles Marti
714 7dd94df7 Carles Marti
def get_set_angles():
715 609104e3 Carles Marti
    set_vals = ['euler', 'internal']
716 7dd94df7 Carles Marti
    check_expect_val(dos_inp.get('Screening', 'set_angles').lower(), set_vals)
717 5261a07f Carles Marti
    set_angles = dos_inp.get('Screening', 'set_angles',
718 5261a07f Carles Marti
                             fallback='euler').lower()
719 7dd94df7 Carles Marti
    return set_angles
720 a7c7b43e Carles Marti
721 a7c7b43e Carles Marti
722 8887f41d Carles
def get_pts_per_angle():
723 d4bedc18 Carles Marti
    err_msg = num_error % ('sample_points_per_angle', 'positive integer')
724 8887f41d Carles
    pts_per_angle = try_command(dos_inp.getint,
725 8887f41d Carles
                                [(ValueError, err_msg)],
726 8887f41d Carles
                                'Screening', 'sample_points_per_angle',
727 8887f41d Carles
                                fallback=3)
728 d4bedc18 Carles Marti
    if pts_per_angle <= 0:
729 d4bedc18 Carles Marti
        logger.error(err_msg)
730 d4bedc18 Carles Marti
        raise ValueError(err_msg)
731 8887f41d Carles
    return pts_per_angle
732 8887f41d Carles
733 8887f41d Carles
734 7d97341d Carles Marti
def get_max_structures():
735 7d97341d Carles Marti
    err_msg = num_error % ('max_structures', 'positive integer')
736 21209d96 Carles Marti
    max_structs = dos_inp.get('Screening', 'max_structures', fallback="False")
737 21209d96 Carles Marti
    if max_structs.lower() in turn_false_answers:
738 21209d96 Carles Marti
        return np.inf
739 21209d96 Carles Marti
    if try_command(int, [(ValueError, err_msg)], max_structs) <= 0:
740 7d97341d Carles Marti
        logger.error(err_msg)
741 7d97341d Carles Marti
        raise ValueError(err_msg)
742 21209d96 Carles Marti
    return int(max_structs)
743 7d97341d Carles Marti
744 7d97341d Carles Marti
745 8887f41d Carles
def get_coll_thrsld():
746 fe91ddb2 Carles Marti
    err_msg = num_error % ('collision_threshold', 'positive number')
747 eef995b8 Carles Marti
    coll_thrsld_str = dos_inp.get('Screening', 'collision_threshold',
748 a44ad3c2 Carles Martí
                                  fallback="False")
749 eef995b8 Carles Marti
    if coll_thrsld_str.lower() in turn_false_answers:
750 eef995b8 Carles Marti
        return False
751 eef995b8 Carles Marti
    coll_thrsld = try_command(float, [(ValueError, err_msg)], coll_thrsld_str)
752 8887f41d Carles
753 8887f41d Carles
    if coll_thrsld <= 0:
754 8887f41d Carles
        logger.error(err_msg)
755 8887f41d Carles
        raise ValueError(err_msg)
756 8887f41d Carles
757 8887f41d Carles
    return coll_thrsld
758 8887f41d Carles
759 8887f41d Carles
760 f98ba5b0 Carles Marti
def get_min_coll_height(norm_vect):
761 5fb01677 Carles Marti
    err_msg = num_error % ('min_coll_height', 'decimal number')
762 5fb01677 Carles Marti
    min_coll_height = dos_inp.get('Screening', 'min_coll_height',
763 5fb01677 Carles Marti
                                  fallback="False")
764 5fb01677 Carles Marti
    if min_coll_height.lower() in turn_false_answers:
765 f98ba5b0 Carles Marti
        return False
766 f98ba5b0 Carles Marti
    min_coll_height = try_command(float, [(ValueError, err_msg)],
767 f98ba5b0 Carles Marti
                                  min_coll_height)
768 f98ba5b0 Carles Marti
    cart_axes = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0],
769 f98ba5b0 Carles Marti
                 [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]]
770 f98ba5b0 Carles Marti
    err_msg = "'min_coll_height' option is only implemented for " \
771 f98ba5b0 Carles Marti
              "'surf_norm_vect' to be one of the x, y or z axes. "
772 8279a51d Carles Marti
    if not isinstance(norm_vect, str) or norm_vect != 'auto':
773 d6da8693 Carles Marti
        check_expect_val(norm_vect.tolist(), cart_axes, err_msg)
774 5fb01677 Carles Marti
    return min_coll_height
775 8887f41d Carles
776 8887f41d Carles
777 9cd032cf Carles Marti
def get_exclude_ads_ctr():
778 9cd032cf Carles Marti
    err_msg = "exclude_ads_ctr must have a boolean value."
779 9cd032cf Carles Marti
    exclude_ads_ctr = try_command(dos_inp.getboolean, [(ValueError, err_msg)],
780 9cd032cf Carles Marti
                                  "Screening", "exclude_ads_ctr",
781 9cd032cf Carles Marti
                                  fallback=False)
782 9cd032cf Carles Marti
    return exclude_ads_ctr
783 9cd032cf Carles Marti
784 9cd032cf Carles Marti
785 c25aa299 Carles Marti
def get_H_donor(spec_atoms):
786 c25aa299 Carles Marti
    from ase.data import chemical_symbols
787 7d37379d Carles Martí
    err_msg = "The value of 'h_donor' must be either False, a chemical symbol " \
788 c25aa299 Carles Marti
              "or an atom index"
789 c25aa299 Carles Marti
    h_donor_str = dos_inp.get('Screening', 'h_donor', fallback="False")
790 c25aa299 Carles Marti
    h_donor = []
791 c25aa299 Carles Marti
    if h_donor_str.lower() in turn_false_answers:
792 c25aa299 Carles Marti
        return False
793 c25aa299 Carles Marti
    err = False
794 c25aa299 Carles Marti
    for el in h_donor_str.split():
795 c25aa299 Carles Marti
        try:
796 c25aa299 Carles Marti
            h_donor.append(int(el))
797 c25aa299 Carles Marti
        except ValueError:
798 c25aa299 Carles Marti
            if el not in chemical_symbols + [nw_sym for pairs in spec_atoms
799 c25aa299 Carles Marti
                                             for nw_sym in pairs]:
800 c25aa299 Carles Marti
                err = True
801 c25aa299 Carles Marti
            else:
802 c25aa299 Carles Marti
                h_donor.append(el)
803 c25aa299 Carles Marti
        finally:
804 c25aa299 Carles Marti
            if err:
805 c25aa299 Carles Marti
                logger.error(err_msg)
806 c25aa299 Carles Marti
                ValueError(err_msg)
807 c25aa299 Carles Marti
    return h_donor
808 c25aa299 Carles Marti
809 c25aa299 Carles Marti
810 c25aa299 Carles Marti
def get_H_acceptor(spec_atoms):
811 c25aa299 Carles Marti
    from ase.data import chemical_symbols
812 c25aa299 Carles Marti
    err_msg = "The value of 'h_acceptor' must be either 'all', a chemical " \
813 30e34792 Carles Martí
              "symbol or an atom index."
814 c25aa299 Carles Marti
    h_acceptor_str = dos_inp.get('Screening', 'h_acceptor', fallback="all")
815 c25aa299 Carles Marti
    if h_acceptor_str.lower() == "all":
816 c25aa299 Carles Marti
        return "all"
817 c25aa299 Carles Marti
    h_acceptor = []
818 c25aa299 Carles Marti
    err = False
819 c25aa299 Carles Marti
    for el in h_acceptor_str.split():
820 c25aa299 Carles Marti
        try:
821 c25aa299 Carles Marti
            h_acceptor.append(int(el))
822 c25aa299 Carles Marti
        except ValueError:
823 c25aa299 Carles Marti
            if el not in chemical_symbols + [nw_sym for pairs in spec_atoms
824 c25aa299 Carles Marti
                                             for nw_sym in pairs]:
825 c25aa299 Carles Marti
                err = True
826 c25aa299 Carles Marti
            else:
827 c25aa299 Carles Marti
                h_acceptor.append(el)
828 c25aa299 Carles Marti
        finally:
829 c25aa299 Carles Marti
            if err:
830 c25aa299 Carles Marti
                logger.error(err_msg)
831 30e34792 Carles Martí
                raise ValueError(err_msg)
832 c25aa299 Carles Marti
    return h_acceptor
833 a765b11c Carles Marti
834 a765b11c Carles Marti
835 b75bf97d Carles Marti
def get_use_molec_file():
836 b75bf97d Carles Marti
    use_molec_file = dos_inp.get('Screening', 'use_molec_file',
837 b75bf97d Carles Marti
                                 fallback='False')
838 13731dc4 Carles Marti
    if use_molec_file.lower() in turn_false_answers:
839 b75bf97d Carles Marti
        return False
840 b75bf97d Carles Marti
    if not os.path.isfile(use_molec_file):
841 b75bf97d Carles Marti
        logger.error(f'File {use_molec_file} not found.')
842 b75bf97d Carles Marti
        raise FileNotFoundError(f'File {use_molec_file} not found')
843 b75bf97d Carles Marti
844 b75bf97d Carles Marti
    return use_molec_file
845 b75bf97d Carles Marti
846 b75bf97d Carles Marti
847 a7128ce1 Carles Marti
# Refinement
848 a7128ce1 Carles Marti
849 7d37379d Carles Martí
def get_refine_inp_file(code, potcar_dir=None):
850 9d3b680c Carles Martí
    inp_file_lst = dos_inp.get('Refinement', 'refine_inp_file').split()
851 f349bb54 Carles
    check_inp_files(inp_file_lst[0] if len(inp_file_lst) == 1 else inp_file_lst,
852 f349bb54 Carles
                    code, potcar_dir)
853 9d3b680c Carles Martí
    return inp_file_lst[0] if len(inp_file_lst) == 1 else inp_file_lst
854 8887f41d Carles
855 8887f41d Carles
856 8887f41d Carles
def get_energy_cutoff():
857 8887f41d Carles
    err_msg = num_error % ('energy_cutoff', 'positive decimal number')
858 8887f41d Carles
    energy_cutoff = try_command(dos_inp.getfloat,
859 8887f41d Carles
                                [(ValueError, err_msg)],
860 8887f41d Carles
                                'Refinement', 'energy_cutoff', fallback=0.5)
861 8887f41d Carles
    if energy_cutoff < 0:
862 8887f41d Carles
        logger.error(err_msg)
863 8887f41d Carles
        raise ValueError(err_msg)
864 8887f41d Carles
    return energy_cutoff
865 8887f41d Carles
866 8887f41d Carles
867 c25aa299 Carles Marti
# Read input parameters
868 c25aa299 Carles Marti
869 8887f41d Carles
def read_input(in_file):
870 4e82c425 Carles Martí
    """Directs the reading of the parameters in the input file.
871 4e82c425 Carles Martí

872 4e82c425 Carles Martí
    @param in_file: The path to the DockOnSurf input file.
873 4e82c425 Carles Martí
    @return inp_vars: Dictionary with the values for every option in the input
874 4e82c425 Carles Martí
    file.
875 4e82c425 Carles Martí
    """
876 9d3b680c Carles Martí
    from modules.formats import adapt_format
877 9d3b680c Carles Martí
878 4e82c425 Carles Martí
    # Checks for errors in the Input file.
879 9d3b680c Carles Martí
    err_msg = False
880 8887f41d Carles
    try:
881 8887f41d Carles
        dos_inp.read(in_file)
882 8887f41d Carles
    except MissingSectionHeaderError as e:
883 8887f41d Carles
        logger.error('There are options in the input file without a Section '
884 695dcff8 Carles Marti
                     'header.')
885 14e0b660 Carles Martí
        err_msg = e
886 8887f41d Carles
    except DuplicateOptionError as e:
887 8887f41d Carles
        logger.error('There is an option in the input file that has been '
888 0bca5abb Carles Marti
                     'specified more than once.')
889 14e0b660 Carles Martí
        err_msg = e
890 8887f41d Carles
    except Exception as e:
891 14e0b660 Carles Martí
        err_msg = e
892 8887f41d Carles
    else:
893 14e0b660 Carles Martí
        err_msg = False
894 8887f41d Carles
    finally:
895 14e0b660 Carles Martí
        if isinstance(err_msg, BaseException):
896 14e0b660 Carles Martí
            raise err_msg
897 17e72a49 Carles
898 7dd94df7 Carles Marti
    inp_vars = {}
899 8887f41d Carles
900 8887f41d Carles
    # Global
901 8887f41d Carles
    if not dos_inp.has_section('Global'):
902 8887f41d Carles
        logger.error(no_sect_err % 'Global')
903 8887f41d Carles
        raise NoSectionError('Global')
904 8887f41d Carles
905 8887f41d Carles
    # Mandatory options
906 8887f41d Carles
    # Checks whether the mandatory options 'run_type', 'code', etc. are present.
907 14e0b660 Carles Martí
    glob_mand_opts = ['run_type', 'code', 'batch_q_sys']
908 7fd58762 Carles
    for opt in glob_mand_opts:
909 8887f41d Carles
        if not dos_inp.has_option('Global', opt):
910 8887f41d Carles
            logger.error(no_opt_err % (opt, 'Global'))
911 8887f41d Carles
            raise NoOptionError(opt, 'Global')
912 8887f41d Carles
913 4e82c425 Carles Martí
    # Mandatory options
914 8887f41d Carles
    isolated, screening, refinement = get_run_type()
915 7dd94df7 Carles Marti
    inp_vars['isolated'] = isolated
916 7dd94df7 Carles Marti
    inp_vars['screening'] = screening
917 7dd94df7 Carles Marti
    inp_vars['refinement'] = refinement
918 14e0b660 Carles Martí
    inp_vars['code'] = get_code()
919 7dd94df7 Carles Marti
    inp_vars['batch_q_sys'] = get_batch_q_sys()
920 8887f41d Carles
921 99afde40 Carles
    # Dependent options:
922 7dd94df7 Carles Marti
    if inp_vars['batch_q_sys']:
923 7dd94df7 Carles Marti
        inp_vars['max_jobs'] = get_max_jobs()
924 7dd94df7 Carles Marti
        if inp_vars['batch_q_sys'] != 'local':
925 09c3325a Carles Marti
            if not dos_inp.has_option('Global', 'subm_script'):
926 09c3325a Carles Marti
                logger.error(no_opt_err % ('subm_script', 'Global'))
927 09c3325a Carles Marti
                raise NoOptionError('subm_script', 'Global')
928 7dd94df7 Carles Marti
            inp_vars['subm_script'] = get_subm_script()
929 f349bb54 Carles
    if inp_vars['code'] == "vasp":
930 f349bb54 Carles
        inp_vars['potcar_dir'] = get_potcar_dir()
931 99afde40 Carles
932 8887f41d Carles
    # Facultative options (Default/Fallback value present)
933 9d3b680c Carles Martí
    inp_vars['pbc_cell'] = get_pbc_cell()
934 7dd94df7 Carles Marti
    inp_vars['project_name'] = get_project_name()
935 8b3d4772 Carles Marti
    # inp_vars['relaunch_err'] = get_relaunch_err()
936 7dd94df7 Carles Marti
    inp_vars['special_atoms'] = get_special_atoms()
937 8887f41d Carles
938 8887f41d Carles
    # Isolated
939 b1d27be5 Carles
    if isolated:
940 b606c71a Carles
        if not dos_inp.has_section('Isolated'):
941 b606c71a Carles
            logger.error(no_sect_err % 'Isolated')
942 b606c71a Carles
            raise NoSectionError('Isolated')
943 8887f41d Carles
        # Mandatory options
944 95dc2c8e Carles
        iso_mand_opts = ['isol_inp_file', 'molec_file']
945 8887f41d Carles
        for opt in iso_mand_opts:
946 8887f41d Carles
            if not dos_inp.has_option('Isolated', opt):
947 8887f41d Carles
                logger.error(no_opt_err % (opt, 'Isolated'))
948 8887f41d Carles
                raise NoOptionError(opt, 'Isolated')
949 7d37379d Carles Martí
        if 'potcar_dir' in inp_vars:
950 7d37379d Carles Martí
            inp_vars['isol_inp_file'] = get_isol_inp_file(inp_vars['code'],
951 7d37379d Carles Martí
                                                          inp_vars[
952 7d37379d Carles Martí
                                                              'potcar_dir'])
953 7d37379d Carles Martí
        else:
954 7d37379d Carles Martí
            inp_vars['isol_inp_file'] = get_isol_inp_file(inp_vars['code'])
955 7dd94df7 Carles Marti
        inp_vars['molec_file'] = get_molec_file()
956 8887f41d Carles
957 9d3b680c Carles Martí
        # Checks for PBC
958 9d3b680c Carles Martí
        atms = adapt_format('ase', inp_vars['molec_file'],
959 9d3b680c Carles Martí
                            inp_vars['special_atoms'])
960 9d3b680c Carles Martí
        if inp_vars['code'] == 'vasp' and np.linalg.det(atms.cell) == 0.0 \
961 9d3b680c Carles Martí
                and inp_vars['pbc_cell'] is False:
962 a5d76bfb Carles Martí
            err_msg = "When running calculations with 'VASP', the PBC cell " \
963 9d3b680c Carles Martí
                      "should be provided either implicitely inside " \
964 9d3b680c Carles Martí
                      "'molec_file' or by setting the 'pbc_cell' option."
965 9d3b680c Carles Martí
            logger.error(err_msg)
966 9d3b680c Carles Martí
            raise ValueError(err_msg)
967 a5d76bfb Carles Martí
        elif inp_vars['pbc_cell'] is False and np.linalg.det(atms.cell) != 0.0:
968 a5d76bfb Carles Martí
            inp_vars['pbc_cell'] = atms.cell
969 a5d76bfb Carles Martí
            logger.info(f"Obtained pbc_cell from '{inp_vars['molec_file']}' "
970 a5d76bfb Carles Martí
                        f"file.")
971 a5d76bfb Carles Martí
        elif (atms.cell != 0).any() and not np.allclose(inp_vars['pbc_cell'],
972 a5d76bfb Carles Martí
                                                        atms.cell):
973 9d3b680c Carles Martí
            logger.warning("'molec_file' has an implicit cell defined "
974 a5d76bfb Carles Martí
                           f"different than 'pbc_cell'.\n"
975 a5d76bfb Carles Martí
                           f"'molec_file' = {atms.cell}.\n"
976 a5d76bfb Carles Martí
                           f"'pbc_cell' = {inp_vars['pbc_cell']}).\n"
977 a5d76bfb Carles Martí
                           "'pbc_cell' value will be used.")
978 9d3b680c Carles Martí
979 8887f41d Carles
        # Facultative options (Default/Fallback value present)
980 7dd94df7 Carles Marti
        inp_vars['num_conformers'] = get_num_conformers()
981 7dd94df7 Carles Marti
        inp_vars['pre_opt'] = get_pre_opt()
982 8887f41d Carles
983 8887f41d Carles
    # Screening
984 b1d27be5 Carles
    if screening:
985 772b40e5 Carles
        if not dos_inp.has_section('Screening'):
986 9f7bb440 Carles
            logger.error(no_sect_err % 'Screening')
987 772b40e5 Carles
            raise NoSectionError('Screening')
988 8887f41d Carles
        # Mandatory options:
989 8887f41d Carles
        # Checks whether the mandatory options are present.
990 4e82c425 Carles Martí
        # Mandatory options
991 a765b11c Carles Marti
        screen_mand_opts = ['screen_inp_file', 'surf_file', 'sites',
992 7dd94df7 Carles Marti
                            'molec_ctrs']
993 8887f41d Carles
        for opt in screen_mand_opts:
994 772b40e5 Carles
            if not dos_inp.has_option('Screening', opt):
995 9f7bb440 Carles
                logger.error(no_opt_err % (opt, 'Screening'))
996 b1d27be5 Carles
                raise NoOptionError(opt, 'Screening')
997 7d37379d Carles Martí
        if 'potcar_dir' in inp_vars:
998 7d37379d Carles Martí
            inp_vars['screen_inp_file'] = get_screen_inp_file(inp_vars['code'],
999 7d37379d Carles Martí
                                                              inp_vars[
1000 7d37379d Carles Martí
                                                                  'potcar_dir'])
1001 7d37379d Carles Martí
        else:
1002 7d37379d Carles Martí
            inp_vars['screen_inp_file'] = get_screen_inp_file(inp_vars['code'])
1003 7dd94df7 Carles Marti
        inp_vars['surf_file'] = get_surf_file()
1004 7dd94df7 Carles Marti
        inp_vars['sites'] = get_sites()
1005 7dd94df7 Carles Marti
        inp_vars['molec_ctrs'] = get_molec_ctrs()
1006 8887f41d Carles
1007 9d3b680c Carles Martí
        # Checks for PBC
1008 9d3b680c Carles Martí
        atms = adapt_format('ase', inp_vars['surf_file'],
1009 9d3b680c Carles Martí
                            inp_vars['special_atoms'])
1010 9d3b680c Carles Martí
        if inp_vars['code'] == 'vasp' and np.linalg.det(atms.cell) == 0.0 \
1011 9d3b680c Carles Martí
                and inp_vars['pbc_cell'] is False:
1012 a5d76bfb Carles Martí
            err_msg = "When running calculations with 'VASP', the PBC cell " \
1013 9d3b680c Carles Martí
                      "should be provided either implicitely inside " \
1014 a5d76bfb Carles Martí
                      "'surf_file' or by setting the 'pbc_cell' option."
1015 9d3b680c Carles Martí
            logger.error(err_msg)
1016 9d3b680c Carles Martí
            raise ValueError(err_msg)
1017 a5d76bfb Carles Martí
        elif inp_vars['pbc_cell'] is False and np.linalg.det(atms.cell) != 0.0:
1018 a5d76bfb Carles Martí
            inp_vars['pbc_cell'] = atms.cell
1019 a5d76bfb Carles Martí
            logger.info(f"Obtained pbc_cell from '{inp_vars['surf_file']}' "
1020 a5d76bfb Carles Martí
                        f"file.")
1021 a5d76bfb Carles Martí
        elif (atms.cell != 0).any() and not np.allclose(inp_vars['pbc_cell'],
1022 a5d76bfb Carles Martí
                                                        atms.cell):
1023 a5d76bfb Carles Martí
            logger.warning("'surf_file' has an implicit cell defined "
1024 a5d76bfb Carles Martí
                           f"different than 'pbc_cell'.\n"
1025 a5d76bfb Carles Martí
                           f"'surf_file' = {atms.cell}.\n"
1026 a5d76bfb Carles Martí
                           f"'pbc_cell' = {inp_vars['pbc_cell']}).\n"
1027 9d3b680c Carles Martí
                           "'pbc_cell' value will be used.")
1028 9d3b680c Carles Martí
1029 8887f41d Carles
        # Facultative options (Default value present)
1030 7dd94df7 Carles Marti
        inp_vars['select_magns'] = get_select_magns()
1031 7dd94df7 Carles Marti
        inp_vars['confs_per_magn'] = get_confs_per_magn()
1032 7dd94df7 Carles Marti
        inp_vars['surf_norm_vect'] = get_surf_norm_vect()
1033 fe91ddb2 Carles Marti
        inp_vars['adsorption_height'] = get_adsorption_height()
1034 7dd94df7 Carles Marti
        inp_vars['set_angles'] = get_set_angles()
1035 7dd94df7 Carles Marti
        inp_vars['sample_points_per_angle'] = get_pts_per_angle()
1036 7dd94df7 Carles Marti
        inp_vars['collision_threshold'] = get_coll_thrsld()
1037 f98ba5b0 Carles Marti
        inp_vars['min_coll_height'] = get_min_coll_height(
1038 f98ba5b0 Carles Marti
            inp_vars['surf_norm_vect'])
1039 8b3d4772 Carles Marti
        if inp_vars['min_coll_height'] is False \
1040 8b3d4772 Carles Marti
                and inp_vars['collision_threshold'] is False:
1041 8b3d4772 Carles Marti
            logger.warning("Collisions are deactivated: Overlapping of "
1042 8b3d4772 Carles Marti
                           "adsorbate and surface is possible")
1043 9cd032cf Carles Marti
        inp_vars['exclude_ads_ctr'] = get_exclude_ads_ctr()
1044 b75bf97d Carles Marti
        inp_vars['h_donor'] = get_H_donor(inp_vars['special_atoms'])
1045 b75bf97d Carles Marti
        inp_vars['max_structures'] = get_max_structures()
1046 b75bf97d Carles Marti
        inp_vars['use_molec_file'] = get_use_molec_file()
1047 8887f41d Carles
1048 8b3d4772 Carles Marti
        # Options depending on the value of others
1049 609104e3 Carles Marti
        if inp_vars['set_angles'] == "internal":
1050 609104e3 Carles Marti
            internal_opts = ['molec_ctrs2', 'molec_ctrs3', 'surf_ctrs2',
1051 609104e3 Carles Marti
                             'max_helic_angle']
1052 609104e3 Carles Marti
            for opt in internal_opts:
1053 7dd94df7 Carles Marti
                if not dos_inp.has_option('Screening', opt):
1054 7dd94df7 Carles Marti
                    logger.error(no_opt_err % (opt, 'Screening'))
1055 7dd94df7 Carles Marti
                    raise NoOptionError(opt, 'Screening')
1056 a98d4172 Carles Marti
            inp_vars['max_helic_angle'] = get_max_helic_angle()
1057 7dd94df7 Carles Marti
            inp_vars['molec_ctrs2'] = get_molec_ctrs2()
1058 7dd94df7 Carles Marti
            inp_vars['molec_ctrs3'] = get_molec_ctrs3()
1059 7dd94df7 Carles Marti
            inp_vars['surf_ctrs2'] = get_surf_ctrs2()
1060 7dd94df7 Carles Marti
            if len(inp_vars["molec_ctrs2"]) != len(inp_vars['molec_ctrs']) \
1061 7dd94df7 Carles Marti
                    or len(inp_vars["molec_ctrs3"]) != \
1062 7dd94df7 Carles Marti
                    len(inp_vars['molec_ctrs']) \
1063 7dd94df7 Carles Marti
                    or len(inp_vars['surf_ctrs2']) != len(inp_vars['sites']):
1064 14e0b660 Carles Martí
                err_msg = "'molec_ctrs' 'molec_ctrs2' and 'molec_ctrs3' must " \
1065 14e0b660 Carles Martí
                          "have the same number of indices "
1066 14e0b660 Carles Martí
                logger.error(err_msg)
1067 14e0b660 Carles Martí
                raise ValueError(err_msg)
1068 7dd94df7 Carles Marti
1069 c25aa299 Carles Marti
        if inp_vars['h_donor'] is False:
1070 c25aa299 Carles Marti
            inp_vars['h_acceptor'] = False
1071 c25aa299 Carles Marti
        else:
1072 c25aa299 Carles Marti
            inp_vars['h_acceptor'] = get_H_acceptor(inp_vars['special_atoms'])
1073 c25aa299 Carles Marti
1074 8887f41d Carles
    # Refinement
1075 b1d27be5 Carles
    if refinement:
1076 8887f41d Carles
        if not dos_inp.has_section('Refinement'):
1077 8887f41d Carles
            logger.error(no_sect_err % 'Refinement')
1078 8887f41d Carles
            raise NoSectionError('Refinement')
1079 8887f41d Carles
        # Mandatory options
1080 8887f41d Carles
        # Checks whether the mandatory options are present.
1081 8887f41d Carles
        ref_mand_opts = ['refine_inp_file']
1082 8887f41d Carles
        for opt in ref_mand_opts:
1083 8887f41d Carles
            if not dos_inp.has_option('Refinement', opt):
1084 8887f41d Carles
                logger.error(no_opt_err % (opt, 'Refinement'))
1085 8887f41d Carles
                raise NoOptionError(opt, 'Refinement')
1086 7d37379d Carles Martí
        if 'potcar_dir' in inp_vars:
1087 7d37379d Carles Martí
            inp_vars['refine_inp_file'] = get_refine_inp_file(inp_vars['code'],
1088 7d37379d Carles Martí
                                                              inp_vars[
1089 7d37379d Carles Martí
                                                                  'potcar_dir'])
1090 7d37379d Carles Martí
        else:
1091 7d37379d Carles Martí
            inp_vars['refine_inp_file'] = get_refine_inp_file(inp_vars['code'])
1092 8887f41d Carles
1093 8887f41d Carles
        # Facultative options (Default value present)
1094 7dd94df7 Carles Marti
        inp_vars['energy_cutoff'] = get_energy_cutoff()
1095 b1d27be5 Carles
        # end energy_cutoff
1096 9f7bb440 Carles
1097 a5cc42ff Carles Marti
    return_vars_str = "\n\t".join([str(key) + ": " + str(value)
1098 7dd94df7 Carles Marti
                                   for key, value in inp_vars.items()])
1099 14e0b660 Carles Martí
    logger.info(f'Correctly read {in_file} parameters:'
1100 14e0b660 Carles Martí
                f' \n\n\t{return_vars_str}\n')
1101 d8a6314e Carles
1102 7dd94df7 Carles Marti
    return inp_vars
1103 8887f41d Carles
1104 8887f41d Carles
1105 8887f41d Carles
if __name__ == "__main__":
1106 8887f41d Carles
    import sys
1107 8887f41d Carles
1108 8887f41d Carles
    print(read_input(sys.argv[1]))