GraphAtoms 2.0.0__tar.gz → 2.1.1__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.0.0 → graphatoms-2.1.1}/PKG-INFO +36 -13
  2. {graphatoms-2.0.0 → graphatoms-2.1.1}/README.md +35 -8
  3. {graphatoms-2.0.0 → graphatoms-2.1.1}/pyproject.toml +1 -5
  4. {graphatoms-2.0.0 → graphatoms-2.1.1}/pyproject.toml.orig +1 -5
  5. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/__init__.py +1 -4
  6. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/network/__init__.py +51 -23
  7. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/network/_metadata.py +12 -3
  8. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/network/_recorder.py +85 -7
  9. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/__init__.py +32 -0
  10. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/common/__init__.py +21 -0
  11. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/common/_base.py +262 -0
  12. {graphatoms-2.0.0/src/graphatoms/enterpoint/runner → graphatoms-2.1.1/src/graphatoms/enterpoint/runner/common}/_helper.py +19 -8
  13. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/general/__init__.py +0 -0
  14. graphatoms-2.0.0/src/graphatoms/enterpoint/runner/_base.py → graphatoms-2.1.1/src/graphatoms/enterpoint/runner/general/_expl.py +99 -319
  15. {graphatoms-2.0.0/src/graphatoms/enterpoint/runner → graphatoms-2.1.1/src/graphatoms/enterpoint/runner/general}/otfkmc.py +13 -6
  16. {graphatoms-2.0.0/src/graphatoms/enterpoint/runner → graphatoms-2.1.1/src/graphatoms/enterpoint/runner/general}/rxngen.py +2 -2
  17. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/ray/__init__.py +0 -0
  18. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/ray/_expl.py +36 -0
  19. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/ray/otfkmc.py +9 -0
  20. graphatoms-2.1.1/src/graphatoms/enterpoint/runner/ray/rxngen.py +5 -0
  21. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/view.py +4 -4
  22. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/reaction/__init__.py +1 -2
  23. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/reaction/_event.py +8 -0
  24. graphatoms-2.0.0/src/graphatoms/reaction/desorption.py → graphatoms-2.1.1/src/graphatoms/reaction/xxsorption.py +100 -0
  25. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/bonds.py +20 -13
  26. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/sysGas.py +1 -0
  27. graphatoms-2.0.0/src/graphatoms/enterpoint/runner/__init__.py +0 -24
  28. graphatoms-2.0.0/src/graphatoms/reaction/adsorption.py +0 -99
  29. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/LICENSE +0 -0
  30. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/__init__.py +0 -0
  31. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/arrayapi/__init__.py +0 -0
  32. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/arrayapi/compat.py +0 -0
  33. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/arrayapi/typing.py +0 -0
  34. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/dataclasses/__init__.py +0 -0
  35. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/dataclasses/_numpydantic.py +0 -0
  36. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/dataclasses/_pydantic2pyarrow.py +0 -0
  37. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/dataclasses/_pydanticMixin.py +0 -0
  38. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/dataclasses/_pydanticModel.py +0 -0
  39. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/dataclasses/graph.py +0 -0
  40. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/__init__.py +0 -0
  41. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/atoms/__init__.py +0 -0
  42. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/atoms/aseread.yaml +0 -0
  43. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/atoms/octahedron.yaml +0 -0
  44. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/bonds/__init__.py +0 -0
  45. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/bonds/raw.yaml +0 -0
  46. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/calculator/__init__.py +0 -0
  47. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/calculator/emt.yaml +0 -0
  48. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/calculator/nequip.yaml +0 -0
  49. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/example.yaml +0 -0
  50. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/config/run.yaml +0 -0
  51. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/network/_scheduler.py +0 -0
  52. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/parallel/__init__.py +0 -0
  53. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/parallel/_base.py +0 -0
  54. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/parallel/_dask.py +0 -0
  55. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/parallel/_executorlib.py +0 -0
  56. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/enterpoint/parallel/_ray.py +0 -0
  57. {graphatoms-2.0.0/src/graphatoms/enterpoint/runner → graphatoms-2.1.1/src/graphatoms/enterpoint/runner/common}/_errors.py +0 -0
  58. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/__init__.py +0 -0
  59. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/_bond_list.py +0 -0
  60. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/_distance_pairs.py +0 -0
  61. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/_inner_outer.py +0 -0
  62. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/_neighbor_list.py +0 -0
  63. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/mic.py +0 -0
  64. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/rotation.py +0 -0
  65. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/geometry/sample.py +0 -0
  66. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/reaction/reaction.py +0 -0
  67. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/__init__.py +0 -0
  68. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/atoms.py +0 -0
  69. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/database/__init__.py +0 -0
  70. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/database/abc.py +0 -0
  71. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/database/dict.py +0 -0
  72. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/database/dir.py +0 -0
  73. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/database/hdf5.py +0 -0
  74. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/database/sqliteASE.py +0 -0
  75. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/graph.py +0 -0
  76. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/sysCluster.py +0 -0
  77. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/system/system.py +0 -0
  78. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/__init__.py +0 -0
  79. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/adsorption.py +0 -0
  80. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/asetools.py +0 -0
  81. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/bytestool.py +0 -0
  82. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/logger.py +0 -0
  83. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/parser.py +0 -0
  84. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/rdutils.py +0 -0
  85. {graphatoms-2.0.0 → graphatoms-2.1.1}/src/graphatoms/utils/subgraph.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphatoms
