Everyone who deals with CP2K applications faces the problem of their compilation which appears to be rather challenging. Several available guides propose different compilation instructions but the choice of the best one is not evident. Here we provide a guide that would allow you to develop your own CP2K build protocol.

The building process consists of the following steps:

  • Compiling required libraries

CP2K uses a great amount of different libraries. It can use linear algebra, fourier transform libraries as well as libraries of exchange-correlation functional and libraries of molecular integrals.

  • Making an appropriate arch-file

To be sure that all environmental variables are set up in the unique way, developers use a special file (ARCH-file) that accumulates all the information about compiler flags, MPI libraries, link flags, etc.

  • Compiling the application

Application is compiled using ARCH-file in different regimes.

  • Running the application

At this stage you should make sure that all the dynamic libraries are linked correctly.

Now let us get into the details.

Before you begin..

.. you should retain the following basic principles:

  1. Never install several packages to the same path (e.g. /usr/local). If you next need to remove some package it will be impossible without source code distributive. Always specify prefix for every library (—prefix=/usr/local/mylib-110/)
  2. Your distributive or library should be linked properly. If all the libraries are resolved by ldd then it is OK. If not, do not forget to append the LD_LIBRARY_PATH variable in the command line.
  3. Be sure that all the libraries are compiled in the same environment, i.e. you use the same same MKL library and fortran and C compilers.
  4. If you recompile something do make clean or make realclean after changing the environment.

Compiling required libraries

Certain libraries require some specific tips to be compiled properly.

1. FFTW

If you want to use fftw library for performing Fourier transforms, explore these flags when configure:

./configure --prefix=/usr/local/fftw-334/ --enable-openmp \
            --enable-threads --enable-sse2 --enable-shared

However, we would recommend you to use Intel MKL library instead of fftw since mkl operates simultaneously both with linear algebra and Fourier transforms.

2. openmpi

While compiling openmpi keep in mind the two main points: (i) compile openmpi with the same compiler as you should use for cp2k and (ii) use —enable-mpi-thread-multiple flag if you want to perform psmp build (see below).

3. libxc

CP2K uses libxc for computing DFT and thus it is appropriate to link this library. Building of cp2k with libxc-2.0.2 or libxc-2.2.0 versions requires the use of the only one specific flag in configure (—enable-shared).

4. libint

Libint library computes molecular integrals. Only the 1.1.4 version of libint can be safely used. Maximum angular momentum level for the Gaussian basis functions in the electron repulsion integrals (libint-max-am) should be set. Here is an example of the configure line:

./configure --prefix=/usr/local/libint-114/ \
     --with-libint-max-am=5 --with-libderiv-max-am1=4 \
     --enable-shared --with-cc=icc --with-cxx=icc --with-ar=ar

Making an appropriate arch-file

There are four types of arch-files: SOPT, SSMP, POPT, PSMS. First letters correspond to «Sequential» or «Parallel» in terms of MPI threads respectively. «OPT» and «SMP» reflect absence or presence of sub-threading by OpenMP respectively. SOPT is an absolutely sequential program. PSMP is threaded by MPI and each MPI thread is threaded by OpenMP.

Let us consider the example of POPT arch-file. First, we determine path variables that will be used by compiler and by linker flags:

MKL_ROOT  = ${MKLROOT}
MKL_LIB = $(MKL_ROOT)/lib/intel64
MKL_INCLUDE = $(MKL_ROOT)/include

XC_LIB = $(HOME)/local/libxc-220/lib
XC_INC = $(HOME)/local/libxc-220/include

LI_LIB = $(HOME)/local/libint-114/lib
LI_INC = $(HOME)/local/libint-114/include

Next, we determine compiler, linker, preprocessor etc. programs:

CC       = icc
CPP      =
FC       = mpif90
LD       = mpif90 -lstdc++
AR       = xiar -r

C code linker (LD)  will probably require -lstdc++ flag, which links to the standard C++ libraries. For compilation with CUDA you should also define NVCC variable.

The most important settings of CP2K build are DFLAGS variables. They can be set as follows:

DFLAGS   = -D__INTEL -D__FFTSG -D__FFTW3 -D__parallel \
           -D__BLACS -D__SCALAPACK -D__LIBINT -D__LIBXC2 -D__MKL

