AtomVoxelizer 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 (35) hide show
  1. atomvoxelizer-0.1.0/.readthedocs.yaml +17 -0
  2. atomvoxelizer-0.1.0/MANIFEST.in +8 -0
  3. atomvoxelizer-0.1.0/PKG-INFO +174 -0
  4. atomvoxelizer-0.1.0/README.md +121 -0
  5. atomvoxelizer-0.1.0/benchmarks/benchmark_backends.py +149 -0
  6. atomvoxelizer-0.1.0/benchmarks/benchmark_structures.py +41 -0
  7. atomvoxelizer-0.1.0/docs/source/analysis.rst +113 -0
  8. atomvoxelizer-0.1.0/docs/source/api.rst +17 -0
  9. atomvoxelizer-0.1.0/docs/source/backends.rst +64 -0
  10. atomvoxelizer-0.1.0/docs/source/conf.py +24 -0
  11. atomvoxelizer-0.1.0/docs/source/index.rst +14 -0
  12. atomvoxelizer-0.1.0/docs/source/publishing.rst +53 -0
  13. atomvoxelizer-0.1.0/docs/source/usage.rst +43 -0
  14. atomvoxelizer-0.1.0/examples/BEA.cif +68 -0
  15. atomvoxelizer-0.1.0/examples/MWW.cif +79 -0
  16. atomvoxelizer-0.1.0/examples/zeolite_analysis.py +116 -0
  17. atomvoxelizer-0.1.0/examples/zeolite_voxel.py +230 -0
  18. atomvoxelizer-0.1.0/pyproject.toml +81 -0
  19. atomvoxelizer-0.1.0/setup.cfg +4 -0
  20. atomvoxelizer-0.1.0/src/AtomVoxelizer.egg-info/PKG-INFO +174 -0
  21. atomvoxelizer-0.1.0/src/AtomVoxelizer.egg-info/SOURCES.txt +33 -0
  22. atomvoxelizer-0.1.0/src/AtomVoxelizer.egg-info/dependency_links.txt +1 -0
  23. atomvoxelizer-0.1.0/src/AtomVoxelizer.egg-info/requires.txt +40 -0
  24. atomvoxelizer-0.1.0/src/AtomVoxelizer.egg-info/top_level.txt +1 -0
  25. atomvoxelizer-0.1.0/src/atomvoxelizer/__init__.py +30 -0
  26. atomvoxelizer-0.1.0/src/atomvoxelizer/analysis.py +207 -0
  27. atomvoxelizer-0.1.0/src/atomvoxelizer/cupy_backend.py +88 -0
  28. atomvoxelizer-0.1.0/src/atomvoxelizer/numba_backend.py +135 -0
  29. atomvoxelizer-0.1.0/src/atomvoxelizer/taichi_backend.py +157 -0
  30. atomvoxelizer-0.1.0/src/atomvoxelizer/voxelgrid.py +308 -0
  31. atomvoxelizer-0.1.0/tests/test_analysis.py +74 -0
  32. atomvoxelizer-0.1.0/tests/test_backends.py +60 -0
  33. atomvoxelizer-0.1.0/tests/test_imports.py +13 -0
  34. atomvoxelizer-0.1.0/tests/test_voxelgrid_numpy.py +96 -0
  35. atomvoxelizer-0.1.0/tests/test_zeolite_analysis_example.py +39 -0
