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,249 @@
1
+ import numpy as np
2
+ import copy
3
+
4
+
5
+ class FIRE2:
6
+ """Fast Inertial Relaxation Engine 2.0 (FIRE2.0) Optimization Algorithm.
7
+
8
+ Implementation of the FIRE2.0 algorithm as described in:
9
+ J. Guénolé, W.G. Nöhring, A. Vaid, F. Houllé, Z. Xie, A. Prakash, E. Bitzek,
10
+ Assessment and optimization of the fast inertial relaxation engine (fire)
11
+ for energy minimization in atomistic simulations and its implementation in lammps,
12
+ Comput. Mater. Sci. 175 (2020) 109584.
13
+ https://doi.org/10.1016/j.commatsci.2020.109584.
14
+
15
+ This implementation uses the Euler semi-implicit integrator.
16
+ """
17
+
18
+ def __init__(self, **config):
19
+ """Initialize FIRE2.0 optimizer with configuration parameters.
20
+
21
+ Parameters
22
+ ----------
23
+ N_min : int, optional
24
+ Minimum steps before time step increase, default 5
25
+ f_inc : float, optional
26
+ Factor to increase time step, default 1.10
27
+ f_alpha : float, optional
28
+ Factor to decrease alpha, default 0.99
29
+ f_dec : float, optional
30
+ Factor to decrease time step, default 0.50
31
+ dt_max : float, optional
32
+ Maximum time step, default 1.0
33
+ dt_min : float, optional
34
+ Minimum time step, default 0.01
35
+ alpha_start : float, optional
36
+ Initial mixing parameter, default 0.25
37
+ maxstep : float, optional
38
+ Maximum step size per coordinate, default 0.2
39
+ halfstepback : bool, optional
40
+ Whether to perform half step back when power becomes negative, default True
41
+ display_flag : bool, optional
42
+ Print optimization information, default True
43
+ max_vdotf_negatif : int, optional
44
+ Maximum number of consecutive negative power steps before stopping, default 0 (disabled)
45
+ """
46
+ # Default parameters (based on the FIRE2.0 paper)
47
+ self.N_min = 5
48
+ self.f_inc = 1.10
49
+ self.f_alpha = 0.99
50
+ self.f_dec = 0.50
51
+ self.dt_max = 1.0
52
+ self.dt_min = 0.01
53
+ self.alpha_start = 0.25
54
+ self.maxstep = 0.2
55
+ self.halfstepback = True
56
+ self.display_flag = True
57
+ self.max_vdotf_negatif = 0 # Default: disabled
58
+
59
+ # Override defaults with user config
60
+ for key, value in config.items():
61
+ setattr(self, key, value)
62
+
63
+ # Internal state variables
64
+ self.iteration = 1
65
+ self.Initialization = True
66
+ self.hessian = None
67
+ self.bias_hessian = None
68
+ self.vdotf_negatif = 0
69
+ self.last_positions = None
70
+ self.last_energy = None
71
+
72
+ def run(self, geom_num_list, B_g, pre_B_g=[], pre_geom=[], B_e=0.0, pre_B_e=0.0,
73
+ pre_move_vector=[], initial_geom_num_list=[], g=[], pre_g=[]):
74
+ """Run one step of the FIRE2.0 optimization algorithm.
75
+
76
+ Parameters
77
+ ----------
78
+ geom_num_list : numpy.ndarray
79
+ Current geometry/coordinates
80
+ B_g : numpy.ndarray
81
+ Current gradient/forces
82
+ pre_B_g : numpy.ndarray, optional
83
+ Previous gradient
84
+ pre_geom : numpy.ndarray, optional
85
+ Previous geometry
86
+ B_e : float, optional
87
+ Current energy
88
+ pre_B_e : float, optional
89
+ Previous energy
90
+ pre_move_vector : numpy.ndarray, optional
91
+ Previous move vector
92
+ initial_geom_num_list : numpy.ndarray, optional
93
+ Initial geometry
94
+ g : numpy.ndarray, optional
95
+ Alternative gradient representation
96
+ pre_g : numpy.ndarray, optional
97
+ Alternative previous gradient representation
98
+
99
+ Returns
100
+ -------
101
+ numpy.ndarray
102
+ Move vector to update positions
103
+ """
104
+ # Initialize on first call
105
+ if self.Initialization:
106
+ self.dt = 0.1
107
+ self.alpha = self.alpha_start
108
+ self.Nsteps = 0
109
+ self.velocity = np.zeros_like(geom_num_list)
110
+ self.last_positions = geom_num_list.copy()
111
+ self.last_energy = B_e
112
+ self.Initialization = False
113
+
114
+ # Save the current positions and energy for potential rollback
115
+ current_positions = geom_num_list.copy()
116
+ current_energy = B_e
117
+
118
+ # Calculate power (P = F·V)
119
+ power = np.dot(self.velocity.flatten(), B_g.flatten())
120
+
121
+ if power > 0.0:
122
+ # Moving downhill
123
+ # Increment Nsteps and check if we should increase dt and decrease alpha
124
+ self.Nsteps += 1
125
+ if self.Nsteps > self.N_min:
126
+ self.dt = min(self.dt * self.f_inc, self.dt_max)
127
+ self.alpha *= self.f_alpha
128
+ else:
129
+ # Moving uphill or starting
130
+ # Reset Nsteps, decrease dt, and reset alpha
131
+ self.Nsteps = 0
132
+ self.dt = max(self.dt * self.f_dec, self.dt_min)
133
+ self.alpha = self.alpha_start
134
+
135
+ # Count consecutive negative power steps
136
+ self.vdotf_negatif += 1
137
+ if self.max_vdotf_negatif > 0 and self.vdotf_negatif > self.max_vdotf_negatif:
138
+ if self.display_flag:
139
+ print("Maximum number of consecutive negative power steps reached")
140
+ return np.zeros_like(geom_num_list)
141
+
142
+ # Apply half step back correction if enabled
143
+ if self.halfstepback and power < 0.0:
144
+ # Back up half a step
145
+ half_step_correction = -0.5 * self.dt * self.velocity
146
+ geom_num_list += half_step_correction
147
+
148
+ if self.display_flag:
149
+ print("Applying half step back correction")
150
+
151
+ # Reset velocity
152
+ self.velocity = np.zeros_like(geom_num_list)
153
+
154
+ # Update velocity using Euler semi-implicit integration
155
+ # First update velocity with current forces (v += dt * F)
156
+ self.velocity += self.dt * B_g
157
+
158
+ # Only apply FIRE mixing if power was positive
159
+ if power > 0.0:
160
+ # Calculate the velocity magnitude and force magnitude
161
+ v_norm = np.linalg.norm(self.velocity)
162
+ f_norm = np.linalg.norm(B_g)
163
+
164
+ if v_norm > 1e-10 and f_norm > 1e-10:
165
+ # Apply FIRE mixing: v = (1-α)v + α|v|F̂
166
+ # Where F̂ is the normalized force vector
167
+ scaled_velocity = (1.0 - self.alpha) * self.velocity
168
+ scaled_force = self.alpha * (v_norm / f_norm) * B_g
169
+ self.velocity = scaled_velocity + scaled_force
170
+
171
+ # Calculate the move vector (dr = dt * v)
172
+ move_vector = self.dt * self.velocity
173
+
174
+ # Check if the maximum step size is exceeded
175
+ move_norm = np.linalg.norm(move_vector)
176
+ if move_norm > self.maxstep:
177
+ move_vector *= (self.maxstep / move_norm)
178
+
179
+ if self.display_flag:
180
+ print("FIRE2.0")
181
+ print(f"Iteration: {self.iteration}")
182
+ print(f"dt: {self.dt:.6f}, alpha: {self.alpha:.6f}, Nsteps: {self.Nsteps}")
183
+ print(f"Power (v·F): {power:.6e}")
184
+ print(f"Max velocity: {np.max(np.abs(self.velocity)):.6e}")
185
+ print(f"Max force: {np.max(np.abs(B_g)):.6e}")
186
+ print(f"Max step: {np.max(np.abs(move_vector)):.6e}")
187
+
188
+ # Update state for next iteration
189
+ self.last_positions = current_positions
190
+ self.last_energy = current_energy
191
+ self.iteration += 1
192
+
193
+ # Reset negative power counter if power is positive
194
+ if power > 0.0:
195
+ self.vdotf_negatif = 0
196
+
197
+ return move_vector
198
+
199
+ def set_hessian(self, hessian):
200
+ """Set Hessian matrix for the optimizer.
201
+
202
+ Parameters
203
+ ----------
204
+ hessian : numpy.ndarray
205
+ Hessian matrix
206
+ """
207
+ self.hessian = hessian
208
+
209
+ def set_bias_hessian(self, bias_hessian):
210
+ """Set bias Hessian matrix for the optimizer.
211
+
212
+ Parameters
213
+ ----------
214
+ bias_hessian : numpy.ndarray
215
+ Bias Hessian matrix
216
+ """
217
+ self.bias_hessian = bias_hessian
218
+
219
+ def get_hessian(self):
220
+ """Get Hessian matrix.
221
+
222
+ Returns
223
+ -------
224
+ numpy.ndarray
225
+ Hessian matrix
226
+ """
227
+ return self.hessian
228
+
229
+ def get_bias_hessian(self):
230
+ """Get bias Hessian matrix.
231
+
232
+ Returns
233
+ -------
234
+ numpy.ndarray
235
+ Bias Hessian matrix
236
+ """
237
+ return self.bias_hessian
238
+
239
+ def reset(self):
240
+ """Reset the optimizer to initial state."""
241
+ self.dt = 0.1
242
+ self.alpha = self.alpha_start
243
+ self.Nsteps = 0
244
+ self.velocity = None
245
+ self.Initialization = True
246
+ self.iteration = 1
247
+ self.vdotf_negatif = 0
248
+ self.last_positions = None
249
+ self.last_energy = None
@@ -0,0 +1,92 @@
1
+ import numpy as np
2
+ from abc import ABC, abstractmethod
3
+ from multioptpy.Optimizer import trust_radius_neb
4
+
5
+ class OptimizationAlgorithm(ABC):
6
+ """Base class for optimization algorithms"""
7
+
8
+ @abstractmethod
9
+ def optimize(self, geometry_num_list, total_force_list, **kwargs):
10
+ """Execute optimization step"""
11
+ pass
12
+
13
+
14
+ class FIREOptimizer(OptimizationAlgorithm):
15
+ """FIRE method optimizer"""
16
+
17
+ def __init__(self, config):
18
+ self.config = config
19
+ # FIRE method parameters
20
+ self.dt = config.dt
21
+ self.a = config.a
22
+ self.n_reset = config.n_reset
23
+ self.FIRE_N_accelerate = config.FIRE_N_accelerate
24
+ self.FIRE_f_inc = config.FIRE_f_inc
25
+ self.FIRE_f_accelerate = config.FIRE_f_accelerate
26
+ self.FIRE_f_decelerate = config.FIRE_f_decelerate
27
+ self.FIRE_a_start = config.FIRE_a_start
28
+ self.FIRE_dt_max = config.FIRE_dt_max
29
+
30
+ # Initialize NEB trust radius
31
+ self.NEB_TR = trust_radius_neb.TR_NEB(
32
+ NEB_FOLDER_DIRECTORY=config.NEB_FOLDER_DIRECTORY,
33
+ fix_init_edge=config.fix_init_edge,
34
+ fix_end_edge=config.fix_end_edge,
35
+ apply_convergence_criteria=config.apply_convergence_criteria
36
+ )
37
+
38
+ def optimize(self, geometry_num_list, total_force_list, pre_total_velocity,
39
+ optimize_num, total_velocity, cos_list, biased_energy_list,
40
+ pre_biased_energy_list, pre_geom):
41
+ """FIRE method optimization"""
42
+ velocity_neb = []
43
+
44
+ for num in range(len(total_velocity)):
45
+ part_velocity_neb = []
46
+ for i in range(len(total_force_list[0])):
47
+ force_norm = np.linalg.norm(total_force_list[num][i])
48
+ velocity_norm = np.linalg.norm(total_velocity[num][i])
49
+ if force_norm > 1e-10: # avoid division by zero
50
+ part_velocity_neb.append(
51
+ (1.0 - self.a) * total_velocity[num][i] +
52
+ self.a * (velocity_norm / force_norm) * total_force_list[num][i]
53
+ )
54
+ else:
55
+ part_velocity_neb.append(total_velocity[num][i])
56
+ velocity_neb.append(part_velocity_neb)
57
+
58
+ velocity_neb = np.array(velocity_neb)
59
+
60
+ np_dot_param = 0.0
61
+ if optimize_num != 0 and len(pre_total_velocity) > 1:
62
+ np_dot_param = np.sum([np.dot(pre_total_velocity[num_1][num_2], total_force_num.T)
63
+ for num_1, total_force in enumerate(total_force_list)
64
+ for num_2, total_force_num in enumerate(total_force)])
65
+ print(np_dot_param)
66
+
67
+ if optimize_num > 0 and np_dot_param > 0 and len(pre_total_velocity) > 1:
68
+ if self.n_reset > self.FIRE_N_accelerate:
69
+ self.dt = min(self.dt * self.FIRE_f_inc, self.FIRE_dt_max)
70
+ self.a *= self.FIRE_f_inc
71
+ self.n_reset += 1
72
+ else:
73
+ velocity_neb *= 0
74
+ self.a = self.FIRE_a_start
75
+ self.dt *= self.FIRE_f_decelerate
76
+ self.n_reset = 0
77
+
78
+ total_velocity = velocity_neb + self.dt * total_force_list
79
+
80
+ if optimize_num != 0 and len(pre_total_velocity) > 1:
81
+ total_delta = self.dt * (total_velocity + pre_total_velocity)
82
+ else:
83
+ total_delta = self.dt * total_velocity
84
+
85
+ # Calculate the movement vector using TR_calc
86
+ move_vector = self.NEB_TR.TR_calc(geometry_num_list, total_force_list, total_delta,
87
+ biased_energy_list, pre_biased_energy_list, pre_geom)
88
+
89
+ # Update geometry using the move vector
90
+ new_geometry = (geometry_num_list + move_vector) * self.config.bohr2angstroms
91
+
92
+ return new_geometry