FermiSimplex 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 (70) hide show
  1. fermisimplex-0.1.0/.gitignore +26 -0
  2. fermisimplex-0.1.0/CHANGELOG.md +14 -0
  3. fermisimplex-0.1.0/CITATION.cff +10 -0
  4. fermisimplex-0.1.0/CMakeLists.txt +31 -0
  5. fermisimplex-0.1.0/LICENSE +28 -0
  6. fermisimplex-0.1.0/PKG-INFO +217 -0
  7. fermisimplex-0.1.0/README.md +188 -0
  8. fermisimplex-0.1.0/ci/test_wheel.py +41 -0
  9. fermisimplex-0.1.0/cpp/CMakeLists.txt +457 -0
  10. fermisimplex-0.1.0/cpp/cmake/fermisimplex-config.cmake.in +9 -0
  11. fermisimplex-0.1.0/cpp/include/fermisimplex/certification.h +64 -0
  12. fermisimplex-0.1.0/cpp/include/fermisimplex/fermi_surface.h +42 -0
  13. fermisimplex-0.1.0/cpp/include/fermisimplex/fermisimplex.h +7 -0
  14. fermisimplex-0.1.0/cpp/include/fermisimplex/hamiltonian.h +49 -0
  15. fermisimplex-0.1.0/cpp/include/fermisimplex/integration.h +70 -0
  16. fermisimplex-0.1.0/cpp/include/fermisimplex/spectral_mesh.h +75 -0
  17. fermisimplex-0.1.0/cpp/src/certification/bounds/mu_bounds.cpp +108 -0
  18. fermisimplex-0.1.0/cpp/src/certification/bounds/mu_bounds.h +38 -0
  19. fermisimplex-0.1.0/cpp/src/certification/bounds/occupation_bounds.cpp +164 -0
  20. fermisimplex-0.1.0/cpp/src/certification/bounds/occupation_bounds.h +29 -0
  21. fermisimplex-0.1.0/cpp/src/certification/linalg/cholesky.cpp +43 -0
  22. fermisimplex-0.1.0/cpp/src/certification/linalg/cholesky.h +23 -0
  23. fermisimplex-0.1.0/cpp/src/certification/linalg/matrix.h +35 -0
  24. fermisimplex-0.1.0/cpp/src/certification/linalg/rotated_blocks.cpp +136 -0
  25. fermisimplex-0.1.0/cpp/src/certification/linalg/rotated_blocks.h +31 -0
  26. fermisimplex-0.1.0/cpp/src/certification/mesh_certificate.h +18 -0
  27. fermisimplex-0.1.0/cpp/src/certification/simplex/anchor_selection.cpp +78 -0
  28. fermisimplex-0.1.0/cpp/src/certification/simplex/anchor_selection.h +42 -0
  29. fermisimplex-0.1.0/cpp/src/certification/simplex/occupation_certificate.cpp +195 -0
  30. fermisimplex-0.1.0/cpp/src/certification/simplex/occupation_certificate.h +42 -0
  31. fermisimplex-0.1.0/cpp/src/certification/simplex/simplex_blocks.cpp +63 -0
  32. fermisimplex-0.1.0/cpp/src/certification/simplex/simplex_blocks.h +33 -0
  33. fermisimplex-0.1.0/cpp/src/certification/simplex/vertex_blocks.cpp +175 -0
  34. fermisimplex-0.1.0/cpp/src/certification/simplex/vertex_blocks.h +33 -0
  35. fermisimplex-0.1.0/cpp/src/certification/simplex_certificate.cpp +210 -0
  36. fermisimplex-0.1.0/cpp/src/core/simplex_geometry.h +47 -0
  37. fermisimplex-0.1.0/cpp/src/core/spectral_mesh.cpp +134 -0
  38. fermisimplex-0.1.0/cpp/src/core/tight_binding.cpp +211 -0
  39. fermisimplex-0.1.0/cpp/src/fermi_surface/adaptive_refinement.cpp +171 -0
  40. fermisimplex-0.1.0/cpp/src/fermi_surface/adaptive_refinement.h +17 -0
  41. fermisimplex-0.1.0/cpp/src/fermi_surface/fermi_surface.cpp +43 -0
  42. fermisimplex-0.1.0/cpp/src/fermi_surface/simplex_classification.cpp +63 -0
  43. fermisimplex-0.1.0/cpp/src/fermi_surface/simplex_classification.h +27 -0
  44. fermisimplex-0.1.0/cpp/src/fermi_surface/surface_extraction.cpp +266 -0
  45. fermisimplex-0.1.0/cpp/src/fermi_surface/surface_extraction.h +21 -0
  46. fermisimplex-0.1.0/cpp/src/fermi_surface/surface_triangulation.cpp +72 -0
  47. fermisimplex-0.1.0/cpp/src/fermi_surface/surface_triangulation.h +14 -0
  48. fermisimplex-0.1.0/cpp/src/integration/charge.cpp +298 -0
  49. fermisimplex-0.1.0/cpp/src/integration/charge.h +60 -0
  50. fermisimplex-0.1.0/cpp/src/integration/density.cpp +150 -0
  51. fermisimplex-0.1.0/cpp/src/integration/density.h +44 -0
  52. fermisimplex-0.1.0/cpp/src/integration/integration.cpp +330 -0
  53. fermisimplex-0.1.0/cpp/src/integration/projected_error.cpp +479 -0
  54. fermisimplex-0.1.0/cpp/src/integration/projected_error.h +40 -0
  55. fermisimplex-0.1.0/cpp/src/linalg/blas.cpp +216 -0
  56. fermisimplex-0.1.0/cpp/src/linalg/blas_lapack.h +74 -0
  57. fermisimplex-0.1.0/cpp/src/linalg/lapack.cpp +270 -0
  58. fermisimplex-0.1.0/pyproject.toml +100 -0
  59. fermisimplex-0.1.0/python/CMakeLists.txt +48 -0
  60. fermisimplex-0.1.0/python/fermisimplex/__init__.py +31 -0
  61. fermisimplex-0.1.0/python/fermisimplex/certification.py +45 -0
  62. fermisimplex-0.1.0/python/fermisimplex/hamiltonian.py +108 -0
  63. fermisimplex-0.1.0/python/fermisimplex/mesh.py +365 -0
  64. fermisimplex-0.1.0/python/src/bindings/arrays.h +52 -0
  65. fermisimplex-0.1.0/python/src/bindings/bindings.h +14 -0
  66. fermisimplex-0.1.0/python/src/bindings/certification.cpp +143 -0
  67. fermisimplex-0.1.0/python/src/bindings/fermi_surface.cpp +65 -0
  68. fermisimplex-0.1.0/python/src/bindings/integration_types.cpp +48 -0
  69. fermisimplex-0.1.0/python/src/bindings/module.cpp +14 -0
  70. fermisimplex-0.1.0/python/src/bindings/spectral_mesh.cpp +393 -0