INTEL is necessary to specify compilation with Intel compiler (here mpif90 is IFC). FFTSG and FFTW flags turn on building the code for corresponding Fourier libraries (FFTSG is a built-in library). parallel turns on the code for MPI version of CP2K. BLACS and SCALAPACK declare the use of the corresponding linear algebra interfaces. MKL flag informs CP2K that MKL implementation of math libraries and interfaces will be used (FFTW, BLACS and SCALAPACK in our case). Finally, LIBINT and LIBXC flags announce using of the corresponding molecular integrals and density functional libraries.

Fortran compiler flags should be set up for proper compiling:

FCFLAGS  = $(DFLAGS) -I$(MKL_INCLUDE)/fftw -I$(LI_INC) -I$(XC_INC) \
           -O2 -msse2 -heap-arrays 64 -funroll-loops -fpp -free

Here DFLAGS is copied to FCFLAGS and then we declare three include directories. In our case, FFTW include directory is FFTW interface of MKL but the folder can differ for other MKL versions. LI_INC and XC_INC were defined above. Next, we give compiler optimization flags (-O2-free). Their choice depends on your taste and on the compiler type.

Next two lines define C prepocessor flags (empty) and fortran linker flags:

CPPFLAGS =
LLDFLAGS  = $(FCFLAGS)

Fortran compiler flags are transferred to fortran linker flags to give the same optimization flags. Included directories will not be processed by fotran linker.

The most complicated arch-file settings are libraries. Libraries can be linked statically (.a) or dynamically (-lname):

LIBS     = -L$(MKL_LIB) -L$(LI_LIB) -L$(XC_LIB) -lmkl_blas95_lp64 -lmkl_lapack95_lp64 \
            ${MKL_LIB}/libmkl_scalapack_lp64.a ${MKL_LIB}/libmkl_intel_lp64.a \
           -Wl,--start-group \
              ${MKL_LIB}/libmkl_intel_lp64.a \
              ${MKL_ROOT}/interfaces/fftw3xf/libfftw3xf_intel.a \
              ${MKL_LIB}/libmkl_sequential.a \
              ${MKL_LIB}/libmkl_core.a \
              ${MKL_LIB}/libmkl_blacs_openmpi_lp64.a \
           -Wl,--end-group -lpthread \
           -lderiv -lint -lxc -lxcf90

First, we define library directories for dynamic linking (-LDIRPATH). Here we use predefined library pathes MKL_LIB, LI_LIB and XC_LIB. According to the dynamic link syntax we have: -lint means that in -L library paths there is file libint.so. -lderiv and -lint are libraries of libint-lxc and -lxcf90 declare access to libxc library. Note that some versions of libxc are linked as two libraries (fortran module is separated) and other versions (e.g. 2.0.2) use only -lxc.

Linking of MKL libraries is alchemical but there exists a special Intel-made tool that can prepare LIBS line for your MKL version: http://software.intel.com/en-us/articles/intel-mkl-link-line-advisor. Pay attention to the path of libfftw3xf_intel.a that can lay in other folder than libmkl_core.a.

You need  this line to compile a compiler-specific object:

OBJECTS_ARCHITECTURE = machine_intel.o

Because of unknown reason graphcon object requires less intensive optimization. It is implemented by the following lines:

FCFLAGS2 = $(DFLAGS) -I$(LI_INC) -I$(XC_INC) -O1 -msse2 -heap-arrays 64 -fpp -free
graphcon.o: graphcon.F
        $(FC) -c $(FCFLAGS2) $<

Compiling and running the application

Arch-file should be saved to arch directory (e.g. ./arch/myarch.popt). Then you can go to makefiles directory and do make:

make -j 20 ARCH=myarch VERSION=popt realclean
make -j 20 ARCH=myarch VERSION=popt

The argument -j 20 means that building process will try to use 20 processors of your computer. In ./exe/ directory the myarch folder with corresponding distributive will appear after make. Before run make sure that e.g. libxc and libint libraries (and other libraries linked dynamically) are in your LD_LIBRARY_PATH. If not do the following:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/_scratch/local/libint-114/lib:~/_scratch/local/libxc-220/lib

Here we append LD_LIBRARY_PATH to our libraries, the colon is used as path separator.