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,282 @@
1
+ import numpy as np
2
+ from numpy.linalg import norm
3
+
4
+ from multioptpy.Parameters.parameter import UnitValueLib
5
+
6
+ class AFIRE_NEB:
7
+ """Adaptive Fast Inertial Relaxation Engine for Nudged Elastic Band calculations.
8
+
9
+ This implementation extends the standard FIRE algorithm with adaptive parameters
10
+ for each image in the NEB chain, improving convergence for reaction paths that have
11
+ regions with different curvatures and energy barriers.
12
+
13
+ Reference:
14
+ E. Bitzek et al., Phys. Rev. Lett. 97, 170201 (2006)
15
+ with adaptive extensions for NEB.
16
+ """
17
+
18
+ def __init__(self, **config):
19
+ # Configuration parameters
20
+ self.config = config
21
+
22
+ # Initialize flags
23
+ self.Initialization = True
24
+ self.iter = 0
25
+
26
+ # FIRE parameters
27
+ self.a_start = config.get("a_start", 0.1)
28
+ self.f_inc = config.get("f_inc", 1.1)
29
+ self.f_dec = config.get("f_dec", 0.5)
30
+ self.f_a = config.get("f_a", 0.99)
31
+ self.dt_start = config.get("dt_start", 0.1)
32
+ self.dt_max = config.get("dt_max", 1.0)
33
+ self.n_min = config.get("n_min", 5)
34
+
35
+ # Per-image adaptive parameters
36
+ self.a_images = None # α values for each image
37
+ self.dt_images = None # Time steps for each image
38
+ self.n_pos_images = None # Consecutive positive dot products counter for each image
39
+
40
+ # Storage for velocities and previous forces
41
+ self.velocities = None
42
+ self.prev_forces = None
43
+ self.prev_positions = None
44
+
45
+ # Maximum step size constraint
46
+ self.maxstep = config.get("maxstep", 0.1)
47
+
48
+ # Unit conversion
49
+ self.bohr2angstroms = UnitValueLib().bohr2angstroms
50
+ if 'bohr2angstroms' in config:
51
+ self.bohr2angstroms = config['bohr2angstroms']
52
+
53
+ # For compatibility with other NEB implementations
54
+ self.TR_NEB = config.get("TR_NEB", None)
55
+
56
+ print(f"Initialized Adaptive FIRE optimizer for NEB with "
57
+ f"a_start={self.a_start}, dt_start={self.dt_start}, maxstep={self.maxstep}")
58
+
59
+ def initialize_data(self, num_images):
60
+ """Initialize data structures for the optimization.
61
+
62
+ Parameters:
63
+ ----------
64
+ num_images : int
65
+ Number of images in the NEB calculation
66
+ """
67
+ # Initialize per-image parameters
68
+ self.a_images = np.ones(num_images) * self.a_start
69
+ self.dt_images = np.ones(num_images) * self.dt_start
70
+ self.n_pos_images = np.zeros(num_images, dtype=int)
71
+
72
+ # Initialize velocities to zero with correct shapes
73
+ self.velocities = [np.zeros_like(img) for img in range(num_images)]
74
+
75
+ # Initialize storage for previous values
76
+ self.prev_forces = [None] * num_images
77
+ self.prev_positions = [None] * num_images
78
+
79
+ print(f"Initialized AFIRE parameters for {num_images} images")
80
+
81
+ def update_velocities_and_positions(self, positions, forces, dt):
82
+ """Update velocities and positions using the FIRE algorithm for multiple images.
83
+
84
+ Parameters:
85
+ ----------
86
+ positions : list of ndarray
87
+ Current positions for all images
88
+ forces : list of ndarray
89
+ Current forces for all images
90
+ dt : ndarray
91
+ Time steps for each image
92
+
93
+ Returns:
94
+ -------
95
+ tuple
96
+ (new_velocities, steps) - Updated velocities and position steps for all images
97
+ """
98
+ new_velocities = []
99
+ steps = []
100
+
101
+ # Process each image independently
102
+ for i in range(len(positions)):
103
+ # Get current force and position
104
+ force = forces[i]
105
+ position = positions[i]
106
+
107
+ # Initialize velocity if needed
108
+ if self.velocities[i] is None or not isinstance(self.velocities[i], np.ndarray):
109
+ self.velocities[i] = np.zeros_like(position)
110
+
111
+ velocity = self.velocities[i]
112
+
113
+ # Ensure velocity has the same shape as force
114
+ if velocity.shape != force.shape:
115
+ velocity = np.zeros_like(force)
116
+ print(f"Warning: Resetting velocity for image {i} due to shape mismatch")
117
+
118
+ # Calculate power (P = F·v)
119
+ power = np.dot(force.flatten(), velocity.flatten())
120
+
121
+ # Calculate velocity magnitude and force magnitude
122
+ v_norm = norm(velocity.flatten())
123
+ f_norm = norm(force.flatten())
124
+
125
+ # Update velocity using FIRE algorithm
126
+ if f_norm > 0 and v_norm > 0:
127
+ # Calculate normalized force and velocity vectors
128
+ f_hat = force.flatten() / f_norm
129
+ v_hat = velocity.flatten() / v_norm
130
+
131
+ # Mix velocity and force direction according to α
132
+ mixed_v = (1.0 - self.a_images[i]) * velocity + self.a_images[i] * v_norm * f_hat.reshape(velocity.shape)
133
+ else:
134
+ mixed_v = velocity.copy()
135
+
136
+ # Perform velocity Verlet integration
137
+ new_v = mixed_v + 0.5 * dt[i] * force
138
+
139
+ # Calculate step
140
+ step = dt[i] * new_v
141
+
142
+ # Apply max step constraint
143
+ step_length = norm(step.flatten())
144
+ if step_length > self.maxstep:
145
+ step = step * (self.maxstep / step_length)
146
+
147
+ # Store results
148
+ new_velocities.append(new_v)
149
+ steps.append(step)
150
+
151
+ # Update FIRE parameters based on power
152
+ if power > 0: # Moving in right direction
153
+ self.n_pos_images[i] += 1
154
+ if self.n_pos_images[i] > self.n_min:
155
+ # Increase time step and decrease mixing parameter
156
+ self.dt_images[i] = min(self.dt_images[i] * self.f_inc, self.dt_max)
157
+ self.a_images[i] *= self.f_a
158
+ else: # Moving in wrong direction
159
+ # Reset parameters
160
+ self.n_pos_images[i] = 0
161
+ self.dt_images[i] *= self.f_dec
162
+ self.a_images[i] = self.a_start
163
+ # Reset velocity (stop inertial motion against force)
164
+ new_velocities[i] = np.zeros_like(velocity)
165
+
166
+ return new_velocities, steps
167
+
168
+ def determine_step(self, dr):
169
+ """Ensure step sizes are within maxstep.
170
+
171
+ Parameters:
172
+ ----------
173
+ dr : list of ndarray
174
+ Step vectors for all images
175
+
176
+ Returns:
177
+ -------
178
+ list of ndarray
179
+ Step vectors constrained by maxstep if necessary
180
+ """
181
+ if self.maxstep is None:
182
+ return dr
183
+
184
+ # Handle list of step vectors
185
+ result = []
186
+ for step in dr:
187
+ # Calculate step length
188
+ step_reshaped = step.reshape(-1, 3) if step.size % 3 == 0 else step
189
+ steplengths = np.sqrt((step_reshaped**2).sum(axis=1))
190
+ longest_step = np.max(steplengths)
191
+
192
+ # Scale step if necessary
193
+ if longest_step > self.maxstep:
194
+ result.append(step * (self.maxstep / longest_step))
195
+ else:
196
+ result.append(step)
197
+ return result
198
+
199
+ def AFIRE_NEB_calc(self, geometry_num_list, total_force_list, pre_total_velocity,
200
+ optimize_num, total_velocity, cos_list,
201
+ biased_energy_list, pre_biased_energy_list, pre_geom):
202
+ """Calculate step using Adaptive FIRE for NEB.
203
+
204
+ Parameters:
205
+ ----------
206
+ geometry_num_list : ndarray
207
+ Current geometry coordinates for all images
208
+ total_force_list : ndarray
209
+ Current forces for all images
210
+ pre_total_velocity : ndarray
211
+ Previous velocities for all images
212
+ optimize_num : int
213
+ Current optimization iteration number
214
+ total_velocity : ndarray
215
+ Current velocities for all images
216
+ cos_list : ndarray
217
+ Cosines between adjacent images
218
+ biased_energy_list : ndarray
219
+ Current energy for all images
220
+ pre_biased_energy_list : ndarray
221
+ Previous energy for all images
222
+ pre_geom : ndarray
223
+ Previous geometry coordinates for all images
224
+
225
+ Returns:
226
+ -------
227
+ ndarray
228
+ Updated geometry coordinates for all images
229
+ """
230
+ print(f"\n{'='*50}\nNEB-AFIRE Iteration {self.iter}\n{'='*50}")
231
+
232
+ # Get number of images
233
+ num_images = len(geometry_num_list)
234
+
235
+ # Initialize data structures if first iteration
236
+ if self.Initialization:
237
+ self.initialize_data(num_images)
238
+ self.Initialization = False
239
+ print("First iteration - initializing AFIRE")
240
+
241
+ # Initialize velocities from pre_total_velocity if available
242
+ if pre_total_velocity is not None and len(pre_total_velocity) >= num_images:
243
+ self.velocities = [vel.copy() if vel is not None else np.zeros_like(geometry_num_list[i])
244
+ for i, vel in enumerate(pre_total_velocity[:num_images])]
245
+ else:
246
+ self.velocities = [np.zeros_like(geom) for geom in geometry_num_list]
247
+
248
+ # Track adaptive parameters
249
+ min_dt = np.min(self.dt_images)
250
+ max_dt = np.max(self.dt_images)
251
+ avg_a = np.mean(self.a_images)
252
+ print(f"FIRE parameters - dt range: [{min_dt:.4f}, {max_dt:.4f}], avg α: {avg_a:.4f}")
253
+
254
+ # Update velocities and calculate steps
255
+ new_velocities, move_vectors = self.update_velocities_and_positions(
256
+ geometry_num_list, total_force_list, self.dt_images
257
+ )
258
+
259
+ # Apply trust region correction if TR_NEB is provided (for compatibility)
260
+ if self.TR_NEB:
261
+ move_vectors = self.TR_NEB.TR_calc(geometry_num_list, total_force_list, move_vectors,
262
+ biased_energy_list, pre_biased_energy_list, pre_geom)
263
+
264
+ # Store updated velocities
265
+ self.velocities = new_velocities
266
+
267
+ # Update geometry using move vectors
268
+ new_geometry = []
269
+ for i, (geom, move) in enumerate(zip(geometry_num_list, move_vectors)):
270
+ new_geom = geom + move
271
+ new_geometry.append(new_geom)
272
+
273
+ # Store current force and position for next iteration
274
+ self.prev_forces[i] = total_force_list[i].copy()
275
+ self.prev_positions[i] = geometry_num_list[i].copy()
276
+
277
+ # Convert to numpy array and apply unit conversion
278
+ new_geometry = np.array(new_geometry)
279
+ new_geometry *= self.bohr2angstroms
280
+
281
+ self.iter += 1
282
+ return new_geometry