pymdkit 1.7.2__tar.gz → 1.7.3__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 (98) hide show
  1. pymdkit-1.7.3/CHANGELOG.md +16 -0
  2. pymdkit-1.7.3/MANIFEST.in +4 -0
  3. {pymdkit-1.7.2 → pymdkit-1.7.3}/PKG-INFO +363 -7
  4. {pymdkit-1.7.2 → pymdkit-1.7.3}/README.md +362 -6
  5. {pymdkit-1.7.2 → pymdkit-1.7.3}/pyproject.toml +1 -1
  6. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/__init__.py +1 -1
  7. pymdkit-1.7.3/src/pymdkit/commands/_gpumd_run.py +121 -0
  8. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_gpumd_thermo.py +222 -265
  9. pymdkit-1.7.3/src/pymdkit/commands/_msd_auto.py +269 -0
  10. pymdkit-1.7.3/src/pymdkit/commands/_msd_conductivity.py +19 -0
  11. pymdkit-1.7.3/src/pymdkit/commands/_msd_coordinates.py +105 -0
  12. pymdkit-1.7.3/src/pymdkit/commands/_msd_fit.py +308 -0
  13. pymdkit-1.7.3/src/pymdkit/commands/_msd_io.py +131 -0
  14. pymdkit-1.7.3/src/pymdkit/commands/_msd_provenance.py +27 -0
  15. pymdkit-1.7.3/src/pymdkit/commands/_msd_range.py +73 -0
  16. pymdkit-1.7.3/src/pymdkit/commands/_msd_thermo.py +44 -0
  17. pymdkit-1.7.3/src/pymdkit/commands/_msd_uncertainty.py +260 -0
  18. pymdkit-1.7.3/src/pymdkit/commands/_pred_msd_plan.py +271 -0
  19. pymdkit-1.7.3/src/pymdkit/commands/_pred_msd_reference.py +213 -0
  20. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/gpumd_job.py +69 -3
  21. pymdkit-1.7.3/src/pymdkit/commands/msd.py +345 -0
  22. pymdkit-1.7.3/src/pymdkit/commands/pred_msd_time.py +211 -0
  23. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/pymdkit_main.py +3 -1
  24. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit.egg-info/PKG-INFO +363 -7
  25. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit.egg-info/SOURCES.txt +25 -1
  26. pymdkit-1.7.3/tests/data/88-Li2YCl3-63-d1.cif +54 -0
  27. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_gpumd_out.py +128 -0
  28. pymdkit-1.7.3/tests/test_msd_auto.py +265 -0
  29. pymdkit-1.7.3/tests/test_msd_fit.py +123 -0
  30. pymdkit-1.7.3/tests/test_msd_large.py +179 -0
  31. pymdkit-1.7.3/tests/test_msd_phase3.py +452 -0
  32. pymdkit-1.7.3/tests/test_msd_range.py +240 -0
  33. pymdkit-1.7.3/tests/test_msd_uncertainty.py +183 -0
  34. pymdkit-1.7.3/tests/test_pred_msd_time.py +229 -0
  35. {pymdkit-1.7.2 → pymdkit-1.7.3}/LICENSE +0 -0
  36. {pymdkit-1.7.2 → pymdkit-1.7.3}/setup.cfg +0 -0
  37. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/_config.py +0 -0
  38. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/_logging.py +0 -0
  39. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/__init__.py +0 -0
  40. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_cifio.py +0 -0
  41. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_extxyz.py +0 -0
  42. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_fileio.py +0 -0
  43. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_geometry.py +0 -0
  44. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_gpumd.py +0 -0
  45. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_gpumd_final_structure.py +0 -0
  46. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_gpumd_msd.py +0 -0
  47. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_gpumd_status.py +0 -0
  48. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_lattice.py +0 -0
  49. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_oxidation.py +0 -0
  50. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_parallel.py +0 -0
  51. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_precision.py +0 -0
  52. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_reduction.py +0 -0
  53. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_submit.py +0 -0
  54. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_submit_vasp.py +0 -0
  55. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_supercell.py +0 -0
  56. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_symmetry.py +0 -0
  57. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_vasp_ehull.py +0 -0
  58. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_vasp_final_structure.py +0 -0
  59. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_vasp_nep.py +0 -0
  60. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_vasp_output.py +0 -0
  61. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/_vaspset.py +0 -0
  62. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/chemsys_entry.py +0 -0
  63. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/compute_rmsd.py +0 -0
  64. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/config.py +0 -0
  65. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/convert.py +0 -0
  66. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/dope.py +0 -0
  67. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/ewald.py +0 -0
  68. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/gpumd_out.py +0 -0
  69. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/nep_rmse.py +0 -0
  70. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/perturb.py +0 -0
  71. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/rd.py +0 -0
  72. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/realloc_occ.py +0 -0
  73. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/submit.py +0 -0
  74. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/supercell.py +0 -0
  75. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/trjconv.py +0 -0
  76. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/vasp_job.py +0 -0
  77. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit/commands/vasp_out.py +0 -0
  78. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit.egg-info/dependency_links.txt +0 -0
  79. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit.egg-info/entry_points.txt +0 -0
  80. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit.egg-info/requires.txt +0 -0
  81. {pymdkit-1.7.2 → pymdkit-1.7.3}/src/pymdkit.egg-info/top_level.txt +0 -0
  82. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_config_logging.py +0 -0
  83. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_convert.py +0 -0
  84. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_ehull.py +0 -0
  85. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_lattice_symmetry.py +0 -0
  86. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_parallel.py +0 -0
  87. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_progress.py +0 -0
  88. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_realloc_occ.py +0 -0
  89. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_rmsd_gpu.py +0 -0
  90. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_rmsd_max.py +0 -0
  91. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_rmsd_two_folder.py +0 -0
  92. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_submit.py +0 -0
  93. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_v165.py +0 -0
  94. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_v170_job_infrastructure.py +0 -0
  95. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_v170_vasp_consolidation.py +0 -0
  96. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_v172_vasp_writing.py +0 -0
  97. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_vasp_out.py +0 -0
  98. {pymdkit-1.7.2 → pymdkit-1.7.3}/tests/test_vaspset.py +0 -0
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## 1.7.3
4
+
5
+ - `pmk msd` analyzes fixed-cell GPUMD NVT trajectories, selects or accepts a
6
+ fitting window, and optionally reports Nernst–Einstein conductivity. It uses
7
+ free-intercept OLS by default. Optional WLS and GLS also estimate the intercept.
8
+ Forced-origin fitting has been removed from production.
9
+ - `pmk pred-msd-time` uses validated full-trajectory OLS references to forecast
10
+ higher-temperature Li conductivity, diffusion, and NVT production duration.
11
+ The Arrhenius forecast and square-root duration scaling are planning heuristics.
12
+ The durations carry no guarantee of MSD convergence.
13
+ - `pmk gpumd-job -msd-time` generates GPUMD 4.2-compatible jobs with explicit
14
+ NVT temperatures, run lengths, and optional `compute_msd` sample counts.
15
+ Fixed-cell NVT production is required for MSD analysis. Earlier NPT equilibration
16
+ is supported when its frames are excluded from the analyzed trajectory.
@@ -0,0 +1,4 @@
1
+ include CHANGELOG.md
2
+ include tests/data/88-Li2YCl3-63-d1.cif
3
+ exclude tests/test_benchmark_msd_io.py
4
+ prune devtools
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymdkit
3
- Version: 1.7.2
3
+ Version: 1.7.3
4
4
  Summary: A Python command-line toolkit for high-throughput atomistic workflows in AI-driven materials design.
5
5
  Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
6
6
  License-Expression: GPL-3.0-or-later
@@ -36,6 +36,17 @@ materials design. Install `pymdkit` once and call its tools from anywhere as
36
36
  Commands expose explicit, documented CLI interfaces designed for reproducible shell,
37
37
  HPC, and AI-agent workflows, and each underlying script is still runnable on its own.
38
38
 
39
+ ## 1.7.3 release notes
40
+
41
+ - `pmk msd` analyzes GPUMD trajectories from fixed-cell NVT production. OLS is
42
+ the default, and OLS, WLS and GLS all fit a free intercept. Forced-origin
43
+ fitting has been removed from production. Changing-cell MSD is outside scope.
44
+ - `pmk pred-msd-time` uses validated free-intercept OLS references for
45
+ higher-temperature Li transport and production-time planning. The duration
46
+ heuristic carries no guarantee of MSD convergence.
47
+ - `pmk gpumd-job -msd-time` turns predictions into GPUMD 4.2-compatible NVT
48
+ job inputs. Earlier NPT equilibration can precede the analyzed production.
49
+
39
50
  ## Install
40
51
 
41
52
  ### Online installation
@@ -86,7 +97,7 @@ installed.
86
97
  On a machine with Internet access, run:
87
98
 
88
99
  ```bash
89
- python -m pip download pymdkit==1.7.2 -d pymdkit-offline
100
+ python -m pip download pymdkit==1.7.3 -d pymdkit-offline
90
101
  ```
91
102
 
92
103
  This downloads `pymdkit` and the dependencies resolved by pip into the
@@ -94,14 +105,14 @@ This downloads `pymdkit` and the dependencies resolved by pip into the
94
105
  system. Then, inside the target pymdkit Python or conda environment, run:
95
106
 
96
107
  ```bash
97
- python -m pip install --no-index --find-links=pymdkit-offline pymdkit==1.7.2
108
+ python -m pip install --no-index --find-links=pymdkit-offline pymdkit==1.7.3
98
109
  ```
99
110
 
100
111
  For optional GPU use, prepare the bundle on a networked machine compatible with
101
112
  the target HPC platform and Python environment:
102
113
 
103
114
  ```bash
104
- python -m pip download "pymdkit[gpu-cuda12]==1.7.2" -d pymdkit-offline
115
+ python -m pip download "pymdkit[gpu-cuda12]==1.7.3" -d pymdkit-offline
105
116
  ```
106
117
 
107
118
  Transfer the whole `pymdkit-offline` directory, then install from it on the
@@ -109,7 +120,7 @@ target system:
109
120
 
110
121
  ```bash
111
122
  python -m pip install --no-index --find-links=pymdkit-offline \
112
- "pymdkit[gpu-cuda12]==1.7.2"
123
+ "pymdkit[gpu-cuda12]==1.7.3"
113
124
  ```
114
125
 
115
126
  This GPU bundle includes the optional `cupy-cuda12x` package. Its wheels must also
@@ -190,6 +201,7 @@ preserve occupancy, oxidation, symmetry, and Wyckoff metadata.
190
201
  | `dope` | Dope structures by substituting or removing selected atoms/sites |
191
202
  | `ewald` | Compute CIF electrostatic energy |
192
203
  | `gpumd-job` | Create supercell, temperature, potential, input, and grouped GPUMD jobs |
204
+ | `pred-msd-time` | Predict Li conductivity, diffusion and NVT production durations from GPUMD MSD |
193
205
  | `gpumd-out` | Export GPUMD thermo/MSD results or gather final structures |
194
206
  | `mp-chemsys` | Download stable Materials Project structures for a chemical system |
195
207
  | `nep-rmse` | Compute NEP energy/force/stress RMSE and select candidates |
@@ -425,8 +437,13 @@ pmk gpumd-out -save-fs [-entry-path DIR] [-fs-name FILENAME] (-of DIR | -output-
425
437
  ```
426
438
 
427
439
  `-entry-path` defaults to `.`. Thermo mode defaults to `thermo.out` and
428
- `run.in`, preserving the per-job text tables, `thermo.png`, and
429
- `abnormal-time.txt` when an abnormal interval is detected. MSD mode defaults
440
+ `run.in`, writing per-job `temperature.txt`, `potential-energy.txt`,
441
+ `pressure.txt`, `lattice-parameters.txt`, `volume.txt`, `lattice-angles.txt`,
442
+ and the six-panel `thermo.png`. Abnormal-fluctuation diagnostics remain in
443
+ console warnings and `gpumd-out.log`; the plot has no abnormal-region shading
444
+ or legend. Thermo mode no longer generates `abnormal-time.txt` and removes
445
+ that exact stale file only after successfully exporting a job's tables and
446
+ plot. MSD mode defaults
430
447
  to mobile ion `Li` with charge `1`, writes
431
448
  `sigma-sdc-summary.txt` at the entry root, and preserves each job's
432
449
  `msd/group_*_msd.txt`, `group_*_sdc.txt`, and `group_*_results.txt`.
@@ -720,3 +737,342 @@ Every command module still works directly, which is handy for debugging:
720
737
  ```bash
721
738
  python src/pymdkit/commands/supercell.py -i in.cif -close-abc 20 -o sc.vasp
722
739
  ```
740
+ ## Atomic trajectory MSD
741
+
742
+ ```bash
743
+ pmk msd -group 0
744
+ pmk msd -group 0 -ne
745
+ pmk msd -group 0 -ne -charge 2
746
+ pmk msd -group 0 -fit-method gls
747
+ pmk msd -group 0 -fit-range 10 100
748
+ pmk msd -group 0 -ne -trajectory-range 0 10
749
+ pmk msd -group 0 -ne -trajectory-range 10 20
750
+ ```
751
+
752
+ `-md-program gpumd` is the default. The current directory and calculation
753
+ subdirectories are searched deterministically, excluding generated `msd`, hidden,
754
+ environment and build directories. Each calculation needs `model.xyz`, `run.in`
755
+ and the native full-system trajectory named by `dump_xyz`, or `dump.xyz` from
756
+ legacy `dump_exyz interval velocity_flag force_flag`. Group selection uses the
757
+ first grouping method in `model.xyz`. Missing group labels are an error.
758
+
759
+ Both `dump_xyz interval filename properties...` and GPUMD 4.2's
760
+ `dump_xyz grouping_method group_id interval filename properties...` are supported.
761
+ For example, `dump_xyz -1 0 200 dump.xyz group unwrapped_position` saves the whole
762
+ system every 200 steps. Legacy grouping methods must be negative (full system);
763
+ the group ID must be an integer and is ignored in this mode. Subset trajectories
764
+ are rejected because whole-system COM correction requires every atom. Legacy
765
+ `group` and modern `group_labels` properties are supported. Earlier NPT
766
+ equilibration without trajectory output is allowed before fixed-cell NVT production.
767
+ Directories with active unresolved `target_t`, `${...}` or `{{...}}` placeholders
768
+ in `run.in` are skipped with a reason; commented placeholders are ignored.
769
+
770
+ This is the mean of individual atomic squared displacements, **not group-COM
771
+ MSD**. Every frame is streamed through a native GPUMD numeric parser (other
772
+ extxyz schemas retain the ASE fallback), then selected coordinates are stored
773
+ in a temporary float64 memmap. All system atoms contribute to mass-weighted COM
774
+ displacement removal using ASE tabulated atomic masses. Species order, atom count,
775
+ PBC flags, and group/ID columns (when present) are checked against the model.
776
+ Native GPUMD full-system row ordering is required: externally sorted same-element
777
+ atoms without stable IDs cannot be identified and must not be supplied.
778
+
779
+ For fixed triclinic cells, consistent `unwrapped_position` is preferred; otherwise
780
+ ASE's general lattice minimum-image algorithm accumulates successive displacements.
781
+ Wrapped output must be frequent enough to resolve each displacement uniquely;
782
+ multiple unseen boundary crossings cannot be recovered from saved frames.
783
+ **MSD analysis supports fixed-cell NVT production.** NPT and changing-cell
784
+ production are rejected, including pure affine deformation.
785
+
786
+ The default `--fit-window auto` searches atom-based total MSD lag windows using
787
+ log-log OLS beta, then calculates D independently with free-intercept Einstein
788
+ OLS (directional slopes/2; total is their arithmetic mean). Following
789
+ [MDTransport (2026)](https://doi.org/10.1021/acs.jcim.6c00558), the search grid
790
+ is 100 ps. The default minimum duration is `min(T/2, 8000 ps)`, a continuous
791
+ pymdkit engineering adaptation of the published piecewise rule that avoids
792
+ infeasible windows immediately above 10 ns. Following
793
+ [He et al. (2018)](https://doi.org/10.1038/s41524-018-0074-y), every automatic
794
+ upper lag is strictly below 0.7T. T is saved frame count times frame interval,
795
+ not the absolute simulation timestamp. Grid boundaries map to nearest MSD
796
+ samples; first positive lag and last allowed lag are included as endpoints.
797
+ The minimum duration is never silently relaxed.
798
+
799
+ Controls are `--min-fit-window PS`, `--fit-window-step PS`, and
800
+ `--beta-tolerance VALUE` (default 0.075, maximum 0.20). Among beta-qualified
801
+ windows, choose D closest to the pool median, then smaller beta deviation, then
802
+ longer duration. Without qualified windows choose minimum beta deviation.
803
+ Separate `beta_status`, `intercept_status`, `einstein_slope_status` and
804
+ `overall_status` distinguish raw beta from affine Einstein model consistency
805
+ and slope stability. Beta thresholds remain 0.075 and 0.20. PASS additionally
806
+ requires available, positive early/middle/late Einstein slopes with relative
807
+ spread `(max-min)/median <= 0.20`. Insufficient segment data or a larger spread
808
+ produces WARNING for beta within 0.20. Above 0.20 the result is REJECT unless
809
+ the positive-intercept model agrees with observed beta within 0.05 **and**
810
+ segment stability passes; this exception permits WARNING only, never PASS.
811
+
812
+ The default reported D uses free-intercept OLS, `MSD(t) = A + 6 D t`.
813
+ For each valid candidate, diagnostics retain free-intercept D,
814
+ intercept fractions at both endpoints, and beta predicted
815
+ by log-log OLS of `b+s*t` on the actual fitting samples. No intercept is
816
+ subtracted from the measured MSD. A detected intercept effect explains model
817
+ consistency, not the physical cause of the intercept. Full-window D remains the
818
+ published estimate; segment D values never replace it. Segment diagnostics are
819
+ computed only for the selected candidate, with explicit unavailable reasons.
820
+ Relative D sensitivity `(P90-P10)/median > 0.5` also produces WARNING. These
821
+ are diagnostics, not evidence of statistical convergence. Internal thresholds
822
+ are named constants in `_msd_auto.py`; no smoothing or independent-window
823
+ sample-count assumption is used. `--mobile-site-distance A` optionally checks
824
+ the approximate MSD >= 0.5a^2 criterion using a known neighboring mobile-site
825
+ distance; this is not a universal cutoff or an inferred instantaneous ion distance.
826
+ Without it the structural ballistic cutoff is not independently determined.
827
+
828
+ `-fit-range START_PS END_PS` retains manual lag-window fitting, including its
829
+ previous upper-lag freedom; it conflicts with explicit `--fit-window auto`.
830
+ `--fit-window manual` requires a range. For example:
831
+
832
+ ```bash
833
+ pmk msd -group 0 -ne --fit-window auto
834
+ pmk msd -group 0 -ne -fit-range 500 1200
835
+ ```
836
+
837
+ Optional `-fit-method wls` and `-fit-method gls` fit the same free-intercept
838
+ Einstein model per direction, using binary nonoverlapping block samples within
839
+ the selected window. WLS uses diagonal block-error covariance and GLS includes
840
+ cross-lag correlations. At least four binary sampling levels and an identifiable
841
+ fit are required. The weighted intercepts appear in `fit-diagnostic.txt`.
842
+ The window and its quality diagnostics use OLS for all three methods.
843
+ Forced-origin fitting has been removed from the production workflow.
844
+
845
+ `-trajectory-range START END` selects a separate saved-trajectory subset in ns,
846
+ using the half-open interval `[START, END)` relative to the first original
847
+ `Time=` header, not the simulation start. GPUMD header times are in fs.
848
+ Every scanned timestamp must be finite, increasing, uniformly spaced and
849
+ consistent with `run.in`; missing timestamps/frames or unreliable thermo
850
+ alignment fail clearly. Boundary comparisons use the existing schedule-scale
851
+ tolerance `max(1e-5 fs, abs(Time)*1e-9)` for floating accumulation. Available
852
+ coverage ends one sampling interval after the last frame (thus 100000 frames
853
+ at 0.2 ps cover 20 ns). Actual selected timestamps/count are recorded.
854
+ Headers and rows before START are streamed without coordinate parsing; reading
855
+ stops at the END header when present. The suffix beyond END is not validated.
856
+ Only selected coordinates enter the existing whole-system mass-weighted COM
857
+ correction, selected individual-atom memmap and independent all-origin FFT.
858
+ Lag time restarts at zero; `-fit-range` remains an independent lag interval in ps.
859
+
860
+ Range outputs go to `msd/segments/START-ENDns/`, with shortest decimal float
861
+ values expanded without exponent or redundant trailing zeros (`0-10ns`,
862
+ `10-20ns`, `0.5-2.5ns`). Existing segment directories are refused. Full-run
863
+ outputs, other segments and root summaries are preserved; successful segment
864
+ aggregate summaries live in the segment directory. Each segment also records
865
+ `diagnostics.json`, `fit-windows.txt` and `fit-diagnostic.txt`, including REJECT.
866
+ No credible fit means no new formal D or conductivity. A 10 ns segment cannot
867
+ fit the full trajectory's 5.9–14 ns window: unchanged automatic thresholds
868
+ search only its available lags. NE uses measured thermo samples in the same
869
+ half-open global interval, after header/schedule alignment and cell checks;
870
+ segment mode never substitutes a full-run temperature or nominal fallback.
871
+ No validated uncertainty estimate or formal confidence interval is implied.
872
+ Omitting `-trajectory-range` retains the full-trajectory path.
873
+
874
+ Each successful calculation creates `msd/msd.txt` (five numeric columns: lag
875
+ time in ps, x/y/z MSD and their sum in Ų), `msd/self-diff.txt` (x/y/z/total
876
+ diffusion in cm²/s, `%.2e`) and, only with `-ne`, `msd/sigma.txt` (x/y/z/total
877
+ Nernst–Einstein conductivity in mS/cm, `%.2f`). Headers are comments. Total
878
+ diffusion and conductivity are directional arithmetic means before rounding;
879
+ display rounding may cause last-digit differences. PASS and WARNING write these
880
+ coefficients with status in their comment headers. Fit rejection returns nonzero
881
+ but preserves `msd/msd.txt`, `fit-windows.txt` (all evaluated candidates, rejection
882
+ reasons, beta, directional D, R², intercept, RSS, points and upper-lag origin
883
+ count, intercept diagnostics and selected-window segment D values), and
884
+ `fit-diagnostic.txt` (settings, selection and sensitivity). Beta-qualified window
885
+ sensitivity, all-valid-candidate sensitivity, and three-segment slope spread are
886
+ reported separately. Segments and MSD time origins are not independent samples. Rejected
887
+ fits write no diffusion or conductivity files. Window-to-window spread is a
888
+ sensitivity diagnostic, not a statistical confidence interval. Formal statistical uncertainty is not estimated by default. Existing `msd` directories cause an error: move them aside
889
+ before repeating a calculation. Temporary coordinate storage is always removed.
890
+
891
+ The five-column raw MSD is published immediately after FFT succeeds, before
892
+ window search, optional uncertainty, or thermodynamic/NE processing. Later errors
893
+ retain this curve and any completed fit diagnostics; parsing/FFT failures are
894
+ reported separately and do not publish a valid curve. REJECT prints the saved
895
+ path and withholds formal diffusion/conductivity files and new aggregates.
896
+ FFT uses float64 atom chunks sized from an internal 128 MiB workspace budget,
897
+ with bounded remapping of time slabs to avoid retaining the entire coordinate
898
+ memmap in RAM. For 100000 frames and 784 selected atoms the temporary coordinate
899
+ file needs 1,881,600,000 bytes, plus filesystem overhead and output files.
900
+ Installation diagnostics are available with `python devtools/diagnose_msd_install.py`;
901
+ run it using the interpreter in the `pmk` shebang, since source and installed
902
+ distribution versions can differ. Both `pmk -version` and `pmk --version` work.
903
+
904
+ Optional covariance uncertainty (experimental Phase 4B.1.1):
905
+
906
+ ```text
907
+ pmk msd -group 0 --uncertainty covariance
908
+ pmk msd -group 0 -ne --uncertainty covariance --uncertainty-lag-points 100 --uncertainty-confidence 0.95
909
+ ```
910
+
911
+ Adds `self-diff-uncertainty.txt`, `uncertainty-diagnostic.txt` and, with `-ne`,
912
+ `sigma-uncertainty.txt`, using labeled JSON records. Existing point estimates and
913
+ formats remain unchanged. Available results include 68% and 95% Bayesian credible
914
+ intervals plus the requested confidence-level interval. SciPy is lazily imported.
915
+ All overlapping origins contribute to moments: `M=N_mobile*(N_frames-lag_index)`.
916
+ The continuous effective scaling parameter is `N'=N_mobile*N_frames/lag_index`,
917
+ not a literal count of disjoint intervals. The default selects 100 original lag
918
+ indices including window endpoints. The smoothing law `a*t^2/N_effective` uses
919
+ closed-form unweighted nonnegative least squares, verified against the objective
920
+ in kinisi 1.1.0 (without copying its implementation).
921
+
922
+ Continuous counts remove the artificial integer discontinuities. Diagnostics
923
+ compare raw and smoothed covariance, and Tabeart minimum-eigenvalue reconditioning
924
+ at condition limits 1e8/1e12/1e16, including eigenvalue adjustments, relative matrix
925
+ change and conditional posteriors. The threshold is lambda_max/condition_limit;
926
+ no diagonal jitter is added. Failed numerical verification remains unavailable.
927
+ Real 500 K covariance is now positive definite, but reported intervals remain
928
+ `UNAVAILABLE`: interacting-ion coverage has not been established. WARNING windows
929
+ retain conditional candidates in diagnostics only; rejected windows have none.
930
+ CLI success does not imply an available interval: inspect the uncertainty status.
931
+
932
+ Intervals are conditional on the chosen window and estimated covariance.
933
+ Interacting ions and whole-system COM correction limit the independent-particle
934
+ approximation. Covariance-parameter, window-selection, distinct-ion correlation
935
+ and Haven-ratio uncertainties are excluded. With uncertainty requested, missing
936
+ `thermo.out` uses a labeled nominal stationary NVT target; the existing ordinary
937
+ NE path still requires measured temperature. NPT remains release-blocked.
938
+ See [Phase 4B.1 report](devtools/MSD_UNCERTAINTY_PHASE4B1_REPORT.md).
939
+ The [Phase 4B.1.1 correction report](devtools/MSD_UNCERTAINTY_PHASE4B1_1_REPORT.md)
940
+ supersedes its effective-count and real-covariance conclusions. Correlated-particle
941
+ nominal 95% coverage is 67% in the corrected seeded benchmark; a narrow interval
942
+ does not demonstrate statistical convergence.
943
+
944
+ External validation is opt-in via `PYMDKIT_MSD_TEST_DATA` or:
945
+
946
+ ```text
947
+ python devtools/validate_msd_uncertainty.py --data-dir PATH --output NEW_OUTPUT_DIRECTORY
948
+ ```
949
+
950
+ Output must be a new directory outside the input dataset. The script hashes
951
+ original inputs/results before and after, regenerates missing diagnostics,
952
+ reads the original trajectory and removes temporary coordinates. Normal tests
953
+ do not require this external dataset.
954
+
955
+ After every eligible calculation succeeds, root-level `self-diff-total.txt` and,
956
+ with `-ne`, `sigma-total.txt` summarize directory, temperature (K), and the
957
+ isotropic total D (cm²/s, `%.2e`) or conductivity (mS/cm, `%.2f`). Rows use
958
+ relative paths and sort by numeric temperature, then path. Summaries use internal
959
+ unrounded totals. NE uses measured mean production temperature; without NE a
960
+ single stationary production NVT target is required (ramps, multiple targets and
961
+ missing NVT targets produce an explicit error). Genuine calculation failures return
962
+ nonzero and preserve previous summaries; skipped templates are not failures.
963
+ A successful run without `-ne` removes any stale root `sigma-total.txt`.
964
+ The companion `msd-quality-total.txt` retains each directory's PASS/WARNING
965
+ status without changing the existing three-column numeric summaries. A rejected
966
+ directory prevents all new aggregate publication; prior summaries remain prior
967
+ results and the terminal/log explicitly reports that they were preserved.
968
+ See [the automatic-fit report](devtools/MSD_AUTO_FIT_REPORT.md) for validation,
969
+ and [the intercept/stability update](devtools/MSD_AUTO_FIT_PHASE4A1_REPORT.md)
970
+ for the current policy, 500 K MSD comparison and limitations.
971
+
972
+ `-ne` requires a homogeneous selected element and `thermo.out`. The default
973
+ `-charge 1.0` is an explicit +1 formal-charge assumption, not inferred oxidation
974
+ state; negative charges are accepted and the sign cancels. The log records charge,
975
+ measured and target temperature, volume and fit diagnostics. Thermodynamic rows
976
+ are aligned using every run's own output interval. Volume is the absolute cell
977
+ determinant from columns 10–18, never a separate column or the initial model
978
+ volume. Only records between the first and last saved trajectory timestamps are
979
+ averaged; shared sample times cross-check trajectory volumes. The thermo reader
980
+ supports NPT mean volumes internally, but this does not enable NPT MSD. NVT
981
+ volumes must be constant. Measured mean temperature enters the NE equation;
982
+ a >5% target mismatch warns. Temperature ramps are rejected for NE.
983
+
984
+ Nernst–Einstein conductivity uses self-diffusion and neglects distinct-ion cross
985
+ correlations. It is not generally equal to experimental conductivity. The existing
986
+ `gpumd-out -msd` workflow is unchanged.
987
+
988
+ ## Plan GPUMD NVT production from Li MSD
989
+
990
+ Run the predictor from a project directory containing completed GPUMD tasks.
991
+
992
+ ```bash
993
+ pmk pred-msd-time -ea 0.2 -temp-interval 50 -max-temp 550
994
+ pmk gpumd-job -i model.xyz -nep nep.txt -in run.in -msd-time pred-msd-time.log
995
+ ```
996
+
997
+ The predictor defaults to Li group 0 in grouping method 0 and selects the lowest
998
+ eligible measured temperature. Use `-group` to select a different Li group or
999
+ `-ref-temp 300` to select a reference by its nominal or measured temperature.
1000
+ The prediction grid advances by `-temp-interval` from the reference's nominal
1001
+ setpoint up to `-max-temp`. Each target must be above the measured reference.
1002
+ Inconsistent results at the same reference temperature require resolution
1003
+ before planning.
1004
+
1005
+ Use a completed, fixed-cell NVT production trajectory with its original
1006
+ `run.in`, `model.xyz`, and aligned `thermo.out`. The predictor requires a
1007
+ full-trajectory free-intercept OLS result from `pmk msd -ne -group 0` (or the
1008
+ matching Li group) with a +1 formal charge. PASS and WARNING are eligible. A
1009
+ baseline WARNING carries into every prediction, and REJECT excludes the fit
1010
+ from baseline selection. Successful MSD analyses write `msd/provenance.json`
1011
+ (or the equivalent file in a segment directory), which records source and
1012
+ result fingerprints, the selected group and fit, and measured thermodynamics
1013
+ when available. Older full-run results require an identifiable trajectory,
1014
+ group, fit window and quality, agreement with the saved curve and NE totals,
1015
+ and output timestamps at least as recent as the inputs. Incomplete or stale
1016
+ analyses are reported with their reason. Prediction does not rerun MSD.
1017
+
1018
+ Measured conductivity comes from the reference MSD slope and Nernst–Einstein
1019
+ (NE) relation. The forecast uses the measured reference temperature and
1020
+ conductivity with the conventional `ln(sigma*T)` Arrhenius relation.
1021
+
1022
+ ```text
1023
+ sigma(T) = sigma_r * (T_r / T) * exp[-Ea/kB * (1/T - 1/T_r)]
1024
+ D(T) = sigma(T) * V(T) * kB * T / (N_Li * q^2) [in consistent units]
1025
+ t_raw = saved_reference_ns * sqrt(D_reference / D(T))
1026
+ t_plan = ceil(max(min_production_ns, t_raw)) [ns]
1027
+ ```
1028
+
1029
+ Conductivity is independent of the volume prediction. Diffusion uses the same
1030
+ NE relation with the predicted volume and the reference Li count. With one NVT
1031
+ volume sample the volume is constant. With compatible samples (same full-cell
1032
+ composition, selected Li count and fully periodic fixed-cell convention), it
1033
+ is interpolated between measured temperatures. Targets beyond the measured
1034
+ volume range use the nearest endpoint and generate a warning. Other measured
1035
+ conductivities are compared at their actual measured temperatures. The log
1036
+ reports the absolute gap, fractional gap relative to the measurement, and
1037
+ measured-to-predicted ratio. Different fit windows limit the comparison to an
1038
+ indicative check. The supplied activation energy stays fixed.
1039
+
1040
+ The square-root scaling is an empirical planning heuristic. The default 6 ns
1041
+ is a planning floor, configurable with `-min-production-ns`. Recommended
1042
+ durations carry no guarantee of MSD convergence. Determine the actual diffusion
1043
+ regime and fit quality with `pmk msd` after production.
1044
+
1045
+ Provide a fixed timestep and use the placeholders in the production block of
1046
+ the job template. Earlier equilibration blocks can use their own numeric
1047
+ temperatures and run lengths. The template syntax below is compatible with
1048
+ GPUMD 4.2.
1049
+
1050
+ ```text
1051
+ potential nep.txt
1052
+ time_step 1.0
1053
+ ensemble npt_scr 300 300 100 0.0 100.0 1000
1054
+ run 2000000
1055
+
1056
+ ensemble nvt_bdp target_t target_t 100
1057
+ dump_thermo 10
1058
+ dump_exyz 1000 1 1
1059
+ compute_msd 5 msd-steps group 0 0
1060
+ run production-steps
1061
+ ```
1062
+
1063
+ - `production-steps` is the number of NVT MD integration steps,
1064
+ `ceil(t_plan * 1e6 / dt_fs)`.
1065
+ - `msd-steps` is GPUMD's `Nc`, the maximum number of correlation samples.
1066
+ It is `floor(0.5 * t_plan * 1e6 / (sample_interval * dt_fs))`. The sample
1067
+ interval is the first argument of the template's `compute_msd`.
1068
+ Omit the entire directive if you only need raw-trajectory `pmk msd`.
1069
+
1070
+ Pass `-in run.in` to the predictor to use the job template's timestep and
1071
+ sampling interval in the table. Otherwise the table uses the reference run's
1072
+ settings and shows a dash when the saved run has no `compute_msd`. The job
1073
+ generator uses the actual template settings and reports any recalculation.
1074
+ It validates the latest successful prediction record and the complete job
1075
+ batch, then creates one directory per target in the invocation directory.
1076
+ Existing destinations cause the batch to fail before generation. The original
1077
+ template, equilibration runs, `dump_exyz` cadence and optional
1078
+ `compute_msd` arguments are preserved.