reaxkit 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reaxkit/__init__.py +0 -0
- reaxkit/analysis/__init__.py +0 -0
- reaxkit/analysis/composed/RDF_analyzer.py +560 -0
- reaxkit/analysis/composed/__init__.py +0 -0
- reaxkit/analysis/composed/connectivity_analyzer.py +706 -0
- reaxkit/analysis/composed/coordination_analyzer.py +144 -0
- reaxkit/analysis/composed/electrostatics_analyzer.py +687 -0
- reaxkit/analysis/per_file/__init__.py +0 -0
- reaxkit/analysis/per_file/control_analyzer.py +165 -0
- reaxkit/analysis/per_file/eregime_analyzer.py +108 -0
- reaxkit/analysis/per_file/ffield_analyzer.py +305 -0
- reaxkit/analysis/per_file/fort13_analyzer.py +79 -0
- reaxkit/analysis/per_file/fort57_analyzer.py +106 -0
- reaxkit/analysis/per_file/fort73_analyzer.py +61 -0
- reaxkit/analysis/per_file/fort74_analyzer.py +65 -0
- reaxkit/analysis/per_file/fort76_analyzer.py +191 -0
- reaxkit/analysis/per_file/fort78_analyzer.py +154 -0
- reaxkit/analysis/per_file/fort79_analyzer.py +83 -0
- reaxkit/analysis/per_file/fort7_analyzer.py +393 -0
- reaxkit/analysis/per_file/fort99_analyzer.py +411 -0
- reaxkit/analysis/per_file/molfra_analyzer.py +359 -0
- reaxkit/analysis/per_file/params_analyzer.py +258 -0
- reaxkit/analysis/per_file/summary_analyzer.py +84 -0
- reaxkit/analysis/per_file/trainset_analyzer.py +84 -0
- reaxkit/analysis/per_file/vels_analyzer.py +95 -0
- reaxkit/analysis/per_file/xmolout_analyzer.py +528 -0
- reaxkit/cli.py +181 -0
- reaxkit/count_loc.py +276 -0
- reaxkit/data/alias.yaml +89 -0
- reaxkit/data/constants.yaml +27 -0
- reaxkit/data/reaxff_input_files_contents.yaml +186 -0
- reaxkit/data/reaxff_output_files_contents.yaml +301 -0
- reaxkit/data/units.yaml +38 -0
- reaxkit/help/__init__.py +0 -0
- reaxkit/help/help_index_loader.py +531 -0
- reaxkit/help/introspection_utils.py +131 -0
- reaxkit/io/__init__.py +0 -0
- reaxkit/io/base_handler.py +165 -0
- reaxkit/io/generators/__init__.py +0 -0
- reaxkit/io/generators/control_generator.py +123 -0
- reaxkit/io/generators/eregime_generator.py +341 -0
- reaxkit/io/generators/geo_generator.py +967 -0
- reaxkit/io/generators/trainset_generator.py +1758 -0
- reaxkit/io/generators/tregime_generator.py +113 -0
- reaxkit/io/generators/vregime_generator.py +164 -0
- reaxkit/io/generators/xmolout_generator.py +304 -0
- reaxkit/io/handlers/__init__.py +0 -0
- reaxkit/io/handlers/control_handler.py +209 -0
- reaxkit/io/handlers/eregime_handler.py +122 -0
- reaxkit/io/handlers/ffield_handler.py +812 -0
- reaxkit/io/handlers/fort13_handler.py +123 -0
- reaxkit/io/handlers/fort57_handler.py +143 -0
- reaxkit/io/handlers/fort73_handler.py +145 -0
- reaxkit/io/handlers/fort74_handler.py +155 -0
- reaxkit/io/handlers/fort76_handler.py +195 -0
- reaxkit/io/handlers/fort78_handler.py +142 -0
- reaxkit/io/handlers/fort79_handler.py +227 -0
- reaxkit/io/handlers/fort7_handler.py +264 -0
- reaxkit/io/handlers/fort99_handler.py +128 -0
- reaxkit/io/handlers/geo_handler.py +224 -0
- reaxkit/io/handlers/molfra_handler.py +184 -0
- reaxkit/io/handlers/params_handler.py +137 -0
- reaxkit/io/handlers/summary_handler.py +135 -0
- reaxkit/io/handlers/trainset_handler.py +658 -0
- reaxkit/io/handlers/vels_handler.py +293 -0
- reaxkit/io/handlers/xmolout_handler.py +174 -0
- reaxkit/utils/__init__.py +0 -0
- reaxkit/utils/alias.py +219 -0
- reaxkit/utils/cache.py +77 -0
- reaxkit/utils/constants.py +75 -0
- reaxkit/utils/equation_of_states.py +96 -0
- reaxkit/utils/exceptions.py +27 -0
- reaxkit/utils/frame_utils.py +175 -0
- reaxkit/utils/log.py +43 -0
- reaxkit/utils/media/__init__.py +0 -0
- reaxkit/utils/media/convert.py +90 -0
- reaxkit/utils/media/make_video.py +91 -0
- reaxkit/utils/media/plotter.py +812 -0
- reaxkit/utils/numerical/__init__.py +0 -0
- reaxkit/utils/numerical/extrema_finder.py +96 -0
- reaxkit/utils/numerical/moving_average.py +103 -0
- reaxkit/utils/numerical/numerical_calcs.py +75 -0
- reaxkit/utils/numerical/signal_ops.py +135 -0
- reaxkit/utils/path.py +55 -0
- reaxkit/utils/units.py +104 -0
- reaxkit/webui/__init__.py +0 -0
- reaxkit/webui/app.py +0 -0
- reaxkit/webui/components.py +0 -0
- reaxkit/webui/layouts.py +0 -0
- reaxkit/webui/utils.py +0 -0
- reaxkit/workflows/__init__.py +0 -0
- reaxkit/workflows/composed/__init__.py +0 -0
- reaxkit/workflows/composed/coordination_workflow.py +393 -0
- reaxkit/workflows/composed/electrostatics_workflow.py +587 -0
- reaxkit/workflows/composed/xmolout_fort7_workflow.py +343 -0
- reaxkit/workflows/meta/__init__.py +0 -0
- reaxkit/workflows/meta/help_workflow.py +136 -0
- reaxkit/workflows/meta/introspection_workflow.py +235 -0
- reaxkit/workflows/meta/make_video_workflow.py +61 -0
- reaxkit/workflows/meta/plotter_workflow.py +601 -0
- reaxkit/workflows/per_file/__init__.py +0 -0
- reaxkit/workflows/per_file/control_workflow.py +110 -0
- reaxkit/workflows/per_file/eregime_workflow.py +267 -0
- reaxkit/workflows/per_file/ffield_workflow.py +390 -0
- reaxkit/workflows/per_file/fort13_workflow.py +86 -0
- reaxkit/workflows/per_file/fort57_workflow.py +137 -0
- reaxkit/workflows/per_file/fort73_workflow.py +151 -0
- reaxkit/workflows/per_file/fort74_workflow.py +88 -0
- reaxkit/workflows/per_file/fort76_workflow.py +188 -0
- reaxkit/workflows/per_file/fort78_workflow.py +135 -0
- reaxkit/workflows/per_file/fort79_workflow.py +314 -0
- reaxkit/workflows/per_file/fort7_workflow.py +592 -0
- reaxkit/workflows/per_file/fort83_workflow.py +60 -0
- reaxkit/workflows/per_file/fort99_workflow.py +223 -0
- reaxkit/workflows/per_file/geo_workflow.py +554 -0
- reaxkit/workflows/per_file/molfra_workflow.py +577 -0
- reaxkit/workflows/per_file/params_workflow.py +135 -0
- reaxkit/workflows/per_file/summary_workflow.py +161 -0
- reaxkit/workflows/per_file/trainset_workflow.py +356 -0
- reaxkit/workflows/per_file/tregime_workflow.py +79 -0
- reaxkit/workflows/per_file/vels_workflow.py +309 -0
- reaxkit/workflows/per_file/vregime_workflow.py +75 -0
- reaxkit/workflows/per_file/xmolout_workflow.py +678 -0
- reaxkit-1.0.0.dist-info/METADATA +128 -0
- reaxkit-1.0.0.dist-info/RECORD +130 -0
- reaxkit-1.0.0.dist-info/WHEEL +5 -0
- reaxkit-1.0.0.dist-info/entry_points.txt +2 -0
- reaxkit-1.0.0.dist-info/licenses/AUTHORS.md +20 -0
- reaxkit-1.0.0.dist-info/licenses/LICENSE +21 -0
- reaxkit-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Coordination (valence satisfaction) analysis utilities.
|
|
3
|
+
|
|
4
|
+
This module provides functions for classifying atomic coordination in a frame
|
|
5
|
+
by comparing each atom's total bond order (typically from ``fort.7``) to its
|
|
6
|
+
expected valence. The resulting labels help identify under- and over-coordinated
|
|
7
|
+
sites (e.g., dangling bonds, over-saturated atoms, and coordination defects).
|
|
8
|
+
|
|
9
|
+
Typical use cases include:
|
|
10
|
+
|
|
11
|
+
- classifying atoms as under / well / over coordinated for a single frame
|
|
12
|
+
- attaching a numeric status code and a human-readable label
|
|
13
|
+
- using coordination labels as defect indicators in post-processing
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
from typing import Mapping, Sequence, Optional, Literal
|
|
19
|
+
import numpy as np
|
|
20
|
+
import pandas as pd
|
|
21
|
+
|
|
22
|
+
Status = Literal[-1, 0, +1] # under, coordinated, over
|
|
23
|
+
|
|
24
|
+
def classify_coordination_for_frame(
|
|
25
|
+
*,
|
|
26
|
+
sum_bos: Sequence[float],
|
|
27
|
+
atom_types: Sequence[str],
|
|
28
|
+
valences: Mapping[str, float],
|
|
29
|
+
threshold: float = 0.3,
|
|
30
|
+
require_all_valences: bool = True,
|
|
31
|
+
) -> pd.DataFrame:
|
|
32
|
+
""" Classify atoms in a single frame as under-, well-, or over-coordinated.
|
|
33
|
+
|
|
34
|
+
Classification is based on ``delta = sum_bos - valence`` and a tolerance
|
|
35
|
+
threshold:
|
|
36
|
+
|
|
37
|
+
- ``status = -1``: under-coordinated (``delta < -threshold``)
|
|
38
|
+
- ``status = 0``: well-coordinated (``|delta| <= threshold``)
|
|
39
|
+
- ``status = +1``: over-coordinated (``delta > threshold``)
|
|
40
|
+
|
|
41
|
+
Works on
|
|
42
|
+
--------
|
|
43
|
+
Fort.7-derived arrays — ``sum_BOs`` + atom types (typically from ``fort.7`` and ``xmolout``)
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
sum_bos : sequence of float
|
|
48
|
+
Per-atom total bond order values (e.g., the ``sum_BOs`` column from fort.7).
|
|
49
|
+
atom_types : sequence of str
|
|
50
|
+
Per-atom type symbols corresponding to ``sum_bos`` (e.g., ``["Al", "N", ...]``).
|
|
51
|
+
valences : mapping of str to float
|
|
52
|
+
Expected valence for each atom type (e.g., ``{"Al": 3.0, "N": 3.0}``).
|
|
53
|
+
threshold : float, default=0.3
|
|
54
|
+
Tolerance used for deciding under/over coordination.
|
|
55
|
+
require_all_valences : bool, default=True
|
|
56
|
+
If True, raise an error if any atom type is missing from ``valences``.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
pandas.DataFrame
|
|
61
|
+
Per-atom classification table with columns:
|
|
62
|
+
``atom_id``, ``atom_type``, ``sum_BOs``, ``valence``, ``delta``, ``status``.
|
|
63
|
+
|
|
64
|
+
Examples
|
|
65
|
+
--------
|
|
66
|
+
>>> sum_bos = [2.8, 3.1, 0.9]
|
|
67
|
+
>>> atom_types = ["Al", "Al", "H"]
|
|
68
|
+
>>> valences = {"Al": 3.0, "H": 1.0}
|
|
69
|
+
>>> df = classify_coordination_for_frame(
|
|
70
|
+
... sum_bos=sum_bos, atom_types=atom_types, valences=valences, threshold=0.3
|
|
71
|
+
... )
|
|
72
|
+
"""
|
|
73
|
+
sum_bos = np.asarray(sum_bos, dtype=float)
|
|
74
|
+
types = np.asarray(atom_types, dtype=object)
|
|
75
|
+
if sum_bos.shape[0] != types.shape[0]:
|
|
76
|
+
raise ValueError(f"Length mismatch: sum_bos({sum_bos.shape[0]}) vs atom_types({types.shape[0]})")
|
|
77
|
+
|
|
78
|
+
val_arr = np.empty_like(sum_bos, dtype=float)
|
|
79
|
+
missing: list[str] = []
|
|
80
|
+
for i, t in enumerate(types):
|
|
81
|
+
if t in valences:
|
|
82
|
+
val_arr[i] = float(valences[t])
|
|
83
|
+
else:
|
|
84
|
+
missing.append(str(t))
|
|
85
|
+
val_arr[i] = np.nan
|
|
86
|
+
|
|
87
|
+
if missing and require_all_valences:
|
|
88
|
+
uniq = ", ".join(sorted(set(missing)))
|
|
89
|
+
raise KeyError(f"Missing valence(s) for atom types: {uniq}")
|
|
90
|
+
|
|
91
|
+
delta = sum_bos - val_arr
|
|
92
|
+
status = np.full(sum_bos.shape, np.nan)
|
|
93
|
+
if np.isfinite(threshold) and threshold >= 0:
|
|
94
|
+
status = np.where(delta < -threshold, -1, status)
|
|
95
|
+
status = np.where(np.abs(delta) <= threshold, 0, status)
|
|
96
|
+
status = np.where(delta > threshold, +1, status)
|
|
97
|
+
|
|
98
|
+
out = pd.DataFrame({
|
|
99
|
+
"atom_id": np.arange(1, len(sum_bos) + 1, dtype=int), # 1-based
|
|
100
|
+
"atom_type": types.astype(str),
|
|
101
|
+
"sum_BOs": sum_bos.astype(float),
|
|
102
|
+
"valence": val_arr.astype(float),
|
|
103
|
+
"delta": delta.astype(float),
|
|
104
|
+
"status": status.astype(float),
|
|
105
|
+
})
|
|
106
|
+
if out["status"].notna().all():
|
|
107
|
+
out["status"] = out["status"].astype(int)
|
|
108
|
+
return out
|
|
109
|
+
|
|
110
|
+
def status_label(series: Sequence[int | float]) -> list[Optional[str]]:
|
|
111
|
+
"""Convert numeric coordination status codes into human-readable labels.
|
|
112
|
+
|
|
113
|
+
Mapping:
|
|
114
|
+
- ``-1`` → ``"under"``
|
|
115
|
+
- `` 0`` → ``"coord"``
|
|
116
|
+
- ``+1`` → ``"over"``
|
|
117
|
+
- ``NaN`` → ``None``
|
|
118
|
+
|
|
119
|
+
Works on
|
|
120
|
+
--------
|
|
121
|
+
Coordination status arrays — output from :func:`classify_coordination_for_frame`
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
series : sequence of int or float
|
|
126
|
+
Numeric status values (``-1``, ``0``, ``+1``), optionally containing NaNs.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
list[str | None]
|
|
131
|
+
Coordination labels in the same order as input.
|
|
132
|
+
|
|
133
|
+
Examples
|
|
134
|
+
--------
|
|
135
|
+
>>> labels = status_label([-1, 0, 1, float("nan")])
|
|
136
|
+
"""
|
|
137
|
+
labels: list[Optional[str]] = []
|
|
138
|
+
for v in series:
|
|
139
|
+
if pd.isna(v):
|
|
140
|
+
labels.append(None)
|
|
141
|
+
else:
|
|
142
|
+
vi = int(v)
|
|
143
|
+
labels.append("under" if vi == -1 else ("coord" if vi == 0 else "over"))
|
|
144
|
+
return labels
|