Coverage for /builds/hweiske/ase/ase/calculators/orca.py: 48.72%

39 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-22 11:22 +0000

1import re 

2 

3import ase.io.orca as io 

4from ase.calculators.genericfileio import (BaseProfile, CalculatorTemplate, 

5 GenericFileIOCalculator) 

6 

7 

8def get_version_from_orca_header(orca_header): 

9 match = re.search(r'Program Version (\S+)', orca_header, re.M) 

10 return match.group(1) 

11 

12 

13class OrcaProfile(BaseProfile): 

14 def __init__(self, binary, **kwargs): 

15 """ 

16 Parameters 

17 ---------- 

18 binary : str 

19 Full path to the orca binary, if full path is not specified ORCA 

20 cannot run in parallel. 

21 """ 

22 # Because ORCA handles its parallelization without being called with 

23 # mpirun/mpiexec/etc parallel should be set to False. 

24 # Whether or not it is run in parallel is controlled by the orcablocks 

25 super().__init__(parallel=False, parallel_info={}) 

26 self.binary = binary 

27 

28 def version(self): 

29 # XXX Allow MPI in argv; the version call should not be parallel. 

30 from ase.calculators.genericfileio import read_stdout 

31 stdout = read_stdout([self.binary, "does_not_exist"]) 

32 return get_version_from_orca_header(stdout) 

33 

34 def get_calculator_command(self, inputfile): 

35 return [self.binary, inputfile] 

36 

37 

38class OrcaTemplate(CalculatorTemplate): 

39 _label = 'orca' 

40 

41 def __init__(self): 

42 super().__init__('orca', 

43 implemented_properties=['energy', 'free_energy', 

44 'forces']) 

45 

46 self.inputname = f'{self._label}.inp' 

47 self.outputname = f'{self._label}.out' 

48 self.errorname = f'{self._label}.err' 

49 

50 def execute(self, directory, profile) -> None: 

51 profile.run(directory, self.inputname, self.outputname, 

52 errorfile=self.errorname) 

53 

54 def write_input(self, profile, directory, atoms, parameters, properties): 

55 parameters = dict(parameters) 

56 

57 kw = dict(charge=0, mult=1, orcasimpleinput='B3LYP def2-TZVP', 

58 orcablocks='%pal nprocs 1 end') 

59 kw.update(parameters) 

60 

61 io.write_orca(directory / self.inputname, atoms, kw) 

62 

63 def read_results(self, directory): 

64 return io.read_orca_outputs(directory, directory / self.outputname) 

65 

66 def load_profile(self, cfg, **kwargs): 

67 return OrcaProfile.from_config(cfg, self.name, **kwargs) 

68 

69 

70class ORCA(GenericFileIOCalculator): 

71 """Class for doing ORCA calculations. 

72 

73 Example: 

74 

75 calc = ORCA(charge=0, mult=1, orcasimpleinput='B3LYP def2-TZVP', 

76 orcablocks='%pal nprocs 16 end') 

77 """ 

78 

79 def __init__(self, *, profile=None, directory='.', parallel_info=None, 

80 parallel=None, **kwargs): 

81 """Construct ORCA-calculator object. 

82 

83 Parameters 

84 ========== 

85 charge: int 

86 

87 mult: int 

88 

89 orcasimpleinput : str 

90 

91 orcablocks: str 

92 

93 

94 Examples 

95 ======== 

96 Use default values: 

97 

98 >>> from ase.calculators.orca import ORCA 

99 >>> h = Atoms( 

100 ... 'H', 

101 ... calculator=ORCA( 

102 ... charge=0, 

103 ... mult=1, 

104 ... directory='water', 

105 ... orcasimpleinput='B3LYP def2-TZVP', 

106 ... orcablocks='%pal nprocs 16 end')) 

107 

108 """ 

109 

110 assert parallel is None, \ 

111 'ORCA does not support keyword parallel - use orcablocks' 

112 assert parallel_info is None, \ 

113 'ORCA does not support keyword parallel_info - use orcablocks' 

114 

115 super().__init__(template=OrcaTemplate(), 

116 profile=profile, directory=directory, 

117 parameters=kwargs)