3
- Version: 2.0.0
3
+ Version: 2.1.1
4
4
  Summary: The Chemical Core Class for Graph Theory Analysis.
5
5
  Keywords: chemistry,graph theory,reaction,event,KMC
6
6
  Author: LiuGaoyong
@@ -29,12 +29,8 @@ Requires-Dist: python-snappy>=0.7.3
29
29
  Requires-Dist: tomli ; python_full_version < '3.11'
30
30
  Requires-Dist: tomli-w
31
31
  Requires-Dist: typing-extensions
32
- Requires-Dist: plotext
33
- Requires-Dist: plotext-plus
34
- Requires-Dist: matplotlib
35
32
  Requires-Dist: executorlib
36
33
  Requires-Dist: hydra-core
37
- Requires-Dist: pipefunc
38
34
  Requires-Dist: typer
39
35
  Requires-Dist: loguru
40
36
  Requires-Python: >=3.12
@@ -62,6 +58,14 @@ The `graphatoms` is a Python library designed for chemical graph theory analysis
62
58
  - **Dataclasses**: Pydantic-based data models for type-safe data handling
63
59
  - **Array API Compatibility**: Full support for array API standard for cross-framework compatibility (NumPy, PyTorch, JAX, CuPy, etc.)
64
60
  - **Subgraph Operations**: Backend-agnostic subgraph extraction with relabeling support using array-api-compat and array-api-extra
61
+ - **CLI Entry Points**: Three console scripts for configuration, execution, and inspection:
62
+ - `graphatoms-config`: Resolve and print the Hydra/OmegaConf run configuration
63
+ - `graphatoms-run`: Launch a run
64
+ - `run_type=otfkmc` for on-the-fly kinetic Monte Carlo simulation
65
+ - `run_type=rxngen` for reaction network generation
66
+ - `graphatoms-network`: Inspect and visualize a stored reaction network
67
+ - **Hydra-driven Configuration**: Composable, override-friendly config via Hydra/OmegaConf with grouped groups (`atoms`, `bonds`, `calculator`)
68
+ - **Pluggable Parallel Backends**: Switch executors at the config level — `serial`, `multiprocessing`, `ray`, `dask`, `executorlib` — for distributed/on-the-fly KMC workflows
65
69
 
66
70
  ## Module Structure
67
71
 
@@ -69,18 +73,33 @@ The `graphatoms` is a Python library designed for chemical graph theory analysis
69
73
  src/graphatoms/
70
74
  ├── arrayapi/ # Array API compatibility layer
71
75
  ├── dataclasses/ # Pydantic-based data models
