mlatom 2.0.5__tar.gz → 2.1.2__tar.gz

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 (101) hide show
  1. {MLatom-2.0.5 → MLatom-2.1.2}/PKG-INFO +14 -9
  2. {MLatom-2.0.5 → MLatom-2.1.2}/README.md +13 -8
  3. {MLatom-2.0.5 → MLatom-2.1.2}/setup.py +1 -1
  4. MLatom-2.1.2/src/MLatom/AIQM1.py +481 -0
  5. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/ML_NEA.py +13 -2
  6. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatom.py +33 -9
  7. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF +0 -0
  8. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/A_KRR.f90 +38 -9
  9. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/A_KRR_kernel.f90 +24 -1
  10. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/MLatomF.f90 +3 -3
  11. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/MLmodel.f90 +41 -4
  12. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/Makefile +1 -1
  13. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/constants.f90 +1 -0
  14. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/dataset.f90 +1 -0
  15. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/optionsModule.f90 +44 -0
  16. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLtasks.py +481 -88
  17. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/README +11 -10
  18. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv0.pt +0 -0
  19. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv1.pt +0 -0
  20. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv2.pt +0 -0
  21. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv3.pt +0 -0
  22. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv4.pt +0 -0
  23. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv5.pt +0 -0
  24. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv6.pt +0 -0
  25. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv7.pt +0 -0
  26. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv0.pt +0 -0
  27. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv1.pt +0 -0
  28. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv2.pt +0 -0
  29. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv3.pt +0 -0
  30. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv4.pt +0 -0
  31. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv5.pt +0 -0
  32. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv6.pt +0 -0
  33. MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv7.pt +0 -0
  34. MLatom-2.1.2/src/MLatom/calculator.py +54 -0
  35. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/doc.py +94 -24
  36. MLatom-2.1.2/src/MLatom/geomopt.py +506 -0
  37. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/header.py +31 -0
  38. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interface_MLatomF.py +15 -7
  39. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/interface_DeePMDkit.py +84 -43
  40. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/template.json +3 -3
  41. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/GAP/interface_GAP.py +27 -13
  42. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/PhysNet_train.py +25 -2
  43. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/interface_PhysNet.py +28 -8
  44. MLatom-2.1.2/src/MLatom/interfaces/TorchANI/TorchANI_predict.py +208 -0
  45. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/TorchANI/TorchANI_train.py +48 -19
  46. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/TorchANI/interface_TorchANI.py +96 -42
  47. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/sGDML/interface_sGDML.py +6 -3
  48. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/ref.json +12 -2
  49. MLatom-2.1.2/src/MLatom/thermo.py +179 -0
  50. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/PKG-INFO +14 -9
  51. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/SOURCES.txt +21 -0
  52. MLatom-2.0.5/src/MLatom/interfaces/TorchANI/TorchANI_predict.py +0 -82
  53. {MLatom-2.0.5 → MLatom-2.1.2}/LICENSE.txt +0 -0
  54. {MLatom-2.0.5 → MLatom-2.1.2}/setup.cfg +0 -0
  55. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/LICENSE.CC-BY-NC-ND-4.0 +0 -0
  56. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/D_CoulombMatrix.f90 +0 -0
  57. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/D_rel2eq.f90 +0 -0
  58. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/MLatomFInfo.f90 +0 -0
  59. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/Makefile.intel +0 -0
  60. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/analyze.f90 +0 -0
  61. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/cs.cpp +0 -0
  62. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/mathUtils.f90 +0 -0
  63. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/molDescr.f90 +0 -0
  64. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/precision.f90 +0 -0
  65. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/sampling.f90 +0 -0
  66. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/statistics.f90 +0 -0
  67. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/stopper.f90 +0 -0
  68. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/strings.f90 +0 -0
  69. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/timing.f90 +0 -0
  70. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/types.f90 +0 -0
  71. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/__init__.py +0 -0
  72. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/args_class.py +0 -0
  73. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/cs.so +0 -0
  74. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/documentation/installation.txt +0 -0
  75. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/E_FCI_451.dat +0 -0
  76. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/E_UHF_451.dat +0 -0
  77. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/R_451.dat +0 -0
  78. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/isubtrain.dat +0 -0
  79. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/itest.dat +0 -0
  80. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/itrain.dat +0 -0
  81. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/ivalidate.dat +0 -0
  82. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/mlatom.inp +0 -0
  83. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/mlatom.saved +0 -0
  84. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/test.sh +0 -0
  85. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/DP_inference.py +0 -0
  86. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/__init__.py +0 -0
  87. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/GAP/__init__.py +0 -0
  88. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/PhysNet_predict.py +0 -0
  89. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/__init__.py +0 -0
  90. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/TorchANI/__init__.py +0 -0
  91. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/__init__.py +0 -0
  92. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/sGDML/__init__.py +0 -0
  93. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/sGDML/sgdml_dataset_from_extxyz.py +0 -0
  94. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/mlatom_gui.py +0 -0
  95. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/shell_cmd.py +0 -0
  96. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/sliceData.py +0 -0
  97. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/stopper.py +0 -0
  98. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/dependency_links.txt +0 -0
  99. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/entry_points.txt +0 -0
  100. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/requires.txt +0 -0
  101. {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MLatom
3
- Version: 2.0.5
3
+ Version: 2.1.2
4
4
  Summary: A Package for Atomistic Simulations with Machine Learning
5
5
  Home-page: http://mlatom.com
6
6
  Author: Pavlo O. Dral
@@ -71,9 +71,15 @@ Permutationally invariant kernel and self-correction are also supported.
71
71
  - permuted.
72
72
 
73
73
 
74
- # The KREG model
74
+ # ML models
75
75
  The [ KREG (Kernel-ridge-regression using RE descriptor and the Gaussian kernel function )](http://dx.doi.org/10.1021/acs.jpclett.8b02469) model is the default ML method.
76
76
 
77
+ ## General-purpose ML models
78
+ - AIQM1 (requires interfaces to other programs as described in http://MLatom.com/AIQM1)
79
+ - Models available via interface to [TorchANI](https://doi.org/10.1021/acs.jcim.0c00451)
80
+ - ANI-1x
81
+ - ANI-1ccx
82
+ - ANI-2x
77
83
 
78
84
  # Model Validation
79
85
  [ ML model can be validated (generalization error can be estimated) in several ways: ](https://web.stanford.edu/~hastie/ElemStatLearn/)
@@ -103,13 +109,12 @@ MLatom can be also used to estimate first derivatives from an ML model. Two scen
103
109
  - derivatives for interfaced models
104
110
 
105
111
 
106
- # Cross Section
112
+ # UV/vis spectra
107
113
  MLatom can significantly accelerate the calculation of cross-section with the Nuclear Ensemble Approach (NEA).
108
114
 
109
- In brief, this feature uses fewer QC calculation to achieve higher precision and reduce computational cost. You can find more detail on this paper (please cite it when using this feature:
115
+ In brief, this feature uses fewer QC calculation to achieve higher precision and reduce computational cost. You can find more detail on this paper (please cite it when using this feature):
110
116
 
111
- > Bao-Xin Xue, Mario Barbatti*, Pavlo O. Dral*, [ Machine Learning for Absorption Cross Sections ](https://doi.org/10.1021/acs.jpca.0c05310), J. Phys. Chem. A 2020, 124, 7199–7210. DOI: 10.1021/acs.jpca.0c05310.
112
- > [ Preprint on ChemRxiv ](https://doi.org/10.26434/chemrxiv.12594191), DOI: 10.26434/chemrxiv.12594191.
117
+ > Bao-Xin Xue, Mario Barbatti, Pavlo O. Dral, [ Machine Learning for Absorption Cross Sections ](https://doi.org/10.1021/acs.jpca.0c05310), J. Phys. Chem. A 2020, 124, 7199–7210. DOI: 10.1021/acs.jpca.0c05310.
113
118
 
114
119
  # Interfaces to 3<sup>rd</sup>-party software
115
120
  MLatom also provides interfaces to some third-party software where extra ML model types are natively implemented. It allows users to access other popular ML model types within MLatom's workflow. Currently available third-party model types are:
@@ -122,10 +127,10 @@ MLatom also provides interfaces to some third-party software where extra ML mode
122
127
 
123
128
  # About Program
124
129
  MLatom: a Package for Atomistic Simulations with Machine Learning
125
- Version 2.0.5
130
+ Version 2.1.2
126
131
  http://mlatom.com/
127
132
 
128
- Copyright (c) 2013-2021 Pavlo O. Dral
133
+ Copyright (c) 2013-2022 Pavlo O. Dral
129
134
  http://dr-dral.com/
130
135
 
131
136
  All rights reserved. This work is licensed under the [Attribution-NonCommercial-NoDerivatives 4.0 International](http://creativecommons.org/licenses/by-nc-nd/4.0/) license. See LICENSE.CC-BY-NC-ND-4.0.
@@ -136,7 +141,7 @@ Cite as:
136
141
 
137
142
  1. Pavlo O. Dral, J. Comput. Chem. 2019, 40, 2339-2347
138
143
  2. Pavlo O. Dral, Fuchun Ge, Bao-Xin Xue, Yi-Fan Hou, Max Pinheiro Jr, Jianxing Huang, Mario Barbatti, Top. Curr. Chem. 2021, 379, 27
139
- 3. Pavlo O. Dral, Bao-Xin Xue, Fuchun Ge, Yi-Fan Hou, Max Pinheiro Jr, MLatom: A Package for Atomistic Simulations with Machine Learning, version 2.0.5, Xiamen University, Xiamen, China, 2013-2021.
144
+ 3. Pavlo O. Dral, Peikun Zheng, Bao-Xin Xue, Fuchun Ge, Yi-Fan Hou, Max Pinheiro Jr, MLatom: A Package for Atomistic Simulations with Machine Learning, version 2.1.2, Xiamen University, Xiamen, China, 2013-2022.
140
145
 
141
146
 
142
147
  # License
@@ -53,9 +53,15 @@ Permutationally invariant kernel and self-correction are also supported.
53
53
  - permuted.
54
54
 
55
55
 
56
- # The KREG model
56
+ # ML models
57
57
  The [ KREG (Kernel-ridge-regression using RE descriptor and the Gaussian kernel function )](http://dx.doi.org/10.1021/acs.jpclett.8b02469) model is the default ML method.
58
58
 
59
+ ## General-purpose ML models
60
+ - AIQM1 (requires interfaces to other programs as described in http://MLatom.com/AIQM1)
61
+ - Models available via interface to [TorchANI](https://doi.org/10.1021/acs.jcim.0c00451)
62
+ - ANI-1x
63
+ - ANI-1ccx
64
+ - ANI-2x
59
65
 
60
66
  # Model Validation
61
67
  [ ML model can be validated (generalization error can be estimated) in several ways: ](https://web.stanford.edu/~hastie/ElemStatLearn/)
@@ -85,13 +91,12 @@ MLatom can be also used to estimate first derivatives from an ML model. Two scen
85
91
  - derivatives for interfaced models
86
92
 
87
93
 
88
- # Cross Section
94
+ # UV/vis spectra
89
95
  MLatom can significantly accelerate the calculation of cross-section with the Nuclear Ensemble Approach (NEA).
90
96
 
91
- In brief, this feature uses fewer QC calculation to achieve higher precision and reduce computational cost. You can find more detail on this paper (please cite it when using this feature:
97
+ In brief, this feature uses fewer QC calculation to achieve higher precision and reduce computational cost. You can find more detail on this paper (please cite it when using this feature):
92
98
 
93
- > Bao-Xin Xue, Mario Barbatti*, Pavlo O. Dral*, [ Machine Learning for Absorption Cross Sections ](https://doi.org/10.1021/acs.jpca.0c05310), J. Phys. Chem. A 2020, 124, 7199–7210. DOI: 10.1021/acs.jpca.0c05310.
94
- > [ Preprint on ChemRxiv ](https://doi.org/10.26434/chemrxiv.12594191), DOI: 10.26434/chemrxiv.12594191.
99
+ > Bao-Xin Xue, Mario Barbatti, Pavlo O. Dral, [ Machine Learning for Absorption Cross Sections ](https://doi.org/10.1021/acs.jpca.0c05310), J. Phys. Chem. A 2020, 124, 7199–7210. DOI: 10.1021/acs.jpca.0c05310.
95
100
 
96
101
  # Interfaces to 3<sup>rd</sup>-party software
97
102
  MLatom also provides interfaces to some third-party software where extra ML model types are natively implemented. It allows users to access other popular ML model types within MLatom's workflow. Currently available third-party model types are:
@@ -104,10 +109,10 @@ MLatom also provides interfaces to some third-party software where extra ML mode
104
109
 
105
110
  # About Program
106
111
  MLatom: a Package for Atomistic Simulations with Machine Learning
107
- Version 2.0.5
112
+ Version 2.1.2
108
113
  http://mlatom.com/
109
114
 
110
- Copyright (c) 2013-2021 Pavlo O. Dral
115
+ Copyright (c) 2013-2022 Pavlo O. Dral
111
116
  http://dr-dral.com/
112
117
 
113
118
  All rights reserved. This work is licensed under the [Attribution-NonCommercial-NoDerivatives 4.0 International](http://creativecommons.org/licenses/by-nc-nd/4.0/) license. See LICENSE.CC-BY-NC-ND-4.0.
@@ -118,7 +123,7 @@ Cite as:
118
123
 
119
124
  1. Pavlo O. Dral, J. Comput. Chem. 2019, 40, 2339-2347
120
125
  2. Pavlo O. Dral, Fuchun Ge, Bao-Xin Xue, Yi-Fan Hou, Max Pinheiro Jr, Jianxing Huang, Mario Barbatti, Top. Curr. Chem. 2021, 379, 27
121
- 3. Pavlo O. Dral, Bao-Xin Xue, Fuchun Ge, Yi-Fan Hou, Max Pinheiro Jr, MLatom: A Package for Atomistic Simulations with Machine Learning, version 2.0.5, Xiamen University, Xiamen, China, 2013-2021.
126
+ 3. Pavlo O. Dral, Peikun Zheng, Bao-Xin Xue, Fuchun Ge, Yi-Fan Hou, Max Pinheiro Jr, MLatom: A Package for Atomistic Simulations with Machine Learning, version 2.1.2, Xiamen University, Xiamen, China, 2013-2022.
122
127
 
123
128
 
124
129
  # License
@@ -43,7 +43,7 @@ with open(os.path.join(here, 'README.md')) as f:
43
43
 
44
44
  setup(
45
45
  name = pkg_name,
46
- version = "2.0.5",
46
+ version = "2.1.2",
47
47
  author = "Pavlo O. Dral",
48
48
  author_email = "admin@mlatom.com",
49
49
  license = 'CC BY-NC-ND 4.0', # https://creativecommons.org/licenses/by-nc-nd/4.0/
@@ -0,0 +1,481 @@
1
+ #!/usr/bin/env python3
2
+ '''
3
+ !---------------------------------------------------------------------------!
4
+ ! AIQM1: Artificial intelligence quantum-mechanical method 1 !
5
+ ! Implementations by: Peikung Zheng !
6
+ !---------------------------------------------------------------------------!
7
+ '''
8
+ import numpy as np
9
+ import os
10
+ import sys
11
+ from collections import Counter
12
+ import stopper
13
+ import json
14
+ import struct
15
+ import re
16
+ #import time
17
+ import warnings
18
+ warnings.filterwarnings("ignore")
19
+
20
+ mlatomdir=os.path.dirname(__file__)
21
+ bohr2a = 0.52917721067
22
+
23
+ class AIQM1Cls(object):
24
+ def __init__(self, argsAIQM1 = sys.argv[1:]):
25
+
26
+ args.parse(argsAIQM1)
27
+ self.mndobin = args.mndobin
28
+ self.dftd4bin = args.dftd4bin
29
+
30
+ self.xyzfile = args.xyzfile
31
+ self.device = args.device
32
+ self.level = args.level
33
+ self.d4 = args.d4
34
+ self.model_index = args.model_index
35
+ self.mndokw = args.mndokw
36
+ self.yestfile = args.yestfile
37
+ self.ygradestfile = args.ygradxyzestfile
38
+ self.hessianestfile = args.hessianestfile
39
+ self.hesscalc = args.hesscalc
40
+ self.species_order = [1, 6, 7, 8]
41
+ self.dftsae = [-4.27888067e-02, -3.34869833e+01, -4.69896148e+01, -6.30294433e+01]
42
+ self.ccsae = [-4.29365862e-02, -3.34329586e+01, -4.69301173e+01, -6.29634763e+01]
43
+
44
+ def define_aev(self):
45
+ Rcr = 5.2000e+00
46
+ Rca = 4.0000e+00
47
+ EtaR = torch.tensor([1.6000000e+01], device=self.device)
48
+ ShfR = torch.tensor([9.0000000e-01, 1.1687500e+00, 1.4375000e+00, 1.7062500e+00, 1.9750000e+00, 2.2437500e+00, 2.5125000e+00, 2.7812500e+00, 3.0500000e+00, 3.3187500e+00, 3.5875000e+00, 3.8562500e+00, 4.1250000e+00, 4.3937500e+00, 4.6625000e+00, 4.9312500e+00], device=self.device)
49
+ Zeta = torch.tensor([3.2000000e+01], device=self.device)
50
+ ShfZ = torch.tensor([1.9634954e-01, 5.8904862e-01, 9.8174770e-01, 1.3744468e+00, 1.7671459e+00, 2.1598449e+00, 2.5525440e+00, 2.9452431e+00], device=self.device)
51
+ EtaA = torch.tensor([8.0000000e+00], device=self.device)
52
+ ShfA = torch.tensor([9.0000000e-01, 1.6750000e+00, 2.4499998e+00, 3.2250000e+00], device=self.device)
53
+ num_species = len(self.species_order)
54
+ aev_computer = torchani.AEVComputer(Rcr, Rca, EtaR, ShfR, EtaA, Zeta, ShfA, ShfZ, num_species)
55
+ self.aev_computer = aev_computer
56
+
57
+ def define_nn(self):
58
+ aev_dim = self.aev_computer.aev_length
59
+ H_network = torch.nn.Sequential(
60
+ torch.nn.Linear(aev_dim, 160),
61
+ torch.nn.GELU(),
62
+ torch.nn.Linear(160, 128),
63
+ torch.nn.GELU(),
64
+ torch.nn.Linear(128, 96),
65
+ torch.nn.GELU(),
66
+ torch.nn.Linear(96, 1)
67
+ )
68
+
69
+ C_network = torch.nn.Sequential(
70
+ torch.nn.Linear(aev_dim, 144),
71
+ torch.nn.GELU(),
72
+ torch.nn.Linear(144, 112),
73
+ torch.nn.GELU(),
74
+ torch.nn.Linear(112, 96),
75
+ torch.nn.GELU(),
76
+ torch.nn.Linear(96, 1)
77
+ )
78
+
79
+ N_network = torch.nn.Sequential(
80
+ torch.nn.Linear(aev_dim, 128),
81
+ torch.nn.GELU(),
82
+ torch.nn.Linear(128, 112),
83
+ torch.nn.GELU(),
84
+ torch.nn.Linear(112, 96),
85
+ torch.nn.GELU(),
86
+ torch.nn.Linear(96, 1)
87
+ )
88
+
89
+ O_network = torch.nn.Sequential(
90
+ torch.nn.Linear(aev_dim, 128),
91
+ torch.nn.GELU(),
92
+ torch.nn.Linear(128, 112),
93
+ torch.nn.GELU(),
94
+ torch.nn.Linear(112, 96),
95
+ torch.nn.GELU(),
96
+ torch.nn.Linear(96, 1)
97
+ )
98
+
99
+ nn = torchani.ANIModel([H_network, C_network, N_network, O_network])
100
+ #print(nn)
101
+ self.nn = nn
102
+
103
+ def load_models(self):
104
+ dirname = os.path.join(mlatomdir, 'aiqm1_model')
105
+ method = 'aiqm1_' + self.level
106
+ models = list()
107
+ if self.model_index is None:
108
+ for i in range(8):
109
+ self.define_nn()
110
+ checkpoint = torch.load(os.path.join(dirname, f'{method}_cv{i}.pt'), map_location=self.device)
111
+ self.nn.load_state_dict(checkpoint['nn'])
112
+ model = torchani.nn.Sequential(self.aev_computer, self.nn).to(self.device).double()
113
+ models.append(model)
114
+ else:
115
+ self.define_nn()
116
+ checkpoint = torch.load(os.path.join(dirname, f'{method}_cv{self.model_index}.pt'), map_location=self.device)
117
+ self.nn.load_state_dict(checkpoint['nn'])
118
+ model = torchani.nn.Sequential(self.aev_computer, self.nn).to(self.device).double()
119
+ models.append(model)
120
+ self.models = models
121
+
122
+ def predict(self, device, d4, sae):
123
+
124
+ numbers, coordinates = get_xyz(self.xyzfile)
125
+ charges, mults, odm2_energies, odm2_grads, odm2_hesses = run_odm2_calculation(self.mndobin, numbers, coordinates, self.hesscalc, self.mndokw)
126
+ shifts = cal_shifts(numbers, sae)
127
+ if d4:
128
+ d4_energies, d4_grads, d4_hesses = run_d4_calculation(self.dftd4bin, self.xyzfile, numbers, coordinates, charges, self.hesscalc)
129
+ species_to_tensor = ChemicalSymbolsToInts(self.species_order)
130
+
131
+ fenergy = open(args.yestfile, 'w')
132
+ fgrad = open(args.ygradxyzestfile, 'w')
133
+ if self.hesscalc:
134
+ fhess = open(args.hessianestfile, 'w')
135
+
136
+ for i in range(len(numbers)):
137
+ nat = len(numbers[i])
138
+ coordinate = torch.tensor(coordinates[i]).to(device).requires_grad_(True)
139
+ shift = torch.tensor(shifts[i]).to(device)
140
+ odm2_energy = torch.tensor(odm2_energies[i]).to(device)
141
+ odm2_grad = torch.tensor(odm2_grads[i]).to(device)
142
+ coordinate = coordinate.unsqueeze(0)
143
+ species = species_to_tensor(numbers[i]).to(device).unsqueeze(0)
144
+ delta_energies = []; delta_grads = []; delta_hesses = []
145
+ for mod in self.models:
146
+ delta_energy = mod((species, coordinate)).energies
147
+ delta_grad = torch.autograd.grad(delta_energy.sum(), coordinate, create_graph=True, retain_graph=True)[0]
148
+ delta_energies.append(delta_energy)
149
+ delta_grads.append(delta_grad)
150
+ if self.hesscalc:
151
+ delta_hess = torchani.utils.hessian(coordinate, energies=delta_energy)
152
+ delta_hesses.append(delta_hess)
153
+
154
+ delta_energy = torch.stack([e for e in delta_energies], dim=0)
155
+
156
+ fmt = ' %-40s: %15.8f Hartree'
157
+ if len(self.models) == 8:
158
+ e_std = delta_energy.std(dim=0, unbiased=False)
159
+ print(fmt % ('Standard deviation of NN contribution', e_std), end='')
160
+ e_std = hartree2kcalmol(e_std)
161
+ print('%15.5f kcal/mol' % e_std)
162
+ np.savetxt('std', e_std.detach().numpy())
163
+ delta_energy = delta_energy.mean(0)
164
+ delta_grad = torch.stack([g for g in delta_grads], dim=0).mean(0)
165
+ energy = delta_energy[0] + odm2_energy + shift
166
+ grad = delta_grad[0] + odm2_grad
167
+ print(fmt % ('NN contribution', delta_energy))
168
+ print(fmt % ('Sum of atomic self energies', shift))
169
+ print(fmt % ('ODM2* contribution', odm2_energy), file=sys.stdout)
170
+ if self.hesscalc:
171
+ odm2_hess = torch.tensor(odm2_hesses[i]).to(device)
172
+ delta_hess = torch.stack([h for h in delta_hesses], dim=0).mean(0)
173
+ hess = delta_hess + odm2_hess
174
+ if d4:
175
+ d4_energy = torch.tensor(d4_energies[i]).to(device)
176
+ d4_grad = torch.tensor(d4_grads[i]).to(device)
177
+ energy = energy + d4_energy
178
+ grad = grad + d4_grad
179
+ print(fmt % ('D4 contribution', d4_energy))
180
+ if self.hesscalc:
181
+ d4_hess = torch.tensor(d4_hesses[i]).to(device)
182
+ hess = hess + d4_hess
183
+ print(fmt % ('Total energy', energy))
184
+ print('')
185
+ fenergy.write('%20.12f\n' % energy)
186
+ fgrad.write('%d\n\n' % nat)
187
+ for j in range(nat):
188
+ fgrad.write('%20.12f %20.12f %20.12f\n' % (grad[j][0], grad[j][1], grad[j][2]))
189
+ if self.hesscalc:
190
+ hess = hess.flatten()
191
+ fhess.write('%d\n\n' % nat)
192
+ for j in range(len(hess)):
193
+ fhess.write('%20.12f\n' % hess[j])
194
+ fenergy.close()
195
+ fgrad.close()
196
+ if self.hesscalc:
197
+ fhess.close()
198
+ return charges, mults
199
+
200
+ def forward(self):
201
+ if self.level == 'dft':
202
+ sae = self.dftsae
203
+ elif self.level == 'cc':
204
+ sae = self.ccsae
205
+ self.define_aev()
206
+ self.load_models()
207
+ charges, mults = self.predict(self.device, self.d4, sae)
208
+ return charges, mults
209
+
210
+ class args(object):
211
+
212
+ @classmethod
213
+ def check_prog(cls):
214
+ # MNDO
215
+ status = os.popen('echo $mndobin').read().strip()
216
+ if len(status) != 0:
217
+ mndobin = status
218
+ else:
219
+ stopper.stopMLatom('Can not find MNDO software, please set the environment variable: export mndobin=...')
220
+ # dftd4
221
+ dftd4bin = None
222
+ if cls.d4:
223
+ status = os.popen('echo $dftd4bin').read().strip()
224
+ if len(status) != 0:
225
+ dftd4bin = status
226
+ else:
227
+ stopper.stopMLatom('Can not find dftd4 software, please set the environment variable: export dftd4bin=...')
228
+ # TorchANI
229
+ try:
230
+ import torch
231
+ import torchani
232
+ from torchani.utils import ChemicalSymbolsToInts
233
+ from torchani.units import hartree2kcalmol
234
+ except:
235
+ stopper.stopMLatom('Please install all Python module required for TorchANI')
236
+ globals()['torch'] = torch
237
+ globals()['torchani'] = torchani
238
+ globals()['ChemicalSymbolsToInts'] = ChemicalSymbolsToInts
239
+ globals()['hartree2kcalmol'] = hartree2kcalmol
240
+
241
+ cls.mndobin = mndobin
242
+ cls.dftd4bin = dftd4bin
243
+
244
+ @classmethod
245
+ def parse(cls, argsraw):
246
+ # Default values:
247
+ cls.xyzfile = None
248
+ cls.level = 'cc'
249
+ cls.d4 = False
250
+ cls.model_index = None
251
+ cls.mndokw = None
252
+ cls.yestfile = 'enest.dat'
253
+ cls.ygradxyzestfile = 'gradest.dat'
254
+ cls.hessianestfile = None
255
+ cls.hesscalc = False
256
+
257
+ argslower = [arg.lower() for arg in argsraw]
258
+ if 'xyzfile' not in ''.join(argslower):
259
+ printHelp()
260
+ stopper.stopMLatom('At least xyzfile should be provided')
261
+ for arg in argsraw:
262
+ if (arg.lower() == 'help'
263
+ or arg.lower() == '-help'
264
+ or arg.lower() == '-h'
265
+ or arg.lower() == '--help'):
266
+ printHelp()
267
+ stopper.stopMLatom('')
268
+ elif arg.lower()[0:len('aiqm1dftstar')] == 'aiqm1dftstar':
269
+ cls.level = 'dft'
270
+ elif arg.lower()[0:len('aiqm1dft')] == 'aiqm1dft':
271
+ cls.level = 'dft'
272
+ cls.d4 = True
273
+ elif arg.lower()[0:len('aiqm1')] == 'aiqm1':
274
+ cls.level = 'cc'
275
+ cls.d4 = True
276
+ elif arg.lower()[0:len('xyzfile=')] == 'xyzfile=':
277
+ cls.xyzfile = arg[len('xyzfile='):]
278
+ #elif arg.lower()[0:len('gpu=')] == 'gpu=':
279
+ # os.environ["CUDA_VISIBLE_DEVICES"] = arg[len('gpu='):]
280
+ # cls.device = torch.device('cuda')
281
+ elif arg.lower()[0:len('model_index=')] == 'model_index=':
282
+ cls.model_index = int(arg[len('model_index='):])
283
+ elif arg.lower()[0:len('mndokeywords=')] == 'mndokeywords=':
284
+ cls.mndokw = arg[len('mndokeywords='):]
285
+ elif arg.lower()[0:len('yestfile=')] == 'yestfile=':
286
+ cls.yestfile = arg[len('yestfile='):]
287
+ elif arg.lower()[0:len('ygradxyzestfile=')] == 'ygradxyzestfile=':
288
+ cls.ygradxyzestfile = arg[len('ygradxyzestfile='):]
289
+ elif arg.lower()[0:len('hessianestfile=')] == 'hessianestfile=':
290
+ cls.hessianestfile = arg[len('hessianestfile='):]
291
+ cls.hesscalc = True
292
+ #else:
293
+ # printHelp()
294
+ # stopper.stopMLatom('Option "%s" is not recognized' % arg)
295
+ cls.check_prog()
296
+ cls.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
297
+
298
+ def get_xyz(xyzfile):
299
+ element2number = {'H':1, 'C':6, 'N':7, 'O':8}
300
+ coordinates = []; numbers = []
301
+ with open(xyzfile, 'r') as f:
302
+ lines = f.readlines()
303
+ for i in range(len(lines)):
304
+ if lines[i].strip().isdigit():
305
+ element = []; coordinate = []
306
+ nat = int(lines[i])
307
+ for j in range(i+2, i+2+nat):
308
+ element.append(lines[j].strip().split()[0])
309
+ coordinate.append(lines[j].strip().split()[1:])
310
+ if element[0].isdigit():
311
+ number = element
312
+ else:
313
+ number = np.array([element2number[i.upper()] for i in element])
314
+ number = np.array(number).astype('int')
315
+ coordinate = np.array(coordinate).astype('float')
316
+ numbers.append(number)
317
+ coordinates.append(coordinate)
318
+ return numbers, coordinates
319
+
320
+ def run_odm2_calculation(mndobin, numbers, coordinates, hesscalc, mndokw):
321
+ charges = np.full(len(numbers), 0)
322
+ mults = np.full(len(numbers), 1)
323
+ energies = []; grads = []; hesses = []
324
+ if mndokw:
325
+ mndokeywords, charges, mults = read_mndokw(mndokw)
326
+ if len(mndokeywords) != len(numbers):
327
+ stopper.stopMLatom('Inconsistency of the nubmer of keywords and molecules')
328
+ for i in range(len(numbers)):
329
+ with open('mndo.inp', 'w') as f:
330
+ if mndokw:
331
+ f.write(mndokeywords[i] + '\n\n\n')
332
+ else:
333
+ if hesscalc:
334
+ f.write('jop=2 +\n')
335
+ else:
336
+ f.write('jop=-2 +\n')
337
+ f.write('iop=-22 igeom=1 iform=1 immdp=-1 nsav15=3 +\n')
338
+ f.write('icuts=-1 icutg=-1 kitscf=9999 iscf=9 iplscf=9 +\n')
339
+ f.write('iprint=-1 kprint=-5 lprint=-2 mprint=0 jprint=-1 +\n')
340
+ f.write('kharge=0 imult=0 nprint=-1\n\n\n')
341
+ number = numbers[i]
342
+ coordinate = coordinates[i]
343
+ for j in range(len(number)):
344
+ f.write('%2s' % (number[j]) + ' '*5)
345
+ f.write('%12.8f %3d' % (coordinate[j][0], 1))
346
+ f.write(' '*5)
347
+ f.write('%12.8f %3d' % (coordinate[j][1], 1))
348
+ f.write(' '*5)
349
+ f.write('%12.8f %3d' % (coordinate[j][2], 1))
350
+ f.write('\n')
351
+ f.write('\n')
352
+ os.system(mndobin + " < mndo.inp > mndo.out")
353
+ energy, grad, hess = get_odm2_result(hesscalc)
354
+ energies.append(energy)
355
+ grads.append(grad)
356
+ hesses.append(hess)
357
+
358
+ #energies = np.array(energies)
359
+ return charges, mults, energies, grads, hesses
360
+
361
+ def read_mndokw(mndokw, split=False):
362
+ with open(mndokw, 'r') as f:
363
+ mndokeywords = f.read().strip('\n')
364
+ mndokeywords = mndokeywords.split('\n\n')
365
+ charges = np.full(len(mndokeywords), 0)
366
+ mults = np.full(len(mndokeywords), 1)
367
+ for i in range(len(mndokeywords)):
368
+ status = re.search('kharge=-?\+?\d+', mndokeywords[i])
369
+ if status:
370
+ charges[i] = int(status.group().split('=')[1])
371
+ status = re.search('imult=\d+', mndokeywords[i])
372
+ if status:
373
+ imult = int(status.group().split('=')[1])
374
+ if imult == 0:
375
+ mults[i] = 1
376
+ else:
377
+ mults[i] = imult
378
+ if split:
379
+ for i in range(len(mndokeywords)):
380
+ with open(f'mndokw_split{i+1}', 'w') as f:
381
+ f.write(mndokeywords[i])
382
+
383
+ return mndokeywords, charges, mults
384
+
385
+ def get_odm2_result(hesscalc):
386
+ hess = None
387
+ with open('fort.15', 'r') as f:
388
+ lines = f.readlines()
389
+ for i in range(len(lines)):
390
+ if 'NUMAT' in lines[i]:
391
+ nat = int(lines[i].strip().split()[-1])
392
+ if 'ENERGY' in lines[i]:
393
+ energy = lines[i+1].strip().split()[0]
394
+ energy = float(energy) / (27.21 * 23.061)
395
+ if 'CARTESIAN GRADIENT' in lines[i]:
396
+ grad = []
397
+ for j in range(nat):
398
+ grad.append(lines[i+j+1].strip().split()[-3:])
399
+ grad = np.array(grad).astype('float') / (27.21 * 23.061)
400
+ if hesscalc:
401
+ lhess = nat * nat * 9
402
+ fhess = open('fort.4', 'rb')
403
+ data = fhess.read()
404
+ dt = f'id{lhess}d'
405
+ dat_size = struct.calcsize(dt)
406
+ temp = struct.unpack(dt, data[:dat_size])
407
+ hess = np.array(temp[2:]).reshape(-1, nat*3) / (0.529167 * 0.529167)
408
+
409
+ return energy, grad, hess
410
+
411
+ def cal_shifts(numbers, sae):
412
+ shifts = []
413
+ for i in range(len(numbers)):
414
+ count = Counter(numbers[i])
415
+ ncount = [count[1], count[6], count[7], count[8]]
416
+ shift = np.dot(ncount, sae)
417
+ shifts.append(shift)
418
+ return shifts
419
+
420
+ def run_d4_calculation(dftd4bin, xyzfile, numbers, coordinates, charges, hesscalc):
421
+ number2element = {1:'H', 6:'C', 7:'N', 8:'O'}
422
+ shifts = []
423
+ d4_energies = []; d4_grads = []; d4_hesses = []
424
+ for i in range(len(numbers)):
425
+ number = numbers[i]
426
+ coordinate = coordinates[i]
427
+ charge = charges[i]
428
+ nat = len(numbers[i])
429
+ with open('coordinate', 'w') as f:
430
+ f.write(str(nat) + '\n\n')
431
+ for j in range(nat):
432
+ f.write('%s %15.12f %15.12f %15.12f\n'
433
+ % (number2element[number[j]], coordinate[j][0], coordinate[j][1], coordinate[j][2]))
434
+ if hesscalc:
435
+ os.system(dftd4bin + " coordinate -s --grad --hess --orca --json -f wb97x -c " + str(charge) + " > /dev/null 2>&1")
436
+ else:
437
+ os.system(dftd4bin + " coordinate -s --grad --orca --json -f wb97x -c " + str(charge) + " > /dev/null 2>&1")
438
+ with open('dftd4.json', 'r') as f:
439
+ d4_results = json.load(f)
440
+ #try:
441
+ # with open('dftd4.json', 'r') as f:
442
+ # d4_results = json.load(f)
443
+ #except:
444
+ # time.sleep(0.5)
445
+ # with open('dftd4.json', 'r') as f:
446
+ # d4_results = json.load(f)
447
+ d4_energy = np.array(d4_results['energy'])
448
+ d4_grad = np.array(d4_results['gradient']) / bohr2a
449
+ d4_grad = d4_grad.reshape(-1, 3)
450
+ d4_energies.append(d4_energy)
451
+ d4_grads.append(d4_grad)
452
+ if hesscalc:
453
+ d4_hess = np.array(d4_results['hessian']).reshape(-1, nat*3) / (bohr2a * bohr2a)
454
+ d4_hesses.append(d4_hess)
455
+ #os.system('rm -f coordinate dftd4.json')
456
+ os.system('rm -f coordinate dftd4.json')
457
+ return d4_energies, d4_grads, d4_hesses
458
+
459
+ def printHelp():
460
+ helpText = '''
461
+ !---------------------------------------------------------------------------!
462
+ ! AIQM1 usage and options !
463
+ !---------------------------------------------------------------------------!
464
+
465
+ Usage:
466
+ MLatom.py AIQM1@DFT* xyzfile=... [options]
467
+ MLatom.py AIQM1@DFT xyzfile=... [options]
468
+ MLatom.py AIQM1 xyzfile=... [options]
469
+
470
+ Options:
471
+ xyzfile=S file S with xyz coordinates
472
+ model_index=N 0-7 (by default the ensemble of 8 models are used)
473
+ YestFile=S file S with estimated Y values
474
+ YgradXYZestFile=S file S with estimated XYZ gradients
475
+ HessianestFile=S file S with estimated Hessians
476
+ mndokeywords=S read MNDO keyword from file S, separating by a blank line for each molecules
477
+ (it is required to set iop=-22, jop=-2 or 2, igeom=1, nsav15=3, immdp=-1)
478
+ '''
479
+ print(helpText)
480
+
481
+