Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/advanced/input_files/input-main.md
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,7 @@
- nspin = 1: pots1.cube;
- nspin = 2: pots1.cube and pots2.cube;
- nspin = 4: pots1.cube, pots2.cube, pots3.cube, and pots4.cube
- 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential.
- 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/02_postprocessing/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential.
- 3: Apart from 1, also output the total local potential of the initial charge density. The files are named as:
- nspin = 1: pots1_ini.cube;
- nspin = 2: pots1_ini.cube and pots2_ini.cube;
Expand Down
6 changes: 3 additions & 3 deletions docs/advanced/windows_installer.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A lightweight installer that brings ABACUS to Windows via WSL2 and
conda-forge. No C++ toolchain, no MPI build, no manual dependency juggling —
run `install-abacus.bat` once and type `abacus` from any Windows terminal.

The scripts live in the repository under `tools/windows/`. This page is the
The scripts live in the repository under `tools/04_windows_installation/`. This page is the
user-facing documentation for the same scripts.

## How it works
Expand Down Expand Up @@ -89,7 +89,7 @@ The pipeline, end to end:
## Installation

1. Clone or download this repository.
2. In `tools/windows/`, right-click `install-abacus.bat` → **Run as administrator**.
2. In `tools/04_windows_installation/`, right-click `install-abacus.bat` → **Run as administrator**.
3. Answer the China-mirror prompt (`y` recommended inside Mainland China).
Then pick an ABACUS version when prompted (leave blank for the latest on
conda-forge; for a pinned install, type an exact version such as `3.7.4`).
Expand Down Expand Up @@ -217,7 +217,7 @@ Hyper-V virtualization layer used by WSL2 is disabled.
## File layout