76
+ ├── enterpoint/ # Entry points: CLI, config, runners, network, parallel
77
+ │ ├── config/ # Hydra/OmegaConf configuration (atoms, bonds, calculator)
78
+ │ ├── network/ # Reaction network: scheduler, recorder, metadata
79
+ │ ├── parallel/ # Pluggable executors (serial, multiprocessing, ray, dask, executorlib)
80
+ │ ├── runner/ # Runners (otfkmc, rxngen) and helpers
81
+ │ ├── steps/ # Step primitives for runners
82
+ │ └── view.py # CLI viewer for reactions
72
83
  ├── geometry/ # Geometric operations
73
84
  ├── reaction/ # Reaction classes and KMC events
74
- │ ├── base/ # Abstract base classes
75
- │ ├── event/ # KMC events (adsorption, desorption, reaction)
76
- │ ├── mcmove/ # Monte Carlo moves
77
- │ ├── mdwarpper/ # MD wrapper
78
- │ └── network/ # Reaction network
85
+ │ ├── _event.py # Event base and event info
86
+ │ ├── reaction.py # Reaction class
87
+ │ └── xxsorption.py # Adsorption/Desorption events
79
88
  ├── system/ # Core system classes
80
- │ ├── atoms/ # Atomic structure handling
81
- │ ├── database/ # Database storage backends
82
- │ └── graph/ # Graph-based system representation
89
+ │ ├── atoms.py # Atomic structure handling
90
+ │ ├── bonds.py # Bond list operations
91
+ │ ├── graph.py # Graph-based system representation
92
+ │ ├── system.py # System abstract base
93
+ │ ├── sysCluster.py # Cluster system
94
+ │ ├── sysGas.py # Gas molecule system
95
+ │ └── database/ # Database storage backends (HDF5, SQLite, folder)
83
96
  └── utils/ # Utility functions
97
+ ├── adsorption.py # Adsorption site helper
98
+ ├── asetools.py # ASE-related tools
99
+ ├── bytestool.py # Byte-level helpers
100
+ ├── logger.py # Logging setup
101
+ ├── parser.py # Hydra argument parsing
102
+ ├── rdutils.py # RDKit utilities
84
103
  └── subgraph.py # Array API compatible subgraph operations
