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,314 @@
1
+ import glob
2
+ import os
3
+ import numpy as np
4
+ from abc import ABC, abstractmethod
5
+
6
+
7
+ from multioptpy.Utils.calc_tools import Calculationtools
8
+ from multioptpy.Parameters.parameter import UnitValueLib, number_element
9
+ from multioptpy.fileio import xyz2list
10
+ from multioptpy.Visualization.visualization import NEBVisualizer
11
+
12
+ class LennardJonesCore:
13
+ """
14
+ Core calculator for Lennard-Jones potential using UFF parameters.
15
+ Handles both homo- and hetero-atomic clusters using combining rules.
16
+ """
17
+ # UFF parameters with well depth D_i in kcal/mol.
18
+ # Source: Rappe, A. K., et al. J. Am. Chem. Soc. 1992, 114, 10024-10035.
19
+ UFF_PARAMETERS = {
20
+ 'He': {'x_i': 2.868, 'D_i': 0.0216},
21
+ 'Ne': {'x_i': 3.087, 'D_i': 0.0731},
22
+ 'Ar': {'x_i': 3.817, 'D_i': 0.237},
23
+ 'Kr': {'x_i': 4.047, 'D_i': 0.357},
24
+ 'Xe': {'x_i': 4.363, 'D_i': 0.507},
25
+ 'Rn': {'x_i': 4.500, 'D_i': 0.635}, # Extrapolated/common value
26
+ }
27
+ SIGMA_CONV_FACTOR = 1 / (2**(1/6))
28
+
29
+ def __init__(self):
30
+ """Initializes a general Lennard-Jones calculator."""
31
+ self.UVL = UnitValueLib()
32
+ # Cache for memoizing parameters of atom types
33
+ self._param_cache = {}
34
+
35
+ def get_parameters(self, atom_symbols):
36
+ """
37
+ Retrieves and converts UFF parameters for a list of atom symbols.
38
+ Returns arrays of sigma and epsilon values for each atom in the list.
39
+ """
40
+ sigmas = np.zeros(len(atom_symbols))
41
+ epsilons = np.zeros(len(atom_symbols))
42
+
43
+ for i, symbol in enumerate(atom_symbols):
44
+
45
+
46
+ if symbol not in self._param_cache:
47
+ if symbol not in self.UFF_PARAMETERS:
48
+ raise ValueError(f"Atom symbol '{symbol}' is not supported. "
49
+ f"Supported: {list(self.UFF_PARAMETERS.keys())}")
50
+
51
+ params = self.UFF_PARAMETERS[symbol]
52
+ sigma_angstrom = params['x_i'] * self.SIGMA_CONV_FACTOR
53
+ sigma = sigma_angstrom / self.UVL.bohr2angstroms
54
+ # Corrected conversion from kcal/mol to hartree
55
+ epsilon = params['D_i'] / self.UVL.hartree2kcalmol
56
+ self._param_cache[symbol] = (sigma, epsilon)
57
+
58
+ sigmas[i], epsilons[i] = self._param_cache[symbol]
59
+
60
+ return sigmas, epsilons
61
+
62
+ def calculate_energy_and_gradient(self, coords_bohr, atom_symbols):
63
+ """Calculates the LJ energy and gradient for a list of atoms."""
64
+ num_atoms = coords_bohr.shape[0]
65
+ if num_atoms <= 1:
66
+ return {"energy": 0.0, "gradient": np.zeros_like(coords_bohr)}
67
+
68
+ base_sigmas, base_epsilons = self.get_parameters(atom_symbols)
69
+
70
+ a, b = np.triu_indices(num_atoms, 1)
71
+ diffs = coords_bohr[a] - coords_bohr[b]
72
+ dists_sq = np.sum(diffs**2, axis=1)
73
+ dists = np.sqrt(dists_sq)
74
+
75
+ # Apply Lorentz-Berthelot combining rules for each pair
76
+ sigmas_ab = (base_sigmas[a] + base_sigmas[b]) / 2.0
77
+ epsilons_ab = np.sqrt(base_epsilons[a] * base_epsilons[b])
78
+
79
+ sigma_over_r = sigmas_ab / dists
80
+ sigma_over_r_6 = sigma_over_r**6
81
+ sigma_over_r_12 = sigma_over_r_6**2
82
+
83
+ energy = np.sum(4 * epsilons_ab * (sigma_over_r_12 - sigma_over_r_6))
84
+
85
+ grad_mag_over_r = -24 * epsilons_ab / dists_sq * (2 * sigma_over_r_12 - sigma_over_r_6)
86
+ grad_pairs = grad_mag_over_r[:, np.newaxis] * diffs
87
+ gradient = np.zeros_like(coords_bohr)
88
+ np.add.at(gradient, a, grad_pairs)
89
+ np.add.at(gradient, b, -grad_pairs)
90
+
91
+ return {"energy": energy, "gradient": gradient}
92
+
93
+ def calculate_hessian(self, coords_bohr, atom_symbols):
94
+ """Calculates the LJ Hessian for a list of atoms using a vectorized approach."""
95
+ num_atoms = coords_bohr.shape[0]
96
+ hessian = np.zeros((num_atoms * 3, num_atoms * 3))
97
+ if num_atoms <= 1:
98
+ return {"hessian": hessian}
99
+
100
+ base_sigmas, base_epsilons = self.get_parameters(atom_symbols)
101
+
102
+ a, b = np.triu_indices(num_atoms, 1)
103
+ diffs = coords_bohr[a] - coords_bohr[b]
104
+ dists_sq = np.sum(diffs**2, axis=1)
105
+ dists = np.sqrt(dists_sq)
106
+
107
+ sigmas_ab = (base_sigmas[a] + base_sigmas[b]) / 2.0
108
+ epsilons_ab = np.sqrt(base_epsilons[a] * base_epsilons[b])
109
+
110
+ sigma_over_r = sigmas_ab / dists
111
+ sigma_over_r_6 = sigma_over_r**6
112
+ sigma_over_r_12 = sigma_over_r_6**2
113
+
114
+ grad_mag_over_r = -24 * epsilons_ab / dists_sq * (2 * sigma_over_r_12 - sigma_over_r_6)
115
+ d2V_dr2 = 24 * epsilons_ab / dists_sq * (26 * sigma_over_r_12 - 7 * sigma_over_r_6)
116
+ dV_dr_over_r = -grad_mag_over_r
117
+
118
+ term1_mag = (d2V_dr2 - dV_dr_over_r) / dists_sq
119
+ term2_mag = dV_dr_over_r
120
+ term1 = np.einsum('p,pi,pj->pij', term1_mag, diffs, diffs)
121
+ term2 = np.identity(3)[np.newaxis, :, :] * term2_mag[:, np.newaxis, np.newaxis]
122
+ sub_hessians = term1 + term2
123
+
124
+ # **Vectorized Hessian Assembly**
125
+ # Create meshgrid of indices for all 3x3 sub-blocks
126
+ p, q = np.meshgrid(np.arange(3), np.arange(3), indexing='ij')
127
+
128
+ # Indices for off-diagonal blocks (a, b) and (b, a)
129
+ row_indices_ab = (a[:, None, None] * 3 + p).flatten()
130
+ col_indices_ab = (b[:, None, None] * 3 + q).flatten()
131
+
132
+ # Indices for diagonal blocks (a, a) and (b, b)
133
+ row_indices_aa = (a[:, None, None] * 3 + p).flatten()
134
+ col_indices_aa = (a[:, None, None] * 3 + q).flatten()
135
+ row_indices_bb = (b[:, None, None] * 3 + p).flatten()
136
+ col_indices_bb = (b[:, None, None] * 3 + q).flatten()
137
+
138
+ # Flatten the sub-hessian blocks to match the indices
139
+ flat_sub_hessians = sub_hessians.flatten()
140
+
141
+ # Atomically add/subtract the blocks into the Hessian matrix
142
+ np.subtract.at(hessian, (row_indices_ab, col_indices_ab), flat_sub_hessians)
143
+ np.subtract.at(hessian, (col_indices_ab, row_indices_ab), flat_sub_hessians)
144
+ np.add.at(hessian, (row_indices_aa, col_indices_aa), flat_sub_hessians)
145
+ np.add.at(hessian, (row_indices_bb, col_indices_bb), flat_sub_hessians)
146
+
147
+ return {"hessian": hessian}
148
+
149
+ class Calculation:
150
+ """
151
+ High-level wrapper for Lennard-Jones calculations.
152
+ """
153
+ def __init__(self, **kwarg):
154
+ UVL = UnitValueLib()
155
+ self.bohr2angstroms = UVL.bohr2angstroms
156
+ self.atom_symbol = kwarg.get("atom_symbol", None) # Can be None initially
157
+ self.FC_COUNT = kwarg.get("FC_COUNT", -1)
158
+ self.Model_hess = kwarg.get("Model_hess")
159
+ self.hessian_flag = kwarg.get("hessian_flag", False)
160
+ self.calculator = LennardJonesCore()
161
+ self.energy = None
162
+ self.gradient = None
163
+ self.coordinate = None
164
+
165
+ def exact_hessian(self, element_list, positions_bohr):
166
+ """Calculates and projects the Hessian."""
167
+ results = self.calculator.calculate_hessian(positions_bohr, self.atom_symbol)
168
+ exact_hess = results['hessian']
169
+
170
+ self.Model_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(
171
+ exact_hess, element_list, positions_bohr, display_eigval=False
172
+ )
173
+
174
+ def single_point(self, file_directory, element_list, iter, electric_charge_and_multiplicity, method="", geom_num_list=None):
175
+ """
176
+ Executes a Lennard-Jones single point calculation, reading from a file
177
+ or using a provided geometry.
178
+ """
179
+ finish_frag = False
180
+ e, g, positions_bohr = None, None, None
181
+
182
+ try:
183
+ os.makedirs(file_directory, exist_ok=True)
184
+ except (OSError, TypeError): # TypeError if file_directory is None
185
+ pass
186
+
187
+ if file_directory is None:
188
+ file_list = ["dummy"] # To run the loop once for geom_num_list
189
+ else:
190
+ file_list = sorted(glob.glob(os.path.join(file_directory, "*_[0-9].xyz")))
191
+ if not file_list and geom_num_list is None:
192
+ raise FileNotFoundError(f"No XYZ files found in {file_directory}")
193
+
194
+ for num, input_file in enumerate(file_list):
195
+ try:
196
+ positions_angstrom = None
197
+ if geom_num_list is None:
198
+ positions_angstrom, read_elements, _ = xyz2list(input_file, electric_charge_and_multiplicity)
199
+
200
+ element_list = read_elements
201
+ else:
202
+ positions_angstrom = geom_num_list
203
+
204
+ if self.atom_symbol is None:
205
+ if element_list is None or len(element_list) == 0:
206
+ raise ValueError("Element list is empty. Cannot determine atom symbol.")
207
+ first_element = element_list
208
+ if type(element_list[0]) is not str:
209
+ first_element = []
210
+ for i in range(len(element_list)):
211
+ first_element.append(number_element(element_list[i]))
212
+
213
+ self.atom_symbol = first_element
214
+ print(f"Atom symbol set to '{self.atom_symbol}' based on the first structure.")
215
+
216
+ positions_bohr = np.array(positions_angstrom, dtype="float64") / self.bohr2angstroms
217
+
218
+ results = self.calculator.calculate_energy_and_gradient(positions_bohr, self.atom_symbol)
219
+ e = results['energy']
220
+ g = results['gradient']
221
+
222
+ if self.FC_COUNT == -1 or isinstance(iter, str):
223
+ if self.hessian_flag:
224
+ self.exact_hessian(element_list, positions_bohr)
225
+ elif iter % self.FC_COUNT == 0 or self.hessian_flag:
226
+ self.exact_hessian(element_list, positions_bohr)
227
+
228
+ break
229
+
230
+ except Exception as error:
231
+ print(f"Error during Lennard-Jones calculation for {input_file}: {error}")
232
+ finish_frag = True
233
+ return np.array([0]), np.array([0]), np.array([0]), finish_frag
234
+
235
+ self.energy = e
236
+ self.gradient = g
237
+ self.coordinate = positions_bohr
238
+ return e, g, positions_bohr, finish_frag
239
+
240
+ class CalculationEngine(ABC):
241
+ @abstractmethod
242
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
243
+ pass
244
+ def _get_file_list(self, file_directory):
245
+ return sum([sorted(glob.glob(os.path.join(file_directory, f"*_" + "[0-9]" * i + ".xyz"))) for i in range(1, 7)], [])
246
+ def _process_visualization(self, energy_list, gradient_list, num_list, optimize_num, config):
247
+ try:
248
+ if hasattr(config, 'save_pict') and config.save_pict:
249
+ visualizer = NEBVisualizer(config)
250
+ tmp_ene_list = np.array(energy_list, dtype="float64") * config.hartree2kcalmol
251
+ visualizer.plot_energy(num_list, tmp_ene_list - tmp_ene_list[0], optimize_num)
252
+ print("energy graph plotted.")
253
+ gradient_norm_list = [np.sqrt(np.linalg.norm(g)**2 / (len(g) * 3)) for g in gradient_list if g.size > 0]
254
+ visualizer.plot_gradient(num_list, gradient_norm_list, optimize_num)
255
+ print("gradient graph plotted.")
256
+ except Exception as e:
257
+ print(f"Visualization error: {e}")
258
+
259
+ class LJEngine(CalculationEngine):
260
+ def __init__(self, atom_symbol=None):
261
+ super().__init__()
262
+ self.atom_symbol = atom_symbol
263
+ self.calculator = LennardJonesCore()
264
+ self.bohr2angstroms = UnitValueLib().bohr2angstroms
265
+
266
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
267
+ gradient_list, energy_list, geometry_num_list, num_list = [], [], [], []
268
+ delete_pre_total_velocity = []
269
+ os.makedirs(file_directory, exist_ok=True)
270
+ file_list = self._get_file_list(file_directory)
271
+
272
+ if not file_list:
273
+ print(f"No XYZ files found in directory: {file_directory}")
274
+ return np.array([]), np.array([]), np.array([]), pre_total_velocity
275
+
276
+ for num, input_file in enumerate(file_list):
277
+ try:
278
+
279
+ print(f"Processing file: {input_file}")
280
+ positions_angstrom, element_list, _ = xyz2list(input_file, None)
281
+
282
+ if self.atom_symbol is None:
283
+ if element_list is None or len(element_list) == 0:
284
+ raise ValueError("Element list from file is empty.")
285
+ first_element = element_list
286
+ if type(element_list[0]) is not str:
287
+ first_element = []
288
+ for i in range(len(element_list)):
289
+ first_element.append(number_element(element_list[i]))
290
+
291
+ self.atom_symbol = first_element
292
+ print(f"Engine atom symbol set to '{self.atom_symbol}' based on the first file.")
293
+
294
+ positions_angstrom = np.array(positions_angstrom, dtype='float64').reshape(-1, 3)
295
+ positions_bohr = positions_angstrom / self.bohr2angstroms
296
+
297
+ results = self.calculator.calculate_energy_and_gradient(positions_bohr, self.atom_symbol)
298
+
299
+ energy_list.append(results['energy'])
300
+ gradient_list.append(results['gradient'])
301
+ geometry_num_list.append(positions_bohr)
302
+ num_list.append(num)
303
+ except Exception as error:
304
+ print(f"Error processing {input_file}: {error}")
305
+ if optimize_num != 0:
306
+ delete_pre_total_velocity.append(num)
307
+
308
+ self._process_visualization(energy_list, gradient_list, num_list, optimize_num, config)
309
+ if optimize_num != 0 and len(pre_total_velocity) > 0 and delete_pre_total_velocity:
310
+ pre_total_velocity = np.delete(np.array(pre_total_velocity), delete_pre_total_velocity, axis=0)
311
+ return (np.array(energy_list, dtype='float64'),
312
+ np.array(gradient_list, dtype='float64'),
313
+ np.array(geometry_num_list, dtype='float64'),
314
+ pre_total_velocity)
@@ -0,0 +1,334 @@
1
+ import glob
2
+ import os
3
+
4
+ import numpy as np
5
+ from abc import ABC, abstractmethod
6
+
7
+ try:
8
+ import psi4
9
+ except:
10
+ pass
11
+
12
+ from multioptpy.Utils.calc_tools import Calculationtools
13
+ from multioptpy.fileio import xyz2list
14
+ from multioptpy.Visualization.visualization import NEBVisualizer
15
+
16
+ """
17
+ Psi4
18
+ D. G. A. Smith, L. A. Burns, A. C. Simmonett, R. M. Parrish, M. C. Schieber, R. Galvelis, P. Kraus, H. Kruse, R. Di Remigio, A. Alenaizan, A. M. James, S. Lehtola, J. P. Misiewicz, M. Scheurer, R. A. Shaw, J. B. Schriber, Y. Xie, Z. L. Glick, D. A. Sirianni, J. S. O'Brien, J. M. Waldrop, A. Kumar, E. G. Hohenstein, B. P. Pritchard, B. R. Brooks, H. F. Schaefer III, A. Yu. Sokolov, K. Patkowski, A. E. DePrince III, U. Bozkaya, R. A. King, F. A. Evangelista, J. M. Turney, T. D. Crawford, C. D. Sherrill, "Psi4 1.4: Open-Source Software for High-Throughput Quantum Chemistry", J. Chem. Phys. 152(18) 184108 (2020).
19
+
20
+ """
21
+ class Calculation:
22
+ def __init__(self, **kwarg):
23
+
24
+ self.START_FILE = kwarg["START_FILE"]
25
+ self.SUB_BASIS_SET = kwarg["SUB_BASIS_SET"]
26
+ self.BASIS_SET = kwarg["BASIS_SET"]
27
+ self.N_THREAD = kwarg["N_THREAD"]
28
+ self.SET_MEMORY = kwarg["SET_MEMORY"]
29
+ self.FUNCTIONAL = kwarg["FUNCTIONAL"]
30
+ self.FC_COUNT = kwarg["FC_COUNT"]
31
+ self.BPA_FOLDER_DIRECTORY = kwarg["BPA_FOLDER_DIRECTORY"]
32
+ self.Model_hess = kwarg["Model_hess"]
33
+ self.unrestrict = kwarg["unrestrict"]
34
+ self.dft_grid = kwarg["dft_grid"]
35
+ self.hessian_flag = False
36
+ if kwarg["excited_state"]:
37
+ self.excited_state = kwarg["excited_state"]
38
+ else:
39
+ self.excited_state = 0
40
+ return
41
+
42
+ def set_dft_grid(self):
43
+ """set dft grid"""
44
+ if self.dft_grid == 0 or self.dft_grid == 1:
45
+ psi4.set_options({'DFT_RADIAL_POINTS': 50, 'DFT_SPHERICAL_POINTS': 194})
46
+ print("DFT Grid (50, 194): SG1")
47
+ elif self.dft_grid == 2 or self.dft_grid == 3:
48
+ psi4.set_options({'DFT_RADIAL_POINTS': 75, 'DFT_SPHERICAL_POINTS': 302})
49
+ print("DFT Grid (70, 302): Default")
50
+ elif self.dft_grid == 4 or self.dft_grid == 5:
51
+ psi4.set_options({'DFT_RADIAL_POINTS': 99, 'DFT_SPHERICAL_POINTS': 590})
52
+ print("DFT Grid (99, 590): Fine")
53
+ elif self.dft_grid == 6 or self.dft_grid == 7:
54
+ psi4.set_options({'DFT_RADIAL_POINTS': 150, 'DFT_SPHERICAL_POINTS': 770})
55
+ print("DFT Grid (150, 770): UltraFine")
56
+ elif self.dft_grid == 8 or self.dft_grid == 9:
57
+ psi4.set_options({'DFT_RADIAL_POINTS': 250, 'DFT_SPHERICAL_POINTS': 974})
58
+ print("DFT Grid (250, 974): SuperFine")
59
+ else:
60
+ raise ValueError("Invalid dft grid setting.")
61
+
62
+ def single_point(self, file_directory, element_list, iter, electric_charge_and_multiplicity, method="", geom_num_list=None):
63
+ """execute QM calclation."""
64
+ finish_frag = False
65
+ input_data_for_display = None
66
+ try:
67
+ os.mkdir(file_directory)
68
+ except:
69
+ pass
70
+ if file_directory is None:
71
+ file_list = ["dummy"]
72
+ else:
73
+ file_list = glob.glob(file_directory+"/*_[0-9].xyz")
74
+
75
+ for num, input_file in enumerate(file_list):
76
+ try:
77
+
78
+ if int(electric_charge_and_multiplicity[1]) > 1 or self.unrestrict:
79
+ psi4.set_options({'reference': 'uks'})
80
+ logfile = file_directory+"/"+self.START_FILE[:-4]+'_'+str(num)+'.log'
81
+ psi4.set_options({"MAXITER": 500})
82
+ self.set_dft_grid()
83
+ if len(self.SUB_BASIS_SET) > 0:
84
+ psi4.basis_helper(self.SUB_BASIS_SET, name='User_Basis_Set', set_option=False)
85
+ psi4.set_options({"basis":'User_Basis_Set'})
86
+ else:
87
+ psi4.set_options({"basis":self.BASIS_SET})
88
+
89
+ if self.excited_state > 0:
90
+ psi4.set_options({'TDSCF_STATES': self.excited_state})
91
+
92
+ psi4.set_output_file(logfile)
93
+ psi4.set_num_threads(nthread=self.N_THREAD)
94
+ psi4.set_memory(self.SET_MEMORY)
95
+ #psi4.procrouting.response.scf_response.tdscf_excitations
96
+ psi4.set_options({"cubeprop_tasks": ["esp"],'cubeprop_filepath': file_directory})
97
+
98
+ if geom_num_list is None:
99
+
100
+ input_data = ""
101
+ position, element_list, electric_charge_and_multiplicity = xyz2list(input_file, electric_charge_and_multiplicity)
102
+ input_data_for_display = np.array(position, dtype="float64")/psi4.constants.bohr2angstroms
103
+ input_data += " ".join(list(map(str, electric_charge_and_multiplicity)))+"\n"
104
+ for j in range(len(position)):
105
+ input_data += element_list[j]+" "+" ".join(position[j])+"\n"
106
+ else:
107
+ print("Input data is given as a numpy array.")
108
+ input_data = ""
109
+
110
+ input_data += " ".join(list(map(str, electric_charge_and_multiplicity)))+"\n"
111
+ for j in range(len(geom_num_list)):
112
+ input_data += element_list[j]+" "+" ".join(list(map(str, geom_num_list[j].tolist())))+"\n"
113
+ input_data_for_display = geom_num_list / psi4.constants.bohr2angstroms
114
+
115
+ input_data = psi4.geometry(input_data)#ang.
116
+
117
+
118
+ g, wfn = psi4.gradient(self.FUNCTIONAL, molecule=input_data, return_wfn=True)
119
+
120
+ e = float(wfn.energy())
121
+ g = np.array(g, dtype = "float64")
122
+ psi4.oeprop(wfn, 'DIPOLE')
123
+ psi4.oeprop(wfn, 'MULLIKEN_CHARGES')
124
+ psi4.oeprop(wfn, 'LOWDIN_CHARGES')
125
+ #psi4.oeprop(wfn, 'WIBERG_LOWDIN_INDICES')
126
+ lumo_alpha = wfn.nalpha()
127
+ lumo_beta = wfn.nbeta()
128
+
129
+ MO_levels = np.array(wfn.epsilon_a_subset("AO","ALL")).tolist()#MO energy levels
130
+ with open(self.BPA_FOLDER_DIRECTORY+"MO_levels.csv" ,"a") as f:
131
+ f.write(",".join(list(map(str,MO_levels))+[str(lumo_alpha),str(lumo_beta)])+"\n")
132
+ with open(self.BPA_FOLDER_DIRECTORY+"dipole.csv" ,"a") as f:
133
+ f.write(",".join(list(map(str,(psi4.constants.dipmom_au2debye*wfn.variable('DIPOLE')).tolist()))+[str(np.linalg.norm(psi4.constants.dipmom_au2debye*wfn.variable('DIPOLE'),ord=2))])+"\n")
134
+ with open(self.BPA_FOLDER_DIRECTORY+"MULLIKEN_CHARGES.csv" ,"a") as f:
135
+ f.write(",".join(list(map(str,wfn.variable('MULLIKEN CHARGES').tolist())))+"\n")
136
+
137
+ alpha_first_ionization_energy = -1 * MO_levels[lumo_alpha-1]
138
+ alpha_electron_affinity = MO_levels[lumo_alpha]
139
+ global_electrophilicity_index = (alpha_first_ionization_energy + alpha_electron_affinity) / (8 * (alpha_first_ionization_energy - alpha_electron_affinity + 1e-15))
140
+
141
+ print("=== global electrophilicity index ===")
142
+ print(global_electrophilicity_index, "hartree")
143
+
144
+ #with open(input_file[:-4]+"_WIBERG_LOWDIN_INDICES.csv" ,"a") as f:
145
+ # for i in range(len(np.array(wfn.variable('WIBERG LOWDIN INDICES')).tolist())):
146
+ # f.write(",".join(list(map(str,np.array(wfn.variable('WIBERG LOWDIN INDICES')).tolist()[i])))+"\n")
147
+
148
+ print("\n")
149
+
150
+ if self.FC_COUNT == -1 or type(iter) is str:
151
+ if self.hessian_flag:
152
+ self.exact_hessian(element_list, input_data_for_display, wfn)
153
+
154
+ elif iter % self.FC_COUNT == 0 or self.hessian_flag:
155
+ self.exact_hessian(element_list, input_data_for_display, wfn)
156
+
157
+ except Exception as error:
158
+ print(error)
159
+ print("This molecule could not be optimized.")
160
+ print("Input file: ",file_list,"\n")
161
+ finish_frag = True
162
+ return np.array([0]), np.array([0]), input_data_for_display, finish_frag
163
+
164
+ psi4.core.clean()
165
+ self.energy = e
166
+ self.gradient = g
167
+ if geom_num_list is None:
168
+ self.coordinate = input_data_for_display
169
+ else:
170
+ self.coordinate = geom_num_list / psi4.constants.bohr2angstroms
171
+ return e, g, self.coordinate, finish_frag
172
+
173
+
174
+ return e, g, input_data_for_display, finish_frag
175
+
176
+ def exact_hessian(self, element_list, input_data_for_display, wfn):
177
+ """exact hessian"""
178
+ _, wfn = psi4.frequencies(self.FUNCTIONAL, return_wfn=True, ref_gradient=wfn.gradient())
179
+ exact_hess = np.array(wfn.hessian())
180
+
181
+ freqs = np.array(wfn.frequencies())
182
+
183
+ print("frequencies: \n",freqs)
184
+ #eigenvalues, _ = np.linalg.eigh(exact_hess)
185
+ #print("=== hessian (before add bias potential) ===")
186
+ #print("eigenvalues: ", eigenvalues)
187
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, input_data_for_display, display_eigval=False)
188
+ self.Model_hess = exact_hess
189
+
190
+
191
+
192
+ class CalculationEngine(ABC):
193
+ """Base class for calculation engines"""
194
+
195
+ @abstractmethod
196
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
197
+ """Calculate energy and gradients"""
198
+ pass
199
+
200
+ def _get_file_list(self, file_directory):
201
+ """Get list of input files"""
202
+ return sum([sorted(glob.glob(os.path.join(file_directory, f"*_" + "[0-9]" * i + ".xyz")))
203
+ for i in range(1, 7)], [])
204
+
205
+ def _process_visualization(self, energy_list, gradient_list, num_list, optimize_num, config):
206
+ """Process common visualization tasks"""
207
+ try:
208
+ if config.save_pict:
209
+ visualizer = NEBVisualizer(config)
210
+ tmp_ene_list = np.array(energy_list, dtype="float64") * config.hartree2kcalmol
211
+ visualizer.plot_energy(num_list, tmp_ene_list - tmp_ene_list[0], optimize_num)
212
+ print("energy graph plotted.")
213
+
214
+ gradient_norm_list = [np.sqrt(np.linalg.norm(g)**2/(len(g)*3)) for g in gradient_list]
215
+ visualizer.plot_gradient(num_list, gradient_norm_list, optimize_num)
216
+ print("gradient graph plotted.")
217
+ except Exception as e:
218
+ print(f"Visualization error: {e}")
219
+
220
+
221
+ class Psi4Engine(CalculationEngine):
222
+ """Psi4 calculation engine"""
223
+
224
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
225
+ if psi4 is None:
226
+ raise ImportError("Psi4 is not available")
227
+
228
+ psi4.core.clean()
229
+ gradient_list = []
230
+ gradient_norm_list = []
231
+ energy_list = []
232
+ geometry_num_list = []
233
+ num_list = []
234
+ delete_pre_total_velocity = []
235
+
236
+ os.makedirs(file_directory, exist_ok=True)
237
+ file_list = self._get_file_list(file_directory)
238
+
239
+ hess_count = 0
240
+
241
+ for num, input_file in enumerate(file_list):
242
+ try:
243
+ print(input_file)
244
+
245
+ logfile = file_directory + "/" + config.init_input + '_' + str(num) + '.log'
246
+ psi4.set_output_file(logfile)
247
+ psi4.set_num_threads(nthread=config.N_THREAD)
248
+ psi4.set_memory(config.SET_MEMORY)
249
+ self._set_psi4_dft_grid(config)
250
+
251
+ if config.unrestrict:
252
+ psi4.set_options({'reference': 'uks'})
253
+
254
+ geometry_list, element_list, electric_charge_and_multiplicity = xyz2list(input_file, None)
255
+
256
+ input_data = str(electric_charge_and_multiplicity[0]) + " " + str(electric_charge_and_multiplicity[1]) + "\n"
257
+ for j in range(len(geometry_list)):
258
+ input_data += element_list[j] + " " + geometry_list[j][0] + " " + geometry_list[j][1] + " " + geometry_list[j][2] + "\n"
259
+
260
+ input_data = psi4.geometry(input_data)
261
+ input_data_for_display = np.array(input_data.geometry(), dtype="float64")
262
+
263
+ g, wfn = psi4.gradient(config.basic_set_and_function, molecule=input_data, return_wfn=True)
264
+ g = np.array(g, dtype="float64")
265
+ e = float(wfn.energy())
266
+
267
+ print('energy:' + str(e) + " a.u.")
268
+
269
+ gradient_list.append(g)
270
+ gradient_norm_list.append(np.sqrt(np.linalg.norm(g)**2/(len(g)*3))) # RMS
271
+ energy_list.append(e)
272
+ num_list.append(num)
273
+ geometry_num_list.append(input_data_for_display)
274
+
275
+ if config.FC_COUNT == -1 or type(optimize_num) is str:
276
+ pass
277
+ elif optimize_num % config.FC_COUNT == 0:
278
+ """exact hessian"""
279
+ _, wfn = psi4.frequencies(config.basic_set_and_function, return_wfn=True, ref_gradient=wfn.gradient())
280
+ exact_hess = np.array(wfn.hessian())
281
+ freqs = np.array(wfn.frequencies())
282
+ print("frequencies: \n", freqs)
283
+ eigenvalues, _ = np.linalg.eigh(exact_hess)
284
+ print("=== hessian (before add bias potential) ===")
285
+ print("eigenvalues: ", eigenvalues)
286
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, input_data_for_display)
287
+ np.save(config.NEB_FOLDER_DIRECTORY + "tmp_hessian_" + str(hess_count) + ".npy", exact_hess)
288
+ with open(config.NEB_FOLDER_DIRECTORY + "tmp_hessian_" + str(hess_count) + ".csv", "a") as f:
289
+ f.write("frequency," + ",".join(map(str, freqs)) + "\n")
290
+
291
+ hess_count += 1
292
+
293
+ except Exception as error:
294
+ print(error)
295
+ print("This molecule could not be optimized.")
296
+ if optimize_num != 0:
297
+ delete_pre_total_velocity.append(num)
298
+
299
+ psi4.core.clean()
300
+
301
+ print("data sampling was completed...")
302
+
303
+ self._process_visualization(energy_list, gradient_list, num_list, optimize_num, config)
304
+
305
+ if optimize_num != 0 and len(pre_total_velocity) != 0:
306
+ pre_total_velocity = pre_total_velocity.tolist()
307
+ for i in sorted(delete_pre_total_velocity, reverse=True):
308
+ pre_total_velocity.pop(i)
309
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
310
+
311
+ return (np.array(energy_list, dtype="float64"),
312
+ np.array(gradient_list, dtype="float64"),
313
+ np.array(geometry_num_list, dtype="float64"),
314
+ pre_total_velocity)
315
+
316
+ def _set_psi4_dft_grid(self, config):
317
+ """Set DFT grid for Psi4"""
318
+ if config.dft_grid == 0 or config.dft_grid == 1:
319
+ psi4.set_options({'DFT_RADIAL_POINTS': 50, 'DFT_SPHERICAL_POINTS': 194})
320
+ print("DFT Grid (50, 194): SG1")
321
+ elif config.dft_grid == 2 or config.dft_grid == 3:
322
+ psi4.set_options({'DFT_RADIAL_POINTS': 75, 'DFT_SPHERICAL_POINTS': 302})
323
+ print("DFT Grid (70, 302): Default")
324
+ elif config.dft_grid == 4 or config.dft_grid == 5:
325
+ psi4.set_options({'DFT_RADIAL_POINTS': 99, 'DFT_SPHERICAL_POINTS': 590})
326
+ print("DFT Grid (99, 590): Fine")
327
+ elif config.dft_grid == 6 or config.dft_grid == 7:
328
+ psi4.set_options({'DFT_RADIAL_POINTS': 150, 'DFT_SPHERICAL_POINTS': 770})
329
+ print("DFT Grid (150, 770): UltraFine")
330
+ elif config.dft_grid == 8 or config.dft_grid == 9:
331
+ psi4.set_options({'DFT_RADIAL_POINTS': 250, 'DFT_SPHERICAL_POINTS': 974})
332
+ print("DFT Grid (250, 974): SuperFine")
333
+ else:
334
+ raise ValueError("Invalid dft grid setting.")