pymultibinit 0.2.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 (42) hide show
  1. pymultibinit-0.2.0/.gitignore +149 -0
  2. pymultibinit-0.2.0/CHANGELOG.md +73 -0
  3. pymultibinit-0.2.0/PKG-INFO +210 -0
  4. pymultibinit-0.2.0/README.md +199 -0
  5. pymultibinit-0.2.0/docs/CFFI_IMPLEMENTATION.md +402 -0
  6. pymultibinit-0.2.0/docs/CONFIG_FILE_USAGE.md +442 -0
  7. pymultibinit-0.2.0/docs/SUPERCELL_EXPORT.md +385 -0
  8. pymultibinit-0.2.0/examples/BaTiO3_example/01_basic_usage.py +115 -0
  9. pymultibinit-0.2.0/examples/BaTiO3_example/BaHfO3_supercell.cif +65 -0
  10. pymultibinit-0.2.0/examples/BaTiO3_example/BaTiO3.abi +92 -0
  11. pymultibinit-0.2.0/examples/BaTiO3_example/BaTiO3.xml +9433 -0
  12. pymultibinit-0.2.0/examples/BaTiO3_example/BaTiO3_DDB +3475 -0
  13. pymultibinit-0.2.0/examples/BaTiO3_example/BaTiO3_config.conf +82 -0
  14. pymultibinit-0.2.0/examples/BaTiO3_example/BaTiO3_supercell.cif +65 -0
  15. pymultibinit-0.2.0/examples/BaTiO3_example/fort.7 +249 -0
  16. pymultibinit-0.2.0/examples/example_libabinit_path.py +61 -0
  17. pymultibinit-0.2.0/examples/multibinit_ini.conf +49 -0
  18. pymultibinit-0.2.0/examples/multibinit_simple.conf +41 -0
  19. pymultibinit-0.2.0/examples/simple_example.py +91 -0
  20. pymultibinit-0.2.0/pyproject.toml +21 -0
  21. pymultibinit-0.2.0/src/pymultibinit/__init__.py +52 -0
  22. pymultibinit-0.2.0/src/pymultibinit/atom_matching.py +344 -0
  23. pymultibinit-0.2.0/src/pymultibinit/calculator.py +208 -0
  24. pymultibinit-0.2.0/src/pymultibinit/cli.py +361 -0
  25. pymultibinit-0.2.0/src/pymultibinit/config.py +246 -0
  26. pymultibinit-0.2.0/src/pymultibinit/potential.py +748 -0
  27. pymultibinit-0.2.0/src/pymultibinit/py.typed +0 -0
  28. pymultibinit-0.2.0/src/pymultibinit/utils.py +186 -0
  29. pymultibinit-0.2.0/src/pymultibinit/wrapper_cffi.py +478 -0
  30. pymultibinit-0.2.0/tests/README.md +172 -0
  31. pymultibinit-0.2.0/tests/__init__.py +0 -0
  32. pymultibinit-0.2.0/tests/test_api.py +431 -0
  33. pymultibinit-0.2.0/tests/test_api.py.bak +422 -0
  34. pymultibinit-0.2.0/tests/test_api_old.py +425 -0
  35. pymultibinit-0.2.0/tests/test_atom_matching.py +266 -0
  36. pymultibinit-0.2.0/tests/test_cffi.py +158 -0
  37. pymultibinit-0.2.0/tests/test_cli.py +394 -0
  38. pymultibinit-0.2.0/tests/test_config.py +399 -0
  39. pymultibinit-0.2.0/tests/test_config_init.py +363 -0
  40. pymultibinit-0.2.0/tests/test_libabinit_path.py +146 -0
  41. pymultibinit-0.2.0/tests/test_supercell_export.py +270 -0
  42. pymultibinit-0.2.0/upload_to_pip.sh +4 -0
@@ -0,0 +1,149 @@
1
+ doc/refs/*.pdf
2
+
3
+
4
+ uv.lock
5
+
6
+ # vim files
7
+ *.swp
8
+
9
+ # Latex
10
+ *.aux
11
+
12
+
13
+ # file for AI IDE
14
+ # kiro
15
+ .kiro/
16
+ # cline
17
+ .cline
18
+ # roo coder
19
+ .roo
20
+ AGENTS.md
21
+ CLAUDE.md
22
+ .opencode
23
+ openspec
24
+
25
+
26
+
27
+ # xyz files
28
+
29
+ .DS_Store
30
+
31
+ # Byte-compiled / optimized / DLL files
32
+ __pycache__/
33
+ *.py[cod]
34
+ *$py.class
35
+
36
+ # numpy results
37
+ *.npy
38
+
39
+ # png files
40
+
41
+ # C extensions
42
+ *.so
43
+ *.a
44
+
45
+ # Fortran extensions
46
+ *.fpp
47
+ *.mod
48
+ *.o
49
+
50
+ # F90wrap files
51
+ *.plist
52
+
53
+ # Distribution / packaging
54
+ .Python
55
+ env/
56
+ build/
57
+ develop-eggs/
58
+ dist/
59
+ downloads/
60
+ eggs/
61
+ .eggs/
62
+ lib/
63
+ lib64/
64
+ parts/
65
+ sdist/
66
+ var/
67
+ wheels/
68
+ *.egg-info/
69
+ *.egg-info/*
70
+ .installed.cfg
71
+ *.egg
72
+
73
+ # temporary files
74
+ temp/
75
+
76
+ # PyInstaller
77
+ # Usually these files are written by a python script from a template
78
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
79
+ *.manifest
80
+ *.spec
81
+
82
+ # Installer logs
83
+ pip-log.txt
84
+ pip-delete-this-directory.txt
85
+
86
+ # Unit test / coverage reports
87
+ htmlcov/
88
+ .tox/
89
+ .coverage
90
+ .coverage.*
91
+ .cache
92
+ nosetests.xml
93
+ coverage.xml
94
+ *.cover
95
+ .hypothesis/
96
+
97
+ # Translations
98
+ *.mo
99
+ *.pot
100
+
101
+ # Django stuff:
102
+ *.log
103
+ local_settings.py
104
+
105
+ # Flask stuff:
106
+ instance/
107
+ .webassets-cache
108
+
109
+ # Scrapy stuff:
110
+ .scrapy
111
+
112
+ # Sphinx documentation
113
+ docs/_build/
114
+
115
+ # PyBuilder
116
+ target/
117
+
118
+ # Jupyter Notebook
119
+ .ipynb_checkpoints
120
+
121
+ # pyenv
122
+ .python-version
123
+
124
+ # celery beat schedule file
125
+ celerybeat-schedule
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # dotenv
131
+ .env
132
+
133
+ # virtualenv
134
+ .venv
135
+ venv/
136
+ ENV/
137
+
138
+ # Spyder project settings
139
+ .spyderproject
140
+ .spyproject
141
+
142
+ # Rope project settings
143
+ .ropeproject
144
+
145
+ # mkdocs documentation
146
+ /site
147
+
148
+ # mypy
149
+ .mypy_cache/
@@ -0,0 +1,73 @@
1
+ # Changelog
2
+
3
+ All notable changes to pymultibinit will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2025-12-07
9
+
10
+ ### Added
11
+ - **Configuration file support**: New way to initialize potentials from config files
12
+ - New `config` module with `MultibinitConfig` class for parsing configuration files
13
+ - New class methods:
14
+ - `MultibinitPotential.from_config_file()`: Initialize potential from config file
15
+ - `MultibinitCalculator.from_config_file()`: Initialize ASE calculator from config file
16
+ - Supports multiple formats:
17
+ - Simple format: `key: value` pairs
18
+ - INI format: Sections with `[section]` headers
19
+ - Both `:` and `=` separators supported
20
+ - Automatic path resolution: Relative paths resolved relative to config file directory
21
+ - Comprehensive test suite with 14 tests covering all config scenarios
22
+ - Example config files in `examples/` directory
23
+ - Complete documentation in `docs/CONFIG_FILE_USAGE.md`
24
+
25
+ - **Supercell structure export**: Ability to extract and export the MULTIBINIT internal supercell structure
26
+ - New methods on `MultibinitPotential`:
27
+ - `get_supercell_structure()`: Get reference structure as numpy arrays
28
+ - `export_supercell_to_ase()`: Export as ASE Atoms object
29
+ - `export_supercell_to_file()`: Export to CIF, VASP, XYZ, etc.
30
+ - Automatic unit conversion (Angstrom for ASE compatibility)
31
+ - Test suite with 8 tests covering all export scenarios
32
+ - Complete documentation in `docs/SUPERCELL_EXPORT.md`
33
+
34
+ - **Automatic atom matching with PBC handling**: `MultibinitPotential` now automatically matches atom ordering between input structures and MULTIBINIT's internal reference structure
35
+ - New `atom_matching` module with core matching utilities
36
+ - Enabled by default with `auto_match_atoms=True` parameter
37
+ - Persistent mapping: computed once on first evaluation, reused for all subsequent calls
38
+ - Automatic force remapping: forces always returned in input atom order
39
+ - **Optimization**: Identity mapping detection to skip unnecessary force remapping when no reordering or PBC shifts needed
40
+ - Full PBC support using minimum image convention
41
+ - New utility functions:
42
+ - `is_identity_mapping_no_pbc_shift()`: Check if mapping is trivial
43
+ - New methods on `MultibinitPotential`:
44
+ - `set_reference_structure()`: Explicitly set reference structure for matching
45
+ - `compute_atom_mapping()`: Compute and store atom mapping
46
+ - `get_atom_mapping()`: Retrieve stored mapping
47
+ - `clear_atom_mapping()`: Reset stored mapping
48
+ - Comprehensive test suite with 12 tests covering all matching scenarios (including PBC shift detection)
49
+ - Complete documentation in `docs/ATOM_MATCHING_USAGE.md`
50
+
51
+ ### Changed
52
+ - `MultibinitPotential.evaluate()` now automatically handles atom reordering when `auto_match_atoms=True` (default)
53
+ - Forces are now automatically mapped back to input atom order for user convenience
54
+ - **Performance improvement**: Force remapping is skipped when mapping is identity (no reordering) and no PBC shifts are needed
55
+
56
+ ### Documentation
57
+ - Added `docs/SUPERCELL_EXPORT.md`: Complete guide for exporting supercell structures with 6 detailed examples
58
+ - Added `docs/CONFIG_FILE_USAGE.md`: Complete guide for configuration file usage
59
+ - Added `examples/multibinit_simple.conf`: Minimal simple format example
60
+ - Added `examples/multibinit_ini.conf`: Full INI format example
61
+ - Added `docs/ATOM_MATCHING_USAGE.md`: Complete usage guide with examples
62
+ - Added `docs/fortran/ATOM_ORDERING_AND_PBC.md`: Technical details on MULTIBINIT's internal atom handling
63
+ - Added `docs/fortran/DIAGRAMS.md`: Visual diagrams for supercell construction and displacement computation
64
+ - Added `docs/DEVELOPER_GUIDE.md`: Complete developer guide for extending pymultibinit
65
+ - Added `docs/api/API_REFERENCE.md`: Full API reference documentation
66
+
67
+ ## [0.1.0] - Initial Release
68
+
69
+ ### Added
70
+ - Initial Python wrapper for MULTIBINIT C API
71
+ - Basic `MultibinitPotential` class for energy and force evaluation
72
+ - ASE calculator interface
73
+ - Basic tests and examples
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.4
2
+ Name: pymultibinit
3
+ Version: 0.2.0
4
+ Summary: Add your description here
5
+ Author-email: Xu He <x.he@uliege.be>
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: ase>=3.26.0
8
+ Requires-Dist: cffi>=2.0.0
9
+ Requires-Dist: numpy>=2.2.6
10
+ Description-Content-Type: text/markdown
11
+
12
+ # pymultibinit - Python Interface to MULTIBINIT
13
+
14
+ Python bindings for ABINIT's MULTIBINIT effective potential library.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ # 1. Build ABINIT library
20
+ cd abinit
21
+ rm -rf build && mkdir build && cd build
22
+ CC=mpicc FC=mpif90 cmake -C ~/.abinit/build/shared.cmake ..
23
+ make -j8
24
+
25
+ # 2. Set library path (choose one):
26
+
27
+ # Option A: LIBABINIT_PATH (recommended)
28
+ export LIBABINIT_PATH=/path/to/abinit/build/src/98_main/libabinit.dylib # macOS
29
+ export LIBABINIT_PATH=/path/to/abinit/build/src/98_main/libabinit.so # Linux
30
+
31
+ # Option B: Add to LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS)
32
+ export LD_LIBRARY_PATH=/path/to/abinit/build/src/98_main:$LD_LIBRARY_PATH
33
+
34
+ # Add to ~/.bashrc or ~/.zshrc for persistence
35
+
36
+ # 3. Install Python package
37
+ pip install pymultibinit
38
+ # or: pip install -e .
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ```python
44
+ from pymultibinit import MultibinitCalculator
45
+ from ase import Atoms
46
+ from ase.optimize import BFGS
47
+
48
+ # Load from config file (recommended)
49
+ calc = MultibinitCalculator.from_config_file("multibinit.conf")
50
+
51
+ # Or from parameters
52
+ calc = MultibinitCalculator.from_params(
53
+ ddb_file="system_DDB",
54
+ sys_file="system.xml",
55
+ ncell=(2, 2, 2),
56
+ ngqpt=(4, 4, 4)
57
+ )
58
+
59
+ # Build supercell (must match ncell!)
60
+ unit_cell = Atoms('BaTiO3',
61
+ scaled_positions=[[0,0,0], [0.5,0.5,0.5],
62
+ [0.5,0,0.5], [0,0.5,0.5], [0.5,0.5,0]],
63
+ cell=[4.0, 4.0, 4.0], pbc=True)
64
+ atoms = unit_cell * (2, 2, 2) # Match ncell=(2,2,2)
65
+ atoms.calc = calc
66
+
67
+ # Run calculation
68
+ energy = atoms.get_potential_energy() # eV
69
+ forces = atoms.get_forces() # eV/Angstrom
70
+ stress = atoms.get_stress() # eV/Angstrom^3
71
+
72
+ # Optimize structure
73
+ opt = BFGS(atoms)
74
+ opt.run(fmax=0.01)
75
+ ```
76
+
77
+ ## Configuration File
78
+
79
+ Create `multibinit.conf`:
80
+
81
+ ```ini
82
+ # Required
83
+ ddb_file: system_DDB
84
+ sys_file: system.xml
85
+ ncell: 2 2 2
86
+
87
+ # Optional
88
+ ngqpt: 4 4 4
89
+ dipdip: 1
90
+ ```
91
+
92
+ ## API Reference
93
+
94
+ ### `MultibinitCalculator` (ASE interface)
95
+
96
+ ```python
97
+ # From config file (recommended)
98
+ calc = MultibinitCalculator.from_config_file("config.conf")
99
+
100
+ # From parameters
101
+ calc = MultibinitCalculator.from_params(
102
+ ddb_file="system_DDB",
103
+ sys_file="system.xml",
104
+ ncell=(2, 2, 2),
105
+ ngqpt=(4, 4, 4),
106
+ dipdip=1
107
+ )
108
+
109
+ # From .abi file
110
+ calc = MultibinitCalculator.from_abi("input.abi")
111
+ ```
112
+
113
+ ### `MultibinitPotential` (Low-level interface)
114
+
115
+ ```python
116
+ from pymultibinit import MultibinitPotential
117
+ import numpy as np
118
+
119
+ pot = MultibinitPotential.from_params(
120
+ ddb_file="system_DDB",
121
+ sys_file="system.xml",
122
+ ncell=(2, 2, 2)
123
+ )
124
+
125
+ # Evaluate (Angstrom/eV by default)
126
+ positions = np.array([[0, 0, 0], [2.0, 0, 0]]) # Angstrom
127
+ lattice = np.array([[4, 0, 0], [0, 4, 0], [0, 0, 4]]) # Angstrom
128
+ energy, forces, stress = pot.evaluate(positions, lattice)
129
+
130
+ # Export structures
131
+ pot.export_supercell_to_file('supercell.cif') # Export to file
132
+ atoms = pot.export_supercell_to_ase() # Get ASE Atoms object
133
+ structure = pot.get_supercell_structure() # Get raw arrays
134
+
135
+ pot.free()
136
+ ```
137
+
138
+ ## Exporting Structures
139
+
140
+ ### Export Reference/Supercell Structure
141
+
142
+ ```python
143
+
144
+ ```
145
+
146
+ ### Command-Line Tools
147
+
148
+ ```bash
149
+ # Export MULTIBINIT reference structure
150
+ mbtools export-ref config.conf output.cif
151
+
152
+ ```
153
+
154
+ ## Important Notes
155
+
156
+ ### Supercell Size
157
+
158
+ **Your structure must match the `ncell` parameter!**
159
+
160
+ ```python
161
+ # Config: ncell: 2 2 2
162
+ calc = MultibinitCalculator.from_config_file("config.conf")
163
+
164
+ # ✓ CORRECT
165
+ atoms = unit_cell * (2, 2, 2) # Match ncell
166
+
167
+ # ✗ WRONG - will fail with "status 3" error
168
+ atoms = unit_cell # Size mismatch
169
+ ```
170
+
171
+ ### Library Not Found?
172
+
173
+ If you get "Could not find libabinit":
174
+
175
+ ```bash
176
+ # Option 1: Set LIBABINIT_PATH
177
+ export LIBABINIT_PATH=/full/path/to/libabinit.dylib
178
+
179
+ # Option 2: Add to library search path
180
+ export LD_LIBRARY_PATH=/path/to/dir/containing/libabinit:$LD_LIBRARY_PATH
181
+
182
+ # Verify
183
+ python -c "from pymultibinit.utils import find_library; print(find_library())"
184
+ ```
185
+
186
+ ### Unit Conventions
187
+
188
+ | Quantity | Python API | Internal |
189
+ |----------|------------|----------|
190
+ | Length | Angstrom | Bohr |
191
+ | Energy | eV | Hartree |
192
+ | Force | eV/Å | Ha/Bohr |
193
+
194
+ Conversions are automatic.
195
+
196
+ ## Examples
197
+
198
+ ```bash
199
+ cd pymultibinit/examples
200
+ python simple_example.py
201
+ ```
202
+
203
+ ## License
204
+
205
+ GPL v3 (same as ABINIT)
206
+
207
+ ## Citation
208
+
209
+ - ABINIT: https://www.abinit.org
210
+ - MULTIBINIT: https://docs.abinit.org/guide/multibinit/
@@ -0,0 +1,199 @@
1
+ # pymultibinit - Python Interface to MULTIBINIT
2
+
3
+ Python bindings for ABINIT's MULTIBINIT effective potential library.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # 1. Build ABINIT library
9
+ cd abinit
10
+ rm -rf build && mkdir build && cd build
11
+ CC=mpicc FC=mpif90 cmake -C ~/.abinit/build/shared.cmake ..
12
+ make -j8
13
+
14
+ # 2. Set library path (choose one):
15
+
16
+ # Option A: LIBABINIT_PATH (recommended)
17
+ export LIBABINIT_PATH=/path/to/abinit/build/src/98_main/libabinit.dylib # macOS
18
+ export LIBABINIT_PATH=/path/to/abinit/build/src/98_main/libabinit.so # Linux
19
+
20
+ # Option B: Add to LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS)
21
+ export LD_LIBRARY_PATH=/path/to/abinit/build/src/98_main:$LD_LIBRARY_PATH
22
+
23
+ # Add to ~/.bashrc or ~/.zshrc for persistence
24
+
25
+ # 3. Install Python package
26
+ pip install pymultibinit
27
+ # or: pip install -e .
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ```python
33
+ from pymultibinit import MultibinitCalculator
34
+ from ase import Atoms
35
+ from ase.optimize import BFGS
36
+
37
+ # Load from config file (recommended)
38
+ calc = MultibinitCalculator.from_config_file("multibinit.conf")
39
+
40
+ # Or from parameters
41
+ calc = MultibinitCalculator.from_params(
42
+ ddb_file="system_DDB",
43
+ sys_file="system.xml",
44
+ ncell=(2, 2, 2),
45
+ ngqpt=(4, 4, 4)
46
+ )
47
+
48
+ # Build supercell (must match ncell!)
49
+ unit_cell = Atoms('BaTiO3',
50
+ scaled_positions=[[0,0,0], [0.5,0.5,0.5],
51
+ [0.5,0,0.5], [0,0.5,0.5], [0.5,0.5,0]],
52
+ cell=[4.0, 4.0, 4.0], pbc=True)
53
+ atoms = unit_cell * (2, 2, 2) # Match ncell=(2,2,2)
54
+ atoms.calc = calc
55
+
56
+ # Run calculation
57
+ energy = atoms.get_potential_energy() # eV
58
+ forces = atoms.get_forces() # eV/Angstrom
59
+ stress = atoms.get_stress() # eV/Angstrom^3
60
+
61
+ # Optimize structure
62
+ opt = BFGS(atoms)
63
+ opt.run(fmax=0.01)
64
+ ```
65
+
66
+ ## Configuration File
67
+
68
+ Create `multibinit.conf`:
69
+
70
+ ```ini
71
+ # Required
72
+ ddb_file: system_DDB
73
+ sys_file: system.xml
74
+ ncell: 2 2 2
75
+
76
+ # Optional
77
+ ngqpt: 4 4 4
78
+ dipdip: 1
79
+ ```
80
+
81
+ ## API Reference
82
+
83
+ ### `MultibinitCalculator` (ASE interface)
84
+
85
+ ```python
86
+ # From config file (recommended)
87
+ calc = MultibinitCalculator.from_config_file("config.conf")
88
+
89
+ # From parameters
90
+ calc = MultibinitCalculator.from_params(
91
+ ddb_file="system_DDB",
92
+ sys_file="system.xml",
93
+ ncell=(2, 2, 2),
94
+ ngqpt=(4, 4, 4),
95
+ dipdip=1
96
+ )
97
+
98
+ # From .abi file
99
+ calc = MultibinitCalculator.from_abi("input.abi")
100
+ ```
101
+
102
+ ### `MultibinitPotential` (Low-level interface)
103
+
104
+ ```python
105
+ from pymultibinit import MultibinitPotential
106
+ import numpy as np
107
+
108
+ pot = MultibinitPotential.from_params(
109
+ ddb_file="system_DDB",
110
+ sys_file="system.xml",
111
+ ncell=(2, 2, 2)
112
+ )
113
+
114
+ # Evaluate (Angstrom/eV by default)
115
+ positions = np.array([[0, 0, 0], [2.0, 0, 0]]) # Angstrom
116
+ lattice = np.array([[4, 0, 0], [0, 4, 0], [0, 0, 4]]) # Angstrom
117
+ energy, forces, stress = pot.evaluate(positions, lattice)
118
+
119
+ # Export structures
120
+ pot.export_supercell_to_file('supercell.cif') # Export to file
121
+ atoms = pot.export_supercell_to_ase() # Get ASE Atoms object
122
+ structure = pot.get_supercell_structure() # Get raw arrays
123
+
124
+ pot.free()
125
+ ```
126
+
127
+ ## Exporting Structures
128
+
129
+ ### Export Reference/Supercell Structure
130
+
131
+ ```python
132
+
133
+ ```
134
+
135
+ ### Command-Line Tools
136
+
137
+ ```bash
138
+ # Export MULTIBINIT reference structure
139
+ mbtools export-ref config.conf output.cif
140
+
141
+ ```
142
+
143
+ ## Important Notes
144
+
145
+ ### Supercell Size
146
+
147
+ **Your structure must match the `ncell` parameter!**
148
+
149
+ ```python
150
+ # Config: ncell: 2 2 2
151
+ calc = MultibinitCalculator.from_config_file("config.conf")
152
+
153
+ # ✓ CORRECT
154
+ atoms = unit_cell * (2, 2, 2) # Match ncell
155
+
156
+ # ✗ WRONG - will fail with "status 3" error
157
+ atoms = unit_cell # Size mismatch
158
+ ```
159
+
160
+ ### Library Not Found?
161
+
162
+ If you get "Could not find libabinit":
163
+
164
+ ```bash
165
+ # Option 1: Set LIBABINIT_PATH
166
+ export LIBABINIT_PATH=/full/path/to/libabinit.dylib
167
+
168
+ # Option 2: Add to library search path
169
+ export LD_LIBRARY_PATH=/path/to/dir/containing/libabinit:$LD_LIBRARY_PATH
170
+
171
+ # Verify
172
+ python -c "from pymultibinit.utils import find_library; print(find_library())"
173
+ ```
174
+
175
+ ### Unit Conventions
176
+
177
+ | Quantity | Python API | Internal |
178
+ |----------|------------|----------|
179
+ | Length | Angstrom | Bohr |
180
+ | Energy | eV | Hartree |
181
+ | Force | eV/Å | Ha/Bohr |
182
+
183
+ Conversions are automatic.
184
+
185
+ ## Examples
186
+
187
+ ```bash
188
+ cd pymultibinit/examples
189
+ python simple_example.py
190
+ ```
191
+
192
+ ## License
193
+
194
+ GPL v3 (same as ABINIT)
195
+
196
+ ## Citation
197
+
198
+ - ABINIT: https://www.abinit.org
199
+ - MULTIBINIT: https://docs.abinit.org/guide/multibinit/