85
104
  ```
86
105
 
@@ -103,6 +122,10 @@ src/graphatoms/
103
122
  - pydantic >= 2.10
104
123
  - python-snappy >= 0.7.3
105
124
  - loguru
125
+ - pandas >= 2
126
+ - scipy >= 1.10
127
+ - typer
128
+ - executorlib
106
129
 
107
130
  ## Installation
108
131
 
@@ -17,6 +17,14 @@ The `graphatoms` is a Python library designed for chemical graph theory analysis
17
17
  - **Dataclasses**: Pydantic-based data models for type-safe data handling
18
18
  - **Array API Compatibility**: Full support for array API standard for cross-framework compatibility (NumPy, PyTorch, JAX, CuPy, etc.)
19
19
  - **Subgraph Operations**: Backend-agnostic subgraph extraction with relabeling support using array-api-compat and array-api-extra
20
+ - **CLI Entry Points**: Three console scripts for configuration, execution, and inspection:
21
+ - `graphatoms-config`: Resolve and print the Hydra/OmegaConf run configuration
22
+ - `graphatoms-run`: Launch a run
23
+ - `run_type=otfkmc` for on-the-fly kinetic Monte Carlo simulation
24
+ - `run_type=rxngen` for reaction network generation
25
+ - `graphatoms-network`: Inspect and visualize a stored reaction network
26
+ - **Hydra-driven Configuration**: Composable, override-friendly config via Hydra/OmegaConf with grouped groups (`atoms`, `bonds`, `calculator`)
27
+ - **Pluggable Parallel Backends**: Switch executors at the config level — `serial`, `multiprocessing`, `ray`, `dask`, `executorlib` — for distributed/on-the-fly KMC workflows
20
28
 
21
29
  ## Module Structure
22
30
 
@@ -24,18 +32,33 @@ The `graphatoms` is a Python library designed for chemical graph theory analysis
24
32
  src/graphatoms/
25
33
  ├── arrayapi/ # Array API compatibility layer
26
34
  ├── dataclasses/ # Pydantic-based data models
35
+ ├── enterpoint/ # Entry points: CLI, config, runners, network, parallel
36
+ │ ├── config/ # Hydra/OmegaConf configuration (atoms, bonds, calculator)
37
+ │ ├── network/ # Reaction network: scheduler, recorder, metadata
38
+ │ ├── parallel/ # Pluggable executors (serial, multiprocessing, ray, dask, executorlib)
39
+ │ ├── runner/ # Runners (otfkmc, rxngen) and helpers
40
+ │ ├── steps/ # Step primitives for runners
41
+ │ └── view.py # CLI viewer for reactions
27
42
  ├── geometry/ # Geometric operations
28
43
  ├── reaction/ # Reaction classes and KMC events
29
- │ ├── base/ # Abstract base classes
30
- │ ├── event/ # KMC events (adsorption, desorption, reaction)
31
- │ ├── mcmove/ # Monte Carlo moves
32
- │ ├── mdwarpper/ # MD wrapper
33
- │ └── network/ # Reaction network
44
+ │ ├── _event.py # Event base and event info
45
+ │ ├── reaction.py # Reaction class
46
+ │ └── xxsorption.py # Adsorption/Desorption events
34
47
  ├── system/ # Core system classes
35
- │ ├── atoms/ # Atomic structure handling
36
- │ ├── database/ # Database storage backends
37
- │ └── graph/ # Graph-based system representation
48
+ │ ├── atoms.py # Atomic structure handling
49
+ │ ├── bonds.py # Bond list operations
50
+ │ ├── graph.py # Graph-based system representation
51
+ │ ├── system.py # System abstract base
52
+ │ ├── sysCluster.py # Cluster system
53
+ │ ├── sysGas.py # Gas molecule system
54
+ │ └── database/ # Database storage backends (HDF5, SQLite, folder)
38
55
  └── utils/ # Utility functions
56
+ ├── adsorption.py # Adsorption site helper
57
+ ├── asetools.py # ASE-related tools
58
+ ├── bytestool.py # Byte-level helpers
59
+ ├── logger.py # Logging setup
60
+ ├── parser.py # Hydra argument parsing
61
+ ├── rdutils.py # RDKit utilities
39
62
  └── subgraph.py # Array API compatible subgraph operations
40
63
  ```
41
64
 
@@ -58,6 +81,10 @@ src/graphatoms/
58
81
  - pydantic >= 2.10
59
82
  - python-snappy >= 0.7.3
60
83
  - loguru
84
+ - pandas >= 2
85
+ - scipy >= 1.10
86
+ - typer
87
+ - executorlib
61
88
 
62
89
  ## Installation
63
90
 
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "graphatoms"
7
- version = "2.0.0"
7
+ version = "2.1.1"
8
8
  readme = "README.md"
9
9
  description = "The Chemical Core Class for Graph Theory Analysis."
10
10
  license-files = ["src/LICENSE"]
@@ -42,12 +42,8 @@ dependencies = [
42
42
  "tomli; python_version < '3.11'",
43
43
  "tomli-w",
44
44
  "typing-extensions",
45
- "plotext",
46
- "plotext-plus",
47
- "matplotlib",
48
45
  "executorlib",
49
46
  "hydra-core",
50
- "pipefunc",
51
47
  "typer",
52
48
  "loguru",
53
49
  ]
@@ -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.0.0"
15
+ version = "2.1.1"
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" }]
@@ -60,12 +60,8 @@ dependencies = [
60
60
  "typing-extensions",
61
61
 
62
62
  # Other
63
- "plotext",
64
- "plotext-plus",
65
- "matplotlib",
66
63
  "executorlib",
67
64
  "hydra-core",
68
- "pipefunc",
69
65
  "typer",
70
66
  "loguru",
71
67
  ]
