Sunday, March 8, 2026

The Horrors of Compiling CP2K

CP2K is one of the most well-established quantum chemistry programs that is free and open-source. I feel like the actual installation instructions in the manual [Link: https://manual.cp2k.org/trunk/getting-started/build-from-source.html] seems extremely technical and for someone that just wants a CP2K binary, too detailed. 

Here's my summary of how I got CP2K up and running.

1. You don't need to download the libraries separately.

It took me a while to figure this out, but you don't need to. CP2K already provides a script that can set up and download, make and install the dependencies for you. It was actually ChatGPT that suggested me this because the official manual seems to not make a reference to this. You do find the README.md in cp2k/tools/toolchain/README.md, but as someone who just started working with this software, I was not really familiar with the source tree.

CP2K has a lot of dependencies but the ones you need to work with are:

Library Role
openBLAS linear algebra operations
fftw fast fourier transforms
libxsmm fast matrix operations
libint one and two electron-integrals
libxc exchange-correlation functionals
spglib handling symmetries in crystal structures
elpa fast eigenvalue solver
openmpi multiprocessing

I do not have CUDA enabled since I will be running this on a pure CPU cluster (ouch, but alright).

2. Install gcc, g++, gfortran and OpenMPI

Goes without saying you'll need compilers. You must have gcc-13 (more on this later)

Download OpenMPI from: https://www.open-mpi.org/software/ompi/v5.0/

I went with OpenMPI 4.1, even though it is outdated (but still supported) as of writing this, but mostly because there have been reports of CP2K showing poor performance with OpenMPI 5. (See this discussion: https://github.com/cp2k/cp2k/issues/3980, I'm not sure if this applies to just the specific OpenMPI 5.0.3, but anyways).

Once you have downloaded the OpenMPI source, as follows:

cd openmpi-4.1.8/

Then, ensure that the place you want to place the OpenMPI library exists as a directory. I put it in my local library directory, i.e.:

mkdir -p \$HOME/.local/lib/openmpi4

Then running the OpenMPI configure script,

./configure --prefix=\$HOME/.local/lib/openmpi4 CC=gcc CXX=g++ FC=gfortran

Once this command completes, compile and install, and don't forget to use all your processors (otherwise it will be slow!)

make -j\$(nproc)

make install

Now OpenMPI is where you want it to be. But for programs and configure scripts to see it, you have to export MPI_HOME and add the MPI directory to your PATH so that mpicc, mpic++ et al., are available. We have the following pair of commands:

export MPI_HOME=\$HOME/.local/lib/openmpi4/

export PATH=\$MPI_HOME/bin:$PATH

OpenMPI is now set up. Let's head to cp2k/tools/toolchain and begin the set up for compiling CP2K.

cd cp2k-2026.1/tools/toolchain
./install_cp2k_toolchain.sh --with-openblas --with-fftw --with-libxsmm --with-libint --with-libxc --with-spglib --with-elpa --mpi-mode=openmpi --enable-cuda=no

3a. Troubleshooting GCC-15 for CP2K 

(skip to the 3b. section if you just want to go ahead with the installation, this is for posterity)

Everything was going good until I got this error while the compilation of COSTA:

[ 37%] Building CXX object src/costa/CMakeFiles/costa.dir/layout.cpp.o
In file included from /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/bu
ild/COSTA-2.2.2/src/costa/grid2grid/grid_layout.hpp:4,
                from /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/bu
ild/COSTA-2.2.2/src/costa/layout.hpp:2,
                from /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/bu
ild/COSTA-2.2.2/src/costa/layout.cpp:1:
/home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/build/COSTA-2.2.2/src/co
sta/grid2grid/mpi_type_wrapper.hpp:68:25: error: ‘uint32_t’ was not declared in
this scope
  68 | struct mpi_type_wrapper<uint32_t> {
     |                         ^~~~~~~~
/home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/build/COSTA-2.2.2/src/co
sta/grid2grid/mpi_type_wrapper.hpp:4:1: note: ‘uint32_t’ is defined in header ‘<cstdint>’; this is probably fixable by adding ‘#include <cstdint>’

Ah, someone forgot to include <cstdint>. It seemed to have worked with gcc-12, or gcc-13, but the system I am running on gcc-15 (Leap 16.0), this does not work. 

Now, I could fall back to gcc-12 or gcc-13, but I don't want to. You might think that just editing mpi_type_wrapper.hpp and adding an "#include <cstdint>" might be enough but that's not the case. The script extracts the .tar.gz file every time it starts the build. So we have to modify that, remove the tar, and rearchive the directory to fool it. From cp2k-2026.1/tools/toolchain: 

code build/COSTA-2.2.2/src/costa/grid2grid/mpi_type_wrapper.hpp

Add in the line:

 #include <cstdint>

Right after "#include <mpi.h>", and then after closing code: 

cd build/

rm COSTA-v2.2.2.tar.gz
tar czf COSTA-v2.2.2.tar.gz COSTA-2.2.2

It worked! But then, ELPA threw a massive error log. 

../src/elpa2/kernels/complex_128bit_256bit_512bit_BLOCK_template.c:51:47: note:
in definition of macro 'CONCAT2_8ARGS'
  51 | #define CONCAT2_8ARGS(a, b, c, d, e, f, g, h) a ## b ## c ## d ## e ## f
## g ## h
     |    
../src/elpa2/kernels/complex_128bit_256bit_512bit_BLOCK_template.c:1872:27: note
: in expansion of macro 'CONCAT_8ARGS'
1872 | static __forceinline void CONCAT_8ARGS(hh_trafo_complex_kernel_,ROW_LENG
TH,_,SIMD_SET,_,BLOCK,hv_,WORD_LENGTH) (DATA_TYPE_PTR q, DATA_TYPE_PTR hh, int n
b, int ldq
     |                           ^~~~~~~~~~~~
make[1]: Leaving directory '/home/sgautam/projects/cp2k/cp2k2026.1/tools/toolchain/build/elpa-2024.05.001/build_cpu'
make: *** [Makefile:75802: all] Error 2
     |                                   1
Error: Invalid character in name at (1)
./src/fortran_constants.F90:164:35:

 164 |  integer(kind=C_INT), parameter ::
     |         

3b. Installing and configuring GCC-13 

I finally bit the bullet and installed gcc13. 

sudo zypper install gcc13 gcc13-c++ gcc13-fortran

To use gcc-13 and not the system's gcc, create a directory called gcc13 (I did so in my \$HOME/.local/bin/gcc-13) and then create a symlink to gcc-13:

ln -s /usr/bin/gcc-13 \$HOME/.local/bin/gcc-13/gcc

ln -s /usr/bin/g++-13 \$HOME/.local/bin/gcc-13/g++

ln -s /usr/bin/gfortran-13 \$HOME/.local/bin/gcc-13/gfortran

Then export it to PATH before others:

export PATH=\$HOME/.local/bin/gcc-13/:$PATH

Now, when I do gcc --version, I get:

gcc (SUSE Linux) 13.4.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Good. Let's remove the build/ and install/ directories and run the script again. 

So...it should work right? Well, it turns out I'd to recompile OpenMPI as well with gcc-13, and then guess what happened?

../src/elpa2/kernels/complex_128bit_256bit_512bit_BLOCK_template.c:51:47: note:
in definition of macro 'CONCAT2_8ARGS'
  51 | #define CONCAT2_8ARGS(a, b, c, d, e, f, g, h) a ## b ## c ## d ## e ## f
## g ## h
     |    
../src/elpa2/kernels/complex_128bit_256bit_512bit_BLOCK_template.c:1872:27: note
: in expansion of macro 'CONCAT_8ARGS'
1872 | static __forceinline void CONCAT_8ARGS(hh_trafo_complex_kernel_,ROW_LENG
TH,_,SIMD_SET,_,BLOCK,hv_,WORD_LENGTH) (DATA_TYPE_PTR q, DATA_TYPE_PTR hh, int n
b, int ldq
     |                           ^~~~~~~~~~~~
make[1]: Leaving directory '/home/sgautam/projects/cp2k/cp2k2026.1/tools/toolchain/build/elpa-2024.05.001/build_cpu'
make: *** [Makefile:75802: all] Error 2
     |                                   1
Error: Invalid character in name at (1)
./src/fortran_constants.F90:164:35:

 164 |  integer(kind=C_INT), parameter ::
     |         

4. Fixing the Issue -- It's the Preprocessor Dummy!

The same error as before. Wow, so gcc version was never an issue.

Well, after enough soul searching and ChatGPT'ing, and Gemini'ing, and DeepSeeking (oh my God) it seems like this is a problem with the gfortran preprocessor. Since I've no idea how Fortran works, I can't comment, but this is what fixed it:

  • Going to cp2k-2026.1/tools/toolchain/scripts/stage5/install_elpa.sh
  • At line 113: CPP="cpp -E" \, changing this to: CPP="cpp -E -P \"
  • I don't know what the -P flag does, but looking it up, it has something to do with adding #line directives, which I'm guessing are invalid characters in Fortran.
I don't know if I'm doing something wrong, but this fixed it and I was greeted with the beautiful message I'd expected to see some 8 hours ago:

========================== usage =========================
Done!
To use the installed tools and libraries and cp2k version
compiled with it you will first need to execute at the prompt:
 source /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/install/setup

If you invoked the toolchain with --install-all then you can proceed to build cp2k like this:
 cd cp2k/
 cmake -S . -B build -DCP2K_USE_EVERYTHING=ON -DCP2K_USE_DLAF=OFF -DCP2K_USE_PEXSI=OFF
 cmake --build build -j 32

If you installed only some packages then you'll have to assemble the matching cmake command yourself.
For available build options see: https://manual.cp2k.org/trunk/getting-started/build-from-source.html

Whew! The nightmare is over...or is it?  

5. Compiling CP2K

Made a script called "cp2k_prepare_compile.sh" so you don't have worry about anything else:

# Export environment variables for MPI and GCC-13
export MPI_HOME=$HOME/.local/lib/openmpi4/
export PATH=$MPI_HOME/bin:$PATH
export PATH=$HOME/.local/bin/gcc-13:$PATH

# Execute source for the toolchain
source ./tools/toolchain/install/setup

mkdir build/
cmake -S . -B build \
   -GNinja \
   -DCP2K_USE_MPI=ON \
   -DCP2K_USE_LIBXC=ON \
   -DCP2K_USE_LIBINT2=ON \
   -DCP2K_USE_SPGLIB=ON \
   -DCP2K_USE_ELPA=ON \
   -DCP2K_USE_SPLA=ON \
   -DCP2K_USE_SIRIUS=ON \
   -DCP2K_USE_COSMA=ON \

echo "CP2K is ready to compile!"
echo "Run \`cmake --build build -j\$(nproc)\` to start the compilation process."

Run it as, 

. ./cp2k_compile_prepare.sh

Then run,

cmake --build build -j\$(nproc) 

That's it!

Now, we install with:

cmake --install ./build/ --prefix=$HOME/.local/

To run, we add the following to LD_LIBRARY_PATH (at least in my case, its /home/sgautam/.local/lib64/), via:

export LD_LIBRARY_PATH="/home/sgautam/.local/lib64:$LD_LIBRARY_PATH" 

Add this to your .bashrc. Now simply run, 

mpirun -np 1 cp2k.psmp --version

Here's what I am greeted with:

--------------------------------------------------------------------------
[[60762,1],0]: A high-performance Open MPI point-to-point messaging module
was unable to find any relevant network interfaces:

Module: OpenFabrics (openib)
 Host: padme

Another transport will be used instead, although this may result in
lower performance.

NOTE: You can disable this warning by setting the MCA parameter
btl_base_warn_component_unused to 0.
--------------------------------------------------------------------------
CP2K version 2026.1
Source code revision git:5e54ba2
cp2kflags: omp libint libxc elpa parallel scalapack cosma spglib sirius
compiler: GCC version 13.4.0
compiler options:
  -I /home/sgautam/projects/cp2k/cp2k-2026.1/build/src/start -I /home/
  sgautam/projects/cp2k/cp2k-2026.1/src -I /home/sgautam/projects/cp2k
  /cp2k-2026.1/build/src -I /home/sgautam/projects/cp2k/cp2k-2026.1/sr
  c/base -I /home/sgautam/projects/cp2k/cp2k-2026.1/src/common -I /hom
  e/sgautam/projects/cp2k/cp2k-2026.1/src/motion -I /home/sgautam/proj
  ects/cp2k/cp2k-2026.1/src/dbm -I /home/sgautam/projects/cp2k/cp2k-20
  26.1/build/src/mod_files -I /home/sgautam/projects/cp2k/cp2k-2026.1/
  tools/toolchain/install/SpFFT-1.1.1/include -I /home/sgautam/project
  s/cp2k/cp2k-2026.1/tools/toolchain/install/pugixml-1.15/include -I /
  home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/install/libvd
  wxc-0.4.0/include -I /home/sgautam/projects/cp2k/cp2k-2026.1/tools/t
  oolchain/install/hdf5-1.14.6/include -I /home/sgautam/projects/cp2k/
  cp2k-2026.1/tools/toolchain/install/gsl-2.8/include -I /home/sgautam
  /projects/cp2k/cp2k-2026.1/tools/toolchain/install/fftw-3.3.10/inclu
  de -I /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/instal
  l/dbcsr-2.9.0/include -I /home/sgautam/projects/cp2k/cp2k-2026.1/too
  ls/toolchain/install/sirius-7.7.1/include/sirius -I /home/sgautam/pr
  ojects/cp2k/cp2k-2026.1/tools/toolchain/install/SpLA-1.6.1/include/s
  pla -I /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/insta
  ll/spglib-2.5.0/include -I /home/sgautam/projects/cp2k/cp2k-2026.1/t
  ools/toolchain/install/COSMA-2.7.0/include -I /home/sgautam/projects
  /cp2k/cp2k-2026.1/tools/toolchain/install/libxc-7.0.0/include -I /ho
  me/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/install/openbla
  s-0.3.30/include -I /home/sgautam/projects/cp2k/cp2k-2026.1/tools/to
  olchain/install/elpa-2024.05.001/cpu/include/elpa_openmp-2024.05.001
   -I /home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/install/
  elpa-2024.05.001/cpu/include/elpa_openmp-2024.05.001/modules -I /hom
  e/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/install/SpLA-1.6
  .1/include -I /home/sgautam/.local/lib/openmpi4/include -I /home/sga
  utam/.local/lib/openmpi4/lib64 -I /home/sgautam/projects/cp2k/cp2k-2
  026.1/tools/toolchain/install/libint-v2.6.0-cp2k-lmax-5/include -I /
  home/sgautam/projects/cp2k/cp2k-2026.1/tools/toolchain/install/libin
  t-v2.6.0-cp2k-lmax-5/include/libint2 -march=alderlake -mmmx -mpopcnt
   -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -mavx2 -mno-sse
  4a -mno-fma4 -mno-xop -mfma -mno-avx512f -mbmi -mbmi2 -maes -mpclmul
   -mno-avx512vl -mno-avx512bw -mno-avx512dq -mno-avx512cd -mno-avx512
  er -mno-avx512pf -mno-avx512vbmi -mno-avx512ifma -mno-avx5124vnniw -
  mno-avx5124fmaps -mno-avx512vpopcntdq -mno-avx512vbmi2 -mgfni -mvpcl
  mulqdq -mno-avx512vnni -mno-avx512bitalg -mno-avx512bf16 -mno-avx512
  vp2intersect -mno-3dnow -madx -mabm -mno-cldemote -mclflushopt -mclw
  b -mno-clzero -mcx16 -mno-enqcmd -mf16c -mfsgsbase -mfxsr -mno-hle -
  msahf -mno-lwp -mlzcnt -mmovbe -mmovdir64b -mmovdiri -mno-mwaitx -mp
  config -mpku -mno-prefetchwt1 -mprfchw -mptwrite -mrdpid -mrdrnd -mr
  dseed -mno-rtm -mserialize -mno-sgx -msha -mshstk -mno-tbm -mno-tsxl
  dtrk -mvaes -mwaitpkg -mno-wbnoinvd -mxsave -mxsavec -mxsaveopt -mxs
  aves -mno-amx-tile -mno-amx-int8 -mno-amx-bf16 -mno-uintr -mhreset -
  mno-kl -mno-widekl -mavxvnni -mno-avx512fp16 -mno-avxifma -mno-avxvn
  niint8 -mno-avxneconvert -mno-cmpccxadd -mno-amx-fp16 -mno-prefetchi
   -mno-raoint -mno-amx-complex --param=l1-cache-size=32 --param=l1-ca
  che-line-size=64 --param=l2-cache-size=24576 -mtune=alderlake -g -O3
   -O3 -Wno-deprecated-declarations -Wno-maybe-uninitialized -Wuniniti
  alized -Wuse-without-only -std=f2008 -fPIE -ffree-form -fimplicit-no
  ne -fno-omit-frame-pointer -fbacktrace -fallow-argument-mismatch -fu
  nroll-loops -fopenmp -fpreprocessed -J src -fpre-include=/usr/includ
  e/finclude/math-vector-fortran.h

Woo-Hoo! At last!

6. Doing Regression Tests

In the cp2k-2026.1/tests/ directory you'll find many tests to check the sanity of the program. Simply run with:

./do_regtest.py \$HOME/.local/bin/ psmp

This is in my case as my install directory is \$HOME/.local/bin and the binary is cp2k.psmp. The tests will take time so be patient.

Now, to do the chemistry...! 

Friday, March 6, 2026

The Hellman-Feynman Theorem And Its Consequences

Computational chemistry takes up an egregious amount of compute power of human civilization. Estimates show that it uses anywhere from 30% to 50%[1] of our compute power. Why, one might ask? What is it that makes quantum chemistry such a computationally "hard" problem? And why are so many computers running these quantum chemistry programs? 

The applications are vast. First principles study of industrial processes, drug design and discovery, catalyst design, even simulation of biological systems can rely on quantum chemical calculations.

For the most part, the goal of a quantum chemical calculation is as follows: given a configuration of atoms (or more appropriately nuclei), output the multi-electron wave function and the electronic energy. It just so happens that electron wave functions follow the Schrodinger Equation, and the SE for a 100 or so electrons (like in a typical molecule) is impossible to solve exactly; the problem was of such great importance than the people who came up with the theory to allow for an estimated (but still useful) solution won the Nobel Prize for Chemistry.[2]

One of the most common tasks in quantum chemistry is called structure optimization. Suppose you create a water molecule in a molecular editor. You place two hydrogen atoms near an oxygen atom and connect them. Is this water? The formula is ($H_{2}O$), but real molecules do not exist in arbitrary shapes. The O–H bond length and the H–O–H bond angle have specific equilibrium values that arise from the underlying quantum mechanics of the electrons and nuclei.

For water, the O–H bond length is about 96 picometers, and the H–O–H bond angle is about 104.5°. In reality, the molecule vibrates around these values due to thermal motion and quantum zero-point energy, but the equilibrium geometry is close to these numbers.

If you want to simulate a reaction involving water, it is best to begin with this equilibrium configuration. You could manually set bond lengths and angles in your molecular editor. But imagine, a molecule with 50 or so atoms, or a biomolecule with a 1000 or so atoms, this would get ugly rather quickly! 

[unfinished post]

[1] Machine Learning the Computational Cost of Quantum Chemistry, Heinen et al (2020)
[2] Walter Kohn and Arthur Sham

The Horrors of Compiling CP2K

CP2K is one of the most well-established quantum chemistry programs that is free and open-source. I feel like the actual installation instru...