minelastic 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. minelastic-0.1.0/CHANGELOG.md +28 -0
  2. minelastic-0.1.0/CITATION.cff +36 -0
  3. minelastic-0.1.0/LICENSE +21 -0
  4. minelastic-0.1.0/MANIFEST.in +6 -0
  5. minelastic-0.1.0/PKG-INFO +165 -0
  6. minelastic-0.1.0/README.md +127 -0
  7. minelastic-0.1.0/docs/codes/ase.md +69 -0
  8. minelastic-0.1.0/docs/codes/other.md +54 -0
  9. minelastic-0.1.0/docs/codes/qe.md +41 -0
  10. minelastic-0.1.0/docs/codes/vasp.md +92 -0
  11. minelastic-0.1.0/docs/get-started/abinit.md +233 -0
  12. minelastic-0.1.0/docs/get-started/cp2k.md +141 -0
  13. minelastic-0.1.0/docs/get-started/first-tensor.md +189 -0
  14. minelastic-0.1.0/docs/get-started/installation.md +41 -0
  15. minelastic-0.1.0/docs/get-started/qe.md +226 -0
  16. minelastic-0.1.0/docs/get-started/vasp.md +209 -0
  17. minelastic-0.1.0/docs/how-to/agentic-workflows.md +48 -0
  18. minelastic-0.1.0/docs/how-to/elastic.md +118 -0
  19. minelastic-0.1.0/docs/how-to/finite-temperature.md +110 -0
  20. minelastic-0.1.0/docs/how-to/internal-strain.md +102 -0
  21. minelastic-0.1.0/docs/how-to/magnetic.md +65 -0
  22. minelastic-0.1.0/docs/how-to/own-workflow.md +135 -0
  23. minelastic-0.1.0/docs/how-to/piezoelectricity.md +216 -0
  24. minelastic-0.1.0/docs/how-to/relaxed-ions.md +117 -0
  25. minelastic-0.1.0/docs/how-to/troubleshooting.md +49 -0
  26. minelastic-0.1.0/docs/index.md +103 -0
  27. minelastic-0.1.0/docs/javascripts/mathjax.js +19 -0
  28. minelastic-0.1.0/docs/reference/api.md +58 -0
  29. minelastic-0.1.0/docs/reference/citing.md +32 -0
  30. minelastic-0.1.0/docs/reference/cli.md +97 -0
  31. minelastic-0.1.0/docs/reference/conventions.md +64 -0
  32. minelastic-0.1.0/docs/reference/validation.md +110 -0
  33. minelastic-0.1.0/docs/theory/cost.md +58 -0
  34. minelastic-0.1.0/docs/theory/elastic.md +85 -0
  35. minelastic-0.1.0/docs/theory/finite-temperature.md +50 -0
  36. minelastic-0.1.0/docs/theory/index.md +142 -0
  37. minelastic-0.1.0/docs/theory/internal-strain.md +51 -0
  38. minelastic-0.1.0/docs/theory/piezoelectricity.md +58 -0
  39. minelastic-0.1.0/docs/theory/relaxed-ions.md +39 -0
  40. minelastic-0.1.0/examples/README.md +23 -0
  41. minelastic-0.1.0/examples/abinit_aln/POSCAR +12 -0
  42. minelastic-0.1.0/examples/abinit_aln/aln.abi +16 -0
  43. minelastic-0.1.0/examples/bks_quartz_piezo.py +109 -0
  44. minelastic-0.1.0/examples/emt_cu.py +17 -0
  45. minelastic-0.1.0/examples/emt_finite_temperature.py +72 -0
  46. minelastic-0.1.0/examples/emt_internal_strain.py +56 -0
  47. minelastic-0.1.0/examples/emt_ionic.py +44 -0
  48. minelastic-0.1.0/examples/qe_aln/pw.in +27 -0
  49. minelastic-0.1.0/examples/replay_vasp_aln.py +34 -0
  50. minelastic-0.1.0/examples/replay_vasp_aln_ionic.py +55 -0
  51. minelastic-0.1.0/examples/vasp_aln/INCAR +8 -0
  52. minelastic-0.1.0/examples/vasp_aln/KPOINTS +5 -0
  53. minelastic-0.1.0/examples/vasp_aln/POSCAR +12 -0
  54. minelastic-0.1.0/mkdocs.yml +130 -0
  55. minelastic-0.1.0/pyproject.toml +47 -0
  56. minelastic-0.1.0/setup.cfg +4 -0
  57. minelastic-0.1.0/skills/minelastic/SKILL.md +160 -0
  58. minelastic-0.1.0/skills/minelastic/references/codes.md +100 -0
  59. minelastic-0.1.0/skills/minelastic/references/quantities.md +98 -0
  60. minelastic-0.1.0/src/minelastic/__init__.py +17 -0
  61. minelastic-0.1.0/src/minelastic/algorithm.py +163 -0
  62. minelastic-0.1.0/src/minelastic/calculator.py +67 -0
  63. minelastic-0.1.0/src/minelastic/cli.py +145 -0
  64. minelastic-0.1.0/src/minelastic/core.py +749 -0
  65. minelastic-0.1.0/src/minelastic/internal_strain.py +42 -0
  66. minelastic-0.1.0/src/minelastic/io/__init__.py +3 -0
  67. minelastic-0.1.0/src/minelastic/io/abinit.py +181 -0
  68. minelastic-0.1.0/src/minelastic/io/aims.py +61 -0
  69. minelastic-0.1.0/src/minelastic/io/generic.py +42 -0
  70. minelastic-0.1.0/src/minelastic/io/qe.py +413 -0
  71. minelastic-0.1.0/src/minelastic/io/vasp.py +432 -0
  72. minelastic-0.1.0/src/minelastic/ionic.py +202 -0
  73. minelastic-0.1.0/src/minelastic/piezo.py +62 -0
  74. minelastic-0.1.0/src/minelastic/properties.py +40 -0
  75. minelastic-0.1.0/src/minelastic/symmetry.py +163 -0
  76. minelastic-0.1.0/src/minelastic/tensor_form.py +159 -0
  77. minelastic-0.1.0/src/minelastic/voigt.py +93 -0
  78. minelastic-0.1.0/src/minelastic/workflow.py +204 -0
  79. minelastic-0.1.0/src/minelastic.egg-info/PKG-INFO +165 -0
  80. minelastic-0.1.0/src/minelastic.egg-info/SOURCES.txt +133 -0
  81. minelastic-0.1.0/src/minelastic.egg-info/dependency_links.txt +1 -0
  82. minelastic-0.1.0/src/minelastic.egg-info/entry_points.txt +2 -0
  83. minelastic-0.1.0/src/minelastic.egg-info/requires.txt +11 -0
  84. minelastic-0.1.0/src/minelastic.egg-info/top_level.txt +1 -0
  85. minelastic-0.1.0/tests/data/al_paper_minimal.json +239 -0
  86. minelastic-0.1.0/tests/data/al_paper_stock.json +579 -0
  87. minelastic-0.1.0/tests/data/aln_cx_stock.json +574 -0
  88. minelastic-0.1.0/tests/data/aln_cx_v2.json +302 -0
  89. minelastic-0.1.0/tests/data/aln_std_stock.json +574 -0
  90. minelastic-0.1.0/tests/data/aln_std_v2.json +302 -0
  91. minelastic-0.1.0/tests/data/se_rot90_stock.json +568 -0
  92. minelastic-0.1.0/tests/data/se_rot90_v2.json +296 -0
  93. minelastic-0.1.0/tests/data/se_std_stock.json +568 -0
  94. minelastic-0.1.0/tests/data/se_std_v2.json +296 -0
  95. minelastic-0.1.0/tests/data_abinit/aln_ecut10.abo +451 -0
  96. minelastic-0.1.0/tests/data_berry/aln_berry_minimal.json +215 -0
  97. minelastic-0.1.0/tests/data_docs/aln_dft_runs.json +596 -0
  98. minelastic-0.1.0/tests/data_ionic/aln_ionic.json +796 -0
  99. minelastic-0.1.0/tests/data_ionic/aln_run_ionic.json +1174 -0
  100. minelastic-0.1.0/tests/data_paper/al_e1.json +629 -0
  101. minelastic-0.1.0/tests/data_paper/al_e2.json +289 -0
  102. minelastic-0.1.0/tests/data_paper/albite_e1.json +779 -0
  103. minelastic-0.1.0/tests/data_paper/albite_e2.json +779 -0
  104. minelastic-0.1.0/tests/data_paper/batio3_e1.json +630 -0
  105. minelastic-0.1.0/tests/data_paper/batio3_e2.json +358 -0
  106. minelastic-0.1.0/tests/data_paper/bi_e1.json +612 -0
  107. minelastic-0.1.0/tests/data_paper/bi_e2.json +340 -0
  108. minelastic-0.1.0/tests/data_paper/camoo4_e1.json +681 -0
  109. minelastic-0.1.0/tests/data_paper/camoo4_e2.json +409 -0
  110. minelastic-0.1.0/tests/data_paper/cawo4_e1.json +672 -0
  111. minelastic-0.1.0/tests/data_paper/cawo4_e2.json +400 -0
  112. minelastic-0.1.0/tests/data_paper/dolomite_e1.json +789 -0
  113. minelastic-0.1.0/tests/data_paper/dolomite_e2.json +517 -0
  114. minelastic-0.1.0/tests/data_paper/ga2o3_e1.json +660 -0
  115. minelastic-0.1.0/tests/data_paper/ga2o3_e2.json +524 -0
  116. minelastic-0.1.0/tests/data_paper/mg_e1.json +619 -0
  117. minelastic-0.1.0/tests/data_paper/mg_e2.json +347 -0
  118. minelastic-0.1.0/tests/data_paper/sio2_e1.json +662 -0
  119. minelastic-0.1.0/tests/data_paper/sio2_e2.json +390 -0
  120. minelastic-0.1.0/tests/data_paper/tio2_e1.json +644 -0
  121. minelastic-0.1.0/tests/data_paper/tio2_e2.json +372 -0
  122. minelastic-0.1.0/tests/data_paper/tisi2_e1.json +767 -0
  123. minelastic-0.1.0/tests/data_paper/tisi2_e2.json +563 -0
  124. minelastic-0.1.0/tests/make_aln_run_fixture.py +59 -0
  125. minelastic-0.1.0/tests/make_docs_fixture.py +52 -0
  126. minelastic-0.1.0/tests/make_ionic_fixture.py +100 -0
  127. minelastic-0.1.0/tests/make_paper_fixtures.sh +40 -0
  128. minelastic-0.1.0/tests/make_vasp_fixture.py +101 -0
  129. minelastic-0.1.0/tests/paper_data_util.py +55 -0
  130. minelastic-0.1.0/tests/test_docs.py +309 -0
  131. minelastic-0.1.0/tests/test_edge_cases.py +397 -0
  132. minelastic-0.1.0/tests/test_ionic.py +210 -0
  133. minelastic-0.1.0/tests/test_minelastic.py +510 -0
  134. minelastic-0.1.0/tests/test_paper_data.py +72 -0
  135. minelastic-0.1.0/tests/test_vasp_data.py +106 -0
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-10-28)
4
+
5
+ First public release, accompanying S. I. Simak and U. Singh, arXiv:2610.11733.
6
+
7
+ * Minimal uncoupled strain sets for all nine elastic symmetry types, in any orientation; extraction
8
+ methods `uncoupled`, `designated` and `lstsq`; consistency checks; VRH moduli and Born stability.
9
+ * Four-point finite differences by default (central differences for MD inputs).
10
+ * `generate`/`collect` from the command line or from Python (`minelastic.generate`, `minelastic.collect`).
11
+ For VASP, every INCAR change is listed and the settings that matter for small stress differences are
12
+ checked; `--fix-incar` applies them.
13
+ * `calculate(..., dipole=f)`: Born charges and piezoelectric tensors with any ASE calculator.
14
+ * Interfaces: VASP, Quantum ESPRESSO (pw.x, any `ibrav`), ABINIT, FHI-aims, any ASE format, any ASE
15
+ calculator.
16
+ * Clamped- and relaxed-ion constants; internal-strain tensor completed by symmetry.
17
+ * `--ionic`: Gamma-point force constants, Born charges, relaxed-ion stiffness and the piezoelectric e and
18
+ d tensors from clamped single points.
19
+ * Berry-phase piezoelectric tensor from the strained cells (VASP `LCALCPOL`).
20
+ * Finite temperature: MD averages (`generate --md`, `collect --md`) and snapshot averages (`--samples`),
21
+ with standard errors and the kinetic term.
22
+ * Symmetry with magnetic order (magnetic space group, including time-reversed operations) from VASP
23
+ `MAGMOM`, ABINIT `spinat`, pw.x species labels and noncollinear directions, and ASE initial moments; VASP
24
+ species blocks and pw.x species labels.
25
+ * Documentation with tutorials for ASE, VASP, Quantum ESPRESSO, ABINIT and CP2K (outputs of real runs),
26
+ how-to guides per quantity and per code, the theory, and the API reference generated from the
27
+ docstrings. The tests run every code block of the documentation and compare the printed output.
28
+ * An agent skill for agentic workflows (`skills/minelastic/`), installable as a Claude Code plugin.
@@ -0,0 +1,36 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use minelastic, please cite the paper below."
3
+ title: "minelastic: elastic constants from minimal uncoupled stress-strain calculations"
4
+ type: software
5
+ version: 0.1.0
6
+ date-released: "2026-10-28"
7
+ license: MIT
8
+ repository-code: "https://github.com/utksi/minelastic"
9
+ url: "https://utksi.github.io/minelastic/"
10
+ keywords:
11
+ - elastic constants
12
+ - stress-strain
13
+ - density functional theory
14
+ - piezoelectricity
15
+ - VASP
16
+ - Quantum ESPRESSO
17
+ - ASE
18
+ authors:
19
+ - family-names: Singh
20
+ given-names: Utkarsh
21
+ affiliation: "Department of Physics, Chemistry and Biology (IFM), Linköping University, Sweden"
22
+ - family-names: Simak
23
+ given-names: Sergei I.
24
+ affiliation: "Department of Physics, Chemistry and Biology (IFM), Linköping University, Sweden"
25
+ preferred-citation:
26
+ type: article
27
+ title: "A General Algorithm for Minimal Uncoupled Stress--Strain Calculations of Elastic Constants"
28
+ authors:
29
+ - family-names: Simak
30
+ given-names: Sergei I.
31
+ - family-names: Singh
32
+ given-names: Utkarsh
33
+ journal: "arXiv preprint arXiv:2610.11733"
34
+ year: 2026
35
+ doi: "10.48550/arXiv.2610.11733"
36
+ url: "https://arxiv.org/abs/2610.11733"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Utkarsh Singh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ include CITATION.cff CHANGELOG.md mkdocs.yml
2
+ recursive-include tests *.py *.json *.sh *.abo
3
+ recursive-include examples *
4
+ recursive-include docs *.md *.js
5
+ recursive-include skills *.md
6
+ prune **/__pycache__
@@ -0,0 +1,165 @@
1
+ Metadata-Version: 2.4
2
+ Name: minelastic
3
+ Version: 0.1.0
4
+ Summary: Elastic constants from minimal uncoupled stress-strain calculations (VASP, Quantum ESPRESSO, ABINIT, FHI-aims, any ASE calculator)
5
+ Author: Utkarsh Singh, Sergei I. Simak
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/utksi/minelastic
8
+ Project-URL: Documentation, https://utksi.github.io/minelastic/
9
+ Project-URL: Source, https://github.com/utksi/minelastic
10
+ Project-URL: Issues, https://github.com/utksi/minelastic/issues
11
+ Project-URL: Paper, https://arxiv.org/abs/2610.11733
12
+ Keywords: elastic constants,stress-strain,density functional theory,VASP,Quantum ESPRESSO,ABINIT,ASE,piezoelectric,materials science
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Scientific/Engineering :: Physics
24
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: numpy>=1.20
29
+ Requires-Dist: spglib>=2.0
30
+ Requires-Dist: ase>=3.22
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest; extra == "test"
33
+ Provides-Extra: docs
34
+ Requires-Dist: mkdocs<2,>=1.6; extra == "docs"
35
+ Requires-Dist: mkdocs-material>=9.5; extra == "docs"
36
+ Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
37
+ Dynamic: license-file
38
+
39
+ <picture>
40
+ <source media="(prefers-color-scheme: dark)" srcset="https://utksi.github.io/minelastic/assets/wordmark-dark.svg">
41
+ <img src="https://utksi.github.io/minelastic/assets/wordmark-light.svg" alt="minelastic" height="72">
42
+ </picture>
43
+
44
+ [![arXiv](https://img.shields.io/badge/arXiv-2610.11733-b31b1b.svg)](https://arxiv.org/abs/2610.11733)
45
+ [![tests](https://github.com/utksi/minelastic/actions/workflows/tests.yml/badge.svg)](https://github.com/utksi/minelastic/actions/workflows/tests.yml)
46
+ [![docs](https://img.shields.io/badge/docs-online-blue.svg)](https://utksi.github.io/minelastic/)
47
+ [![license: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/utksi/minelastic/blob/main/LICENSE)
48
+
49
+ Elastic, internal-strain and piezoelectric tensors from the fewest possible stress calculations, for every
50
+ crystal symmetry and with any electronic-structure code.
51
+
52
+ <picture>
53
+ <source media="(prefers-color-scheme: dark)" srcset="https://utksi.github.io/minelastic/assets/hero-dark.svg">
54
+ <img src="https://utksi.github.io/minelastic/assets/hero-light.svg" alt="The usual approach applies six strain patterns; minelastic applies one to a cubic crystal and reads c11, c12 and c44 from the stress components of the strained cell. Below, the number of strain patterns for each crystal system.">
55
+ </picture>
56
+
57
+ **minelastic** implements the minimal and uncoupled strain sets scheme of
58
+
59
+ > S. I. Simak and U. Singh, *A general algorithm for minimal uncoupled stress-strain calculations of
60
+ > elastic constants*, [arXiv:2610.11733](https://arxiv.org/abs/2610.11733) (2026).
61
+
62
+ Each independent elastic constant is read off one stress component of one strained cell, and the number of
63
+ strain patterns is the smallest that any stress-strain method can use: one for a cubic crystal and two for
64
+ tetragonal, trigonal and hexagonal crystals, where the usual approach (VASP's `IBRION = 6` and most
65
+ workflows) applies six. The same strained cells also give the internal-strain tensor and, with Berry-phase
66
+ dipoles, the clamped-ion piezoelectric tensor; a few single points with displaced atoms add the relaxed-ion constants,
67
+ the Born charges and the total piezoelectric tensors; and molecular dynamics in the strained cells gives the
68
+ constants at finite temperature.
69
+
70
+ ## Installation
71
+
72
+ <!-- skip: installs the package -->
73
+ ```bash
74
+ pip install minelastic
75
+ ```
76
+
77
+ minelastic requires Python 3.9 or newer; numpy, spglib and ASE are installed with it.
78
+
79
+ ## Usage
80
+
81
+ With any ASE calculator, in memory:
82
+
83
+ <!-- run -->
84
+ ```python
85
+ from ase.build import bulk
86
+ from ase.calculators.emt import EMT
87
+ import minelastic
88
+
89
+ result = minelastic.calculate(bulk("Cu", "fcc", a=3.59, cubic=True), EMT())
90
+ print(result.summary())
91
+ ```
92
+
93
+ <!-- output -->
94
+ ```text
95
+ minelastic 0.1.0: Fm-3m (225), cubic, 1 strain pattern(s), method 'uncoupled'
96
+ c11 = 172.50 GPa
97
+ c12 = 115.35 GPa
98
+ c44 = 89.84 GPa
99
+ ...
100
+ Born stable: True (eigenvalues 57.2, 57.2, 89.8, 89.8, 89.8, 403.2)
101
+ K_VRH = 134.40 G_VRH = 56.85 E = 149.48 GPa nu = 0.315 A_U = 1.755
102
+ ...
103
+ ```
104
+
105
+ With a DFT code, minelastic writes the inputs of the strained cells from the input of the relaxed structure
106
+ and reads the finished calculations:
107
+
108
+ <!-- skip: needs a VASP template and the VASP runs -->
109
+ ```bash
110
+ # ref/ holds POSCAR, INCAR, POTCAR and KPOINTS of the relaxed structure
111
+ minelastic generate vasp ref/ -o el
112
+ # run VASP in every directory listed in el/STATES
113
+ minelastic collect el # prints the constants, writes el/elastic.json
114
+ ```
115
+
116
+ VASP, Quantum ESPRESSO, ABINIT, FHI-aims and every structure format that ASE writes are supported, and any
117
+ ASE calculator (EMT, MACE, CP2K, ...) can be used directly.
118
+
119
+ ## Documentation
120
+
121
+ The documentation at https://utksi.github.io/minelastic/ contains tutorials for VASP, Quantum ESPRESSO,
122
+ ABINIT and CP2K, how-to guides for every quantity, the theory with all formulas, and the validation against
123
+ the codes' own elastic, internal-strain, Born-charge and piezoelectric tensors. Runnable scripts are in
124
+ [`examples/`](https://github.com/utksi/minelastic/tree/main/examples).
125
+
126
+ ## Usage with agentic workflows
127
+
128
+ An AI coding agent can run minelastic for you. [`skills/minelastic`](https://github.com/utksi/minelastic/tree/main/skills/minelastic) is an agent skill
129
+ with the commands and the checks that a correct calculation needs. In Claude Code:
130
+
131
+ <!-- skip: Claude Code commands -->
132
+ ```text
133
+ /plugin marketplace add utksi/minelastic
134
+ /plugin install minelastic@minelastic
135
+ ```
136
+
137
+ Other agents can read [`skills/minelastic/SKILL.md`](https://github.com/utksi/minelastic/blob/main/skills/minelastic/SKILL.md) directly. Examples are in
138
+ the [documentation](https://utksi.github.io/minelastic/how-to/agentic-workflows/).
139
+
140
+ ## Citing
141
+
142
+ If you use minelastic in published work, please cite the paper:
143
+
144
+ ```bibtex
145
+ @misc{simak2026minimal,
146
+ title = {A General Algorithm for Minimal Uncoupled Stress--Strain
147
+ Calculations of Elastic Constants},
148
+ author = {Simak, Sergei I. and Singh, Utkarsh},
149
+ year = {2026},
150
+ eprint = {2610.11733},
151
+ archivePrefix = {arXiv},
152
+ primaryClass = {cond-mat.mtrl-sci},
153
+ doi = {10.48550/arXiv.2610.11733}
154
+ }
155
+ ```
156
+
157
+ ## Tests and license
158
+
159
+ `pip install -e ".[test]" && pytest tests` runs the tests. They use stored stresses of real calculations,
160
+ among them the paper's benchmark runs for all nine elastic types, and they run every code example of the
161
+ documentation, so no DFT code is needed.
162
+
163
+ minelastic is distributed under the MIT license ([LICENSE](https://github.com/utksi/minelastic/blob/main/LICENSE)). It was developed at the Department of
164
+ Physics, Chemistry and Biology (IFM), Linköping University. Questions and bug reports are welcome as GitHub
165
+ issues.
@@ -0,0 +1,127 @@
1
+ <picture>
2
+ <source media="(prefers-color-scheme: dark)" srcset="https://utksi.github.io/minelastic/assets/wordmark-dark.svg">
3
+ <img src="https://utksi.github.io/minelastic/assets/wordmark-light.svg" alt="minelastic" height="72">
4
+ </picture>
5
+
6
+ [![arXiv](https://img.shields.io/badge/arXiv-2610.11733-b31b1b.svg)](https://arxiv.org/abs/2610.11733)
7
+ [![tests](https://github.com/utksi/minelastic/actions/workflows/tests.yml/badge.svg)](https://github.com/utksi/minelastic/actions/workflows/tests.yml)
8
+ [![docs](https://img.shields.io/badge/docs-online-blue.svg)](https://utksi.github.io/minelastic/)
9
+ [![license: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/utksi/minelastic/blob/main/LICENSE)
10
+
11
+ Elastic, internal-strain and piezoelectric tensors from the fewest possible stress calculations, for every
12
+ crystal symmetry and with any electronic-structure code.
13
+
14
+ <picture>
15
+ <source media="(prefers-color-scheme: dark)" srcset="https://utksi.github.io/minelastic/assets/hero-dark.svg">
16
+ <img src="https://utksi.github.io/minelastic/assets/hero-light.svg" alt="The usual approach applies six strain patterns; minelastic applies one to a cubic crystal and reads c11, c12 and c44 from the stress components of the strained cell. Below, the number of strain patterns for each crystal system.">
17
+ </picture>
18
+
19
+ **minelastic** implements the minimal and uncoupled strain sets scheme of
20
+
21
+ > S. I. Simak and U. Singh, *A general algorithm for minimal uncoupled stress-strain calculations of
22
+ > elastic constants*, [arXiv:2610.11733](https://arxiv.org/abs/2610.11733) (2026).
23
+
24
+ Each independent elastic constant is read off one stress component of one strained cell, and the number of
25
+ strain patterns is the smallest that any stress-strain method can use: one for a cubic crystal and two for
26
+ tetragonal, trigonal and hexagonal crystals, where the usual approach (VASP's `IBRION = 6` and most
27
+ workflows) applies six. The same strained cells also give the internal-strain tensor and, with Berry-phase
28
+ dipoles, the clamped-ion piezoelectric tensor; a few single points with displaced atoms add the relaxed-ion constants,
29
+ the Born charges and the total piezoelectric tensors; and molecular dynamics in the strained cells gives the
30
+ constants at finite temperature.
31
+
32
+ ## Installation
33
+
34
+ <!-- skip: installs the package -->
35
+ ```bash
36
+ pip install minelastic
37
+ ```
38
+
39
+ minelastic requires Python 3.9 or newer; numpy, spglib and ASE are installed with it.
40
+
41
+ ## Usage
42
+
43
+ With any ASE calculator, in memory:
44
+
45
+ <!-- run -->
46
+ ```python
47
+ from ase.build import bulk
48
+ from ase.calculators.emt import EMT
49
+ import minelastic
50
+
51
+ result = minelastic.calculate(bulk("Cu", "fcc", a=3.59, cubic=True), EMT())
52
+ print(result.summary())
53
+ ```
54
+
55
+ <!-- output -->
56
+ ```text
57
+ minelastic 0.1.0: Fm-3m (225), cubic, 1 strain pattern(s), method 'uncoupled'
58
+ c11 = 172.50 GPa
59
+ c12 = 115.35 GPa
60
+ c44 = 89.84 GPa
61
+ ...
62
+ Born stable: True (eigenvalues 57.2, 57.2, 89.8, 89.8, 89.8, 403.2)
63
+ K_VRH = 134.40 G_VRH = 56.85 E = 149.48 GPa nu = 0.315 A_U = 1.755
64
+ ...
65
+ ```
66
+
67
+ With a DFT code, minelastic writes the inputs of the strained cells from the input of the relaxed structure
68
+ and reads the finished calculations:
69
+
70
+ <!-- skip: needs a VASP template and the VASP runs -->
71
+ ```bash
72
+ # ref/ holds POSCAR, INCAR, POTCAR and KPOINTS of the relaxed structure
73
+ minelastic generate vasp ref/ -o el
74
+ # run VASP in every directory listed in el/STATES
75
+ minelastic collect el # prints the constants, writes el/elastic.json
76
+ ```
77
+
78
+ VASP, Quantum ESPRESSO, ABINIT, FHI-aims and every structure format that ASE writes are supported, and any
79
+ ASE calculator (EMT, MACE, CP2K, ...) can be used directly.
80
+
81
+ ## Documentation
82
+
83
+ The documentation at https://utksi.github.io/minelastic/ contains tutorials for VASP, Quantum ESPRESSO,
84
+ ABINIT and CP2K, how-to guides for every quantity, the theory with all formulas, and the validation against
85
+ the codes' own elastic, internal-strain, Born-charge and piezoelectric tensors. Runnable scripts are in
86
+ [`examples/`](https://github.com/utksi/minelastic/tree/main/examples).
87
+
88
+ ## Usage with agentic workflows
89
+
90
+ An AI coding agent can run minelastic for you. [`skills/minelastic`](https://github.com/utksi/minelastic/tree/main/skills/minelastic) is an agent skill
91
+ with the commands and the checks that a correct calculation needs. In Claude Code:
92
+
93
+ <!-- skip: Claude Code commands -->
94
+ ```text
95
+ /plugin marketplace add utksi/minelastic
96
+ /plugin install minelastic@minelastic
97
+ ```
98
+
99
+ Other agents can read [`skills/minelastic/SKILL.md`](https://github.com/utksi/minelastic/blob/main/skills/minelastic/SKILL.md) directly. Examples are in
100
+ the [documentation](https://utksi.github.io/minelastic/how-to/agentic-workflows/).
101
+
102
+ ## Citing
103
+
104
+ If you use minelastic in published work, please cite the paper:
105
+
106
+ ```bibtex
107
+ @misc{simak2026minimal,
108
+ title = {A General Algorithm for Minimal Uncoupled Stress--Strain
109
+ Calculations of Elastic Constants},
110
+ author = {Simak, Sergei I. and Singh, Utkarsh},
111
+ year = {2026},
112
+ eprint = {2610.11733},
113
+ archivePrefix = {arXiv},
114
+ primaryClass = {cond-mat.mtrl-sci},
115
+ doi = {10.48550/arXiv.2610.11733}
116
+ }
117
+ ```
118
+
119
+ ## Tests and license
120
+
121
+ `pip install -e ".[test]" && pytest tests` runs the tests. They use stored stresses of real calculations,
122
+ among them the paper's benchmark runs for all nine elastic types, and they run every code example of the
123
+ documentation, so no DFT code is needed.
124
+
125
+ minelastic is distributed under the MIT license ([LICENSE](https://github.com/utksi/minelastic/blob/main/LICENSE)). It was developed at the Department of
126
+ Physics, Chemistry and Biology (IFM), Linköping University. Questions and bug reports are welcome as GitHub
127
+ issues.
@@ -0,0 +1,69 @@
1
+ # ASE calculators
2
+
3
+ Any ASE calculator that returns the stress can be used directly from Python: EMT and other interatomic
4
+ potentials, machine-learned potentials such as MACE, and DFT codes driven through ASE such as CP2K. The
5
+ [first tutorial](../get-started/first-tensor.md) uses EMT, and the [CP2K tutorial](../get-started/cp2k.md) a
6
+ DFT code.
7
+
8
+ ## `calculate`
9
+
10
+ <!-- input -->
11
+ ```python
12
+ result = minelastic.calculate(atoms, calc, relax_ions=False, method="uncoupled", fmax=1e-4, steps=500,
13
+ optimizer=None, dipole=None, **setup_kwargs)
14
+ ```
15
+
16
+ builds the strain set of `atoms` (`ElasticSetup(atoms, **setup_kwargs)`), computes every strained and
17
+ displaced cell with the ASE calculator `calc` and returns the `ElasticResult`. For each cell it takes
18
+
19
+ * the stress, `calc.get_stress()` in eV/Å$^3$, converted to GPa (tension positive, as in ASE);
20
+ * the forces, for the internal-strain tensor and, with `ionic=True`, the force constants;
21
+ * the dipole `dipole(atoms)` in e Å, if a function is given, for the Born charges and the piezoelectric
22
+ tensors.
23
+
24
+ With `relax_ions=True` the atoms of each strained cell are first relaxed at fixed cell with `optimizer`
25
+ (default BFGS) to `fmax` (eV/Å). `setup_kwargs` are the options of `ElasticSetup`: `scheme`, `delta`,
26
+ `stencil`, `symprec`, `frame`, `ionic` and `displacement` ([Python API](../reference/api.md)).
27
+
28
+ The how-to pages show each quantity with an ASE calculator:
29
+
30
+ | quantity | example | page |
31
+ |---|---|---|
32
+ | clamped- and relaxed-ion constants | fcc and hcp Cu, EMT | [Your first elastic tensor](../get-started/first-tensor.md) |
33
+ | relaxed-ion constants, two routes | hcp Cu, EMT (`examples/emt_ionic.py`) | [Relaxed-ion constants](../how-to/relaxed-ions.md#with-an-ase-calculator) |
34
+ | internal-strain tensor, force constants | hcp Cu, EMT (`examples/emt_internal_strain.py`) | [Internal strain](../how-to/internal-strain.md#with-an-ase-calculator) |
35
+ | Born charges, piezoelectric e and d | alpha-quartz, BKS rigid-ion model (`examples/bks_quartz_piezo.py`) | [Piezoelectricity](../how-to/piezoelectricity.md#with-an-ase-calculator) |
36
+ | finite temperature | fcc Al, EMT molecular dynamics (`examples/emt_finite_temperature.py`) | [Finite temperature](../how-to/finite-temperature.md#with-an-ase-calculator) |
37
+
38
+ !!! tip
39
+
40
+ Relax the reference cell with the same calculator first: the textbook constants refer to a stress-free
41
+ reference.
42
+
43
+ ## Machine-learned potentials
44
+
45
+ Any ASE calculator works.
46
+
47
+ !!! tip "Double precision"
48
+
49
+ Run machine-learned potentials in double precision: the stresses of the strained cells differ by only
50
+ about 1 GPa.
51
+
52
+ <!-- skip: needs MACE -->
53
+ ```python
54
+ from ase.io import read
55
+ from ase.filters import FrechetCellFilter
56
+ from ase.optimize import BFGS
57
+ from mace.calculators import mace_mp
58
+ import minelastic
59
+
60
+ atoms = read("POSCAR")
61
+ calc = mace_mp(model="medium", default_dtype="float64")
62
+ atoms.calc = calc
63
+ BFGS(FrechetCellFilter(atoms)).run(fmax=1e-4) # stress-free reference
64
+ result = minelastic.calculate(atoms, calc, relax_ions=True)
65
+ print(result.summary())
66
+ ```
67
+
68
+ For wurtzite AlN with MACE-MPA-0, the minimal set and the six single strains agree to 0.1 GPa, and the two
69
+ routes to the relaxed-ion constants to 0.3 GPa ([Validation](../reference/validation.md)).
@@ -0,0 +1,54 @@
1
+ # ABINIT, FHI-aims and other codes
2
+
3
+ ## ABINIT
4
+
5
+ A complete example is the [ABINIT tutorial](../get-started/abinit.md). The template
6
+ directory holds the reference structure as `POSCAR` and one ABINIT input file (`*.abi`) that reads it with
7
+ `structure "poscar:POSCAR"`. The input sets everything else: pseudopotentials in the order of the POSCAR
8
+ species, cutoff, k-point mesh and convergence.
9
+
10
+ ABINIT's POSCAR reader takes the element of each atom from the end of its coordinate line, so minelastic
11
+ writes the strained POSCARs in that form; for the same reason two species of one element cannot be used.
12
+ Magnetic sublattices are set with `spinat`, which minelastic also reads for the symmetry
13
+ ([Magnetic materials](../how-to/magnetic.md)). `collect` reads the stress and forces from the newest
14
+ `*.abo` file of each directory. With `--relax-ions`, `ionmov 2`, `ntime 100` and `tolmxf 1.0d-6` are
15
+ appended unless the input sets `ionmov`. The cell must stay fixed (`optcell 0`), the ions must stay fixed for
16
+ clamped-ion runs (no `ionmov`), and dataset-specific values of `ionmov` and `optcell` are not accepted.
17
+
18
+ ## FHI-aims
19
+
20
+ The template directory holds `geometry.in` (the reference structure) and `control.in`:
21
+
22
+ <!-- skip: needs an FHI-aims template and the FHI-aims runs -->
23
+ ```bash
24
+ minelastic generate aims ref/ -o el # geometry.in per strain state, control.in copied
25
+ # run aims in every directory, output in aims.out
26
+ minelastic collect el
27
+ ```
28
+
29
+ `control.in` must request the stress (`compute_analytical_stress .true.`) and must not relax the cell
30
+ (`relax_unit_cell`); otherwise `generate` stops with an error. For clamped ions it must not relax the atoms
31
+ either. With `--relax-ions`, `relax_geometry bfgs 1E-3` is added unless it is present. The FHI-aims reader
32
+ is tested on an output distributed with ASE; minelastic has not been run with FHI-aims itself.
33
+
34
+ ## Any format ASE can write (CASTEP, SIESTA, ...)
35
+
36
+ The `generic` interface writes only the strained structure in each directory and copies further input
37
+ files. The results are read back with ASE:
38
+
39
+ <!-- skip: needs CASTEP inputs and the CASTEP runs -->
40
+ ```bash
41
+ minelastic generate generic crystal.cell -o el --format castep-cell --filename crystal.cell \
42
+ --extra crystal.param
43
+ # run the code in every directory
44
+ minelastic collect el --output crystal.castep --format castep-castep
45
+ ```
46
+
47
+ The reference structure (`crystal.cell` here) is read with the same `--format` as the files that are
48
+ written. Make sure the inputs request the stress and keep the cell fixed. Keep the ions fixed too, unless
49
+ you want relaxed ions. `minelastic info crystal.cell --format castep-cell` shows the strain set first.
50
+
51
+ ## Anything else
52
+
53
+ The Python API separates the strain set from how the calculations are run, so stresses from any source can
54
+ be used ([Your own workflow](../how-to/own-workflow.md)).
@@ -0,0 +1,41 @@
1
+ # Quantum ESPRESSO
2
+
3
+ A complete example is the [Quantum ESPRESSO tutorial](../get-started/qe.md). Below we describe how
4
+ minelastic handles the pw.x inputs and outputs.
5
+
6
+ ## Template and commands
7
+
8
+ The template is the pw.x input of the relaxed reference structure. pw.x runs in one sub-directory per
9
+ state, so set `pseudo_dir` to an absolute path.
10
+
11
+ <!-- skip: needs a pw.x template and the pw.x runs -->
12
+ ```bash
13
+ minelastic generate qe pw.in -o el # clamped ions
14
+ minelastic generate qe pw.in -o el_relaxed --relax-ions
15
+ for d in $(cat el/STATES); do (cd el/$d && mpirun pw.x -in pw.in > pw.out); done
16
+ minelastic collect el
17
+ ```
18
+
19
+ ## The inputs
20
+
21
+ Every strained input is written with
22
+
23
+ * `ibrav = 0`, the strained `CELL_PARAMETERS` in Å and `ATOMIC_POSITIONS crystal`;
24
+ * the species labels and `if_pos` flags of the template;
25
+ * `tstress` and `tprnfor` switched on.
26
+
27
+ Any `ibrav` is accepted, with `celldm` or with `A, B, C, cosAB, ...`, and the positions may be given in
28
+ `alat`, `bohr`, `angstrom` or `crystal`. All other namelists and cards are copied unchanged. For relaxed
29
+ ions, `calculation = 'relax'` is set, with tight `forc_conv_thr` and `etot_conv_thr` unless the template
30
+ sets them: the defaults of pw.x stop the relaxation before the internal strain is relaxed. `collect` reads
31
+ `pw.out` in each directory (`--output` for another name). pw.x prints the stress in Ry/bohr$^3$, positive in
32
+ compression; minelastic converts it to GPa, positive in tension.
33
+
34
+ ## Magnetic order and molecular dynamics
35
+
36
+ pw.x needs a separate species label for every magnetic sublattice (starting magnetization per species), and
37
+ minelastic treats the labels as distinct species in the symmetry analysis. With `noncolin = .true.` it also
38
+ reads the moment directions from `starting_magnetization`, `angle1` and `angle2`
39
+ ([Magnetic materials](../how-to/magnetic.md)). For finite temperature, the template has `calculation = 'md'`
40
+ with a thermostat in `&IONS` and a fixed cell; `generate --md` keeps it and `collect --md` averages the
41
+ stresses of all steps ([Finite temperature](../how-to/finite-temperature.md#with-vasp-or-quantum-espresso)).
@@ -0,0 +1,92 @@
1
+ # VASP
2
+
3
+ A complete example is the [VASP tutorial](../get-started/vasp.md). Below we describe how minelastic
4
+ handles the VASP inputs and outputs.
5
+
6
+ ## Template and commands
7
+
8
+ The template directory holds the input of the relaxed reference structure: `POSCAR`, `INCAR`, `POTCAR`, and
9
+ `KPOINTS` or `KSPACING` in the INCAR.
10
+
11
+ <!-- skip: needs a template directory ref/ and the VASP runs -->
12
+ ```bash
13
+ minelastic info --code vasp ref/ # symmetry, tensor form and strain set; no files written
14
+ minelastic generate vasp ref/ -o el # one directory per state, listed in el/STATES
15
+ minelastic collect el # after the runs; writes el/elastic.json
16
+ ```
17
+
18
+ Each `el/<state>/` holds `POSCAR` (the strained or displaced cell, with the species lines and the
19
+ selective-dynamics flags of the template), `INCAR`, `KPOINTS` and `POTCAR` (`--potcar link` symlinks it).
20
+ `el/minelastic.json` records the setup; `collect` needs it.
21
+
22
+ ## The INCAR
23
+
24
+ `generate` copies the template's INCAR and changes only what the type of calculation requires:
25
+
26
+ * `IBRION = -1`, `NSW = 0`, `ISIF = 2` for clamped ions (`ISIF = 2` computes the stress);
27
+ * `IBRION = 2`, `NSW = 99`, `ISIF = 2` and, unless set, `EDIFFG = -5E-4` with `--relax-ions`;
28
+ * with `--md`, the template's `IBRION = 0`, `NSW` and `POTIM` are kept and `ISIF = 2` is set;
29
+ * `NFREE`, `POTIM`, `LEPSILON` and `LCALCEPS` are removed, so that an `IBRION = 6` input can be used as it
30
+ is (relaxations then use VASP's default `POTIM`);
31
+ * `KSPACING` is replaced by the explicit k-point mesh of the reference cell, so that all cells use the same
32
+ mesh.
33
+
34
+ Every change is listed. The settings that matter for stress differences of a few GPa are checked, but left as
35
+ they are: `EDIFF` at most 1E-6 (1E-8 suggested; 1E-6 for MD), `ENCUT` at least 1.3 times the largest
36
+ `ENMAX` of the POTCAR, `PREC = Accurate` (or `High`) and `LREAL = .FALSE.`. The template of the tutorial
37
+ meets all of them. The INCAR of an `IBRION = 6` run with VASP's defaults gives:
38
+
39
+ <!-- shell -->
40
+ ```console
41
+ $ cat ibrion6/INCAR
42
+ IBRION = 6
43
+ ISIF = 3
44
+ NFREE = 2
45
+ POTIM = 0.015
46
+ $ minelastic generate vasp ibrion6 -o el
47
+ ...
48
+ NOTE: INCAR: set IBRION = -1 (template: 6), NSW = 0, ISIF = 2 (template: 3); removed NFREE, POTIM
49
+ NOTE: INCAR: recommended for small stress differences: EDIFF default 1E-4 -> 1E-8, ENCUT default ENMAX = 400 -> 520, PREC default Normal -> Accurate. The template values are kept; --fix-incar (fix_incar=True) applies all of these
50
+ ```
51
+
52
+ `--fix-incar` applies all of the recommended values. There is no partial fix: the INCAR is either the
53
+ template's or follows all the recommendations.
54
+
55
+ ## Running
56
+
57
+ Any scheduler works. For example, a Slurm job array over the lines of `STATES`:
58
+
59
+ <!-- skip: submits a Slurm job -->
60
+ ```bash
61
+ #!/bin/bash
62
+ #SBATCH --array=1-8 # one task per line of el/STATES
63
+ d=el/$(sed -n "${SLURM_ARRAY_TASK_ID}p" el/STATES)
64
+ cd "$d" && srun vasp_std > out
65
+ ```
66
+
67
+ ## Reading the results
68
+
69
+ `collect` reads the stress and the forces of each directory from `vasprun.xml`, or from `OUTCAR` if there is
70
+ no readable `vasprun.xml`. VASP prints the stress in kB, positive in compression, in the order XX YY ZZ XY YZ
71
+ ZX; minelastic converts it to GPa, positive in tension, in Voigt order. With `--md` the stress of every ionic
72
+ step is read; with `--piezo` the Berry-phase dipole of each cell (`LCALCPOL`); with `--born OUTCAR` the Born
73
+ charges and the clamped-ion piezoelectric tensor of a DFPT (`LEPSILON`) or `LCALCEPS` run.
74
+
75
+ `minelastic vasp-tensor OUTCAR` reads the tensor that VASP prints for `IBRION = 6` with `ISIF = 3` or more,
76
+ converts it to GPa and Voigt order, and adds the Voigt-Reuss-Hill moduli and the Born stability test
77
+ ([Elastic constants in practice](../how-to/elastic.md#compare-with-vasps-ibrion-6)).
78
+
79
+ ## Notes
80
+
81
+ * Use the same `ENCUT`, `PREC`, k-point mesh and `EDIFF` for the reference and all strained cells. The
82
+ plane-wave basis changes with the volume of the strained cell, and a raised cutoff (1.3 to 1.4 times
83
+ ENMAX) keeps the resulting Pulay stress small.
84
+ * `MAGMOM`, `LDAU*`, `ISPIN` and all other tags are copied unchanged, and `MAGMOM` enters the symmetry
85
+ analysis ([Magnetic materials](../how-to/magnetic.md)). If the cell has to be rotated to its standard
86
+ orientation, direction-dependent inputs (`LNONCOLLINEAR`, `LSORBIT`, `SAXIS`, `EFIELD`, Cartesian k points)
87
+ are refused; use `--frame input`.
88
+ * The elastic constants, the internal-strain tensor, the relaxed-ion constants and the piezoelectric tensors
89
+ of the tutorial structure are on the how-to pages:
90
+ [elastic constants](../how-to/elastic.md), [relaxed ions](../how-to/relaxed-ions.md#with-vasp),
91
+ [internal strain](../how-to/internal-strain.md#with-vasp) and
92
+ [piezoelectricity](../how-to/piezoelectricity.md#with-vasp).