@@ -0,0 +1,17 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-24.04
5
+ tools:
6
+ python: "3.12"
7
+
8
+ sphinx:
9
+ configuration: docs/source/conf.py
10
+
11
+ python:
12
+ install:
13
+ - method: pip
14
+ path: .
15
+ extra_requirements:
16
+ - docs
17
+
@@ -0,0 +1,8 @@
1
+ include .readthedocs.yaml
2
+ include README.md
3
+ include pyproject.toml
4
+ recursive-include benchmarks *.py
5
+ recursive-include docs/source *.py *.rst
6
+ recursive-include examples *.py *.cif
7
+ recursive-include tests *.py
8
+
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: AtomVoxelizer
3
+ Version: 0.1.0
4
+ Summary: Periodic atom-centered voxel grids for atomistic structures.
5
+ Author: AtomVoxelizer contributors
6
+ Project-URL: Homepage, https://gitlab.com/tgmaxson/atomvoxelizer
7
+ Project-URL: Documentation, https://atomvoxelizer.readthedocs.io/
8
+ Project-URL: Repository, https://gitlab.com/tgmaxson/atomvoxelizer
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
19
+ Classifier: Topic :: Scientific/Engineering :: Physics
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: matplotlib
23
+ Requires-Dist: numpy
24
+ Provides-Extra: numba
25
+ Requires-Dist: numba; extra == "numba"
26
+ Provides-Extra: cupy
27
+ Requires-Dist: cupy; extra == "cupy"
28
+ Requires-Dist: numba; extra == "cupy"
29
+ Provides-Extra: taichi
30
+ Requires-Dist: taichi; extra == "taichi"
31
+ Provides-Extra: analysis
32
+ Requires-Dist: scikit-image; extra == "analysis"
33
+ Provides-Extra: examples
34
+ Requires-Dist: ase; extra == "examples"
35
+ Requires-Dist: requests; extra == "examples"
36
+ Provides-Extra: docs
37
+ Requires-Dist: sphinx; extra == "docs"
38
+ Provides-Extra: dev
39
+ Requires-Dist: ase; extra == "dev"
40
+ Requires-Dist: numba; extra == "dev"
41
+ Requires-Dist: pytest; extra == "dev"
42
+ Requires-Dist: requests; extra == "dev"
43
+ Requires-Dist: scikit-image; extra == "dev"
44
+ Requires-Dist: sphinx; extra == "dev"
45
+ Requires-Dist: taichi; extra == "dev"
46
+ Provides-Extra: bench
47
+ Requires-Dist: ase; extra == "bench"
48
+ Requires-Dist: numba; extra == "bench"
49
+ Requires-Dist: taichi; extra == "bench"
50
+ Provides-Extra: publish
51
+ Requires-Dist: build; extra == "publish"
52
+ Requires-Dist: twine; extra == "publish"
53
+
54
+ # AtomVoxelizer
55
+
56
+ AtomVoxelizer builds periodic atom-centered voxel grids for atomistic structures.
57
+ The core `VoxelGrid` class stores a 3D NumPy grid over a periodic cell and provides
58
+ helpers for adding, setting, scaling, sampling, and plotting spherical regions.
59
+
60
+ ## Installation
61
+
62
+ Install from this repository:
63
+
64
+ ```bash
65
+ pip install .
66
+ ```
67
+
68
+ Install optional acceleration backends with extras:
69
+
70
+ ```bash
71
+ pip install ".[numba]"
72
+ pip install ".[taichi]"
73
+ pip install ".[cupy]"
74
+ pip install ".[analysis]"
75
+ ```
76
+
77
+ `VoxelGrid` is always the NumPy backend. Optional acceleration backends are
78
+ explicit: `VoxelGridNumba`, `VoxelGridTaichi`, and `VoxelGridCuPy`.
79
+ `VoxelGridAnalysis` provides connected-volume and marching-cubes surface-area
80
+ analysis when the `analysis` extra is installed.
81
+
82
+ For development, examples, tests, and documentation:
83
+
84
+ ```bash
85
+ pip install -e ".[dev,examples]"
86
+ ```
87
+
88
+ ## Basic Usage
89
+
90
+ ```python
91
+ import numpy as np
92
+
93
+ from atomvoxelizer import VoxelGrid
94
+
95
+ cell = np.eye(3) * 10.0
96
+ grid = VoxelGrid(cell=cell, resolution=0.25)
97
+
98
+ grid.add_sphere(center=np.array([5.0, 5.0, 5.0]), radius=1.0, value=1.0)
99
+ grid.set_sphere(center=np.array([2.0, 2.0, 2.0]), radius=0.5, value=-1.0)
100
+ grid.clamp_grid(min_val=-1.0, max_val=1.0)
101
+ ```
102
+
103
+ ## Zeolite Example
104
+
105
+ The zeolite example and CIF files live in `examples/`.
106
+
107
+ ```bash
108
+ pip install -e ".[examples]"
109
+ python examples/zeolite_voxel.py BEA
110
+ ```
111
+
112
+ The script reads a framework CIF, builds voxel grids at several resolutions, plots
113
+ middle XZ slices, benchmarks supercell scaling, and opens a 3D scatter plot.
114
+
115
+ The analysis example estimates pore volume and internal surface area:
116
+
117
+ ```bash
118
+ pip install -e ".[examples,analysis]"
119
+ python examples/zeolite_analysis.py BEA --resolution 0.25
120
+ python examples/zeolite_analysis.py BEA --convergence 1.0 0.75 0.5 --plot bea_convergence.png
121
+ ```
122
+
123
+ ## Tests and Benchmarks
124
+
125
+ Run the correctness tests with:
126
+
127
+ ```bash
128
+ pytest
129
+ ```
130
+
131
+ Run the backend benchmark with:
132
+
133
+ ```bash
134
+ python benchmarks/benchmark_backends.py --backends numpy numba taichi cupy
135
+ ```
136
+
137
+ Run the built-in structure benchmarks for a zeolite and a roughly 1000 atom Wulff
138
+ construction with:
139
+
140
+ ```bash
141
+ python benchmarks/benchmark_structures.py
142
+ ```
143
+
144
+ Backends whose optional dependencies are not installed are reported as missing.
145
+
146
+ ## Documentation
147
+
148
+ Documentation is scaffolded with Sphinx for Read the Docs.
149
+
150
+ Build it locally with:
151
+
152
+ ```bash
153
+ pip install -e ".[docs]"
154
+ sphinx-build -b html docs/source docs/build/html
155
+ ```
156
+
157
+ Read the Docs can use `.readthedocs.yaml` directly.
158
+
159
+ ## Publishing
160
+
161
+ Build and check PyPI artifacts with:
162
+
163
+ ```bash
164
+ pip install -e ".[publish]"
165
+ python -m build
166
+ twine check dist/*
167
+ ```
168
+
169
+ Upload to TestPyPI first, then PyPI:
170
+
171
+ ```bash
172
+ twine upload --repository testpypi dist/*
173
+ twine upload dist/*
174
+ ```
@@ -0,0 +1,121 @@
1
+ # AtomVoxelizer
2
+
3
+ AtomVoxelizer builds periodic atom-centered voxel grids for atomistic structures.
4
+ The core `VoxelGrid` class stores a 3D NumPy grid over a periodic cell and provides
5
+ helpers for adding, setting, scaling, sampling, and plotting spherical regions.
6
+
7
+ ## Installation
8
+
9
+ Install from this repository:
10
+
11
+ ```bash
12
+ pip install .
13
+ ```
14
+
15
+ Install optional acceleration backends with extras:
16
+
17
+ ```bash
18
+ pip install ".[numba]"
19
+ pip install ".[taichi]"
20
+ pip install ".[cupy]"
21
+ pip install ".[analysis]"
22
+ ```
23
+
24
+ `VoxelGrid` is always the NumPy backend. Optional acceleration backends are
25
+ explicit: `VoxelGridNumba`, `VoxelGridTaichi`, and `VoxelGridCuPy`.
26
+ `VoxelGridAnalysis` provides connected-volume and marching-cubes surface-area
27
+ analysis when the `analysis` extra is installed.
28
+
29
+ For development, examples, tests, and documentation:
30
+
31
+ ```bash
32
+ pip install -e ".[dev,examples]"
33
+ ```
34
+
35
+ ## Basic Usage
36
+
37
+ ```python
38
+ import numpy as np
39
+
40
+ from atomvoxelizer import VoxelGrid
41
+
42
+ cell = np.eye(3) * 10.0
43
+ grid = VoxelGrid(cell=cell, resolution=0.25)
44
+
45
+ grid.add_sphere(center=np.array([5.0, 5.0, 5.0]), radius=1.0, value=1.0)
46
+ grid.set_sphere(center=np.array([2.0, 2.0, 2.0]), radius=0.5, value=-1.0)
47
+ grid.clamp_grid(min_val=-1.0, max_val=1.0)
48
+ ```
49
+
50
+ ## Zeolite Example
51
+
52
+ The zeolite example and CIF files live in `examples/`.
53
+
54
+ ```bash
55
+ pip install -e ".[examples]"
56
+ python examples/zeolite_voxel.py BEA
57
+ ```
58
+
59
+ The script reads a framework CIF, builds voxel grids at several resolutions, plots
60
+ middle XZ slices, benchmarks supercell scaling, and opens a 3D scatter plot.
61
+
62
+ The analysis example estimates pore volume and internal surface area:
63
+
64
+ ```bash
65
+ pip install -e ".[examples,analysis]"
66
+ python examples/zeolite_analysis.py BEA --resolution 0.25
67
+ python examples/zeolite_analysis.py BEA --convergence 1.0 0.75 0.5 --plot bea_convergence.png
68
+ ```
69
+
70
+ ## Tests and Benchmarks
71
+
72
+ Run the correctness tests with:
73
+
74
+ ```bash
75
+ pytest
76
+ ```
77
+
78
+ Run the backend benchmark with:
79
+
80
+ ```bash
81
+ python benchmarks/benchmark_backends.py --backends numpy numba taichi cupy
82
+ ```
83
+
84
+ Run the built-in structure benchmarks for a zeolite and a roughly 1000 atom Wulff
85
+ construction with:
86
+
87
+ ```bash
88
+ python benchmarks/benchmark_structures.py
89
+ ```
90
+
91
+ Backends whose optional dependencies are not installed are reported as missing.
92
+
93
+ ## Documentation
94
+
95
+ Documentation is scaffolded with Sphinx for Read the Docs.
96
+
97
+ Build it locally with:
98
+
99
+ ```bash
100
+ pip install -e ".[docs]"
101
+ sphinx-build -b html docs/source docs/build/html
102
+ ```
103
+
104
+ Read the Docs can use `.readthedocs.yaml` directly.
105
+
106
+ ## Publishing
107
+
108
+ Build and check PyPI artifacts with:
109
+
110
+ ```bash
111
+ pip install -e ".[publish]"
112
+ python -m build
113
+ twine check dist/*
114
+ ```
115
+
116
+ Upload to TestPyPI first, then PyPI:
117
+
118
+ ```bash
119
+ twine upload --repository testpypi dist/*
120
+ twine upload dist/*
121
+ ```
@@ -0,0 +1,149 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import importlib
5
+ import time
6
+ from pathlib import Path
7
+
8
+ import numpy as np
9
+ from ase.cluster import wulff_construction
10
+ from ase.data import covalent_radii
11
+ from ase.io import read
12
+
13
+ from atomvoxelizer import VoxelGrid
14
+
15
+
16
+ ROOT = Path(__file__).resolve().parents[1]
17
+
18
+
19
+ def load_backend(name):
20
+ if name == "numpy":
21
+ return VoxelGrid
22
+ if name == "numba":
23
+ module = importlib.import_module("atomvoxelizer.numba_backend")
24
+ return module.VoxelGridNumba
25
+ if name == "taichi":
26
+ module = importlib.import_module("atomvoxelizer.taichi_backend")
27
+ return module.VoxelGridTaichi
28
+ if name == "cupy":
29
+ module = importlib.import_module("atomvoxelizer.cupy_backend")
30
+ return module.VoxelGridCuPy
31
+ raise ValueError(f"Unknown backend: {name}")
32
+
33
+
34
+ def make_synthetic_workload(cell_length, atom_count, seed):
35
+ rng = np.random.default_rng(seed)
36
+ centers = rng.random((atom_count, 3)) * cell_length
37
+ radii = rng.choice(np.array([0.55, 0.75, 1.0], dtype=np.float64), size=atom_count)
38
+ return np.eye(3) * cell_length, centers, radii
39
+
40
+
41
+ def make_zeolite_workload(framework, radius_scale):
42
+ atoms = read(ROOT / "examples" / f"{framework.upper()}.cif")
43
+ centers = atoms.get_positions()
44
+ radii = np.array([covalent_radii[atom.number] * radius_scale for atom in atoms], dtype=np.float64)
45
+ return atoms.cell.array, centers, radii
46
+
47
+
48
+ def make_wulff_workload(size, radius_scale, padding):
49
+ atoms = wulff_construction(
50
+ "Pt",
51
+ surfaces=[(1, 0, 0), (1, 1, 0), (1, 1, 1)],
52
+ energies=[1.0, 1.08, 0.92],
53
+ size=size,
54
+ structure="fcc",
55
+ latticeconstant=3.92,
56
+ rounding="closest",
57
+ )
58
+ positions = atoms.get_positions()
59
+ positions -= positions.min(axis=0)
60
+ positions += padding
61
+ lengths = positions.max(axis=0) + padding
62
+ radii = np.array([covalent_radii[atom.number] * radius_scale for atom in atoms], dtype=np.float64)
63
+ return np.diag(lengths), positions, radii
64
+
65
+
66
+ def make_workload(args):
67
+ if args.workload == "synthetic":
68
+ return make_synthetic_workload(args.cell_length, args.atoms, args.seed)
69
+ if args.workload == "zeolite":
70
+ return make_zeolite_workload(args.framework, args.radius_scale)
71
+ if args.workload == "wulff":
72
+ return make_wulff_workload(args.wulff_size, args.radius_scale, args.padding)
73
+ raise ValueError(f"Unknown workload: {args.workload}")
74
+
75
+
76
+ def run_once(cls, cell, resolution, centers, radii):
77
+ grid = cls(cell=cell, resolution=resolution)
78
+ grid.add_spheres(centers, radii, value=1.0)
79
+ grid.set_spheres(centers, radii * 0.5, value=-1.0)
80
+ grid.clamp_grid(-1.0, 1.0)
81
+ synchronize = getattr(grid, "synchronize", None)
82
+ if synchronize is not None:
83
+ synchronize()
84
+ return grid
85
+
86
+
87
+ def time_backend(cls, cell, resolution, centers, radii, repeats):
88
+ run_once(cls, cell, resolution, centers[: min(2, len(centers))], radii[: min(2, len(radii))])
89
+ times = []
90
+ grid = None
91
+ for _ in range(repeats):
92
+ start = time.perf_counter()
93
+ grid = run_once(cls, cell, resolution, centers, radii)
94
+ times.append(time.perf_counter() - start)
95
+ return np.array(times), grid
96
+
97
+
98
+ def consistency_summary(values, reference):
99
+ occupied = int(np.count_nonzero(values))
100
+ total = float(values.sum())
101
+ if reference is None:
102
+ return occupied, total, 0.0
103
+ return occupied, total, float(np.max(np.abs(values - reference)))
104
+
105
+
106
+ def main():
107
+ parser = argparse.ArgumentParser(description="Benchmark AtomVoxelizer backends.")
108
+ parser.add_argument("--backends", nargs="+", default=["numpy", "numba", "taichi", "cupy"])
109
+ parser.add_argument("--workload", choices=["synthetic", "zeolite", "wulff"], default="zeolite")
110
+ parser.add_argument("--resolution", type=float, default=0.25)
111
+ parser.add_argument("--repeats", type=int, default=3)
112
+ parser.add_argument("--radius-scale", type=float, default=1.0)
113
+ parser.add_argument("--framework", default="BEA")
114
+ parser.add_argument("--wulff-size", type=int, default=1000)
115
+ parser.add_argument("--padding", type=float, default=5.0)
116
+ parser.add_argument("--cell-length", type=float, default=32.0)
117
+ parser.add_argument("--atoms", type=int, default=512)
118
+ parser.add_argument("--seed", type=int, default=123)
119
+ args = parser.parse_args()
120
+
121
+ cell, centers, radii = make_workload(args)
122
+ reference = None
123
+
124
+ print(
125
+ "workload,backend,backend_name,atoms,gpts,best_s,mean_s,std_s,"
126
+ "occupied_voxels,value_sum,max_abs_diff"
127
+ )
128
+ for backend in args.backends:
129
+ try:
130
+ cls = load_backend(backend)
131
+ times, grid = time_backend(cls, cell, args.resolution, centers, radii, args.repeats)
132
+ except ImportError as exc:
133
+ print(f"{args.workload},{backend},missing,{len(centers)},(),nan,nan,nan,0,nan,nan # {exc}")
134
+ continue
135
+
136
+ values = grid.to_numpy()
137
+ if reference is None:
138
+ reference = values
139
+ occupied, total, max_abs_diff = consistency_summary(values, reference)
140
+ print(
141
+ f"{args.workload},{backend},{grid.backend_name},{len(centers)},"
142
+ f"{tuple(int(x) for x in grid.gpts)},{times.min():.6f},{times.mean():.6f},"
143
+ f"{times.std():.6f},{occupied},{total:.6f},{max_abs_diff:.6g}"
144
+ )
145
+
146
+
147
+ if __name__ == "__main__":
148
+ main()
149
+
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+ import sys
5
+
6
+
7
+ def main():
8
+ commands = [
9
+ [
10
+ sys.executable,
11
+ "benchmarks/benchmark_backends.py",
12
+ "--workload",
13
+ "zeolite",
14
+ "--framework",
15
+ "BEA",
16
+ "--resolution",
17
+ "0.25",
18
+ "--repeats",
19
+ "3",
20
+ ],
21
+ [
22
+ sys.executable,
23
+ "benchmarks/benchmark_backends.py",
24
+ "--workload",
25
+ "wulff",
26
+ "--wulff-size",
27
+ "1000",
28
+ "--resolution",
29
+ "0.35",
30
+ "--repeats",
31
+ "3",
32
+ ],
33
+ ]
34
+
35
+ for command in commands:
36
+ subprocess.run(command, check=True)
37
+
38
+
39
+ if __name__ == "__main__":
40
+ main()
41
+
@@ -0,0 +1,113 @@
1
+ Analysis
2
+ ========
3
+
4
+ ``VoxelGridAnalysis`` provides post-processing helpers for voxel grids. The
5
+ analysis dependency is optional because marching cubes and connected-component
6
+ labeling use scikit-image:
7
+
8
+ .. code-block:: bash
9
+
10
+ pip install ".[analysis]"
11
+
12
+ Connected Volumes
13
+ -----------------
14
+
15
+ The analysis class can select voxel regions by value, label connected
16
+ components, and convert voxel counts to physical volumes using the determinant
17
+ of the periodic cell:
18
+
19
+ .. code-block:: python
20
+
21
+ from atomvoxelizer import VoxelGridAnalysis
22
+
23
+ analysis = VoxelGridAnalysis(grid)
24
+ regions = analysis.analyze_regions(threshold=0.5)
25
+
26
+ for region in regions:
27
+ print(region.voxel_count, region.volume, region.surface_area)
28
+
29
+ ``volume`` is reported in cubic Angstrom when the input cell is in Angstrom.
30
+ ``surface_area`` is estimated by applying marching cubes to the selected voxel
31
+ mask and transforming mesh vertices into real-space coordinates. By default,
32
+ connected-component labeling and surface-area estimation apply periodic boundary
33
+ conditions. Periodic connected components are merged across opposite cell faces;
34
+ periodic surface areas are measured from a tiled mask and counted only for the
35
+ central periodic image.
36
+
37
+ Zeolite Pore Volume And Surface Area
38
+ ------------------------------------
39
+
40
+ For zeolites, a common workflow is:
41
+
42
+ 1. Build an occupied framework mask from atomic cores.
43
+ 2. Analyze the inverse mask as the pore space.
44
+ 3. Sum connected-region volumes to estimate accessible pore volume.
45
+ 4. Sum marching-cubes surface areas to estimate internal surface area.
46
+
47
+ Example:
48
+
49
+ .. code-block:: python
50
+
51
+ from atomvoxelizer import VoxelGridAnalysis
52
+
53
+ analysis = VoxelGridAnalysis(voxel_grid)
54
+ pore_regions = analysis.analyze_regions(max_value=0.0)
55
+ pore_volume_a3 = sum(region.volume for region in pore_regions)
56
+ pore_area_a2 = sum(region.surface_area for region in pore_regions)
57
+
58
+ mass_amu = sum(atoms.get_masses())
59
+ pore_volume_cm3_g = analysis.volume_angstrom3_to_cm3_per_g(pore_volume_a3, mass_amu)
60
+ internal_area_m2_g = analysis.area_angstrom2_to_m2_per_g(pore_area_a2, mass_amu)
61
+
62
+ The same workflow is provided as ``examples/zeolite_analysis.py``:
63
+
64
+ .. code-block:: bash
65
+
66
+ python examples/zeolite_analysis.py BEA --resolution 0.25
67
+
68
+ The example can also run a resolution-convergence study and save a plot:
69
+
70
+ .. code-block:: bash
71
+
72
+ python examples/zeolite_analysis.py BEA --convergence 1.0 0.75 0.5 0.35 --plot bea_convergence.png
73
+
74
+ Experimental Comparison
75
+ -----------------------
76
+
77
+ Experimental BET surface area and pore volume are usually reported as
78
+ ``m^2/g`` and ``cm^3/g``. Direct comparison to a geometric voxel model requires
79
+ normalizing by the mass represented by the simulated unit cell or supercell and
80
+ matching the experimental assumptions: framework composition, extra-framework
81
+ cations, adsorbate probe size, activation state, defects, and whether the
82
+ reported pore volume is micropore, mesopore, or total pore volume.
83
+
84
+ AtomVoxelizer provides unit-conversion helpers once you know the mass represented
85
+ by the simulated structure:
86
+
87
+ .. code-block:: python
88
+
89
+ mass_amu = sum(atoms.get_masses())
90
+ pore_volume_cm3_g = analysis.volume_angstrom3_to_cm3_per_g(pore_volume_a3, mass_amu)
91
+ area_m2_g = analysis.area_angstrom2_to_m2_per_g(pore_area_a2, mass_amu)
92
+
93
+ The comparison table should be filled with values from the specific material
94
+ and synthesis route being modeled:
95
+
96
+ .. list-table::
97
+ :header-rows: 1
98
+
99
+ * - Framework
100
+ - Experimental BET surface area
101
+ - Experimental pore volume
102
+ - Notes
103
+ * - BEA
104
+ - source-specific
105
+ - source-specific
106
+ - Zeolite beta values depend strongly on Si/Al ratio and activation.
107
+ * - MWW/MCM-22
108
+ - source-specific
109
+ - source-specific
110
+ - MCM-22 reports often distinguish micropore and external surface area.
111
+
112
+ Use the voxel result as a geometric internal-surface estimate, not as a direct
113
+ replacement for adsorbate-specific BET analysis.
@@ -0,0 +1,17 @@
1
+ API Reference
2
+ =============
3
+
4
+ .. autoclass:: atomvoxelizer.VoxelGrid
5
+ :members:
6
+ :undoc-members:
7
+ :show-inheritance:
8
+
9
+ .. autoclass:: atomvoxelizer.VoxelGridNumPy
10
+ :members:
11
+ :undoc-members:
12
+ :show-inheritance:
13
+
14
+ .. autoclass:: atomvoxelizer.VoxelGridAnalysis
15
+ :members:
16
+ :undoc-members:
17
+ :show-inheritance: