Skip to content

Commit 17b38af

Browse files
authored
Feature: support pyabacus to run abacus directory (Useful information for the following developments of pyabacus) (deepmodeling#6943)
* Fix: update pyabacus with AI code diagnosis * Feature: add ModuleESolver in pyabacus, support ks_lcao only * Feature: support pyabacus to run abacus directory * Fix: another pyabacus in PyPI * Refactor: add utils to simplify codes in pyabacus and add data interfaces in ESolver
1 parent d4b15bc commit 17b38af

36 files changed

Lines changed: 9028 additions & 324 deletions

docs/advanced/interface/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Interfaces to Other Softwares
66
:maxdepth: 1
77
:caption: Examples
88

9+
pyabacus
910
deepks
1011
dpgen
1112
deeph
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
# PyABACUS
2+
3+
PyABACUS is the official Python interface for ABACUS, providing a convenient way to run DFT calculations directly from Python scripts.
4+
5+
## Installation
6+
7+
### From Source (Recommended)
8+
9+
```bash
10+
cd /path/to/abacus-develop/python/pyabacus
11+
pip install -e .
12+
```
13+
14+
### With C++ Driver Support
15+
16+
For full functionality including direct library calls (faster than subprocess), build ABACUS with Python bindings:
17+
18+
```bash
19+
cmake -B build -DENABLE_PYABACUS=ON -DENABLE_LCAO=ON
20+
cmake --build build -j8
21+
pip install -e python/pyabacus
22+
```
23+
24+
**Note:** The `pyabacus` package on PyPI is a different project and is NOT related to ABACUS. Please install from source as shown above.
25+
26+
## Quick Start
27+
28+
### Basic SCF Calculation
29+
30+
```python
31+
import pyabacus
32+
33+
# Run calculation from a directory containing INPUT, STRU, KPT files
34+
result = pyabacus.abacus("./Si_scf/")
35+
36+
# Check results
37+
print(f"Converged: {result.converged}")
38+
print(f"Total energy: {result.etot_ev:.6f} eV")
39+
print(result.summary())
40+
```
41+
42+
### Calculate Forces and Stress
43+
44+
```python
45+
result = pyabacus.abacus(
46+
"./Si_relax/",
47+
calculate_force=True,
48+
calculate_stress=True,
49+
)
50+
51+
# Access forces (in eV/Angstrom)
52+
if result.has_forces:
53+
forces = result.forces_ev_ang
54+
print(f"Max force: {forces.max():.6f} eV/Ang")
55+
56+
# Access stress tensor (in kbar)
57+
if result.has_stress:
58+
print(f"Stress tensor:\n{result.stress}")
59+
```
60+
61+
### Parallel Calculation
62+
63+
```python
64+
# Run with MPI and OpenMP parallelization
65+
result = pyabacus.abacus(
66+
"./Si_scf/",
67+
nprocs=4, # 4 MPI processes (mpirun -np 4)
68+
nthreads=2, # 2 OpenMP threads (OMP_NUM_THREADS=2)
69+
)
70+
```
71+
72+
This is equivalent to running:
73+
```bash
74+
OMP_NUM_THREADS=2 mpirun -np 4 abacus
75+
```
76+
77+
### Silent Mode
78+
79+
```python
80+
# Run without output
81+
result = pyabacus.abacus("./Si_scf/", verbosity=0)
82+
```
83+
84+
## API Reference
85+
86+
### `pyabacus.abacus()`
87+
88+
Main function for running ABACUS calculations.
89+
90+
```python
91+
def abacus(
92+
input_dir: str = None,
93+
*,
94+
input_file: str = None,
95+
stru_file: str = None,
96+
kpt_file: str = None,
97+
pseudo_dir: str = None,
98+
orbital_dir: str = None,
99+
output_dir: str = None,
100+
calculate_force: bool = True,
101+
calculate_stress: bool = False,
102+
verbosity: int = 1,
103+
nprocs: int = 1,
104+
nthreads: int = 1,
105+
) -> CalculationResult
106+
```
107+
108+
**Parameters:**
109+
110+
| Parameter | Type | Default | Description |
111+
|-----------|------|---------|-------------|
112+
| `input_dir` | str | `"."` | Directory containing INPUT, STRU, KPT files |
113+
| `input_file` | str | None | Explicit path to INPUT file |
114+
| `stru_file` | str | None | Explicit path to STRU file |
115+
| `kpt_file` | str | None | Explicit path to KPT file |
116+
| `pseudo_dir` | str | None | Directory containing pseudopotentials |
117+
| `orbital_dir` | str | None | Directory containing orbital files (LCAO) |
118+
| `output_dir` | str | `"OUT.PYABACUS"` | Directory for output files |
119+
| `calculate_force` | bool | True | Whether to calculate forces |
120+
| `calculate_stress` | bool | False | Whether to calculate stress tensor |
121+
| `verbosity` | int | 1 | Output level (0=silent, 1=normal, 2=verbose) |
122+
| `nprocs` | int | 1 | Number of MPI processes |
123+
| `nthreads` | int | 1 | Number of OpenMP threads |
124+
125+
**Returns:** `CalculationResult` object
126+
127+
### `CalculationResult`
128+
129+
Container for calculation results.
130+
131+
**Attributes:**
132+
133+
| Attribute | Type | Description |
134+
|-----------|------|-------------|
135+
| `converged` | bool | Whether SCF converged |
136+
| `niter` | int | Number of SCF iterations |
137+
| `drho` | float | Final charge density difference |
138+
| `etot` | float | Total energy (Ry) |
139+
| `etot_ev` | float | Total energy (eV) |
140+
| `forces` | ndarray | Forces on atoms (nat, 3) in Ry/Bohr |
141+
| `forces_ev_ang` | ndarray | Forces in eV/Angstrom |
142+
| `stress` | ndarray | Stress tensor (3, 3) in kbar |
143+
| `fermi_energy` | float | Fermi energy (eV) |
144+
| `bandgap` | float | Band gap (eV) |
145+
| `nat` | int | Number of atoms |
146+
| `ntype` | int | Number of atom types |
147+
| `nbands` | int | Number of bands |
148+
| `nks` | int | Number of k-points |
149+
| `output_dir` | str | Path to output directory (OUT.$suffix) |
150+
| `log_file` | str | Path to the main log file |
151+
| `output_files` | dict | Dictionary of output files (filename -> path) |
152+
153+
**Methods:**
154+
155+
| Method | Description |
156+
|--------|-------------|
157+
| `summary()` | Return a formatted summary string |
158+
| `energies` | Dictionary of all energy components |
159+
| `has_forces` | Whether forces are available |
160+
| `has_stress` | Whether stress is available |
161+
| `has_output_dir` | Whether output directory exists |
162+
| `get_output_file(name)` | Get full path to specific output file |
163+
| `list_output_files()` | List all output file names |
164+
165+
## Output File Tracking
166+
167+
PyABACUS automatically tracks output files generated during calculations:
168+
169+
```python
170+
result = pyabacus.abacus("./Si_scf/")
171+
172+
# Check output directory
173+
print(f"Output directory: {result.output_dir}")
174+
print(f"Log file: {result.log_file}")
175+
176+
# List all output files
177+
print("Output files:")
178+
for filename in result.list_output_files():
179+
print(f" {filename}")
180+
181+
# Get path to specific file
182+
bands_file = result.get_output_file("BANDS_1.dat")
183+
if bands_file:
184+
# Read and process band structure data
185+
import numpy as np
186+
bands = np.loadtxt(bands_file)
187+
```
188+
189+
### Common Output Files
190+
191+
| File | Description |
192+
|------|-------------|
193+
| `running_scf.log` | Main calculation log |
194+
| `BANDS_1.dat` | Band structure data |
195+
| `PDOS` | Projected density of states |
196+
| `CHARGE.cube` | Charge density in cube format |
197+
| `SPIN1_CHG.cube` | Spin-up charge density |
198+
| `SPIN2_CHG.cube` | Spin-down charge density |
199+
| `istate.info` | Band eigenvalues and occupations |
200+
| `kpoints` | K-point information |
201+
202+
## Convenience Functions
203+
204+
### `run_scf()`
205+
206+
Alias for `abacus()` with default SCF parameters:
207+
208+
```python
209+
result = pyabacus.run_scf("./Si_scf/")
210+
```
211+
212+
### `run_relax()`
213+
214+
Alias for `abacus()` with force calculation enabled:
215+
216+
```python
217+
result = pyabacus.run_relax("./Si_relax/")
218+
```
219+
220+
## Examples
221+
222+
### Energy vs. Lattice Constant
223+
224+
```python
225+
import pyabacus
226+
import numpy as np
227+
228+
lattice_constants = np.linspace(5.0, 5.5, 11)
229+
energies = []
230+
231+
for a in lattice_constants:
232+
# Modify STRU file with new lattice constant
233+
# ... (file modification code)
234+
235+
result = pyabacus.abacus("./Si_eos/", verbosity=0)
236+
energies.append(result.etot_ev)
237+
238+
# Plot equation of state
239+
import matplotlib.pyplot as plt
240+
plt.plot(lattice_constants, energies, 'o-')
241+
plt.xlabel("Lattice constant (Ang)")
242+
plt.ylabel("Energy (eV)")
243+
plt.savefig("eos.png")
244+
```
245+
246+
### Parallel Batch Calculations
247+
248+
```python
249+
import pyabacus
250+
from pathlib import Path
251+
252+
# Run calculations for multiple systems with parallelization
253+
systems = ["Si", "Ge", "C"]
254+
results = {}
255+
256+
for system in systems:
257+
input_dir = Path(f"./{system}_scf/")
258+
if input_dir.exists():
259+
result = pyabacus.abacus(
260+
str(input_dir),
261+
nprocs=4,
262+
nthreads=2,
263+
)
264+
results[system] = {
265+
"energy": result.etot_ev,
266+
"converged": result.converged,
267+
"bandgap": result.bandgap,
268+
}
269+
270+
# Print summary
271+
for system, data in results.items():
272+
print(f"{system}: E={data['energy']:.4f} eV, gap={data['bandgap']:.2f} eV")
273+
```
274+
275+
## Troubleshooting
276+
277+
### ABACUS executable not found
278+
279+
If you see "ABACUS executable not found", ensure:
280+
1. ABACUS is installed and in your PATH
281+
2. Or build with C++ driver support (see Installation)
282+
283+
### MPI not found
284+
285+
If you see "mpirun/mpiexec not found" when using `nprocs > 1`:
286+
1. Install MPI (OpenMPI or MPICH)
287+
2. Ensure `mpirun` or `mpiexec` is in your PATH
288+
3. Or set `nprocs=1` to run without MPI
289+
290+
### Import errors
291+
292+
If `import pyabacus` fails:
293+
1. Ensure pyabacus is installed: `pip install pyabacus`
294+
2. Check Python version compatibility (Python 3.8+)
295+
296+
### Calculation not converging
297+
298+
Check the log file for details:
299+
```python
300+
result = pyabacus.abacus("./problem_case/")
301+
if not result.converged:
302+
log_path = result.get_output_file("running_scf.log")
303+
if log_path:
304+
with open(log_path) as f:
305+
print(f.read()[-2000:]) # Print last 2000 chars
306+
```
307+
308+
### Forces or stress not available
309+
310+
Forces and stress are parsed from the ABACUS output log. Ensure:
311+
1. `cal_force` is set in your INPUT file for forces
312+
2. `cal_stress` is set in your INPUT file for stress
313+
3. The calculation completed successfully

python/pyabacus/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,18 @@ execute_process(
9696
set(TARGET_PACK pyabacus)
9797
set(CMAKE_INSTALL_RPATH "${PYTHON_SITE_PACKAGES}/${TARGET_PACK}")
9898

99+
# Option to build the driver module (requires full ABACUS library)
100+
option(BUILD_PYABACUS_DRIVER "Build PyABACUS driver module" OFF)
101+
99102
# add subdirectories for submodules
100103
add_subdirectory(${PROJECT_SOURCE_DIR}/src/hsolver)
101104
add_subdirectory(${PROJECT_SOURCE_DIR}/src/ModuleBase)
102105
add_subdirectory(${PROJECT_SOURCE_DIR}/src/ModuleNAO)
106+
add_subdirectory(${PROJECT_SOURCE_DIR}/src/ModuleESolver)
107+
108+
# Conditionally add driver module
109+
if(BUILD_PYABACUS_DRIVER)
110+
message(STATUS "Building PyABACUS driver module")
111+
add_subdirectory(${PROJECT_SOURCE_DIR}/src/ModuleDriver)
112+
endif()
103113

0 commit comments

Comments
 (0)