Coverage for biobb_cp2k / cp2k / cp2k_run.py: 83%

76 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-05 12:58 +0000

1#!/usr/bin/env python3 

2 

3"""Module containing the Cp2kRun class and the command line interface.""" 

4from typing import Optional 

5import shutil 

6import os 

7from pathlib import Path, PurePath 

8from biobb_common.generic.biobb_object import BiobbObject 

9from biobb_common.tools import file_utils as fu 

10from biobb_common.tools.file_utils import launchlogger 

11from biobb_cp2k.cp2k.common import check_input_path, check_output_path 

12 

13 

14class Cp2kRun(BiobbObject): 

15 """ 

16 | biobb_cp2k Cp2kRun 

17 | Wrapper of the `CP2K QM tool <https://www.cp2k.org/>`_ module. 

18 | Runs atomistic simulations of solid state, liquid, molecular, periodic, material, crystal, and biological systems using CP2K QM tool. 

19 

20 Args: 

21 input_inp_path (str): Input configuration file (CP2K run options). File type: input. `Sample file <https://github.com/bioexcel/biobb_cp2k/raw/master/biobb_cp2k/test/data/cp2k/cp2k_energy.inp>`_. Accepted formats: inp (edam:format_2330), in (edam:format_2330), txt (edam:format_2330), wfn (edam:format_2333). 

22 output_log_path (str): Output log file. File type: output. `Sample file <https://github.com/bioexcel/biobb_cp2k/raw/master/biobb_cp2k/test/reference/cp2k/cp2k_run_out.log>`_. Accepted formats: log (edam:format_2330), out (edam:format_2330), txt (edam:format_2330), o (edam:format_2330). 

23 output_outzip_path (str): Output files. File type: output. `Sample file <https://github.com/bioexcel/biobb_cp2k/raw/master/biobb_cp2k/test/reference/cp2k/cp2k_run_out.zip>`_. Accepted formats: zip (edam:format_3987), gzip (edam:format_3987), gz (edam:format_3987). 

24 output_rst_path (str): Output restart file. File type: output. `Sample file <https://github.com/bioexcel/biobb_cp2k/raw/master/biobb_cp2k/test/reference/cp2k/cp2k_run_out.wfn>`_. Accepted formats: wfn (edam:format_2333). 

25 properties (dict - Python dictionary object containing the tool parameters, not input/output files): 

26 * **binary_path** (*str*) - ("cp2k.sopt") CP2K binary path to be used. 

27 * **param_path** (*str*) - (None) Path to the CP2K parameter data files (BASIS_SET, POTENTIALS, etc.). If not provided, the parameter data files included in the package will be used. 

28 * **mpi_bin** (*str*) - (None) Path to the MPI runner. Usually "mpirun" or "srun". 

29 * **mpi_np** (*int*) - (0) [0~1000|1] Number of MPI processes. Usually an integer bigger than 1. 

30 * **mpi_flags** (*str*) - (None) Path to the MPI hostlist file. 

31 * **remove_tmp** (*bool*) - (True) [WF property] Remove temporal files. 

32 * **restart** (*bool*) - (False) [WF property] Do not execute if output files exist. 

33 * **sandbox_path** (*str*) - ("./") [WF property] Parent path to the sandbox directory. 

34 

35 Examples: 

36 This is a use example of how to use the building block from Python:: 

37 

38 from biobb_cp2k.cp2k.cp2k_run import cp2k_run 

39 prop = { 

40 'binary_path': 'cp2k.sopt' 

41 } 

42 cp2k_run(input_inp_path='/path/to/cp2k_input.inp', 

43 output_log_path='/path/to/cp2k_log.log', 

44 output_outzip_path='/path/to/cp2k_out.zip', 

45 output_rst_path='/path/to/cp2k_rst.wfn', 

46 properties=prop) 

47 

48 Info: 

49 * wrapped_software: 

50 * name: CP2K 

51 * version: >=7.1.0 

52 * license: GPL-2.0 

53 * multinode: mpi 

54 * ontology: 

55 * name: EDAM 

56 * schema: http://edamontology.org/EDAM.owl 

57 

58 """ 

59 

60 def __init__(self, input_inp_path: str, output_log_path: str, 

61 output_outzip_path: str, output_rst_path: str, 

62 properties: Optional[dict] = None, **kwargs) -> None: 

63 

64 properties = properties or {} 

65 

66 # Call parent class constructor 

67 super().__init__(properties) 

68 self.locals_var_dict = locals().copy() 

69 

70 # Input/Output files 

71 self.io_dict = { 

72 'in': {'input_inp_path': input_inp_path}, 

73 'out': {'output_log_path': output_log_path, 

74 'output_outzip_path': output_outzip_path, 

75 'output_rst_path': output_rst_path} 

76 } 

77 

78 # Properties specific for BB 

79 self.properties = properties 

80 self.binary_path = properties.get('binary_path', 'cp2k.sopt') 

81 self.param_path = properties.get('param_path', None) 

82 

83 # Properties for MPI 

84 self.mpi_bin = properties.get('mpi_bin') 

85 self.mpi_np = properties.get('mpi_np') 

86 self.mpi_flags = properties.get('mpi_flags') 

87 

88 # Check the properties 

89 self.check_properties(properties) 

90 self.check_arguments() 

91 

92 def check_data_params(self, out_log, out_err): 

93 """ Checks input/output paths correctness """ 

94 

95 # Check input(s) 

