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,119 @@
1
+ import torch
2
+
3
+
4
+ class BondCalculator:
5
+ def __init__(self, element_list, params):
6
+ self.element_list = element_list
7
+
8
+ #self.k_bond_list = []
9
+ self.r0_bond_list = []
10
+ self.paulingEN_list = []
11
+
12
+ for element in element_list:
13
+ #self.k_bond_list.append(params.k_bond[element])
14
+ self.r0_bond_list.append(params.eeq_covalent_radii[element])
15
+ self.paulingEN_list.append(params.paulingEN[element])
16
+
17
+ #self.k_bond_list = torch.tensor(self.k_bond_list, dtype=torch.float64)
18
+ self.r0_bond_list = torch.tensor(self.r0_bond_list, dtype=torch.float64)
19
+ self.paulingEN_list = torch.tensor(self.paulingEN_list, dtype=torch.float64)
20
+
21
+ self.en_polynominal_param = params.en_polynominal_param
22
+ self._calc_corrected_r0_and_en_diff2_matrix()
23
+ self.eta = params.eta_bond
24
+ self.k_en = params.k_en_bond
25
+
26
+ return
27
+
28
+ def get_en_poly_index(self, atomic_number):
29
+ if not isinstance(atomic_number, int) or atomic_number <= 0:
30
+ raise ValueError("Atomic number must be a positive integer.")
31
+ if atomic_number <= 2: # Z = 1-2 (H, He)
32
+ return 0
33
+ elif atomic_number <= 10: # Z = 3-10 (Li-Ne)
34
+ return 1
35
+ elif atomic_number <= 18: # Z = 11-18 (Na-Ar)
36
+ return 2
37
+ elif atomic_number <= 36: # Z = 19-36 (K-Kr)
38
+ return 3
39
+ elif atomic_number <= 54: # Z = 37-54 (Rb-Xe)
40
+ return 4
41
+ else: # Z = 55- (Cs-)
42
+ return 5
43
+
44
+ def _calc_corrected_r0_and_en_diff2_matrix(self):
45
+ en_diff2_matrix = torch.zeros((len(self.element_list), len(self.element_list)), dtype=torch.float64)
46
+ corrected_r0_matrix = torch.zeros((len(self.element_list), len(self.element_list)), dtype=torch.float64)
47
+ for i in range(len(self.element_list)):
48
+ for j in range(len(self.element_list)):
49
+ r0_ij = self.r0_bond_list[i] + self.r0_bond_list[j]
50
+
51
+ c_i = self.en_polynominal_param[self.get_en_poly_index(int(self.element_list[i])+1)]
52
+ c_j = self.en_polynominal_param[self.get_en_poly_index(int(self.element_list[j])+1)]
53
+ c = 0.5 * (c_i + c_j)
54
+ c_1 = c[0]
55
+ c_2 = c[1]
56
+
57
+ en_diff = torch.abs(self.paulingEN_list[i] - self.paulingEN_list[j])
58
+ corrected_r0_matrix[i, j] = r0_ij * (1.0 - c_1 * en_diff + c_2 * (en_diff ** 2))
59
+ en_diff2_matrix[i, j] = en_diff ** 2
60
+
61
+ self.corrected_r0_matrix = corrected_r0_matrix
62
+ self.en_diff2_matrix = en_diff2_matrix
63
+ return corrected_r0_matrix, en_diff2_matrix
64
+
65
+ def calculation(self, xyz): # xyz: (N, 3) torch tensor
66
+ N = xyz.shape[0]
67
+ diff = xyz.unsqueeze(1) - xyz.unsqueeze(0)
68
+ # r is the (N, N) matrix of pairwise distances. Diagonal is 0.0
69
+ r = torch.linalg.norm(diff, dim=-1)
70
+
71
+ k_bond_ij = 1.0 #torch.sqrt(self.k_bond_list.unsqueeze(1) * self.k_bond_list.unsqueeze(0))
72
+ r0_ij = self.corrected_r0_matrix
73
+ en_diff2_ij = self.en_diff2_matrix
74
+
75
+ # --- Modifications ---
76
+
77
+ # 1. Calculate the cutoff matrix for bond determination
78
+ cutoff_matrix = 1.25 * r0_ij
79
+
80
+ # 2. Create a mask for pairs where the current distance r is <= the cutoff
81
+ mask = (r <= cutoff_matrix)
82
+
83
+ # 3. Always set the diagonal (i=i) to False to exclude self-interaction
84
+ mask.fill_diagonal_(False)
85
+
86
+ # 4. Calculate the energy term for all pairs
87
+ energy_term = -1.0 * k_bond_ij * torch.exp(self.eta * (1.0 * self.k_en * en_diff2_ij) * (r - r0_ij) ** 2.0)
88
+
89
+ # 5. Use torch.where to select the energy term only for masked pairs.
90
+ # Set 0.0 for False pairs (non-bonded pairs and the diagonal).
91
+ bond_energy_matrix = torch.where(mask, energy_term, 0.0)
92
+
93
+ # The previous .fill_diagonal_(0.0) is no longer needed.
94
+ # --- End of modifications ---
95
+
96
+ energy = torch.sum(bond_energy_matrix) / 2.0
97
+ return energy # shape: scalar
98
+
99
+
100
+ def energy(self, xyz):
101
+ xyz = torch.tensor(xyz, dtype=torch.float64)
102
+ energy = self.calculation(xyz)
103
+ return energy
104
+
105
+ def gradient(self, xyz):
106
+ xyz = torch.tensor(xyz, dtype=torch.float64)
107
+ energy = self.calculation(xyz)
108
+ gradient = torch.func.jacrev(self.calculation)(xyz)
109
+ return energy, gradient
110
+
111
+ def hessian(self, xyz):
112
+ xyz = torch.tensor(xyz, dtype=torch.float64)
113
+ energy = self.calculation(xyz)
114
+ hessian = torch.func.hessian(self.calculation)(xyz)
115
+ return energy, hessian
116
+
117
+
118
+
119
+
@@ -0,0 +1,303 @@
1
+ import numpy as np
2
+ import torch
3
+ from multioptpy.SQM.sqm2.sqm2_data import SQM2Parameters
4
+ from multioptpy.SQM.sqm2.sqm2_rep import RepulsionCalculator
5
+ from multioptpy.SQM.sqm2.sqm2_srb import SRBCalculator
6
+ from multioptpy.SQM.sqm2.sqm2_disp import DispersionCalculator
7
+ from multioptpy.SQM.sqm2.sqm2_eeq import IESEnergyCalculator
8
+ from multioptpy.SQM.sqm2.sqm2_qm import EHTCalculator
9
+ from multioptpy.SQM.sqm2.sqm2_basis import BasisSet
10
+ from multioptpy.SQM.sqm2.sqm2_bond import BondCalculator
11
+
12
+ ANG2BOHR = 1.8897261246257704
13
+
14
+ class SQM2Calculator:
15
+ def __init__(self, xyz, element_list, charge, spin):# xyz: (N,3) in Angstrom, element_list: atomic numbers (1-indexed)
16
+ # ref.: https://doi.org/10.26434/chemrxiv.8326202.v1
17
+ sqm_params = SQM2Parameters()
18
+ self.element_list = np.array(element_list, dtype=np.int64) - 1 # 0-indexed
19
+ self.xyz = np.array(xyz, dtype=np.float64)
20
+ self.xyz = self.xyz * ANG2BOHR # Angstrom -> Bohr
21
+ self.charge = charge
22
+ self.spin = spin
23
+
24
+ self.repulsion_calculator = RepulsionCalculator(self.element_list, sqm_params)
25
+ self.srb_calculator = SRBCalculator(self.element_list, sqm_params)
26
+ self.dispersion_calculator = DispersionCalculator(self.element_list, sqm_params)
27
+ self.ies_calculator = IESEnergyCalculator(self.element_list, charge, sqm_params)
28
+ self.basis_set = BasisSet(self.element_list, sqm_params)
29
+ #print(self.basis_set.basis)
30
+ self.eht_calculator = EHTCalculator(self.element_list, charge, spin, sqm_params, self.basis_set)
31
+ self.bond_calculator = BondCalculator(self.element_list, sqm_params)
32
+ self.sqm_params = sqm_params
33
+
34
+ def get_overlap_matrix(self):
35
+ if not self.eht_calculator:
36
+ raise ValueError("EHT calculator is not initialized.")
37
+ return self.eht_calculator.get_overlap_integral_matrix()
38
+
39
+ def get_eht_mo_energy(self):
40
+ if not self.eht_calculator:
41
+ raise ValueError("EHT calculator is not initialized.")
42
+ return self.eht_calculator.get_mo_energy()
43
+
44
+ def get_eht_mo_coeff(self):
45
+ if not self.eht_calculator:
46
+ raise ValueError("EHT calculator is not initialized.")
47
+ return self.eht_calculator.get_mo_coeff()
48
+
49
+ def total_energy(self, xyz): # xyz: ndarray (N,3) in Angstrom
50
+ xyz = xyz * ANG2BOHR # Angstrom -> Bohr
51
+
52
+ repulsion_energy = self.repulsion_calculator.energy(xyz)
53
+ srb_energy = self.srb_calculator.energy(xyz)
54
+ ies_energy = self.ies_calculator.energy(xyz)
55
+
56
+ eeq_charge = self.ies_calculator.eeq_charge(xyz)
57
+ eeq_charge = eeq_charge.detach().numpy()
58
+
59
+ cn = self.ies_calculator.cn(xyz)
60
+ cn = cn.detach().numpy()
61
+ dispersion_energy = self.dispersion_calculator.energy(xyz)
62
+ eht_energy = self.eht_calculator.energy(xyz, eeq_charge, cn)
63
+ #bond_energy = self.bond_calculator.energy(xyz)
64
+ total_energy = repulsion_energy + srb_energy + ies_energy + dispersion_energy + eht_energy
65
+ total_energy = float(total_energy.item())
66
+ print("Total Energy:", total_energy)
67
+
68
+ return total_energy # in Hartree: float
69
+
70
+ def total_gradient(self, xyz): # xyz: ndarray (N,3) in Angstrom
71
+ xyz = xyz * ANG2BOHR # Angstrom -> Bohr
72
+ eeq_charge = self.ies_calculator.eeq_charge(xyz)
73
+ eeq_charge = eeq_charge.detach().numpy()
74
+ _, d_eeq_charge = self.ies_calculator.d_eeq_charge_d_xyz(xyz)
75
+ #print("d_eeq_charge:", d_eeq_charge)
76
+ d_eeq_charge = d_eeq_charge.detach().numpy()
77
+ cn = self.ies_calculator.cn(xyz)
78
+ cn = cn.detach().numpy()
79
+ _, d_cn = self.ies_calculator.d_cn_d_xyz(xyz)
80
+ #print("d_cn:", d_cn)
81
+ d_cn = d_cn.detach().numpy()
82
+ #eht_energy = self.eht_calculator.energy(xyz, eeq_charge, cn)#, eeq_charge, cn, d_eeq_charge, d_cn)
83
+ eht_energy, eht_gradient = self.eht_calculator.gradient(xyz, eeq_charge, cn, d_eeq_charge, d_cn)
84
+ eht_gradient = torch.nan_to_num(eht_gradient, nan=0.0, posinf=0.0, neginf=0.0)
85
+ repulsion_energy, repulsion_gradient = self.repulsion_calculator.gradient(xyz)
86
+ repulsion_gradient = torch.nan_to_num(repulsion_gradient, nan=0.0, posinf=0.0, neginf=0.0)
87
+
88
+ srb_energy, srb_gradient = self.srb_calculator.gradient(xyz)
89
+ srb_gradient = torch.nan_to_num(srb_gradient, nan=0.0, posinf=0.0, neginf=0.0)
90
+ ies_energy, ies_gradient = self.ies_calculator.gradient(xyz)
91
+ ies_gradient = torch.nan_to_num(ies_gradient, nan=0.0, posinf=0.0, neginf=0.0)
92
+ dispersion_energy, dispersion_gradient = self.dispersion_calculator.gradient(xyz)
93
+ dispersion_gradient = torch.nan_to_num(dispersion_gradient, nan=0.0, posinf=0.0, neginf=0.0)
94
+
95
+ total_energy = repulsion_energy + srb_energy + ies_energy + dispersion_energy + eht_energy
96
+ total_gradient = repulsion_gradient + srb_gradient + ies_gradient + dispersion_gradient + eht_gradient
97
+ print("Total gradient norm:", torch.norm(total_gradient).item())
98
+ total_energy = float(total_energy.item())
99
+ total_gradient = total_gradient.detach().numpy()
100
+ return total_energy, total_gradient # gradient: ndarray (N,3) in Bohr
101
+
102
+ def total_hessian(self, xyz): # xyz: ndarray (N,3) in Angstrom
103
+ xyz = xyz * ANG2BOHR # Angstrom -> Bohr
104
+ eeq_charge = self.ies_calculator.eeq_charge(xyz)
105
+ eeq_charge = eeq_charge.detach().numpy()
106
+
107
+ _, d_eeq_charge = self.ies_calculator.d_eeq_charge_d_xyz(xyz)
108
+ _, dd_eeq_charge = self.ies_calculator.d2_eeq_charge_d_xyz2(xyz)
109
+ d_eeq_charge = d_eeq_charge.detach().numpy()
110
+ dd_eeq_charge = dd_eeq_charge.detach().numpy()
111
+ #print("dd_eeq_charge:", dd_eeq_charge)
112
+
113
+
114
+ cn = self.ies_calculator.cn(xyz)
115
+ cn = cn.detach().numpy()
116
+ _, d_cn = self.ies_calculator.d_cn_d_xyz(xyz)
117
+ d_cn = d_cn.detach().numpy()
118
+ _, dd_cn = self.ies_calculator.d2_cn_d_xyz2(xyz)
119
+ dd_cn = dd_cn.detach().numpy()
120
+ #print("dd_cn:", dd_cn)
121
+
122
+
123
+ eht_hessian = self.eht_calculator.hessian(xyz, eeq_charge, cn, d_eeq_charge, dd_eeq_charge, d_cn, dd_cn)
124
+ eht_hessian = torch.nan_to_num(eht_hessian, nan=0.0, posinf=0.0, neginf=0.0)
125
+
126
+ repulsion_energy, repulsion_hessian = self.repulsion_calculator.hessian(xyz)
127
+ repulsion_hessian = torch.nan_to_num(repulsion_hessian, nan=0.0, posinf=0.0, neginf=0.0)
128
+ srb_energy, srb_hessian = self.srb_calculator.hessian(xyz)
129
+ srb_hessian = torch.nan_to_num(srb_hessian, nan=0.0, posinf=0.0, neginf=0.0)
130
+ ies_energy, ies_hessian = self.ies_calculator.hessian(xyz)
131
+ ies_hessian = torch.nan_to_num(ies_hessian, nan=0.0, posinf=0.0, neginf=0.0)
132
+ dispersion_energy, dispersion_hessian = self.dispersion_calculator.hessian(xyz)
133
+ dispersion_hessian = torch.nan_to_num(dispersion_hessian, nan=0.0, posinf=0.0, neginf=0.0)
134
+ #bond_energy, bond_hessian = self.bond_calculator.hessian(xyz)
135
+ #bond_hessian = torch.nan_to_num(bond_hessian, nan=0.0, posinf=0.0, neginf=0.0)
136
+
137
+ total_energy = repulsion_energy + srb_energy + ies_energy + dispersion_energy #+ bond_energy
138
+ total_hessian = eht_hessian + repulsion_hessian + srb_hessian + ies_hessian + dispersion_hessian #+ bond_hessian
139
+
140
+ total_energy = float(total_energy.item())
141
+ total_hessian = total_hessian.detach().numpy()
142
+
143
+ return total_hessian # hessian: ndarray (3N,3N) in Bohr
144
+
145
+
146
+ if __name__ == "__main__":
147
+
148
+ print("\nStarting structural optimization for H2O using steepest descent...\n")
149
+ element_list = np.array([8, 1, 1])# O, H, H
150
+ xyz = np.array([[0.0000, 0.0000, 0.0173],
151
+ [0.0000, 0.7572, -0.4692],
152
+ [0.0000, -0.7572, -0.4692]])#(Angstrom)
153
+ xyz = np.array(xyz)
154
+ charge = 0
155
+ spin = 0
156
+
157
+
158
+ calculator = SQM2Calculator(xyz, element_list, charge, spin)
159
+
160
+ E_total = calculator.total_energy(xyz)
161
+
162
+
163
+
164
+ # Parameters for optimization
165
+ max_iter = 40
166
+ lr = 0.1 # Learning rate (adjusted for Angstrom units; may need tuning)
167
+ threshold = 1e-3 # Convergence threshold for gradient norm
168
+ xyz_ang = xyz
169
+ for iter in range(max_iter):
170
+
171
+ # Get total energy and gradient (gradient is dE/dx where x internal is Bohr)
172
+ total_energy, total_gradient_bohr = calculator.total_gradient(xyz_ang)
173
+
174
+ total_gradient_ang = total_gradient_bohr * ANG2BOHR
175
+
176
+ # Update xyz in Angstrom
177
+ xyz_ang = xyz_ang - lr * total_gradient_ang
178
+
179
+ # Check convergence
180
+ grad_norm = np.linalg.norm(total_gradient_ang)
181
+ print(f"Iteration {iter + 1}: Energy = {total_energy:.6f}, Gradient Norm = {grad_norm:.6f}")
182
+ xyz_ang = xyz_ang
183
+ if grad_norm < threshold:
184
+ print("Optimization converged.")
185
+ break
186
+
187
+ # Display optimized structure
188
+ optimized_xyz = xyz_ang
189
+ elements = ['O', 'H', 'H'] # Corresponding to atomic numbers [8,1,1]
190
+
191
+ print("\nOptimized Structure:")
192
+ for i in range(len(elements)):
193
+ print(f"{elements[i]} {optimized_xyz[i, 0]:.6f} {optimized_xyz[i, 1]:.6f} {optimized_xyz[i, 2]:.6f}")
194
+
195
+ print("\nStarting structural optimization for H3N using steepest descent...\n")
196
+ element_list = np.array([5, 1, 1, 1])# B, H, H, H
197
+ xyz = np.array([[ -3.51351354, 0.43156059, 0.00000000],
198
+ [ -3.18019165, -0.51125250, 0.00000000],
199
+ [ -3.18017444, 0.90296076, 0.81649673],
200
+ [ -3.18017444, 0.90296076, -0.81649673]])#(Angstrom)
201
+ xyz = np.array(xyz)
202
+ charge = 0
203
+ spin = 0
204
+
205
+
206
+ calculator = SQM2Calculator(xyz, element_list, charge, spin)
207
+
208
+ E_total = calculator.total_energy(xyz)
209
+
210
+ #=============================================================================================
211
+
212
+ # Parameters for optimization
213
+ max_iter = 50
214
+ lr = 0.1 # Learning rate (adjusted for Angstrom units; may need tuning)
215
+ threshold = 5e-3 # Convergence threshold for gradient norm
216
+ xyz_ang = xyz
217
+ for iter in range(max_iter):
218
+
219
+ # Get total energy and gradient (gradient is dE/dx where x internal is Bohr)
220
+ total_energy, total_gradient_bohr = calculator.total_gradient(xyz_ang)
221
+
222
+ total_gradient_ang = total_gradient_bohr * ANG2BOHR
223
+
224
+ # Update xyz in Angstrom
225
+ xyz_ang = xyz_ang - lr * total_gradient_ang
226
+
227
+ # Check convergence
228
+ grad_norm = np.linalg.norm(total_gradient_ang)
229
+ print(f"Iteration {iter + 1}: Energy = {total_energy:.6f}, Gradient Norm = {grad_norm:.6f}")
230
+ xyz_ang = xyz_ang
231
+ if grad_norm < threshold:
232
+ print("Optimization converged.")
233
+ break
234
+
235
+ # Display optimized structure
236
+ optimized_xyz = xyz_ang
237
+ elements = ['B', 'H', 'H', 'H'] # Corresponding to atomic numbers [5,1,1,1]
238
+
239
+ print("\nOptimized Structure:")
240
+ for i in range(len(elements)):
241
+ print(f"{elements[i]} {optimized_xyz[i, 0]:.6f} {optimized_xyz[i, 1]:.6f} {optimized_xyz[i, 2]:.6f}")
242
+
243
+
244
+
245
+
246
+ print("\nStarting structural optimization for Pd(PH3) using steepest descent...\n")
247
+
248
+ element_list = np.array([28, 15, 1, 1, 1])
249
+
250
+
251
+ xyz = np.array([[0.0000, 0.0000, 2.3000], # Pd
252
+ [0.0000, 0.0000, 0.0000], # P
253
+ [1.3900, 0.0000, -0.3300], # H1 (P-H 1.42 A, Pd-P-H 100 deg)
254
+ [-0.6950, 1.2038, -0.3300], # H2
255
+ [-0.6950, -1.2038, -0.3300]]) # H3 (Angstrom)
256
+
257
+
258
+ xyz = np.array(xyz)
259
+ charge = 0
260
+ spin = 0
261
+
262
+
263
+ calculator = SQM2Calculator(xyz, element_list, charge, spin)
264
+
265
+ E_total = calculator.total_energy(xyz)
266
+
267
+ # Parameters for optimization
268
+ max_iter = 40
269
+ lr = 0.1 # Learning rate (adjusted for Angstrom units; may need tuning)
270
+ threshold = 1e-2 # Convergence threshold for gradient norm
271
+ xyz_ang = xyz
272
+ for iter in range(max_iter):
273
+
274
+ # Get total energy and gradient (gradient is dE/dx where x internal is Bohr)
275
+ total_energy, total_gradient_bohr = calculator.total_gradient(xyz_ang)
276
+
277
+
278
+ total_gradient_ang = total_gradient_bohr * ANG2BOHR
279
+
280
+ # Update xyz in Angstrom
281
+ xyz_ang = xyz_ang - lr * total_gradient_ang
282
+
283
+ # Check convergence
284
+ grad_norm = np.linalg.norm(total_gradient_ang)
285
+ print(f"Iteration {iter + 1}: Energy = {total_energy:.6f}, Gradient Norm = {grad_norm:.6f}")
286
+ xyz_ang = xyz_ang
287
+ if grad_norm < threshold:
288
+ print("Optimization converged.")
289
+ break
290
+
291
+ # Display optimized structure
292
+ optimized_xyz = xyz_ang
293
+
294
+
295
+ elements = ['Pd', 'P', 'H', 'H', 'H'] # Corresponding to atomic numbers [46,15,1,1,1]
296
+
297
+ print("\nOptimized Structure:")
298
+ for i in range(len(elements)):
299
+ print(f"{elements[i]} {optimized_xyz[i, 0]:.6f} {optimized_xyz[i, 1]:.6f} {optimized_xyz[i, 2]:.6f}")
300
+
301
+
302
+
303
+