MultiOptPy 1.20.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. multioptpy/Calculator/__init__.py +0 -0
  2. multioptpy/Calculator/ase_calculation_tools.py +424 -0
  3. multioptpy/Calculator/ase_tools/__init__.py +0 -0
  4. multioptpy/Calculator/ase_tools/fairchem.py +28 -0
  5. multioptpy/Calculator/ase_tools/gamess.py +19 -0
  6. multioptpy/Calculator/ase_tools/gaussian.py +165 -0
  7. multioptpy/Calculator/ase_tools/mace.py +28 -0
  8. multioptpy/Calculator/ase_tools/mopac.py +19 -0
  9. multioptpy/Calculator/ase_tools/nwchem.py +31 -0
  10. multioptpy/Calculator/ase_tools/orca.py +22 -0
  11. multioptpy/Calculator/ase_tools/pygfn0.py +37 -0
  12. multioptpy/Calculator/dxtb_calculation_tools.py +344 -0
  13. multioptpy/Calculator/emt_calculation_tools.py +458 -0
  14. multioptpy/Calculator/gpaw_calculation_tools.py +183 -0
  15. multioptpy/Calculator/lj_calculation_tools.py +314 -0
  16. multioptpy/Calculator/psi4_calculation_tools.py +334 -0
  17. multioptpy/Calculator/pwscf_calculation_tools.py +189 -0
  18. multioptpy/Calculator/pyscf_calculation_tools.py +327 -0
  19. multioptpy/Calculator/sqm1_calculation_tools.py +611 -0
  20. multioptpy/Calculator/sqm2_calculation_tools.py +376 -0
  21. multioptpy/Calculator/tblite_calculation_tools.py +352 -0
  22. multioptpy/Calculator/tersoff_calculation_tools.py +818 -0
  23. multioptpy/Constraint/__init__.py +0 -0
  24. multioptpy/Constraint/constraint_condition.py +834 -0
  25. multioptpy/Coordinate/__init__.py +0 -0
  26. multioptpy/Coordinate/polar_coordinate.py +199 -0
  27. multioptpy/Coordinate/redundant_coordinate.py +638 -0
  28. multioptpy/IRC/__init__.py +0 -0
  29. multioptpy/IRC/converge_criteria.py +28 -0
  30. multioptpy/IRC/dvv.py +544 -0
  31. multioptpy/IRC/euler.py +439 -0
  32. multioptpy/IRC/hpc.py +564 -0
  33. multioptpy/IRC/lqa.py +540 -0
  34. multioptpy/IRC/modekill.py +662 -0
  35. multioptpy/IRC/rk4.py +579 -0
  36. multioptpy/Interpolation/__init__.py +0 -0
  37. multioptpy/Interpolation/adaptive_interpolation.py +283 -0
  38. multioptpy/Interpolation/binomial_interpolation.py +179 -0
  39. multioptpy/Interpolation/geodesic_interpolation.py +785 -0
  40. multioptpy/Interpolation/interpolation.py +156 -0
  41. multioptpy/Interpolation/linear_interpolation.py +473 -0
  42. multioptpy/Interpolation/savitzky_golay_interpolation.py +252 -0
  43. multioptpy/Interpolation/spline_interpolation.py +353 -0
  44. multioptpy/MD/__init__.py +0 -0
  45. multioptpy/MD/thermostat.py +185 -0
  46. multioptpy/MEP/__init__.py +0 -0
  47. multioptpy/MEP/pathopt_bneb_force.py +443 -0
  48. multioptpy/MEP/pathopt_dmf_force.py +448 -0
  49. multioptpy/MEP/pathopt_dneb_force.py +130 -0
  50. multioptpy/MEP/pathopt_ewbneb_force.py +207 -0
  51. multioptpy/MEP/pathopt_gpneb_force.py +512 -0
  52. multioptpy/MEP/pathopt_lup_force.py +113 -0
  53. multioptpy/MEP/pathopt_neb_force.py +225 -0
  54. multioptpy/MEP/pathopt_nesb_force.py +205 -0
  55. multioptpy/MEP/pathopt_om_force.py +153 -0
  56. multioptpy/MEP/pathopt_qsm_force.py +174 -0
  57. multioptpy/MEP/pathopt_qsmv2_force.py +304 -0
  58. multioptpy/ModelFunction/__init__.py +7 -0
  59. multioptpy/ModelFunction/avoiding_model_function.py +29 -0
  60. multioptpy/ModelFunction/binary_image_ts_search_model_function.py +47 -0
  61. multioptpy/ModelFunction/conical_model_function.py +26 -0
  62. multioptpy/ModelFunction/opt_meci.py +50 -0
  63. multioptpy/ModelFunction/opt_mesx.py +47 -0
  64. multioptpy/ModelFunction/opt_mesx_2.py +49 -0
  65. multioptpy/ModelFunction/seam_model_function.py +27 -0
  66. multioptpy/ModelHessian/__init__.py +0 -0
  67. multioptpy/ModelHessian/approx_hessian.py +147 -0
  68. multioptpy/ModelHessian/calc_params.py +227 -0
  69. multioptpy/ModelHessian/fischer.py +236 -0
  70. multioptpy/ModelHessian/fischerd3.py +360 -0
  71. multioptpy/ModelHessian/fischerd4.py +398 -0
  72. multioptpy/ModelHessian/gfn0xtb.py +633 -0
  73. multioptpy/ModelHessian/gfnff.py +709 -0
  74. multioptpy/ModelHessian/lindh.py +165 -0
  75. multioptpy/ModelHessian/lindh2007d2.py +707 -0
  76. multioptpy/ModelHessian/lindh2007d3.py +822 -0
  77. multioptpy/ModelHessian/lindh2007d4.py +1030 -0
  78. multioptpy/ModelHessian/morse.py +106 -0
  79. multioptpy/ModelHessian/schlegel.py +144 -0
  80. multioptpy/ModelHessian/schlegeld3.py +322 -0
  81. multioptpy/ModelHessian/schlegeld4.py +559 -0
  82. multioptpy/ModelHessian/shortrange.py +346 -0
  83. multioptpy/ModelHessian/swartd2.py +496 -0
  84. multioptpy/ModelHessian/swartd3.py +706 -0
  85. multioptpy/ModelHessian/swartd4.py +918 -0
  86. multioptpy/ModelHessian/tshess.py +40 -0
  87. multioptpy/Optimizer/QHAdam.py +61 -0
  88. multioptpy/Optimizer/__init__.py +0 -0
  89. multioptpy/Optimizer/abc_fire.py +83 -0
  90. multioptpy/Optimizer/adabelief.py +58 -0
  91. multioptpy/Optimizer/adabound.py +68 -0
  92. multioptpy/Optimizer/adadelta.py +65 -0
  93. multioptpy/Optimizer/adaderivative.py +56 -0
  94. multioptpy/Optimizer/adadiff.py +68 -0
  95. multioptpy/Optimizer/adafactor.py +70 -0
  96. multioptpy/Optimizer/adam.py +65 -0
  97. multioptpy/Optimizer/adamax.py +62 -0
  98. multioptpy/Optimizer/adamod.py +83 -0
  99. multioptpy/Optimizer/adamw.py +65 -0
  100. multioptpy/Optimizer/adiis.py +523 -0
  101. multioptpy/Optimizer/afire_neb.py +282 -0
  102. multioptpy/Optimizer/block_hessian_update.py +709 -0
  103. multioptpy/Optimizer/c2diis.py +491 -0
  104. multioptpy/Optimizer/component_wise_scaling.py +405 -0
  105. multioptpy/Optimizer/conjugate_gradient.py +82 -0
  106. multioptpy/Optimizer/conjugate_gradient_neb.py +345 -0
  107. multioptpy/Optimizer/coordinate_locking.py +405 -0
  108. multioptpy/Optimizer/dic_rsirfo.py +1015 -0
  109. multioptpy/Optimizer/ediis.py +417 -0
  110. multioptpy/Optimizer/eve.py +76 -0
  111. multioptpy/Optimizer/fastadabelief.py +61 -0
  112. multioptpy/Optimizer/fire.py +77 -0
  113. multioptpy/Optimizer/fire2.py +249 -0
  114. multioptpy/Optimizer/fire_neb.py +92 -0
  115. multioptpy/Optimizer/gan_step.py +486 -0
  116. multioptpy/Optimizer/gdiis.py +609 -0
  117. multioptpy/Optimizer/gediis.py +203 -0
  118. multioptpy/Optimizer/geodesic_step.py +433 -0
  119. multioptpy/Optimizer/gpmin.py +633 -0
  120. multioptpy/Optimizer/gpr_step.py +364 -0
  121. multioptpy/Optimizer/gradientdescent.py +78 -0
  122. multioptpy/Optimizer/gradientdescent_neb.py +52 -0
  123. multioptpy/Optimizer/hessian_update.py +433 -0
  124. multioptpy/Optimizer/hybrid_rfo.py +998 -0
  125. multioptpy/Optimizer/kdiis.py +625 -0
  126. multioptpy/Optimizer/lars.py +21 -0
  127. multioptpy/Optimizer/lbfgs.py +253 -0
  128. multioptpy/Optimizer/lbfgs_neb.py +355 -0
  129. multioptpy/Optimizer/linesearch.py +236 -0
  130. multioptpy/Optimizer/lookahead.py +40 -0
  131. multioptpy/Optimizer/nadam.py +64 -0
  132. multioptpy/Optimizer/newton.py +200 -0
  133. multioptpy/Optimizer/prodigy.py +70 -0
  134. multioptpy/Optimizer/purtubation.py +16 -0
  135. multioptpy/Optimizer/quickmin_neb.py +245 -0
  136. multioptpy/Optimizer/radam.py +75 -0
  137. multioptpy/Optimizer/rfo_neb.py +302 -0
  138. multioptpy/Optimizer/ric_rfo.py +842 -0
  139. multioptpy/Optimizer/rl_step.py +627 -0
  140. multioptpy/Optimizer/rmspropgrave.py +65 -0
  141. multioptpy/Optimizer/rsirfo.py +1647 -0
  142. multioptpy/Optimizer/rsprfo.py +1056 -0
  143. multioptpy/Optimizer/sadam.py +60 -0
  144. multioptpy/Optimizer/samsgrad.py +63 -0
  145. multioptpy/Optimizer/tr_lbfgs.py +678 -0
  146. multioptpy/Optimizer/trim.py +273 -0
  147. multioptpy/Optimizer/trust_radius.py +207 -0
  148. multioptpy/Optimizer/trust_radius_neb.py +121 -0
  149. multioptpy/Optimizer/yogi.py +60 -0
  150. multioptpy/OtherMethod/__init__.py +0 -0
  151. multioptpy/OtherMethod/addf.py +1150 -0
  152. multioptpy/OtherMethod/dimer.py +895 -0
  153. multioptpy/OtherMethod/elastic_image_pair.py +629 -0
  154. multioptpy/OtherMethod/modelfunction.py +456 -0
  155. multioptpy/OtherMethod/newton_traj.py +454 -0
  156. multioptpy/OtherMethod/twopshs.py +1095 -0
  157. multioptpy/PESAnalyzer/__init__.py +0 -0
  158. multioptpy/PESAnalyzer/calc_irc_curvature.py +125 -0
  159. multioptpy/PESAnalyzer/cmds_analysis.py +152 -0
  160. multioptpy/PESAnalyzer/koopman_analysis.py +268 -0
  161. multioptpy/PESAnalyzer/pca_analysis.py +314 -0
  162. multioptpy/Parameters/__init__.py +0 -0
  163. multioptpy/Parameters/atomic_mass.py +20 -0
  164. multioptpy/Parameters/atomic_number.py +22 -0
  165. multioptpy/Parameters/covalent_radii.py +44 -0
  166. multioptpy/Parameters/d2.py +61 -0
  167. multioptpy/Parameters/d3.py +63 -0
  168. multioptpy/Parameters/d4.py +103 -0
  169. multioptpy/Parameters/dreiding.py +34 -0
  170. multioptpy/Parameters/gfn0xtb_param.py +137 -0
  171. multioptpy/Parameters/gfnff_param.py +315 -0
  172. multioptpy/Parameters/gnb.py +104 -0
  173. multioptpy/Parameters/parameter.py +22 -0
  174. multioptpy/Parameters/uff.py +72 -0
  175. multioptpy/Parameters/unit_values.py +20 -0
  176. multioptpy/Potential/AFIR_potential.py +55 -0
  177. multioptpy/Potential/LJ_repulsive_potential.py +345 -0
  178. multioptpy/Potential/__init__.py +0 -0
  179. multioptpy/Potential/anharmonic_keep_potential.py +28 -0
  180. multioptpy/Potential/asym_elllipsoidal_potential.py +718 -0
  181. multioptpy/Potential/electrostatic_potential.py +69 -0
  182. multioptpy/Potential/flux_potential.py +30 -0
  183. multioptpy/Potential/gaussian_potential.py +101 -0
  184. multioptpy/Potential/idpp.py +516 -0
  185. multioptpy/Potential/keep_angle_potential.py +146 -0
  186. multioptpy/Potential/keep_dihedral_angle_potential.py +105 -0
  187. multioptpy/Potential/keep_outofplain_angle_potential.py +70 -0
  188. multioptpy/Potential/keep_potential.py +99 -0
  189. multioptpy/Potential/mechano_force_potential.py +74 -0
  190. multioptpy/Potential/nanoreactor_potential.py +52 -0
  191. multioptpy/Potential/potential.py +896 -0
  192. multioptpy/Potential/spacer_model_potential.py +221 -0
  193. multioptpy/Potential/switching_potential.py +258 -0
  194. multioptpy/Potential/universal_potential.py +34 -0
  195. multioptpy/Potential/value_range_potential.py +36 -0
  196. multioptpy/Potential/void_point_potential.py +25 -0
  197. multioptpy/SQM/__init__.py +0 -0
  198. multioptpy/SQM/sqm1/__init__.py +0 -0
  199. multioptpy/SQM/sqm1/sqm1_core.py +1792 -0
  200. multioptpy/SQM/sqm2/__init__.py +0 -0
  201. multioptpy/SQM/sqm2/calc_tools.py +95 -0
  202. multioptpy/SQM/sqm2/sqm2_basis.py +850 -0
  203. multioptpy/SQM/sqm2/sqm2_bond.py +119 -0
  204. multioptpy/SQM/sqm2/sqm2_core.py +303 -0
  205. multioptpy/SQM/sqm2/sqm2_data.py +1229 -0
  206. multioptpy/SQM/sqm2/sqm2_disp.py +65 -0
  207. multioptpy/SQM/sqm2/sqm2_eeq.py +243 -0
  208. multioptpy/SQM/sqm2/sqm2_overlapint.py +704 -0
  209. multioptpy/SQM/sqm2/sqm2_qm.py +578 -0
  210. multioptpy/SQM/sqm2/sqm2_rep.py +66 -0
  211. multioptpy/SQM/sqm2/sqm2_srb.py +70 -0
  212. multioptpy/Thermo/__init__.py +0 -0
  213. multioptpy/Thermo/normal_mode_analyzer.py +865 -0
  214. multioptpy/Utils/__init__.py +0 -0
  215. multioptpy/Utils/bond_connectivity.py +264 -0
  216. multioptpy/Utils/calc_tools.py +884 -0
  217. multioptpy/Utils/oniom.py +96 -0
  218. multioptpy/Utils/pbc.py +48 -0
  219. multioptpy/Utils/riemann_curvature.py +208 -0
  220. multioptpy/Utils/symmetry_analyzer.py +482 -0
  221. multioptpy/Visualization/__init__.py +0 -0
  222. multioptpy/Visualization/visualization.py +156 -0
  223. multioptpy/WFAnalyzer/MO_analysis.py +104 -0
  224. multioptpy/WFAnalyzer/__init__.py +0 -0
  225. multioptpy/Wrapper/__init__.py +0 -0
  226. multioptpy/Wrapper/autots.py +1239 -0
  227. multioptpy/Wrapper/ieip_wrapper.py +93 -0
  228. multioptpy/Wrapper/md_wrapper.py +92 -0
  229. multioptpy/Wrapper/neb_wrapper.py +94 -0
  230. multioptpy/Wrapper/optimize_wrapper.py +76 -0
  231. multioptpy/__init__.py +5 -0
  232. multioptpy/entrypoints.py +916 -0
  233. multioptpy/fileio.py +660 -0
  234. multioptpy/ieip.py +340 -0
  235. multioptpy/interface.py +1086 -0
  236. multioptpy/irc.py +529 -0
  237. multioptpy/moleculardynamics.py +432 -0
  238. multioptpy/neb.py +1267 -0
  239. multioptpy/optimization.py +1553 -0
  240. multioptpy/optimizer.py +709 -0
  241. multioptpy-1.20.2.dist-info/METADATA +438 -0
  242. multioptpy-1.20.2.dist-info/RECORD +246 -0
  243. multioptpy-1.20.2.dist-info/WHEEL +5 -0
  244. multioptpy-1.20.2.dist-info/entry_points.txt +9 -0
  245. multioptpy-1.20.2.dist-info/licenses/LICENSE +674 -0
  246. multioptpy-1.20.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,189 @@