96 self.io_dict["in"]["input_inp_path"] = check_input_path(self.io_dict["in"]["input_inp_path"], "input_inp_path", False, out_log, self.__class__.__name__) 

97 

98 # Check output(s) 

99 self.io_dict["out"]["output_log_path"] = check_output_path(self.io_dict["out"]["output_log_path"], "output_log_path", False, out_log, self.__class__.__name__) 

100 self.io_dict["out"]["output_outzip_path"] = check_output_path(self.io_dict["out"]["output_outzip_path"], "output_outzip_path", False, out_log, self.__class__.__name__) 

101 self.io_dict["out"]["output_rst_path"] = check_output_path(self.io_dict["out"]["output_rst_path"], "output_rst_path", False, out_log, self.__class__.__name__) 

102 

103 @launchlogger 

104 def launch(self): 

105 """Launches the execution of the Cp2kRun module.""" 

106 

107 # check input/output paths and parameters 

108 self.check_data_params(self.out_log, self.err_log) 

109 

110 # Setup Biobb 

111 if self.check_restart(): 

112 return 0 

113 self.stage_files() 

114 

115 # Creating temporary folder 

116 tmp_folder = fu.create_unique_dir() 

117 fu.log('Creating %s temporary folder' % tmp_folder, self.out_log) 

118 

119 shutil.copy2(self.io_dict["in"]["input_inp_path"], tmp_folder) 

120 

121 # set path to the CP2K parameter data files 

122 if not self.param_path: 

123 # os.environ["CP2K_DATA_DIR"] = str(PurePath(myself.__file__).parent.joinpath('cp2k_data')) 

124 os.environ["CP2K_DATA_DIR"] = str(Path(os.getenv("CONDA_PREFIX", "")).joinpath('cp2k_aux').joinpath('cp2k_data')) 

125 else: 

126 if not Path(PurePath(self.param_path)).exists(): 

127 fu.log(self.__class__.__name__ + ': Unexisting %s folder, exiting' % self.param_path, self.out_log) 

128 raise SystemExit(self.__class__.__name__ + ': Unexisting %s folder' % self.param_path) 

129 os.environ["CP2K_DATA_DIR"] = self.param_path 

130 

131 # Command line 

132 # cp2k.sopt -i benzene_dimer.inp -o mp2_test.out 

133 self.cmd = ['cd', tmp_folder, ';', 

134 self.binary_path, 

135 '-i', PurePath(self.io_dict["in"]["input_inp_path"]).name, 

136 '-o', PurePath(self.io_dict["out"]["output_log_path"]).name] 

137 

138 # general mpi properties 

139 if self.mpi_bin: 

140 mpi_cmd = [self.mpi_bin] 

141 if self.mpi_np: 

142 mpi_cmd.append('-n') 

143 mpi_cmd.append(str(self.mpi_np)) 

144 if self.mpi_flags: 

145 mpi_cmd.extend(self.mpi_flags) 

146 self.cmd = mpi_cmd + self.cmd 

147 

148 # Run Biobb block 

149 self.run_biobb() 

150 

151 # Gather output files in a single zip file 

152 self.output = PurePath(tmp_folder).joinpath("cp2k_out.zip") 

153 out_files = [] 

154 restart = '' 

155 for root, dirs, files in os.walk(tmp_folder): 

156 for file in files: 

157 # fu.log('FILE %s ' % file, self.out_log) 

158 # if file.endswith('.out'): 

159 # out_files.append(file) 

160 # elif file.endswith('.wfn'): 

161 # restart = file 

162 

163 if file.endswith('.wfn'): 

164 restart = tmp_folder + '/' + file 

165 else: 

166 out_files.append(tmp_folder + '/' + file) 

167 

168 fu.zip_list(str(self.output), out_files, self.out_log) 

169 

170 # Copy outputs from temporary folder to output path 

171 shutil.copy2(self.output, PurePath(self.io_dict["out"]["output_outzip_path"])) 

172 shutil.copy2(PurePath(tmp_folder).joinpath(PurePath(self.io_dict["out"]["output_log_path"]).name), PurePath(self.io_dict["out"]["output_log_path"])) 

173 if restart: 

174 shutil.copy2(restart, PurePath(self.io_dict["out"]["output_rst_path"])) 

175 

176 # Copy files to host 

177 self.copy_to_host() 

178 

179 # remove temporary folder(s) 

180 self.tmp_files.append(tmp_folder) 

181 self.remove_tmp_files() 

182 

183 self.check_arguments(output_files_created=True, raise_exception=False) 

184 

185 return self.return_code 

186 

187 

188def cp2k_run(input_inp_path: str, 

189 output_log_path: str, output_outzip_path: str, output_rst_path: str, 

190 properties: Optional[dict] = None, **kwargs) -> int: 

191 """Create :class:`Cp2kRun <cp2k.cp2k_run.Cp2kRun>`cp2k.cp2k_run.Cp2kRun class and 

192 execute :meth:`launch() <cp2k.cp2k_run.Cp2kRun.launch>` method""" 

193 return Cp2kRun(**dict(locals())).launch() 

194 

195 

196cp2k_run.__doc__ = Cp2kRun.__doc__ 

197main = Cp2kRun.get_main(cp2k_run, "Running atomistic simulations of solid state, liquid, molecular, periodic, material, crystal, and biological systems using CP2K QM tool.") 

198 

199if __name__ == '__main__': 

200 main()