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.
- {MLatom-2.0.5 → MLatom-2.1.2}/PKG-INFO +14 -9
- {MLatom-2.0.5 → MLatom-2.1.2}/README.md +13 -8
- {MLatom-2.0.5 → MLatom-2.1.2}/setup.py +1 -1
- MLatom-2.1.2/src/MLatom/AIQM1.py +481 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/ML_NEA.py +13 -2
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatom.py +33 -9
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/A_KRR.f90 +38 -9
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/A_KRR_kernel.f90 +24 -1
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/MLatomF.f90 +3 -3
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/MLmodel.f90 +41 -4
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/Makefile +1 -1
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/constants.f90 +1 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/dataset.f90 +1 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/optionsModule.f90 +44 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLtasks.py +481 -88
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/README +11 -10
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv0.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv1.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv2.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv3.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv4.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv5.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv6.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_cc_cv7.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv0.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv1.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv2.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv3.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv4.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv5.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv6.pt +0 -0
- MLatom-2.1.2/src/MLatom/aiqm1_model/aiqm1_dft_cv7.pt +0 -0
- MLatom-2.1.2/src/MLatom/calculator.py +54 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/doc.py +94 -24
- MLatom-2.1.2/src/MLatom/geomopt.py +506 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/header.py +31 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interface_MLatomF.py +15 -7
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/interface_DeePMDkit.py +84 -43
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/template.json +3 -3
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/GAP/interface_GAP.py +27 -13
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/PhysNet_train.py +25 -2
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/interface_PhysNet.py +28 -8
- MLatom-2.1.2/src/MLatom/interfaces/TorchANI/TorchANI_predict.py +208 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/TorchANI/TorchANI_train.py +48 -19
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/TorchANI/interface_TorchANI.py +96 -42
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/sGDML/interface_sGDML.py +6 -3
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/ref.json +12 -2
- MLatom-2.1.2/src/MLatom/thermo.py +179 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/PKG-INFO +14 -9
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/SOURCES.txt +21 -0
- MLatom-2.0.5/src/MLatom/interfaces/TorchANI/TorchANI_predict.py +0 -82
- {MLatom-2.0.5 → MLatom-2.1.2}/LICENSE.txt +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/setup.cfg +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/LICENSE.CC-BY-NC-ND-4.0 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/D_CoulombMatrix.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/D_rel2eq.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/MLatomFInfo.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/Makefile.intel +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/analyze.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/cs.cpp +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/mathUtils.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/molDescr.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/precision.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/sampling.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/statistics.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/stopper.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/strings.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/timing.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/MLatomF_src/types.f90 +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/args_class.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/cs.so +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/documentation/installation.txt +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/E_FCI_451.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/E_UHF_451.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/R_451.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/isubtrain.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/itest.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/itrain.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/ivalidate.dat +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/mlatom.inp +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/mlatom.saved +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/example/test.sh +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/DP_inference.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/DeePMDkit/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/GAP/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/PhysNet_predict.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/PhysNet/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/TorchANI/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/sGDML/__init__.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/interfaces/sGDML/sgdml_dataset_from_extxyz.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/mlatom_gui.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/shell_cmd.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/sliceData.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom/stopper.py +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/dependency_links.txt +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/entry_points.txt +0 -0
- {MLatom-2.0.5 → MLatom-2.1.2}/src/MLatom.egg-info/requires.txt +0 -0
- {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.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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.
|
|
130
|
+
Version 2.1.2
|
|
126
131
|
http://mlatom.com/
|
|
127
132
|
|
|
128
|
-
Copyright (c) 2013-
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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.
|
|
112
|
+
Version 2.1.2
|
|
108
113
|
http://mlatom.com/
|
|
109
114
|
|
|
110
|
-
Copyright (c) 2013-
|
|
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.
|
|
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.
|
|
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
|
+
|