Thank you for all the help, libint builds now. CMake would definitely make this easier, and I have noticed all the work you have put in to the CMake modifications on your own fork/pull requests, so thank you for that. I was also able to make the changes I needed to libint, which were thankfully all in the header files, so make export
didn’t have to rebuild much, though the modifications worked on the first try. For anyone’s reference, the following worked for me:
all_configure.sh
:
#!/bin/bash
# Build the compiler for libint in your current directory
# This also unifies all the config options that are scattered throughout the code
# Granted, you still have to edit them in three different spots within this file, but it's a bit more manageable
set -e
WD=$(pwd)
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
if [[ "$WD/" == "$SCRIPT_DIR/" ]] || [[ "$WD/" == "$SCRIPT_DIR/"* ]]; then
echo "Looks like you're in the libint source tree"
echo "I'm told that you can't put your build directory in the source tree"
echo "Stopping before you get a more frustrating error..."
exit 1
fi
cd $SCRIPT_DIR
./autogen.sh
# Patch the CMakeLists file
# Yes, its in the source tree, but this feels less cursed than unzipping and re-zipping
MAX_AM_ERI=2 # Note that this is just one minus the length of LIBINT_eri_max_am, I think
sed -i -E "s/set\(MAX_AM_ERI \"[0-9]*\"\)/set\(MAX_AM_ERI \"$MAX_AM_ERI\"\)/" export/cmake/CMakeLists.txt.export
# Get the config string
# * For each integrals class, supply a list with max AM for each enabled derivative level.
# * User is responsible for "distributing" defaults across classes and derivs.
# e.g., `--enable-eri2=2 --with-max-am=4` (`--with-eri2-max-am` not specified) becomes `eri2_max_am = [4, 4, 4]`
export LIBINT_orderings=ss
# max am:
# * only used for paired on eri3.
# * must be same length as eri3_max_am.
# * if `--with-max-am` not given to ./configure, duplicate `eri3_max_am` as `max_am` here.
# * this script will NOT use this as default for other integrals classes.
export LIBINT_max_am=5,5
export LIBINT_multipole=10
export LIBINT_onebody=5,4,3
export LIBINT_eri_max_am=5,5
export LIBINT_eri3_max_am=5,5
export LIBINT_eri3_pure_sh=False
export LIBINT_eri2_max_am=5,5
export LIBINT_eri2_pure_sh=False
export LIBINT_g12_max_am=4,4
CONFIG_STR=$(python3 export/cmake/configuration-gen.py)
echo Using generated config string $CONFIG_STR
sed -i -E "s/return \"[^\"]*\";/return \"$CONFIG_STR\";/" src/lib/libint/configuration.cc
# Ok, so now configure will all of our options.
# I stole these from the Psi4 release: https://forum.psicode.org/t/which-libint-version-is-being-used/3117/13?u=kb1rd
cd $WD
$SCRIPT_DIR/configure \
--enable-eri=1 \
--enable-eri3=1 \
--enable-eri2=1 \
--enable-1body=2 \
--enable-g12=1 \
--disable-1body-property-derivs \
--with-multipole-max-order=10 \
--with-g12-max-am=4 \
--with-eri-max-am=5,5 \
--with-eri3-max-am=5,5 \
--with-eri2-max-am=5,5 \
--with-max-am=5,5
# Now actually make. I think you only need to re-run this if you change the header files in include/libint2/...
make export
echo
echo "All set, export file created!"
export/cmake/configuration-gen.py
:
# <<< User edit
import os
def arg(nm): return os.environ["LIBINT_" + nm]
# https://stackoverflow.com/a/715455/7853604
# Leaving the full list in there because it makes me chuckle
def arg_bool(nm): arg(nm).lower() in ['true', '1', 't', 'y', 'yes', 'yeah', 'yup', 'certainly', 'uh-huh']
def arg_intarray(nm): return [int(a) for a in arg(nm).split(',')] if arg(nm).strip() else []
# * For each integrals class, supply a list with max AM for each enabled derivative level.
# * User is responsible for "distributing" defaults across classes and derivs.
# e.g., `--enable-eri2=2 --with-max-am=4` (`--with-eri2-max-am` not specified) becomes `eri2_max_am = [4, 4, 4]`
orderings = arg('orderings')
# max am:
# * only used for paired on eri3.
# * must be same length as eri3_max_am.
# * if `--with-max-am` not given to ./configure, duplicate `eri3_max_am` as `max_am` here.
# * this script will NOT use this as default for other integrals classes.
max_am = arg_intarray("max_am")
multipole = arg_intarray("multipole")
onebody = arg_intarray("onebody")
eri_max_am = arg_intarray("eri_max_am")
eri3_max_am = arg_intarray("eri3_max_am")
eri3_pure_sh = arg_bool("eri3_pure_sh")
eri2_max_am = arg_intarray("eri2_max_am")
eri2_pure_sh = arg_bool("eri2_pure_sh")
g12_max_am = arg_intarray("g12_max_am")
# >>> End user edit
amstr = "SPDFGHIKLMNOQRTUVWXYZ"
components = [orderings]
# multipole
for deriv in range(len(multipole)):
for am in range(multipole[deriv], 1, -1): # don't enumerate s, p
centers = amstr[am].lower() * 2
comp = f"multipole_{centers}_d{deriv}"
components.append(comp)
# onebody
for deriv in range(len(onebody)):
for am in range(onebody[deriv], 1, -1):
centers = amstr[am].lower() * 2
comp = f"onebody_{centers}_d{deriv}"
components.append(comp)
# eri (4-center)
for deriv in range(len(eri_max_am)):
for am in range(eri_max_am[deriv], 1, -1):
centers = amstr[am].lower() * 4
comp = f"eri_{centers}_d{deriv}"
components.append(comp)
# eri3
no_pure_sh = []
for deriv in range(len(eri3_max_am)):
for am_paired in range(max_am[deriv], 1, -1):
for am_fitting in range(eri3_max_am[deriv], 1, -1):
if am_fitting >= am_paired:
centers = amstr[am_paired].lower() * 2 + amstr[am_fitting].upper()
comp = f"eri_{centers}_d{deriv}"
#print(deriv, am_fitting, am_paired, centers, comp)
components.append(comp)
no_pure_sh.append(comp.lower())
if not eri3_pure_sh:
components.extend(no_pure_sh)
# eri2
no_pure_sh = []
for deriv in range(len(eri2_max_am)):
for am in range(eri2_max_am[deriv], 1, -1):
centers = amstr[am].upper() * 2
comp = f"eri_{centers}_d{deriv}"
components.append(comp)
no_pure_sh.append(comp.lower())
if not eri2_pure_sh:
components.extend(no_pure_sh)
# g12
for deriv in range(len(g12_max_am)):
for am in range(g12_max_am[deriv], 1, -1):
centers = amstr[am].lower() * 4
comp = f"g12_{centers}_d{deriv}"
components.append(comp)
#for comp in components:
# print(comp)
components = ";".join(components)
print(components)