1{ lib
2, stdenv
3, fetchFromGitHub
4, autoconf
5, automake
6, libtool
7, python3
8, perl
9, gmpxx
10, mpfr
11, boost
12, eigen
13, gfortran
14, cmake
15, enableFMA ? stdenv.hostPlatform.fmaSupport
16, enableFortran ? true
17, enableSSE ? (!enableFortran) && stdenv.hostPlatform.isx86_64
18
19 # Maximum angular momentum of basis functions
20 # 7 is required for def2/J auxiliary basis on 3d metals upwards
21, maxAm ? 7
22
23 # ERI derivative order for 4-, 3- and 2-centre ERIs.
24 # 2nd derivatives are defaults and allow gradients Hessians with density fitting
25 # Setting them to zero disables derivatives.
26, eriDeriv ? 2
27, eri3Deriv ? 2
28, eri2Deriv ? 2
29
30 # Angular momentum for derivatives of ERIs. Takes a list of length $DERIV_ORD+1.
31 # Starting from index 0, each index i specifies the supported angular momentum
32 # for the derivative order i, e.g. [6,5,4] supports ERIs for l=6, their first
33 # derivatives for l=5 and their second derivatives for l=4.
34, eriAm ? (builtins.genList (i: maxAm - 1 - i) (eriDeriv + 1))
35, eri3Am ? (builtins.genList (i: maxAm - i) (eri2Deriv + 1))
36, eri2Am ? (builtins.genList (i: maxAm - i) (eri2Deriv + 1))
37
38 # Same as above for optimised code. Higher optimisations take a long time.
39, eriOptAm ? (builtins.genList (i: maxAm - 3 - i) (eriDeriv + 1))
40, eri3OptAm ? (builtins.genList (i: maxAm - 3 - i) (eri2Deriv + 1))
41, eri2OptAm ? (builtins.genList (i: maxAm - 3 - i) (eri2Deriv + 1))
42
43 # One-Electron integrals of all kinds including multipole integrals.
44 # Libint does not build them and their derivatives by default.
45, enableOneBody ? false
46, oneBodyDerivOrd ? 2
47, multipoleOrd ? 4 # Maximum order of multipole integrals, 4=octopoles
48
49 # Whether to enable generic code if angular momentum is unsupported
50, enableGeneric ? true
51
52 # Support integrals over contracted Gaussian
53, enableContracted ? true
54
55 # Spherical harmonics/Cartesian orbital conventions
56, cartGaussOrd ? "standard" # Ordering of Cartesian basis functions, "standard" is CCA
57, shGaussOrd ? "standard" # Ordering of spherical harmonic basis functions. "standard" is -l to +l, "guassian" is 0, 1, -1, 2, -2, ...
58, shellSet ? "standard"
59, eri3PureSh ? false # Transformation of 3-centre ERIs into spherical harmonics
60, eri2PureSh ? false # Transformation of 2-centre ERIs into spherical harmonics
61}:
62
63# Check that Fortran bindings are not used together with SIMD real type
64assert (if enableFortran then !enableSSE else true);
65
66# Check that a possible angular momentum for basis functions is used
67assert (maxAm >= 1 && maxAm <= 8);
68
69# Check for valid derivative order in ERIs
70assert (eriDeriv >= 0 && eriDeriv <= 4);
71assert (eri2Deriv >= 0 && eri2Deriv <= 4);
72assert (eri3Deriv >= 0 && eri3Deriv <= 4);
73
74# Ensure valid arguments for generated angular momenta in ERI derivatives are used.
75assert (
76 builtins.length eriAm == eriDeriv + 1 &&
77 builtins.foldl' (a: b: a && b) true (builtins.map (a: a <= maxAm && a >= 0) eriAm)
78);
79assert (
80 builtins.length eri3Am == eriDeriv + 1 &&
81 builtins.foldl' (a: b: a && b) true (builtins.map (a: a <= maxAm && a >= 0) eri3Am)
82);
83assert (
84 builtins.length eri2Am == eriDeriv + 1 &&
85 builtins.foldl' (a: b: a && b) true (builtins.map (a: a <= maxAm && a >= 0) eri2Am)
86);
87
88# Ensure valid arguments for generated angular momenta in optimised ERI derivatives are used.
89assert (
90 builtins.length eriOptAm == eriDeriv + 1 &&
91 builtins.foldl' (a: b: a && b) true (builtins.map (a: a <= maxAm && a >= 0) eriOptAm)
92);
93assert (
94 builtins.length eri3OptAm == eriDeriv + 1 &&
95 builtins.foldl' (a: b: a && b) true (builtins.map (a: a <= maxAm && a >= 0) eri3OptAm)
96);
97assert (
98 builtins.length eri2OptAm == eriDeriv + 1 &&
99 builtins.foldl' (a: b: a && b) true (builtins.map (a: a <= maxAm && a >= 0) eri2OptAm)
100);
101
102# Ensure a valid derivative order for one-electron integrals
103assert (oneBodyDerivOrd >= 0 && oneBodyDerivOrd <= 4);
104
105# Check that valid basis shell orders are used, see https://github.com/evaleev/libint/wiki
106assert (builtins.elem cartGaussOrd [ "standard" "intv3" "gamess" "orca" "bagel" ]);
107assert (builtins.elem shGaussOrd [ "standard" "gaussian" ]);
108assert (builtins.elem shellSet [ "standard" "orca" ]);
109
110let
111 pname = "libint";
112 version = "2.9.0";
113
114 meta = with lib; {
115 description = "Library for the evaluation of molecular integrals of many-body operators over Gaussian functions";
116 homepage = "https://github.com/evaleev/libint";
117 license = with licenses; [ lgpl3Only gpl3Only ];
118 maintainers = with maintainers; [ markuskowa sheepforce ];
119 platforms = [ "x86_64-linux" ];
120 };
121
122 codeGen = stdenv.mkDerivation {
123 inherit pname version;
124
125 src = fetchFromGitHub {
126 owner = "evaleev";
127 repo = pname;
128 rev = "v${version}";
129 hash = "sha256-y+Mo8J/UWDrkkNEDAoostb/k6jrhYYeU0u9Incrd2cE=";
130 };
131
132 # Replace hardcoded "/bin/rm" with normal "rm"
133 postPatch = ''
134 for f in \
135 bin/ltmain.sh \
136 configure.ac \
137 src/bin/libint/Makefile \
138 src/lib/libint/Makefile.library \
139 tests/eri/Makefile \
140 tests/hartree-fock/Makefile \
141 tests/unit/Makefile; do
142 substituteInPlace $f --replace-warn "/bin/rm" "rm"
143 done
144 '';
145
146 nativeBuildInputs = [
147 autoconf
148 automake
149 libtool
150 mpfr
151 python3
152 perl
153 gmpxx
154 ] ++ lib.optional enableFortran gfortran;
155
156 buildInputs = [ boost eigen ];
157
158 configureFlags = with lib; [
159 "--with-max-am=${builtins.toString maxAm}"
160 "--with-eri-max-am=${concatStringsSep "," (builtins.map builtins.toString eriAm)}"
161 "--with-eri3-max-am=${concatStringsSep "," (builtins.map builtins.toString eri3Am)}"
162 "--with-eri2-max-am=${concatStringsSep "," (builtins.map builtins.toString eri2Am)}"
163 "--with-eri-opt-am=${concatStringsSep "," (builtins.map builtins.toString eriOptAm)}"
164 "--with-eri3-opt-am=${concatStringsSep "," (builtins.map builtins.toString eri3OptAm)}"
165 "--with-eri2-opt-am=${concatStringsSep "," (builtins.map builtins.toString eri2OptAm)}"
166 "--with-cartgauss-ordering=${cartGaussOrd}"
167 "--with-shgauss-ordering=${shGaussOrd}"
168 "--with-shell-set=${shellSet}"
169 ]
170 ++ optional enableFMA "--enable-fma"
171 ++ optional (eriDeriv > 0) "--enable-eri=${builtins.toString eriDeriv}"
172 ++ optional (eri2Deriv > 0) "--enable-eri2=${builtins.toString eri2Deriv}"
173 ++ optional (eri3Deriv > 0) "--enable-eri3=${builtins.toString eri3Deriv}"
174 ++ lists.optionals enableOneBody [
175 "--enable-1body=${builtins.toString oneBodyDerivOrd}"
176 "--enable-1body-property-derivs"
177 ]
178 ++ optional (multipoleOrd > 0) "--with-multipole-max-order=${builtins.toString multipoleOrd}"
179 ++ optional enableGeneric "--enable-generic"
180 ++ optional enableContracted "--enable-contracted-ints"
181 ++ optional eri3PureSh "--enable-eri3-pure-sh"
182 ++ optional eri2PureSh "--enable-eri2-pure-sh"
183 ;
184
185 preConfigure = ''
186 ./autogen.sh
187 '';
188
189 makeFlags = [ "export" ];
190
191 installPhase = ''
192 mkdir -p $out
193 cp ${pname}-${version}.tgz $out/.
194 '';
195
196 enableParallelBuilding = true;
197
198 inherit meta;
199 };
200
201 codeComp = stdenv.mkDerivation {
202 inherit pname version;
203
204 src = "${codeGen}/${pname}-${version}.tgz";
205
206 nativeBuildInputs = [
207 python3
208 cmake
209 ] ++ lib.optional enableFortran gfortran;
210
211 buildInputs = [ boost eigen ];
212
213 # Default is just "double", but SSE2 is available on all x86_64 CPUs.
214 # AVX support is advertised, but does not work.
215 # Fortran interface is incompatible with changing the LIBINT2_REALTYPE.
216 cmakeFlags = [
217 "-DLIBINT2_SHGAUSS_ORDERING=${shGaussOrd}"
218 ] ++ lib.optional enableFortran "-DENABLE_FORTRAN=ON"
219 ++ lib.optional enableSSE "-DLIBINT2_REALTYPE=libint2::simd::VectorSSEDouble";
220
221 # Can only build in the source-tree. A lot of preprocessing magic fails otherwise.
222 dontUseCmakeBuildDir = true;
223
224 inherit meta;
225 };
226
227in
228codeComp