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.
Files changed (85) hide show
  1. {graphatoms-2.1.1 → graphatoms-2.2.0}/PKG-INFO +1 -1
  2. {graphatoms-2.1.1 → graphatoms-2.2.0}/pyproject.toml +2 -1
  3. {graphatoms-2.1.1 → graphatoms-2.2.0}/pyproject.toml.orig +2 -1
  4. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/arrayapi/typing.py +3 -3
  5. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/__init__.py +9 -3
  6. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/example.yaml +0 -1
  7. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/__init__.py +100 -15
  8. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/_metadata.py +9 -26
  9. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/_recorder.py +45 -46
  10. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/__init__.py +4 -0
  11. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/_base.py +97 -16
  12. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/_helper.py +174 -32
  13. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/general/_expl.py +95 -45
  14. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/general/otfkmc.py +72 -19
  15. graphatoms-2.2.0/src/graphatoms/enterpoint/runner/general/rxngen.py +152 -0
  16. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/_expl.py +2 -2
  17. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/view.py +19 -2
  18. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_bond_list.py +1 -2
  19. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/reaction/__init__.py +1 -2
  20. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/reaction/_event.py +141 -80
  21. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/reaction/reaction.py +5 -15
  22. graphatoms-2.2.0/src/graphatoms/reaction/xxsorption.py +209 -0
  23. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/atoms.py +4 -2
  24. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/bonds.py +13 -5
  25. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/__init__.py +20 -4
  26. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/abc.py +9 -7
  27. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/dict.py +8 -1
  28. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/dir.py +9 -1
  29. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/hdf5.py +9 -1
  30. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/database/sqliteASE.py +9 -1
  31. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/graph.py +9 -22
  32. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/sysCluster.py +1 -0
  33. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/sysGas.py +56 -29
  34. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/adsorption.py +1 -1
  35. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/rdutils.py +1 -1
  36. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/general/rxngen.py +0 -9
  37. graphatoms-2.1.1/src/graphatoms/reaction/xxsorption.py +0 -198
  38. {graphatoms-2.1.1 → graphatoms-2.2.0}/README.md +0 -0
  39. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/LICENSE +0 -0
  40. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/__init__.py +0 -0
  41. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/arrayapi/__init__.py +0 -0
  42. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/arrayapi/compat.py +0 -0
  43. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/__init__.py +0 -0
  44. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_numpydantic.py +0 -0
  45. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_pydantic2pyarrow.py +0 -0
  46. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_pydanticMixin.py +0 -0
  47. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/_pydanticModel.py +0 -0
  48. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/dataclasses/graph.py +0 -0
  49. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/__init__.py +0 -0
  50. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/atoms/__init__.py +0 -0
  51. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/atoms/aseread.yaml +0 -0
  52. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/atoms/octahedron.yaml +0 -0
  53. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/bonds/__init__.py +0 -0
  54. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/bonds/raw.yaml +0 -0
  55. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/calculator/__init__.py +0 -0
  56. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/calculator/emt.yaml +0 -0
  57. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/calculator/nequip.yaml +0 -0
  58. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/config/run.yaml +0 -0
  59. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/network/_scheduler.py +0 -0
  60. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/__init__.py +0 -0
  61. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_base.py +0 -0
  62. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_dask.py +0 -0
  63. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_executorlib.py +0 -0
  64. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/parallel/_ray.py +0 -0
  65. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/__init__.py +0 -0
  66. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/common/_errors.py +0 -0
  67. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/general/__init__.py +0 -0
  68. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/__init__.py +0 -0
  69. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/otfkmc.py +0 -0
  70. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/enterpoint/runner/ray/rxngen.py +0 -0
  71. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/__init__.py +0 -0
  72. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_distance_pairs.py +0 -0
  73. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_inner_outer.py +0 -0
  74. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/_neighbor_list.py +0 -0
  75. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/mic.py +0 -0
  76. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/rotation.py +0 -0
  77. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/geometry/sample.py +0 -0
  78. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/__init__.py +0 -0
  79. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/system/system.py +0 -0
  80. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/__init__.py +0 -0
  81. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/asetools.py +0 -0
  82. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/bytestool.py +0 -0
  83. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/logger.py +0 -0
  84. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/parser.py +0 -0
  85. {graphatoms-2.1.1 → graphatoms-2.2.0}/src/graphatoms/utils/subgraph.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphatoms
3
- Version: 2.1.1
3
+ Version: 2.2.0
4
4
  Summary: The Chemical Core Class for Graph Theory Analysis.
5
5
  Keywords: chemistry,graph theory,reaction,event,KMC
6
6
  Author: LiuGaoyong
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "graphatoms"
7
- version = "2.1.1"
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.1.1"
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
- TODO: 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))``.
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 TODO: 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."
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"]
@@ -64,7 +64,6 @@ event:
64
64
  gas_sticking:
65
65
  CO: 0.5
66
66
  CO2: 0.5
67
- gas_pressure: {}
68
67
  temperature: 300.0
69
68
  optimizer:
70
69
  method: "lbfgs"
@@ -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 ["ts", "gas", "minima", "cluster", "system"]
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
- return "fasdasdgase"
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
- return "fail"
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
- is_new = self.write_event(
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
- return f"{'new' if is_new else 'old'} {event}"
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=True)
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=True)
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
- exclude_gas: bool = False,
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 ((not exclude_gas) or self.key_g[i] is None)
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 ((not exclude_gas) or self.key_g[i] is None)
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 # type: ignore
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: