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.
Files changed (130) hide show
  1. reaxkit/__init__.py +0 -0
  2. reaxkit/analysis/__init__.py +0 -0
  3. reaxkit/analysis/composed/RDF_analyzer.py +560 -0
  4. reaxkit/analysis/composed/__init__.py +0 -0
  5. reaxkit/analysis/composed/connectivity_analyzer.py +706 -0
  6. reaxkit/analysis/composed/coordination_analyzer.py +144 -0
  7. reaxkit/analysis/composed/electrostatics_analyzer.py +687 -0
  8. reaxkit/analysis/per_file/__init__.py +0 -0
  9. reaxkit/analysis/per_file/control_analyzer.py +165 -0
  10. reaxkit/analysis/per_file/eregime_analyzer.py +108 -0
  11. reaxkit/analysis/per_file/ffield_analyzer.py +305 -0
  12. reaxkit/analysis/per_file/fort13_analyzer.py +79 -0
  13. reaxkit/analysis/per_file/fort57_analyzer.py +106 -0
  14. reaxkit/analysis/per_file/fort73_analyzer.py +61 -0
  15. reaxkit/analysis/per_file/fort74_analyzer.py +65 -0
  16. reaxkit/analysis/per_file/fort76_analyzer.py +191 -0
  17. reaxkit/analysis/per_file/fort78_analyzer.py +154 -0
  18. reaxkit/analysis/per_file/fort79_analyzer.py +83 -0
  19. reaxkit/analysis/per_file/fort7_analyzer.py +393 -0
  20. reaxkit/analysis/per_file/fort99_analyzer.py +411 -0
  21. reaxkit/analysis/per_file/molfra_analyzer.py +359 -0
  22. reaxkit/analysis/per_file/params_analyzer.py +258 -0
  23. reaxkit/analysis/per_file/summary_analyzer.py +84 -0
  24. reaxkit/analysis/per_file/trainset_analyzer.py +84 -0
  25. reaxkit/analysis/per_file/vels_analyzer.py +95 -0
  26. reaxkit/analysis/per_file/xmolout_analyzer.py +528 -0
  27. reaxkit/cli.py +181 -0
  28. reaxkit/count_loc.py +276 -0
  29. reaxkit/data/alias.yaml +89 -0
  30. reaxkit/data/constants.yaml +27 -0
  31. reaxkit/data/reaxff_input_files_contents.yaml +186 -0
  32. reaxkit/data/reaxff_output_files_contents.yaml +301 -0
  33. reaxkit/data/units.yaml +38 -0
  34. reaxkit/help/__init__.py +0 -0
  35. reaxkit/help/help_index_loader.py +531 -0
  36. reaxkit/help/introspection_utils.py +131 -0
  37. reaxkit/io/__init__.py +0 -0
  38. reaxkit/io/base_handler.py +165 -0
  39. reaxkit/io/generators/__init__.py +0 -0
  40. reaxkit/io/generators/control_generator.py +123 -0
  41. reaxkit/io/generators/eregime_generator.py +341 -0
  42. reaxkit/io/generators/geo_generator.py +967 -0
  43. reaxkit/io/generators/trainset_generator.py +1758 -0
  44. reaxkit/io/generators/tregime_generator.py +113 -0
  45. reaxkit/io/generators/vregime_generator.py +164 -0
  46. reaxkit/io/generators/xmolout_generator.py +304 -0
  47. reaxkit/io/handlers/__init__.py +0 -0
  48. reaxkit/io/handlers/control_handler.py +209 -0
  49. reaxkit/io/handlers/eregime_handler.py +122 -0
  50. reaxkit/io/handlers/ffield_handler.py +812 -0
  51. reaxkit/io/handlers/fort13_handler.py +123 -0
  52. reaxkit/io/handlers/fort57_handler.py +143 -0
  53. reaxkit/io/handlers/fort73_handler.py +145 -0
  54. reaxkit/io/handlers/fort74_handler.py +155 -0
  55. reaxkit/io/handlers/fort76_handler.py +195 -0
  56. reaxkit/io/handlers/fort78_handler.py +142 -0
  57. reaxkit/io/handlers/fort79_handler.py +227 -0
  58. reaxkit/io/handlers/fort7_handler.py +264 -0
  59. reaxkit/io/handlers/fort99_handler.py +128 -0
  60. reaxkit/io/handlers/geo_handler.py +224 -0
  61. reaxkit/io/handlers/molfra_handler.py +184 -0
  62. reaxkit/io/handlers/params_handler.py +137 -0
  63. reaxkit/io/handlers/summary_handler.py +135 -0
  64. reaxkit/io/handlers/trainset_handler.py +658 -0
  65. reaxkit/io/handlers/vels_handler.py +293 -0
  66. reaxkit/io/handlers/xmolout_handler.py +174 -0
  67. reaxkit/utils/__init__.py +0 -0
  68. reaxkit/utils/alias.py +219 -0
  69. reaxkit/utils/cache.py +77 -0
  70. reaxkit/utils/constants.py +75 -0
  71. reaxkit/utils/equation_of_states.py +96 -0
  72. reaxkit/utils/exceptions.py +27 -0
  73. reaxkit/utils/frame_utils.py +175 -0
  74. reaxkit/utils/log.py +43 -0
  75. reaxkit/utils/media/__init__.py +0 -0
  76. reaxkit/utils/media/convert.py +90 -0
  77. reaxkit/utils/media/make_video.py +91 -0
  78. reaxkit/utils/media/plotter.py +812 -0
  79. reaxkit/utils/numerical/__init__.py +0 -0
  80. reaxkit/utils/numerical/extrema_finder.py +96 -0
  81. reaxkit/utils/numerical/moving_average.py +103 -0
  82. reaxkit/utils/numerical/numerical_calcs.py +75 -0
  83. reaxkit/utils/numerical/signal_ops.py +135 -0
  84. reaxkit/utils/path.py +55 -0
  85. reaxkit/utils/units.py +104 -0
  86. reaxkit/webui/__init__.py +0 -0
  87. reaxkit/webui/app.py +0 -0
  88. reaxkit/webui/components.py +0 -0
  89. reaxkit/webui/layouts.py +0 -0
  90. reaxkit/webui/utils.py +0 -0
  91. reaxkit/workflows/__init__.py +0 -0
  92. reaxkit/workflows/composed/__init__.py +0 -0
  93. reaxkit/workflows/composed/coordination_workflow.py +393 -0
  94. reaxkit/workflows/composed/electrostatics_workflow.py +587 -0
  95. reaxkit/workflows/composed/xmolout_fort7_workflow.py +343 -0
  96. reaxkit/workflows/meta/__init__.py +0 -0
  97. reaxkit/workflows/meta/help_workflow.py +136 -0
  98. reaxkit/workflows/meta/introspection_workflow.py +235 -0
  99. reaxkit/workflows/meta/make_video_workflow.py +61 -0
  100. reaxkit/workflows/meta/plotter_workflow.py +601 -0
  101. reaxkit/workflows/per_file/__init__.py +0 -0
  102. reaxkit/workflows/per_file/control_workflow.py +110 -0
  103. reaxkit/workflows/per_file/eregime_workflow.py +267 -0
  104. reaxkit/workflows/per_file/ffield_workflow.py +390 -0
  105. reaxkit/workflows/per_file/fort13_workflow.py +86 -0
  106. reaxkit/workflows/per_file/fort57_workflow.py +137 -0
  107. reaxkit/workflows/per_file/fort73_workflow.py +151 -0
  108. reaxkit/workflows/per_file/fort74_workflow.py +88 -0
  109. reaxkit/workflows/per_file/fort76_workflow.py +188 -0
  110. reaxkit/workflows/per_file/fort78_workflow.py +135 -0
  111. reaxkit/workflows/per_file/fort79_workflow.py +314 -0
  112. reaxkit/workflows/per_file/fort7_workflow.py +592 -0
  113. reaxkit/workflows/per_file/fort83_workflow.py +60 -0
  114. reaxkit/workflows/per_file/fort99_workflow.py +223 -0
  115. reaxkit/workflows/per_file/geo_workflow.py +554 -0
  116. reaxkit/workflows/per_file/molfra_workflow.py +577 -0
  117. reaxkit/workflows/per_file/params_workflow.py +135 -0
  118. reaxkit/workflows/per_file/summary_workflow.py +161 -0
  119. reaxkit/workflows/per_file/trainset_workflow.py +356 -0
  120. reaxkit/workflows/per_file/tregime_workflow.py +79 -0
  121. reaxkit/workflows/per_file/vels_workflow.py +309 -0
  122. reaxkit/workflows/per_file/vregime_workflow.py +75 -0
  123. reaxkit/workflows/per_file/xmolout_workflow.py +678 -0
  124. reaxkit-1.0.0.dist-info/METADATA +128 -0
  125. reaxkit-1.0.0.dist-info/RECORD +130 -0
  126. reaxkit-1.0.0.dist-info/WHEEL +5 -0
  127. reaxkit-1.0.0.dist-info/entry_points.txt +2 -0
  128. reaxkit-1.0.0.dist-info/licenses/AUTHORS.md +20 -0
  129. reaxkit-1.0.0.dist-info/licenses/LICENSE +21 -0
  130. reaxkit-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,79 @@