@@ -0,0 +1,26 @@
1
+ .pixi/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ .pytest_cache/
7
+ .ipynb_checkpoints/
8
+ .ruff_cache/
9
+ .mypy_cache/
10
+ .coverage
11
+ htmlcov/
12
+ artifacts/
13
+ docs/generated/
14
+
15
+ build/
16
+ dist/
17
+ *.egg-info/
18
+ _skbuild/
19
+ CMakeCache.txt
20
+ CMakeFiles/
21
+ cmake-build-*/
22
+ compile_commands.json
23
+
24
+ *.so
25
+ *.dylib
26
+ *.dll
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ All notable changes to FermiSimplex are documented in this file.
4
+
5
+ ## Unreleased
6
+
7
+ ## 0.1.0 - 2026-07-28
8
+
9
+ - Added adaptive Fermi-surface extraction, charge integration, and density
10
+ matrices through a shared Python and C++ numerical core.
11
+ - Added occupation certification, projected charge-error estimation, and
12
+ reusable eigensystem caching on adaptive simplex meshes.
13
+ - Added production tests, performance benchmarks, examples, and visual
14
+ documentation.
@@ -0,0 +1,10 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use FermiSimplex, please cite it using this metadata."
3
+ title: "FermiSimplex"
4
+ version: "0.1.0"
5
+ date-released: "2026-07-28"
6
+ authors:
7
+ - family-names: "Vilkelis"
8
+ given-names: "Kostas"
9
+ license: "BSD-3-Clause"
10
+ repository-code: "https://gitlab.kwant-project.org/qt/lineartetrahedron"
@@ -0,0 +1,31 @@
1
+ cmake_minimum_required(VERSION 3.28...3.30)
2
+
3
+ project(
4
+ FermiSimplex
5
+ VERSION 0.1.0
6
+ LANGUAGES CXX
7
+ )
8
+
9
+ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
10
+ set(FERMISIMPLEX_TOP_LEVEL_DEFAULT ON)
11
+ include(CTest)
12
+ else()
13
+ set(FERMISIMPLEX_TOP_LEVEL_DEFAULT OFF)
14
+ endif()
15
+
16
+ option(
17
+ FERMISIMPLEX_BUILD_PYTHON
18
+ "Build the FermiSimplex Python extension"
19
+ "${FERMISIMPLEX_TOP_LEVEL_DEFAULT}"
20
+ )
21
+ option(
22
+ FERMISIMPLEX_BUILD_TESTING
23
+ "Build the FermiSimplex C++ tests"
24
+ "${FERMISIMPLEX_TOP_LEVEL_DEFAULT}"
25
+ )
26
+
27
+ add_subdirectory(cpp)
28
+
29
+ if(FERMISIMPLEX_BUILD_PYTHON)
30
+ add_subdirectory(python)
31
+ endif()
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Kostas Vilkelis
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its contributors
16
+ may be used to endorse or promote products derived from this software without
17
+ specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,217 @@
1
+ Metadata-Version: 2.4
2
+ Name: FermiSimplex
3
+ Version: 0.1.0
4
+ Summary: Adaptive spectral calculations with simplex occupation certification
5
+ Keywords: adaptive mesh,electronic structure,Fermi surface,scientific computing
6
+ Author: Kostas Vilkelis
7
+ License-Expression: BSD-3-Clause
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Operating System :: MacOS
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: C++
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Physics
20
+ Project-URL: Repository, https://gitlab.kwant-project.org/qt/lineartetrahedron
21
+ Project-URL: Mirror, https://github.com/Kostusas/FermiSimplex
22
+ Project-URL: Documentation, https://github.com/Kostusas/FermiSimplex/blob/main/docs/showcase.md
23
+ Project-URL: Changelog, https://github.com/Kostusas/FermiSimplex/blob/main/CHANGELOG.md
24
+ Requires-Python: <3.14,>=3.11
25
+ Requires-Dist: numpy>=2.0
26
+ Provides-Extra: examples
27
+ Requires-Dist: matplotlib>=3.8; extra == "examples"
28
+ Description-Content-Type: text/markdown
29
+
30
+ # FermiSimplex
31
+
32
+ **Adaptive, occupation-certified spectral calculations on simplex meshes.**
33
+
34
+ FermiSimplex finds Fermi surfaces and computes zero-temperature charge and
35
+ density matrices without paying for a dense momentum grid. Its central object
36
+ is the local occupation
37
+
38
+ $$
39
+ N(k; \mu) = \mathrm{Tr}\left[\Theta\left(\mu I - H(k)\right)\right],
40
+ $$
41
+
42
+ and its central question is simple: *can the occupation be proved constant on
43
+ this simplex, or should we look more closely?*
44
+
45
+ The upstream development repository is
46
+ [GitLab](https://gitlab.kwant-project.org/qt/lineartetrahedron); the
47
+ [GitHub repository](https://github.com/Kostusas/FermiSimplex) is a public
48
+ mirror.
49
+
50
+ ![Adaptive Fermi-surface refinement](https://raw.githubusercontent.com/Kostusas/FermiSimplex/main/docs/assets/fermi_surface_refinement.gif)
51
+
52
+ See the [visual Python tour][visual-tour] for a presentation-ready
53
+ introduction with real adaptive sampling traces, multiband examples, and a
54
+ rotating noble-metal-inspired three-dimensional surface.
55
+
56
+ - 🛡️ **Gapped-region proofs** combine cached eigensystems with rigorous spectral
57
+ bounds to exclude a Fermi-level crossing throughout a simplex and to bound
58
+ the remaining charge.
59
+ - ⚡ **Adaptive sampling**, built on
60
+ [AdaptiveSimplex](https://gitlab.kwant-project.org/qt/adaptivesimplex),
61
+ concentrates diagonalizations near unresolved Fermi surfaces instead of
62
+ refining the entire Brillouin zone uniformly.
63
+ - 🚀 **Numerical efficiency by design:** adaptive refinement, shared spectral
64
+ caching, and the compiled numerical core avoid repeated work as the Fermi
65
+ surface becomes progressively sharper.
66
+ - 🎯 **Projected charge estimates** compare sampled projected eigenvalues with
67
+ vertex-linear interpolation only in the bands whose occupation is still
68
+ ambiguous.
69
+ - 🧩 **Python and C++** share one numerical core; models can be dense callables
70
+ or translation-invariant tight-binding Hamiltonians.
71
+
72
+ ## Quick start
73
+
74
+ From a source checkout with a C++20 compiler and BLAS/LAPACK available:
75
+
76
+ ```bash
77
+ pip install .
78
+ ```
79
+
80
+ The model below produces the three-dimensional surface shown above:
81
+
82
+ ```python
83
+ import numpy as np
84
+
85
+ from fermisimplex import SpectralMesh
86
+
87
+
88
+ def hamiltonian(kx, ky, kz):
89
+ phase = 2 * np.pi * np.array([kx, ky, kz])
90
+ return np.array([[np.cos(phase).sum()]], dtype=complex)
91
+
92
+
93
+ mesh = SpectralMesh(hamiltonian)
94
+ surface = mesh.fermi_surface(
95
+ mu=0.17,
96
+ min_feature_size=0.07,
97
+ curvature_bound=(2 * np.pi) ** 2,
98
+ )
99
+
100
+ surface.points # (npoints, 3)
101
+ surface.cells # (ntriangles, 3)
102
+ surface.cell_bands # band index for every triangle
103
+ ```
104
+
105
+ The coordinates are reduced coordinates in $[0,1]^d$. Here
106
+ $M=(2\pi)^2$ bounds every directional second derivative of the scalar
107
+ Hamiltonian. `SpectralMesh` infers the momentum-space dimension from the
108
+ callable arguments and the matrix dimension by evaluating it at the origin.
109
+ Callables receive separate coordinates: `hamiltonian(kx, ky, ...)`.
110
+
111
+ ![Two- and three-dimensional Fermi surfaces](https://raw.githubusercontent.com/Kostusas/FermiSimplex/main/docs/assets/fermi_surface_gallery.png)
112
+
113
+ The same `SpectralMesh` can drive the other observables and reuse every
114
+ eigensystem it has already computed:
115
+
116
+ ```python
117
+ charge = mesh.integrate_charge(
118
+ mu=0.17,
119
+ target_error=1e-2,
120
+ max_refinements=10_000,
121
+ curvature_bound=(2 * np.pi) ** 2,
122
+ )
123
+ density = mesh.integrate_density_matrix(
124
+ mu=0.17,
125
+ lattice_vectors=[(0, 0, 0), (1, 0, 0)],
126
+ target_error=1e-2,
127
+ max_refinements=10_000,
128
+ )
129
+
130
+ charge.value
131
+ charge.stopping_error
132
+ charge.certified_error_bound
133
+ density.matrices # (number of lattice vectors, ndof, ndof)
134
+ ```
135
+
136
+ For a tight-binding model,
137
+
138
+ $$
139
+ H(k)=\sum_R H_R e^{-2\pi i k\cdot R},
140
+ $$
141
+
142
+ pass `{R: H_R, ...}` directly to `SpectralMesh`. Opposite hoppings are checked
143
+ for $H_{-R}=H_R^\dagger$.
144
+
145
+ ## What does the certificate prove?
146
+
147
+ At each simplex, FermiSimplex asks: **can the occupation change between the
148
+ sampled vertices?** It combines their eigensystems with `curvature_bound`,
149
+ which limits how much the Hamiltonian can bend in between. If occupied and
150
+ unoccupied trial subspaces remain on opposite sides of $\mu$, the occupation
151
+ is fixed everywhere—without sampling the interior.
152
+
153
+ - **Certified:** no Fermi surface crosses the simplex.
154
+ - **Partially certified:** rigorous lower and upper occupation bounds remain.
155
+ - **Inconclusive:** this is not a gapless verdict; FermiSimplex refines and
156
+ tries again.
157
+
158
+ Every charge and Fermi-surface simplex is checked. The remaining uncertainty
159
+ becomes `charge.certified_error_bound`; `surface.coverage_certified` concerns
160
+ classification down to `min_feature_size`, not topology or geometric accuracy.
161
+ Density matrices currently use adaptive estimates instead.
162
+
163
+ The guarantee assumes a valid `curvature_bound`. Omitting it, `None`, and
164
+ `0.0` all assert zero curvature; none disables certification. See the
165
+ [mathematics guide][mathematics] for the proof and error bounds.
166
+
167
+ ## API at a glance
168
+
169
+ - `SpectralMesh`: accept a callable or tight-binding dictionary and own the
170
+ adaptive geometry and cached eigensystems.
171
+ - `certify_simplex`: certify supplied vertex eigenpairs directly; eigenvalues
172
+ must be finite and ascending, and eigenvector columns must be finite and
173
+ orthonormal. These performance-sensitive numerical preconditions are not
174
+ rechecked.
175
+ - `mesh.integrate_charge`: adaptive filling and $dQ/d\mu$.
176
+ - `mesh.integrate_density_matrix`: real-space density-matrix components.
177
+ - `mesh.fermi_surface`: band-labelled points and cells in reduced coordinates.
178
+
179
+ Adaptive controls such as `target_error`, `max_refinements`, and
180
+ `preview_depth` are ordinary keyword arguments on the calculation that uses
181
+ them—there is no separate options object. Charge calculations default to
182
+ `preview_depth=0` because their sampled projected-error estimate drives
183
+ refinement intrinsically; positive depths are intended for explicit
184
+ diagnostic comparisons.
185
+
186
+ See the [visual Python tour][visual-tour], runnable
187
+ [quick start][quick-start], and
188
+ [two-band plotting example][fermi-example], the
189
+ [visual-generation notes][visuals], and the
190
+ [build and architecture guide][development].
191
+
192
+ ## Development
193
+
194
+ AdaptiveSimplex provides the mesh geometry, refinement, vertex caching, and
195
+ cut-simplex integration; FermiSimplex adds the spectral models, certificates,
196
+ and observable-specific algorithms.
197
+
198
+ ```bash
199
+ pixi run test
200
+ ```
201
+
202
+ This builds the standalone C++ library, verifies an installed downstream CMake
203
+ consumer, rebuilds the Python extension, and runs the Python tests. The dense
204
+ 60-band stress case lives in [benchmarks/fermi_surface_60.py][stress-benchmark].
205
+
206
+ FermiSimplex is licensed under the BSD 3-Clause license. If you use it in
207
+ research, please cite the metadata in [CITATION.cff][citation].
208
+
209
+
210
+ [visual-tour]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/showcase.md
211
+ [mathematics]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/mathematics.md
212
+ [quick-start]: https://github.com/Kostusas/FermiSimplex/blob/main/examples/quick_start.py
213
+ [fermi-example]: https://github.com/Kostusas/FermiSimplex/blob/main/examples/fermi_surface.py
214
+ [visuals]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/visuals.md
215
+ [development]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/development.md
216
+ [stress-benchmark]: https://github.com/Kostusas/FermiSimplex/blob/main/benchmarks/fermi_surface_60.py
217
+ [citation]: https://github.com/Kostusas/FermiSimplex/blob/main/CITATION.cff
@@ -0,0 +1,188 @@
1
+ # FermiSimplex
2
+
3
+ **Adaptive, occupation-certified spectral calculations on simplex meshes.**
4
+
5
+ FermiSimplex finds Fermi surfaces and computes zero-temperature charge and
6
+ density matrices without paying for a dense momentum grid. Its central object
7
+ is the local occupation
8
+
9
+ $$
10
+ N(k; \mu) = \mathrm{Tr}\left[\Theta\left(\mu I - H(k)\right)\right],
11
+ $$
12
+
13
+ and its central question is simple: *can the occupation be proved constant on
14
+ this simplex, or should we look more closely?*
15
+
16
+ The upstream development repository is
17
+ [GitLab](https://gitlab.kwant-project.org/qt/lineartetrahedron); the
18
+ [GitHub repository](https://github.com/Kostusas/FermiSimplex) is a public
19
+ mirror.
20
+
21
+ ![Adaptive Fermi-surface refinement](https://raw.githubusercontent.com/Kostusas/FermiSimplex/main/docs/assets/fermi_surface_refinement.gif)
22
+
23
+ See the [visual Python tour][visual-tour] for a presentation-ready
24
+ introduction with real adaptive sampling traces, multiband examples, and a
25
+ rotating noble-metal-inspired three-dimensional surface.
26
+
27
+ - 🛡️ **Gapped-region proofs** combine cached eigensystems with rigorous spectral
28
+ bounds to exclude a Fermi-level crossing throughout a simplex and to bound
29
+ the remaining charge.
30
+ - ⚡ **Adaptive sampling**, built on
31
+ [AdaptiveSimplex](https://gitlab.kwant-project.org/qt/adaptivesimplex),
32
+ concentrates diagonalizations near unresolved Fermi surfaces instead of
33
+ refining the entire Brillouin zone uniformly.
34
+ - 🚀 **Numerical efficiency by design:** adaptive refinement, shared spectral
35
+ caching, and the compiled numerical core avoid repeated work as the Fermi
36
+ surface becomes progressively sharper.
37
+ - 🎯 **Projected charge estimates** compare sampled projected eigenvalues with
38
+ vertex-linear interpolation only in the bands whose occupation is still
39
+ ambiguous.
40
+ - 🧩 **Python and C++** share one numerical core; models can be dense callables
41
+ or translation-invariant tight-binding Hamiltonians.
42
+
43
+ ## Quick start
44
+
45
+ From a source checkout with a C++20 compiler and BLAS/LAPACK available:
46
+
47
+ ```bash
48
+ pip install .
49
+ ```
50
+
51
+ The model below produces the three-dimensional surface shown above:
52
+
53
+ ```python
54
+ import numpy as np
55
+
56
+ from fermisimplex import SpectralMesh
57
+
58
+
59
+ def hamiltonian(kx, ky, kz):
60
+ phase = 2 * np.pi * np.array([kx, ky, kz])
61
+ return np.array([[np.cos(phase).sum()]], dtype=complex)
62
+
63
+
64
+ mesh = SpectralMesh(hamiltonian)
65
+ surface = mesh.fermi_surface(
66
+ mu=0.17,
67
+ min_feature_size=0.07,
68
+ curvature_bound=(2 * np.pi) ** 2,
69
+ )
70
+
71
+ surface.points # (npoints, 3)
72
+ surface.cells # (ntriangles, 3)
73
+ surface.cell_bands # band index for every triangle
74
+ ```
75
+
76
+ The coordinates are reduced coordinates in $[0,1]^d$. Here
77
+ $M=(2\pi)^2$ bounds every directional second derivative of the scalar
78
+ Hamiltonian. `SpectralMesh` infers the momentum-space dimension from the
79
+ callable arguments and the matrix dimension by evaluating it at the origin.
80
+ Callables receive separate coordinates: `hamiltonian(kx, ky, ...)`.
81
+
82
+ ![Two- and three-dimensional Fermi surfaces](https://raw.githubusercontent.com/Kostusas/FermiSimplex/main/docs/assets/fermi_surface_gallery.png)
83
+
84
+ The same `SpectralMesh` can drive the other observables and reuse every
85
+ eigensystem it has already computed:
86
+
87
+ ```python
88
+ charge = mesh.integrate_charge(
89
+ mu=0.17,
90
+ target_error=1e-2,
91
+ max_refinements=10_000,
92
+ curvature_bound=(2 * np.pi) ** 2,
93
+ )
94
+ density = mesh.integrate_density_matrix(
95
+ mu=0.17,
96
+ lattice_vectors=[(0, 0, 0), (1, 0, 0)],
97
+ target_error=1e-2,
98
+ max_refinements=10_000,
99
+ )
100
+
101
+ charge.value
102
+ charge.stopping_error
103
+ charge.certified_error_bound
104
+ density.matrices # (number of lattice vectors, ndof, ndof)
105
+ ```
106
+
107
+ For a tight-binding model,
108
+
109
+ $$
110
+ H(k)=\sum_R H_R e^{-2\pi i k\cdot R},
111
+ $$
112
+
113
+ pass `{R: H_R, ...}` directly to `SpectralMesh`. Opposite hoppings are checked
114
+ for $H_{-R}=H_R^\dagger$.
115
+
116
+ ## What does the certificate prove?
117
+
118
+ At each simplex, FermiSimplex asks: **can the occupation change between the
119
+ sampled vertices?** It combines their eigensystems with `curvature_bound`,
120
+ which limits how much the Hamiltonian can bend in between. If occupied and
121
+ unoccupied trial subspaces remain on opposite sides of $\mu$, the occupation
122
+ is fixed everywhere—without sampling the interior.
123
+
124
+ - **Certified:** no Fermi surface crosses the simplex.
125
+ - **Partially certified:** rigorous lower and upper occupation bounds remain.
126
+ - **Inconclusive:** this is not a gapless verdict; FermiSimplex refines and
127
+ tries again.
128
+
129
+ Every charge and Fermi-surface simplex is checked. The remaining uncertainty
130
+ becomes `charge.certified_error_bound`; `surface.coverage_certified` concerns
131
+ classification down to `min_feature_size`, not topology or geometric accuracy.
132
+ Density matrices currently use adaptive estimates instead.
133
+
134
+ The guarantee assumes a valid `curvature_bound`. Omitting it, `None`, and
135
+ `0.0` all assert zero curvature; none disables certification. See the
136
+ [mathematics guide][mathematics] for the proof and error bounds.
137
+
138
+ ## API at a glance
139
+
140
+ - `SpectralMesh`: accept a callable or tight-binding dictionary and own the
141
+ adaptive geometry and cached eigensystems.
142
+ - `certify_simplex`: certify supplied vertex eigenpairs directly; eigenvalues
143
+ must be finite and ascending, and eigenvector columns must be finite and
144
+ orthonormal. These performance-sensitive numerical preconditions are not
145
+ rechecked.
146
+ - `mesh.integrate_charge`: adaptive filling and $dQ/d\mu$.
147
+ - `mesh.integrate_density_matrix`: real-space density-matrix components.
148
+ - `mesh.fermi_surface`: band-labelled points and cells in reduced coordinates.
149
+
150
+ Adaptive controls such as `target_error`, `max_refinements`, and
151
+ `preview_depth` are ordinary keyword arguments on the calculation that uses
152
+ them—there is no separate options object. Charge calculations default to
153
+ `preview_depth=0` because their sampled projected-error estimate drives
154
+ refinement intrinsically; positive depths are intended for explicit
155
+ diagnostic comparisons.
156
+
157
+ See the [visual Python tour][visual-tour], runnable
158
+ [quick start][quick-start], and
159
+ [two-band plotting example][fermi-example], the
160
+ [visual-generation notes][visuals], and the
161
+ [build and architecture guide][development].
162
+
163
+ ## Development
164
+
165
+ AdaptiveSimplex provides the mesh geometry, refinement, vertex caching, and
166
+ cut-simplex integration; FermiSimplex adds the spectral models, certificates,
167
+ and observable-specific algorithms.
168
+
169
+ ```bash
170
+ pixi run test
171
+ ```
172
+
173
+ This builds the standalone C++ library, verifies an installed downstream CMake
174
+ consumer, rebuilds the Python extension, and runs the Python tests. The dense
175
+ 60-band stress case lives in [benchmarks/fermi_surface_60.py][stress-benchmark].
176
+
177
+ FermiSimplex is licensed under the BSD 3-Clause license. If you use it in
178
+ research, please cite the metadata in [CITATION.cff][citation].
179
+
180
+
181
+ [visual-tour]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/showcase.md
182
+ [mathematics]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/mathematics.md
183
+ [quick-start]: https://github.com/Kostusas/FermiSimplex/blob/main/examples/quick_start.py
184
+ [fermi-example]: https://github.com/Kostusas/FermiSimplex/blob/main/examples/fermi_surface.py
185
+ [visuals]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/visuals.md
186
+ [development]: https://github.com/Kostusas/FermiSimplex/blob/main/docs/development.md
187
+ [stress-benchmark]: https://github.com/Kostusas/FermiSimplex/blob/main/benchmarks/fermi_surface_60.py
188
+ [citation]: https://github.com/Kostusas/FermiSimplex/blob/main/CITATION.cff
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from importlib.metadata import version
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+
9
+ import fermisimplex
10
+ from fermisimplex import SpectralMesh
11
+
12
+
13
+ def test_installed_distribution_runs_a_native_surface_calculation():
14
+ def hamiltonian(kx, ky):
15
+ coordinate_sum = kx + ky
16
+ return np.diag(
17
+ [coordinate_sum - 1.5, coordinate_sum - 0.5]
18
+ ).astype(complex)
19
+
20
+ surface = SpectralMesh(hamiltonian).fermi_surface(
21
+ mu=0.0,
22
+ min_feature_size=0.2,
23
+ curvature_bound=0.0,
24
+ )
25
+
26
+ assert version("FermiSimplex")
27
+ assert surface.completed
28
+ assert surface.coverage_certified
29
+ assert set(surface.cell_bands.tolist()) == {0, 1}
30
+
31
+
32
+ def test_bundled_openblas_notice_matches_platform_backend():
33
+ package_dir = Path(fermisimplex.__file__).resolve().parent
34
+ notice = package_dir / "licenses" / "scipy-openblas32.txt"
35
+
36
+ if sys.platform == "darwin":
37
+ assert not notice.exists()
38
+ return
39
+
40
+ assert notice.is_file()
41
+ assert "OpenBLAS" in notice.read_text()