@@ -66,7 +66,7 @@ class Config:
66
66
 
67
67
  calculator: CalcConfig = MISSING
68
68
 
69
- outputs: str = "./zzz"
69
+ outputs: str = "."
70
70
  max_steps: int = 100000
71
71
  max_times: float = 1000.0 # seconds
72
72
  run_type: str = "otfkmc" # otfkmc, rxngen
@@ -98,8 +98,6 @@ cs.store(group="calculator", name="calc_nequip", node=NequipConfig)
98
98
  version_base=None,
99
99
  )
100
100
  def print_config(cfg: Config) -> None:
101
- from shutil import rmtree
102
-
103
101
  print(OmegaConf.to_yaml(cfg))
104
102
  print("""
105
103
  hydra:
@@ -107,4 +105,3 @@ hydra:
107
105
  dir: ${outputs}
108
106
  verbose: ${debug}
109
107
  """)
110
- rmtree(Path(cfg.outputs))
@@ -4,8 +4,14 @@ from pathlib import Path
4
4
  from typing import Literal
5
5
 
6
6
  from graphatoms.enterpoint.config import EventConfig
7
- from graphatoms.reaction import EventBase, EventInfo, Reaction
8
- from graphatoms.system import Cluster, SysGraph
7
+ from graphatoms.reaction import (
8
+ Adsorption,
9
+ Desorption,
10
+ EventBase,
11
+ EventInfo,
12
+ Reaction,
13
+ )
14
+ from graphatoms.system import Gas, SysGraph
9
15
  from graphatoms.system.database import DatabaseABC, get_db
10
16
 
11
17
  from ._metadata import MetaData
@@ -14,14 +20,14 @@ from ._recorder import Recorder
14
20
  from ._scheduler import Scheduler
15
21
 
16
22
  __all__ = [
17
- "RxNet",
18
23
  "MetaData",
19
24
  "Recorder",
20
25
  "Scheduler",
26
+ "ReactionNetwork",
21
27
  ]
22
28
 
23
29
 