1
+ """
2
+ Temperature-regime (tregime) workflow for ReaxKit.
3
+
4
+ This workflow provides a utility for generating sample `tregime.in` files,
5
+ which define temperature schedules used in ReaxFF molecular dynamics
6
+ simulations.
7
+
8
+ It supports:
9
+ - Writing a correctly formatted `tregime.in` file with fixed-width columns.
10
+ - Controlling the number of temperature-regime rows written to the file.
11
+ - Automatically selecting a standardized output location when no explicit
12
+ output path is provided.
13
+
14
+ The workflow is intended to simplify creation of valid temperature-regime
15
+ input files for testing, prototyping, and reproducible simulation setup.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import argparse
21
+ from pathlib import Path
22
+
23
+ from reaxkit.io.generators.tregime_generator import write_sample_tregime
24
+
25
+
26
+ def _task_generate(args: argparse.Namespace) -> int:
27
+ # Default output location: reaxkit_outputs/tregime/tregime.in
28
+ out_default = Path("reaxkit_outputs") / "tregime" / "tregime.in"
29
+
30
+ # Prefer your project resolver if available
31
+ out_path: Path
32
+ if args.out:
33
+ out_path = Path(args.out)
34
+ else:
35
+ try:
36
+ from reaxkit.utils.path import resolve_output_path # type: ignore
37
+
38
+ out_path = Path(
39
+ resolve_output_path(
40
+ kind="tregime",
41
+ out=args.out,
42
+ default_name="tregime.in",
43
+ )
44
+ )
45
+ except Exception:
46
+ out_path = out_default
47
+
48
+ write_sample_tregime(out_path, n_rows=args.rows)
49
+
50
+ print(f"[Done] Sample tregime generated in {out_path}")
51
+ return 0
52
+
53
+
54
+ def register_tasks(subparsers: argparse._SubParsersAction) -> None:
55
+ gen = subparsers.add_parser(
56
+ "gen",
57
+ help="Generate a sample tregime.in file (fixed-width columns).",
58
+ description=(
59
+ "Examples:\n"
60
+ " reaxkit tregime gen \n"
61
+ " reaxkit tregime gen --rows 5 \n"
62
+ ),
63
+ formatter_class=argparse.RawTextHelpFormatter,
64
+ )
65
+ gen.add_argument(
66
+ "--out",
67
+ default="reaxkit_generated_inputs/tregime.in",
68
+ help=(
69
+ "Output tregime filename or path. "
70
+ "If not provided, writes to reaxkit_outputs/tregime/tregime.in"
71
+ ),
72
+ )
73
+ gen.add_argument(
74
+ "--rows",
75
+ type=int,
76
+ default=3,
77
+ help="Number of sample rows to write.",
78
+ )
79
+ gen.set_defaults(_run=_task_generate)
@@ -0,0 +1,309 @@
1
+ """
2
+ Velocity and acceleration (vels) analysis workflow for ReaxKit.
3
+
4
+ This workflow provides tools for inspecting, visualizing, and exporting data
5
+ from ReaxFF velocity-related output files, including `vels`, `moldyn.vel`,
6
+ and `molsav`.
7
+
8
+ It supports:
9
+ - Extracting per-atom coordinates, velocities, accelerations, or previous-step
10
+ accelerations for all atoms or selected subsets.
11
+ - Printing extracted data to the console or exporting it to CSV.
12
+ - Visualizing scalar velocity or acceleration components (e.g. vx, vz, ax)
13
+ mapped onto atomic positions using 3D scatter plots.
14
+ - Generating 2D projected heatmaps (xy, xz, yz) of scalar quantities by spatial
15
+ binning and aggregation.
16
+
17
+ The workflow is designed for spatially resolved analysis of atomic motion and
18
+ dynamics in ReaxFF molecular dynamics simulations.
19
+ """
20
+
21
+
22
+ from __future__ import annotations
23
+
24
+ import argparse
25
+ from typing import Optional, Tuple, Union
26
+
27
+ import numpy as np
28
+ import pandas as pd
29
+
30
+ from reaxkit.io.handlers.vels_handler import VelsHandler
31
+ from reaxkit.analysis.per_file.vels_analyzer import get_vels_data
32
+ from reaxkit.utils.media.plotter import scatter3d_points, heatmap2d_from_3d
33
+ from reaxkit.utils.path import resolve_output_path
34
+
35
+
36
+ # ------------------------- small parsers -------------------------
37
+
38
+ def _parse_atoms_1based(spec: Optional[str]) -> Optional[list[int]]:
39
+ """
40
+ Parse atoms like:
41
+ "1,3,7" or "1 3 7" or "1-5" (inclusive) or "1-10,15,20-25"
42
+ Returns 1-based indices (as stored in vels dfs).
43
+ """
44
+ if spec is None:
45
+ return None
46
+ s = spec.strip()
47
+ if not s:
48
+ return None
49
+
50
+ out: list[int] = []
51
+ parts = s.replace(",", " ").split()
52
+ for p in parts:
53
+ if "-" in p:
54
+ a, b = p.split("-", 1)
55
+ if a.strip().isdigit() and b.strip().isdigit():
56
+ lo, hi = int(a), int(b)
57
+ if lo <= hi:
58
+ out.extend(list(range(lo, hi + 1)))
59
+ else:
60
+ out.extend(list(range(hi, lo + 1)))
61
+ else:
62
+ if p.isdigit():
63
+ out.append(int(p))
64
+
65
+ # unique, preserve order
66
+ seen = set()
67
+ uniq = []
68
+ for x in out:
69
+ if x not in seen:
70
+ uniq.append(x)
71
+ seen.add(x)
72
+ return uniq or None
73
+
74
+
75
+ def _parse_bins(bins: str) -> Union[int, Tuple[int, int]]:
76
+ if "," in bins:
77
+ nx, ny = [int(x) for x in bins.split(",")]
78
+ return (nx, ny)
79
+ return int(bins)
80
+
81
+
82
+ def _value_column_to_key(value_col: str) -> tuple[str, str]:
83
+ """
84
+ Map a requested scalar column to the vels_get key + dataframe column name.
85
+ Examples:
86
+ vx/vy/vz -> ("velocities", "vx"/"vy"/"vz")
87
+ ax/ay/az -> ("accelerations", "ax"/"ay"/"az")
88
+ pax/pay/paz -> ("prev_accelerations", "ax"/"ay"/"az")
89
+ """
90
+ v = value_col.strip().lower()
91
+ if v in {"vx", "vy", "vz"}:
92
+ return ("velocities", v)
93
+ if v in {"ax", "ay", "az"}:
94
+ return ("accelerations", v)
95
+ if v in {"pax", "pay", "paz"}:
96
+ # previous accels share ax/ay/az columns
97
+ return ("prev_accelerations", "a" + v[1:])
98
+ raise ValueError("value_col must be one of: vx,vy,vz, ax,ay,az, pax,pay,paz")
99
+
100
+
101
+ # ------------------------- common args -------------------------
102
+
103
+ def _add_common_vels_io_args(p: argparse.ArgumentParser) -> None:
104
+ p.add_argument("--file", default="vels", help="Path to vels/moldyn.vel/molsav file.")
105
+ p.add_argument("--atoms", default=None,
106
+ help='1-based atom indices (optional). Examples: "1,3,7" or "1-10,25".')
107
+ p.add_argument("--export", default=None, help="Path to export CSV data.")
108
+ p.add_argument("--print", action="store_true", help="Print output to console.")
109
+
110
+
111
+ def _add_common_plot_args(p: argparse.ArgumentParser) -> None:
112
+ p.add_argument("--save", default=None, help="Path to save plot image (dir or full filename).")
113
+ p.add_argument("--vmin", type=float, default=None, help="Color scale min (auto if not set).")
114
+ p.add_argument("--vmax", type=float, default=None, help="Color scale max (auto if not set).")
115
+ p.add_argument("--cmap", default="coolwarm", help="Matplotlib colormap.")
116
+
117
+
118
+ # ------------------------- tasks -------------------------
119
+
120
+ def _get_task(args: argparse.Namespace) -> int:
121
+ h = VelsHandler(args.file)
122
+
123
+ atoms = _parse_atoms_1based(args.atoms)
124
+
125
+ out = get_vels_data(h, args.key, atoms=atoms)
126
+
127
+ # metadata
128
+ if isinstance(out, dict):
129
+ if args.print or (not args.export):
130
+ for k, v in out.items():
131
+ print(f"{k}: {v}")
132
+ if args.export:
133
+ export_path = resolve_output_path(args.export, workflow="vels")
134
+ # simple key/value csv
135
+ dfm = pd.DataFrame([{"key": k, "value": str(v)} for k, v in out.items()])
136
+ dfm.to_csv(export_path, index=False)
137
+ print(f"[Done] Requested data is exported to {export_path}")
138
+ return 0
139
+
140
+ # dataframe
141
+ df = out
142
+ if args.print or (not args.export):
143
+ # avoid flooding console; you can change this later
144
+ with pd.option_context("display.max_rows", 30, "display.width", 140):
145
+ print(df)
146
+
147
+ if args.export:
148
+ export_path = resolve_output_path(args.export, workflow="vels")
149
+ df.to_csv(export_path, index=False)
150
+ print(f"[Done] Requested data is exported to {export_path}")
151
+
152
+ return 0
153
+
154
+
155
+ def _plot3d_task(args: argparse.Namespace) -> int:
156
+ h = VelsHandler(args.file)
157
+ atoms = _parse_atoms_1based(args.atoms)
158
+
159
+ # coords
160
+ cdf = get_vels_data(h, "coordinates", atoms=atoms)
161
+ if cdf.empty:
162
+ raise ValueError("No coordinates to plot (empty selection).")
163
+
164
+ # scalar values from one of the sections
165
+ key, col = _value_column_to_key(args.value)
166
+ vdf = get_vels_data(h, key, atoms=atoms)
167
+ if vdf.empty:
168
+ raise ValueError(f"No data for {args.value} to plot (empty selection or missing section).")
169
+
170
+ merged = cdf.merge(vdf, on="atom_index", how="inner")
171
+ if merged.empty:
172
+ raise ValueError("No matching atom rows between coordinates and selected values.")
173
+
174
+ coords = merged[["x", "y", "z"]].to_numpy(float)
175
+ vals = merged[col].to_numpy(float)
176
+
177
+ m = np.isfinite(vals)
178
+ coords = coords[m]
179
+ vals = vals[m]
180
+ if coords.size == 0:
181
+ raise ValueError("All selected values are NaN/invalid; nothing to plot.")
182
+
183
+ title = f"{args.value}_3D"
184
+ scatter3d_points(
185
+ coords,
186
+ vals,
187
+ title=title,
188
+ s=args.size,
189
+ alpha=args.alpha,
190
+ cmap=args.cmap,
191
+ vmin=args.vmin,
192
+ vmax=args.vmax,
193
+ elev=args.elev,
194
+ azim=args.azim,
195
+ save=(resolve_output_path(args.save, workflow="vels") if args.save else None),
196
+ show_message=True,
197
+ )
198
+ return 0
199
+
200
+
201
+ def _heatmap2d_task(args: argparse.Namespace) -> int:
202
+ h = VelsHandler(args.file)
203
+ atoms = _parse_atoms_1based(args.atoms)
204
+
205
+ cdf = get_vels_data(h, "coordinates", atoms=atoms)
206
+ if cdf.empty:
207
+ raise ValueError("No coordinates to plot (empty selection).")
208
+
209
+ key, col = _value_column_to_key(args.value)
210
+ vdf = get_vels_data(h, key, atoms=atoms)
211
+ if vdf.empty:
212
+ raise ValueError(f"No data for {args.value} to plot (empty selection or missing section).")
213
+
214
+ merged = cdf.merge(vdf, on="atom_index", how="inner")
215
+ if merged.empty:
216
+ raise ValueError("No matching atom rows between coordinates and selected values.")
217
+
218
+ coords = merged[["x", "y", "z"]].to_numpy(float)
219
+ vals = merged[col].to_numpy(float)
220
+ m = np.isfinite(vals)
221
+ coords = coords[m]
222
+ vals = vals[m]
223
+ if coords.size == 0:
224
+ raise ValueError("All selected values are NaN/invalid; nothing to plot.")
225
+
226
+ bins = _parse_bins(args.bins)
227
+ title = f"{args.value}_{args.plane}_heatmap2d"
228
+
229
+ heatmap2d_from_3d(
230
+ coords,
231
+ vals,
232
+ plane=args.plane,
233
+ bins=bins,
234
+ agg=args.agg,
235
+ vmin=args.vmin,
236
+ vmax=args.vmax,
237
+ cmap=args.cmap,
238
+ title=title,
239
+ save=(resolve_output_path(args.save, workflow="vels") if args.save else None),
240
+ show_message=True,
241
+ )
242
+ return 0
243
+
244
+
245
+ # ------------------------- CLI registration -------------------------
246
+
247
+ def register_tasks(subparsers: argparse._SubParsersAction) -> None:
248
+ # ---------------- get ----------------
249
+ g = subparsers.add_parser(
250
+ "get",
251
+ help="Get vels data (coords/vels/accels/prev) for all or selected atoms.",
252
+ description=(
253
+ "Examples:\n"
254
+ " reaxkit vels get --key velocities --atoms 1,3,7 --print\n"
255
+ " reaxkit vels get --key coordinates --atoms 1-50 --export coords.csv\n"
256
+ " reaxkit vels get --key metadata --print\n"
257
+ ),
258
+ formatter_class=argparse.RawTextHelpFormatter,
259
+ )
260
+ _add_common_vels_io_args(g)
261
+ g.add_argument("--key", required=True,
262
+ choices=["metadata", "coordinates", "velocities", "accelerations", "prev_accelerations"],
263
+ help="Which dataset to return.")
264
+ g.set_defaults(_run=_get_task)
265
+
266
+ # ---------------- plot3d ----------------
267
+ p3 = subparsers.add_parser(
268
+ "plot3d",
269
+ help="3D scatter: color a scalar (vz, vx, ax, ...) on atomic positions.",
270
+ description=(
271
+ "Examples:\n"
272
+ " reaxkit vels plot3d --value vz --save vz_3d.png\n"
273
+ " reaxkit vels plot3d --value vz --atoms 1-500 --cmap coolwarm\n"
274
+ ),
275
+ formatter_class=argparse.RawTextHelpFormatter,
276
+ )
277
+ p3.add_argument("--file", default="vels", help="Path to vels/moldyn.vel/molsav file.")
278
+ p3.add_argument("--atoms", default=None,
279
+ help='1-based atom indices. Examples: "1,3,7" or "1-10,25".')
280
+ p3.add_argument("--value", required=True,
281
+ help="Scalar to plot: vx,vy,vz, ax,ay,az, pax,pay,paz.")
282
+ _add_common_plot_args(p3)
283
+ p3.add_argument("--size", type=float, default=8.0, help="Marker size.")
284
+ p3.add_argument("--alpha", type=float, default=0.9, help="Marker transparency.")
285
+ p3.add_argument("--elev", type=float, default=22.0, help="3D view elevation.")
286
+ p3.add_argument("--azim", type=float, default=38.0, help="3D view azimuth.")
287
+ p3.set_defaults(_run=_plot3d_task)
288
+
289
+ # ---------------- heatmap2d ----------------
290
+ h2 = subparsers.add_parser(
291
+ "heatmap2d",
292
+ help="2D heatmap: project positions to xy/xz/yz and bin/aggregate a scalar.",
293
+ description=(
294
+ "Examples:\n"
295
+ " reaxkit vels heatmap2d --value vz --plane xz --bins 60 --agg mean --save vz_xz.png\n"
296
+ " reaxkit vels heatmap2d --value vz --plane xy --bins 80,40 --agg max\n"
297
+ ),
298
+ formatter_class=argparse.RawTextHelpFormatter,
299
+ )
300
+ h2.add_argument("--file", default="vels", help="Path to vels/moldyn.vel/molsav file.")
301
+ h2.add_argument("--atoms", default=None,
302
+ help='1-based atom indices. Examples: "1,3,7" or "1-10,25".')
303
+ h2.add_argument("--value", required=True,
304
+ help="Scalar to plot: vx,vy,vz, ax,ay,az, pax,pay,paz.")
305
+ h2.add_argument("--plane", default="xy", choices=["xy", "xz", "yz"], help="Projection plane.")
306
+ h2.add_argument("--bins", default="50", help='Grid bins: "N" or "Nx,Ny" (e.g., "80,40").')
307
+ h2.add_argument("--agg", default="mean", help="Aggregation: mean|max|min|sum|count.")
308
+ _add_common_plot_args(h2)
309
+ h2.set_defaults(_run=_heatmap2d_task)
@@ -0,0 +1,75 @@
1
+ """
2
+ Volume-regime (vregime) workflow for ReaxKit.
3
+
4
+ This workflow provides a utility for generating sample `vregime.in` files,
5
+ which define volume or pressure control schedules used in ReaxFF simulations.
6
+
7
+ It supports:
8
+ - Writing a correctly formatted `vregime.in` file with fixed-width columns.
9
+ - Controlling the number of volume-regime rows written to the file.
10
+ - Automatically selecting a standardized output location when no explicit
11
+ output path is provided.
12
+
13
+ The workflow is intended to simplify creation of valid volume-regime input
14
+ files for testing, prototyping, and reproducible ReaxFF simulation setup.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ from pathlib import Path
21
+
22
+ from reaxkit.io.generators.vregime_generator import write_sample_vregime
23
+
24
+ def _task_generate(args: argparse.Namespace) -> int:
25
+ out_default = Path("reaxkit_outputs") / "vregime" / "vregime.in"
26
+
27
+ if args.out:
28
+ out_path = Path(args.out)
29
+ else:
30
+ # Prefer your project resolver if available
31
+ try:
32
+ from reaxkit.utils.path import resolve_output_path # type: ignore
33
+
34
+ out_path = Path(
35
+ resolve_output_path(
36
+ kind="vregime",
37
+ out=None,
38
+ default_name="vregime.in",
39
+ )
40
+ )
41
+ except Exception:
42
+ out_path = out_default
43
+
44
+ write_sample_vregime(out_path, n_rows=args.rows)
45
+
46
+ print(f"[Done] Sample vregime generated in {out_path}")
47
+ return 0
48
+
49
+
50
+ def register_tasks(subparsers: argparse._SubParsersAction) -> None:
51
+ p = subparsers.add_parser(
52
+ "gen",
53
+ help="Generate a sample vregime.in file (Volume regimes).",
54
+ description=(
55
+ "Examples:\n"
56
+ " reaxkit vregime gen \n"
57
+ " reaxkit vregime gen --rows 3 \n"
58
+ ),
59
+ formatter_class=argparse.RawTextHelpFormatter,
60
+ )
61
+ p.add_argument(
62
+ "--out",
63
+ default="reaxkit_generated_inputs/vregime.in",
64
+ help=(
65
+ "Output vregime filename or path. "
66
+ "If not provided, writes to reaxkit_outputs/vregime/vregime.in"
67
+ ),
68
+ )
69
+ p.add_argument(
70
+ "--rows",
71
+ type=int,
72
+ default=5,
73
+ help="Number of sample rows to write.",
74
+ )
75
+ p.set_defaults(_run=_task_generate)