├── molecules ├── co.in ├── ar.in ├── he.in ├── ne.in ├── be.in ├── lih.in ├── h2.in ├── n2.in ├── ch4.in ├── h2o.in ├── ethane.in └── benzene.in ├── scripts ├── test_be.py ├── test_he.py ├── test_n2.py ├── test_li.py ├── test_h2o.py ├── test_h2.py └── test_ethane.py ├── .editorconfig ├── .gitignore ├── .github └── workflows │ └── build.yml ├── README.md └── src ├── quadrature.cpp ├── bragg.h ├── config.h ├── pngfuncs.h ├── config.h.in ├── spherical_harmonics.h ├── rectangulargrid.h ├── functionals.h ├── dftcxx.cpp ├── cspline.h ├── rectangulargrid.cpp ├── spherical_harmonics.cpp ├── CMakeLists.txt ├── gridpoint.cpp ├── gamma.h ├── pngfuncs.cpp ├── settings.h ├── functionals.cpp ├── settings.cpp ├── cspline.cpp ├── molecule.h ├── moleculargrid.h ├── cgf.cpp ├── dft.h ├── gridpoint.h ├── gamma.cpp ├── cgf.h ├── atomicgrid.h ├── molecule.cpp ├── integrals.h ├── moleculargrid.cpp └── dft.cpp /molecules/co.in: -------------------------------------------------------------------------------- 1 | name = carbon monoxide 2 | basis = sto3g 3 | units = bohr 4 | 5 | system: 6 | 2 7 | C 0 0 0 8 | O 0 0 2.116 9 | -------------------------------------------------------------------------------- /molecules/ar.in: -------------------------------------------------------------------------------- 1 | name = Argon atom 2 | basis = sto3g 3 | units = angstrom 4 | 5 | system: 6 | 1 7 | Ar 0.000000 0.000000 0.000000 8 | -------------------------------------------------------------------------------- /molecules/he.in: -------------------------------------------------------------------------------- 1 | name = Helium atom 2 | basis = sto3g 3 | units = angstrom 4 | 5 | system: 6 | 1 7 | He 0.000000 0.000000 0.000000 8 | -------------------------------------------------------------------------------- /molecules/ne.in: -------------------------------------------------------------------------------- 1 | name = neon atom 2 | basis = sto3g 3 | units = angstrom 4 | 5 | system: 6 | 1 7 | Ne 0.000000 0.000000 0.000000 8 | -------------------------------------------------------------------------------- /molecules/be.in: -------------------------------------------------------------------------------- 1 | name = Beryllium atom 2 | basis = sto3g 3 | units = angstrom 4 | 5 | system: 6 | 1 7 | Be 0.000000 0.000000 0.000000 8 | -------------------------------------------------------------------------------- /molecules/lih.in: -------------------------------------------------------------------------------- 1 | name = lithium hydride molecule 2 | basis = sto3g 3 | units = bohr 4 | 5 | system: 6 | 2 7 | Li 0.000000 0.000000 0.403635 8 | H 0.000000 0.000000 -1.210905 9 | -------------------------------------------------------------------------------- /molecules/h2.in: -------------------------------------------------------------------------------- 1 | name = hydrogen molecule 2 | basis = sto3g 3 | units = angstrom 4 | grid = ultrafine 5 | 6 | system: 7 | 2 8 | H 0 0 -.36700000000000000000 9 | H 0 0 .36700000000000000000 10 | -------------------------------------------------------------------------------- /molecules/n2.in: -------------------------------------------------------------------------------- 1 | name = nitrogen molecule 2 | basis = p631 3 | units = angstrom 4 | 5 | system: 6 | 2 7 | N 0.000000 0.000000 0.000000 8 | N 0.000000 0.000000 1.097600 9 | -------------------------------------------------------------------------------- /scripts/test_be.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | be = Molecule('be', [(4,(0,0,0))], units="Angstrom") 7 | en,orbe,orbs = dft(be, functional="LDA", basis="sto-3g") 8 | -------------------------------------------------------------------------------- /scripts/test_he.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | he = Molecule('he', [(2,(0,0,0))], units="Angstrom") 7 | en,orbe,orbs = dft(he, functional="LDA", basis="sto-3g") 8 | -------------------------------------------------------------------------------- /molecules/ch4.in: -------------------------------------------------------------------------------- 1 | name = methane 2 | basis = sto6g 3 | units = bohr 4 | 5 | system: 6 | 5 7 | C -0.213 0.154 0.000 8 | H -0.213 2.304 0.000 9 | H 1.814 -0.563 0.000 10 | H -1.226 -0.563 1.755 11 | H -1.226 -0.563 -1.755 12 | -------------------------------------------------------------------------------- /molecules/h2o.in: -------------------------------------------------------------------------------- 1 | name = water molecule 2 | basis = p631 3 | units = bohr 4 | hartree_evaluation = becke_grid 5 | 6 | system: 7 | 3 8 | O 0.0000 0.0000 0.0000 9 | H 0.7570 0.5860 0.0000 10 | H -0.757 0.5860 0.0000 11 | -------------------------------------------------------------------------------- /scripts/test_n2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | n2 = Molecule('n2', [(7,(0,0,0)),(7,(0,0,1.097600))], units="Angstrom") 7 | en,orbe,orbs = dft(n2, functional="LDA", basis="sto-3g") 8 | -------------------------------------------------------------------------------- /scripts/test_li.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | lih = Molecule('LiH', [(1,(0,0,-1.210905)), (3,(0,0,0.403635))], units="Bohr") 7 | en,orbe,orbs = dft(lih, functional="LDA", basis="sto-3g") 8 | -------------------------------------------------------------------------------- /scripts/test_h2o.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | h2o = Molecule('h2o', [(1,(0.7570,0.5860,0.0)),(1,(-0.757,0.5860,0.0)),(8,(0,0,0))], units="Bohr") 7 | en,orbe,orbs = dft(h2o, functional="LDA", basis="sto-3g") 8 | -------------------------------------------------------------------------------- /scripts/test_h2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | h2 = Molecule('h2', [(1,(0,0,-.36700000000000000000)),(1,(0,0,0.36700000000000000000))], units="Angstrom") 7 | en,orbe,orbs = dft(h2, functional="LDA", basis="sto-3g") 8 | -------------------------------------------------------------------------------- /molecules/ethane.in: -------------------------------------------------------------------------------- 1 | name = ethane 2 | basis = sto3g 3 | units = angstrom 4 | 5 | system: 6 | 8 7 | H 0.0998334 0.995004 -0.6 8 | H 0.911616 0.411044 1.6 9 | H 0.811782 -0.58396 -0.6 10 | H -0.0998334 -0.995004 1.6 11 | H -0.911616 -0.411044 -0.6 12 | H -0.811782 0.583961 1.6 13 | C 0 0 0 14 | C 0 0 1 15 | -------------------------------------------------------------------------------- /molecules/benzene.in: -------------------------------------------------------------------------------- 1 | name = benzene molecule 2 | basis = sto6g 3 | units = angstrom 4 | hartree_evaluation = becke_grid 5 | 6 | system: 7 | 12 8 | C 0.000 1.396 0.000 9 | C 1.209 0.698 0.000 10 | C 1.209 -0.698 0.000 11 | C 0.000 -1.396 0.000 12 | C -1.209 -0.698 0.000 13 | C -1.209 0.698 0.000 14 | H 0.000 2.479 0.000 15 | H 2.147 1.240 0.000 16 | H 2.147 -1.240 0.000 17 | H 0.000 -2.479 0.000 18 | H -2.147 -1.240 0.000 19 | H -2.147 1.240 0.000 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | indent_style = space 12 | indent_size = 4 13 | 14 | [Makefile] 15 | indent_style = tab 16 | end_of_line = lf 17 | insert_final_newline = true 18 | trim_trailing_whitespace = true 19 | indent_style = tab 20 | indent_size = 4 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Compiled Object files 3 | *.slo 4 | *.lo 5 | *.o 6 | *.obj 7 | 8 | # Precompiled Headers 9 | *.gch 10 | *.pch 11 | 12 | # Compiled Dynamic libraries 13 | *.so 14 | *.dylib 15 | *.dll 16 | 17 | # Fortran module files 18 | *.mod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | # povray 32 | *.pov 33 | *.png 34 | 35 | bin/dftcxx 36 | *.ply 37 | *.obj 38 | *.chg 39 | 40 | build/* 41 | pyquante.log 42 | -------------------------------------------------------------------------------- /scripts/test_ethane.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PyQuante import Molecule 4 | from PyQuante.dft import dft 5 | 6 | coord = [ 7 | (1,(0.0998334, 0.995004, -0.6)), 8 | (1,(0.911616, 0.411044, 1.6)), 9 | (1,(0.811782, -0.58396, -0.6)), 10 | (1,(-0.0998334, -0.995004, 1.6)), 11 | (1,(-0.911616, -0.411044, -0.6)), 12 | (1,(-0.811782, 0.583961, 1.6)), 13 | (6, (0, 0, 0)), 14 | (6, (0, 0, 1)) 15 | ] 16 | 17 | ethane = Molecule('ethane', coord, units="Angstrom") 18 | en,orbe,orbs = dft(ethane, functional="LDA", basis="sto-3g") 19 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ "master", "develop" ] 6 | pull_request: 7 | branches: [ "master", "develop" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Install dependencies 17 | run: sudo apt install -y build-essential cmake libboost-all-dev pkg-config libeigen3-dev libpng-dev libtclap-dev 18 | - name: Configure CMake 19 | run: mkdir build && cd build && cmake ../src 20 | - name: Build 21 | run: cd build && make -j3 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DFTCXX 2 | 3 | [![Build](https://github.com/ifilot/dftcxx/actions/workflows/build.yml/badge.svg)](https://github.com/ifilot/dftcxx/actions/workflows/build.yml) 4 | 5 | DFTCXX calculates the electronic structure of simple molecules within the 6 | framework of Density Functional Theory (DFT) at the LDA level of theory. It is 7 | mainly written for educational purposes. The source code has been documented 8 | (i.e. commented) relatively extensively to provide students the opportunity to 9 | read and understand the algorithm. 10 | 11 | > [!TIP] 12 | > * Want to know more about electronic structure calculations? Have a look at my 13 | > [free lecture book](https://ifilot.pages.tue.nl/elements-of-electronic-structure-theory/). 14 | > * Interested in a Python-based Density Functional Theory code? Have a look at [PyDFT](https://github.com/ifilot/pydft) 15 | 16 | ## Compilation 17 | 18 | DFTCXX depends on a couple of libraries, which are normally directly available by your favorite package manager. 19 | 20 | * [Boost](https://www.boost.org/) 21 | * [TCLAP](https://tclap.sourceforge.net/) 22 | * [Eigen3](https://eigen.tuxfamily.org/index.php?title=Main_Page) 23 | * [libPNG](http://www.libpng.org/pub/png/libpng.html) 24 | 25 | To ensure you have the right packages on a (Debian-type) of operating system, 26 | you can run the following 27 | 28 | ``` 29 | sudo apt install build-essential cmake libboost-all-dev pkg-config libeigen3-dev \ 30 | libpng-dev libtclap-dev 31 | ``` 32 | 33 | To compile the program: 34 | ``` 35 | mkdir build 36 | cd build 37 | cmake ../src 38 | make -j9 39 | ``` 40 | 41 | ## Execution 42 | ``` 43 | ./dftcxx -i ../molecules/h2.in 44 | ``` 45 | -------------------------------------------------------------------------------- /src/quadrature.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "quadrature.h" 23 | 24 | constexpr unsigned int Quadrature::num_lebedev_points[11]; 25 | constexpr double Quadrature::lebedev_coefficients[][4]; 26 | -------------------------------------------------------------------------------- /src/bragg.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _BRAGG_H 23 | #define _BRAGG_H 24 | 25 | static constexpr float bragg_radii[20] = 26 | { 27 | 0.35, 28 | 0.28, 29 | 1.28, 30 | 0.96, 31 | 0.84, 32 | 0.70, 33 | 0.71, 34 | 0.66, 35 | 0.57, 36 | 0.58, 37 | 1.66, 38 | 1.41, 39 | 1.21, 40 | 1.11, 41 | 1.07, 42 | 1.05, 43 | 1.02, 44 | 1.06, 45 | 2.03, 46 | 1.76 47 | }; 48 | 49 | #endif //_BRAGG_H 50 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #/************************************************************************** 2 | # config.h.in -- This file is part of DFTCXX. * 3 | # * 4 | # Copyright (C) 2016, Ivo Filot * 5 | # * 6 | # DFTCXX is free software: * 7 | # you can redistribute it and/or modify it under the terms of the * 8 | # GNU General Public License as published by the Free Software * 9 | # Foundation, either version 3 of the License, or (at your option) * 10 | # any later version. * 11 | # * 12 | # DFTCXX is distributed in the hope that it will be useful, * 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | # See the GNU General Public License for more details. * 16 | # * 17 | # You should have received a copy of the GNU General Public License * 18 | # along with this program. If not, see http://www.gnu.org/licenses/. * 19 | # * 20 | #**************************************************************************/ 21 | 22 | #ifndef _CONFIG_H 23 | #define _CONFIG_H 24 | 25 | #define VERSION_MAJOR 1 26 | #define VERSION_MINOR 1 27 | #define VERSION_MICRO 2 28 | #define VERSION "1.1.2" 29 | 30 | static const std::string PROGRAM_VERSION(VERSION); 31 | static const unsigned int PROGRAM_VERSION_MAJOR = VERSION_MAJOR; 32 | static const unsigned int PROGRAM_VERSION_MINOR = VERSION_MINOR; 33 | static const unsigned int PROGRAM_VERSION_MICRO = VERSION_MICRO; 34 | 35 | #endif // _CONFIG_H 36 | -------------------------------------------------------------------------------- /src/pngfuncs.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _UTIL_PNG_H 23 | #define _UTIL_PNG_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace PNG { 31 | 32 | void write_image_buffer_to_png(const std::string& filename, const std::vector& buffer, unsigned int width, unsigned int height, unsigned int col); 33 | void write_file_callback(png_structp png_ptr, png_bytep data, png_size_t count); 34 | } 35 | 36 | #endif //_UTIL_PNG_H 37 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | #/************************************************************************** 2 | # config.h.in -- This file is part of DFTCXX. * 3 | # * 4 | # Copyright (C) 2016, Ivo Filot * 5 | # * 6 | # DFTCXX is free software: * 7 | # you can redistribute it and/or modify it under the terms of the * 8 | # GNU General Public License as published by the Free Software * 9 | # Foundation, either version 3 of the License, or (at your option) * 10 | # any later version. * 11 | # * 12 | # DFTCXX is distributed in the hope that it will be useful, * 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | # See the GNU General Public License for more details. * 16 | # * 17 | # You should have received a copy of the GNU General Public License * 18 | # along with this program. If not, see http://www.gnu.org/licenses/. * 19 | # * 20 | #**************************************************************************/ 21 | 22 | #ifndef _CONFIG_H 23 | #define _CONFIG_H 24 | 25 | #define VERSION_MAJOR @VERSION_MAJOR@ 26 | #define VERSION_MINOR @VERSION_MINOR@ 27 | #define VERSION_MICRO @VERSION_MICRO@ 28 | #define VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@" 29 | 30 | static const std::string PROGRAM_VERSION(VERSION); 31 | static const unsigned int PROGRAM_VERSION_MAJOR = VERSION_MAJOR; 32 | static const unsigned int PROGRAM_VERSION_MINOR = VERSION_MINOR; 33 | static const unsigned int PROGRAM_VERSION_MICRO = VERSION_MICRO; 34 | 35 | #endif // _CONFIG_H 36 | -------------------------------------------------------------------------------- /src/spherical_harmonics.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _SPHERICAL_HARMONIC_H 23 | #define _SPHERICAL_HARMONIC_H 24 | 25 | #include 26 | #include 27 | 28 | namespace SH { 29 | double spherical_harmonic(int l, int m, double pole, double azimuth); 30 | 31 | double prefactor_spherical_harmonic(int l, int m); 32 | 33 | double polar_function(int l, int m, double theta); 34 | 35 | double azimuthal_function(int m, double phi); 36 | 37 | double legendre (int n, double x); 38 | 39 | double legendre_p (int n, int m, double x); 40 | }; 41 | 42 | #endif // _SPHERICAL_HARMONIC_H 43 | -------------------------------------------------------------------------------- /src/rectangulargrid.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _RECTANGULAR_GRID 23 | #define _RECTANGULAR_GRID 24 | 25 | #include "gridpoint.h" 26 | #include "pngfuncs.h" 27 | 28 | class RectangularGrid { 29 | private: 30 | std::shared_ptr mol; //!< pointer to molecule class 31 | std::vector grid; //!< set of all gridpoints 32 | unsigned int gridsize; 33 | 34 | public: 35 | RectangularGrid(const std::shared_ptr& mol); 36 | 37 | /** 38 | * @brief build a grid 39 | * 40 | * @param[in] size size of the grid in angstrom 41 | * @param[in] dp number of grid points in each Cartesian direction 42 | */ 43 | void build_grid(double size, unsigned int dp); 44 | 45 | /** 46 | * @fn set_density 47 | * @brief set the density at the grid point given a density matrix 48 | * 49 | * @param P reference to density matrix 50 | * 51 | * Loops over all the grid points and calculates the local density 52 | * using the amplitudes of the basis functions and the density matrix 53 | * 54 | * @return void 55 | */ 56 | void set_density(const MatrixXXd& P); 57 | 58 | /** 59 | * @brief write the gradient to a data file 60 | * 61 | * @param[in] filename path to data file 62 | */ 63 | void write_gradient(const std::string& filename); 64 | 65 | private: 66 | }; 67 | 68 | #endif // _RECTANGULAR_GRID 69 | -------------------------------------------------------------------------------- /src/functionals.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _FUNCTIONALS_H 23 | #define _FUNCTIONALS_H 24 | 25 | #include 26 | #include 27 | 28 | typedef Eigen::Matrix MatrixXXd; 29 | typedef Eigen::Matrix VectorXd; 30 | 31 | class Functional { 32 | public: 33 | Functional(); 34 | 35 | // functionals 36 | void xalpha_x_functional(const VectorXd& densitiesa, 37 | const VectorXd& densitiesb, 38 | VectorXd& ex, 39 | VectorXd& vxa, 40 | VectorXd& vxb); 41 | 42 | void vwm_c_functional(const VectorXd& densitiesa, 43 | const VectorXd& densitiesb, 44 | VectorXd& ec, 45 | VectorXd& vca, 46 | VectorXd& vcb); 47 | 48 | private: 49 | static constexpr double pi = 3.14159265358979323846; 50 | 51 | // auxiliary functions 52 | double vwn_xx(double x, double b, double c); 53 | double vwn_epsp(double x); 54 | double vwn_epsf(double x); 55 | double vwn_eps(double x, double a, double x0, double b, double c); 56 | double vwn_depsp(double x); 57 | double vwn_depsf(double x); 58 | double vwn_deps(double x, double a, double x0, double b, double c); 59 | double vwn_g(double z); 60 | double vwn_dg(double z); 61 | }; 62 | 63 | #endif //_FUNCTIONALS_H 64 | -------------------------------------------------------------------------------- /src/dftcxx.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "molecule.h" 27 | #include "dft.h" 28 | #include "config.h" 29 | 30 | int main(int argc, char** argv) { 31 | 32 | try { 33 | TCLAP::CmdLine cmd("Perform DFT calculation.", ' ', PROGRAM_VERSION); 34 | 35 | // input filename 36 | TCLAP::ValueArg arg_input_filename("i","input","Input file (i.e. h2.in)",true,"h2.in","filename"); 37 | cmd.add(arg_input_filename); 38 | 39 | cmd.parse(argc, argv); 40 | 41 | const std::string input_filename = arg_input_filename.getValue(); 42 | 43 | std::cout << "--------------------------------------------------------------" << std::endl; 44 | std::cout << std::endl; 45 | std::cout << "Executing DFTCXX v." << PROGRAM_VERSION << std::endl; 46 | std::cout << "Author: Ivo Filot " << std::endl; 47 | std::cout << std::endl; 48 | std::cout << "--------------------------------------------------------------" << std::endl; 49 | std::cout << std::endl; 50 | 51 | auto start = std::chrono::system_clock::now(); 52 | 53 | DFT dft(input_filename); 54 | dft.scf(); 55 | 56 | auto end = std::chrono::system_clock::now(); 57 | auto elapsed = std::chrono::duration_cast(end - start); 58 | std::cout << boost::format("Total elapsed time: %f ms\n") % elapsed.count(); 59 | 60 | return 0; 61 | 62 | } catch (TCLAP::ArgException &e) { 63 | std::cerr << "error: " << e.error() << 64 | " for arg " << e.argId() << std::endl; 65 | return -1; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/cspline.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _CSPLINE_H 23 | #define _CSPLINE_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /** 33 | * @brief Cubic spline class. 34 | */ 35 | class Cspline { 36 | private: 37 | std::vector x; // x and y values with the same indices are datapoints 38 | std::vector y; 39 | std::vector< std::vector > spline; //contains n-rows of polynomial coefficients 40 | bool spline_generated; 41 | 42 | public: 43 | /** 44 | * @brief default constructor 45 | */ 46 | Cspline(); 47 | 48 | /** 49 | * @brief Set the x and y values used for spline construction. 50 | * 51 | * @param[in] xx X-axis values. 52 | * @param[in] yy Y-axis values. 53 | */ 54 | void set_values(const std::vector& xx, const std::vector& yy); 55 | 56 | /** 57 | * @brief Generate a spline through the (x,y) points. 58 | * 59 | * The spline generation is done by setting up a tridiagonal 60 | * matrix problem. This matrix problem can be solved with the 61 | * Thomas algorithm. The algorithm is generalized to work with 62 | * points that are irregularly spaced over the x-axis. 63 | */ 64 | void generate_spline(); 65 | 66 | /** 67 | * @brief Evaluate the spline at a point on the x-axis. 68 | * 69 | * @param[in] xx Point of evaluation. 70 | * 71 | * @return Spline value at point of evaluation. 72 | */ 73 | double eval(double x) const; 74 | 75 | /** 76 | * @brief Gets the minimum. 77 | * 78 | * @return The minimum. 79 | */ 80 | inline double get_min() const { 81 | return x[0]; 82 | } 83 | 84 | /** 85 | * @brief Gets the maximum. 86 | * 87 | * @return The maximum. 88 | */ 89 | inline double get_max() const { 90 | return x.back(); 91 | } 92 | 93 | /** 94 | * @brief print the data points 95 | */ 96 | void print() const; 97 | 98 | }; 99 | 100 | #endif //_CSPLINE_H 101 | -------------------------------------------------------------------------------- /src/rectangulargrid.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "rectangulargrid.h" 23 | 24 | RectangularGrid::RectangularGrid(const std::shared_ptr& _mol) { 25 | this->mol = _mol; 26 | } 27 | 28 | /** 29 | * @brief build a grid 30 | * 31 | * @param[in] size size of the grid in angstrom 32 | * @param[in] dp number of grid points in each Cartesian direction 33 | */ 34 | void RectangularGrid::build_grid(double size, unsigned int dp) { 35 | const double gdsize = size / (double)(dp - 1); 36 | const vec3 ctr(0,0,0); 37 | this->gridsize = dp; 38 | 39 | for(unsigned int i=0; igrid.emplace_back(pos, ctr); 48 | 49 | // set basis function amplitude 50 | this->grid.back().set_basis_func_amp(mol); 51 | 52 | // set basis function gradient 53 | this->grid.back().set_basis_func_grad(mol); 54 | } 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * @fn set_density 61 | * @brief set the density at the grid point given a density matrix 62 | * 63 | * @param P reference to density matrix 64 | * 65 | * Loops over all the grid points and calculates the local density 66 | * using the amplitudes of the basis functions and the density matrix 67 | * 68 | * @return void 69 | */ 70 | void RectangularGrid::set_density(const MatrixXXd& P) { 71 | for(unsigned int i=0; igrid.size(); i++) { 72 | this->grid[i].set_density(P); 73 | this->grid[i].set_gradient(P); 74 | } 75 | } 76 | 77 | /** 78 | * @brief write the gradient to a data file 79 | * 80 | * @param[in] filename path to data file 81 | */ 82 | void RectangularGrid::write_gradient(const std::string& filename) { 83 | std::ofstream out(filename); 84 | 85 | for(unsigned int i=0; igrid.size(); i++) { 86 | 87 | const vec3& pos = this->grid[i].get_position(); 88 | const vec3& grad = this->grid[i].get_gradient(); 89 | 90 | out << boost::format("%12.8f %12.8f %12.8f %12.8f %12.8f %12.8f\n") 91 | % pos[0] % pos[1] % pos[2] % grad[0] % grad[1] % grad[2]; 92 | } 93 | 94 | out.close(); 95 | } 96 | -------------------------------------------------------------------------------- /src/spherical_harmonics.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "spherical_harmonics.h" 23 | 24 | double SH::spherical_harmonic(int l, int m, double pole, double azimuth) { 25 | return SH::polar_function(l, m, pole) * SH::azimuthal_function(m, azimuth); 26 | } 27 | 28 | double SH::prefactor_spherical_harmonic(int l, int m) { 29 | static const double pre = 1.0 / std::sqrt(4 * M_PI); 30 | return pre * (m == 0 ? 1 : std::sqrt(2.0)) * 31 | std::sqrt((double)(2 * l + 1) * boost::math::factorial(l - std::abs(m)) / 32 | boost::math::factorial(l + std::abs(m)) ); 33 | } 34 | 35 | double SH::polar_function(int l, int m, double theta) { 36 | return SH::legendre_p(l, std::abs(m), std::cos(theta)); 37 | } 38 | 39 | double SH::azimuthal_function(int m, double phi) { 40 | if(m == 0) return 1.0; 41 | 42 | if(m > 0) { 43 | return std::cos((double)m * phi); 44 | } else { 45 | return std::sin(-(double)m * phi); 46 | } 47 | } 48 | 49 | /* legendre function */ 50 | 51 | double SH::legendre (int n, double x) { 52 | int i; 53 | 54 | if(n < 0) { 55 | return -1; 56 | } 57 | 58 | std::vector v(n+1, 0.0); 59 | 60 | if(n < 1) { 61 | return 1.0; 62 | } 63 | 64 | v[1] = x; 65 | 66 | for ( i = 2; i <= n; i++ ) { 67 | v[i] = ( ( double ) ( 2 * i - 1 ) * x * v[i-1] 68 | - ( double ) ( i - 1 ) * v[i-2] ) 69 | / ( double ) ( i ); 70 | } 71 | 72 | return v[n]; 73 | } 74 | 75 | /* associated legendre function 76 | * 77 | * note that x should lie between -1 and 1 for this to work, else 78 | * a NAN will be returned 79 | */ 80 | 81 | double SH::legendre_p (int n, int m, double x) { 82 | double fact; 83 | int i; 84 | int j; 85 | int k; 86 | std::vector v(n+1, 0.0); 87 | 88 | // 89 | // J = M is the first nonzero function. 90 | // 91 | if ( m <= n ) { 92 | v[m] = 1.0; 93 | 94 | fact = 1.0; 95 | for ( k = 0; k < m; k++ ) { 96 | v[m] *= - fact * std::sqrt ( 1.0 - x * x); 97 | fact += 2.0; 98 | } 99 | } 100 | 101 | // 102 | // J = M + 1 is the second nonzero function. 103 | // 104 | if ( m + 1 <= n ) { 105 | v[m+1] = x * ( double ) ( 2 * m + 1 ) * v[m]; 106 | } 107 | // 108 | // Now we use a three term recurrence. 109 | // 110 | for ( j = m + 2; j <= n; j++ ) { 111 | v[j] = ( ( double ) ( 2 * j - 1 ) * x * v[(j-1)] 112 | + ( double ) ( - j - m + 1 ) * v[(j-2)] ) 113 | / ( double ) ( j - m ); 114 | } 115 | 116 | return v[n]; 117 | } 118 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #/************************************************************************** 2 | # CMakeLists.txt -- This file is part of DFTCXX. * 3 | # * 4 | # Copyright (C) 2016, Ivo Filot * 5 | # * 6 | # DFTCXX is free software: * 7 | # you can redistribute it and/or modify it under the terms of the * 8 | # GNU General Public License as published by the Free Software * 9 | # Foundation, either version 3 of the License, or (at your option) * 10 | # any later version. * 11 | # * 12 | # DFTCXX is distributed in the hope that it will be useful, * 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | # See the GNU General Public License for more details. * 16 | # * 17 | # You should have received a copy of the GNU General Public License * 18 | # along with this program. If not, see http://www.gnu.org/licenses/. * 19 | # * 20 | #**************************************************************************/ 21 | 22 | # set minimum cmake requirements 23 | cmake_minimum_required(VERSION 2.8) 24 | project (dftcxx) 25 | 26 | # add custom directory to look for .cmake files 27 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules ) 28 | 29 | # prepare configuration file 30 | SET(VERSION_MAJOR "1") 31 | SET(VERSION_MINOR "1") 32 | SET(VERSION_MICRO "2") 33 | configure_file(config.h.in ../src/config.h @ONLY) 34 | 35 | # Enable release build 36 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 37 | message(STATUS "Setting build type to 'Release' as none was specified.") 38 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) 39 | # Set the possible values of build type for cmake-gui 40 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") 41 | endif() 42 | 43 | # Check for OpenMP 44 | if(NOT WIN32) 45 | find_package(OpenMP) 46 | if (OPENMP_FOUND) 47 | option(HAS_OPENMP "OpenMP enabled" ON) 48 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 49 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 50 | endif() 51 | else() 52 | set(HAS_OPENMP OFF) 53 | endif() 54 | 55 | # set Boost 56 | if(APPLE) 57 | SET(BOOST_INCLUDEDIR "/usr/local/include") 58 | SET(BOOST_LIBRARYDIR "/usr/local/lib") 59 | ELSE() 60 | SET(BOOST_INCLUDEDIR "/usr/include") 61 | SET(BOOST_LIBRARYDIR "/usr/lib/x86_64-linux-gnu") 62 | ENDIF() 63 | SET (Boost_NO_SYSTEM_PATHS ON) 64 | SET (Boost_USE_MULTITHREADED ON) 65 | SET (Boost_USE_STATIC_LIBS ON) 66 | SET (Boost_USE_STATIC_RUNTIME OFF) 67 | SET (BOOST_ALL_DYN_LINK OFF) 68 | 69 | find_package(Boost COMPONENTS regex iostreams filesystem REQUIRED) 70 | find_package(PkgConfig REQUIRED) 71 | pkg_check_modules(EIGEN eigen3 REQUIRED) 72 | pkg_check_modules(TCLAP tclap REQUIRED) 73 | pkg_check_modules(PNG REQUIRED libpng) 74 | 75 | # Set include folders 76 | include_directories(${CMAKE_CURRENT_SOURCE_DIR} 77 | ${CMAKE_BINARY_DIR} 78 | ${TCLAP_INCLUDE_DIR} 79 | ${Boost_INCLUDE_DIRS} 80 | ${EIGEN_INCLUDE_DIRS} 81 | ${PNG_INCLUDE_DIRS}) 82 | 83 | # use C++14 and SSE2 vectorization 84 | add_definitions(-std=c++14) 85 | add_definitions(-march=native) 86 | if(OPENMP_FOUND) 87 | add_definitions(-DHAS_OPENMP) 88 | endif() 89 | 90 | # Add sources 91 | file(GLOB SOURCES "*.cpp") 92 | 93 | # Set executable 94 | add_executable(dftcxx ${SOURCES}) 95 | 96 | # Link libraries 97 | target_link_libraries(dftcxx ) 98 | target_link_libraries(dftcxx ${PNG_LIBRARIES} ${Boost_LIBRARIES}) 99 | 100 | ### 101 | # Installing 102 | ## 103 | install (TARGETS dftcxx DESTINATION bin) 104 | -------------------------------------------------------------------------------- /src/gridpoint.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "gridpoint.h" 23 | 24 | /** 25 | * @fn GridPoint 26 | * @brief GridPoint Constructor 27 | * 28 | * @param _r vec3 position of the grid point 29 | * 30 | * @return GridPoint instance 31 | */ 32 | GridPoint::GridPoint(const vec3& _r, const vec3& _r_at): 33 | r(_r), 34 | r_at(_r_at) 35 | {} 36 | 37 | /** 38 | * @fn set_basis_func_amp 39 | * @brief calculates the amplitudes at the grid point of all basis functions 40 | * 41 | * @param _mol pointer to the molecule object 42 | * 43 | * @return void 44 | */ 45 | void GridPoint::set_basis_func_amp(const std::shared_ptr& _mol) { 46 | const unsigned int size = _mol->get_nr_bfs(); 47 | this->basis_func_amp = VectorXd(size); 48 | 49 | for(unsigned int i=0; ibasis_func_amp(i) = _mol->get_cgf(i).get_amp(this->r); 51 | } 52 | } 53 | 54 | /** 55 | * @fn set_basis_func_grad 56 | * @brief calculates the gradient at the grid point of all basis functions 57 | * 58 | * @param _mol pointer to the molecule object 59 | * 60 | * @return void 61 | */ 62 | void GridPoint::set_basis_func_grad(const std::shared_ptr& _mol) { 63 | const unsigned int size = _mol->get_nr_bfs(); 64 | this->basis_func_grad = MatrixXXd(size, 3); 65 | 66 | for(unsigned int i=0; iget_cgf(i).get_grad(this->r); 68 | for(unsigned int j=0; j<3; j++) { 69 | this->basis_func_grad(i,j) = grad(j); 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * @fn set_density 76 | * @brief calculates the density at the grid point using the density matrix 77 | * 78 | * @param _mol reference to density matrix 79 | * 80 | * @return void 81 | */ 82 | void GridPoint::set_density(const MatrixXXd& D) { 83 | this->density = 2.0 * this->basis_func_amp.dot(D * this->basis_func_amp); 84 | } 85 | 86 | /** 87 | * @fn set_density 88 | * @brief calculates the gradient at the grid point using the density matrix 89 | * 90 | * @param _mol reference to density matrix 91 | * 92 | * @return void 93 | */ 94 | void GridPoint::set_gradient(const MatrixXXd& D) { 95 | VectorXd x = this->basis_func_grad.col(0); 96 | VectorXd y = this->basis_func_grad.col(1); 97 | VectorXd z = this->basis_func_grad.col(2); 98 | 99 | // apply product rule for the gradient 100 | double gx = 2.0 * this->basis_func_amp.transpose().dot(D * x) + 101 | 2.0 * x.transpose().dot(D * this->basis_func_amp); 102 | double gy = 2.0 * this->basis_func_amp.transpose().dot(D * y) + 103 | 2.0 * y.transpose().dot(D * this->basis_func_amp); 104 | double gz = 2.0 * this->basis_func_amp.transpose().dot(D * z) + 105 | 2.0 * z.transpose().dot(D * this->basis_func_amp); 106 | 107 | this->grad = vec3(gx, gy, gz); 108 | } 109 | -------------------------------------------------------------------------------- /src/gamma.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | /* 23 | * Incomplete Gamma Function 24 | * 25 | * Used in the evaluation of the two-electron integrals. 26 | * 27 | */ 28 | 29 | /* 30 | * The functions below were extracted from: 31 | * 32 | * Numerical Recipes 33 | * William H. Press, Saul A. Teukolsky, William T., 34 | * Vetterling and Brian P. Flannery 35 | * 3rd edition page 261 36 | * ISBN-13: 978-0521880688 37 | */ 38 | 39 | #ifndef _GAMMA_H 40 | #define _GAMMA_H 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | class GammaInc { 47 | public: 48 | double Fgamma(const double m, double x); 49 | 50 | /* 51 | * @fn gamm_inc 52 | * @brief Calculates the incomplete gamma function P(a,x) 53 | * 54 | * gamma(a,x) 55 | * ---------- 56 | * G(a) 57 | * 58 | * @param a "squared width" of the IGF 59 | * @param x Upper bound of the integral in the IGF 60 | * 61 | * returns double value of the incomplete Gamma Function 62 | */ 63 | double gamm_inc(const double a, const double x); 64 | 65 | /* 66 | * @fn gamm_inc 67 | * @brief Calculates the incomplete gamma function P(a,x) 68 | * 69 | * This routine selects the best function to use in the 70 | * evaluation of the Incomplete Gamma Function (IGF). 71 | * 72 | * @param a "squared width" of the IGF 73 | * @param x Upper bound of the integral in the IGF 74 | * 75 | * returns double value of the incomplete Gamma Function 76 | */ 77 | double gammp(const double m, const double x); 78 | 79 | private: 80 | /* 81 | * @fn gser 82 | * @brief Gamma function P(a,x) evaluated by its series representation 83 | * 84 | * @param a "squared width" of the IGF 85 | * @param x Upper bound of the integral in the IGF 86 | * 87 | * returns double value of the incomplete Gamma Function 88 | */ 89 | double gser(const double a, const double x); 90 | 91 | 92 | double gammln(const double xx); 93 | 94 | /* 95 | * @fn gcf 96 | * @brief Gamma function P(a,x) evaluated by its continued fraction representation 97 | * 98 | * @param a "squared width" of the IGF 99 | * @param x Upper bound of the integral in the IGF 100 | * 101 | * returns double value of the incomplete Gamma Function 102 | */ 103 | double gcf(const double a, const double x); 104 | 105 | /* 106 | * @fn gammpapprox 107 | * @brief Incomplete Gamma function P(a,x) or Q(a,x) evaluated by quadrature 108 | * 109 | * Returns P(a,x) or Q(a,x), when psig is 1 or 0, respectively. 110 | * 111 | * @param a "squared width" of the IGF 112 | * @param x Upper bound of the integral in the IGF 113 | * @param psig Whether to evaluate P(a,x) or Q(a,x) 114 | * 115 | * returns double value of the incomplete Gamma Function 116 | */ 117 | double gammpapprox(double a, double x, int psig); 118 | }; 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /src/pngfuncs.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "pngfuncs.h" 23 | 24 | void PNG::write_image_buffer_to_png(const std::string& filename, const std::vector& buffer, unsigned int width, unsigned int height, unsigned int col) { 25 | png_structp png_ptr; 26 | png_infop info_ptr; 27 | 28 | /* create file */ 29 | std::ofstream ofile(filename.c_str(), std::ios::binary); 30 | 31 | if (!ofile.is_open() ) { 32 | std::cerr << "[write_png_file] File " << filename.c_str() << " could not be opened for reading" << std::endl; 33 | exit(-1); 34 | } 35 | 36 | /* initialize stuff */ 37 | png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 38 | 39 | if (!png_ptr) { 40 | std::cerr << "[write_png_file] png_create_write_struct failed" << std::endl; 41 | } 42 | 43 | info_ptr = png_create_info_struct(png_ptr); 44 | if (!info_ptr) { 45 | std::cerr << "[write_png_file] png_create_info_struct failed" << std::endl; 46 | } 47 | 48 | if (setjmp(png_jmpbuf(png_ptr))) { 49 | std::cerr << "[write_png_file] Error during init_io"; 50 | } 51 | 52 | png_set_write_fn(png_ptr, (void *)&ofile, write_file_callback, NULL); 53 | 54 | /* write header */ 55 | if (setjmp(png_jmpbuf(png_ptr))) { 56 | std::cerr << "[write_png_file] Error during writing header" << std::endl; 57 | } 58 | 59 | png_set_IHDR(png_ptr, info_ptr, width, height, 60 | 8, col, PNG_INTERLACE_NONE, 61 | PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 62 | 63 | png_write_info(png_ptr, info_ptr); 64 | 65 | 66 | /* write bytes */ 67 | if (setjmp(png_jmpbuf(png_ptr))) { 68 | std::cerr << "[write_png_file] Error during writing bytes" << std::endl; 69 | } 70 | 71 | png_bytep *row_pointers; 72 | if(col == PNG_COLOR_TYPE_GRAY) { 73 | row_pointers = new png_bytep[height]; 74 | for(unsigned int i=0; iwrite((char*)data, count); 115 | } 116 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _SETTINGS_H 23 | #define _SETTINGS_H 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | class Settings { 35 | private: 36 | std::string name; // name of the system 37 | std::string basis_set; // basis set (i.e. sto-3g, sto-6g) 38 | unsigned int grid_level; // fineness of the grid 39 | unsigned int radial_points; // number of radial points 40 | unsigned int lebedev_order; // lebedev order 41 | unsigned int lmax; // lmax 42 | unsigned int hartree_evaluation; // Hartree evaluation method 43 | 44 | std::unordered_map key_values; // map to store settings 45 | 46 | public: 47 | 48 | enum { // defines the type of evaluation for the Hartree potential 49 | BECKE_GRID, 50 | TWO_ELECTRON_INTEGRALS, 51 | 52 | NUM_HARTEE_EVALUATION 53 | }; 54 | 55 | enum { // defines fineness of the numerical integration 56 | GRID_COARSE, 57 | GRID_MEDIUM, 58 | GRID_FINE, 59 | GRID_ULTRAFINE, 60 | 61 | NR_GRID_RESOLUTIONS 62 | }; 63 | 64 | enum { // lebedev orders 65 | LEBEDEV_6, 66 | LEBEDEV_14, 67 | LEBEDEV_26, 68 | LEBEDEV_38, 69 | LEBEDEV_50, 70 | LEBEDEV_74, 71 | LEBEDEV_86, 72 | LEBEDEV_110, 73 | LEBEDEV_146, 74 | LEBEDEV_170, 75 | LEBEDEV_194, 76 | 77 | NUM_LEBEDEV_POINTS 78 | }; 79 | 80 | /** 81 | * @brief constructor 82 | * 83 | * @param[in] filename input file 84 | */ 85 | Settings(const std::string& filename); 86 | 87 | /** 88 | * @brief obtain a value by a key from settings 89 | * 90 | * @param[in] key key 91 | * 92 | * @return value 93 | */ 94 | const std::string& get_value(const std::string& key) const; 95 | 96 | /** 97 | * @brief Gets the hartree evaluation method 98 | * 99 | * @return The hartree evaluation method 100 | */ 101 | inline unsigned int get_hartree_evaluation_method() const { 102 | return this->hartree_evaluation; 103 | } 104 | 105 | /** 106 | * @brief get the number of radial points 107 | * 108 | * @return number of radial points 109 | */ 110 | inline unsigned int get_radial_points() const { 111 | return this->radial_points; 112 | } 113 | 114 | /** 115 | * @brief get the Lebedev order 116 | * 117 | * @return The lebedev order. 118 | */ 119 | inline unsigned int get_lebedev_order() const { 120 | return this->lebedev_order; 121 | } 122 | 123 | /** 124 | * @brief return maximum angular value 125 | * 126 | * @return The lmax. 127 | */ 128 | inline unsigned int get_lmax() const { 129 | return this->lmax; 130 | } 131 | 132 | private: 133 | 134 | /** 135 | * @brief Sets the default settings. 136 | */ 137 | void set_default_settings(); 138 | 139 | /** 140 | * @brief Reads a settings file. 141 | * 142 | * @param[in] filename input file 143 | */ 144 | void read_settings_file(const std::string& filename); 145 | 146 | /** 147 | * @brief Sets the grid fineness. 148 | * 149 | * @param[in] fineness fineness constant 150 | */ 151 | void set_grid_fineness(unsigned int fineness); 152 | }; 153 | 154 | #endif // _SETTINGS_H 155 | -------------------------------------------------------------------------------- /src/functionals.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "functionals.h" 23 | 24 | void Functional::xalpha_x_functional(const VectorXd& densitiesa, 25 | const VectorXd& densitiesb, 26 | VectorXd& ex, 27 | VectorXd& vxa, 28 | VectorXd& vxb) { 29 | 30 | static const double tol = 1e-10; 31 | static const double xalpha = 2.0 / 3.0; 32 | static const double fac = -2.25 * xalpha * std::pow(3.0 / 4.0 / pi, 1.0 / 3.0); 33 | 34 | ex = VectorXd::Zero(densitiesa.size()); 35 | vxa = VectorXd::Zero(densitiesa.size()); 36 | vxb = VectorXd::Zero(densitiesb.size()); 37 | 38 | #ifdef HAS_OPENMP 39 | #pragma omp parallel for 40 | #endif 41 | for(unsigned int i=0; i * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "settings.h" 23 | 24 | /** 25 | * @brief constructor 26 | * 27 | * @param[in] filename input file 28 | */ 29 | Settings::Settings(const std::string& filename) { 30 | this->read_settings_file(filename); 31 | this->set_default_settings(); 32 | } 33 | 34 | /** 35 | * @brief Reads a settings file. 36 | * 37 | * @param[in] filename input file 38 | */ 39 | void Settings::read_settings_file(const std::string& filename) { 40 | // check if filename exists 41 | if (!boost::filesystem::exists(filename)) { 42 | throw std::runtime_error("Cannot open " + filename + "!"); 43 | } 44 | 45 | // static regex patterns 46 | const boost::regex regex_system("^system:\\s*$"); 47 | boost::smatch what; 48 | 49 | // read from file 50 | std::ifstream infile(filename); 51 | std::string line; 52 | std::vector pieces; 53 | 54 | while(std::getline(infile, line)) { 55 | boost::split(pieces, line, boost::is_any_of("="), boost::token_compress_on); 56 | if(pieces.size() == 2) { 57 | std::string keyword = pieces[0]; 58 | std::string value = pieces[1]; 59 | 60 | boost::trim(keyword); 61 | boost::trim(value); 62 | 63 | this->key_values.emplace(keyword, value); 64 | } 65 | 66 | if(boost::regex_match(line, what, regex_system)) { 67 | break; 68 | } 69 | } 70 | } 71 | 72 | /** 73 | * @brief obtain a value by a key from settings 74 | * 75 | * @param[in] key key 76 | * 77 | * @return value 78 | */ 79 | const std::string& Settings::get_value(const std::string& key) const { 80 | auto got = this->key_values.find(key); 81 | if(got != this->key_values.end()) { 82 | return got->second; 83 | } else { 84 | throw std::logic_error("Could not find " + key); 85 | } 86 | } 87 | 88 | /** 89 | * @brief Sets the default settings. 90 | */ 91 | void Settings::set_default_settings() { 92 | // ***************************** 93 | // set hartree evaluation method 94 | // ***************************** 95 | std::string he; 96 | try { 97 | he = this->get_value("hartree_evaluation"); 98 | } catch(const std::exception& e) { 99 | he = "becke_grid"; 100 | } 101 | 102 | if(he.compare("two_electron_integrals") == 0) { 103 | this->hartree_evaluation = Settings::TWO_ELECTRON_INTEGRALS; 104 | } else if(he.compare("becke_grid")) { 105 | this->hartree_evaluation = Settings::BECKE_GRID; 106 | } else { 107 | Settings::BECKE_GRID; 108 | } 109 | 110 | // ***************************** 111 | // set fineness of the grid 112 | // ***************************** 113 | std::string grid_fineness; 114 | try { 115 | grid_fineness = this->get_value("grid"); 116 | } catch(const std::exception& e) { 117 | grid_fineness = "medium"; 118 | } 119 | 120 | if(grid_fineness.compare("coarse") == 0) { 121 | this->set_grid_fineness(GRID_COARSE); 122 | } else if(grid_fineness.compare("medium") == 0) { 123 | this->set_grid_fineness(GRID_MEDIUM); 124 | } else if(grid_fineness.compare("fine") == 0) { 125 | this->set_grid_fineness(GRID_FINE); 126 | } else if(grid_fineness.compare("ultrafine") == 0) { 127 | this->set_grid_fineness(GRID_ULTRAFINE); 128 | } 129 | 130 | // ************************************ 131 | // overrule grid parameters if present 132 | // ************************************ 133 | 134 | try { 135 | this->radial_points = boost::lexical_cast(this->get_value("radial_points")); 136 | } catch(const std::exception& e) { 137 | // do nothing 138 | } 139 | 140 | try { 141 | this->lebedev_order = boost::lexical_cast(this->get_value("lebedev_order")); 142 | } catch(const std::exception& e) { 143 | // do nothing 144 | } 145 | 146 | try { 147 | this->lmax = boost::lexical_cast(this->get_value("lmax")); 148 | } catch(const std::exception& e) { 149 | // do nothing 150 | } 151 | } 152 | 153 | /** 154 | * @brief Sets the grid fineness. 155 | * 156 | * @param[in] fineness fineness constant 157 | */ 158 | void Settings::set_grid_fineness(unsigned int fineness) { 159 | // set the resolution of the grid 160 | switch(fineness) { 161 | case GRID_COARSE: 162 | this->radial_points = 10; 163 | this->lebedev_order = LEBEDEV_50; 164 | this->lmax = 5; 165 | break; 166 | case GRID_MEDIUM: 167 | this->radial_points = 15; 168 | this->lebedev_order = LEBEDEV_110; 169 | this->lmax = 8; 170 | break; 171 | case GRID_FINE: 172 | this->radial_points = 20; 173 | this->lebedev_order = LEBEDEV_146; 174 | this->lmax = 10; 175 | break; 176 | case GRID_ULTRAFINE: 177 | this->radial_points = 30; 178 | this->lebedev_order = LEBEDEV_194; 179 | this->lmax = 11; 180 | break; 181 | default: // medium settings 182 | this->radial_points = 15; 183 | this->lebedev_order = LEBEDEV_110; 184 | this->lmax = 8; 185 | break; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/cspline.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "cspline.h" 23 | 24 | /** 25 | * @brief default constructor 26 | */ 27 | Cspline::Cspline() : 28 | spline_generated(false) {} 29 | 30 | /** 31 | * @brief Set the x and y values used for spline construction. 32 | * 33 | * @param[in] xx X-axis values. 34 | * @param[in] yy Y-axis values. 35 | */ 36 | void Cspline::set_values(const std::vector& xx, const std::vector& yy) { 37 | x = xx; 38 | y = yy; 39 | if(x.size() != y.size()) { 40 | std::stringstream error; 41 | error << "Cspline x and y data ranges do not match: "<< x.size() << " != " << y.size(); 42 | throw std::runtime_error(error.str()); 43 | } 44 | if(x.size() < 3) { 45 | std::stringstream error; 46 | error << "Cspline data range has to contain 3 of more items. Range = "<< x.size(); 47 | throw std::runtime_error(error.str()); 48 | } 49 | for(unsigned int i=1; i" << x[i]; 53 | throw std::runtime_error(error.str()); 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * @brief Generate a spline through the (x,y) points. 60 | * 61 | * The spline generation is done by setting up a tridiagonal matrix 62 | * problem. This matrix problem can be solved with the Thomas 63 | * algorithm. The algorithm is generalized to work with points that 64 | * are irregularly spaced over the x-axis. 65 | */ 66 | void Cspline::generate_spline() { 67 | //spline contains n-rows of polynomial coefficients 68 | spline = std::vector< std::vector >(x.size()-1,std::vector(4,0.0)); 69 | 70 | //tridiagonal matrix problem to be solved with the Thomas algorithm 71 | //|bc00||D0||Y0| 72 | //|abc0||D1||Y1| 73 | //|0abc||D2||Y2| 74 | //|00ab||D3||Y3| 75 | 76 | std::vector A(x.size(),0.0); 77 | std::vector B(x.size(),0.0); 78 | std::vector C(x.size(),0.0); 79 | std::vector D(x.size(),0.0); 80 | std::vector Y(x.size(),0.0); 81 | double h0; 82 | double h1; 83 | double r0; 84 | double r1; 85 | // FILE_LOG(logDEBUG) << "generate b_0, c_0, and Y_0"; 86 | h0 = x[1]-x[0]; 87 | h1 = x[2]-x[1]; 88 | r0 = (y[1]-y[0])/h0; 89 | r1 = (y[2]-y[1])/h1; 90 | B[0] = h1*(h0+h1); 91 | C[0] = (h0+h1)*(h0+h1); 92 | // C[0] = h0; 93 | Y[0] = r0*(3*h0*h1+2*h1*h1)+r1*h0*h0; 94 | //generate a_i, b_i, c_i, and Y_i 95 | for(unsigned int i=1; i0; i--) { 126 | D[i-1] = Y[i-1] - C[i-1] * D[i]; 127 | } 128 | //the matrix problem has been solved and can be used to get the polynomial coefficients 129 | //yi(x) = ai + bi*x + ci*x^2 + di*x^3 130 | double dx; 131 | double dy; 132 | for(unsigned int i=0; ispline_generated = true; 142 | } 143 | 144 | /** 145 | * @brief Evaluate the spline at a point on the x-axis. 146 | * 147 | * @param[in] xx Point of evaluation. 148 | * 149 | * @return Spline value at point of evaluation. 150 | */ 151 | double Cspline::eval(double xx) const { 152 | if(!this->spline_generated) { 153 | throw std::runtime_error("Spline interpolation was not performed, cannot evaluate."); 154 | } 155 | 156 | if(xx < x[0]) { 157 | return y.front(); 158 | } 159 | if(xx >= x.back()) { 160 | return y.back(); 161 | } 162 | 163 | //find correct x-data interval to interpolate and return the interpolated value 164 | for(unsigned int i=1; i * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _MOLECULE_H 23 | #define _MOLECULE_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "cgf.h" 34 | #include "settings.h" 35 | 36 | typedef Eigen::Vector3d vec3; 37 | 38 | /** 39 | * @brief Class for atom. 40 | */ 41 | class Atom { 42 | public: 43 | 44 | /** 45 | * @brief atom constructor 46 | */ 47 | Atom(); 48 | 49 | /** 50 | * @brief atom constructor 51 | * 52 | * @param[in] atnr atom number (i.e. number of protons) 53 | * @param[in] _position atom position 54 | */ 55 | Atom(unsigned int atnr, const vec3& _position); 56 | 57 | /** 58 | * @brief Gets the position. 59 | * 60 | * @return The position. 61 | */ 62 | inline const vec3& get_position() const { 63 | return this->position; 64 | } 65 | 66 | /** 67 | * @brief Gets the charge. 68 | * 69 | * @return The charge. 70 | */ 71 | inline const unsigned int get_charge() const { 72 | return this->atnr; 73 | } 74 | 75 | private: 76 | unsigned int atnr; // atomic number 77 | vec3 position; // atom position 78 | }; 79 | 80 | /** 81 | * @brief Class for molecule. 82 | */ 83 | class Molecule { 84 | private: 85 | std::vector> atoms; // atoms in the molecule 86 | std::vector cgfs; // vector of cgfs of this molecule 87 | std::shared_ptr settings; // pointer to settings file 88 | 89 | public: 90 | 91 | /** 92 | * @brief molecule constructor 93 | * 94 | * @param[in] filename input file 95 | * @param[in] _settings pointer to settings object 96 | */ 97 | Molecule(const std::string& filename, const std::shared_ptr& _settings); 98 | 99 | /** 100 | * @brief Reads a molecule from file. 101 | * 102 | * @param[in] filename The filename 103 | */ 104 | void read_molecule_from_file(const std::string& filename); 105 | 106 | /** 107 | * @brief Gets the number of atoms. 108 | * 109 | * @return The number of atoms. 110 | */ 111 | inline unsigned int get_nr_atoms() const { 112 | return this->atoms.size(); 113 | } 114 | 115 | /** 116 | * @brief Gets the number of bfs. 117 | * 118 | * @return The number of bfs. 119 | */ 120 | inline unsigned int get_nr_bfs() const { 121 | return this->cgfs.size(); 122 | } 123 | 124 | /** 125 | * @brief get contracted Gaussian function (CGF) i 126 | * 127 | * @param[in] i cgf identifier 128 | * 129 | * @return The cgf. 130 | */ 131 | inline const CGF& get_cgf(unsigned int i) const { 132 | return this->cgfs[i]; 133 | } 134 | 135 | /** 136 | * @brief get the vector of all contracted Gaussian functions (cgf) 137 | * 138 | * @return The cgfs. 139 | */ 140 | inline const std::vector* get_cgfs() const { 141 | return &this->cgfs; 142 | } 143 | 144 | /** 145 | * @brief get pointer to atom 146 | * 147 | * @param[in] i atom id 148 | * 149 | * @return pointer to atom class 150 | */ 151 | inline const std::shared_ptr& get_atom(unsigned int i) const { 152 | return this->atoms[i]; 153 | } 154 | 155 | /** 156 | * @brief Gets the atomic position. 157 | * 158 | * @param[in] i atom id 159 | * 160 | * @return The atomic position. 161 | */ 162 | inline const vec3& get_atomic_position(unsigned int i) const { 163 | return this->atoms[i]->get_position(); 164 | } 165 | 166 | /** 167 | * @brief Gets the atomic charge. 168 | * 169 | * @param[in] i atom id 170 | * 171 | * @return The atomic charge. 172 | */ 173 | inline const unsigned int get_atomic_charge(unsigned int i) const { 174 | return this->atoms[i]->get_charge(); 175 | } 176 | 177 | /** 178 | * @brief Adds an atom. 179 | * 180 | * @param[in] atom The atom 181 | */ 182 | inline void add_atom(const Atom& atom) { 183 | this->atoms.emplace_back(std::make_shared(atom)); 184 | } 185 | 186 | /** 187 | * @brief Adds a contracted Gaussian functional 188 | * 189 | * @param[in] atid atom id 190 | * @param[in] cgf The cgf 191 | */ 192 | inline void add_cgf(unsigned int atid, const CGF cgf) { 193 | this->cgfs.push_back(cgf); 194 | } 195 | 196 | /** 197 | * @brief Sets the basis set. 198 | * 199 | * @param[in] basis_set The basis set 200 | */ 201 | void set_basis_set(const std::string& basis_set); 202 | 203 | /** 204 | * @brief Gets the number of elec. 205 | * 206 | * @return The number of elec. 207 | */ 208 | unsigned int get_nr_elec() const; 209 | 210 | /** 211 | * @brief the total number of gtos in this molecule 212 | * 213 | * @return total number of gtos 214 | */ 215 | unsigned int get_nr_gtos() const; 216 | 217 | private: 218 | 219 | /** 220 | * @brief Gets the atom number from string. 221 | * 222 | * @param[in] el element name 223 | * 224 | * @return atom number 225 | */ 226 | unsigned int get_atom_number_from_string(std::string el); 227 | }; 228 | 229 | #endif //_MOLECULE_H 230 | -------------------------------------------------------------------------------- /src/moleculargrid.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _MOLECULAR_GRID_H 23 | #define _MOLECULAR_GRID_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "molecule.h" 30 | #include "gridpoint.h" 31 | #include "atomicgrid.h" 32 | 33 | /* 34 | * @class MolecularGrid 35 | * @brief Set of grid points for the numerical integration 36 | * 37 | * For evaluating non-local properties of the system, a numerical integration 38 | * has to be performed. The numerical integration proceeds over a set of grid points. 39 | * The MolecularGrid routine constructs these grid points and sets appropriate 40 | * weights for these grid points according to the procedure by Becke: 41 | * 42 | * A multicenter numerical integration scheme for polyatomic molecules 43 | * A. D. Becke 44 | * The Journal of Chemical Physics 88, 2547 (1988); doi: 10.1063/1.454033 45 | * http://dx.doi.org/10.1063/1.454033 46 | * 47 | */ 48 | class MolecularGrid { 49 | private: 50 | static constexpr double pi = 3.14159265358979323846; 51 | 52 | std::shared_ptr mol; // pointer to molecule object 53 | 54 | std::vector> atomic_grids; // vector of pointers to atomic grids 55 | 56 | std::vector atomic_densities; 57 | 58 | unsigned int angular_points; 59 | unsigned int radial_points; 60 | unsigned int lebedev_order; 61 | unsigned int lebedev_offset; 62 | int lmax; 63 | 64 | // density coefficients (MXN) matrix where M are the radial points and N the combined lm index 65 | MatrixXXd rho_lm; 66 | 67 | // hartree potential coefficient (MXN) matrix where M are the radial points and N the combined lm index 68 | MatrixXXd U_lm; 69 | 70 | // vector holding radial distances 71 | VectorXd r_n; 72 | 73 | size_t grid_size; //!< total grid size 74 | 75 | public: 76 | /** 77 | * @fn MolecularGrid 78 | * @brief MolecularGrid constructor 79 | * 80 | * @param _mol pointer to Molecule class 81 | * 82 | * @return MolecularGrid instance 83 | */ 84 | MolecularGrid(const std::shared_ptr& _mol); 85 | 86 | /** 87 | * @fn calculate_density 88 | * @brief calculate the total electron density (number of electrons) 89 | * 90 | * Calculates the total number of electrons by summing the weights 91 | * multiplied by the local value of the electron density. 92 | * 93 | * @return number of electrons 94 | */ 95 | double calculate_density() const; 96 | 97 | /** 98 | * @brief Sets the grid parameters (fine-tuning) 99 | * 100 | * @param[in] _radial_points number of radial points 101 | * @param[in] _lebedev_order The lebedev order 102 | * @param[in] _lmax maximum angular momentum for spherical harmonics 103 | */ 104 | void set_grid_parameters(unsigned int _radial_points, unsigned int _lebedev_order, unsigned int _lmax); 105 | 106 | /** 107 | * @fn create_grid 108 | * @brief creates the molecular grid 109 | * 110 | * Creates a molecular grid given a set of atoms and a set of 111 | * basis functions. For each atom, an atomic grid is created. The 112 | * numerical integration is carried out over all the atomic grids. The 113 | * contribution of the atomic grid to the overall integration over the 114 | * whole molecule is controlled via a weight factor as defined by Becke. 115 | * 116 | * @return void 117 | */ 118 | void create_grid(); 119 | 120 | /** 121 | * @fn set_density 122 | * @brief set the density at the grid point given a density matrix 123 | * 124 | * @param P reference to density matrix 125 | * 126 | * Loops over all the grid points and calculates the local density 127 | * using the amplitudes of the basis functions and the density matrix 128 | * 129 | * @return void 130 | */ 131 | void set_density(const MatrixXXd& P); 132 | 133 | /** 134 | * @brief Calculates the hartree potential. 135 | * 136 | * @return The hartree potential. 137 | */ 138 | MatrixXXd calculate_hartree_potential(); 139 | 140 | /** 141 | * @fn get_weights 142 | * @brief get the weights of all the grid points as a vector 143 | * 144 | * @return vector containing all the weights 145 | */ 146 | VectorXd get_weights() const; 147 | 148 | /** 149 | * @fn get_densities 150 | * @brief get the densities of all the grid points as a vector 151 | * 152 | * @return vector containing all the densities 153 | */ 154 | VectorXd get_densities() const; 155 | 156 | /** 157 | * @fn get_amplitudes 158 | * @brief get the amplitudes of all the grid points and all the basis functions as a matrix 159 | * 160 | * @return matrix (basis functions x grid points) 161 | */ 162 | MatrixXXd get_amplitudes() const; 163 | 164 | /** 165 | * @brief correct the densities to match the total number of electrons 166 | */ 167 | void correct_densities(); 168 | 169 | private: 170 | /** 171 | * @fn get_becke_weight_pn 172 | * @brief calculate Pn(r) (i.e. for a single gridpoint) for atom n (eq. 22 in A.D. Becke J.Chem.Phys. 88, 2547) 173 | * 174 | * Reference: A.D. Becke, J.Chem.Phys. 88, 2547, (1988) 175 | * Link: http://dx.doi.org/10.1063/1.454033 176 | * 177 | * @param atnr atomic number 178 | * @param p0 grid point position 179 | * 180 | * @return double Becke weight value 181 | */ 182 | double get_becke_weight_pn(unsigned int i, const vec3& p0); 183 | 184 | /* 185 | * auxiliary functions for the Becke grid 186 | */ 187 | 188 | double cutoff(double mu); 189 | double fk(unsigned int k, double mu); 190 | }; 191 | 192 | #endif //_MOLECULAR_GRID_H 193 | -------------------------------------------------------------------------------- /src/cgf.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "cgf.h" 23 | 24 | GTO::GTO(double _c, 25 | const vec3& _position, // position (unit = Bohr) 26 | double _alpha, 27 | unsigned int _l, 28 | unsigned int _m, 29 | unsigned int _n): 30 | c(_c), 31 | alpha(_alpha), 32 | l(_l), 33 | m(_m), 34 | n(_n), 35 | position(_position) { 36 | 37 | // calculate the normalization constant 38 | this->calculate_normalization_constant(); 39 | } 40 | 41 | /* 42 | * @fn get_amp 43 | * @brief Gets the amplitude of the GTO 44 | * 45 | * @param vec3 r coordinates 46 | * 47 | * @return const double amplitude 48 | */ 49 | const double GTO::get_amp(const vec3& r) const { 50 | double r2 = (r - this->position).squaredNorm(); 51 | 52 | return this->norm * 53 | std::pow(r[0]-this->position[0], l) * 54 | std::pow(r[1]-this->position[1], m) * 55 | std::pow(r[2]-this->position[2], n) * 56 | std::exp(- this->alpha * r2); 57 | } 58 | 59 | /* 60 | * @fn get_gradient 61 | * @brief Gets the gradient of the GTO 62 | * 63 | * @param vec3 r coordinates 64 | * 65 | * @return gradient 66 | */ 67 | vec3 GTO::get_grad(const vec3& r) const { 68 | const double ex = std::exp(-this->alpha * std::pow(r[0]-this->position[0],2)); 69 | const double fx = std::pow(r[0] - this->position[0], this->l) * ex; 70 | 71 | const double ey = std::exp(-this->alpha * std::pow(r[1]-this->position[1],2)); 72 | const double fy = std::pow(r[1] - this->position[1], this->m) * ey; 73 | 74 | const double ez = std::exp(-this->alpha * std::pow(r[2]-this->position[2],2)); 75 | const double fz = std::pow(r[2] - this->position[2], this->n) * ez; 76 | 77 | double gx = -2.0 * this->alpha * (r[0]-this->position[0]) * fx; 78 | double gy = -2.0 * this->alpha * (r[1]-this->position[1]) * fy; 79 | double gz = -2.0 * this->alpha * (r[2]-this->position[2]) * fz; 80 | 81 | if(this->l > 0) { 82 | gx += std::pow(r[0] - this->position[0], this->l-1) * ex; 83 | } 84 | if(this->m > 0) { 85 | gy += std::pow(r[1] - this->position[1], this->m-1) * ey; 86 | } 87 | if(this->n > 0) { 88 | gz += std::pow(r[2] - this->position[2], this->n-1) * ez; 89 | } 90 | 91 | return vec3(this->c * gx * fy * fz, 92 | this->c * fx * gy * fz, 93 | this->c * fx * fy * gz); 94 | } 95 | 96 | /* 97 | * @fn calculate_normalization_constant 98 | * @brief Calculates the normalization constant so that =1 99 | * 100 | * @return void 101 | */ 102 | void GTO::calculate_normalization_constant() { 103 | static const double pi = 3.14159265359; 104 | 105 | double nom = std::pow(2.0, 2.0 * (l + m + n) + 3.0 / 2.0) * 106 | std::pow(alpha, (l + m + n) + 3.0 / 2.0); 107 | 108 | double denom = (l < 1 ? 1 : boost::math::double_factorial(2 * l - 1) )* 109 | (m < 1 ? 1 : boost::math::double_factorial(2 * m - 1) )* 110 | (n < 1 ? 1 : boost::math::double_factorial(2 * n - 1) )* 111 | std::pow(pi, 3.0 / 2.0); 112 | 113 | this->norm = std::sqrt(nom / denom); 114 | } 115 | 116 | /* 117 | * @fn CGF 118 | * @brief Constructor 119 | * 120 | * @return CGF 121 | */ 122 | CGF::CGF(): 123 | r(vec3(0,0,0)) { 124 | // do nothing 125 | } 126 | 127 | /* 128 | * @fn CGF 129 | * @brief Default constructor 130 | * 131 | * @return CGF 132 | */ 133 | CGF::CGF(const vec3& _r): 134 | r(_r) { 135 | // do nothing 136 | } 137 | 138 | /* 139 | * @fn get_amp 140 | * @brief Gets the amplitude of the CGF 141 | * 142 | * @param vec3 r coordinates 143 | * 144 | * @return const double amplitude 145 | */ 146 | const double CGF::get_amp(const vec3& r) const { 147 | double sum = 0.0; 148 | 149 | for(const auto& gto : this->gtos) { 150 | sum += gto.get_coefficient() * gto.get_amp(r); 151 | } 152 | 153 | return sum; 154 | } 155 | 156 | /* 157 | * @fn get_amp 158 | * @brief Gets the gradient of the CGF 159 | * 160 | * @param vec3 r coordinates 161 | * 162 | * @return gradient 163 | */ 164 | vec3 CGF::get_grad(const vec3& r) const { 165 | vec3 sum = vec3(0,0,0); 166 | 167 | for(const auto& gto : this->gtos) { 168 | sum += gto.get_coefficient() * gto.get_grad(r); 169 | } 170 | 171 | return sum; 172 | } 173 | 174 | /* 175 | * @fn add_GTO 176 | * @brief Add a GTO to the CGF 177 | * 178 | * @param unsigned int type type of the orbital (see above for the list) 179 | * @param double alpha alpha value 180 | * @param double c coefficient 181 | * @param const vec3& vec3 position 182 | * 183 | * @return void 184 | */ 185 | void CGF::add_gto(unsigned int type, // type of the orbital (see above for the list) 186 | double alpha, // alpha value 187 | double c, // coefficient 188 | const vec3& vec3) { // position 189 | 190 | switch(type) { 191 | // S ORBITAL 192 | case GTO_S: 193 | gtos.push_back(GTO(c, r, alpha, 0,0,0)); 194 | break; 195 | 196 | // P ORBITALS 197 | case GTO_PX: 198 | gtos.push_back(GTO(c, r, alpha, 1,0,0)); 199 | break; 200 | case GTO_PY: 201 | gtos.push_back(GTO(c, r, alpha, 0,1,0)); 202 | break; 203 | case GTO_PZ: 204 | gtos.push_back(GTO(c, r, alpha, 0,0,1)); 205 | break; 206 | 207 | // D ORBITALS 208 | case GTO_DX2: 209 | gtos.push_back(GTO(c, r, alpha, 2,0,0)); 210 | break; 211 | case GTO_DXY: 212 | gtos.push_back(GTO(c, r, alpha, 1,1,0)); 213 | break; 214 | case GTO_DXZ: 215 | gtos.push_back(GTO(c, r, alpha, 1,0,1)); 216 | break; 217 | case GTO_DY2: 218 | gtos.push_back(GTO(c, r, alpha, 0,2,0)); 219 | break; 220 | case GTO_DYZ: 221 | gtos.push_back(GTO(c, r, alpha, 0,1,1)); 222 | break; 223 | case GTO_DZ2: 224 | gtos.push_back(GTO(c, r, alpha, 0,0,2)); 225 | break; 226 | 227 | default: 228 | std::cerr << "Undefined orbital type. Exiting..." << std::endl; 229 | exit(-1); 230 | break; 231 | } 232 | } 233 | 234 | /* 235 | * @fn set_position 236 | * @brief Set a (new) center for the CGF 237 | * 238 | * @param pos center of the CGF 239 | * 240 | * @return void 241 | */ 242 | void CGF::set_position(const vec3 &pos) { 243 | this->r = pos; 244 | 245 | for(unsigned int i=0; igtos.size(); i++) { 246 | this->gtos[i].set_position(pos); 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /src/dft.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _DFT_H 23 | #define _DFT_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "molecule.h" 32 | #include "moleculargrid.h" 33 | #include "integrals.h" 34 | #include "functionals.h" 35 | #include "rectangulargrid.h" 36 | #include "settings.h" 37 | 38 | typedef Eigen::Matrix MatrixXXd; 39 | typedef Eigen::Matrix VectorXd; 40 | 41 | class DFT { 42 | private: 43 | std::shared_ptr mol; // pointer to molecule class 44 | std::unique_ptr molgrid; // pointer to molecular grid 45 | std::shared_ptr integrator; // pointer to integrator class 46 | std::shared_ptr functional; // pointer to functional class 47 | std::shared_ptr settings; // pointer to settings class 48 | 49 | const std::vector* cgfs; // pointer vector of Contracted Gaussian Functions 50 | 51 | MatrixXXd S; // overlap matrix 52 | MatrixXXd T; // kinetic matrix 53 | MatrixXXd V; // nuclear attraction matrix 54 | MatrixXXd H; // single electron matrix 55 | VectorXd ints; // two-electron integrals 56 | 57 | MatrixXXd X; // transformation matrix 58 | MatrixXXd Xp; // transpose of transformation matrix 59 | MatrixXXd Cc; // basis set eigenvectors in transformed basis 60 | MatrixXXd C; // basis set eigenvectors in original basis 61 | MatrixXXd P; // density matrix 62 | MatrixXXd J; // two-electron (coulomb) repulsion matrix 63 | MatrixXXd XC; // two-electron exchange-correlation matrix 64 | 65 | unsigned int nelec; // number of electrons of the molecule 66 | 67 | double exc; // exchange correlation energy 68 | double enuc; // nuclear repulsion energy 69 | double et; // total energy 70 | double single_electron_energy; // total single electron energy 2*trace(P * H) 71 | double electronic_repulsion; // total electronic repulsion 2*trace(P * J) 72 | 73 | bool is_first; // whether this is the first iteration 74 | 75 | public: 76 | 77 | /** 78 | * @fn DFT 79 | * @brief DFT routine constructor 80 | * 81 | * @return DFT instance 82 | */ 83 | DFT(const std::string& filename); 84 | 85 | /** 86 | * @fn scf 87 | * @brief perform the self-consistent field iterations 88 | * 89 | * @return void 90 | */ 91 | void scf(); 92 | 93 | private: 94 | /* 95 | * construction functions 96 | */ 97 | 98 | /** 99 | * @fn add_molecule 100 | * @brief add molecule to the DFT routine 101 | * 102 | * @param _mol pointer to Molecule class 103 | * 104 | * Links molecule to the DFT routine by a pointer. The 105 | * Contracted Gaussian Functions of the molecule are copied 106 | * to the DFT routine class and the routine matrices are 107 | * constructed. 108 | * 109 | * @return void 110 | */ 111 | void add_molecule(const std::shared_ptr& _mol); 112 | 113 | /** 114 | * @fn copy_cgfs_from_molecule 115 | * @brief copy cgfs from the molecule class to the dft class 116 | * 117 | * @return void 118 | */ 119 | void copy_cgfs_from_molecule(); 120 | 121 | /** 122 | * @fn construct_matrices 123 | * @brief construct the matrices and two-electron integrals for the SCF procedure 124 | * 125 | * @return void 126 | */ 127 | void construct_matrices(); 128 | 129 | /** 130 | * @fn calculate_nuclear_repulsion 131 | * @brief calculate the nuclear repulsion energy 132 | * 133 | * @return void 134 | */ 135 | void calculate_nuclear_repulsion(); 136 | 137 | /** 138 | * @fn calculate_two_electron_integrals 139 | * @brief calculate the two-electron integrals 140 | * 141 | * @return void 142 | */ 143 | void calculate_two_electron_integrals(); 144 | 145 | /** 146 | * @fn calculate_transformation_matrix 147 | * @brief calculate the transformation matrix X from the overlap matrix S 148 | * 149 | * The transformation matrix X is calculated from the overlap matrix S by 150 | * canonical orthogonalization. This transformation matrix X ensures that 151 | * the Slater determinant consists of orthogonal spin-orbitals. 152 | * 153 | * @return void 154 | */ 155 | void calculate_transformation_matrix(); 156 | 157 | /* 158 | * functions for the SCF routine 159 | */ 160 | 161 | /** 162 | * @fn calculate_density_matrix 163 | * @brief calculate the density matrix from the coefficient matrix 164 | * 165 | * Performs eigenvector decomposition on the Fock matrix F. From these 166 | * the coefficients in the transformed basis are calculated. The basis 167 | * function coefficients in the original basis can be obtained by 168 | * using the transformation matrix X. From these coefficients in the 169 | * original representation, the density matrix P is calculated. 170 | * 171 | * @return void 172 | */ 173 | void calculate_density_matrix(); 174 | 175 | /** 176 | * @fn calculate_electronic_repulsion_matrix 177 | * @brief calculates electronic repulsion matrix 178 | * 179 | * Calculate the electronic repulsion matrix using the 180 | * density matrix and the two-electron integrals. 181 | * 182 | * @return void 183 | */ 184 | void calculate_electronic_repulsion_matrix(); 185 | 186 | /** 187 | * @fn calculate_exchange_correlation_matrix 188 | * @brief calculates the exchange-correlation matrix 189 | * 190 | * @return void 191 | */ 192 | void calculate_exchange_correlation_matrix(); 193 | 194 | /** 195 | * @fn calculate_energy 196 | * @brief calculate the energy of the molecule 197 | * 198 | * @return void 199 | */ 200 | void calculate_energy(); 201 | 202 | /** 203 | * @brief Calculates the hartree potential from two electrons integrals 204 | */ 205 | void calculate_hartree_potential_te_int(); 206 | 207 | /** 208 | * @brief Calculates the hartree potential over Becke grid using Poisson equation 209 | */ 210 | void calculate_hartree_potential_becke_poisson(); 211 | 212 | /* 213 | * @brief Finalize calculation and store requested data 214 | */ 215 | void finalize(); 216 | }; 217 | 218 | #endif //_DFT_H 219 | -------------------------------------------------------------------------------- /src/gridpoint.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _GRIDPOINT_H 23 | #define _GRIDPOINT_H 24 | 25 | #include 26 | 27 | #include "molecule.h" 28 | 29 | typedef Eigen::Vector3d vec3; 30 | typedef Eigen::Matrix VectorXd; 31 | typedef Eigen::Matrix MatrixXXd; 32 | 33 | /* 34 | * @class GridPoint 35 | * @brief Represents a point in the molecular grid 36 | * 37 | * Grid point at position r; stores local information such as the amplitude 38 | * of all the basis functions in the basis set and the local density. 39 | * 40 | * Numerical integrations of any kind of property is conducted by 41 | * evaluating the local value of the functional at the grid point and 42 | * multiplying this by the weight of the grid point. Integration is then 43 | * performed by summing over all the grid points. 44 | * 45 | * The weights take into account: 46 | * - the Jacobian for integration into spherical coordinates 47 | * - the weight for the Lebedev integration (angular part) 48 | * - the weight for the Gauss-Chebyshev integration (radial part) 49 | * - the weight for the Becke grid (see: http://dx.doi.org/10.1063/1.454033) 50 | * 51 | */ 52 | class GridPoint { 53 | private: 54 | const vec3 r; // position in 3D space 55 | const vec3 r_at; // get position relative to atom the gridpoint adheres to 56 | 57 | double w; // weight 58 | double w_becke; // Fuzzy cell weight 59 | double density; // current density at grid point 60 | vec3 grad; // gradient 61 | 62 | const Atom* atom; // atom this gridpoint adheres to 63 | VectorXd basis_func_amp; // amplitude of basis functions at gridpoint 64 | MatrixXXd basis_func_grad; // gradient of basis functions at gridpoint 65 | 66 | public: 67 | /** 68 | * @brief construct grid point 69 | * 70 | * @param[in] _r position in complete space 71 | * @param[in] _r_at position in fuzzy cell 72 | */ 73 | GridPoint(const vec3& _r, const vec3& _r_at); 74 | 75 | /* 76 | * SETTERS 77 | */ 78 | 79 | /** 80 | * @fn set_weight 81 | * @brief set the weight at the grid point 82 | * 83 | * @param _w value of the weight 84 | * 85 | * @return void 86 | */ 87 | inline void set_weight(double _w) { 88 | this->w = _w; 89 | } 90 | 91 | /** 92 | * @brief Sets the becke weight. 93 | * 94 | * @param[in] bw becke weight 95 | */ 96 | inline void set_becke_weight(double bw) { 97 | this->w_becke = bw; 98 | } 99 | 100 | /** 101 | * @brief Gets the becke weight. 102 | * 103 | * @return The becke weight. 104 | */ 105 | inline double get_becke_weight() const { 106 | return this->w_becke; 107 | } 108 | 109 | /** 110 | * @fn multiply_weight 111 | * @brief multiply weight by factor at the grid point 112 | * 113 | * @param _w weight multiplication factor 114 | * 115 | * @return void 116 | */ 117 | inline void multiply_weight(double _w) { 118 | this->w *= _w; 119 | } 120 | 121 | /** 122 | * @brief multiply density by correction factor 123 | * 124 | * @param[in] _d correction factor 125 | */ 126 | inline void multiply_density(double _d) { 127 | this->density *= _d; 128 | } 129 | 130 | /** 131 | * @fn set_atom 132 | * @brief defines the atom to which this grid point is 'linked' 133 | * 134 | * @param at pointer to Atom class 135 | * 136 | * @return void 137 | */ 138 | inline void set_atom(const Atom* at) { 139 | this->atom = at; 140 | } 141 | 142 | /** 143 | * @fn set_basis_func_amp 144 | * @brief calculates the amplitudes at the grid point of all basis functions 145 | * 146 | * @param _mol pointer to the molecule object 147 | * 148 | * @return void 149 | */ 150 | void set_basis_func_amp(const std::shared_ptr& _mol); 151 | 152 | /** 153 | * @fn set_basis_func_grad 154 | * @brief calculates the gradient at the grid point of all basis functions 155 | * 156 | * @param _mol pointer to the molecule object 157 | * 158 | * @return void 159 | */ 160 | void set_basis_func_grad(const std::shared_ptr& _mol); 161 | 162 | /** 163 | * @fn set_density 164 | * @brief calculates the density at the grid point using the density matrix 165 | * 166 | * @param _mol reference to density matrix 167 | * 168 | * @return void 169 | */ 170 | void set_density(const MatrixXXd& D); 171 | 172 | /** 173 | * @fn set_gradient 174 | * @brief calculates the gradient at the grid point using the density matrix 175 | * 176 | * @param _mol reference to density matrix 177 | * 178 | * @return void 179 | */ 180 | void set_gradient(const MatrixXXd& D); 181 | 182 | /* 183 | * GETTERS 184 | */ 185 | 186 | /** 187 | * @fn get_position 188 | * @brief get the position of the grid point 189 | * 190 | * @return vec3 position of the grid point 191 | */ 192 | inline const vec3& get_position() const { 193 | return this->r; 194 | } 195 | 196 | /** 197 | * @fn get_position_fuzzy_cell 198 | * @brief get the position of the grid point relative to fuzzy cell 199 | * 200 | * @return vec3 position of the grid point relative to fuzzy cell 201 | */ 202 | inline const vec3& get_position_fuzzy_cell() const { 203 | return this->r_at; 204 | } 205 | 206 | /** 207 | * @fn get_atom_position 208 | * @brief get the position of the atom to which this grid point is 'linked' 209 | * 210 | * @return vec3 position of the atom 211 | */ 212 | inline const vec3& get_atom_position() const { 213 | return this->atom->get_position(); 214 | } 215 | 216 | /** 217 | * @fn get_weight 218 | * @brief get the weight of the grid point in the numerical integration 219 | * 220 | * @return double weight 221 | */ 222 | inline const double get_weight() const { 223 | return this->w; 224 | } 225 | 226 | /** 227 | * @fn get_density 228 | * @brief get the electron density at the grid point 229 | * 230 | * @return double density 231 | */ 232 | inline const double get_density() const { 233 | return this->density; 234 | } 235 | 236 | /** 237 | * @fn get_gradient 238 | * @brief get the electron density gradient at the grid point 239 | * 240 | * @return gradient 241 | */ 242 | inline const vec3& get_gradient() const { 243 | return this->grad; 244 | } 245 | 246 | /** 247 | * @fn get_basis_func_amp 248 | * @brief get the amplitude of the basis functions 249 | * 250 | * @return (Eigen3) vector containing basis function amplitudes 251 | */ 252 | inline const VectorXd& get_basis_func_amp() const { 253 | return this->basis_func_amp; 254 | } 255 | }; 256 | 257 | #endif // _GRIDPOINT_H 258 | -------------------------------------------------------------------------------- /src/gamma.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | /* 23 | * Incomplete Gamma Function 24 | * 25 | * Used in the evaluation of the two-electron integrals. 26 | * 27 | */ 28 | 29 | /* 30 | * The functions below were extracted from: 31 | * 32 | * Numerical Recipes 33 | * William H. Press, Saul A. Teukolsky, William T., 34 | * Vetterling and Brian P. Flannery 35 | * 3rd edition page 261 36 | * ISBN-13: 978-0521880688 37 | */ 38 | 39 | #include "gamma.h" 40 | 41 | double GammaInc::Fgamma(const double m, double x) { 42 | double tiny = 0.00000001; 43 | x = std::max(std::abs(x),tiny); 44 | double val = gamm_inc(m+0.5,x); 45 | return 0.5 * std::pow(x,-m - 0.5) * val; 46 | } 47 | 48 | /* 49 | * @fn gamm_inc 50 | * @brief Calculates the incomplete gamma function P(a,x) 51 | * 52 | * gamma(a,x) 53 | * ---------- 54 | * G(a) 55 | * 56 | * @param a "squared width" of the IGF 57 | * @param x Upper bound of the integral in the IGF 58 | * 59 | * returns double value of the incomplete Gamma Function 60 | */ 61 | double GammaInc::gamm_inc(const double a, const double x) { 62 | double gammap = gammp(a,x); 63 | double gln = gammln(a); 64 | return exp(gln) * gammap; 65 | } 66 | 67 | /* 68 | * @fn gamm_inc 69 | * @brief Calculates the incomplete gamma function P(a,x) 70 | * 71 | * This routine selects the best function to use in the 72 | * evaluation of the Incomplete Gamma Function (IGF). 73 | * 74 | * @param a "squared width" of the IGF 75 | * @param x Upper bound of the integral in the IGF 76 | * 77 | * returns double value of the incomplete Gamma Function 78 | */ 79 | double GammaInc::gammp(const double a, double x) { 80 | static const int ASWITCH = 100; 81 | 82 | if(x < 0.0 || a <= 0.0) { 83 | std::cerr << "Bad value in Fgamma!"; 84 | return 0.0; 85 | } 86 | 87 | if(x == 0.0) { 88 | return 0.0; 89 | } else if(a >= ASWITCH) { 90 | return gammpapprox(a,x,1); /* use quadrature */ 91 | } else if(x < a + 1.0) { 92 | return gser(a,x); /* use the series expansion */ 93 | } else { 94 | return 1.0 - gcf(a,x); /* use the continued fraction expansion */ 95 | } 96 | } 97 | 98 | /* 99 | * @fn gser 100 | * @brief Gamma function P(a,x) evaluated by its series representation 101 | * 102 | * @param a "squared width" of the IGF 103 | * @param x Upper bound of the integral in the IGF 104 | * 105 | * returns double value of the incomplete Gamma Function 106 | */ 107 | double GammaInc::gser(const double a, const double x) { 108 | double EPS = std::numeric_limits::epsilon(); 109 | 110 | double sum, del, ap; 111 | double gln = gammln(a); 112 | ap = a; 113 | 114 | del = sum = 1.0/a; 115 | for(;;) { 116 | ++ap; 117 | del *= x / ap; 118 | sum += del; 119 | if(std::fabs(del) < std::fabs(sum)*EPS) { 120 | return sum * exp(-x +a*std::log(x)-gln); 121 | } 122 | } 123 | } 124 | 125 | double GammaInc::gammln(const double xx) { 126 | int j; 127 | double x, tmp, y, ser; 128 | static const double cof[14]={57.1562356658629235,-59.5979603554754912, 129 | 14.1360979747417471,-0.491913816097620199,.339946499848118887e-4, 130 | .465236289270485756e-4,-.983744753048795646e-4,.158088703224912494e-3, 131 | -.210264441724104883e-3,.217439618115212643e-3,-.164318106536763890e-3, 132 | .844182239838527433e-4,-.261908384015814087e-4,.368991826595316234e-5}; 133 | if(xx <= 0) { 134 | std::cerr << "Bad argument in gammln"; 135 | return 0.0; 136 | } 137 | 138 | y = x = xx; 139 | tmp = x+5.24218750000000000; 140 | tmp = (x+0.5)*std::log(tmp)-tmp; 141 | ser = 0.999999999999997092; 142 | for (j=0;j<14;j++) ser += cof[j]/++y; 143 | return tmp+std::log(2.5066282746310005*ser/x); 144 | } 145 | 146 | /* 147 | * @fn gcf 148 | * @brief Gamma function P(a,x) evaluated by its continued fraction representation 149 | * 150 | * @param a "squared width" of the IGF 151 | * @param x Upper bound of the integral in the IGF 152 | * 153 | * returns double value of the incomplete Gamma Function 154 | */ 155 | double GammaInc::gcf(const double a, const double x) { 156 | double EPS = std::numeric_limits::epsilon(); 157 | double FPMIN = std::numeric_limits::min() / EPS; 158 | 159 | int i; 160 | double an, b, c, d, del, h; 161 | double gln = gammln(a); 162 | b = x + 1.0 - a; 163 | c = 1.0 / FPMIN; 164 | d = 1.0 /b; 165 | h = d; 166 | for(i=1;;i++) { 167 | an = -i * (i-a); 168 | b += 2.0; 169 | d = an * d + b; 170 | if(std::fabs(d) < FPMIN) d = FPMIN; 171 | c = b + an /c; 172 | if(std::fabs(c) < FPMIN) c = FPMIN; 173 | d = 1.0 / d; 174 | del = d * c; 175 | h *= del; 176 | if(std::fabs(del - 1.0) <= EPS) break; 177 | } 178 | 179 | return exp(-x + a * std::log(x) - gln)*h; 180 | } 181 | 182 | /* 183 | * @fn gammpapprox 184 | * @brief Incomplete Gamma function P(a,x) or Q(a,x) evaluated by quadrature 185 | * 186 | * Returns P(a,x) or Q(a,x), when psig is 1 or 0, respectively. 187 | * 188 | * @param a "squared width" of the IGF 189 | * @param x Upper bound of the integral in the IGF 190 | * @param psig Whether to evaluate P(a,x) or Q(a,x) 191 | * 192 | * returns double value of the incomplete Gamma Function 193 | */ 194 | double GammaInc::gammpapprox(double a, double x, int psig) { 195 | static const int ngau = 18; 196 | 197 | double y[18] = {0.0021695375159141994, 198 | 0.011413521097787704,0.027972308950302116,0.051727015600492421, 199 | 0.082502225484340941, 0.12007019910960293,0.16415283300752470, 200 | 0.21442376986779355, 0.27051082840644336, 0.33199876341447887, 201 | 0.39843234186401943, 0.46931971407375483, 0.54413605556657973, 202 | 0.62232745288031077, 0.70331500465597174, 0.78649910768313447, 203 | 0.87126389619061517, 0.95698180152629142}; 204 | 205 | double w[18] = {0.0055657196642445571, 206 | 0.012915947284065419,0.020181515297735382,0.027298621498568734, 207 | 0.034213810770299537,0.040875750923643261,0.047235083490265582, 208 | 0.053244713977759692,0.058860144245324798,0.064039797355015485, 209 | 0.068745323835736408,0.072941885005653087,0.076598410645870640, 210 | 0.079687828912071670,0.082187266704339706,0.084078218979661945, 211 | 0.085346685739338721,0.085983275670394821}; 212 | 213 | int j; 214 | double xu, t, sum, ans; 215 | double a1 = a - 1.0, lna1 = std::log(a1), sqrta1 = sqrt(a1); 216 | double gln = gammln(a); 217 | 218 | if(x > a1) xu = std::max(a1 + 11.5 * sqrta1, x + 6.0 * sqrta1); 219 | else xu = std::max(0., std::min(a1 - 7.5 * sqrta1, x - 5.0 * sqrta1)); 220 | sum = 0; 221 | 222 | for(j=0; j < ngau; j++) { 223 | t = x + (xu-x)*y[j]; 224 | sum += w[j] * exp(-(t-a1)+a1*(std::log(t)-lna1)); 225 | } 226 | 227 | ans = sum * (xu-x)*exp(a1*(lna1-1.)-gln); 228 | return (psig?(ans>0.0? 1.0-ans:-ans):(ans>=0.0? ans:1.0+ans)); 229 | } 230 | -------------------------------------------------------------------------------- /src/cgf.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _CGF_H 23 | #define _CGF_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | typedef Eigen::Vector3d vec3; 30 | 31 | /* 32 | * Gaussian Type Orbital 33 | * 34 | * N * (x-X)^l * (y-Y)^m * (z-Z)^n * exp(-alpha * r^2) 35 | * 36 | * where r = sqrt(x^2 + y^2 + z^2) 37 | * and N a normalization constant such that = 1 38 | * 39 | */ 40 | 41 | class GTO { // Gaussian Type Orbital 42 | private: 43 | double c; // coefficient 44 | double alpha; // alpha value in the exponent 45 | unsigned int l,m,n; // powers of the polynomial 46 | vec3 position; // position vector (unit = Bohr) 47 | double norm; // normalization constant 48 | 49 | public: 50 | /* 51 | * @fn GTO 52 | * @brief Construct Gaussian Type Orbital 53 | * 54 | * @param _c coefficient 55 | * @param _position position of the Gaussian 56 | * @param _alpha alpha value in the exponent 57 | * @param _l power of x in the polynomial 58 | * @param _m power of y in the polynomial 59 | * @param _n power of z in the polynomial 60 | * 61 | * returns double value of the incomplete Gamma Function 62 | */ 63 | GTO(double _c, 64 | const vec3& _position, 65 | double _alpha, 66 | unsigned int _l, 67 | unsigned int _m, 68 | unsigned int _n); 69 | 70 | /* 71 | * INLINE GETTERS 72 | */ 73 | 74 | /* 75 | * @fn get_coefficient 76 | * @brief get the coefficient 77 | * 78 | * @return const double coefficient 79 | */ 80 | inline const double get_coefficient() const { 81 | return this->c; 82 | } 83 | 84 | /* 85 | * @fn get_coefficient 86 | * @brief Gets the alpha value in the polynomial 87 | * 88 | * @return const double coefficient 89 | */ 90 | inline const double get_alpha() const { 91 | return this->alpha; 92 | } 93 | 94 | /* 95 | * @fn get_l 96 | * @brief Gets power of the x component 97 | * 98 | * @return const double power 99 | */ 100 | inline const unsigned int get_l() const { 101 | return this->l; 102 | } 103 | 104 | /* 105 | * @fn get_m 106 | * @brief Gets power of the y component 107 | * 108 | * @return const double power 109 | */ 110 | inline const unsigned int get_m() const { 111 | return this->m; 112 | } 113 | 114 | /* 115 | * @fn get_n 116 | * @brief Gets power of the z component 117 | * 118 | * @return const double power 119 | */ 120 | inline const unsigned int get_n() const { 121 | return this->n; 122 | } 123 | 124 | /* 125 | * @fn get normalization constant 126 | * @brief Returns the constant that ensures that the GTO is normalized 127 | * 128 | * @return const double norm constant 129 | */ 130 | inline const double get_norm() const { 131 | return this->norm; 132 | } 133 | 134 | /* 135 | * @fn get_position 136 | * @brief Get the center of the Gaussian 137 | * 138 | * @return const double vec3 139 | */ 140 | inline const vec3& get_position() const { 141 | return this->position; 142 | } 143 | 144 | /* 145 | * @fn get_amp 146 | * @brief Gets the amplitude of the GTO 147 | * 148 | * @param vec3 r coordinates 149 | * 150 | * @return const double amplitude 151 | */ 152 | const double get_amp(const vec3& r) const; 153 | 154 | /* 155 | * @fn get_gradient 156 | * @brief Gets the gradient of the GTO 157 | * 158 | * @param vec3 r coordinates 159 | * 160 | * @return gradient 161 | */ 162 | vec3 get_grad(const vec3& r) const; 163 | 164 | /* 165 | * @fn set_position 166 | * @brief Set (new) position of GTO 167 | * 168 | * @return void 169 | */ 170 | inline void set_position(const vec3& _position) { 171 | this->position = _position; 172 | } 173 | 174 | private: 175 | /* 176 | * @fn calculate_normalization_constant 177 | * @brief Calculates the normalization constant so that =1 178 | * 179 | * @return void 180 | */ 181 | void calculate_normalization_constant(); 182 | }; 183 | 184 | 185 | class CGF { // Contracted Gaussian Function 186 | private: 187 | std::vector gtos; // vector holding all gtos 188 | vec3 r; // position of the CGF 189 | 190 | public: 191 | /* 192 | * @fn CGF 193 | * @brief Constructor 194 | * 195 | * @return CGF 196 | */ 197 | CGF(); 198 | 199 | /* 200 | * @fn CGF 201 | * @brief Default constructor 202 | * 203 | * @return CGF 204 | */ 205 | CGF(const vec3& _r); 206 | 207 | // type of GTOs to add 208 | enum{ 209 | GTO_S, 210 | GTO_PX, 211 | GTO_PY, 212 | GTO_PZ, 213 | GTO_DX2, 214 | GTO_DXY, 215 | GTO_DXZ, 216 | GTO_DY2, 217 | GTO_DYZ, 218 | GTO_DZ2, 219 | 220 | NUM_GTO 221 | }; 222 | 223 | /* 224 | * @fn size 225 | * @brief Returns the length of the contraction 226 | * 227 | * @return unsigned int length 228 | */ 229 | inline const unsigned int size() const { 230 | return this->gtos.size(); 231 | } 232 | 233 | /* 234 | * @fn size 235 | * @brief Returns the normalization constant of a GTO 236 | * 237 | * @param unsigned int i ith GTO in the CGF 238 | * 239 | * @return double normalization constant 240 | */ 241 | inline const double get_norm_gto(const unsigned int i) const { 242 | return this->gtos[i].get_norm(); 243 | } 244 | 245 | /* 246 | * @fn size 247 | * @brief Returns the coefficient of the GTO 248 | * 249 | * @param unsigned int i ith GTO in the CGF 250 | * 251 | * @return double GTO coefficient 252 | */ 253 | inline const double get_coefficient_gto(const unsigned int i) const { 254 | return this->gtos[i].get_coefficient(); 255 | } 256 | 257 | /* 258 | * @fn size 259 | * @brief Returns the GTO 260 | * 261 | * @param unsigned int i ith GTO in the CGF 262 | * 263 | * @return GTO 264 | */ 265 | inline const GTO& get_gto(const unsigned int i) const { 266 | return this->gtos[i]; 267 | } 268 | 269 | /* 270 | * @fn get_amp 271 | * @brief Gets the amplitude of the CGF 272 | * 273 | * @param vec3 r coordinates 274 | * 275 | * @return const double amplitude 276 | */ 277 | const double get_amp(const vec3& r) const; 278 | 279 | /* 280 | * @fn get_amp 281 | * @brief Gets the gradient of the CGF 282 | * 283 | * @param vec3 r coordinates 284 | * 285 | * @return gradient 286 | */ 287 | vec3 get_grad(const vec3& r) const; 288 | 289 | /* 290 | * @fn add_GTO 291 | * @brief Add a GTO to the CGF 292 | * 293 | * @param unsigned int type type of the orbital (see above for the list) 294 | * @param double alpha alpha value 295 | * @param double c coefficient 296 | * @param const vec3& vec3 position 297 | * 298 | * @return void 299 | */ 300 | void add_gto(unsigned int type, 301 | double alpha, 302 | double c, 303 | const vec3& vec3); 304 | 305 | /* 306 | * @fn set_position 307 | * @brief Set a (new) center for the CGF 308 | * 309 | * @param pos center of the CGF 310 | * 311 | * @return void 312 | */ 313 | void set_position(const vec3 &pos); 314 | }; 315 | 316 | #endif //_CGF_H 317 | -------------------------------------------------------------------------------- /src/atomicgrid.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #ifndef _ATOMIC_GRID_H 23 | #define _ATOMIC_GRID_H 24 | 25 | #include "gridpoint.h" 26 | #include "quadrature.h" 27 | #include "molecule.h" 28 | #include "cspline.h" 29 | #include "spherical_harmonics.h" 30 | 31 | class AtomicGrid { 32 | private: 33 | static constexpr double pi = 3.14159265358979323846; 34 | 35 | // pointer to Atom object 36 | std::shared_ptr atom; 37 | 38 | // pointer to molecule object 39 | std::shared_ptr mol; 40 | 41 | // density coefficients (MXN) matrix where M are the radial points and N the combined lm index 42 | MatrixXXd rho_lm; 43 | 44 | // hartree potential coefficient (MXN) matrix where M are the radial points and N the combined lm index 45 | MatrixXXd U_lm; 46 | unsigned int lm; 47 | 48 | // hartree potential 49 | VectorXd V_fuzzy_cell; 50 | VectorXd V; 51 | 52 | // vector holding radial distances 53 | VectorXd r_n; 54 | 55 | std::vector grid; // set of all gridpoints 56 | 57 | std::vector splines; 58 | 59 | unsigned int angular_points; 60 | unsigned int radial_points; 61 | unsigned int lebedev_offset; 62 | unsigned int lmax; 63 | 64 | MatrixXXd Jj; // numerical J matrix for this atom 65 | double density; // total electron density for this fuzzy cell 66 | bool density_cached; // whether density has been evaluated 67 | 68 | public: 69 | 70 | /** 71 | * @brief create atomic grid 72 | * 73 | * @param[in] _atom pointer to atom 74 | */ 75 | AtomicGrid(const std::shared_ptr& _atom); 76 | 77 | /** 78 | * @brief Creates an atomic grid. 79 | * 80 | * @param[in] _radial_points number of radial points 81 | * @param[in] _angular_points number of angular points 82 | * @param[in] _lebedev_offset lebedev offset 83 | * @param[in] _lmax maximum angular quantum number l 84 | * @param[in] _mol pointer to molecule 85 | */ 86 | void create_atomic_grid(unsigned int _radial_points, 87 | unsigned int _angular_points, 88 | unsigned int _lebedev_offset, 89 | unsigned int _lmax, 90 | const std::shared_ptr& _mol); 91 | 92 | /** 93 | * @brief Gets the grid size. 94 | * 95 | * @return The grid size. 96 | */ 97 | inline size_t get_grid_size() const { 98 | return this->grid.size(); 99 | } 100 | 101 | /** 102 | * @brief get the center position of the fuzzy cell 103 | * 104 | * @return fuzzy cell center position 105 | */ 106 | inline const vec3& get_position() const { 107 | return this->atom->get_position(); 108 | } 109 | 110 | /** 111 | * @brief get the position of the grid point 112 | * 113 | * @param[in] idx index of grid point 114 | * 115 | * @return grid point position 116 | */ 117 | inline const vec3& get_position_grid_point(unsigned int idx) const { 118 | return this->grid[idx].get_position(); 119 | } 120 | 121 | /** 122 | * @fn get_density 123 | * @brief get the total electron density 124 | * 125 | * @return total electron density 126 | */ 127 | double get_density(); 128 | 129 | /** 130 | * @fn set_density 131 | * @brief set the density at the grid point given a density matrix 132 | * 133 | * @param P reference to density matrix 134 | * 135 | * Loops over all the grid points and calculates the local density 136 | * using the amplitudes of the basis functions and the density matrix 137 | * 138 | * @return void 139 | */ 140 | void set_density(const MatrixXXd& P); 141 | 142 | /** 143 | * @brief correct the densities 144 | * 145 | * @param[in] correction_factor The correction factor 146 | */ 147 | void correct_density(double correction_factor); 148 | 149 | /** 150 | * @fn get_weights 151 | * @brief get the weights of all the grid points as a vector 152 | * 153 | * @return vector containing all the weights 154 | */ 155 | VectorXd get_weights() const; 156 | 157 | /** 158 | * @fn get_densities 159 | * @brief get the densities of all the grid points as a vector 160 | * 161 | * @return vector containing all the densities 162 | */ 163 | VectorXd get_densities() const; 164 | 165 | /** 166 | * @fn get_positions 167 | * @brief get the positions of all the grid points as a vector 168 | * 169 | * @return vector containing all the positions 170 | */ 171 | MatrixXXd get_positions() const; 172 | 173 | /** 174 | * @brief set fuzzy cell weights 175 | * 176 | * @param[in] vw fuzzy cell weights 177 | */ 178 | void set_becke_weights(const VectorXd& vw); 179 | 180 | /** 181 | * @fn get_amplitudes 182 | * @brief get the amplitudes of all the grid points and all the basis functions as a matrix 183 | * 184 | * @return matrix (basis functions x grid points) 185 | */ 186 | MatrixXXd get_amplitudes() const; 187 | 188 | /** 189 | * @brief get coulomb matrix 190 | * 191 | * @return Coulomb matrix 192 | */ 193 | inline const MatrixXXd& get_J() const { 194 | return this->Jj; 195 | } 196 | 197 | /** 198 | * @brief calculate density at distance r 199 | */ 200 | void calculate_rho_lm(); 201 | 202 | /** 203 | * @brief calculate spherical harmonic coefficients 204 | */ 205 | void calculate_U_lm(); 206 | 207 | /** 208 | * @brief Calculates the j matrix. 209 | */ 210 | void calculate_J_matrix(); 211 | 212 | /** 213 | * @brief Gets the sh value. 214 | * 215 | * @param[in] r radial distance from fuzzy cell center 216 | * @param[in] lm lm index 217 | * 218 | * @return The sh value. 219 | */ 220 | double get_sh_value(double r, unsigned int lm) const; 221 | 222 | /** 223 | * @brief get the local hartree potential for this fuzzy cell 224 | * 225 | * @param[in] idx grid point index 226 | * 227 | * @return local cell hartree potential Vn 228 | */ 229 | inline double get_V(unsigned int idx) const { 230 | return this->V_fuzzy_cell(idx); 231 | } 232 | 233 | /** 234 | * @brief Set total Hartree potential for gridpoint 235 | * 236 | * @param[in] idx grid point index 237 | * @param[in] v total hartree potential 238 | */ 239 | inline void set_V_gp(unsigned int idx, double v) { 240 | this->V(idx) = v; 241 | } 242 | 243 | private: 244 | double d2zdr2(double r, double m); 245 | 246 | double dzdrsq(double r, double m); 247 | 248 | /** 249 | * @fn calculate_density 250 | * @brief calculate the total electron density (number of electrons) 251 | * 252 | * Calculates the total number of electrons by summing the weights 253 | * multiplied by the local value of the electron density. 254 | * 255 | * @return number of electrons 256 | */ 257 | void calculate_density(); 258 | 259 | /** 260 | * @brief perform interpolation on the spherical harmonic coefficients 261 | */ 262 | void interpolate_sh_coeff(); 263 | 264 | /** 265 | * @brief calculate lm index 266 | * 267 | * @param[in] l l quantum number 268 | * @param[in] m m quantum number 269 | * 270 | * @return the lm index 271 | */ 272 | inline unsigned int calculate_lm(unsigned int l, unsigned int m) { 273 | return l * l + l + m; 274 | } 275 | }; 276 | 277 | #endif //_ATOMIC_GRID_H 278 | -------------------------------------------------------------------------------- /src/molecule.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "molecule.h" 23 | 24 | /** 25 | * @brief atom constructor 26 | */ 27 | Atom::Atom() : 28 | atnr(0), 29 | position(vec3(0,0,0)) 30 | { 31 | } 32 | 33 | /** 34 | * @brief atom constructor 35 | * 36 | * @param[in] atnr atom number (i.e. number of protons) 37 | * @param[in] _position atom position 38 | */ 39 | Atom::Atom(unsigned int _atnr, const vec3& _position): 40 | atnr(_atnr), 41 | position(_position) { 42 | } 43 | 44 | /** 45 | * @brief molecule constructor 46 | * 47 | * @param[in] filename input file 48 | * @param[in] _settings pointer to settings object 49 | */ 50 | Molecule::Molecule(const std::string& filename, const std::shared_ptr& _settings) : 51 | settings(_settings) 52 | { 53 | this->read_molecule_from_file(filename); 54 | } 55 | 56 | /** 57 | * @brief Reads a molecule from file. 58 | * 59 | * @param[in] filename The filename 60 | */ 61 | void Molecule::read_molecule_from_file(const std::string& filename) { 62 | std::cout << " Reading input file " << std::endl; 63 | std::cout << "========================================" << std::endl; 64 | 65 | static const double angstrom_to_bohr = 1.889725989; 66 | bool unit_angstrom; 67 | try { 68 | unit_angstrom = this->settings->get_value("units").compare("angstrom") == 0 ? true : false; 69 | } catch(const std::exception& e) { 70 | unit_angstrom = false; 71 | } 72 | 73 | std::cout << "Reading file:\t\t" << filename << std::endl; 74 | std::cout << std::endl; 75 | 76 | std::cout << "System name: " << this->settings->get_value("name") << std::endl; 77 | std::string basis_set = "basis/" + this->settings->get_value("basis") + ".dat"; 78 | std::cout << "Basis set: " << basis_set << std::endl; 79 | std::cout << std::endl; 80 | 81 | // ignore all settings information 82 | std::ifstream infile(filename); 83 | std::string line; 84 | while(std::getline(infile, line)) { 85 | if(line.substr(0,7).compare("system:") == 0) { 86 | break; 87 | } 88 | } 89 | 90 | std::getline(infile, line); // grab number of atoms 91 | unsigned int nratoms = boost::lexical_cast(line); 92 | std::cout << "Atoms in system:\t" << nratoms << std::endl; 93 | 94 | std::vector pieces; 95 | for(unsigned int i=0; iget_atom_number_from_string(pieces[0]); 99 | double x = boost::lexical_cast(pieces[1]); 100 | double y = boost::lexical_cast(pieces[2]); 101 | double z = boost::lexical_cast(pieces[3]); 102 | 103 | if(unit_angstrom) { 104 | x *= angstrom_to_bohr; 105 | y *= angstrom_to_bohr; 106 | z *= angstrom_to_bohr; 107 | } 108 | 109 | this->add_atom(Atom(atnr, vec3(x, y, z) ) ); 110 | } 111 | 112 | infile.close(); 113 | 114 | this->set_basis_set(basis_set); 115 | std::cout << "========================================" << std::endl; 116 | 117 | for(unsigned int i=0; iatoms[i]->get_charge() 120 | % this->atoms[i]->get_position()[0] 121 | % this->atoms[i]->get_position()[1] 122 | % this->atoms[i]->get_position()[2] << std::endl; 123 | } 124 | 125 | std::cout << "========================================" << std::endl; 126 | std::cout << "Total number of GTOs: " << this->get_nr_gtos() << std::endl; 127 | std::cout << std::endl; 128 | } 129 | 130 | /** 131 | * @brief Sets the basis set. 132 | * 133 | * @param[in] basis_set The basis set 134 | */ 135 | void Molecule::set_basis_set(const std::string& basis_set) { 136 | // define origin vector 137 | static const vec3 origin(0,0,0); 138 | 139 | // collect for which atom types we need to fetch basis 140 | // set information 141 | unsigned int highest_atom = 0; 142 | for(unsigned int i=0; iatoms.size(); i++) { 143 | highest_atom = std::max(highest_atom, this->atoms[i]->get_charge()); 144 | } 145 | 146 | // open the file 147 | if (!boost::filesystem::exists("../" + basis_set)) { 148 | std::cerr << "Please make sure you are running dftcxx from the build directory..." << std::endl; 149 | throw std::runtime_error("Cannot open ../" + basis_set + "!"); 150 | } 151 | 152 | std::ifstream infile("../" + basis_set); 153 | std::string line; 154 | std::vector bs_cgfs; 155 | while(std::getline(infile, line)) { 156 | 157 | // skip comment lines 158 | if(line[0] == '#') { 159 | continue; 160 | } 161 | 162 | std::vector pieces; 163 | boost::split(pieces, line, boost::is_any_of(" \t"), boost::token_compress_on); 164 | unsigned int atnr = boost::lexical_cast(pieces[0]); 165 | unsigned int ncgfs = boost::lexical_cast(pieces[1]); 166 | bs_cgfs.clear(); 167 | 168 | // collect cgfs 169 | for(unsigned int i=0; i(pieces[1]); 174 | 175 | // allocate cgfs in vector 176 | switch(type) { 177 | case 'S': 178 | bs_cgfs.resize(bs_cgfs.size() + 1); 179 | break; 180 | 181 | case 'P': 182 | bs_cgfs.resize(bs_cgfs.size() + 3); 183 | break; 184 | 185 | case 'D': 186 | bs_cgfs.resize(bs_cgfs.size() + 6); 187 | break; 188 | } 189 | 190 | // collect gtos for cgf 191 | unsigned int cgfs_size = bs_cgfs.size(); 192 | for(unsigned int j=0; j(pieces[1]); 197 | double coefficient = boost::lexical_cast(pieces[2]); 198 | 199 | switch(type) { 200 | case 'S': 201 | bs_cgfs[cgfs_size - 1].add_gto(CGF::GTO_S, exponent, coefficient, origin); 202 | break; 203 | 204 | case 'P': 205 | bs_cgfs[cgfs_size-3].add_gto(CGF::GTO_PX, exponent, coefficient, origin); 206 | bs_cgfs[cgfs_size-2].add_gto(CGF::GTO_PY, exponent, coefficient, origin); 207 | bs_cgfs[cgfs_size-1].add_gto(CGF::GTO_PZ, exponent, coefficient, origin); 208 | break; 209 | 210 | case 'D': 211 | bs_cgfs[cgfs_size-6].add_gto(CGF::GTO_DX2, exponent, coefficient, origin); 212 | bs_cgfs[cgfs_size-5].add_gto(CGF::GTO_DXY, exponent, coefficient, origin); 213 | bs_cgfs[cgfs_size-4].add_gto(CGF::GTO_DXZ, exponent, coefficient, origin); 214 | bs_cgfs[cgfs_size-3].add_gto(CGF::GTO_DY2, exponent, coefficient, origin); 215 | bs_cgfs[cgfs_size-2].add_gto(CGF::GTO_DYZ, exponent, coefficient, origin); 216 | bs_cgfs[cgfs_size-1].add_gto(CGF::GTO_DZ2, exponent, coefficient, origin); 217 | break; 218 | } 219 | } 220 | } 221 | 222 | // add basis functions to the atoms 223 | for(unsigned int i=0; iatoms.size(); i++) { 224 | if(this->atoms[i]->get_charge() == atnr) { 225 | for(unsigned int j=0; jatoms[i]->get_position()); 227 | this->add_cgf(i, bs_cgfs[j]); 228 | } 229 | } 230 | } 231 | 232 | if(atnr == highest_atom) { // highest atom reached, break reading file 233 | break; 234 | } 235 | } 236 | 237 | infile.close(); 238 | } 239 | 240 | /** 241 | * @brief Gets the number of elec. 242 | * 243 | * @return The number of elec. 244 | */ 245 | unsigned int Molecule::get_nr_elec() const { 246 | unsigned int nr_elec = 0; 247 | 248 | for(unsigned int i=0; iatoms.size(); i++) { 249 | nr_elec += this->atoms[i]->get_charge(); 250 | } 251 | 252 | return nr_elec; 253 | } 254 | 255 | /** 256 | * @brief the total number of gtos in this molecule 257 | * 258 | * @return total number of gtos 259 | */ 260 | unsigned int Molecule::get_nr_gtos() const { 261 | unsigned int sz = 0; 262 | 263 | for(unsigned int i=0; icgfs.size(); i++) { 264 | sz += this->cgfs[i].size(); 265 | } 266 | 267 | return sz; 268 | } 269 | 270 | /** 271 | * @brief Gets the atom number from string. 272 | * 273 | * @param[in] el element name 274 | * 275 | * @return atom number 276 | */ 277 | unsigned int Molecule::get_atom_number_from_string(std::string el) { 278 | static const std::vector names = {"H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", 279 | "Mg", "Al", "Si", "P", "S", "Cl", "Ar"}; 280 | 281 | for(unsigned int i=0; i * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include 23 | #include 24 | 25 | #include "gamma.h" 26 | #include "cgf.h" 27 | 28 | class Integrator { 29 | public: 30 | /** 31 | * @fn Integrator 32 | * @brief Integrator constructor method 33 | * 34 | * @return Integrator class 35 | */ 36 | Integrator(); 37 | 38 | /** 39 | * @fn overlap 40 | * @brief Calculates overlap integral of two CGF 41 | * 42 | * @param const CGF& cgf1 Contracted Gaussian Function 43 | * @param const CGF& cgf2 Contracted Gaussian Function 44 | ********************* 45 | * Calculates the value of < cgf1 | cgf2 > 46 | * 47 | * @return double value of the overlap integral 48 | */ 49 | double overlap(const CGF& cgf1, const CGF& cgf2); 50 | 51 | /** 52 | * @fn overlap 53 | * @brief Calculates overlap integral of two GTO 54 | * 55 | * @param const GTO& gto1 Gaussian Type Orbital 56 | * @param const GTO& gto2 Gaussian Type Orbital 57 | * 58 | * Calculates the value of < gto1 | gto2 > 59 | * 60 | * @return double value of the overlap integral 61 | */ 62 | double overlap(const GTO& gto1, const GTO& gto2); 63 | 64 | /** 65 | * @fn kinetic 66 | * @brief Calculates kinetic integral of two CGF 67 | * 68 | * @param const CGF& cgf1 Contracted Gaussian Function 69 | * @param const CGF& cgf2 Contracted Gaussian Function 70 | * 71 | * Calculates the value of < cgf1 | T | cgf2 > 72 | * 73 | * @return double value of the kinetic integral 74 | */ 75 | double kinetic(const CGF& cgf1, const CGF& cgf2); 76 | 77 | /** 78 | * @fn kinetic 79 | * @brief Calculates kinetic integral of two GTO 80 | * 81 | * @param const GTO& gto1 Gaussian Type Orbital 82 | * @param const GTO& gto2 Gaussian Type Orbital 83 | * 84 | * Calculates the value of < gto1 | H | gto2 > 85 | * 86 | * @return double value of the kinetic integral 87 | */ 88 | double kinetic(const GTO& gto1, const GTO& gto2); 89 | 90 | /** 91 | * @fn nuclear 92 | * @brief Calculates nuclear integral of two CGF 93 | * 94 | * @param const CGF& cgf1 Contracted Gaussian Function 95 | * @param const CGF& cgf2 Contracted Gaussian Function 96 | * @param unsigned int charge charge of the nucleus in a.u. 97 | * 98 | * Calculates the value of < cgf1 | V | cgf2 > 99 | * 100 | * @return double value of the nuclear integral 101 | */ 102 | double nuclear(const CGF &cgf1, const CGF &cgf2, const vec3& nucleus, unsigned int charge); 103 | 104 | /** 105 | * @fn nuclear 106 | * @brief Calculates nuclear integral of two CGF 107 | * 108 | * @param const GTO& gto1 Contracted Gaussian Function 109 | * @param const GTO& gto2 Contracted Gaussian Function 110 | * @param unsigned int charge charge of the nucleus in a.u. 111 | * 112 | * Calculates the value of < gto1 | V | gto2 > 113 | * 114 | * @return double value of the nuclear integral 115 | */ 116 | double nuclear(const GTO >o1, const GTO >o2, const vec3& nucleus); 117 | 118 | /** 119 | * @fn repulsion 120 | * @brief Calculates two-electron repulsion integral of four CGF 121 | * 122 | * @param const CGF& cgf1 Contracted Gaussian Function 123 | * @param const CGF& cgf2 Contracted Gaussian Function 124 | * @param const CGF& cgf3 Contracted Gaussian Function 125 | * @param const CGF& cgf4 Contracted Gaussian Function 126 | * 127 | * Calculates the value of < cgf1 | cgf2 | cgf3 | cgf4 > 128 | * 129 | * @return double value of the repulsion integral 130 | */ 131 | double repulsion(const CGF &cgf1, const CGF &cgf2, const CGF &cgf3, const CGF &cgf4); 132 | 133 | /** 134 | * @fn repulsion 135 | * @brief Calculates two-electron repulsion integral of four CGF 136 | * 137 | * @param const GTO& gto1 Contracted Gaussian Function 138 | * @param const GTO& gto2 Contracted Gaussian Function 139 | * @param const GTO& gto3 Contracted Gaussian Function 140 | * @param const GTO& gto4 Contracted Gaussian Function 141 | * 142 | * Calculates the value of < gto1 | gto2 | gto3 | gto4 > 143 | * 144 | * @return double value of the repulsion integral 145 | */ 146 | double repulsion(const GTO >o1, const GTO >o2, const GTO >o3, const GTO >o4); 147 | 148 | const unsigned int teindex(unsigned int i, unsigned int j, unsigned int k, unsigned int l); 149 | 150 | /********************************* 151 | * 152 | * PRIVATE FUNCTIONS AND VARIABLES 153 | * 154 | *********************************/ 155 | 156 | private: 157 | /* 158 | * @var gamma_inc 159 | * @brief class that handles the evaluation of the Gamma function 160 | */ 161 | GammaInc gamma_inc; 162 | 163 | /** 164 | * @fn overlap 165 | * @brief Performs overlap integral evaluation 166 | * 167 | * @param double alpha1 Gaussian exponent of the first GTO 168 | * @param unsigned int l1 Power of x component of the polynomial of the first GTO 169 | * @param unsigned int m1 Power of y component of the polynomial of the first GTO 170 | * @param unsigned int n1 Power of z component of the polynomial of the first GTO 171 | * @param vec3 a Center of the Gaussian orbital of the first GTO 172 | * @param double alpha2 Gaussian exponent of the second GTO 173 | * @param unsigned int l2 Power of x component of the polynomial of the second GTO 174 | * @param unsigned int m2 Power of y component of the polynomial of the second GTO 175 | * @param unsigned int n2 Power of z component of the polynomial of the second GTO 176 | * @param vec3 b Center of the Gaussian orbital of the second GTO 177 | * 178 | * @return double value of the overlap integral 179 | */ 180 | double overlap(double alpha1, unsigned int l1, unsigned int m1, unsigned int n1, const vec3 &a, 181 | double alpha2, unsigned int l2, unsigned int m2, unsigned int n2, const vec3 &b); 182 | 183 | /** 184 | * @fn nuclear 185 | * @brief Performs nuclear integral evaluation 186 | * 187 | * @param vec3 a Center of the Gaussian orbital of the first GTO 188 | * @param unsigned int l1 Power of x component of the polynomial of the first GTO 189 | * @param unsigned int m1 Power of y component of the polynomial of the first GTO 190 | * @param unsigned int n1 Power of z component of the polynomial of the first GTO 191 | * @param double alpha1 Gaussian exponent of the first GTO 192 | * @param vec3 b Center of the Gaussian orbital of the second GTO 193 | * @param unsigned int l2 Power of x component of the polynomial of the second GTO 194 | * @param unsigned int m2 Power of y component of the polynomial of the second GTO 195 | * @param unsigned int n2 Power of z component of the polynomial of the second GTO 196 | * @param double alpha2 Gaussian exponent of the second GTO 197 | * @param vec3 c 198 | * 199 | * @return double value of the nuclear integral 200 | */ 201 | double nuclear(const vec3& a, 202 | int l1, int m1, int n1, 203 | double alpha1, 204 | const vec3& b, 205 | int l2, int m2, int n2, 206 | double alpha2, 207 | const vec3& c); 208 | 209 | /** 210 | * @fn nuclear 211 | * @brief Performs nuclear integral evaluation 212 | * 213 | * @param vec3 a Center of the Gaussian orbital of the first GTO 214 | * @param unsigned int l1 Power of x component of the polynomial of the first GTO 215 | * @param unsigned int m1 Power of y component of the polynomial of the first GTO 216 | * @param unsigned int n1 Power of z component of the polynomial of the first GTO 217 | * @param double alpha1 Gaussian exponent of the first GTO 218 | * @param vec3 b Center of the Gaussian orbital of the second GTO 219 | * @param unsigned int l2 Power of x component of the polynomial of the second GTO 220 | * @param unsigned int m2 Power of y component of the polynomial of the second GTO 221 | * @param unsigned int n2 Power of z component of the polynomial of the second GTO 222 | * @param double alpha2 Gaussian exponent of the second GTO 223 | * @param vec3 c 224 | * 225 | * @return double value of the nuclear integral 226 | */ 227 | double repulsion(const vec3 &a, const double norma, const int la, const int ma, const int na, const double alphaa, 228 | const vec3 &b, const double normb, const int lb, const int mb, const int nb, const double alphab, 229 | const vec3 &c, const double normc, const int lc, const int mc, const int nc, const double alphac, 230 | const vec3 &d, const double normd, const int ld, const int md, const int nd, const double alphad); 231 | 232 | /** 233 | * @fn overlap_1D 234 | * @brief Calculates one dimensional overlap integral 235 | * 236 | * @param int l1 Power of 'x' component of the polynomial of the first GTO 237 | * @param int l2 Power of 'x' component of the polynomial of the second GTO 238 | * @param double x1 'x' component of the position of the first GTO 239 | * @param double x2 'x' component of the position of the second GTO 240 | * @param double gamma Sum of the two Gaussian exponents 241 | * 242 | * @return double value of the one dimensional overlap integral 243 | */ 244 | double overlap_1D(int l1, int l2, double x1, double x2, double gamma); 245 | 246 | /************************ 247 | * 248 | * AUXILIARY FUNCTIONS 249 | * 250 | ************************/ 251 | 252 | /** 253 | * @fn gaussian_product_center 254 | * @brief Calculates the Gaussian product center of two GTOs 255 | * 256 | * @param double alpha1 Gaussian exponent of the first GTO 257 | * @param double alpha2 Gaussian exponent of the second GTO 258 | * @param const vec3 a Center of the first GTO 259 | * @param const vec3 b Center of the second GTO 260 | * 261 | * 262 | * @return new gaussian product center 263 | */ 264 | vec3 gaussian_product_center(double alpha1, const vec3 &a, 265 | double alpha2, const vec3 &b); 266 | 267 | double binomial_prefactor(int s, int ia, int ib, double xpa, double xpb); 268 | 269 | double binomial(int a, int b); 270 | 271 | std::vector A_array(const int l1, const int l2, 272 | const double pa, const double pb, 273 | const double cp, const double g); 274 | 275 | double A_term(const int i, const int r, const int u, 276 | const int l1, const int l2, 277 | const double pax, const double pbx, 278 | const double cpx, const double gamma); 279 | 280 | double gamma(const double m, double x); 281 | 282 | std::vector B_array(const int l1,const int l2,const int l3,const int l4, 283 | const double p, const double a, const double b, const double q, const double c, const double d, 284 | const double g1, const double g2, const double delta); 285 | 286 | double B_term(const int i1, const int i2, const int r1, const int r2, const int u, const int l1, const int l2, const int l3, const int l4, 287 | const double px, const double ax, const double bx, const double qx, const double cx, const double dx, const double gamma1, 288 | const double gamma2, const double delta); 289 | 290 | double fB(const int i, const int l1, const int l2, const double p, const double a, const double b, const int r, const double q); 291 | double B0(int i, int r, double q); 292 | double fact_ratio2(const int a, const int b); 293 | }; 294 | -------------------------------------------------------------------------------- /src/moleculargrid.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "moleculargrid.h" 23 | 24 | /** 25 | * @fn MolecularGrid 26 | * @brief MolecularGrid constructor 27 | * 28 | * @param _mol pointer to Molecule class 29 | * 30 | * @return MolecularGrid instance 31 | */ 32 | MolecularGrid::MolecularGrid(const std::shared_ptr& _mol) { 33 | this->mol = _mol; 34 | this->grid_size = 0; 35 | } 36 | 37 | /** 38 | * @fn set_density 39 | * @brief set the density at the grid point given a density matrix 40 | * 41 | * @param P reference to density matrix 42 | * 43 | * Loops over all the grid points and calculates the local density 44 | * using the amplitudes of the basis functions and the density matrix 45 | * 46 | * @return void 47 | */ 48 | void MolecularGrid::set_density(const MatrixXXd& P) { 49 | #pragma omp parallel for 50 | for(unsigned int i=0; iatomic_grids.size(); i++) { 51 | this->atomic_grids[i]->set_density(P); 52 | } 53 | } 54 | 55 | /** 56 | * @fn get_weights 57 | * @brief get the weights of all the grid points as a vector 58 | * 59 | * @return vector containing all the weights 60 | */ 61 | VectorXd MolecularGrid::get_weights() const { 62 | VectorXd weights = VectorXd::Zero(this->grid_size); 63 | unsigned int idx =0; 64 | 65 | for(unsigned int i=0; iatomic_grids.size(); i++) { 66 | VectorXd vec_weight = this->atomic_grids[i]->get_weights(); 67 | 68 | #pragma omp parallel for 69 | for(unsigned int j=0; jgrid_size); 87 | unsigned int idx = 0; 88 | 89 | for(unsigned int i=0; iatomic_grids.size(); i++) { 90 | VectorXd vec_densities = this->atomic_grids[i]->get_densities(); 91 | 92 | #pragma omp parallel for 93 | for(unsigned int j=0; jmol->get_nr_bfs(), this->grid_size); 111 | unsigned int idx = 0; 112 | 113 | for(unsigned int i=0; iatomic_grids.size(); i++) { 114 | MatrixXXd agrid_amplitudes = this->atomic_grids[i]->get_amplitudes(); 115 | 116 | #pragma omp parallel for 117 | for(unsigned int j = 0; jatomic_grids[i]->get_grid_size(); j++) { 118 | for(unsigned int k=0; kmol->get_nr_bfs(); k++) { 119 | amplitudes(k, idx + j) = agrid_amplitudes(k,j); 120 | } 121 | } 122 | 123 | idx += this->atomic_grids[i]->get_grid_size(); 124 | } 125 | 126 | return amplitudes; 127 | } 128 | 129 | /** 130 | * @brief correct the densities to match the total number of electrons 131 | */ 132 | void MolecularGrid::correct_densities() { 133 | double sum = 0.0; 134 | double charge = 0.0; 135 | 136 | for(unsigned int i=0; iatomic_grids.size(); i++) { 137 | sum += this->atomic_grids[i]->get_density(); 138 | charge += this->mol->get_atomic_charge(i); 139 | } 140 | 141 | double correction_factor = charge / sum; 142 | 143 | for(unsigned int i=0; iatomic_grids.size(); i++) { 144 | this->atomic_grids[i]->correct_density(correction_factor); 145 | } 146 | } 147 | 148 | /** 149 | * @fn calculate_density 150 | * @brief calculate the total electron density (number of electrons) 151 | * 152 | * Calculates the total number of electrons by summing the weights 153 | * multiplied by the local value of the electron density. 154 | * 155 | * @return number of electrons 156 | */ 157 | double MolecularGrid::calculate_density() const { 158 | double sum = 0.0; 159 | 160 | #pragma omp parallel for reduction(+:sum) 161 | for(unsigned int i=0; iatomic_grids.size(); i++) { 162 | sum += this->atomic_grids[i]->get_density(); 163 | } 164 | 165 | return sum; 166 | } 167 | 168 | /** 169 | * @brief Sets the grid parameters (fine-tuning) 170 | * 171 | * @param[in] _radial_points number of radial points 172 | * @param[in] _lebedev_order The lebedev order 173 | * @param[in] _lmax maximum angular momentum for spherical harmonics 174 | */ 175 | void MolecularGrid::set_grid_parameters(unsigned int _radial_points, unsigned int _lebedev_order, unsigned int _lmax) { 176 | this->radial_points = _radial_points; 177 | this->lebedev_order = _lebedev_order; 178 | this->lmax = _lmax; 179 | } 180 | 181 | /** 182 | * @fn create_grid 183 | * @brief creates the molecular grid 184 | * 185 | * Creates a molecular grid given a set of atoms and a set of 186 | * basis functions. For each atom, an atomic grid is created. The 187 | * numerical integration is carried out over all the atomic grids. The 188 | * contribution of the atomic grid to the overall integration over the 189 | * whole molecule is controlled via a weight factor as defined by Becke. 190 | * 191 | * @return void 192 | */ 193 | void MolecularGrid::create_grid() { 194 | 195 | auto start = std::chrono::system_clock::now(); //tic 196 | 197 | std::cout << " Constructing molecular grid " << std::endl; 198 | std::cout << "========================================" << std::endl; 199 | std::cout << "Number of radial points: " << this->radial_points << std::endl; 200 | std::cout << "Lebedev order: " << this->lebedev_order << std::endl; 201 | std::cout << "Lmax value: " << this->lmax << std::endl; 202 | 203 | // calculate number of angular points 204 | this->angular_points = Quadrature::num_lebedev_points[this->lebedev_order]; 205 | 206 | // The Lebedev coefficients and radial points are stored in a large matrix. 207 | // Given a particular order for the integration, we have to start reading 208 | // this matrix from a specific position. Here, we calculate that position. 209 | lebedev_offset = 0; 210 | for(unsigned int i=0; ilebedev_order; i++) { 211 | lebedev_offset += Quadrature::num_lebedev_points[i]; 212 | } 213 | 214 | // generate for each atom an atomic grid 215 | for(unsigned int i=0; imol->get_nr_atoms(); i++) { 216 | // add atomic density 217 | this->atomic_densities.push_back(0); 218 | 219 | this->atomic_grids.emplace_back(new AtomicGrid(this->mol->get_atom(i))); 220 | this->atomic_grids.back()->create_atomic_grid(radial_points, 221 | angular_points, 222 | lebedev_offset, 223 | lmax, 224 | mol); 225 | this->grid_size += this->atomic_grids.back()->get_grid_size(); 226 | } 227 | 228 | // calculate the Becke weights for the atomic grids 229 | for(unsigned int i=0; imol->get_nr_atoms(); i++) { 230 | 231 | MatrixXXd positions = this->atomic_grids[i]->get_positions(); 232 | VectorXd becke_weight_coeff = VectorXd::Zero(positions.rows()); 233 | 234 | // loop over positions 235 | for(unsigned int j=0; jmol->get_nr_atoms(); k++) { 242 | const double term = this->get_becke_weight_pn(k, positions.row(j)); // obtain single Pn(r) term 243 | denom += term; 244 | if(i == k) { 245 | nom = term; 246 | } 247 | } 248 | 249 | // set weight from cell function: wn(r) = Pn(r) / SUM_m Pm(r) (eq. 22) 250 | becke_weight_coeff(j) = nom / denom; 251 | } 252 | 253 | this->atomic_grids[i]->set_becke_weights(becke_weight_coeff); 254 | } 255 | 256 | auto end = std::chrono::system_clock::now(); //toc 257 | auto elapsed = std::chrono::duration_cast(end - start); 258 | std::cout << boost::format("Total time: %f ms\n") % elapsed.count(); 259 | std::cout << "========================================" << std::endl; 260 | std::cout << std::endl; 261 | } 262 | 263 | /** 264 | * @fn get_becke_weight_pn 265 | * @brief calculate Pi(r) (i.e. for a single gridpoint) for atom n (eq. 13 in A.D. Becke J.Chem.Phys. 88, 2547) 266 | * 267 | * Reference: A.D. Becke, J.Chem.Phys. 88, 2547, (1988) 268 | * Link: http://dx.doi.org/10.1063/1.454033 269 | * 270 | * @param i atom id i 271 | * @param p0 grid point position 272 | * 273 | * @return double Becke weight value 274 | */ 275 | double MolecularGrid::get_becke_weight_pn(unsigned int i, const vec3& p0) { 276 | double wprod = 1.0; 277 | 278 | // get position of central atom in fuzzy cell 279 | const vec3 p1 = this->mol->get_atom(i)->get_position(); 280 | 281 | // loop over all other atoms 282 | for(unsigned int j=0; jmol->get_nr_atoms(); j++) { 283 | if(i == j) { 284 | continue; 285 | } 286 | 287 | // get position of other atom 288 | const vec3 p2 = this->mol->get_atom(j)->get_position(); 289 | 290 | // calculate mu (eq. 11 in A.D. Becke J.Chem.Phys. 88, 2547) 291 | double mu = ((p0 - p1).norm() 292 | - (p0 - p2).norm() )/ 293 | (p2-p1).norm(); 294 | 295 | // (eq. 13 in A.D. Becke J.Chem.Phys. 88, 2547) 296 | wprod *= this->cutoff(mu); 297 | } 298 | 299 | return wprod; 300 | } 301 | 302 | /** 303 | * @fn cutoff 304 | * @brief calculates the Becke weight 305 | * 306 | * @param fineness mu (elliptical coordinate) 307 | * 308 | * @return double Becke weight value 309 | */ 310 | double MolecularGrid::cutoff(double mu) { 311 | return 0.5 * (1.0 - this->fk(3, mu)); 312 | } 313 | 314 | /** 315 | * @fn fk 316 | * @brief recursive function to have smooth overlapping atomic grids 317 | * 318 | * @param k number of iterations 319 | * @param mu elliptical coordinate 320 | * 321 | * @return value 322 | */ 323 | double MolecularGrid::fk(unsigned int k, double mu) { 324 | for(unsigned int i=0; iatomic_grids.size(); i++) { 338 | this->atomic_grids[i]->calculate_rho_lm(); 339 | this->atomic_grids[i]->calculate_U_lm(); 340 | } 341 | 342 | for(unsigned int i=0; iatomic_grids.size(); i++) { 343 | 344 | #pragma omp parallel for 345 | for(unsigned int j=0; jatomic_grids[i]->get_grid_size(); j++) { 346 | 347 | double V = 0.0; 348 | 349 | for(unsigned int k=0; katomic_grids.size(); k++) { 350 | if(i == k) { // obtain Vn for fuzzy cell 351 | V += this->atomic_grids[k]->get_V(j); 352 | } else { // interpolatie Vn 353 | 354 | // set lm index 355 | unsigned int lm = 0; 356 | 357 | // loop over l and m 358 | for(int l=0; l<=lmax; l++) { 359 | for(int m=-l; m<=l; m++) { 360 | 361 | const double pre = SH::prefactor_spherical_harmonic(l, m); 362 | const vec3 pos = this->atomic_grids[i]->get_position_grid_point(j) - this->atomic_grids[k]->get_position(); 363 | 364 | // convert to spherical coordinates 365 | const double r = pos.norm(); // due to unit sphere 366 | const double azimuth = std::atan2(pos(1),pos(0)); 367 | const double pole = std::acos(pos(2) / r); // due to unit sphere else z/r 368 | 369 | const double y_lm = pre * SH::spherical_harmonic(l, m, pole, azimuth); 370 | V += 1.0 / r * y_lm * this->atomic_grids[k]->get_sh_value(r, lm); 371 | 372 | lm++; 373 | } 374 | } 375 | } 376 | } 377 | 378 | this->atomic_grids[i]->set_V_gp(j, V); 379 | } 380 | } 381 | 382 | MatrixXXd J = MatrixXXd::Zero(this->mol->get_nr_bfs(), this->mol->get_nr_bfs()); 383 | for(unsigned int i=0; iatomic_grids.size(); i++) { 384 | this->atomic_grids[i]->calculate_J_matrix(); 385 | J += this->atomic_grids[i]->get_J(); 386 | } 387 | 388 | return J; 389 | } 390 | -------------------------------------------------------------------------------- /src/dft.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * This file is part of DFTCXX. * 3 | * * 4 | * Author: Ivo Filot * 5 | * * 6 | * DFTCXX is free software: * 7 | * you can redistribute it and/or modify it under the terms of the * 8 | * GNU General Public License as published by the Free Software * 9 | * Foundation, either version 3 of the License, or (at your option) * 10 | * any later version. * 11 | * * 12 | * DFTCXX is distributed in the hope that it will be useful, * 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty * 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * 15 | * See the GNU General Public License for more details. * 16 | * * 17 | * You should have received a copy of the GNU General Public License * 18 | * along with this program. If not, see http://www.gnu.org/licenses/. * 19 | * * 20 | **************************************************************************/ 21 | 22 | #include "dft.h" 23 | 24 | /** 25 | * @fn DFT 26 | * @brief DFT routine constructor 27 | * 28 | * @return DFT instance 29 | */ 30 | DFT::DFT(const std::string& filename) { 31 | is_first = true; 32 | this->settings = std::make_shared(filename); 33 | this->mol = std::make_shared(filename, this->settings); 34 | 35 | this->add_molecule(this->mol); 36 | } 37 | 38 | /** 39 | * @fn add_molecule 40 | * @brief add molecule to the DFT routine 41 | * 42 | * @param _mol pointer to Molecule class 43 | * 44 | * Links molecule to the DFT routine by a pointer. The 45 | * Contracted Gaussian Functions of the molecule are copied 46 | * to the DFT routine class and the routine matrices are 47 | * constructed. 48 | * 49 | * @return void 50 | */ 51 | void DFT::add_molecule(const std::shared_ptr& _mol) { 52 | // set molecule 53 | this->mol = _mol; 54 | this->nelec = this->mol->get_nr_elec(); 55 | 56 | // construct molecular grid based on molecule and basis functions 57 | this->molgrid = std::make_unique(this->mol); 58 | this->molgrid->set_grid_parameters(this->settings->get_radial_points(), 59 | this->settings->get_lebedev_order(), 60 | this->settings->get_lmax()); 61 | this->molgrid->create_grid(); 62 | 63 | // copy the contracted gaussian functions to the DFT class 64 | this->copy_cgfs_from_molecule(); 65 | 66 | std::cout << "Loading molecule and constructing matrices." << std::endl; 67 | auto start = std::chrono::system_clock::now(); //tic 68 | 69 | // construct all matrices 70 | this->construct_matrices(); 71 | 72 | auto end = std::chrono::system_clock::now(); //toc 73 | auto elapsed = std::chrono::duration_cast(end - start); 74 | std::cout << boost::format("Total time: %f ms\n") % elapsed.count(); 75 | std::cout << std::endl; 76 | } 77 | 78 | /** 79 | * @fn scf 80 | * @brief perform the self-consistent field iterations 81 | * 82 | * @return void 83 | */ 84 | void DFT::scf() { 85 | static const unsigned int max_iterations = 100; 86 | 87 | std::cout << " Starting calculation " << std::endl; 88 | std::cout << "========================================" << std::endl; 89 | std::cout << " # energy elec" << std::endl; 90 | std::cout << "----------------------------------------" << std::endl; 91 | double old_energy = this->et; 92 | double difference = 1.0; 93 | unsigned int iteration = 0; 94 | 95 | while(difference > 1e-4 || iteration < 3) { 96 | iteration++; 97 | 98 | auto start = std::chrono::system_clock::now(); //tic 99 | 100 | this->calculate_density_matrix(); 101 | this->calculate_electronic_repulsion_matrix(); 102 | this->calculate_exchange_correlation_matrix(); 103 | this->calculate_energy(); 104 | 105 | auto end = std::chrono::system_clock::now(); //toc 106 | auto elapsed = std::chrono::duration_cast(end - start); 107 | 108 | std::cout << boost::format("%3i %9.7f %4.2f (%3i) \n") 109 | % iteration 110 | % this->et 111 | % this->molgrid->calculate_density() 112 | % this->nelec; 113 | 114 | std::cout << boost::format("\tE_XC \t= %9.7f\n\tE_NUC \t= %9.7f\n\tE_ONE \t= %9.7f\n\tE_J \t= %9.7f\n\tt \t=%9.7f ms\n") 115 | % this->exc 116 | % this->enuc 117 | % this->single_electron_energy 118 | % this->electronic_repulsion 119 | % (elapsed.count()); 120 | 121 | std::cout << "----------------------------------------" << std::endl; 122 | 123 | difference = std::abs(this->et - old_energy); 124 | old_energy = this->et; 125 | 126 | if(iteration >= max_iterations) { 127 | std::cout << "========================================" << std::endl; 128 | std::cout << "Stopping because maximum number of iterations has been reached." << std::endl; 129 | std::cout << std::endl; 130 | break; 131 | } 132 | } 133 | 134 | if(iteration < max_iterations) { 135 | std::cout << "========================================" << std::endl; 136 | std::cout << "Stopping because energy criterion is reached." << std::endl; 137 | std::cout << std::endl; 138 | } 139 | 140 | // output results 141 | this->finalize(); 142 | } 143 | 144 | /** 145 | * @fn copy_cgfs_from_molecule 146 | * @brief copy cgfs from the molecule class to the dft class 147 | * 148 | * @return void 149 | */ 150 | void DFT::copy_cgfs_from_molecule() { 151 | this->cgfs = this->mol->get_cgfs(); 152 | } 153 | 154 | /** 155 | * @fn construct_matrices 156 | * @brief construct the matrices and two-electron integrals for the SCF procedure 157 | * 158 | * @return void 159 | */ 160 | void DFT::construct_matrices() { 161 | const unsigned int size = this->mol->get_nr_bfs(); 162 | 163 | // overlap matrix 164 | this->S = MatrixXXd::Zero(size, size); 165 | 166 | // kinetic energy matrix 167 | this->T = MatrixXXd::Zero(size, size); 168 | 169 | // nuclear attraction matrix 170 | this->V = MatrixXXd::Zero(size, size); 171 | 172 | // single-electron matrix 173 | this->H = MatrixXXd::Zero(size, size); 174 | 175 | // coulombic repulsion matrix 176 | this->J = MatrixXXd::Zero(size, size); 177 | 178 | // exchange-correlation matrix 179 | this->XC = MatrixXXd::Zero(size, size); 180 | 181 | // density matrix 182 | this->P = MatrixXXd::Zero(size, size); 183 | 184 | // calculate values of matrix elements 185 | #pragma omp parallel for schedule(dynamic) 186 | for(unsigned int i=0; icgfs->size(); i++) { 187 | for(unsigned int j=i; jcgfs->size(); j++) { 188 | S(i,j) = S(j,i) = this->integrator->overlap(cgfs->at(i), cgfs->at(j)); 189 | T(i,j) = T(j,i) = this->integrator->kinetic(cgfs->at(i), cgfs->at(j)); 190 | double v_sum = 0.0; 191 | for(unsigned int k=0; kmol->get_nr_atoms(); k++) { 192 | v_sum += this->integrator->nuclear(cgfs->at(i), cgfs->at(j), 193 | this->mol->get_atomic_position(k), 194 | this->mol->get_atomic_charge(k)); 195 | } 196 | V(i,j) = V(j,i) = v_sum; 197 | } 198 | } 199 | 200 | // calculate single-electron matrix by summing T and V matrices 201 | this->H = this->T + this->V; 202 | 203 | // calculate nuclear repulsion energy 204 | this->calculate_nuclear_repulsion(); 205 | 206 | // calculate all two-electron integrals 207 | if(this->settings->get_hartree_evaluation_method() == Settings::TWO_ELECTRON_INTEGRALS) { 208 | auto start = std::chrono::system_clock::now(); //tic 209 | std::cout << "Explicitly calculating two electron integrals... " << std::flush; 210 | this->calculate_two_electron_integrals(); 211 | auto end = std::chrono::system_clock::now(); //toc 212 | auto elapsed = std::chrono::duration_cast(end - start); 213 | std::cout << boost::format("(%f ms)\n") % elapsed.count(); 214 | } 215 | 216 | // calculate transformation matrix from the overlap matrix 217 | this->calculate_transformation_matrix(); 218 | 219 | // calculate the density matrix from the coefficient matrices 220 | this->calculate_density_matrix(); 221 | 222 | // calculate the electronic repulsion matrix from the density 223 | this->calculate_electronic_repulsion_matrix(); 224 | 225 | // calculate the total energy of the molecule 226 | this->calculate_energy(); 227 | } 228 | 229 | /** 230 | * @fn calculate_nuclear_repulsion 231 | * @brief calculate the nuclear repulsion energy 232 | * 233 | * @return void 234 | */ 235 | void DFT::calculate_nuclear_repulsion() { 236 | this->enuc = 0.0; 237 | 238 | for(unsigned int i=0; imol->get_nr_atoms(); i++) { 239 | for(unsigned int j=i+1; jmol->get_nr_atoms(); j++) { 240 | this->enuc += this->mol->get_atomic_charge(i) * 241 | this->mol->get_atomic_charge(j) / 242 | (this->mol->get_atomic_position(i) - 243 | this->mol->get_atomic_position(j)).norm(); 244 | } 245 | } 246 | } 247 | 248 | /** 249 | * @fn calculate_two_electron_integrals 250 | * @brief calculate the two-electron integrals 251 | * 252 | * @return void 253 | */ 254 | void DFT::calculate_two_electron_integrals() { 255 | const unsigned int size = this->mol->get_nr_bfs(); 256 | 257 | unsigned int nrints = integrator->teindex(size,size,size,size); 258 | this->ints = VectorXd::Ones(nrints); 259 | this->ints *= -1.0; 260 | 261 | #ifdef HAS_OPENMP 262 | #pragma omp parallel for schedule(dynamic) 263 | #endif 264 | for(unsigned int i=0; iteindex(i,j,k,l); 272 | 273 | // this avoids recalculating an integral which has 274 | // already been evaluated 275 | if(this->ints(idx) != -1.0) { 276 | continue; 277 | } 278 | 279 | this->ints(idx) = integrator->repulsion(this->cgfs->at(i), 280 | this->cgfs->at(j), 281 | this->cgfs->at(k), 282 | this->cgfs->at(l)); 283 | } 284 | } 285 | } 286 | } 287 | } 288 | } 289 | 290 | /** 291 | * @fn calculate_transformation_matrix 292 | * @brief calculate the transformation matrix X from the overlap matrix S 293 | * 294 | * The transformation matrix X is calculated from the overlap matrix S by 295 | * canonical orthogonalization. This transformation matrix X ensures that 296 | * the Slater determinant consists of orthogonal spin-orbitals. 297 | * 298 | * @return void 299 | */ 300 | void DFT::calculate_transformation_matrix() { 301 | const unsigned int size = this->mol->get_nr_bfs(); // nr of cgfs 302 | 303 | Eigen::SelfAdjointEigenSolver es(S); 304 | Eigen::MatrixXd D = es.eigenvalues().real().asDiagonal(); 305 | for(unsigned int i=0; iX = U * D; 315 | this->Xp = X.transpose(); 316 | } 317 | 318 | /** 319 | * @fn calculate_density_matrix 320 | * @brief calculate the density matrix from the coefficient matrix 321 | * 322 | * Performs eigenvector decomposition on the Fock matrix F. From these 323 | * the coefficients in the transformed basis are calculated. The basis 324 | * function coefficients in the original basis can be obtained by 325 | * using the transformation matrix X. From these coefficients in the 326 | * original representation, the density matrix P is calculated. 327 | * 328 | * @return void 329 | */ 330 | void DFT::calculate_density_matrix() { 331 | static const double alpha = 0.50; // mixing parameter alpha (NOTE: obtain this value from input file...) 332 | const unsigned int size = this->mol->get_nr_bfs(); // nr of cgfs 333 | 334 | MatrixXXd F = this->H + 2.0 * this->J + this->XC; 335 | 336 | MatrixXXd Fp = this->Xp * F * this->X; 337 | 338 | // compute eigenvectors and eigenvalues 339 | Eigen::SelfAdjointEigenSolver es(Fp); 340 | this->Cc = es.eigenvectors().real(); 341 | 342 | // obtain true coefficient matrix using the transformation matrix 343 | this->C = this->X * this->Cc; 344 | 345 | MatrixXXd Pnew = MatrixXXd::Zero(size, size); 346 | for(unsigned int i=0; inelec / 2; k++) { 349 | Pnew(i,j) += C(i,k) * C(j,k); 350 | } 351 | } 352 | } 353 | 354 | if(is_first) { 355 | this->P = Pnew; 356 | is_first = false; 357 | } else { 358 | this->P = (1.0 - alpha) * Pnew + alpha * P; 359 | } 360 | 361 | // set the new density 362 | this->molgrid->set_density(P); 363 | 364 | // correct density 365 | this->molgrid->correct_densities(); 366 | } 367 | 368 | /** 369 | * @fn calculate_electronic_repulsion_matrix 370 | * @brief calculates electronic repulsion matrix 371 | * 372 | * Calculate the electronic repulsion matrix using the 373 | * density matrix and the two-electron integrals. 374 | * 375 | * @return void 376 | */ 377 | void DFT::calculate_electronic_repulsion_matrix() { 378 | switch(this->settings->get_hartree_evaluation_method()) { 379 | case Settings::BECKE_GRID: 380 | this->calculate_hartree_potential_becke_poisson(); 381 | break; 382 | case Settings::TWO_ELECTRON_INTEGRALS: 383 | this->calculate_hartree_potential_te_int(); 384 | break; 385 | } 386 | } 387 | 388 | /** 389 | * @fn calculate_exchange_correlation_matrix 390 | * @brief calculates the exchange-correlation matrix 391 | * 392 | * @return void 393 | */ 394 | void DFT::calculate_exchange_correlation_matrix() { 395 | VectorXd densities = this->molgrid->get_densities(); 396 | VectorXd weights = this->molgrid->get_weights(); 397 | MatrixXXd amplitudes = this->molgrid->get_amplitudes(); 398 | 399 | VectorXd ex; // exchange energy 400 | VectorXd vxa; // exchange potential (spin-up) 401 | VectorXd vxb; // exchange potential (spin-down) 402 | 403 | VectorXd ec; // correlation energy 404 | VectorXd vca; // correlation potential (spin-up) 405 | VectorXd vcb; // correlation potential (spin-down) 406 | 407 | VectorXd densitiesa = densities * 0.5; 408 | VectorXd densitiesb = densities * 0.5; 409 | 410 | // calculate exchange energies and potential 411 | this->functional->xalpha_x_functional(densitiesa, densitiesb, ex, vxa, vxb); 412 | 413 | // calculate correlation energy and potential 414 | this->functional->vwm_c_functional(densitiesa, densitiesb, ec, vca, vcb); 415 | 416 | // calculate total exchange-correlation energy 417 | this->exc = weights.dot(ex + ec); 418 | 419 | // calculate gridpoint-wise xc potential 420 | 421 | // I still don't understand why I need to put a 0.5 here... (see also the function above) 422 | // Does it have anything to do how I construct the density matrix P? 423 | // Can someone who knows the answer send me an e-mail? 424 | VectorXd wva = weights.cwiseProduct((vxa + vxb + vca + vcb) * 0.5); 425 | 426 | for(unsigned int i=0; icgfs->size(); i++) { 427 | VectorXd row = amplitudes.row(i); 428 | VectorXd wva_i = wva.cwiseProduct(row); 429 | for(unsigned int j=0; jcgfs->size(); j++) { 430 | this->XC(i,j) = wva_i.dot(amplitudes.row(j)); 431 | } 432 | } 433 | } 434 | 435 | /** 436 | * @fn calculate_energy 437 | * @brief calculate the energy of the molecule 438 | * 439 | * @return void 440 | */ 441 | void DFT::calculate_energy() { 442 | this->single_electron_energy = 2.0 * (this->P * this->H).trace(); 443 | this->electronic_repulsion = 2.0 * (this->P * this->J).trace(); 444 | 445 | // sum all terms 446 | this->et = this->single_electron_energy + this->electronic_repulsion + this->enuc + this->exc; 447 | } 448 | 449 | /** 450 | * @brief Calculates the hartree potential from two electrons integrals 451 | */ 452 | void DFT::calculate_hartree_potential_te_int() { 453 | const unsigned int size = this->mol->get_nr_bfs(); 454 | 455 | // Populate two-electron repulsion matrix 456 | #pragma omp parallel for collapse(2) 457 | for(unsigned int i=0; iJ(i,j) = 0.; /* reset J matrix */ 460 | for(unsigned int k=0; kteindex(i,j,k,l); 463 | 464 | // Exchange in Hartree-Fock 465 | //const unsigned int index2 = integrator->teindex(i,k,l,j); 466 | //this->J(i,j) += P(k,l) * (ints(index) - 0.5 * ints(index2)); 467 | 468 | // I still don't understand why I need to put a 0.5 here... (see also the function below) 469 | // Does it have anything to do how I construct the density matrix P? 470 | // Can someone who knows the answer send me an e-mail? 471 | 472 | this->J(i,j) += P(k,l) * ints(index); 473 | } 474 | } 475 | } 476 | } 477 | } 478 | 479 | /** 480 | * @brief Calculates the hartree potential over Becke grid using Poisson equation 481 | */ 482 | void DFT::calculate_hartree_potential_becke_poisson() { 483 | this->J = this->molgrid->calculate_hartree_potential(); 484 | } 485 | 486 | /* 487 | * @brief Finalize calculation and store requested data 488 | */ 489 | void DFT::finalize() { 490 | 491 | // needs to be connected to interface 492 | 493 | // // build rectangular grid 494 | // RectangularGrid rg(this->mol); 495 | 496 | // // create grid points 497 | // rg.build_grid(5.0, 15); 498 | 499 | // // set the density 500 | // rg.set_density(this->P); 501 | 502 | // // write the grid to a file 503 | // rg.write_gradient("data.dat"); 504 | } 505 | --------------------------------------------------------------------------------