```
tools/windows/
tools/04_windows_installation/
├── install-abacus.bat # Windows entry point (admin, interactive)
├── uninstall-abacus.bat # Clean removal, optionally including the distro
├── provision.sh # Linux-side installer (runs as root in WSL)
Expand Down
2 changes: 1 addition & 1 deletion docs/parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2867,7 +2867,7 @@ parameters:
* nspin = 1: pots1.cube;
* nspin = 2: pots1.cube and pots2.cube;
* nspin = 4: pots1.cube, pots2.cube, pots3.cube, and pots4.cube
* 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential.
* 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/02_postprocessing/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential.
* 3: Apart from 1, also output the total local potential of the initial charge density. The files are named as:
* nspin = 1: pots1_ini.cube;
* nspin = 2: pots1_ini.cube and pots2_ini.cube;
Expand Down
8 changes: 4 additions & 4 deletions source/source_basis/module_nao/atomic_radials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ void AtomicRadials::read_abacus_orb(std::ifstream& ifs, std::ofstream* ptr_log,
* Read the orbital file.
*
* For orbital file format, see
* (new) abacus-develop/tools/SIAB/PyTorchGradient/source/IO/print_orbital.py
* (old) abacus-develop/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.cpp
* (new) abacus-develop/tools/01_NAO_generation/pytorch/IO/print_orbital.py
* (old) abacus-develop/tools/01_NAO_generation/SIAB/src_spillage/Plot_Psi.cpp
* */
int ngrid = 0; // number of grid points
double dr = 0; // grid spacing
Expand Down Expand Up @@ -284,8 +284,8 @@ void AtomicRadials::read_abacus_orb(std::ifstream& ifs, std::ofstream* ptr_log,
// * Read the orbital file.
// *
// * For orbital file format, see
// * (new) abacus-develop/tools/SIAB/PyTorchGradient/source/IO/print_orbital.py
// * (old) abacus-develop/tools/SIAB/SimulatedAnnealing/source/src_spillage/Plot_Psi.cpp
// * (new) abacus-develop/tools/01_NAO_generation/pytorch/IO/print_orbital.py
// * (old) abacus-develop/tools/01_NAO_generation/SIAB/src_spillage/Plot_Psi.cpp
// * */
// int ngrid = 0; // number of grid points
// double dr = 0; // grid spacing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ In molecular dynamics simulations, the output frequency is controlled by out_fre
* nspin = 1: pots1.cube;
* nspin = 2: pots1.cube and pots2.cube;
* nspin = 4: pots1.cube, pots2.cube, pots3.cube, and pots4.cube
* 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential.
* 2: Output the electrostatic potential on real space grids into OUT.{suffix}/pot_es.cube. The Python script named tools/02_postprocessing/average_pot/aveElecStatPot.py can be used to calculate the average electrostatic potential along the z-axis and outputs it into ElecStaticPot_AVE. Please note that the total local potential refers to the local component of the self-consistent potential, excluding the non-local pseudopotential. The distinction between the local potential and the electrostatic potential is as follows: local potential = electrostatic potential + XC potential.
* 3: Apart from 1, also output the total local potential of the initial charge density. The files are named as:
* out_freq_ion = 0:
* nspin = 1: `pot_ini.cube`;
Expand Down
2 changes: 1 addition & 1 deletion source/source_io/module_qo/to_qo_kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ void toQO::calculate()
std::string filename = out_dir_ + "/QO_ovlpR_" + std::to_string(iR) + ".dat";
std::remove(filename.c_str());
}
printf("toQO::calculate: calculation of S(k) done, run /tools/qo/postprocess.py to do representation "
printf("toQO::calculate: calculation of S(k) done, run /tools/01_NAO_generation/qo/postprocess.py to do representation "
"transform.\n");
}
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
195 changes: 195 additions & 0 deletions tools/03_code_analysis/generate_include_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#!/usr/bin/env python3
import os
import re
import sys
from collections import defaultdict

INCLUDE_PATTERN = re.compile(r'^\s*#\s*include\s*["<]([^">]+)[">]', re.MULTILINE)

def find_source_files(root_dir):
cpp_files = []
h_files = []
for dirpath, dirnames, filenames in os.walk(root_dir):
for filename in filenames:
if filename.endswith('.cpp'):
cpp_files.append(os.path.join(dirpath, filename))
elif filename.endswith('.h'):
h_files.append(os.path.join(dirpath, filename))
return cpp_files + h_files

def parse_includes(filepath, include_dirs):
try:
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
except:
return []

includes = []
for match in INCLUDE_PATTERN.finditer(content):
include_path = match.group(1)
includes.append(include_path)
return includes

def resolve_include(include_name, source_file_dir, include_dirs):
for include_dir in [source_file_dir] + include_dirs:
full_path = os.path.join(include_dir, include_name)
if os.path.exists(full_path):
return os.path.normpath(full_path)
return None

def compute_depth(filepath, include_map, visited, depth_cache, include_dirs):
if filepath in depth_cache:
return depth_cache[filepath]
if filepath in visited:
return 0

visited.add(filepath)
max_depth = 0
source_dir = os.path.dirname(filepath)

if filepath not in include_map:
depth_cache[filepath] = 0
visited.remove(filepath)
return 0

for include_name in include_map[filepath]:
resolved_path = resolve_include(include_name, source_dir, include_dirs)
if resolved_path:
child_depth = compute_depth(resolved_path, include_map, visited, depth_cache, include_dirs)
max_depth = max(max_depth, child_depth + 1)

depth_cache[filepath] = max_depth
visited.remove(filepath)
return max_depth

def get_include_chain(filepath, include_map, include_dirs, max_depth=30):
chain = [filepath]
visited = set()
visited.add(filepath)
current = filepath

for _ in range(max_depth):
source_dir = os.path.dirname(current)
if current not in include_map or not include_map[current]:
break

next_include = None
max_child_depth = -1

for include_name in include_map[current]:
resolved_path = resolve_include(include_name, source_dir, include_dirs)
if resolved_path and resolved_path not in visited:
child_depth = 0
temp_visited = set()
child_depth = compute_depth(resolved_path, include_map, temp_visited, {}, include_dirs)
if child_depth > max_child_depth:
max_child_depth = child_depth
next_include = resolved_path

if next_include:
visited.add(next_include)
chain.append(next_include)
current = next_include
else:
break

return chain

def main():
script_dir = os.path.dirname(os.path.abspath(__file__))
# Script is at tools/03_code_analysis/, repo root is two levels up
repo_root = os.path.dirname(os.path.dirname(script_dir))
root_dir = os.path.join(repo_root, 'source')

include_dirs = [
root_dir,
os.path.join(root_dir, 'source_base'),
os.path.join(root_dir, 'source_cell'),
os.path.join(root_dir, 'source_pw'),
os.path.join(root_dir, 'source_lcao'),
os.path.join(root_dir, 'source_basis'),
os.path.join(root_dir, 'source_esolver'),
os.path.join(root_dir, 'source_hsolver'),
os.path.join(root_dir, 'source_io'),
os.path.join(root_dir, 'source_psi'),
os.path.join(root_dir, 'source_relax'),
os.path.join(root_dir, 'source_estate'),
os.path.join(root_dir, 'source_hamilt'),
os.path.join(root_dir, 'source_main'),
os.path.join(root_dir, 'source_md'),
]

all_files = find_source_files(root_dir)
print(f"Found {len(all_files)} source files")

include_map = {}
for filepath in all_files:
includes = parse_includes(filepath, include_dirs)
if includes:
include_map[filepath] = includes

print(f"Parsed includes for {len(include_map)} files")

depth_cache = {}
file_depths = []

for filepath in all_files:
visited = set()
depth = compute_depth(filepath, include_map, visited, depth_cache, include_dirs)
file_depths.append((filepath, depth))

file_depths.sort(key=lambda x: -x[1])

min_depth = 18
deep_files = [(f, d) for f, d in file_depths if d >= min_depth]

output = []
output.append(f"=== Files with #include dependency depth >= {min_depth} ===")
output.append(f"Total found: {len(deep_files)} files")
output.append("")

top_10 = deep_files[:10]
if top_10:
output.append("=" * 80)
output.append("TOP 10 deepest dependency chains (showing full include path):")
output.append("=" * 80)
output.append("")

for filepath, depth in top_10:
chain = get_include_chain(filepath, include_map, include_dirs)
rel_path = os.path.relpath(filepath, root_dir)
output.append(f" Depth {depth}: {rel_path}")
output.append(" Include chain:")
for i, step in enumerate(chain):
prefix = " " if i == 0 else " -> "
output.append(f"{prefix}{os.path.relpath(step, root_dir)}")
output.append("")

output.append("=" * 80)
output.append(f"Full list of all {len(deep_files)} files with depth >= {min_depth}:")
output.append("=" * 80)
output.append("")

depth_groups = defaultdict(list)
for filepath, depth in deep_files:
depth_groups[depth].append(filepath)

for depth in sorted(depth_groups.keys(), reverse=True):
files = sorted(depth_groups[depth])
output.append(f" Depth {depth} ({len(files)} files):")
for filepath in files:
rel_path = os.path.relpath(filepath, root_dir)
output.append(f" {rel_path}")
output.append("")

output_path = os.path.join(script_dir, 'deep_include_analysis.txt')
with open(output_path, 'w') as f:
f.write('\n'.join(output))

print(f"Analysis complete.")
print(f"Results have been generated at:")
print(f" {output_path}")
print(f"Total files with depth >= {min_depth}: {len(deep_files)}")

if __name__ == '__main__':
main()
File renamed without changes.
File renamed without changes.
100 changes: 87 additions & 13 deletions tools/README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,99 @@
SIAB: codes to generate numerical atomic orbitals.
# ABACUS Tools

molden: generate molden style file for Multiwfn analysis.
This directory contains various auxiliary tools for ABACUS calculations.

plot-tools: band structure, dos and pdos, dipole and adsorption.
## Directory Structure

rt-tddft-tools: tools for real-time tddft.
```
tools/
├── README.md
├── 01_NAO_generation/ # Numerical atomic orbital generation tools
│ ├── SIAB/ # Simulated Annealing method (C++)
│ ├── pytorch/ # PyTorch gradient method V1
│ ├── pytorch_dpsi/ # PyTorch gradient method V2 (with dpsi)
│ ├── pytorch_gradient_source/ # Original PyTorch gradient implementation
│ ├── lcao_bash/ # LCAO basis set bash tools
│ ├── abfs_bash/ # ABFS basis set bash tools
│ ├── qo/ # Quasiatomic orbital (QO) generation
│ ├── Generate_Orbital_AllInOne.sh # Main orbital generation script
│ └── examples/ # Usage examples
├── 02_postprocessing/ # Post-processing and visualization tools
│ ├── rt-tddft-tools/ # Real-time TDDFT analysis
│ ├── stm/ # STM image generation
│ ├── average_pot/ # Average electrostatic potential
│ ├── selective_dynamics/ # ABACUS + Phonopy phonon calculation
│ └── plot-tools/ # Band structure, DOS, dipole and absorption
├── 03_code_analysis/ # Source code analysis tools
│ └── generate_include_analysis.py
└── 04_windows_installation/ # Windows one-click installer via WSL2
├── install-abacus.bat
├── uninstall-abacus.bat
├── provision.sh
└── README.md
```

average_pot: python script used to calculate and plot the average electrostatic potential.
## Quick Start

stm: generate figures related to Scanning tunneling microscope technique.
### Generate Numerical Atomic Orbitals

generate_orbital.sh: script used to generate numerical atomic orbitals (NAO).
```bash
cd 01_NAO_generation
./Generate_Orbital_AllInOne.sh ORBITAL_INPUT
```

opt_abfs_bash: related to generating NAO basis set.
### RT-TDDFT Post-processing

opt_lcao_bash: related to generating NAO basis set.
```bash
cd 02_postprocessing/rt-tddft-tools
python plot_absorption.py --help
```

opt_orb_pytorch: related to generating NAO basis set.
### STM Image Generation

opt_orb_pytorch_dpsi: related to generating NAO basis set.
```bash
cd 02_postprocessing/stm
python stm.py --help
```

qo: generate quasiatomic orbital (qo).
### Average Electrostatic Potential

selective_dynamics: used to do selective dynamics with ABACUS + Phonopy.
```bash
cd 02_postprocessing/average_pot
python aveElecStatPot.py --help
```

### Windows Installation

Run as administrator:
```bash
04_windows_installation/install-abacus.bat
```

## Tool Descriptions

### 01_NAO_generation/
- **SIAB/** - Simulated Annealing method for NAO optimization (C++)
- **pytorch/** - PyTorch gradient method V1 for NAO optimization
- **pytorch_dpsi/** - PyTorch gradient method V2 with dpsi calculation
- **pytorch_gradient_source/** - Original PyTorch gradient implementation
- **lcao_bash/** - Bash tools for LCAO basis set generation
- **abfs_bash/** - Bash tools for ABFS basis set generation
- **qo/** - Quasiatomic orbital (QO) generation tool
- **examples/** - Example input files and test cases

### 02_postprocessing/
- **rt-tddft-tools/** - Tools for real-time time-dependent density functional theory analysis
- **stm/** - Tools for generating STM images from LDOS cube files
- **average_pot/** - Python script to calculate and plot average electrostatic potential
- **selective_dynamics/** - Tools for selective dynamics with ABACUS + Phonopy
- **plot-tools/** - Band structure, DOS, dipole and absorption plotting tools

### 03_code_analysis/
- **generate_include_analysis.py** - Header file dependency depth analysis tool

### 04_windows_installation/
- Windows one-click installer via WSL2 + conda-forge
Loading
Loading