Compilation Guide
DFTBaby includes Fortran extensions for performance-critical calculations. This guide explains how to compile them.
Overview
DFTBaby has three main Fortran extension modules:
Core Extensions (
DFTB/extensions/) - Essential for most calculationsForce Field (
DFTB/ForceField/src/) - Required for QM/MM simulationsMultiple Scattering (
DFTB/MultipleScattering/src/) - Advanced electronic structure methods
Prerequisites
Required Tools
Python 3.12+ with NumPy 2.0+
Fortran compiler:
gfortran(recommended) or Intelifortf2py: Included with NumPy
BLAS/LAPACK: Linear algebra libraries
make: Build automation tool
Install on Ubuntu/Debian
sudo apt-get update
sudo apt-get install gfortran libblas-dev liblapack-dev make
Install on macOS
brew install gcc make openblas lapack
Install on Fedora/RHEL
sudo dnf install gcc-gfortran blas-devel lapack-devel make
Install in Conda Environment (Recommended for Python 3.12)
IMPORTANT: If you’re using conda with Python 3.12 and NumPy 2.0+, use conda-forge packages to avoid meson/BLAS linking issues.
# Create conda environment
conda create -n dftbaby python=3.12 -y
conda activate dftbaby
# Install all dependencies
conda install -c conda-forge numpy scipy openblas liblapack gfortran make
# Verify installation
python3 -c "import numpy; print(f'NumPy {numpy.__version__}')"
gfortran --version
For conda users experiencing BLAS linking errors, see the detailed troubleshooting guide: ➜ :doc:`compilation_fixes` (Error 7: Meson backend BLAS linking)
Verify Installation
Check that required tools are available:
# Check gfortran
gfortran --version
# Check f2py
python3 -c "import numpy.f2py; print(numpy.f2py.__version__)"
# Check make
make --version
Core Extensions (Essential)
These extensions are required for most DFTBaby calculations.
Location
DFTB/extensions/
Modules Compiled
thomson.so- Thomson charge distributiontddftb.so- TD-DFTB calculationsmulliken.so- Mulliken population analysisslako.so- Slater-Koster transformationsgrad.so- Analytical gradientscosmo.so- COSMO solvation model
Compilation Steps
Method 1: Simple compilation (GNU gfortran)
For system Python or conda with working BLAS:
cd DFTB/extensions/
make clean
make
This compiles all extensions with default settings (GNU compilers, OpenMP parallelization).
Method 1b: Conda environment (if regular Makefile fails)
If you’re using conda and get cannot find -lblas errors, use the conda-specific Makefile:
cd DFTB/extensions/
# Use Makefile.conda which lets meson auto-detect libraries
make -f Makefile.conda clean
make -f Makefile.conda
# Or create a symlink to use regular make commands
mv Makefile Makefile.system
ln -s Makefile.conda Makefile
make clean && make
Why use Makefile.conda?
NumPy 2.0+ uses meson/ninja build backend (not distutils)
Meson handles library linking differently - explicit
-lblas -lgompmay failMakefile.condaremoves explicit library flags and lets meson auto-detectWorks with conda-installed BLAS/LAPACK packages
Method 2: Intel compilers (for HPC clusters)
If you have Intel compilers and MKL:
cd DFTB/extensions/
# Load Intel modules (on HPC systems)
module load compiler/intel/icc
source $(dirname $(which icc))/compilervars.sh intel64
source $(dirname $(which icc))/../mkl/bin/mklvars.sh intel64
# Edit Makefile: change SYS=GNU to SYS=INTEL
sed -i 's/SYS=GNU/SYS=INTEL/' Makefile
# Compile
make clean
make
Method 3: Manual f2py (if make fails)
cd DFTB/extensions/
# Compile each module individually
python3 -m numpy.f2py -c thomson.f90 -m thomson --fcompiler=gfortran --opt="-O3"
python3 -m numpy.f2py -c tddftb.f90 -m tddftb --fcompiler=gfortran --opt="-O3"
python3 -m numpy.f2py -c mulliken.f90 -m mulliken --fcompiler=gfortran --opt="-O3"
python3 -m numpy.f2py -c slako.f90 -m slako --fcompiler=gfortran --opt="-O3"
python3 -m numpy.f2py -c grad.f90 -m grad --fcompiler=gfortran --opt="-O3"
python3 -m numpy.f2py -c cosmo.f90 -m cosmo --fcompiler=gfortran --opt="-O3"
Verification
Test that modules can be imported:
cd DFTB/extensions/
python3 << 'EOF'
import thomson
import tddftb
import mulliken
import slako
import grad
import cosmo
print("✓ All core extensions compiled successfully!")
EOF
Performance Settings
For optimal performance with OpenMP parallelization:
# Set number of threads (adjust based on your CPU)
export OMP_NUM_THREADS=4
# Increase stack size (prevents segfaults in parallel code)
export OMP_STACKSIZE=1g
ulimit -s unlimited
Add these lines to your ~/.bashrc to make them permanent.
Force Field Extensions (QM/MM)
These extensions are required only for QM/MM simulations with periodic systems.
Location
DFTB/ForceField/src/
Module Compiled
ff.so- UFF/DREIDING force fields with periodic boundary conditions
Compilation Steps
cd DFTB/ForceField/src/
make clean
make
This compiles the C-based force field module.
Verification
cd DFTB/ForceField/
python3 << 'EOF'
import ff
print("✓ Force field extension compiled successfully!")
EOF
Troubleshooting
Issue: lapack not found
# Install LAPACK development files
sudo apt-get install liblapack-dev
Issue: setup.py errors
Check that setup.py exists in DFTB/ForceField/src/:
ls -la DFTB/ForceField/src/setup.py
Multiple Scattering Extensions (Advanced)
These extensions are optional and used for advanced electronic structure calculations.
Location
DFTB/MultipleScattering/src/
Modules Compiled
Wigner3j.so- Wigner 3j symbolscoul90.so- Coulomb and spherical Bessel functionsmod_bessel.so- Modified spherical Bessel functionssphharm.so- Spherical harmonicscms.so- Continuum multiple scatteringms.so- Bound orbital multiple scatteringphoto.so- Photoionization cross sectionsnumerov.so- Numerov solver for radial Schrödinger equation
Compilation Steps
cd DFTB/MultipleScattering/src/
make clean
make
This compiles all multiple scattering modules. Compilation may take several minutes.
Verification
cd DFTB/MultipleScattering/
python3 << 'EOF'
import Wigner3j
import coul90
import mod_bessel
import sphharm
import cms
import ms
import photo
import numerov
print("✓ All multiple scattering extensions compiled successfully!")
EOF
Complete Compilation Script
To compile everything at once:
#!/bin/bash
# compile_all.sh - Compile all DFTBaby Fortran extensions
set -e # Exit on error
echo "Compiling DFTBaby Fortran Extensions"
echo "===================================="
# Set performance options
export OMP_NUM_THREADS=4
export OMP_STACKSIZE=1g
# 1. Core Extensions (Required)
echo ""
echo "[1/3] Compiling core extensions..."
cd DFTB/extensions/
make clean
make
cd ../..
echo "✓ Core extensions compiled"
# 2. Force Field (for QM/MM)
echo ""
echo "[2/3] Compiling force field extensions..."
cd DFTB/ForceField/src/
make clean
make
cd ../../..
echo "✓ Force field extensions compiled"
# 3. Multiple Scattering (optional)
echo ""
echo "[3/3] Compiling multiple scattering extensions..."
cd DFTB/MultipleScattering/src/
make clean
make
cd ../../..
echo "✓ Multiple scattering extensions compiled"
echo ""
echo "===================================="
echo "All extensions compiled successfully!"
echo ""
echo "Performance settings:"
echo " OMP_NUM_THREADS=$OMP_NUM_THREADS"
echo " OMP_STACKSIZE=$OMP_STACKSIZE"
echo ""
echo "To use parallelization, run:"
echo " export OMP_NUM_THREADS=4"
echo " export OMP_STACKSIZE=1g"
echo " ulimit -s unlimited"
Save this as compile_all.sh and run:
chmod +x compile_all.sh
./compile_all.sh
Common Issues and Solutions
Compilation Errors
Error: f2py: command not found
Solution: Install NumPy with f2py:
pip3 install --upgrade numpy
Error: gfortran: command not found
Solution: Install gfortran compiler:
sudo apt-get install gfortran
Error: cannot find -lblas or cannot find -llapack
Solution: Install BLAS and LAPACK:
sudo apt-get install libblas-dev liblapack-dev
Error: Segmentation fault when importing modules
Solution: Increase stack size:
export OMP_STACKSIZE=1g
ulimit -s unlimited
Error: Module version mismatch
Solution: Recompile with the same Python version:
make clean
make
Import Errors
Error: ImportError: cannot import name 'thomson'
Solution: Ensure you’re in the correct directory or extensions are in Python path:
# Check if .so files exist
ls -la DFTB/extensions/*.so
# Test from DFTB parent directory
cd /path/to/DFTBaby
python3 -c "from DFTB.extensions import thomson"
Error: ImportError: undefined symbol: __kmpc_fork_call
Solution: Link with OpenMP library:
# Recompile with explicit OpenMP flag
cd DFTB/extensions/
make clean
F2PY_OPTIONS="--f90flags='-fopenmp' -lgomp" make
Performance Issues
Slow calculations despite compilation
Check OpenMP is enabled:
# Should show your thread count echo $OMP_NUM_THREADS
Verify parallel regions in code:
nm DFTB/extensions/tddftb.so | grep -i omp
Profile with different thread counts:
for i in 1 2 4 8; do export OMP_NUM_THREADS=$i echo "Threads: $i" time python3 your_calculation.py done
Platform-Specific Notes
Linux (Intel MKL)
For maximum performance on Intel CPUs with MKL:
# Load Intel MKL
source /opt/intel/mkl/bin/mklvars.sh intel64
# Compile with Intel compilers
cd DFTB/extensions/
sed -i 's/SYS=GNU/SYS=INTEL/' Makefile
make clean
make
# Set MKL threads
export MKL_NUM_THREADS=4
macOS (Apple Silicon)
For M1/M2/M3 Macs:
# Install Homebrew GCC (not Apple's gcc)
brew install gcc
# Use Homebrew's gfortran
cd DFTB/extensions/
make clean
FC=gfortran-13 make # Version may vary
Windows (WSL)
Use Windows Subsystem for Linux (WSL2):
# In WSL Ubuntu
sudo apt-get update
sudo apt-get install gfortran libblas-dev liblapack-dev
# Then follow Linux instructions
cd DFTB/extensions/
make
HPC Clusters
On SLURM-based clusters:
#!/bin/bash
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=8
#SBATCH --time=00:30:00
# Load modules
module load python/3.12
module load gcc/11.3.0
module load openblas
# Compile
cd $SLURM_SUBMIT_DIR/DFTB/extensions/
make clean
make
# Set threads
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
Testing Compilation
Quick Test Suite
#!/usr/bin/env python3
"""Test all compiled extensions"""
import sys
def test_core_extensions():
"""Test core extensions"""
print("Testing core extensions...")
try:
from DFTB.extensions import thomson, tddftb, mulliken, slako, grad, cosmo
print(" ✓ All core extensions loaded")
return True
except ImportError as e:
print(f" ✗ Core extension import failed: {e}")
return False
def test_forcefield():
"""Test force field extension"""
print("Testing force field extension...")
try:
from DFTB.ForceField import ff
print(" ✓ Force field extension loaded")
return True
except ImportError as e:
print(f" ✗ Force field import failed: {e}")
return False
def test_multiple_scattering():
"""Test multiple scattering extensions"""
print("Testing multiple scattering extensions...")
try:
from DFTB.MultipleScattering import (
Wigner3j, coul90, mod_bessel, sphharm,
cms, ms, photo, numerov
)
print(" ✓ All multiple scattering extensions loaded")
return True
except ImportError as e:
print(f" ✗ Multiple scattering import failed: {e}")
return False
if __name__ == "__main__":
print("DFTBaby Fortran Extensions Test")
print("=" * 40)
results = []
results.append(test_core_extensions())
results.append(test_forcefield())
results.append(test_multiple_scattering())
print("=" * 40)
if all(results):
print("SUCCESS: All extensions working!")
sys.exit(0)
else:
print("FAILURE: Some extensions failed")
sys.exit(1)
Save as test_extensions.py and run:
python3 test_extensions.py
Performance Benchmarking
Simple benchmark for parallelization:
#!/usr/bin/env python3
"""Benchmark OpenMP performance"""
import time
import numpy as np
from DFTB.extensions import tddftb
def benchmark(threads):
"""Run benchmark with specified thread count"""
import os
os.environ['OMP_NUM_THREADS'] = str(threads)
# Create test data
n = 1000
A = np.random.rand(n, n)
B = np.random.rand(n, n)
# Time matrix operation
start = time.time()
C = np.dot(A, B)
elapsed = time.time() - start
return elapsed
print("OpenMP Performance Benchmark")
print("Threads | Time (s) | Speedup")
print("-" * 35)
baseline = None
for threads in [1, 2, 4, 8]:
t = benchmark(threads)
if baseline is None:
baseline = t
speedup = baseline / t
print(f" {threads:2d} | {t:7.3f} | {speedup:6.2f}x")
NumPy 2.0 Migration Issues
IMPORTANT: If you experience compilation errors, especially after upgrading from NumPy 1.x to 2.0+, see the comprehensive troubleshooting guide:
➜ :doc:`compilation_fixes`
This includes:
NumPy 2.0 breaking changes (removed
-fexternal-blas,numpy.distutils)Fixed Makefile changes
Common error messages and solutions
Verified working configurations
Step-by-step migration checklist
Further Information
Makefile details: Check comments in each
Makefilef2py documentation: https://numpy.org/doc/stable/f2py/
OpenMP tuning: https://www.openmp.org/
Compiler options:
gfortran --helporifort --help
For compilation issues, check:
Python version:
python3 --versionNumPy version:
python3 -c "import numpy; print(numpy.__version__)f2py availability:
python3 -m numpy.f2py --helpCompiler version:
gfortran --versionLibrary paths:
ldconfig -p | grep -E "(blas|lapack)"