24
- class RxNet:
30
+ class ReactionNetwork:
25
31
  def __init__(
26
32
  self,
27
33
  path: Path | str,
@@ -81,16 +87,26 @@ class RxNet:
81
87
  self.metadata: MetaData = MetaData()
82
88
 
83
89
  # initialize the databases
84
- lst: list[DatabaseABC] = [
90
+ (
91
+ self.db_ts,
92
+ self.db_gas,
93
+ self.db_minima,
94
+ self.db_cluster,
95
+ self.db_system,
96
+ ) = [
85
97
  get_db(
86
98
  path=path,
87
99
  format=format,
88
100
  prefix=prefix,
89
101
  append=restart,
90
102
  )
91
- for prefix in ["ts", "gas", "minima"]
103
+ for prefix in ["ts", "gas", "minima", "cluster", "system"]
92
104
  ]
93
- self.db_ts, self.db_gas, self.db_minima = lst
105
+ assert isinstance(self.db_ts, DatabaseABC)
106
+ assert isinstance(self.db_gas, DatabaseABC)
107
+ assert isinstance(self.db_minima, DatabaseABC)
108
+ assert isinstance(self.db_cluster, DatabaseABC)
109
+ assert isinstance(self.db_system, DatabaseABC)
94
110
 
95
111
  def summary(self) -> str:
96
112
  """Return the summary of the network."""
@@ -102,16 +118,24 @@ class RxNet:
102
118
  self.scheduler.write_npz(self.__path / "scheduler.npz")
103
119
  self.metadata.persistence(self.__path)
104
120
 
105
- def read(self, key: str) -> tuple[EventInfo, EventBase]:
121
+ def read_event(self, key: str) -> tuple[EventInfo, EventBase]:
122
+ """Read the event from the database."""
106
123
  if self.metadata.has(key):
107
124
  info = self.metadata.read(key)
108
125
  if info.key_g is not None:
109
- raise NotImplementedError("Ads/Des is not supported.")
126
+ assert info.key_t is None
127
+ g = Gas.from_ase(self.db_gas[info.key_g])
128
+ r = SysGraph.from_ase(self.db_minima[info.key_r])
129
+ p = SysGraph.from_ase(self.db_minima[info.key_p])
130
+ if r.natoms < p.natoms:
131
+ return info, Adsorption(G=g, R=r, P=p)
132
+ else:
133
+ return info, Desorption(G=g, R=r, P=p)
110
134
  else:
111
135
  assert info.key_t is not None
112
- ts = Cluster.from_ase(self.db_ts[info.key_t])
113
- r = Cluster.from_ase(self.db_minima[info.key_r])
114
- p = Cluster.from_ase(self.db_minima[info.key_p])
136
+ ts = SysGraph.from_ase(self.db_ts[info.key_t])
137
+ r = SysGraph.from_ase(self.db_minima[info.key_r])
138
+ p = SysGraph.from_ase(self.db_minima[info.key_p])
115
139
  return info, Reaction(T=ts, R=r, P=p)
116
140
  else:
117
141
  raise ValueError(f"Event {key} is not in the database.")
@@ -143,7 +167,7 @@ class RxNet:
143
167
  fname.write_bytes(pickle.dumps(event))
144
168
  fname.with_suffix(".err").write_text(msg)
145
169
  raise ValueError(msg)
146
- is_new = self._write(
170
+ is_new = self.write_event(
147
171
  event,
148
172
  for_cluster,
149
173
  for_system,
@@ -154,7 +178,7 @@ class RxNet:
154
178
  else:
155
179
  raise ValueError(f"Unknown event type: {type(event)}")
156
180
 
157
- def _write(
181
+ def write_event(
158
182
  self,
159
183
  event: EventBase,
160
184
  for_cluster: str,
@@ -170,12 +194,12 @@ class RxNet:
170
194
  else:
171
195
  self.metadata.write(event, for_cluster, for_system)
172
196
  try:
173
- self.__write(event.R, "minima")
174
- self.__write(event.P, "minima")
197
+ self.write_sysgraph(event.R, "minima")
198
+ self.write_sysgraph(event.P, "minima")
175
199
  if event.G is not None:
176
- self.__write(event.G, "gas")
200
+ self.write_sysgraph(event.G, "gas")
177
201
  if event.T is not None:
178
- self.__write(event.T, "ts")
202
+ self.write_sysgraph(event.T, "ts")
179
203
  if persist:
180
204
  self.persistence()
181
205
  return True
@@ -201,17 +225,21 @@ class RxNet:
201
225
  self.persistence()
202
226
  raise e
203
227
 
204
- def __write(
228
+ def write_sysgraph(
205
229
  self,
206
230
  sysgraph: SysGraph,
207
- type: Literal["minima", "ts", "gas"] | str,
231
+ type: Literal["minima", "ts", "gas", "cluster", "system"] | str,
208
232
  ) -> bool:
209
233
  """Return True if the value is new, False otherwise."""
210
- if type == "minima":
234
+ if type.lower() == "minima":
211
235
  return self.db_minima.add(sysgraph, check_positions=True)
212
- elif type == "ts":
236
+ elif type.lower() == "ts":
213
237
  return self.db_ts.add(sysgraph, check_positions=True)
214
- elif type == "gas":
238
+ elif type.lower() == "gas":
215
239
  return self.db_gas.add(sysgraph, check_positions=False)
240
+ elif type.lower() == "system":
241
+ return self.db_system.add(sysgraph, check_positions=True)
242
+ elif type.lower() == "cluster":
243
+ return self.db_cluster.add(sysgraph, check_positions=True)
216
244
  else:
217
245
  raise ValueError(f"Unknown type: {type}")
@@ -14,6 +14,7 @@ from pydantic import (
14
14
  from graphatoms.dataclasses import OurBaseModel
15
15
  from graphatoms.enterpoint.config import EventConfig
16
16
  from graphatoms.reaction import EventBase, EventInfo
17
+ from graphatoms.system.bonds import matchmode2nmatch
17
18
 
18
19
  __all__ = ["MetaData"]
19
20
 
@@ -110,6 +111,7 @@ class _MetaDataTable(BaseModel):
110
111
  *,
111
112
  cluster_key: str | None = None,
112
113
  system_key: str | None = None,
114
+ exclude_gas: bool = False,
113
115
  **kwargs,
114
116
  ) -> int:
115
117
  if cluster_key is not None:
@@ -117,7 +119,10 @@ class _MetaDataTable(BaseModel):
117
119
  [
118
120
  self.count[i]
119
121
  for i, ck in enumerate(self.for_cluster)
120
- if ck == cluster_key
122
+ if (
123
+ ck == cluster_key
124
+ and ((not exclude_gas) or self.key_g[i] is None)
125
+ )
121
126
  ]
122
127
  + [0]
123
128
  )
@@ -126,7 +131,10 @@ class _MetaDataTable(BaseModel):
126
131
  [
127
132
  self.count[i]
128
133
  for i, sk in enumerate(self.for_system)
129
- if sk == system_key
134
+ if (
135
+ sk == system_key
136
+ and ((not exclude_gas) or self.key_g[i] is None)
137
+ )
130
138
  ]
131
139
  + [0]
132
140
  )
@@ -174,7 +182,8 @@ class MetaData(BaseModel):
174
182
  names = ["rxn_key", "is_forward", "nmatched", "rate"]
175
183
  for (rxn_key, is_forward), single_match_res in matching_dct.items():
176
184
  i: int = self.table.key_rxn.index(rxn_key)
177
- nmatched = int(single_match_res.shape[0])
185
+ # Eliminate the overestimation caused by permutation symmetry.
186
+ nmatched = matchmode2nmatch(single_match_res)
178
187
  if is_forward:
179
188
  rate = self.table.rate_forword[i]
180
189
  else:
@@ -23,14 +23,15 @@ Ref:
23
23
  """
24
24
 
25
25
  from collections import defaultdict
26
- from typing import override
26
+ from datetime import datetime
27
+ from typing import Annotated, override
27
28
 
28
29
  import pydantic
29
30
 
30
31
  from graphatoms.dataclasses import OurBaseModel # type: ignore
31
32
 
32
33
 
33
- class _OldNewRecorder(OurBaseModel):
34
+ class _RecorderBase(pydantic.BaseModel):
34
35
  old: pydantic.NonNegativeInt = 0
35
36
  new: pydantic.NonNegativeInt = 0
36
37
  fail: pydantic.NonNegativeInt = 0
@@ -47,6 +48,70 @@ class _OldNewRecorder(OurBaseModel):
47
48
  """
48
49
  return sum([self.old, self.new, self.fail])
49
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
+
96
+ class _OldNewRecorder(OurBaseModel, _RecorderBase):
97
+ @pydantic.validate_call
98
+ def get_williams_confidence(
99
+ self, min_found: pydantic.NonNegativeInt
100
+ ) -> Annotated[float, pydantic.Field(ge=0.5, lt=1.0)]:
101
+ """The Williams confidence formula.
102
+
103
+ Args:
104
+ min_found: The minimum time found for all events.
105
+
106
+ Returns:
107
+ The confidence value.
108
+ """
109
+ m = self.continuous_nonnew
110
+ factor = min_found / self.total
111
+ factor2 = 1 / (1 + factor)
112
+ value = 1 / (1 + factor2**m)
113
+ return value
114
+
50
115
  @pydantic.validate_call
51
116
  def exploration_can_be_finished(
52
117
  self,
@@ -61,10 +126,7 @@ class _OldNewRecorder(OurBaseModel):
61
126
  "min_found must be provided for Williams"
62
127
  + " formula (i.e. confidence < 1)."
63
128
  )
64
- m = self.continuous_nonnew
65
- factor = min_found / self.total
66
- factor2 = 1 / (1 + factor)
67
- value = 1 / (1 + factor2**m)
129
+ value = self.get_williams_confidence(min_found)
68
130
  else:
69
131
  # Use Xu-Henkelman formula
70
132
  value = self.continuous_old
@@ -106,7 +168,7 @@ class _OldNewRecorder(OurBaseModel):
106
168
  class Recorder(OurBaseModel):
107
169
  system: set[str] = set()
108
170
  cluster: dict[str, _OldNewRecorder] = defaultdict(_OldNewRecorder)
109
- adsorption: set[str] = set()
171
+ adsorption: dict[str, _OldNewRecorder] = defaultdict(_OldNewRecorder)
110
172
  bulk: set[str] = set()
111
173
 
112
174
  @override
@@ -119,8 +181,10 @@ class Recorder(OurBaseModel):
119
181
 
120
182
 
121
183
  if __name__ == "__main__":
184
+ from io import StringIO
122
185
  from pathlib import Path
123
186
 
187
+ import pandas as pd
124
188
  obj = Recorder()
125
189
  obj.system.add("fdsafs")
126
190
  obj.cluster["fdsafs"].new += 1
@@ -128,3 +192,17 @@ if __name__ == "__main__":
128
192
  print(obj)
129
193
  print(repr(obj))
130
194
  obj.write_json(Path("a.json"))
195
+
196
+ io = StringIO()
197
+ io.write(RecorderInfo.get_csv_title() + "\n")
198
+ a = RecorderInfo(confidence=0.6)
199
+ io.write(RecorderInfo(confidence=0.5).to_csv_line() + "\n")
200
+ io.write(RecorderInfo(confidence=0.5).to_csv_line() + "\n")
201
+ io.write(a.to_csv_line() + "\n")
202
+
203
+ s = io.getvalue()
204
+ print(s)
205
+ df = pd.read_csv(StringIO(s))
206
+ print("df:")
207
+ print(df)
208
+ print(df.sort_values(by="create_at", ascending=True))
@@ -0,0 +1,32 @@
1
+ import os
2
+
3
+ os.environ["HYDRA_FULL_ERROR"] = "1"
4
+
5
+ import hydra
6
+
7
+ from graphatoms.enterpoint.config import CONFIG_DIR, Config
8
+
9
+ from .general.otfkmc import OTFKMC as OnTheFlyKMC
10
+ from .general.rxngen import ReactionNetworkGenerator
11
+ from .ray.otfkmc import RayOTFKMC as RayOnTheFlyKMC
12
+ from .ray.rxngen import RayReactionNetworkGenerator
13
+
14
+
15
+ @hydra.main(
16
+ config_path=CONFIG_DIR.as_posix(),
17
+ config_name="run",
18
+ version_base=None,
19
+ )
20
+ def run(cfg: Config) -> None:
21
+ if str(cfg.run_type).lower() == "otfkmc":
22
+ if str(cfg.parallel).lower() == "ray":
23
+ RayOnTheFlyKMC(config=cfg).run()
24
+ else:
25
+ OnTheFlyKMC(config=cfg).run()
26
+ elif str(cfg.run_type).lower() == "rxngen":
27
+ if str(cfg.parallel).lower() == "ray":
28
+ RayReactionNetworkGenerator(config=cfg).run()
29
+ else:
30
+ ReactionNetworkGenerator(config=cfg).run()
31
+ else:
32
+ raise ValueError(f" run_type `{cfg.run_type}` is not supported.")
@@ -0,0 +1,21 @@
1
+ from ._base import RunnerABC
2
+ from ._errors import CheckVibrationFailed, HelperException, OptimizationFailed
3
+ from ._helper import (
4
+ helper_adsorption,
5
+ helper_apply,
6
+ helper_dimer,
7
+ helper_match,
8
+ helper_optimization,
9
+ )
10
+
11
+ __all__ = [
12
+ "RunnerABC",
13
+ "CheckVibrationFailed",
14
+ "HelperException",
15
+ "OptimizationFailed",
16
+ "helper_adsorption",
17
+ "helper_apply",
18
+ "helper_dimer",
19
+ "helper_match",
20
+ "helper_optimization",
21
+ ]