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
File without changes
@@ -0,0 +1,424 @@
1
+ import glob
2
+ import os
3
+ import numpy as np
4
+ import datetime
5
+ from abc import ABC, abstractmethod
6
+
7
+ try:
8
+ from ase import Atoms
9
+ from ase.vibrations import Vibrations
10
+ except ImportError:
11
+ print("ASE is not installed. Please install ASE to use this module.")
12
+
13
+ from multioptpy.Utils.calc_tools import Calculationtools
14
+ from multioptpy.Parameters.parameter import UnitValueLib, number_element
15
+ from multioptpy.fileio import read_software_path, xyz2list
16
+ from multioptpy.Visualization.visualization import NEBVisualizer
17
+ from multioptpy.Calculator.ase_tools.gamess import ASE_GAMESSUS
18
+ from multioptpy.Calculator.ase_tools.nwchem import ASE_NWCHEM
19
+ from multioptpy.Calculator.ase_tools.gaussian import ASE_GAUSSIAN
20
+ from multioptpy.Calculator.ase_tools.orca import ASE_ORCA
21
+ from multioptpy.Calculator.ase_tools.fairchem import ASE_FAIRCHEM
22
+ from multioptpy.Calculator.ase_tools.mace import ASE_MACE
23
+ from multioptpy.Calculator.ase_tools.mopac import ASE_MOPAC
24
+ from multioptpy.Calculator.ase_tools.pygfn0 import ASE_GFN0
25
+
26
+ """
27
+ referrence:
28
+
29
+ @inproceedings{Batatia2022mace,
30
+ title={{MACE}: Higher Order Equivariant Message Passing Neural Networks for Fast and Accurate Force Fields},
31
+ author={Ilyes Batatia and David Peter Kovacs and Gregor N. C. Simm and Christoph Ortner and Gabor Csanyi},
32
+ booktitle={Advances in Neural Information Processing Systems},
33
+ editor={Alice H. Oh and Alekh Agarwal and Danielle Belgrave and Kyunghyun Cho},
34
+ year={2022},
35
+ url={https://openreview.net/forum?id=YPpSngE-ZU}
36
+ }
37
+
38
+ @misc{Batatia2022Design,
39
+ title = {The Design Space of E(3)-Equivariant Atom-Centered Interatomic Potentials},
40
+ author = {Batatia, Ilyes and Batzner, Simon and Kov{\'a}cs, D{\'a}vid P{\'e}ter and Musaelian, Albert and Simm, Gregor N. C. and Drautz, Ralf and Ortner, Christoph and Kozinsky, Boris and Cs{\'a}nyi, G{\'a}bor},
41
+ year = {2022},
42
+ number = {arXiv:2205.06643},
43
+ eprint = {2205.06643},
44
+ eprinttype = {arxiv},
45
+ doi = {10.48550/arXiv.2205.06643},
46
+ archiveprefix = {arXiv}
47
+ }
48
+
49
+ ASE
50
+ Ask Hjorth Larsen, Jens Jørgen Mortensen, Jakob Blomqvist,
51
+ Ivano E. Castelli, Rune Christensen, Marcin Dułak, Jesper Friis,
52
+ Michael N. Groves, Bjørk Hammer, Cory Hargus, Eric D. Hermes,
53
+ Paul C. Jennings, Peter Bjerre Jensen, James Kermode, John R. Kitchin,
54
+ Esben Leonhard Kolsbjerg, Joseph Kubal, Kristen Kaasbjerg,
55
+ Steen Lysgaard, Jón Bergmann Maronsson, Tristan Maxson, Thomas Olsen,
56
+ Lars Pastewka, Andrew Peterson, Carsten Rostgaard, Jakob Schiøtz,
57
+ Ole Schütt, Mikkel Strange, Kristian S. Thygesen, Tejs Vegge,
58
+ Lasse Vilhelmsen, Michael Walter, Zhenhua Zeng, Karsten Wedel Jacobsen
59
+ The Atomic Simulation Environment—A Python library for working with atoms
60
+ J. Phys.: Condens. Matter Vol. 29 273002, 2017
61
+
62
+ """
63
+
64
+ class Calculation:
65
+ def __init__(self, **kwarg):
66
+ UVL = UnitValueLib()
67
+
68
+ self.bohr2angstroms = UVL.bohr2angstroms
69
+ self.hartree2eV = UVL.hartree2eV
70
+
71
+ self.START_FILE = kwarg.get("START_FILE", None)
72
+ self.N_THREAD = kwarg.get("N_THREAD", 1)
73
+ self.SET_MEMORY = kwarg.get("SET_MEMORY", "2GB")
74
+ self.FUNCTIONAL = kwarg.get("FUNCTIONAL", "PBE")
75
+ self.BASIS_SET = kwarg.get("BASIS_SET", "6-31G(d)")
76
+ self.FC_COUNT = kwarg.get("FC_COUNT", 1)
77
+ self.BPA_FOLDER_DIRECTORY = kwarg.get("BPA_FOLDER_DIRECTORY", None)
78
+ self.Model_hess = kwarg.get("Model_hess", None)
79
+ self.unrestrict = kwarg.get("unrestrict", None)
80
+ self.software_type = kwarg.get("software_type", None)
81
+ self.hessian_flag = False
82
+ self.software_path_dict = read_software_path(kwarg.get("software_path_file", "./software_path.conf"))
83
+
84
+ def calc_exact_hess(self, calc_obj, positions, element_list):
85
+
86
+
87
+ timestamp = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S_%f")[:-2]
88
+
89
+ if self.software_type == "gaussian":
90
+ print("Calculating exact Hessian using Gaussian...")
91
+ exact_hess = calc_obj.calc_analytic_hessian() # in hartree/Bohr^2
92
+
93
+ else:
94
+ vib = Vibrations(atoms=calc_obj.atom_obj, delta=0.001, name="z_hess_"+timestamp)
95
+ vib.run()
96
+ result_vib = vib.get_vibrations()
97
+ exact_hess = result_vib.get_hessian_2d() # eV/Ų
98
+ vib.clean()
99
+ exact_hess = exact_hess / self.hartree2eV * (self.bohr2angstroms ** 2)
100
+
101
+ if type(element_list[0]) is str:
102
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, positions)
103
+ else:
104
+ exact_hess = Calculationtools().project_out_hess_tr_and_rot_for_coord(exact_hess, [number_element(elem_num) for elem_num in element_list], positions)
105
+ exact_hess = (exact_hess + exact_hess.T) / 2 # make sure it's symmetric
106
+
107
+ self.Model_hess = exact_hess
108
+
109
+ return exact_hess
110
+
111
+ def single_point(self, file_directory, element_list, iter, electric_charge_and_multiplicity, method, geom_num_list=None):
112
+ """execute extended tight binding method calculation."""
113
+
114
+ finish_frag = False
115
+
116
+ try:
117
+ os.mkdir(file_directory)
118
+ except:
119
+ pass
120
+
121
+ if file_directory is None:
122
+ file_list = ["dummy"]
123
+ else:
124
+ file_list = glob.glob(file_directory+"/*_[0-9].xyz")
125
+
126
+ for num, input_file in enumerate(file_list):
127
+ try:
128
+ if geom_num_list is None:
129
+ positions, _, electric_charge_and_multiplicity = xyz2list(input_file, electric_charge_and_multiplicity)
130
+ else:
131
+ positions = geom_num_list
132
+
133
+ positions = np.array(positions, dtype="float64") # ang.
134
+ atom_obj = Atoms(element_list, positions)
135
+ calc_obj = setup_calculator(
136
+ atom_obj,
137
+ self.software_type,
138
+ electric_charge_and_multiplicity,
139
+ input_file=input_file,
140
+ software_path_dict=self.software_path_dict,
141
+ functional=self.FUNCTIONAL,
142
+ basis_set=self.BASIS_SET,
143
+ set_memory=self.SET_MEMORY,
144
+ )
145
+ calc_obj.run()
146
+ g = -1*calc_obj.atom_obj.get_forces(apply_constraint=False) * self.bohr2angstroms / self.hartree2eV # eV/ang. to a.u.
147
+ e = calc_obj.atom_obj.get_potential_energy(apply_constraint=False) / self.hartree2eV # eV to hartree
148
+
149
+
150
+ if self.FC_COUNT == -1 or type(iter) is str:
151
+ if self.hessian_flag:
152
+ _ = self.calc_exact_hess(calc_obj, positions, element_list)
153
+
154
+
155
+ elif iter % self.FC_COUNT == 0 or self.hessian_flag:
156
+ # exact numerical hessian
157
+ _ = self.calc_exact_hess(calc_obj, positions, element_list)
158
+ except Exception as error:
159
+ print(error)
160
+ print("This molecule could not be optimized.")
161
+ finish_frag = True
162
+ return np.array([0]), np.array([0]), np.array([0]), finish_frag
163
+
164
+ positions /= self.bohr2angstroms
165
+ self.energy = e
166
+ self.gradient = g
167
+ self.coordinate = positions
168
+
169
+ return e, g, positions, finish_frag
170
+
171
+
172
+
173
+ class CalculationEngine(ABC):
174
+ #Base class for calculation engines
175
+
176
+ @abstractmethod
177
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
178
+ #Calculate energy and gradients
179
+ pass
180
+
181
+ def _get_file_list(self, file_directory):
182
+ #Get list of input files
183
+ return sum([sorted(glob.glob(os.path.join(file_directory, f"*_" + "[0-9]" * i + ".xyz")))
184
+ for i in range(1, 7)], [])
185
+
186
+ def _process_visualization(self, energy_list, gradient_list, num_list, optimize_num, config):
187
+ #Process common visualization tasks
188
+ try:
189
+ if config.save_pict:
190
+ visualizer = NEBVisualizer(config)
191
+ tmp_ene_list = np.array(energy_list, dtype="float64") * config.hartree2kcalmol
192
+ visualizer.plot_energy(num_list, tmp_ene_list - tmp_ene_list[0], optimize_num)
193
+ print("energy graph plotted.")
194
+
195
+ gradient_norm_list = [np.sqrt(np.linalg.norm(g)**2/(len(g)*3)) for g in gradient_list]
196
+ visualizer.plot_gradient(num_list, gradient_norm_list, optimize_num)
197
+ print("gradient graph plotted.")
198
+ except Exception as e:
199
+ print(f"Visualization error: {e}")
200
+
201
+
202
+
203
+ class ASEEngine(CalculationEngine):
204
+ """ASE-based calculation engine supporting multiple quantum chemistry software packages.
205
+
206
+ This engine uses the Atomic Simulation Environment (ASE) to interface with various
207
+ quantum chemistry software packages like GAMESSUS, NWChem, Gaussian, ORCA, MACE, and MOPAC.
208
+ """
209
+ def __init__(self, **kwargs):
210
+ UVL = UnitValueLib()
211
+ self.software_path_file = kwargs.get("software_path_file", "./software_path.conf")
212
+ self.software_path_dict = read_software_path(self.software_path_file)
213
+
214
+ self.bohr2angstroms = UVL.bohr2angstroms
215
+ self.hartree2eV = UVL.hartree2eV
216
+
217
+ def calculate(self, file_directory, optimize_num, pre_total_velocity, config):
218
+ """Calculate energy and gradients using ASE and the configured software.
219
+
220
+ Args:
221
+ file_directory (str): Directory containing input files
222
+ optimize_num (int): Optimization iteration number
223
+ pre_total_velocity (np.ndarray): Previous velocities for dynamics
224
+ config (object): Configuration object with calculation parameters
225
+
226
+ Returns:
227
+ tuple: (energy_list, gradient_list, geometry_num_list, pre_total_velocity)
228
+ """
229
+ gradient_list = []
230
+ energy_list = []
231
+ geometry_num_list = []
232
+ gradient_norm_list = []
233
+ delete_pre_total_velocity = []
234
+ num_list = []
235
+
236
+ os.makedirs(file_directory, exist_ok=True)
237
+ file_list = self._get_file_list(file_directory)
238
+
239
+ if not file_list:
240
+ print("No input files found in directory.")
241
+ return (np.array([], dtype="float64"),
242
+ np.array([], dtype="float64"),
243
+ np.array([], dtype="float64"),
244
+ pre_total_velocity)
245
+
246
+ # Get element list from the first file
247
+ geometry_list_tmp, element_list, _ = xyz2list(file_list[0], None)
248
+
249
+ hess_count = 0
250
+ software_type = config.othersoft
251
+
252
+ for num, input_file in enumerate(file_list):
253
+ try:
254
+ print(f"Processing file: {input_file}")
255
+ positions, _, electric_charge_and_multiplicity = xyz2list(input_file, None)
256
+
257
+ positions = np.array(positions, dtype="float64") # in angstroms
258
+ atom_obj = Atoms(element_list, positions)
259
+ calc_obj = setup_calculator(
260
+ atom_obj,
261
+ software_type,
262
+ electric_charge_and_multiplicity,
263
+ input_file=input_file,
264
+ software_path_dict=self.software_path_dict,
265
+ functional=config.FUNCTIONAL,
266
+ basis_set=config.basisset,
267
+ set_memory=config.SET_MEMORY,
268
+ )
269
+ calc_obj.run()
270
+ # Calculate energy and forces
271
+ g = -1 * calc_obj.atom_obj.get_forces(apply_constraint=False) * self.bohr2angstroms / self.hartree2eV # eV/ang. to a.u.
272
+ e = calc_obj.atom_obj.get_potential_energy(apply_constraint=False) / self.hartree2eV # eV to hartree
273
+
274
+ # Store results
275
+ energy_list.append(e)
276
+ gradient_list.append(g)
277
+ gradient_norm_list.append(np.sqrt(np.linalg.norm(g)**2/(len(g)*3))) # RMS
278
+ geometry_num_list.append(positions / self.bohr2angstroms) # Convert to Bohr
279
+ num_list.append(num)
280
+
281
+ # Handle hessian calculation if needed
282
+ if config.FC_COUNT == -1 or isinstance(optimize_num, str):
283
+ pass
284
+ elif optimize_num % config.FC_COUNT == 0:
285
+ # Calculate exact numerical hessian
286
+ timestamp = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S_%f")[:-2]
287
+ if software_type == "gaussian":
288
+ exact_hess = calc_obj.calc_analytic_hessian() # in hartree/Bohr^2
289
+ exact_hess = exact_hess
290
+ else:
291
+ vib = Vibrations(atoms=calc_obj.atom_obj, delta=0.001, name="z_hess_"+timestamp)
292
+ vib.run()
293
+ result_vib = vib.get_vibrations()
294
+ exact_hess = result_vib.get_hessian_2d() # eV/Ų
295
+ vib.clean()
296
+
297
+ # Convert hessian units
298
+ exact_hess = exact_hess / self.hartree2eV * (self.bohr2angstroms ** 2)
299
+
300
+ # Project out translational and rotational modes
301
+ calc_tools = Calculationtools()
302
+ exact_hess = calc_tools.project_out_hess_tr_and_rot_for_coord(exact_hess, element_list, positions)
303
+
304
+
305
+ # Save hessian
306
+ np.save(os.path.join(config.NEB_FOLDER_DIRECTORY, f"tmp_hessian_{hess_count}.npy"), exact_hess)
307
+ hess_count += 1
308
+
309
+ except Exception as error:
310
+ print(f"Error: {error}")
311
+ print("This molecule could not be optimized.")
312
+ if optimize_num != 0:
313
+ delete_pre_total_velocity.append(num)
314
+
315
+ # Process visualization
316
+ self._process_visualization(energy_list, gradient_list, num_list, optimize_num, config)
317
+
318
+ # Update velocities if needed
319
+ if optimize_num != 0 and len(pre_total_velocity) != 0:
320
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
321
+ pre_total_velocity = pre_total_velocity.tolist()
322
+ for i in sorted(delete_pre_total_velocity, reverse=True):
323
+ pre_total_velocity.pop(i)
324
+ pre_total_velocity = np.array(pre_total_velocity, dtype="float64")
325
+
326
+ return (np.array(energy_list, dtype="float64"),
327
+ np.array(gradient_list, dtype="float64"),
328
+ np.array(geometry_num_list, dtype="float64"),
329
+ pre_total_velocity)
330
+
331
+
332
+
333
+ def setup_calculator(atom_obj, software_type, electric_charge_and_multiplicity, input_file=None, software_path_dict=None, functional=None, basis_set=None, set_memory=None):
334
+ """Module-level helper to attach the appropriate calculator to an ASE Atoms object.
335
+
336
+ Parameters mirror the previous inline branches. Returns the atoms object with
337
+ .calc set.
338
+ """
339
+ software_path_dict = software_path_dict or {}
340
+
341
+ if software_type == "gamessus":
342
+ calc_obj = ASE_GAMESSUS(atom_obj=atom_obj,
343
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
344
+ gamessus_path=software_path_dict.get("gamessus"),
345
+ functional=functional,
346
+ basis_set=basis_set)
347
+
348
+ return calc_obj
349
+ if software_type == "nwchem":
350
+ calc_obj = ASE_NWCHEM(atom_obj=atom_obj,
351
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
352
+ input_file=input_file,
353
+ functional=functional,
354
+ basis_set=basis_set,
355
+ memory=set_memory)
356
+
357
+ return calc_obj
358
+ if software_type == "gaussian":
359
+ calc_obj = ASE_GAUSSIAN(atom_obj=atom_obj,
360
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
361
+ functional=functional,
362
+ basis_set=basis_set,
363
+ memory=set_memory,
364
+ software_path_dict=software_path_dict)
365
+ return calc_obj
366
+
367
+ if software_type == "orca":
368
+ calc_obj = ASE_ORCA(atom_obj=atom_obj,
369
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
370
+ input_file=input_file,
371
+ orca_path=software_path_dict.get("orca"),
372
+ functional=functional,
373
+ basis_set=basis_set)
374
+
375
+ return calc_obj
376
+
377
+ if software_type == "uma-s-1":
378
+ calc_obj = ASE_FAIRCHEM(atom_obj=atom_obj,
379
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
380
+ software_path=software_path_dict.get("uma-s-1"),
381
+ software_type=software_type)
382
+ return calc_obj
383
+ if software_type == "uma-s-1p1":
384
+ calc_obj = ASE_FAIRCHEM(atom_obj=atom_obj,
385
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
386
+ software_path=software_path_dict.get("uma-s-1p1"),
387
+ software_type=software_type)
388
+ return calc_obj
389
+ if software_type == "uma-m-1p1":
390
+ calc_obj = ASE_FAIRCHEM(atom_obj=atom_obj,
391
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
392
+ software_path=software_path_dict.get("uma-m-1p1"),
393
+ software_type=software_type)
394
+
395
+ return calc_obj
396
+ if software_type == "mace_mp":
397
+ calc_obj = ASE_MACE(atom_obj=atom_obj,
398
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
399
+ software_path=software_path_dict.get("mace_mp"),
400
+ software_type=software_type)
401
+ return calc_obj
402
+ if software_type == "mace_off":
403
+ calc_obj = ASE_MACE(atom_obj=atom_obj,
404
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
405
+ software_path=software_path_dict.get("mace_off"),
406
+ software_type=software_type)
407
+
408
+ return calc_obj
409
+ if software_type == "GFN0-xTB":
410
+ calc_obj = ASE_GFN0(atom_obj=atom_obj,
411
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
412
+ software_type=software_type)
413
+
414
+ return calc_obj
415
+ if software_type == "mopac":
416
+ calc_obj = ASE_MOPAC(atom_obj=atom_obj,
417
+ electric_charge_and_multiplicity=electric_charge_and_multiplicity,
418
+ input_file=input_file)
419
+ return calc_obj
420
+
421
+ # Unknown software type
422
+ raise ValueError(f"Unsupported software type: {software_type}")
423
+
424
+
File without changes
@@ -0,0 +1,28 @@
1
+
2
+
3
+ class ASE_FAIRCHEM:
4
+ def __init__(self, **kwargs):
5
+ self.atom_obj = kwargs.get('atom_obj', None)
6
+ self.electric_charge_and_multiplicity = kwargs.get('electric_charge_and_multiplicity', None)
7
+ self.software_path = kwargs.get('software_path', None)
8
+ self.task_name = "omol"
9
+ self.software_type = kwargs.get('software_type', None)
10
+ print(f"ASE_FAIRCHEM: software_type = {self.software_type}")
11
+
12
+
13
+ def run(self): # fairchem.core: version 2.x.x
14
+ try:
15
+ from fairchem.core import FAIRChemCalculator
16
+ from fairchem.core.units.mlip_unit import load_predict_unit
17
+ except ImportError:
18
+ raise ImportError("FAIRChem.core modules not found")
19
+ # Load the prediction unit
20
+ predict_unit = load_predict_unit(path=self.software_path, device="cpu")
21
+
22
+ # Set up the FAIRChem calculator
23
+ fairchem_calc = FAIRChemCalculator(predict_unit=predict_unit, task_name=self.task_name)
24
+ self.atom_obj.info = {"charge": int(self.electric_charge_and_multiplicity[0]),
25
+ "spin": int(self.electric_charge_and_multiplicity[1])}
26
+ self.atom_obj.calc = fairchem_calc
27
+
28
+ return self.atom_obj
@@ -0,0 +1,19 @@
1
+
2
+
3
+ class ASE_GAMESSUS:
4
+ def __init__(self, **kwargs):
5
+ self.atom_obj = kwargs.get('atom_obj', None)
6
+ self.electric_charge_and_multiplicity = kwargs.get('electric_charge_and_multiplicity', None)
7
+ self.gamessus_path = kwargs.get('gamessus_path', None)
8
+ self.functional = kwargs.get('functional', None)
9
+ self.basis_set = kwargs.get('basis_set', None)
10
+ self.memory = kwargs.get('memory', None)
11
+
12
+ def run(self):
13
+ from ase.calculators.gamess_us import GAMESSUS
14
+ self.atom_obj.calc = GAMESSUS(userscr=self.gamessus_path,
15
+ contrl=dict(dfttyp=self.functional),
16
+ charge=self.electric_charge_and_multiplicity[0],
17
+ mult=self.electric_charge_and_multiplicity[1],
18
+ basis=self.basis_set)
19
+ return self.atom_obj
@@ -0,0 +1,165 @@
1
+ import os
2
+ import numpy as np
3
+
4
+
5
+ # If you want to use Gaussian with ASE, you need to have ASE installed and Gaussian 16.
6
+ # ASE can be installed via pip:
7
+ # pip install ase
8
+ # Gaussian 16 must be installed separately and is not free software.
9
+ # Make sure to set the GAUSS_EXEDIR environment variable to point to the directory containing the Gaussian executables.
10
+ # You must write the directory of the Gaussian executables in the software_path.conf file.
11
+ # (e.x., C:\g16\bin for Windows or /usr/local/g16/g16 for Linux)
12
+
13
+ class ASE_GAUSSIAN:
14
+ def __init__(self, **kwargs):
15
+ self.atom_obj = kwargs.get('atom_obj', None)
16
+ self.electric_charge_and_multiplicity = kwargs.get('electric_charge_and_multiplicity', None)
17
+ self.functional = kwargs.get('functional', None)
18
+ self.basis_set = kwargs.get('basis_set', None)
19
+ self.memory = kwargs.get('memory', None)
20
+ self.software_path_dict = kwargs.get('software_path_dict', None)
21
+ self.gau_prog = "g16" # Default to Gaussian 16
22
+ from ase.calculators.gaussian import Gaussian
23
+ self.Gaussian = Gaussian
24
+
25
+
26
+ def run(self):
27
+ if os.name == "nt": # windows (for Gaussian16W)
28
+ os.environ['GAUSS_EXEDIR'] = self.software_path_dict.get("gaussian", "")
29
+ input_file = self.atom_obj.info.get('input_file', 'unknown')
30
+ abs_path = os.path.abspath(input_file)
31
+ #input_file_name = os.path.basename(abs_path)
32
+ input_dir = os.path.dirname(abs_path)
33
+ self.atom_obj.calc = self.Gaussian(xc=self.functional,
34
+ basis=self.basis_set,
35
+ scf='xqc,maxcon=128,maxcyc=32,conver=8',
36
+ mem=self.memory,
37
+ command=f'{self.gau_prog} {input_dir}\\Gaussian.com {input_dir}\\Gaussian.log',
38
+ charge=int(self.electric_charge_and_multiplicity[0]),
39
+ mult=int(self.electric_charge_and_multiplicity[1])
40
+ )
41
+
42
+ elif os.name == "posix": # Linux (for Gaussian16)
43
+ os.environ['GAUSS_EXEDIR'] = self.software_path_dict.get("gaussian", "")
44
+ input_file = self.atom_obj.info.get('input_file', 'unknown')
45
+ abs_path = os.path.abspath(input_file)
46
+ #input_file_name = os.path.basename(abs_path)
47
+ input_dir = os.path.dirname(abs_path)
48
+ atom_obj.calc = self.Gaussian(xc=functional,
49
+ basis=basis_set,
50
+ scf='xqc,maxcon=128,maxcyc=32,conver=8',
51
+ mem=memory,
52
+ command=f'{self.gau_prog} < {input_dir}/Gaussian.com > {input_dir}/Gaussian.log',
53
+ charge=int(electric_charge_and_multiplicity[0]),
54
+ mult=int(electric_charge_and_multiplicity[1])
55
+ )
56
+ else:
57
+ raise EnvironmentError("Unsupported operating system")
58
+
59
+ return self.atom_obj
60
+
61
+
62
+ def calc_analytic_hessian(self):
63
+ """Calculate and return the analytic Hessian matrix."""
64
+
65
+ if self.atom_obj.calc is None:
66
+ raise ValueError("Calculator not set. Please run the 'run' method first.")
67
+
68
+ if os.name == "nt": # windows (for Gaussian16W)
69
+ os.environ['GAUSS_EXEDIR'] = self.software_path_dict.get("gaussian", "")
70
+ input_file = self.atom_obj.info.get('input_file', 'unknown')
71
+ abs_path = os.path.abspath(input_file)
72
+ input_dir = os.path.dirname(abs_path)
73
+ self.atom_obj.calc = self.Gaussian(xc=self.functional,
74
+ basis=self.basis_set,
75
+ scf='xqc,maxcon=128,maxcyc=32,conver=8',
76
+ extra='freq=noraman',
77
+ mem=self.memory,
78
+ command=f'{self.gau_prog} {input_dir}\\Gaussian.com {input_dir}\\Gaussian.log',
79
+ charge=int(self.electric_charge_and_multiplicity[0]),
80
+ mult=int(self.electric_charge_and_multiplicity[1]),
81
+
82
+ )
83
+ self.atom_obj.calc.calculate(self.atom_obj)
84
+
85
+ elif os.name == "posix": # Linux (for Gaussian16)
86
+ os.environ['GAUSS_EXEDIR'] = self.software_path_dict.get("gaussian", "")
87
+ input_file = self.atom_obj.info.get('input_file', 'unknown')
88
+ abs_path = os.path.abspath(input_file)
89
+ input_dir = os.path.dirname(abs_path)
90
+ self.atom_obj.calc = self.Gaussian(xc=self.functional,
91
+ basis=self.basis_set,
92
+ scf='xqc,maxcon=128,maxcyc=32,conver=8',
93
+ extra='freq=noraman',
94
+ mem=self.memory,
95
+ command=f'{self.gau_prog} < {input_dir}/Gaussian.com > {input_dir}/Gaussian.log',
96
+ charge=int(self.electric_charge_and_multiplicity[0]),
97
+ mult=int(self.electric_charge_and_multiplicity[1]),
98
+
99
+ )
100
+ self.atom_obj.calc.calculate(self.atom_obj)
101
+ else: # Unsupported OS
102
+ raise EnvironmentError("Unsupported operating system")
103
+
104
+ hessian = self._extract_hessian_from_output(input_dir + "/Gaussian")
105
+
106
+ return hessian # in hartree/Bohr^2
107
+
108
+ def _extract_hessian_from_output(self, label):
109
+ log_file = f"{label}.log"
110
+
111
+ if not os.path.exists(log_file):
112
+ raise FileNotFoundError(f"Gaussian output file {log_file} not found")
113
+
114
+ with open(log_file, 'r') as f:
115
+ lines = f.readlines()
116
+
117
+ # Find Hessian in output
118
+ reading_hessian = False
119
+
120
+ counter_1 = 0
121
+ counter_2 = 0
122
+
123
+ for i, line in enumerate(lines):
124
+ # Determine number of atoms
125
+ if 'NAtoms=' in line:
126
+ n_atoms = int(line.split('NAtoms=')[1].split()[0])
127
+ n_coords = n_atoms * 3
128
+ hessian = np.zeros((n_coords, n_coords))
129
+
130
+ # Locate Hessian matrix section
131
+ if 'Force constants in Cartesian coordinates:' in line:
132
+ reading_hessian = True
133
+ tmp_i = i
134
+ continue
135
+
136
+ if reading_hessian and tmp_i + 1 < i:
137
+ # Parse Hessian data
138
+ if line.strip() == '':
139
+ reading_hessian = False
140
+ continue
141
+
142
+ parts = line.split()
143
+ atom_counter_i = 0 + 5 * counter_1
144
+
145
+ if len(parts) > 1:
146
+
147
+ if "D" in parts[1]:
148
+ values = [float(x.replace('D', 'E')) for x in parts[1:]]
149
+ values = np.array(values, dtype=np.float64)
150
+
151
+ values_len = len(values)
152
+
153
+ hessian[(atom_counter_i + counter_2), atom_counter_i:(atom_counter_i + values_len)] = values
154
+ hessian[atom_counter_i:(atom_counter_i + values_len), (atom_counter_i + counter_2)] = values
155
+ counter_2 += 1
156
+ else:
157
+ counter_1 += 1
158
+ counter_2 = 0
159
+
160
+
161
+ hessian = (hessian + hessian.T) / 2 # Symmetrize Hessian
162
+
163
+ return hessian #hartree/Bohr^2
164
+
165
+
@@ -0,0 +1,28 @@
1
+
2
+
3
+
4
+ class ASE_MACE:
5
+ def __init__(self, **kwargs):
6
+
7
+ self.atom_obj = kwargs.get('atom_obj', None)
8
+ self.electric_charge_and_multiplicity = kwargs.get('electric_charge_and_multiplicity', None)
9
+ self.software_path = kwargs.get('software_path', None)
10
+ self.software_type = kwargs.get('software_type', None)
11
+
12
+ def set_nnp(self):
13
+ if self.software_type == "MACE_MP":
14
+ from mace.calculators import mace_mp
15
+ mace_mp = mace_mp()
16
+ return mace_mp
17
+ elif self.software_type == "MACE_OFF":
18
+ from mace.calculators import mace_off
19
+ mace_off = mace_off()
20
+ return mace_off
21
+ else:
22
+ raise ValueError(f"Unsupported software type: {self.software_type}")
23
+
24
+
25
+ def run(self):
26
+ nnp_obj = self.set_nnp()
27
+ self.atom_obj.calc = nnp_obj
28
+ return self.atom_obj