stjames 0.0.40__py3-none-any.whl → 0.0.42__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.
Potentially problematic release.
This version of stjames might be problematic. Click here for more details.
- stjames/__init__.py +3 -0
- stjames/atom.py +66 -0
- stjames/base.py +13 -13
- stjames/basis_set.py +3 -7
- stjames/calculation.py +2 -0
- stjames/constraint.py +22 -2
- stjames/data/__init__.py +1 -0
- stjames/data/bragg_radii.json +1 -0
- stjames/data/elements.py +27 -0
- stjames/data/isotopes.json +1 -0
- stjames/data/nist_isotopes.json +1 -0
- stjames/data/read_nist_isotopes.py +116 -0
- stjames/data/symbol_element.json +1 -0
- stjames/method.py +34 -1
- stjames/molecule.py +113 -15
- stjames/opt_settings.py +10 -5
- stjames/periodic_cell.py +34 -0
- stjames/settings.py +25 -38
- stjames/solvent.py +1 -0
- stjames/task.py +1 -0
- stjames/types.py +8 -0
- stjames/workflows/__init__.py +6 -0
- stjames/workflows/admet.py +7 -0
- stjames/workflows/basic_calculation.py +9 -0
- stjames/workflows/bde.py +269 -0
- stjames/workflows/descriptors.py +2 -1
- stjames/workflows/fukui.py +6 -7
- stjames/workflows/molecular_dynamics.py +60 -0
- stjames/workflows/multistage_opt.py +261 -0
- stjames/workflows/redox_potential.py +9 -8
- stjames/workflows/scan.py +6 -6
- stjames/workflows/spin_states.py +144 -0
- stjames/workflows/workflow.py +31 -1
- {stjames-0.0.40.dist-info → stjames-0.0.42.dist-info}/METADATA +3 -3
- stjames-0.0.42.dist-info/RECORD +52 -0
- {stjames-0.0.40.dist-info → stjames-0.0.42.dist-info}/WHEEL +1 -1
- stjames-0.0.40.dist-info/RECORD +0 -36
- {stjames-0.0.40.dist-info → stjames-0.0.42.dist-info}/LICENSE +0 -0
- {stjames-0.0.40.dist-info → stjames-0.0.42.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
from typing import Self, Sequence
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field, model_validator
|
|
4
|
+
|
|
5
|
+
from ..constraint import Constraint
|
|
6
|
+
from ..method import XTB_METHODS, Method
|
|
7
|
+
from ..mode import Mode
|
|
8
|
+
from ..opt_settings import OptimizationSettings
|
|
9
|
+
from ..settings import Settings
|
|
10
|
+
from ..solvent import Solvent, SolventSettings
|
|
11
|
+
from ..task import Task
|
|
12
|
+
from ..types import UUID
|
|
13
|
+
from .workflow import Workflow
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MultiStageOptSettings(BaseModel):
|
|
17
|
+
"""
|
|
18
|
+
Settings for multi-stage optimizations.
|
|
19
|
+
|
|
20
|
+
RECKLESS
|
|
21
|
+
GFN2-xTB//GFN-FF (no pre-opt)
|
|
22
|
+
RAPID *default
|
|
23
|
+
r²SCAN-3c//GFN2-xTB with GFN0-xTB pre-opt (off by default)
|
|
24
|
+
CAREFUL
|
|
25
|
+
wB97X-3c//B97-3c with GFN2-xTB pre-opt
|
|
26
|
+
METICULOUS
|
|
27
|
+
wB97M-D3BJ/def2-TZVPPD//wB97X-3c//B97-3c with GFN2-xTB pre-opt
|
|
28
|
+
|
|
29
|
+
Notes:
|
|
30
|
+
- No solvent in pre-opt
|
|
31
|
+
- If solvent: xTB singlepoints use CPCMX, xTB optimizations use ALBP, all else use CPCM
|
|
32
|
+
- Allows a single point to be called with no optimization
|
|
33
|
+
|
|
34
|
+
:param mode: Mode for settings
|
|
35
|
+
:param optimization_settings: list of opt settings to apply successively
|
|
36
|
+
:param singlepoint_settings: final single point settings
|
|
37
|
+
:param solvent: solvent to use
|
|
38
|
+
:param xtb_preopt: pre-optimize with xtb (sets based on mode when None)
|
|
39
|
+
:param constraints: constraints for optimization
|
|
40
|
+
:param transition_state: whether this is a transition state
|
|
41
|
+
:param frequencies: whether to calculate frequencies
|
|
42
|
+
|
|
43
|
+
>>> msos = MultiStageOptSettings(mode=Mode.RAPID, solvent="water")
|
|
44
|
+
>>> msos
|
|
45
|
+
<MultiStageOptSettings RAPID>
|
|
46
|
+
>>> msos.level_of_theory
|
|
47
|
+
'r2scan_3c/cpcm(water)//gfn2_xtb/alpb(water)'
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
mode: Mode
|
|
51
|
+
optimization_settings: Sequence[Settings] = tuple()
|
|
52
|
+
singlepoint_settings: Settings | None = None
|
|
53
|
+
solvent: Solvent | None = None
|
|
54
|
+
xtb_preopt: bool | None = None
|
|
55
|
+
constraints: Sequence[Constraint] = tuple()
|
|
56
|
+
transition_state: bool = False
|
|
57
|
+
frequencies: bool = True
|
|
58
|
+
|
|
59
|
+
def __str__(self) -> str:
|
|
60
|
+
return repr(self)
|
|
61
|
+
|
|
62
|
+
def __repr__(self) -> str:
|
|
63
|
+
"""
|
|
64
|
+
String representation of the settings.
|
|
65
|
+
|
|
66
|
+
>>> print(MultiStageOptSettings(mode=Mode.RAPID, solvent="water"))
|
|
67
|
+
<MultiStageOptSettings RAPID>
|
|
68
|
+
"""
|
|
69
|
+
if self.mode != Mode.MANUAL:
|
|
70
|
+
return f"<{type(self).__name__} {self.mode.name}>"
|
|
71
|
+
|
|
72
|
+
return f"<{type(self).__name__} {self.level_of_theory}>"
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def level_of_theory(self) -> str:
|
|
76
|
+
"""
|
|
77
|
+
Returns the level of theory for the workflow.
|
|
78
|
+
|
|
79
|
+
>>> msos = MultiStageOptSettings(mode=Mode.RAPID, solvent="hexane")
|
|
80
|
+
>>> msos.level_of_theory
|
|
81
|
+
'r2scan_3c/cpcm(hexane)//gfn2_xtb/alpb(hexane)'
|
|
82
|
+
"""
|
|
83
|
+
methods = [self.singlepoint_settings] if self.singlepoint_settings else []
|
|
84
|
+
methods += reversed(self.optimization_settings)
|
|
85
|
+
|
|
86
|
+
return "//".join(m.level_of_theory for m in methods)
|
|
87
|
+
|
|
88
|
+
@model_validator(mode="after")
|
|
89
|
+
def set_mode_and_settings(self) -> Self:
|
|
90
|
+
"""Check mode and settings are properly specified, and assign settings based on mode."""
|
|
91
|
+
opt_or_sp = bool(self.optimization_settings) or bool(self.singlepoint_settings)
|
|
92
|
+
|
|
93
|
+
if self.mode == Mode.AUTO:
|
|
94
|
+
self.mode = Mode.RAPID
|
|
95
|
+
|
|
96
|
+
match (self.mode, opt_or_sp):
|
|
97
|
+
case (Mode.DEBUG, _):
|
|
98
|
+
raise NotImplementedError("Unsupported mode: DEBUG")
|
|
99
|
+
|
|
100
|
+
case (Mode.MANUAL, False):
|
|
101
|
+
raise ValueError("Must specify at least one of optimization_settings or singlepoint_settings with MANUAL mode")
|
|
102
|
+
case (Mode.MANUAL, True):
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
case (mode, True):
|
|
106
|
+
raise ValueError(f"Cannot specify optimization_settings or singlepoint_settings with {mode=}")
|
|
107
|
+
|
|
108
|
+
case (mode, False):
|
|
109
|
+
self._assign_settings_by_mode(mode)
|
|
110
|
+
|
|
111
|
+
return self
|
|
112
|
+
|
|
113
|
+
def _assign_settings_by_mode(self, mode: Mode) -> None:
|
|
114
|
+
"""
|
|
115
|
+
Construct the settings based on the Mode.
|
|
116
|
+
|
|
117
|
+
:param mode: Mode to use
|
|
118
|
+
"""
|
|
119
|
+
opt_settings = OptimizationSettings(constraints=self.constraints, transition_state=self.transition_state)
|
|
120
|
+
|
|
121
|
+
# No solvent in pre-opt
|
|
122
|
+
OPT = [Task.OPTIMIZE if not self.transition_state else Task.OPTIMIZE_TS]
|
|
123
|
+
gfn0_pre_opt = [Settings(method=Method.GFN0_XTB, tasks=OPT, mode=Mode.RAPID, opt_settings=opt_settings)]
|
|
124
|
+
gfn2_pre_opt = [Settings(method=Method.GFN2_XTB, tasks=OPT, mode=Mode.RAPID, opt_settings=opt_settings)]
|
|
125
|
+
|
|
126
|
+
def opt(method: Method, basis_set: str | None = None, solvent: Solvent | None = None, freq: bool = False) -> Settings:
|
|
127
|
+
"""Generates optimization settings."""
|
|
128
|
+
model = "alpb" if method in XTB_METHODS else "cpcm"
|
|
129
|
+
|
|
130
|
+
return Settings(
|
|
131
|
+
method=method,
|
|
132
|
+
basis_set=basis_set,
|
|
133
|
+
tasks=OPT + [Task.FREQUENCIES] * freq,
|
|
134
|
+
solvent_settings=SolventSettings(solvent=solvent, model=model) if solvent else None,
|
|
135
|
+
opt_settings=opt_settings,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
def sp(method: Method, basis_set: str | None = None, solvent: Solvent | None = None) -> Settings:
|
|
139
|
+
"""Generate singlepoint settings."""
|
|
140
|
+
model = "cpcmx" if method in XTB_METHODS else "cpcm"
|
|
141
|
+
|
|
142
|
+
return Settings(
|
|
143
|
+
method=method,
|
|
144
|
+
basis_set=basis_set,
|
|
145
|
+
solvent_settings=SolventSettings(solvent=solvent, model=model) if solvent else None,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
match mode:
|
|
149
|
+
case Mode.RECKLESS:
|
|
150
|
+
self.xtb_preopt = False
|
|
151
|
+
self.optimization_settings = [opt(Method.GFN_FF, solvent=self.solvent, freq=self.frequencies)]
|
|
152
|
+
self.singlepoint_settings = sp(Method.GFN2_XTB, solvent=self.solvent)
|
|
153
|
+
|
|
154
|
+
case Mode.RAPID:
|
|
155
|
+
self.xtb_preopt = bool(self.xtb_preopt)
|
|
156
|
+
self.optimization_settings = [
|
|
157
|
+
*gfn0_pre_opt * self.xtb_preopt,
|
|
158
|
+
opt(Method.GFN2_XTB, solvent=self.solvent, freq=self.frequencies),
|
|
159
|
+
]
|
|
160
|
+
self.singlepoint_settings = sp(Method.R2SCAN3C, solvent=self.solvent)
|
|
161
|
+
|
|
162
|
+
case Mode.CAREFUL:
|
|
163
|
+
self.xtb_preopt = (self.xtb_preopt is None) or self.xtb_preopt
|
|
164
|
+
self.optimization_settings = [
|
|
165
|
+
*gfn2_pre_opt * self.xtb_preopt,
|
|
166
|
+
opt(Method.B973C, solvent=self.solvent, freq=self.frequencies),
|
|
167
|
+
]
|
|
168
|
+
self.singlepoint_settings = sp(Method.WB97X3C, solvent=self.solvent)
|
|
169
|
+
|
|
170
|
+
case Mode.METICULOUS:
|
|
171
|
+
self.xtb_preopt = (self.xtb_preopt is None) or self.xtb_preopt
|
|
172
|
+
self.optimization_settings = [
|
|
173
|
+
*gfn2_pre_opt * self.xtb_preopt,
|
|
174
|
+
opt(Method.B973C, solvent=self.solvent),
|
|
175
|
+
opt(Method.WB97X3C, solvent=self.solvent, freq=self.frequencies),
|
|
176
|
+
]
|
|
177
|
+
self.singlepoint_settings = sp(Method.WB97MD3BJ, "def2-TZVPPD", solvent=self.solvent)
|
|
178
|
+
|
|
179
|
+
case mode:
|
|
180
|
+
raise NotImplementedError(f"Cannot assign settings for {mode=}")
|
|
181
|
+
|
|
182
|
+
assert self.xtb_preopt is not None
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class MultiStageOptWorkflow(Workflow, MultiStageOptSettings):
|
|
186
|
+
"""
|
|
187
|
+
Workflow for multi-stage optimizations.
|
|
188
|
+
|
|
189
|
+
Inherited
|
|
190
|
+
:param initial_molecule: Molecule of interest
|
|
191
|
+
:param mode: Mode for workflow
|
|
192
|
+
:param optimization_settings: list of opt settings to apply successively
|
|
193
|
+
:param singlepoint_settings: final single point settings
|
|
194
|
+
:param solvent: solvent to use
|
|
195
|
+
:param xtb_preopt: pre-optimize with xtb (sets based on mode when None)
|
|
196
|
+
:param constraints: constraints for optimization
|
|
197
|
+
:param transition_state: whether this is a transition state
|
|
198
|
+
:param frequencies: whether to calculate frequencies
|
|
199
|
+
|
|
200
|
+
Populated while running
|
|
201
|
+
:param calculations: list of calculation UUIDs
|
|
202
|
+
|
|
203
|
+
>>> from stjames.molecule import Atom, Molecule
|
|
204
|
+
>>> He = Molecule(charge=0, multiplicity=1, atoms=[Atom(atomic_number=2, position=[0, 0, 0])])
|
|
205
|
+
>>> msow = MultiStageOptWorkflow(initial_molecule=He, mode=Mode.RAPID, solvent="water")
|
|
206
|
+
>>> msow
|
|
207
|
+
<MultiStageOptWorkflow RAPID>
|
|
208
|
+
>>> msow.level_of_theory
|
|
209
|
+
'r2scan_3c/cpcm(water)//gfn2_xtb/alpb(water)'
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
# Populated while running the workflow
|
|
213
|
+
calculations: list[UUID | None] = Field(default_factory=list)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# the id of a mutable object may change, thus using object()
|
|
217
|
+
_sentinel_msos = object()
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class MultiStageOptMixin(BaseModel):
|
|
221
|
+
"""
|
|
222
|
+
Mixin for workflows that use MultiStageOptSettings.
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
mso_mode: Mode
|
|
226
|
+
# Need to use a sentinel object to make both mypy and pydantic happy
|
|
227
|
+
multistage_opt_settings: MultiStageOptSettings = _sentinel_msos # type: ignore [assignment]
|
|
228
|
+
solvent: Solvent | None = None
|
|
229
|
+
xtb_preopt: bool | None = None
|
|
230
|
+
constraints: Sequence[Constraint] = tuple()
|
|
231
|
+
transition_state: bool = False
|
|
232
|
+
frequencies: bool = True
|
|
233
|
+
|
|
234
|
+
@model_validator(mode="after")
|
|
235
|
+
def set_mso_settings(self) -> Self:
|
|
236
|
+
if self.mso_mode == Mode.AUTO:
|
|
237
|
+
self.mso_mode = Mode.RAPID
|
|
238
|
+
|
|
239
|
+
match self.mso_mode, self.multistage_opt_settings:
|
|
240
|
+
case (Mode.DEBUG, _):
|
|
241
|
+
raise NotImplementedError("Unsupported mode: DEBUG")
|
|
242
|
+
|
|
243
|
+
case (Mode.MANUAL, msos) if msos is _sentinel_msos:
|
|
244
|
+
raise ValueError("Must specify multistage_opt_settings with MANUAL mode")
|
|
245
|
+
case (Mode.MANUAL, _):
|
|
246
|
+
pass
|
|
247
|
+
|
|
248
|
+
case (mso_mode, msos) if msos is not _sentinel_msos:
|
|
249
|
+
raise ValueError(f"Cannot specify multistage_opt_settings with {mso_mode=}, {msos=}")
|
|
250
|
+
|
|
251
|
+
case (mso_mode, _):
|
|
252
|
+
self.multistage_opt_settings = MultiStageOptSettings(
|
|
253
|
+
mode=mso_mode,
|
|
254
|
+
solvent=self.solvent,
|
|
255
|
+
xtb_preopt=self.xtb_preopt,
|
|
256
|
+
constraints=self.constraints,
|
|
257
|
+
transition_state=self.transition_state,
|
|
258
|
+
frequencies=self.frequencies,
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
return self
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
from ..mode import Mode
|
|
4
4
|
from ..solvent import Solvent
|
|
5
|
+
from ..types import UUID
|
|
5
6
|
from .workflow import Workflow
|
|
6
7
|
|
|
7
8
|
|
|
@@ -12,16 +13,16 @@ class RedoxPotentialWorkflow(Workflow):
|
|
|
12
13
|
oxidation: bool = True
|
|
13
14
|
|
|
14
15
|
# legacy values - remove in future release!
|
|
15
|
-
redox_type:
|
|
16
|
-
redox_potential:
|
|
16
|
+
redox_type: UUID | None = None
|
|
17
|
+
redox_potential: float | None = None
|
|
17
18
|
|
|
18
19
|
# uuids
|
|
19
|
-
neutral_molecule:
|
|
20
|
-
anion_molecule:
|
|
21
|
-
cation_molecule:
|
|
20
|
+
neutral_molecule: UUID | None = None
|
|
21
|
+
anion_molecule: UUID | None = None
|
|
22
|
+
cation_molecule: UUID | None = None
|
|
22
23
|
|
|
23
|
-
reduction_potential:
|
|
24
|
-
oxidation_potential:
|
|
24
|
+
reduction_potential: float | None = None
|
|
25
|
+
oxidation_potential: float | None = None
|
|
25
26
|
|
|
26
27
|
def model_post_init(self, __context: Any) -> None:
|
|
27
28
|
"""Keep back-compatible with old schema."""
|
stjames/workflows/scan.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
import numpy as np
|
|
2
|
+
from numpy.typing import NDArray
|
|
4
3
|
|
|
5
4
|
from ..base import Base
|
|
6
5
|
from ..molecule import Molecule
|
|
7
6
|
from ..settings import Settings
|
|
7
|
+
from ..types import UUID
|
|
8
8
|
from .workflow import Workflow
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class ScanPoint(Base):
|
|
12
12
|
index: int
|
|
13
13
|
molecule: Molecule
|
|
14
|
-
energy:
|
|
15
|
-
uuid:
|
|
14
|
+
energy: float | None = None
|
|
15
|
+
uuid: UUID | None = None
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class ScanSettings(Base):
|
|
@@ -22,7 +22,7 @@ class ScanSettings(Base):
|
|
|
22
22
|
stop: float
|
|
23
23
|
num: int
|
|
24
24
|
|
|
25
|
-
def vals(self) -> np.
|
|
25
|
+
def vals(self) -> NDArray[np.float64]:
|
|
26
26
|
return np.linspace(self.start, self.stop, self.num)
|
|
27
27
|
|
|
28
28
|
class Config:
|
|
@@ -35,4 +35,4 @@ class ScanWorkflow(Workflow):
|
|
|
35
35
|
calc_engine: str
|
|
36
36
|
|
|
37
37
|
# uuids of scan points
|
|
38
|
-
scan_points: list[
|
|
38
|
+
scan_points: list[UUID | None] = []
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field, PositiveInt, field_validator, model_validator
|
|
4
|
+
|
|
5
|
+
from ..mode import Mode
|
|
6
|
+
from ..types import UUID
|
|
7
|
+
from .multistage_opt import MultiStageOptMixin
|
|
8
|
+
from .workflow import Workflow
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SpinState(BaseModel):
|
|
12
|
+
"""
|
|
13
|
+
The result of a SpinState calculation.
|
|
14
|
+
|
|
15
|
+
:param multiplicity: multiplicity of the SpinState
|
|
16
|
+
:param energy: energy of the optimized Molecule
|
|
17
|
+
:param calculation: the UUIDs of the Calculations that produced this SpinState
|
|
18
|
+
|
|
19
|
+
>>> from stjames.molecule import Atom, Molecule
|
|
20
|
+
>>> He = Molecule(charge=0, multiplicity=1, atoms=[Atom(atomic_number=2, position=[0, 0, 0])])
|
|
21
|
+
>>> SpinState(multiplicity=3, energy=-13.4291, calculation=['8a031a27-30d2-4ac7-8ade-efae9e9fc94a'])
|
|
22
|
+
<SpinState 3 -13.429>
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
multiplicity: PositiveInt
|
|
26
|
+
energy: float
|
|
27
|
+
calculation: list[UUID | None]
|
|
28
|
+
|
|
29
|
+
def __str__(self) -> str:
|
|
30
|
+
return repr(self)
|
|
31
|
+
|
|
32
|
+
def __repr__(self) -> str:
|
|
33
|
+
return f"<{type(self).__name__} {self.multiplicity} {self.energy:.3f}>"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_sentinel_mso_mode = object()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class SpinStatesWorkflow(Workflow, MultiStageOptMixin):
|
|
40
|
+
"""
|
|
41
|
+
Workflow for computing spin states of molecules.
|
|
42
|
+
|
|
43
|
+
Uses the modes from MultiStageOptSettings.
|
|
44
|
+
|
|
45
|
+
Influenced by:
|
|
46
|
+
[Performance of Quantum Chemistry Methods for Benchmark Set of Spin–State
|
|
47
|
+
Energetics Derived from Experimental Data of 17 Transition Metal Complexes
|
|
48
|
+
(SSE17)](https://chemrxiv.org/engage/chemrxiv/article-details/66a8b15cc9c6a5c07a792487)
|
|
49
|
+
|
|
50
|
+
Inherited
|
|
51
|
+
:param initial_molecule: Molecule of interest
|
|
52
|
+
:param multistage_opt_settings: set by mode unless mode=MANUAL (ignores additional settings if set)
|
|
53
|
+
:param solvent: solvent to use
|
|
54
|
+
:param xtb_preopt: pre-optimize with xtb (sets based on mode when None)
|
|
55
|
+
:param constraints: constraints to add
|
|
56
|
+
:param transition_state: whether this is a transition state
|
|
57
|
+
:param frequencies: whether to calculate frequencies
|
|
58
|
+
|
|
59
|
+
Overridden:
|
|
60
|
+
:param mso_mode: Mode for MultiStageOptSettings
|
|
61
|
+
|
|
62
|
+
New:
|
|
63
|
+
:param mode: Mode for workflow
|
|
64
|
+
:param states: multiplicities of the spin state targetted
|
|
65
|
+
:param spin_states: resulting spin states data
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
>>> from stjames.molecule import Atom, Molecule
|
|
69
|
+
>>> He = Molecule(charge=0, multiplicity=1, atoms=[Atom(atomic_number=2, position=[0, 0, 0])])
|
|
70
|
+
>>> ss = SpinStatesWorkflow(initial_molecule=He, states=[1, 3, 5], mode=Mode.RAPID, solvent="water")
|
|
71
|
+
>>> str(ss)
|
|
72
|
+
'<SpinStatesWorkflow [1, 3, 5] RAPID>'
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
mode: Mode
|
|
76
|
+
mso_mode: Mode = _sentinel_mso_mode # type: ignore [assignment]
|
|
77
|
+
states: list[PositiveInt]
|
|
78
|
+
|
|
79
|
+
# Results
|
|
80
|
+
spin_states: list[SpinState] = Field(default_factory=list)
|
|
81
|
+
|
|
82
|
+
def __str__(self) -> str:
|
|
83
|
+
return repr(self)
|
|
84
|
+
|
|
85
|
+
def __repr__(self) -> str:
|
|
86
|
+
if self.mode != Mode.MANUAL:
|
|
87
|
+
return f"<{type(self).__name__} {self.states} {self.mode.name}>"
|
|
88
|
+
|
|
89
|
+
return f"<{type(self).__name__} {self.states} {self.level_of_theory}>"
|
|
90
|
+
|
|
91
|
+
def __len__(self) -> int:
|
|
92
|
+
return len(self.states)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def level_of_theory(self) -> str:
|
|
96
|
+
return self.multistage_opt_settings.level_of_theory
|
|
97
|
+
|
|
98
|
+
@field_validator("states")
|
|
99
|
+
@classmethod
|
|
100
|
+
def validate_states(cls, states: list[PositiveInt]) -> list[PositiveInt]:
|
|
101
|
+
"""Confirm that all spin states are valid."""
|
|
102
|
+
if not states:
|
|
103
|
+
raise ValueError("Expected at least one spin state.")
|
|
104
|
+
|
|
105
|
+
if any((states[0] - mult) % 2 for mult in states):
|
|
106
|
+
raise ValueError(f"Inconsistent multiplicities found: {states}")
|
|
107
|
+
|
|
108
|
+
return states
|
|
109
|
+
|
|
110
|
+
def str_results(self) -> str:
|
|
111
|
+
return "SpinStatesResults\n" + "\n".join(f" {ss.multiplicity}: {ss.energy:>5.2f}" for ss in self.spin_states)
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def energies(self) -> list[float]:
|
|
115
|
+
return [ss.energy for ss in self.spin_states]
|
|
116
|
+
|
|
117
|
+
@model_validator(mode="before")
|
|
118
|
+
@classmethod
|
|
119
|
+
def set_mso_mode(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
120
|
+
"""Set the MultiStageOptSettings mode to match current SpinStates mode."""
|
|
121
|
+
values["mso_mode"] = values["mode"]
|
|
122
|
+
return values
|
|
123
|
+
|
|
124
|
+
@field_validator("mode")
|
|
125
|
+
@classmethod
|
|
126
|
+
def set_mode_auto(cls, mode: Mode) -> Mode:
|
|
127
|
+
if mode == Mode.AUTO:
|
|
128
|
+
return Mode.RAPID
|
|
129
|
+
|
|
130
|
+
return mode
|
|
131
|
+
|
|
132
|
+
@field_validator("spin_states")
|
|
133
|
+
@classmethod
|
|
134
|
+
def validate_spin_states(cls, spin_states: list[SpinState]) -> list[SpinState]:
|
|
135
|
+
"""Ensure that all spin states have consistent results."""
|
|
136
|
+
mults = [ss.multiplicity for ss in spin_states]
|
|
137
|
+
|
|
138
|
+
if len(mults) != len(set(mults)):
|
|
139
|
+
raise ValueError(f"Duplicate multiplicities found: {mults}")
|
|
140
|
+
|
|
141
|
+
if any((mults[0] - mult) % 2 for mult in mults[1:]):
|
|
142
|
+
raise ValueError(f"Inconsistent multiplicities found: {mults}")
|
|
143
|
+
|
|
144
|
+
return spin_states
|
stjames/workflows/workflow.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
from pydantic import BaseModel, ConfigDict
|
|
2
|
+
|
|
1
3
|
from ..base import Base
|
|
2
4
|
from ..message import Message
|
|
5
|
+
from ..mode import Mode
|
|
3
6
|
from ..molecule import Molecule
|
|
7
|
+
from ..types import UUID
|
|
4
8
|
|
|
5
9
|
|
|
6
10
|
class Workflow(Base):
|
|
@@ -13,4 +17,30 @@ class Workflow(Base):
|
|
|
13
17
|
class DBCalculation(Base):
|
|
14
18
|
"""Encodes a calculation that's in the database. This isn't terribly useful by itself."""
|
|
15
19
|
|
|
16
|
-
uuid:
|
|
20
|
+
uuid: UUID
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WorkflowInput(BaseModel):
|
|
24
|
+
"""
|
|
25
|
+
Input for a workflow.
|
|
26
|
+
|
|
27
|
+
:param initial_molecule: Molecule of interest
|
|
28
|
+
:param mode: Mode for workflow
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
model_config = ConfigDict(extra="forbid")
|
|
32
|
+
|
|
33
|
+
initial_molecule: Molecule
|
|
34
|
+
mode: Mode
|
|
35
|
+
|
|
36
|
+
def __str__(self) -> str:
|
|
37
|
+
return repr(self)
|
|
38
|
+
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
return f"<{type(self).__name__} {self.mode.name}>"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class WorkflowResults(BaseModel):
|
|
44
|
+
"""Results of a workflow."""
|
|
45
|
+
|
|
46
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: stjames
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.42
|
|
4
4
|
Summary: standardized JSON atom/molecule encoding scheme
|
|
5
5
|
Author-email: Corin Wagen <corin@rowansci.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/rowansci/stjames
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/rowansci/stjames/issues
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: pydantic >=2.4
|
|
@@ -27,7 +27,7 @@ This is not intended to be run as a standalone library: it's basically just a bi
|
|
|
27
27
|
|
|
28
28
|
## Installation
|
|
29
29
|
|
|
30
|
-
To install, ensure you have Python 3.
|
|
30
|
+
To install, ensure you have Python 3.11 or newer. Then run:
|
|
31
31
|
|
|
32
32
|
```
|
|
33
33
|
pip install stjames
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
stjames/__init__.py,sha256=LkWCylP4VeXyQL0iu5w6yeYK1UHjcUH55hwWXTy4mQQ,576
|
|
2
|
+
stjames/_deprecated_solvent_settings.py,sha256=gj5j9p3zakIwSTK5_ndqBXJx--IzjZNxZ75z-wipLOo,450
|
|
3
|
+
stjames/atom.py,sha256=2NZ-tyWk6uPrn_rsANFFultNHS0CvgYYXwj8rud991M,2056
|
|
4
|
+
stjames/base.py,sha256=9PvUjBeVSkmA3TaruaB0uvjFMbWYTGKXECISNGAj_AU,1201
|
|
5
|
+
stjames/basis_set.py,sha256=wI3M2q9uPf9jhKpAi4E2DrsyKzloDGLRjAlk7krdYgc,949
|
|
6
|
+
stjames/calculation.py,sha256=O2LwwQ_cOLmDOGXTHA9J71YbUZXigUSbvbLA-fSVm3w,915
|
|
7
|
+
stjames/constraint.py,sha256=IQsQPGbjaoWXZkAOPPBH0_-EGtWwGkkHBhuPg53v5-M,890
|
|
8
|
+
stjames/correction.py,sha256=_pNG3qSylfx0iyUxqwx9HPU0m032YwP6wSPCjbJrD94,358
|
|
9
|
+
stjames/diis_settings.py,sha256=QHc7L-hktkbOWBYr29byTdqL8lWJzKJiY9XW8ha4Qzo,552
|
|
10
|
+
stjames/grid_settings.py,sha256=WrSNGc-8_f87YBZYt9Hh7RbhM4MweADoVzwBMcSqcsE,640
|
|
11
|
+
stjames/int_settings.py,sha256=5HXp8opt5ZyY1UpmfaK7NVloWVLM5jkG0elEEqpVLUo,896
|
|
12
|
+
stjames/message.py,sha256=Rq6QqmHZKecWxYH8fVyXmuoCCPZv8YinvgykSeorXSU,216
|
|
13
|
+
stjames/method.py,sha256=xnfphxyiWZotxQcmgvpFMJDmGEM2B-_5cbPkgYZBIws,1245
|
|
14
|
+
stjames/mode.py,sha256=xw46Cc7f3eTS8i35qECi-8DocAlANhayK3w4akD4HBU,496
|
|
15
|
+
stjames/molecule.py,sha256=XJdfEJndl4DqY_mg5scWH9xWQU8gNcXN74Qb4n2TN1c,6798
|
|
16
|
+
stjames/opt_settings.py,sha256=gxXGtjy9l-Q5Wen9eO6T6HHRCuS8rfOofdVQIJj0JcI,550
|
|
17
|
+
stjames/periodic_cell.py,sha256=JDCyynpamggTNi_HnTnnotRbeSMBfYc-srhD-IwUnrg,996
|
|
18
|
+
stjames/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
stjames/scf_settings.py,sha256=xMMCQ0hVB4nNFSiWesNQZUa_aLsozSZGYWweAPPDGBg,2356
|
|
20
|
+
stjames/settings.py,sha256=-MSVrfRcBz6O7aRZA-xTtEfJHRJ8BRxc6Bg9wad2DSY,8786
|
|
21
|
+
stjames/solvent.py,sha256=u037tmu-9oa21s-WEDZ7VC7nuNVjkqR2ML4JWjWSME4,1158
|
|
22
|
+
stjames/status.py,sha256=wTKNcNxStoEHrxxgr_zTyN90NITa3rxMQZzOgrCifEw,332
|
|
23
|
+
stjames/task.py,sha256=OLINRqe66o7t8arffilwmggrF_7TH0L79u6DhGruxV8,329
|
|
24
|
+
stjames/thermochem_settings.py,sha256=ZTLz31v8Ltutde5Nfm0vH5YahWjcfFWfr_R856KffxE,517
|
|
25
|
+
stjames/types.py,sha256=2FBtEwpaqBIgN7fmVRORJfkv-am0Lssr8e7ho7Fui8w,206
|
|
26
|
+
stjames/data/__init__.py,sha256=O59Ksp7AIqwOELCWymfCx7YeBzwNOGCMlGQi7tNLqiE,24
|
|
27
|
+
stjames/data/bragg_radii.json,sha256=hhbn-xyZNSdmnULIjN2Cvq-_BGIZIqG243Ls_mey61w,1350
|
|
28
|
+
stjames/data/elements.py,sha256=9BW01LZlyJ0H5s7Q26vUmjZIST41fwOYYrGvmPd7q0w,858
|
|
29
|
+
stjames/data/isotopes.json,sha256=5ba8QnLrHD_Ypv2xekv2cIRwYrX3MQ19-1FOFtt0RuU,8357
|
|
30
|
+
stjames/data/nist_isotopes.json,sha256=d5DNk1dX0iB1waEYIRR6JMHuA7AuYwSBEgBvb4EKyhM,14300
|
|
31
|
+
stjames/data/read_nist_isotopes.py,sha256=y10FNjW43QpC45qib7VHsIghEwT7GG5rsNwHdc9osRI,3309
|
|
32
|
+
stjames/data/symbol_element.json,sha256=vl_buFusTqBd-muYQtMLtTDLy2OtBI6KkBeqkaWRQrg,1186
|
|
33
|
+
stjames/workflows/__init__.py,sha256=TQwTrX8hzUKBcCV4C05IvePjnEotsAWTbXv4-b8zDRk,331
|
|
34
|
+
stjames/workflows/admet.py,sha256=V8noO0Eb7h2bDFSnj6Pxv4ILm0lGxyVRCi13hE0zmEQ,149
|
|
35
|
+
stjames/workflows/basic_calculation.py,sha256=q48bpab7ZqmRTR4PsGC6bWkuxqkVdJRM8gysevTYXP0,212
|
|
36
|
+
stjames/workflows/bde.py,sha256=rboqtrV1DNwq7MKPht9g5d7ahHxaqGN-PvXlTjGor4M,9831
|
|
37
|
+
stjames/workflows/conformer.py,sha256=YYwL3l7OaVeea4N9-ihghwa_ieKY6hia9LNbiTraMb0,2732
|
|
38
|
+
stjames/workflows/descriptors.py,sha256=jQ3RuMi7xk799JZ_AL1ARL3yQfWLG03L_VVsK4KIMeY,281
|
|
39
|
+
stjames/workflows/fukui.py,sha256=F5tw5jTqBimo_GiXuThhRpoxauZE5YadZjObLFDCba8,348
|
|
40
|
+
stjames/workflows/molecular_dynamics.py,sha256=ImZN9G1xolkUSXyv0d_KKPtCIPG9uXdkVyJuFdtOToU,1917
|
|
41
|
+
stjames/workflows/multistage_opt.py,sha256=YL-lbpJs8AB5vOERonb7-Q69SIM4feuB9mUtbepYIHA,10040
|
|
42
|
+
stjames/workflows/pka.py,sha256=zpR90Yv2L-D56o2mGArM8027DWpnFFnay31UR9Xh5Nc,774
|
|
43
|
+
stjames/workflows/redox_potential.py,sha256=u6QThnqheJp6EDuWiJApJEh-fp0TKGfSyKfa8ykf85g,1211
|
|
44
|
+
stjames/workflows/scan.py,sha256=hL4Hco3Ns0dntjh2G2HhhWmED1mbt0gA_hsglPQ5Vjg,814
|
|
45
|
+
stjames/workflows/spin_states.py,sha256=hzGbYfG4KGYYQPV4cF0ufCndDMoIVnZt2ZZt7LqvJgc,4854
|
|
46
|
+
stjames/workflows/tautomer.py,sha256=kZSCHo2Q7LzqtQjF_WyyxjECkndG49T9QOM12hsUkx8,421
|
|
47
|
+
stjames/workflows/workflow.py,sha256=t5Yz-d5WgSQEiHbiZfc4NQ653mEnydiGZ-lEkkPYAKw,994
|
|
48
|
+
stjames-0.0.42.dist-info/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
|
|
49
|
+
stjames-0.0.42.dist-info/METADATA,sha256=mIKojGiwySNE8F0-7hulBNJv2WFORfn08rwCUghPbWM,1628
|
|
50
|
+
stjames-0.0.42.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
51
|
+
stjames-0.0.42.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
|
|
52
|
+
stjames-0.0.42.dist-info/RECORD,,
|
stjames-0.0.40.dist-info/RECORD
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
stjames/__init__.py,sha256=RJ1b132RSXVbQfptduVM1ZSQrnSTsg0a-VfgBwQn9zo,506
|
|
2
|
-
stjames/_deprecated_solvent_settings.py,sha256=gj5j9p3zakIwSTK5_ndqBXJx--IzjZNxZ75z-wipLOo,450
|
|
3
|
-
stjames/base.py,sha256=R49yN4UoiOSjZEkadbMLqLLVNYmysXE4VvCU5JHTCNg,1190
|
|
4
|
-
stjames/basis_set.py,sha256=Fi6vJx-ni2aOozFYH2hrSlc9lL01XzPO4zO6onJliuE,1035
|
|
5
|
-
stjames/calculation.py,sha256=0eCZ59lqmnI_QxEdMp7esrTeutNyO_pIFrZQf_FncSo,848
|
|
6
|
-
stjames/constraint.py,sha256=gkp0y0yQPeii8jdBNllZ9JS8t0o2bkEVTFAkyhShmWk,329
|
|
7
|
-
stjames/correction.py,sha256=_pNG3qSylfx0iyUxqwx9HPU0m032YwP6wSPCjbJrD94,358
|
|
8
|
-
stjames/diis_settings.py,sha256=QHc7L-hktkbOWBYr29byTdqL8lWJzKJiY9XW8ha4Qzo,552
|
|
9
|
-
stjames/grid_settings.py,sha256=WrSNGc-8_f87YBZYt9Hh7RbhM4MweADoVzwBMcSqcsE,640
|
|
10
|
-
stjames/int_settings.py,sha256=5HXp8opt5ZyY1UpmfaK7NVloWVLM5jkG0elEEqpVLUo,896
|
|
11
|
-
stjames/message.py,sha256=Rq6QqmHZKecWxYH8fVyXmuoCCPZv8YinvgykSeorXSU,216
|
|
12
|
-
stjames/method.py,sha256=iThn9tkkM0x0uX95o3Tcz3QQtad47UYGDL76hW3ySaM,787
|
|
13
|
-
stjames/mode.py,sha256=xw46Cc7f3eTS8i35qECi-8DocAlANhayK3w4akD4HBU,496
|
|
14
|
-
stjames/molecule.py,sha256=G78Bm88r8w-4cx_AOUyxLrn_gIt-TdeoYeBoiociqX8,3032
|
|
15
|
-
stjames/opt_settings.py,sha256=5nTGih8KZ3x_yGfPL7pdGdsuOpCIfuJUrKoSK5YSDJg,458
|
|
16
|
-
stjames/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
stjames/scf_settings.py,sha256=xMMCQ0hVB4nNFSiWesNQZUa_aLsozSZGYWweAPPDGBg,2356
|
|
18
|
-
stjames/settings.py,sha256=mn9TY2y2Juqou-bfIkXFWM_pbs_90-MgYYzAnWXCwVQ,8660
|
|
19
|
-
stjames/solvent.py,sha256=0Kb2O3kTXMbcTH2br9bg7vtgG-Q7uRzhcMKSdUktVNo,1140
|
|
20
|
-
stjames/status.py,sha256=wTKNcNxStoEHrxxgr_zTyN90NITa3rxMQZzOgrCifEw,332
|
|
21
|
-
stjames/task.py,sha256=TTl-iTdvDNCZTdPsyS6bYmxzY0ez9PgYlL62fztayXQ,307
|
|
22
|
-
stjames/thermochem_settings.py,sha256=ZTLz31v8Ltutde5Nfm0vH5YahWjcfFWfr_R856KffxE,517
|
|
23
|
-
stjames/workflows/__init__.py,sha256=sy9J04mCJpyVGcG4DecCi6pncwbZVvybI7sJKzavjgo,167
|
|
24
|
-
stjames/workflows/conformer.py,sha256=YYwL3l7OaVeea4N9-ihghwa_ieKY6hia9LNbiTraMb0,2732
|
|
25
|
-
stjames/workflows/descriptors.py,sha256=Jqx_4u_ZhdFJrT-ITU6zlFY0n8llh6zhzIhM38e8NCs,255
|
|
26
|
-
stjames/workflows/fukui.py,sha256=FAabgLi_ig6Zp_jiTkuveP0wAObwv68liuumr85rb0g,366
|
|
27
|
-
stjames/workflows/pka.py,sha256=zpR90Yv2L-D56o2mGArM8027DWpnFFnay31UR9Xh5Nc,774
|
|
28
|
-
stjames/workflows/redox_potential.py,sha256=iPkFt1Dj1sUywS9pLSEBVpCjHZcEwUESluY0ggLii8A,1213
|
|
29
|
-
stjames/workflows/scan.py,sha256=d1ca1uk1nxdzlSwqMLZ0W1_DHyrQMnHJmvPfziCS0SA,773
|
|
30
|
-
stjames/workflows/tautomer.py,sha256=kZSCHo2Q7LzqtQjF_WyyxjECkndG49T9QOM12hsUkx8,421
|
|
31
|
-
stjames/workflows/workflow.py,sha256=6hFe5PZejJu6bZ3yTkoJ9-xQMBn_-8tUsbk4FUZxog0,367
|
|
32
|
-
stjames-0.0.40.dist-info/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
|
|
33
|
-
stjames-0.0.40.dist-info/METADATA,sha256=GeuHmCFTQwu5cq521KVGYIdQBKmyOuBwonQ19a3ShO0,1626
|
|
34
|
-
stjames-0.0.40.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
|
35
|
-
stjames-0.0.40.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
|
|
36
|
-
stjames-0.0.40.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|