GraphAtoms 2.1.1__tar.gz → 2.2.0__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.
- {graphatoms-2.1.1 → graphatoms-2.2.0}/PKG-INFO +1 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/pyproject.toml +2 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/pyproject.toml.orig +2 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/arrayapi/typing.py +3 -3
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/__init__.py +9 -3
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/example.yaml +0 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/__init__.py +100 -15
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/_metadata.py +9 -26
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/_recorder.py +45 -46
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/__init__.py +4 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/_base.py +97 -16
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/_helper.py +174 -32
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/general/_expl.py +95 -45
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/general/otfkmc.py +72 -19
- graphatoms-2.2.0/src/graphatoms/enterpoint/runner/general/rxngen.py +152 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/_expl.py +2 -2
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/view.py +19 -2
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_bond_list.py +1 -2
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/reaction/__init__.py +1 -2
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/reaction/_event.py +141 -80
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/reaction/reaction.py +5 -15
- graphatoms-2.2.0/src/graphatoms/reaction/xxsorption.py +209 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/atoms.py +4 -2
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/bonds.py +13 -5
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/__init__.py +20 -4
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/abc.py +9 -7
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/dict.py +8 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/dir.py +9 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/hdf5.py +9 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/sqliteASE.py +9 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/graph.py +9 -22
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/sysCluster.py +1 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/sysGas.py +56 -29
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/adsorption.py +1 -1
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/rdutils.py +1 -1
- graphatoms-2.1.1/src/graphatoms/enterpoint/runner/general/rxngen.py +0 -9
- graphatoms-2.1.1/src/graphatoms/reaction/xxsorption.py +0 -198
- {graphatoms-2.1.1 → graphatoms-2.2.0}/README.md +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/LICENSE +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/arrayapi/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/arrayapi/compat.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_numpydantic.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_pydantic2pyarrow.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_pydanticMixin.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_pydanticModel.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/graph.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/atoms/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/atoms/aseread.yaml +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/atoms/octahedron.yaml +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/bonds/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/bonds/raw.yaml +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/calculator/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/calculator/emt.yaml +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/calculator/nequip.yaml +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/run.yaml +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/_scheduler.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_base.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_dask.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_executorlib.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_ray.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/_errors.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/general/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/otfkmc.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/rxngen.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_distance_pairs.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_inner_outer.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_neighbor_list.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/mic.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/rotation.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/sample.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/system.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/__init__.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/asetools.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/bytestool.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/logger.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/parser.py +0 -0
- {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/subgraph.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "graphatoms"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
description = "The Chemical Core Class for Graph Theory Analysis."
|
|
10
10
|
license-files = ["src/LICENSE"]
|
|
@@ -72,6 +72,7 @@ dev = [
|
|
|
72
72
|
"jupyterlab",
|
|
73
73
|
"chemiscope",
|
|
74
74
|
"nglview",
|
|
75
|
+
"grpcio",
|
|
75
76
|
"ray",
|
|
76
77
|
]
|
|
77
78
|
|
|
@@ -12,7 +12,7 @@ graphatoms-network = "graphatoms.enterpoint.view:main"
|
|
|
12
12
|
graphatoms-run = "graphatoms.enterpoint.runner:run"
|
|
13
13
|
[project]
|
|
14
14
|
name = "graphatoms"
|
|
15
|
-
version = "2.
|
|
15
|
+
version = "2.2.0"
|
|
16
16
|
readme = "README.md"
|
|
17
17
|
description = "The Chemical Core Class for Graph Theory Analysis."
|
|
18
18
|
authors = [{ name = "LiuGaoyong", email = "liugaoyong_88@163.com" }]
|
|
@@ -76,6 +76,7 @@ dev = [
|
|
|
76
76
|
"chemiscope",
|
|
77
77
|
# "playwright>=1.52", # chemiscope [headless]
|
|
78
78
|
"nglview",
|
|
79
|
+
"grpcio",
|
|
79
80
|
"ray",
|
|
80
81
|
]
|
|
81
82
|
|
|
@@ -4243,8 +4243,8 @@ class abs[TArray: Array](Protocol):
|
|
|
4243
4243
|
.. note::
|
|
4244
4244
|
For complex floating-point operands, conforming implementations should take care to avoid undue overflow or underflow during intermediate stages of computation.
|
|
4245
4245
|
|
|
4246
|
-
..
|
|
4247
|
-
|
|
4246
|
+
.. note::
|
|
4247
|
+
Once ``hypot`` is added to the specification, remove the special cases for complex floating-point operands and the note concerning guarding against undue overflow/underflow, and state that special cases must be handled as if implemented as ``hypot(real(x), imag(x))``.
|
|
4248
4248
|
|
|
4249
4249
|
Parameters
|
|
4250
4250
|
----------
|
|
@@ -9679,7 +9679,7 @@ class ArrayNamespace[TArray: Array, TDtype, TDevice](Protocol):
|
|
|
9679
9679
|
sort: sort[TArray,]
|
|
9680
9680
|
"Returns a sorted copy of an input array ``x``.\n\n.. note::\n For backward compatibility, conforming implementations may support complex numbers; however, inequality comparison of complex numbers is unspecified and thus implementation-dependent (see :ref:`complex-number-ordering`).\n\nParameters\n----------\nx: array\n input array. Should have a real-valued data type.\naxis: int\n axis along which to sort. If set to ``-1``, the function must sort along the last axis. Default: ``-1``.\ndescending: bool\n sort order. If ``True``, the array must be sorted in descending order (by value). If ``False``, the array must be sorted in ascending order (by value). Default: ``False``.\nstable: bool\n sort stability. If ``True``, the returned array must maintain the relative order of ``x`` values which compare as equal. If ``False``, the returned array may or may not maintain the relative order of ``x`` values which compare as equal (i.e., the relative order of ``x`` values which compare as equal is implementation-dependent). Default: ``True``.\n\nReturns\n-------\nout : array\n a sorted array. The returned array must have the same data type and shape as ``x``."
|
|
9681
9681
|
abs: abs[TArray,]
|
|
9682
|
-
"Calculates the absolute value for each element ``x_i`` of the input array ``x``.\n\nFor real-valued input arrays, the element-wise result has the same magnitude as the respective element in ``x`` but has positive sign.\n\n.. note::\n For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent.\n\n.. note::\n For complex floating-point operands, the complex absolute value is known as the norm, modulus, or magnitude and, for a complex number :math:`z = a + bj` is computed as\n\n .. math::\n \\operatorname{abs}(z) = \\sqrt{a^2 + b^2}\n\n.. note::\n For complex floating-point operands, conforming implementations should take care to avoid undue overflow or underflow during intermediate stages of computation.\n\n..\n
|
|
9682
|
+
"Calculates the absolute value for each element ``x_i`` of the input array ``x``.\n\nFor real-valued input arrays, the element-wise result has the same magnitude as the respective element in ``x`` but has positive sign.\n\n.. note::\n For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent.\n\n.. note::\n For complex floating-point operands, the complex absolute value is known as the norm, modulus, or magnitude and, for a complex number :math:`z = a + bj` is computed as\n\n .. math::\n \\operatorname{abs}(z) = \\sqrt{a^2 + b^2}\n\n.. note::\n For complex floating-point operands, conforming implementations should take care to avoid undue overflow or underflow during intermediate stages of computation.\n\n..\n once ``hypot`` is added to the specification, remove the special cases for complex floating-point operands and the note concerning guarding against undue overflow/underflow, and state that special cases must be handled as if implemented as ``hypot(real(x), imag(x))``.\n\nParameters\n----------\nx: array\n input array. Should have a numeric data type.\n\nReturns\n-------\nout: array\n an array containing the absolute value of each element in ``x``. If ``x`` has a real-valued data type, the returned array must have the same data type as ``x``. If ``x`` has a complex floating-point data type, the returned array must have a real-valued floating-point data type whose precision matches the precision of ``x`` (e.g., if ``x`` is ``complex128``, then the returned array must have a ``float64`` data type).\n\nNotes\n-----\n\n**Special Cases**\n\nFor real-valued floating-point operands,\n\n- If ``x_i`` is ``NaN``, the result is ``NaN``.\n- If ``x_i`` is ``-0``, the result is ``+0``.\n- If ``x_i`` is ``-infinity``, the result is ``+infinity``.\n\nFor complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and\n\n- If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is any value (including ``NaN``), the result is ``+infinity``.\n- If ``a`` is any value (including ``NaN``) and ``b`` is either ``+infinity`` or ``-infinity``, the result is ``+infinity``.\n- If ``a`` is either ``+0`` or ``-0``, the result is equal to ``abs(b)``.\n- If ``b`` is either ``+0`` or ``-0``, the result is equal to ``abs(a)``.\n- If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN``.\n- If ``a`` is a finite number and ``b`` is ``NaN``, the result is ``NaN``.\n- If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN``.\n\n.. versionchanged:: 2022.12\n Added complex data type support."
|
|
9683
9683
|
acos: acos[TArray,]
|
|
9684
9684
|
"Calculates an implementation-dependent approximation of the principal value of the inverse cosine for each element ``x_i`` of the input array ``x``.\n\nEach element-wise result is expressed in radians.\n\n.. note::\n The principal value of the arc cosine of a complex number :math:`z` is\n\n .. math::\n \\operatorname{acos}(z) = \\frac{1}{2}\\pi + j\\ \\ln(zj + \\sqrt{1-z^2})\n\n For any :math:`z`,\n\n .. math::\n \\operatorname{acos}(z) = \\pi - \\operatorname{acos}(-z)\n\n.. note::\n For complex floating-point operands, ``acos(conj(x))`` must equal ``conj(acos(x))``.\n\n.. note::\n The inverse cosine (or arc cosine) is a multi-valued function and requires a branch cut on the complex plane. By convention, a branch cut is placed at the line segments :math:`(-\\infty, -1)` and :math:`(1, \\infty)` of the real axis.\n\n Accordingly, for complex arguments, the function returns the inverse cosine in the range of a strip unbounded along the imaginary axis and in the interval :math:`[0, \\pi]` along the real axis.\n\n *Note: branch cuts follow C99 and have provisional status* (see :ref:`branch-cuts`).\n\nParameters\n----------\nx: array\n input array. Should have a floating-point data type.\n\nReturns\n-------\nout: array\n an array containing the inverse cosine of each element in ``x``. The returned array must have a floating-point data type determined by :ref:`type-promotion`.\n\nNotes\n-----\n\n**Special cases**\n\nFor real-valued floating-point operands,\n\n- If ``x_i`` is ``NaN``, the result is ``NaN``.\n- If ``x_i`` is greater than ``1``, the result is ``NaN``.\n- If ``x_i`` is less than ``-1``, the result is ``NaN``.\n- If ``x_i`` is ``1``, the result is ``+0``.\n\nFor complex floating-point operands, let ``a = real(x_i)``, ``b = imag(x_i)``, and\n\n- If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``+0``, the result is ``π/2 - 0j``.\n- If ``a`` is either ``+0`` or ``-0`` and ``b`` is ``NaN``, the result is ``π/2 + NaN j``.\n- If ``a`` is a finite number and ``b`` is ``+infinity``, the result is ``π/2 - infinity j``.\n- If ``a`` is a nonzero finite number and ``b`` is ``NaN``, the result is ``NaN + NaN j``.\n- If ``a`` is ``-infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``π - infinity j``.\n- If ``a`` is ``+infinity`` and ``b`` is a positive (i.e., greater than ``0``) finite number, the result is ``+0 - infinity j``.\n- If ``a`` is ``-infinity`` and ``b`` is ``+infinity``, the result is ``3π/4 - infinity j``.\n- If ``a`` is ``+infinity`` and ``b`` is ``+infinity``, the result is ``π/4 - infinity j``.\n- If ``a`` is either ``+infinity`` or ``-infinity`` and ``b`` is ``NaN``, the result is ``NaN ± infinity j`` (sign of the imaginary component is unspecified).\n- If ``a`` is ``NaN`` and ``b`` is a finite number, the result is ``NaN + NaN j``.\n- If ``a`` is ``NaN`` and ``b`` is ``+infinity``, the result is ``NaN - infinity j``.\n- If ``a`` is ``NaN`` and ``b`` is ``NaN``, the result is ``NaN + NaN j``.\n\n.. versionchanged:: 2022.12\n Added complex data type support."
|
|
9685
9685
|
acosh: acosh[TArray,]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from collections import defaultdict
|
|
2
3
|
from dataclasses import dataclass, field
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Any
|
|
@@ -29,6 +30,7 @@ class ExplConfig:
|
|
|
29
30
|
maxtry: int = 1000
|
|
30
31
|
maxconfidence: float = 10
|
|
31
32
|
max_ncore_for_surface: int = 3 # 4, 5, 6
|
|
33
|
+
optimization_for_system: bool = True
|
|
32
34
|
surface_only_explore_single_core: bool = True
|
|
33
35
|
allow_multiple_adsorption: bool = False
|
|
34
36
|
allow_explore_bulk: bool = False
|
|
@@ -45,9 +47,6 @@ class EventConfig:
|
|
|
45
47
|
min_frequency_for_ts: float = 20.0 # cm^-1
|
|
46
48
|
simplified_threshold: float = 7.0 # the simplified threshold for event
|
|
47
49
|
gas_sticking: dict[str, float] = field(default_factory=dict)
|
|
48
|
-
gas_pressure: dict[str, float] = field(default_factory=dict)
|
|
49
|
-
default_pressure: float = 101325
|
|
50
|
-
default_sticking: float = 1.0
|
|
51
50
|
temperature: float = 300
|
|
52
51
|
|
|
53
52
|
|
|
@@ -70,6 +69,13 @@ class Config:
|
|
|
70
69
|
max_steps: int = 100000
|
|
71
70
|
max_times: float = 1000.0 # seconds
|
|
72
71
|
run_type: str = "otfkmc" # otfkmc, rxngen
|
|
72
|
+
gas_pressure_cache_box_length: float = 1e4 # in Angstrom
|
|
73
|
+
initial_gas_pressure: dict[str, float] = field(default_factory=dict)
|
|
74
|
+
# the initial gas pressure only effect for `OTFKMC`, and the key of
|
|
75
|
+
# `initial_gas_pressure` must be the same as the key of `gas_sticking`
|
|
76
|
+
# 2. if the key of `initial_gas_pressure` is not in `gas_sticking`, then the initial gas pressure is 0.0 # noqa: E501
|
|
77
|
+
# 1. if the key of `gas_sticking` is not in `initial_gas_pressure`, then the gas sticking is 1.0 # noqa: E501
|
|
78
|
+
|
|
73
79
|
parallel_workers: int = 0 # 0 means use all cores
|
|
74
80
|
parallel: str = "serial" # serial, multiprocessing, ray, dask, executorlib
|
|
75
81
|
loglevel: str = "info" # Literal["debug", "info", "warning", "error"]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import dataclasses as dc
|
|
2
2
|
import pickle
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Literal
|
|
4
|
+
from typing import Literal, Self
|
|
5
5
|
|
|
6
6
|
from graphatoms.enterpoint.config import EventConfig
|
|
7
7
|
from graphatoms.reaction import (
|
|
@@ -16,7 +16,7 @@ from graphatoms.system.database import DatabaseABC, get_db
|
|
|
16
16
|
|
|
17
17
|
from ._metadata import MetaData
|
|
18
18
|
from ._metadata import _MetaDataBasic as MetaDataBasic
|
|
19
|
-
from ._recorder import Recorder
|
|
19
|
+
from ._recorder import Recorder, RecorderInfo
|
|
20
20
|
from ._scheduler import Scheduler
|
|
21
21
|
|
|
22
22
|
__all__ = [
|
|
@@ -38,6 +38,7 @@ class ReactionNetwork:
|
|
|
38
38
|
**kwargs,
|
|
39
39
|
) -> None:
|
|
40
40
|
self.__path = path = Path(path)
|
|
41
|
+
self.__path_exploration_recorder = path / "exploration.csv"
|
|
41
42
|
if config is not None:
|
|
42
43
|
metadata_basic = MetaDataBasic(
|
|
43
44
|
**(
|
|
@@ -62,6 +63,10 @@ class ReactionNetwork:
|
|
|
62
63
|
f"The path `{self.__path}` does not exist."
|
|
63
64
|
+ " Please create it or use `restart=False`."
|
|
64
65
|
)
|
|
66
|
+
assert self.__path_exploration_recorder.exists(), (
|
|
67
|
+
f"The path `{self.__path_exploration_recorder}` does not exist."
|
|
68
|
+
+ " Please create it or use `restart=False`."
|
|
69
|
+
)
|
|
65
70
|
self.scheduler = Scheduler.read_npz(path / "scheduler.npz")
|
|
66
71
|
self.recorder = Recorder.read_json(path / "recorder.json")
|
|
67
72
|
self.metadata = MetaData.from_storage(path)
|
|
@@ -79,12 +84,17 @@ class ReactionNetwork:
|
|
|
79
84
|
f"The path `{self.__path}` does exist."
|
|
80
85
|
+ " Please delete it or use `restart=True`."
|
|
81
86
|
)
|
|
87
|
+
self.__path.mkdir(parents=True, exist_ok=True)
|
|
88
|
+
self.__path_exploration_recorder.write_text(
|
|
89
|
+
RecorderInfo.get_csv_title() + "\n"
|
|
90
|
+
)
|
|
82
91
|
self.recorder: Recorder = Recorder()
|
|
83
92
|
self.scheduler: Scheduler = Scheduler()
|
|
84
93
|
if metadata_basic is not None:
|
|
85
94
|
self.metadata: MetaData = MetaData(basic=metadata_basic)
|
|
86
95
|
else:
|
|
87
96
|
self.metadata: MetaData = MetaData()
|
|
97
|
+
self.__format = format
|
|
88
98
|
|
|
89
99
|
# initialize the databases
|
|
90
100
|
(
|
|
@@ -99,8 +109,15 @@ class ReactionNetwork:
|
|
|
99
109
|
format=format,
|
|
100
110
|
prefix=prefix,
|
|
101
111
|
append=restart,
|
|
112
|
+
use_positions_uuid=use_positions_uuid,
|
|
102
113
|
)
|
|
103
|
-
for prefix in [
|
|
114
|
+
for prefix, use_positions_uuid in [
|
|
115
|
+
("ts", True),
|
|
116
|
+
("gas", False),
|
|
117
|
+
("minima", True),
|
|
118
|
+
("cluster", False),
|
|
119
|
+
("system", False),
|
|
120
|
+
]
|
|
104
121
|
]
|
|
105
122
|
assert isinstance(self.db_ts, DatabaseABC)
|
|
106
123
|
assert isinstance(self.db_gas, DatabaseABC)
|
|
@@ -108,9 +125,33 @@ class ReactionNetwork:
|
|
|
108
125
|
assert isinstance(self.db_cluster, DatabaseABC)
|
|
109
126
|
assert isinstance(self.db_system, DatabaseABC)
|
|
110
127
|
|
|
128
|
+
@classmethod
|
|
129
|
+
def merge(
|
|
130
|
+
cls,
|
|
131
|
+
*networks: Self,
|
|
132
|
+
new_path: Path | str,
|
|
133
|
+
new_format: str | Literal["dir", "h5", "sqlite"] = "dir",
|
|
134
|
+
**kwargs,
|
|
135
|
+
) -> Self:
|
|
136
|
+
"""Merge the networks."""
|
|
137
|
+
raise NotImplementedError("Merge the networks.")
|
|
138
|
+
cls(
|
|
139
|
+
path=new_path,
|
|
140
|
+
restart=False,
|
|
141
|
+
config=networks[0].metadata.basic,
|
|
142
|
+
format=networks[0].__format,
|
|
143
|
+
)
|
|
144
|
+
|
|
111
145
|
def summary(self) -> str:
|
|
112
146
|
"""Return the summary of the network."""
|
|
113
|
-
|
|
147
|
+
msg = f"ReactionNetwork: {self.__path} (format={self.__format})\n"
|
|
148
|
+
msg += f" #System :{len(self.db_system)}\n"
|
|
149
|
+
msg += f" #Cluster :{len(self.db_cluster)}\n"
|
|
150
|
+
msg += f" #Minima :{len(self.db_minima)}\n"
|
|
151
|
+
msg += f" #Gas :{len(self.db_gas)}\n"
|
|
152
|
+
msg += f" #TS :{len(self.db_ts)}\n"
|
|
153
|
+
msg += f"#Event :{len(self.metadata.table)}\n"
|
|
154
|
+
return msg
|
|
114
155
|
|
|
115
156
|
def persistence(self) -> None:
|
|
116
157
|
"""Persist the data to the database."""
|
|
@@ -143,20 +184,36 @@ class ReactionNetwork:
|
|
|
143
184
|
def found(
|
|
144
185
|
self,
|
|
145
186
|
event: EventBase | str,
|
|
187
|
+
for_gas: str | None,
|
|
188
|
+
for_cluster: str,
|
|
146
189
|
*,
|
|
147
|
-
for_cluster: str | None = None,
|
|
148
190
|
for_system: str | None = None,
|
|
149
191
|
persist: bool = True,
|
|
150
192
|
**kwargs,
|
|
151
193
|
) -> Literal["new", "old", "fail"] | str:
|
|
194
|
+
if for_system is None:
|
|
195
|
+
for_system = ""
|
|
196
|
+
if for_gas is None:
|
|
197
|
+
for_gas = ""
|
|
198
|
+
old_new = self.recorder.cluster[for_cluster]
|
|
199
|
+
min_found = self.metadata.table.get_minconut_for(
|
|
200
|
+
cluster_key=for_cluster,
|
|
201
|
+
system_key=for_system,
|
|
202
|
+
gas_key=None,
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
old_new = self.recorder.adsorption[f"{for_cluster}_{for_gas}"]
|
|
206
|
+
min_found = self.metadata.table.get_minconut_for(
|
|
207
|
+
cluster_key=for_cluster,
|
|
208
|
+
system_key=for_system,
|
|
209
|
+
gas_key=for_gas,
|
|
210
|
+
)
|
|
211
|
+
|
|
152
212
|
if isinstance(event, str):
|
|
153
|
-
|
|
213
|
+
old_new.found_fail()
|
|
214
|
+
result = "fail"
|
|
154
215
|
elif isinstance(event, EventBase):
|
|
155
216
|
simplified_threshold = self.metadata.basic.simplified_threshold
|
|
156
|
-
if for_system is None:
|
|
157
|
-
for_system = ""
|
|
158
|
-
if for_cluster is None:
|
|
159
|
-
for_cluster = event.R.get_key_for_metadata()
|
|
160
217
|
if simplified_threshold > 0:
|
|
161
218
|
try:
|
|
162
219
|
event = event.simplify(simplified_threshold)
|
|
@@ -167,17 +224,32 @@ class ReactionNetwork:
|
|
|
167
224
|
fname.write_bytes(pickle.dumps(event))
|
|
168
225
|
fname.with_suffix(".err").write_text(msg)
|
|
169
226
|
raise ValueError(msg)
|
|
170
|
-
|
|
227
|
+
if self.write_event(
|
|
171
228
|
event,
|
|
172
229
|
for_cluster,
|
|
173
230
|
for_system,
|
|
174
231
|
persist=persist,
|
|
175
232
|
**kwargs,
|
|
176
|
-
)
|
|
177
|
-
|
|
233
|
+
):
|
|
234
|
+
old_new.found_new()
|
|
235
|
+
result = f"new {event}"
|
|
236
|
+
else:
|
|
237
|
+
old_new.found_old()
|
|
238
|
+
result = f"old {event}"
|
|
178
239
|
else:
|
|
179
240
|
raise ValueError(f"Unknown event type: {type(event)}")
|
|
180
241
|
|
|
242
|
+
info = RecorderInfo.from_oldnew(
|
|
243
|
+
oldnew=old_new,
|
|
244
|
+
min_found=min_found,
|
|
245
|
+
for_cluster=for_cluster,
|
|
246
|
+
for_system=for_system,
|
|
247
|
+
for_gas=for_gas,
|
|
248
|
+
)
|
|
249
|
+
with self.__path_exploration_recorder.open("a") as f:
|
|
250
|
+
f.write(info.to_csv_line() + "\n")
|
|
251
|
+
return result
|
|
252
|
+
|
|
181
253
|
def write_event(
|
|
182
254
|
self,
|
|
183
255
|
event: EventBase,
|
|
@@ -188,6 +260,19 @@ class ReactionNetwork:
|
|
|
188
260
|
**kwargs,
|
|
189
261
|
) -> bool:
|
|
190
262
|
"""Write the event to the database."""
|
|
263
|
+
if isinstance(event, Desorption):
|
|
264
|
+
event = event.reversed
|
|
265
|
+
assert isinstance(event, Adsorption | Reaction), (
|
|
266
|
+
f"Unknown event type: {type(event)}. Only " #
|
|
267
|
+
"Adsorption and Reaction are supported, " #
|
|
268
|
+
"and the Desorption will be reversed."
|
|
269
|
+
)
|
|
270
|
+
if event.G is not None:
|
|
271
|
+
assert event.R.natoms < event.P.natoms, (
|
|
272
|
+
f"Event {event._string()} is not Adsorption. "
|
|
273
|
+
"The R must have fewer atoms than P."
|
|
274
|
+
)
|
|
275
|
+
|
|
191
276
|
if self.metadata.has(event):
|
|
192
277
|
self.metadata.rxn_count_add_one(event)
|
|
193
278
|
return False
|
|
@@ -238,8 +323,8 @@ class ReactionNetwork:
|
|
|
238
323
|
elif type.lower() == "gas":
|
|
239
324
|
return self.db_gas.add(sysgraph, check_positions=False)
|
|
240
325
|
elif type.lower() == "system":
|
|
241
|
-
return self.db_system.add(sysgraph, check_positions=
|
|
326
|
+
return self.db_system.add(sysgraph, check_positions=False)
|
|
242
327
|
elif type.lower() == "cluster":
|
|
243
|
-
return self.db_cluster.add(sysgraph, check_positions=
|
|
328
|
+
return self.db_cluster.add(sysgraph, check_positions=False)
|
|
244
329
|
else:
|
|
245
330
|
raise ValueError(f"Unknown type: {type}")
|
|
@@ -7,7 +7,6 @@ import pandas as pd
|
|
|
7
7
|
from pydantic import (
|
|
8
8
|
BaseModel,
|
|
9
9
|
NonNegativeFloat,
|
|
10
|
-
computed_field,
|
|
11
10
|
model_validator,
|
|
12
11
|
)
|
|
13
12
|
|
|
@@ -19,36 +18,14 @@ from graphatoms.system.bonds import matchmode2nmatch
|
|
|
19
18
|
__all__ = ["MetaData"]
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
class _GasInfo(BaseModel):
|
|
23
|
-
name: str
|
|
24
|
-
sticking: float
|
|
25
|
-
pressure: float
|
|
26
|
-
|
|
27
|
-
|
|
28
21
|
class _MetaDataBasic(OurBaseModel, EventConfig):
|
|
29
22
|
gas_sticking: dict[str, NonNegativeFloat] = {}
|
|
30
|
-
gas_pressure: dict[str, NonNegativeFloat] = {}
|
|
31
23
|
temperature: float = 300
|
|
32
24
|
|
|
33
25
|
@override
|
|
34
26
|
def _string(self) -> str:
|
|
35
27
|
return ", ".join([f"{k}={v}" for k, v in self.model_dump().items()])
|
|
36
28
|
|
|
37
|
-
@computed_field
|
|
38
|
-
@property
|
|
39
|
-
def gas_info_lst(self) -> list[_GasInfo]:
|
|
40
|
-
result: list[_GasInfo] = []
|
|
41
|
-
for name, sticking in self.gas_sticking.items():
|
|
42
|
-
pressure = self.gas_pressure.get(name, self.default_pressure)
|
|
43
|
-
result.append(
|
|
44
|
-
_GasInfo(
|
|
45
|
-
name=name,
|
|
46
|
-
sticking=sticking,
|
|
47
|
-
pressure=pressure,
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
return result
|
|
51
|
-
|
|
52
29
|
|
|
53
30
|
class _MetaDataTable(BaseModel):
|
|
54
31
|
key_rxn: list[str] = []
|
|
@@ -111,7 +88,7 @@ class _MetaDataTable(BaseModel):
|
|
|
111
88
|
*,
|
|
112
89
|
cluster_key: str | None = None,
|
|
113
90
|
system_key: str | None = None,
|
|
114
|
-
|
|
91
|
+
gas_key: str | None = None,
|
|
115
92
|
**kwargs,
|
|
116
93
|
) -> int:
|
|
117
94
|
if cluster_key is not None:
|
|
@@ -121,7 +98,7 @@ class _MetaDataTable(BaseModel):
|
|
|
121
98
|
for i, ck in enumerate(self.for_cluster)
|
|
122
99
|
if (
|
|
123
100
|
ck == cluster_key
|
|
124
|
-
and ((
|
|
101
|
+
and ((gas_key is None) or self.key_g[i] is gas_key)
|
|
125
102
|
)
|
|
126
103
|
]
|
|
127
104
|
+ [0]
|
|
@@ -133,7 +110,7 @@ class _MetaDataTable(BaseModel):
|
|
|
133
110
|
for i, sk in enumerate(self.for_system)
|
|
134
111
|
if (
|
|
135
112
|
sk == system_key
|
|
136
|
-
and ((
|
|
113
|
+
and ((gas_key is None) or self.key_g[i] is gas_key)
|
|
137
114
|
)
|
|
138
115
|
]
|
|
139
116
|
+ [0]
|
|
@@ -164,6 +141,9 @@ class MetaData(BaseModel):
|
|
|
164
141
|
def bkl_solver(
|
|
165
142
|
self,
|
|
166
143
|
matching_dct: dict[tuple[str, bool], np.ndarray],
|
|
144
|
+
*args,
|
|
145
|
+
env_pressure: dict[str, float] = {},
|
|
146
|
+
**kwargs,
|
|
167
147
|
) -> tuple[pd.DataFrame, str, bool, float, float]:
|
|
168
148
|
"""Solve the BKL equation to select the reaction.
|
|
169
149
|
|
|
@@ -186,6 +166,9 @@ class MetaData(BaseModel):
|
|
|
186
166
|
nmatched = matchmode2nmatch(single_match_res)
|
|
187
167
|
if is_forward:
|
|
188
168
|
rate = self.table.rate_forword[i]
|
|
169
|
+
key_g = self.table.key_g[i]
|
|
170
|
+
if key_g is not None:
|
|
171
|
+
rate *= env_pressure.get(key_g, 0.0)
|
|
189
172
|
else:
|
|
190
173
|
rate = self.table.rate_reversed[i]
|
|
191
174
|
lst.append((rxn_key, is_forward, nmatched, rate))
|
|
@@ -24,11 +24,11 @@ Ref:
|
|
|
24
24
|
|
|
25
25
|
from collections import defaultdict
|
|
26
26
|
from datetime import datetime
|
|
27
|
-
from typing import Annotated, override
|
|
27
|
+
from typing import Annotated, Self, override
|
|
28
28
|
|
|
29
29
|
import pydantic
|
|
30
30
|
|
|
31
|
-
from graphatoms.dataclasses import OurBaseModel
|
|
31
|
+
from graphatoms.dataclasses import OurBaseModel
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class _RecorderBase(pydantic.BaseModel):
|
|
@@ -48,50 +48,6 @@ class _RecorderBase(pydantic.BaseModel):
|
|
|
48
48
|
"""
|
|
49
49
|
return sum([self.old, self.new, self.fail])
|
|
50
50
|
|
|
51
|
-
class RecorderInfo(_RecorderBase):
|
|
52
|
-
create_at: datetime = pydantic.Field(default_factory=lambda: datetime.now())
|
|
53
|
-
confidence: Annotated[float, pydantic.Field(ge=0.5, lt=1.0)]
|
|
54
|
-
for_cluster: str = pydantic.Field(default="")
|
|
55
|
-
for_system: str = pydantic.Field(default="")
|
|
56
|
-
for_gas: str = pydantic.Field(default="")
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def get_csv_title(cls) -> str:
|
|
60
|
-
return ",".join(
|
|
61
|
-
[
|
|
62
|
-
"old",
|
|
63
|
-
"new",
|
|
64
|
-
"fail",
|
|
65
|
-
"total",
|
|
66
|
-
"skip",
|
|
67
|
-
"continuous_old",
|
|
68
|
-
"continuous_nonnew",
|
|
69
|
-
"confidence",
|
|
70
|
-
"create_at",
|
|
71
|
-
"for_cluster",
|
|
72
|
-
"for_system",
|
|
73
|
-
"for_gas",
|
|
74
|
-
]
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
def to_csv_line(self) -> str:
|
|
78
|
-
return ",".join(
|
|
79
|
-
[
|
|
80
|
-
f"{self.old}",
|
|
81
|
-
f"{self.new}",
|
|
82
|
-
f"{self.fail}",
|
|
83
|
-
f"{self.total}",
|
|
84
|
-
f"{self.skip}",
|
|
85
|
-
f"{self.continuous_old}",
|
|
86
|
-
f"{self.continuous_nonnew}",
|
|
87
|
-
f"{self.confidence}",
|
|
88
|
-
f"{self.create_at.strftime('%Y-%m-%d %H:%M:%S.%f')}",
|
|
89
|
-
f"{self.for_cluster}",
|
|
90
|
-
f"{self.for_system}",
|
|
91
|
-
f"{self.for_gas}",
|
|
92
|
-
]
|
|
93
|
-
)
|
|
94
|
-
|
|
95
51
|
|
|
96
52
|
class _OldNewRecorder(OurBaseModel, _RecorderBase):
|
|
97
53
|
@pydantic.validate_call
|
|
@@ -165,6 +121,49 @@ class _OldNewRecorder(OurBaseModel, _RecorderBase):
|
|
|
165
121
|
self.fail += 1
|
|
166
122
|
|
|
167
123
|
|
|
124
|
+
class RecorderInfo(_RecorderBase):
|
|
125
|
+
create_at: datetime = pydantic.Field(default_factory=lambda: datetime.now())
|
|
126
|
+
confidence: Annotated[float, pydantic.Field(ge=0.5, lt=1.0)]
|
|
127
|
+
for_cluster: str = pydantic.Field(default="")
|
|
128
|
+
for_system: str = pydantic.Field(default="")
|
|
129
|
+
for_gas: str = pydantic.Field(default="")
|
|
130
|
+
|
|
131
|
+
@classmethod
|
|
132
|
+
def from_oldnew(
|
|
133
|
+
cls,
|
|
134
|
+
oldnew: _OldNewRecorder,
|
|
135
|
+
min_found: pydantic.NonNegativeInt,
|
|
136
|
+
*,
|
|
137
|
+
for_cluster: str = "",
|
|
138
|
+
for_system: str = "",
|
|
139
|
+
for_gas: str = "",
|
|
140
|
+
) -> Self:
|
|
141
|
+
return cls(
|
|
142
|
+
old=oldnew.old,
|
|
143
|
+
new=oldnew.new,
|
|
144
|
+
fail=oldnew.fail,
|
|
145
|
+
skip=oldnew.skip,
|
|
146
|
+
continuous_old=oldnew.continuous_old,
|
|
147
|
+
continuous_nonnew=oldnew.continuous_nonnew,
|
|
148
|
+
confidence=oldnew.get_williams_confidence(min_found),
|
|
149
|
+
for_cluster=for_cluster,
|
|
150
|
+
for_system=for_system,
|
|
151
|
+
for_gas=for_gas,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
@classmethod
|
|
155
|
+
def get_csv_title(cls) -> str:
|
|
156
|
+
msg = "old,new,fail,total,skip,continuous_old,continuous_nonnew"
|
|
157
|
+
return f"{msg},confidence,for_cluster,for_system,for_gas,create_at"
|
|
158
|
+
|
|
159
|
+
def to_csv_line(self) -> str:
|
|
160
|
+
msg = f"{self.old},{self.new},{self.fail},{self.total},"
|
|
161
|
+
msg += f"{self.skip},{self.continuous_old},{self.continuous_nonnew},"
|
|
162
|
+
msg += f"{self.confidence},{self.for_cluster},{self.for_system}"
|
|
163
|
+
create_at = self.create_at.strftime("%Y-%m-%d %H:%M:%S.%f")
|
|
164
|
+
return f"{msg},{self.for_gas},{create_at}"
|
|
165
|
+
|
|
166
|
+
|
|
168
167
|
class Recorder(OurBaseModel):
|
|
169
168
|
system: set[str] = set()
|
|
170
169
|
cluster: dict[str, _OldNewRecorder] = defaultdict(_OldNewRecorder)
|
|
@@ -19,11 +19,15 @@ from .ray.rxngen import RayReactionNetworkGenerator
|
|
|
19
19
|
)
|
|
20
20
|
def run(cfg: Config) -> None:
|
|
21
21
|
if str(cfg.run_type).lower() == "otfkmc":
|
|
22
|
+
OnTheFlyKMC(config=cfg).run()
|
|
23
|
+
return
|
|
22
24
|
if str(cfg.parallel).lower() == "ray":
|
|
23
25
|
RayOnTheFlyKMC(config=cfg).run()
|
|
24
26
|
else:
|
|
25
27
|
OnTheFlyKMC(config=cfg).run()
|
|
26
28
|
elif str(cfg.run_type).lower() == "rxngen":
|
|
29
|
+
ReactionNetworkGenerator(config=cfg).run()
|
|
30
|
+
return
|
|
27
31
|
if str(cfg.parallel).lower() == "ray":
|
|
28
32
|
RayReactionNetworkGenerator(config=cfg).run()
|
|
29
33
|
else:
|