1
+ import glob
2
+ import os
3
+ import numpy as np
4
+ from abc import ABC, abstractmethod
5
+
6
+ try:
7
+ from ase import Atoms
8
+ from ase.vibrations import Vibrations
9
+ from ase.calculators.espresso import Espresso
10
+ except ImportError:
11
+ print("ASE or Quantum ESPRESSO is not installed. Please install them to use this module.")
12
+
13
+ from multioptpy.Utils.calc_tools import Calculationtools
14
+ from multioptpy.Parameters.parameter import UnitValueLib, number_element
15
+ from multioptpy.fileio import xyz2list
16
+ from multioptpy.Visualization.visualization import NEBVisualizer
17
+
18
+ class Calculation:
19
+ def __init__(self, **kwarg):
20
+ UVL = UnitValueLib()
21
+ self.bohr2angstroms = UVL.bohr2angstroms
22
+ self.hartree2eV = UVL.hartree2eV
23
+
24
+ self.START_FILE = kwarg["START_FILE"]
25
+ self.N_THREAD = kwarg["N_THREAD"]
26
+ self.SET_MEMORY = kwarg["SET_MEMORY"]
27
+ self.FUNCTIONAL = kwarg["FUNCTIONAL"]
28
+ self.FC_COUNT = kwarg["FC_COUNT"]
29
+ self.BPA_FOLDER_DIRECTORY = kwarg["BPA_FOLDER_DIRECTORY"]
30
+ self.Model_hess = kwarg["Model_hess"]
31
+ self.hessian_flag = False
32
+ self.espresso_input = kwarg.get("espresso_input", {})
33
+
34
+ def calc_exact_hess(self, atom_obj, positions, element_list):
35
+ vib = Vibrations(atom_obj, delta=0.001)
36
+ vib.run()
37
+ result_vib = vib.get_vibrations()
38
+ exact_hess = result_vib.get_hessian_2d()
39
+ vib.clean()
40
+ exact_hess = exact_hess / self.hartree2eV * (self.bohr2angstroms ** 2)
41
+ if type(element_list[0]) is str:
42
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, positions)
43
+ else:
44
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, [number_element(elem_num) for elem_num in element_list], positions)
45
+ self.Model_hess = exact_hess
46
+ return exact_hess
47
+
48
+ def single_point(self, file_directory, element_list, iter, electric_charge_and_multiplicity, method, geom_num_list=None):
49
+ finish_frag = False
50
+ try:
51
+ os.mkdir(file_directory)
52
+ except:
53
+ pass
54
+
55
+ if file_directory is None:
56
+ file_list = ["dummy"]
57
+ else:
58
+ file_list = glob.glob(file_directory + "/*_[0-9].xyz")
59
+
60
+ for num, input_file in enumerate(file_list):
61
+ try:
62
+ if geom_num_list is None:
63
+ positions, _, electric_charge_and_multiplicity = xyz2list(input_file, electric_charge_and_multiplicity)
64
+ else:
65
+ positions = geom_num_list
66
+
67
+ positions = np.array(positions, dtype="float64")
68
+ atom_obj = Atoms(element_list, positions)
69
+ espresso_params = dict(xc=self.FUNCTIONAL, kpts=(1, 1, 1))
70
+ espresso_params.update(self.espresso_input)
71
+ atom_obj.calc = Espresso(**espresso_params)
72
+
73
+ e = atom_obj.get_potential_energy(apply_constraint=False) / self.hartree2eV
74
+ g = -1 * atom_obj.get_forces(apply_constraint=False) * self.bohr2angstroms / self.hartree2eV
75
+
76
+ if self.FC_COUNT == -1 or type(iter) is str:
77
+ if self.hessian_flag:
78
+ _ = self.calc_exact_hess(atom_obj, positions, element_list)
79
+ elif iter % self.FC_COUNT == 0 or self.hessian_flag:
80
+ _ = self.calc_exact_hess(atom_obj, positions, element_list)
81
+ except Exception as error:
82
+ print(error)
83
+ print("This molecule could not be optimized.")
84
+ finish_frag = True
85
+ return np.array([0]), np.array([0]), np.array([0]), finish_frag
86
+
87
+ positions /= self.bohr2angstroms
88
+ self.energy = e
89
+ self.gradient = g
90
+ self.coordinate = positions
91
+
92
+ return e, g, positions, finish_frag
93
+
94
+ class PWSCFEngine(ABC):
95
+ @abstractmethod
96
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
97
+ pass
98
+
99
+ def _get_file_list(self, file_directory):
100
+ return sum([sorted(glob.glob(os.path.join(file_directory, f"*_" + "[0-9]" * i + ".xyz")))
101
+ for i in range(1, 7)], [])
102
+
103
+ def _process_visualization(self, energy_list, gradient_list, num_list, optimize_num, config):
104
+ try:
105
+ if config.save_pict:
106
+ visualizer = NEBVisualizer(config)
107
+ tmp_ene_list = np.array(energy_list, dtype="float64") * config.hartree2kcalmol
108
+ visualizer.plot_energy(num_list, tmp_ene_list - tmp_ene_list[0], optimize_num)
109
+ print("energy graph plotted.")
110
+ gradient_norm_list = [np.sqrt(np.linalg.norm(g) ** 2 / (len(g) * 3)) for g in gradient_list]
111
+ visualizer.plot_gradient(num_list, gradient_norm_list, optimize_num)
112
+ print("gradient graph plotted.")
113
+ except Exception as e:
114
+ print(f"Visualization error: {e}")
115
+
116
+ class PWSCFASEEngine(PWSCFEngine):
117
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
118
+ gradient_list = []
119
+ energy_list = []
120
+ geometry_num_list = []
121
+ num_list = []
122
+ delete_pre_total_velocity = []
123
+
124
+ os.makedirs(file_directory, exist_ok=True)
125
+ file_list = self._get_file_list(file_directory)
126
+
127
+ if not file_list:
128
+ print("No input files found in directory.")
129
+ return (np.array([], dtype="float64"),
130
+ np.array([], dtype="float64"),
131
+ np.array([], dtype="float64"),
132
+ pre_total_velocity)
133
+
134
+ geometry_list_tmp, element_list, _ = xyz2list(file_list[0], None)
135
+ hess_count = 0
136
+
137
+ for num, input_file in enumerate(file_list):
138
+ try:
139
+ print(f"\n{input_file}\n")
140
+ positions, _, electric_charge_and_multiplicity = xyz2list(input_file, None)
141
+
142
+ positions = np.array(positions, dtype="float64")
143
+ atom_obj = Atoms(element_list, positions)
144
+ espresso_params = dict(xc=config.FUNCTIONAL, kpts=(1, 1, 1))
145
+ if hasattr(config, 'espresso_input'):
146
+ espresso_params.update(config.espresso_input)
147
+ atom_obj.calc = Espresso(**espresso_params)
148
+
149
+ e = atom_obj.get_potential_energy(apply_constraint=False) / config.hartree2eV
150
+ g = -1 * atom_obj.get_forces(apply_constraint=False) * config.bohr2angstroms / config.hartree2eV
151
+
152
+ energy_list.append(e)
153
+ gradient_list.append(g)
154
+ geometry_num_list.append(positions / config.bohr2angstroms)
155
+ num_list.append(num)
156
+
157
+ if config.FC_COUNT == -1 or isinstance(optimize_num, str):
158
+ pass
159
+ elif optimize_num % config.FC_COUNT == 0:
160
+ vib = Vibrations(atom_obj, delta=0.001)
161
+ vib.run()
162
+ result_vib = vib.get_vibrations()
163
+ exact_hess = result_vib.get_hessian_2d()
164
+ vib.clean()
165
+ exact_hess = exact_hess / config.hartree2eV * (config.bohr2angstroms ** 2)
166
+ calc_tools = Calculationtools()
167
+ exact_hess = calc_tools.project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, positions)
168
+ np.save(os.path.join(config.NEB_FOLDER_DIRECTORY, f"tmp_hessian_{hess_count}.npy"), exact_hess)
169
+ hess_count += 1
170
+
171
+ except Exception as error:
172
+ print(f"Error: {error}")
173
+ print("This molecule could not be optimized.")
174
+ if optimize_num != 0:
175
+ delete_pre_total_velocity.append(num)
176
+
177
+ self._process_visualization(energy_list, gradient_list, num_list, optimize_num, config)
178
+
179
+ if optimize_num != 0 and len(pre_total_velocity) != 0:
180
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
181
+ pre_total_velocity = pre_total_velocity.tolist()
182
+ for i in sorted(delete_pre_total_velocity, reverse=True):
183
+ pre_total_velocity.pop(i)
184
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
185
+
186
+ return (np.array(energy_list, dtype="float64"),
187
+ np.array(gradient_list, dtype="float64"),
188
+ np.array(geometry_num_list, dtype="float64"),
189
+ pre_total_velocity)
@@ -0,0 +1,327 @@
1
+
2
+ import glob
3
+ import os
4
+ import numpy as np
5
+
6
+ from abc import ABC, abstractmethod
7
+
8
+
9
+ try:
10
+ import pyscf
11
+ from pyscf import tdscf
12
+ from pyscf.hessian import thermo
13
+ except:
14
+ pass
15
+
16
+ from multioptpy.Utils.calc_tools import Calculationtools
17
+ from multioptpy.Parameters.parameter import UnitValueLib
18
+ from multioptpy.fileio import xyz2list
19
+ from multioptpy.Visualization.visualization import NEBVisualizer
20
+
21
+ """
22
+ Ref.:PySCF
23
+ Recent developments in the PySCF program package, Qiming Sun, Xing Zhang, Samragni Banerjee, Peng Bao, Marc Barbry, Nick S. Blunt, Nikolay A. Bogdanov, George H. Booth, Jia Chen, Zhi-Hao Cui, Janus J. Eriksen, Yang Gao, Sheng Guo, Jan Hermann, Matthew R. Hermes, Kevin Koh, Peter Koval, Susi Lehtola, Zhendong Li, Junzi Liu, Narbe Mardirossian, James D. McClain, Mario Motta, Bastien Mussard, Hung Q. Pham, Artem Pulkin, Wirawan Purwanto, Paul J. Robinson, Enrico Ronca, Elvira R. Sayfutyarova, Maximilian Scheurer, Henry F. Schurkus, James E. T. Smith, Chong Sun, Shi-Ning Sun, Shiv Upadhyay, Lucas K. Wagner, Xiao Wang, Alec White, James Daniel Whitfield, Mark J. Williamson, Sebastian Wouters, Jun Yang, Jason M. Yu, Tianyu Zhu, Timothy C. Berkelbach, Sandeep Sharma, Alexander Yu. Sokolov, and Garnet Kin-Lic Chan, J. Chem. Phys., 153, 024109 (2020). doi:10.1063/5.0006074
24
+
25
+ """
26
+
27
+ class Calculation:
28
+ def __init__(self, **kwarg):
29
+ UVL = UnitValueLib()
30
+
31
+ self.bohr2angstroms = UVL.bohr2angstroms
32
+ self.hartree2eV = UVL.hartree2eV
33
+ self.START_FILE = kwarg["START_FILE"]
34
+ self.SUB_BASIS_SET = kwarg["SUB_BASIS_SET"]
35
+ self.ECP = kwarg["ECP"]
36
+ self.BASIS_SET = kwarg["BASIS_SET"]
37
+ self.N_THREAD = kwarg["N_THREAD"]
38
+ self.SET_MEMORY = kwarg["SET_MEMORY"]
39
+ self.FUNCTIONAL = kwarg["FUNCTIONAL"]
40
+ self.FC_COUNT = kwarg["FC_COUNT"]
41
+ self.BPA_FOLDER_DIRECTORY = kwarg["BPA_FOLDER_DIRECTORY"]
42
+ self.Model_hess = kwarg["Model_hess"]
43
+ self.electronic_charge = kwarg["electronic_charge"]
44
+ self.spin_multiplicity = kwarg["spin_multiplicity"]
45
+ self.unrestrict = kwarg["unrestrict"]
46
+ self.dft_grid = kwarg["dft_grid"]
47
+ self.hessian_flag = False
48
+ if kwarg["excited_state"]:
49
+ self.excited_state = kwarg["excited_state"] # Available up to third excited state
50
+ else:
51
+ self.excited_state = 0
52
+
53
+ def single_point(self, file_directory, element_list, iter, electric_charge_and_multiplicity="", method="", geom_num_list=None):
54
+ """execute QM calclation."""
55
+ finish_frag = False
56
+ try:
57
+ os.mkdir(file_directory)
58
+ except:
59
+ pass
60
+
61
+ if file_directory is None:
62
+ file_list = ["dummy"]
63
+ else:
64
+ file_list = glob.glob(file_directory+"/*_[0-9].xyz")
65
+
66
+ for num, input_file in enumerate(file_list):
67
+ try:
68
+ pyscf.lib.num_threads(self.N_THREAD)
69
+
70
+ if geom_num_list is not None:
71
+ geom_num_list = np.array(geom_num_list, dtype="float64")
72
+ input_data_for_display = geom_num_list / self.bohr2angstroms
73
+ input_data = [[element_list[i], geom_num_list[i][0], geom_num_list[i][1], geom_num_list[i][2]] for i in range(len(geom_num_list))]
74
+ print("position is not read from xyz file. The position is read from input variable.")
75
+ mol = pyscf.gto.M(atom = input_data,
76
+ charge = self.electronic_charge,
77
+ spin = self.spin_multiplicity,
78
+ ecp = self.ECP,
79
+ basis = self.SUB_BASIS_SET,
80
+ max_memory = float(self.SET_MEMORY.replace("GB","")) * 1024, #SET_MEMORY unit is GB
81
+ verbose=4)
82
+ else:
83
+ positions, element_list, electric_charge_and_multiplicity = xyz2list(input_file, electric_charge_and_multiplicity)
84
+ input_data_for_display = np.array(positions, dtype="float64")/self.bohr2angstroms
85
+
86
+
87
+ mol = pyscf.gto.M(atom = input_file,
88
+ charge = self.electronic_charge,
89
+ spin = self.spin_multiplicity,
90
+ basis = self.SUB_BASIS_SET,
91
+ ecp = self.ECP,
92
+ max_memory = float(self.SET_MEMORY.replace("GB","")) * 1024, #SET_MEMORY unit is GB
93
+ verbose=4)
94
+
95
+ scf_max_cycle = 500 + 5 * len(element_list)
96
+
97
+ if self.excited_state == 0:
98
+ if self.FUNCTIONAL == "hf" or self.FUNCTIONAL == "HF":
99
+ if int(self.spin_multiplicity) > 0 or self.unrestrict:
100
+ mf = mol.UHF().density_fit()
101
+ else:
102
+ mf = mol.RHF().density_fit()
103
+ else:
104
+ if int(self.spin_multiplicity) > 0 or self.unrestrict:
105
+ mf = mol.UKS().x2c().density_fit()
106
+ else:
107
+ mf = mol.RKS().density_fit()
108
+ mf.xc = self.FUNCTIONAL
109
+ mf.grids.level = self.dft_grid
110
+ print("dft grid: ", self.dft_grid)
111
+ mf.direct_scf = True
112
+ g = mf.run(max_cycle=scf_max_cycle).nuc_grad_method().kernel()
113
+ e = float(vars(mf)["e_tot"])
114
+ else:
115
+ if self.FUNCTIONAL == "hf" or self.FUNCTIONAL == "HF":
116
+ if int(self.spin_multiplicity) > 0 or self.unrestrict:
117
+ mf = mol.UHF().density_fit().run(max_cycle=scf_max_cycle)
118
+
119
+ else:
120
+ mf = mol.RHF().density_fit().run(max_cycle=scf_max_cycle)
121
+
122
+ else:
123
+ if int(self.spin_multiplicity) > 0 or self.unrestrict:
124
+ mf = mol.UKS().x2c().density_fit().run(max_cycle=scf_max_cycle)
125
+
126
+ else:
127
+ mf = mol.RKS().density_fit().run(max_cycle=scf_max_cycle)
128
+ mf.xc = self.FUNCTIONAL
129
+ mf.grids.level = self.dft_grid
130
+ mf.direct_scf = True
131
+ print("dft grid: ", self.dft_grid)
132
+ ground_e = float(vars(mf)["e_tot"])
133
+ mf = tdscf.TDA(mf)
134
+ g = mf.run(max_cycle=scf_max_cycle).nuc_grad_method().kernel(state=self.excited_state)
135
+ e = vars(mf)["e"][self.excited_state-1]
136
+ e += ground_e
137
+
138
+ g = np.array(g, dtype = "float64")
139
+
140
+ print("\n")
141
+
142
+
143
+
144
+ if self.FC_COUNT == -1 or type(iter) is str:
145
+ if self.hessian_flag:
146
+ self.exact_hessian(element_list, input_data_for_display, mf)
147
+
148
+ elif iter % self.FC_COUNT == 0 or self.hessian_flag:
149
+
150
+ self.exact_hessian(element_list, input_data_for_display, mf)
151
+
152
+ except Exception as error:
153
+ print(error)
154
+ print("This molecule could not be optimized.")
155
+ print("Input file: ",file_list,"\n")
156
+ finish_frag = True
157
+ return np.array([0]), np.array([0]), input_data_for_display, finish_frag
158
+
159
+ self.energy = e
160
+ self.gradient = g
161
+ self.coordinate = input_data_for_display
162
+
163
+ return e, g, input_data_for_display, finish_frag
164
+
165
+ def exact_hessian(self, element_list, input_data_for_display, mf):
166
+ """exact hessian"""
167
+ exact_hess = mf.Hessian().kernel()
168
+
169
+ freqs = thermo.harmonic_analysis(mf.mol, exact_hess)
170
+ exact_hess = exact_hess.transpose(0,2,1,3).reshape(len(input_data_for_display)*3, len(input_data_for_display)*3)
171
+ print("frequencies: \n",freqs["freq_wavenumber"])
172
+ #eigenvalues, _ = np.linalg.eigh(exact_hess)
173
+ #print("=== hessian (before add bias potential) ===")
174
+ #print("eigenvalues: ", eigenvalues)
175
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, input_data_for_display, display_eigval=False)
176
+
177
+ self.Model_hess = exact_hess
178
+
179
+
180
+
181
+ class CalculationEngine(ABC):
182
+ """Base class for calculation engines"""
183
+
184
+ @abstractmethod
185
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
186
+ """Calculate energy and gradients"""
187
+ pass
188
+
189
+ def _get_file_list(self, file_directory):
190
+ """Get list of input files"""
191
+ return sum([sorted(glob.glob(os.path.join(file_directory, f"*_" + "[0-9]" * i + ".xyz")))
192
+ for i in range(1, 7)], [])
193
+
194
+ def _process_visualization(self, energy_list, gradient_list, num_list, optimize_num, config):
195
+ """Process common visualization tasks"""
196
+ try:
197
+ if config.save_pict:
198
+ visualizer = NEBVisualizer(config)
199
+ tmp_ene_list = np.array(energy_list, dtype="float64") * config.hartree2kcalmol
200
+ visualizer.plot_energy(num_list, tmp_ene_list - tmp_ene_list[0], optimize_num)
201
+ print("energy graph plotted.")
202
+
203
+ gradient_norm_list = [np.sqrt(np.linalg.norm(g)**2/(len(g)*3)) for g in gradient_list]
204
+ visualizer.plot_gradient(num_list, gradient_norm_list, optimize_num)
205
+ print("gradient graph plotted.")
206
+ except Exception as e:
207
+ print(f"Visualization error: {e}")
208
+
209
+
210
+
211
+
212
+ class PySCFEngine(CalculationEngine):
213
+ """PySCF calculation engine"""
214
+
215
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
216
+ gradient_list = []
217
+ energy_list = []
218
+ geometry_num_list = []
219
+ gradient_norm_list = []
220
+ delete_pre_total_velocity = []
221
+ num_list = []
222
+
223
+ os.makedirs(file_directory, exist_ok=True)
224
+ file_list = self._get_file_list(file_directory)
225
+
226
+ hess_count = 0
227
+
228
+ for num, input_file in enumerate(file_list):
229
+ try:
230
+ print(input_file)
231
+ geometry_list, element_list, electric_charge_and_multiplicity = xyz2list(input_file, None)
232
+ words = []
233
+ for i in range(len(geometry_list)):
234
+ words.append([element_list[i], float(geometry_list[i][0]), float(geometry_list[i][1]), float(geometry_list[i][2])])
235
+
236
+ input_data_for_display = np.array(geometry_list, dtype="float64") / config.bohr2angstroms
237
+
238
+ mol = pyscf.gto.M(atom=words,
239
+ charge=int(electric_charge_and_multiplicity[0]),
240
+ spin=int(electric_charge_and_multiplicity[1]),
241
+ basis=config.SUB_BASIS_SET,
242
+ ecp=config.ECP,
243
+ max_memory=float(config.SET_MEMORY.replace("GB","")) * 1024,
244
+ verbose=4)
245
+
246
+ if config.excited_state == 0:
247
+ if config.FUNCTIONAL == "hf" or config.FUNCTIONAL == "HF":
248
+ if int(electric_charge_and_multiplicity[1]) > 0 or config.unrestrict:
249
+ mf = mol.UHF().density_fit()
250
+ else:
251
+ mf = mol.RHF().density_fit()
252
+ else:
253
+ if int(electric_charge_and_multiplicity[1]) > 0 or config.unrestrict:
254
+ mf = mol.UKS().x2c().density_fit()
255
+ else:
256
+ mf = mol.RKS().density_fit()
257
+ mf.xc = config.FUNCTIONAL
258
+ mf.grids.level = config.dft_grid
259
+ g = mf.run().nuc_grad_method().kernel()
260
+ e = float(vars(mf)["e_tot"])
261
+ else:
262
+ if config.FUNCTIONAL == "hf" or config.FUNCTIONAL == "HF":
263
+ if int(electric_charge_and_multiplicity[1])-1 > 0 or config.unrestrict:
264
+ mf = mol.UHF().density_fit().run()
265
+ else:
266
+ mf = mol.RHF().density_fit().run()
267
+ else:
268
+ if int(electric_charge_and_multiplicity[1])-1 > 0 or config.unrestrict:
269
+ mf = mol.UKS().x2c().density_fit().run()
270
+ else:
271
+ mf = mol.RKS().density_fit().run()
272
+ mf.xc = config.FUNCTIONAL
273
+ mf.grids.level = config.dft_grid
274
+
275
+ ground_e = float(vars(mf)["e_tot"])
276
+
277
+ mf = tdscf.TDA(mf)
278
+ g = mf.run().nuc_grad_method().kernel(state=config.excited_state)
279
+ e = vars(mf)["e"][config.excited_state-1]
280
+ e += ground_e
281
+
282
+ g = np.array(g, dtype="float64")
283
+ print("\n")
284
+ energy_list.append(e)
285
+ gradient_list.append(g)
286
+ gradient_norm_list.append(np.sqrt(np.linalg.norm(g)**2/(len(g)*3))) # RMS
287
+ geometry_num_list.append(input_data_for_display)
288
+ num_list.append(num)
289
+
290
+ if config.FC_COUNT == -1 or type(optimize_num) is str:
291
+ pass
292
+ elif optimize_num % config.FC_COUNT == 0:
293
+ """exact hessian"""
294
+ exact_hess = mf.Hessian().kernel()
295
+ freqs = thermo.harmonic_analysis(mf.mol, exact_hess)
296
+ exact_hess = exact_hess.transpose(0,2,1,3).reshape(len(input_data_for_display)*3, len(input_data_for_display)*3)
297
+ print("frequencies: \n", freqs["freq_wavenumber"])
298
+ eigenvalues, _ = np.linalg.eigh(exact_hess)
299
+ print("=== hessian (before add bias potential) ===")
300
+ print("eigenvalues: ", eigenvalues)
301
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, input_data_for_display)
302
+
303
+ np.save(config.NEB_FOLDER_DIRECTORY + "tmp_hessian_" + str(hess_count) + ".npy", exact_hess)
304
+ with open(config.NEB_FOLDER_DIRECTORY + "tmp_hessian_" + str(hess_count) + ".csv", "a") as f:
305
+ f.write("frequency," + ",".join(map(str, freqs["freq_wavenumber"])) + "\n")
306
+ hess_count += 1
307
+
308
+ except Exception as error:
309
+ print(error)
310
+ print("This molecule could not be optimized.")
311
+ if optimize_num != 0:
312
+ delete_pre_total_velocity.append(num)
313
+
314
+ self._process_visualization(energy_list, gradient_list, num_list, optimize_num, config)
315
+
316
+ if optimize_num != 0 and len(pre_total_velocity) != 0:
317
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
318
+ pre_total_velocity = pre_total_velocity.tolist()
319
+ for i in sorted(delete_pre_total_velocity, reverse=True):
320
+ pre_total_velocity.pop(i)
321
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
322
+
323
+ return (np.array(energy_list, dtype="float64"),
324
+ np.array(gradient_list, dtype="float64"),
325
+ np.array(geometry_num_list, dtype="float64"),
326
+ pre_total_velocity)
327
+