Skip to content

Commit 5fec435

Browse files
authored
Dockerize CI workflow (pyscf#359)
* dockerize ci workflow * remove ecp * dockerize nightly build * cache c2s * remove pytest cache * same user in ci * setup cupy cache dir * more env variables * int2c2e_ip not implemented
1 parent 0f5b8d6 commit 5fec435

File tree

7 files changed

+120
-142
lines changed

7 files changed

+120
-142
lines changed

.github/workflows/nightly_build.yml

+35-50
Original file line numberDiff line numberDiff line change
@@ -16,70 +16,55 @@ jobs:
1616
runs-on: [self-hosted, Linux, X64, v100]
1717
steps:
1818
- uses: actions/checkout@v3
19-
- name: Install dependencies
19+
20+
- name: Pull CUDA Devel Image
2021
run: |
21-
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
22-
python3 -m pip install --upgrade pip
23-
pip3 install flake8 pytest coverage pytest-cov pyscf-dispersion
24-
pip3 install pytest-benchmark
25-
pip3 install pyscf --upgrade
26-
pip3 install numpy --upgrade
27-
pip3 install scipy --upgrade
28-
pip3 install cupy-cuda12x --upgrade
29-
pip3 install gpu4pyscf-libxc-cuda12x --upgrade
30-
git config --global core.compression 9
22+
docker pull wxj6000/gpu4pyscf:latest
23+
3124
- name: Run RKS tests
3225
run: |
33-
export CUDA_HOME=/usr/local/cuda
34-
export PATH=${CUDA_HOME}/bin:${PATH}
35-
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:$LD_LIBRARY_PATH
36-
sh build.sh
37-
pytest gpu4pyscf/tests/test_benchmark_rks.py -s -v -m "not slow and not high_memory" --benchmark-compare-fail=min:10% --benchmark-compare=v1.3.0_rks_1v100 --benchmark-storage=gpu4pyscf/tests/benchmark_results/
38-
26+
docker run --gpus all \
27+
-u "$(id -u):$(id -g)" \
28+
-e CUPY_CACHE_DIR=/workspace/.cupy_cache \
29+
-e HTTP_PROXY=$HTTP_PROXY \
30+
-e HTTPS_PROXY=$HTTPS_PROXY \
31+
-v $GITHUB_WORKSPACE:/workspace wxj6000/gpu4pyscf:latest \
32+
/bin/bash -c "cd /workspace && source build.sh && pytest gpu4pyscf/tests/test_benchmark_rks.py -s -v -m 'not slow and not high_memory' --benchmark-compare-fail=min:10% --benchmark-compare=v1.3.0_rks_1v100 --benchmark-storage=gpu4pyscf/tests/benchmark_results/ && rm -rf .pytest_cache"
33+
3934
test_uks:
4035
runs-on: [self-hosted, Linux, X64, v100]
4136
steps:
4237
- uses: actions/checkout@v3
43-
- name: Install dependencies
38+
39+
- name: Pull CUDA Devel Image
4440
run: |
45-
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
46-
python3 -m pip install --upgrade pip
47-
pip3 install flake8 pytest coverage pytest-cov pyscf-dispersion
48-
pip3 install pytest-benchmark
49-
pip3 install pyscf --upgrade
50-
pip3 install numpy --upgrade
51-
pip3 install scipy --upgrade
52-
pip3 install cupy-cuda12x --upgrade
53-
pip3 install gpu4pyscf-libxc-cuda12x --upgrade
54-
git config --global core.compression 9
41+
docker pull wxj6000/gpu4pyscf:latest
42+
5543
- name: Run UKS tests
5644
run: |
57-
export CUDA_HOME=/usr/local/cuda
58-
export PATH=${CUDA_HOME}/bin:${PATH}
59-
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:$LD_LIBRARY_PATH
60-
sh build.sh
61-
pytest gpu4pyscf/tests/test_benchmark_uks.py -s -v -m "not slow and not high_memory" --benchmark-compare-fail=min:10% --benchmark-compare=v1.3.0_uks_1v100 --benchmark-storage=gpu4pyscf/tests/benchmark_results/
62-
45+
docker run --gpus all \
46+
-u "$(id -u):$(id -g)" \
47+
-e CUPY_CACHE_DIR=/workspace/.cupy_cache \
48+
-e HTTP_PROXY=$HTTP_PROXY \
49+
-e HTTPS_PROXY=$HTTPS_PROXY \
50+
-v $GITHUB_WORKSPACE:/workspace wxj6000/gpu4pyscf:latest \
51+
/bin/bash -c "cd /workspace && source build.sh && pytest gpu4pyscf/tests/test_benchmark_uks.py -s -v -m 'not slow and not high_memory' --benchmark-compare-fail=min:10% --benchmark-compare=v1.3.0_uks_1v100 --benchmark-storage=gpu4pyscf/tests/benchmark_results/ && rm -rf .pytest_cache"
52+
6353
test_tddft:
6454
runs-on: [self-hosted, Linux, X64, v100]
6555
steps:
6656
- uses: actions/checkout@v3
67-
- name: Install dependencies
57+
58+
- name: Pull CUDA Devel Image
6859
run: |
69-
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
70-
python3 -m pip install --upgrade pip
71-
pip3 install flake8 pytest coverage pytest-cov pyscf-dispersion
72-
pip3 install pytest-benchmark
73-
pip3 install pyscf --upgrade
74-
pip3 install numpy --upgrade
75-
pip3 install scipy --upgrade
76-
pip3 install cupy-cuda12x --upgrade
77-
pip3 install gpu4pyscf-libxc-cuda12x --upgrade
78-
git config --global core.compression 9
60+
docker pull wxj6000/gpu4pyscf:latest
61+
7962
- name: Run TDDFT tests
8063
run: |
81-
export CUDA_HOME=/usr/local/cuda
82-
export PATH=${CUDA_HOME}/bin:${PATH}
83-
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:$LD_LIBRARY_PATH
84-
sh build.sh
85-
pytest gpu4pyscf/tests/test_benchmark_tddft.py -s -v -m "not slow and not high_memory" --benchmark-compare-fail=min:10% --benchmark-compare=v1.3.0_tddft_1v100 --benchmark-storage=gpu4pyscf/tests/benchmark_results/
64+
docker run --gpus all \
65+
-u "$(id -u):$(id -g)" \
66+
-e CUPY_CACHE_DIR=/workspace/.cupy_cache \
67+
-e HTTP_PROXY=$HTTP_PROXY \
68+
-e HTTPS_PROXY=$HTTPS_PROXY \
69+
-v $GITHUB_WORKSPACE:/workspace wxj6000/gpu4pyscf:latest \
70+
/bin/bash -c "cd /workspace && source build.sh && pytest gpu4pyscf/tests/test_benchmark_tddft.py -s -v -m 'not slow and not high_memory' --benchmark-compare-fail=min:10% --benchmark-compare=v1.3.0_tddft_1v100 --benchmark-storage=gpu4pyscf/tests/benchmark_results/ && rm -rf .pytest_cache"

.github/workflows/unittest.yml

+22-40
Original file line numberDiff line numberDiff line change
@@ -17,54 +17,36 @@ jobs:
1717
runs-on: [self-hosted, Linux, X64, v100]
1818
steps:
1919
- uses: actions/checkout@v3
20-
- name: Install dependencies
21-
run: |
22-
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
23-
python3 -m pip install --upgrade pip
24-
pip3 install pytest-benchmark
25-
pip3 install flake8 pytest coverage pytest-cov pyscf-dispersion
26-
pip3 install pyscf --upgrade
27-
pip3 install git+https://github.com/pyscf/properties --upgrade
28-
pip3 install numpy --upgrade
29-
pip3 install h5py --upgrade
30-
pip3 install gpu4pyscf-libxc-cuda12x --upgrade
31-
pip3 install cupy-cuda12x --upgrade
32-
git config --global core.compression 9
33-
- name: Build GPU4PySCF
20+
21+
- name: Pull CUDA Devel Image
3422
run: |
35-
export CUDA_HOME=/usr/local/cuda
36-
export CMAKE_CONFIGURE_ARGS="-DBUILD_LIBXC=OFF -DCUDA_ARCHITECTURES=70-real -DBUILD_CUTLASS=ON"
37-
sh build.sh
23+
docker pull wxj6000/gpu4pyscf:latest
24+
3825
- name: Test with pytest
3926
run: |
40-
echo $GITHUB_WORKSPACE
41-
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
42-
pytest -m "not benchmark" --cov=$GITHUB_WORKSPACE
27+
docker run --gpus all \
28+
-u "$(id -u):$(id -g)" \
29+
-e CUPY_CACHE_DIR=/workspace/.cupy_cache \
30+
-e HTTP_PROXY=$HTTP_PROXY \
31+
-e HTTPS_PROXY=$HTTPS_PROXY \
32+
-v $GITHUB_WORKSPACE:/workspace wxj6000/gpu4pyscf:latest \
33+
/bin/bash -c "cd /workspace && source build.sh && pytest -m 'not benchmark' --cov=/workspace && rm -rf .pytest_cache"
4334
4435
multi-gpu:
4536
runs-on: [self-hosted, Linux, X64, 2T4]
4637
steps:
4738
- uses: actions/checkout@v3
48-
- name: Install dependencies
49-
run: |
50-
pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
51-
python3 -m pip install --upgrade pip
52-
pip3 install pytest-benchmark
53-
pip3 install flake8 pytest coverage pytest-cov pyscf-dispersion
54-
pip3 install pyscf --upgrade
55-
pip3 install git+https://github.com/pyscf/properties --upgrade
56-
pip3 install numpy --upgrade
57-
pip3 install h5py --upgrade
58-
pip3 install gpu4pyscf-libxc-cuda12x --upgrade
59-
pip3 install cupy-cuda12x --upgrade
60-
git config --global core.compression 9
61-
- name: Build GPU4PySCF
39+
40+
- name: Pull CUDA Devel Image
6241
run: |
63-
export CUDA_HOME=/usr/local/cuda
64-
export CMAKE_CONFIGURE_ARGS="-DBUILD_LIBXC=OFF -DCUDA_ARCHITECTURES=70-real -DBUILD_CUTLASS=ON"
65-
sh build.sh
42+
docker pull wxj6000/gpu4pyscf:latest
43+
6644
- name: Test with pytest
6745
run: |
68-
echo $GITHUB_WORKSPACE
69-
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
70-
pytest -m "not benchmark" --cov=$GITHUB_WORKSPACE
46+
docker run --gpus all \
47+
-u "$(id -u):$(id -g)" \
48+
-e CUPY_CACHE_DIR=/workspace/.cupy_cache \
49+
-e HTTP_PROXY=$HTTP_PROXY \
50+
-e HTTPS_PROXY=$HTTPS_PROXY \
51+
-v $GITHUB_WORKSPACE:/workspace wxj6000/gpu4pyscf:latest \
52+
/bin/bash -c "cd /workspace && source build.sh && pytest -m 'not benchmark' --cov=/workspace && rm -rf .pytest_cache"

dockerfiles/compile/Dockerfile

+17-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,5 @@
11
# CUDA 11.8
2-
FROM nvidia/cuda:11.8.0-devel-ubuntu22.04
3-
RUN apt-get update && \
4-
apt-get install -yq --no-install-recommends gnupg2 curl vim python3 python3-pip python3-setuptools cmake git \
5-
ca-certificates libopenblas-dev gfortran
6-
7-
ENV CUDA_HOME="/usr/local/cuda" LD_LIBRARY_PATH="${CUDA_HOME}/lib64::${LD_LIBRARY_PATH}"
8-
RUN echo "export PATH=${CUDA_HOME}/bin:\$PATH" >> /etc/bash.bashrc
9-
RUN echo "export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:\$LD_LIBRARY_PATH" >> /etc/bash.bashrc
10-
11-
RUN pip3 install -U --no-cache-dir pytest numpy cupy-cuda11x pyscf cutensor-cu11
12-
13-
# CUDA 12.3
14-
#FROM nvidia/cuda:12.3.2-devel-ubuntu22.04
2+
#FROM nvidia/cuda:11.8.0-devel-ubuntu22.04
153
#RUN apt-get update && \
164
# apt-get install -yq --no-install-recommends gnupg2 curl vim python3 python3-pip python3-setuptools cmake git \
175
# ca-certificates libopenblas-dev gfortran
@@ -20,4 +8,19 @@ RUN pip3 install -U --no-cache-dir pytest numpy cupy-cuda11x pyscf cutensor-cu11
208
#RUN echo "export PATH=${CUDA_HOME}/bin:\$PATH" >> /etc/bash.bashrc
219
#RUN echo "export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:\$LD_LIBRARY_PATH" >> /etc/bash.bashrc
2210

23-
#RUN pip3 install -U --no-cache-dir pytest numpy cupy-cuda12x pyscf cutensor-cu12
11+
#RUN pip3 install -U --no-cache-dir pytest numpy cupy-cuda11x pyscf cutensor-cu11
12+
13+
# CUDA 12.4
14+
FROM nvidia/cuda:12.4.1-devel-ubuntu22.04
15+
RUN apt-get update && \
16+
apt-get install -yq --no-install-recommends gnupg2 curl vim python3 python3-pip python3-setuptools cmake git \
17+
ca-certificates libopenblas-dev gfortran
18+
19+
ENV CUDA_HOME="/usr/local/cuda" LD_LIBRARY_PATH="${CUDA_HOME}/lib64::${LD_LIBRARY_PATH}"
20+
RUN echo "export PATH=${CUDA_HOME}/bin:\$PATH" >> /etc/bash.bashrc
21+
RUN echo "export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:\$LD_LIBRARY_PATH" >> /etc/bash.bashrc
22+
23+
RUN pip3 install -U --no-cache-dir pytest numpy cupy-cuda12x pyscf cutensor-cu12 pytest-cov pytest-benchmark flake8 pyscf-dispersion
24+
RUN pip3 install geometric
25+
RUN pip3 install gpu4pyscf-libxc-cuda12x==0.5
26+
RUN pip3 install git+https://github.com/pyscf/properties --upgrade

gpu4pyscf/gto/mole.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@
2323

2424
PTR_BAS_COORD = 7
2525

26-
# @functools.lru_cache(20) # This cache introduces a bug in mutli-gpu mode
26+
_c2s = {}
27+
2728
def cart2sph_by_l(l, normalized='sp'):
28-
c2s = gto.mole.cart2sph(l, normalized=normalized)
29-
return cp.asarray(c2s, order='C')
29+
device_id = cp.cuda.Device().id
30+
if (l, device_id, normalized) not in _c2s:
31+
c2s = gto.mole.cart2sph(l, normalized=normalized)
32+
_c2s[l,device_id,normalized] = cp.asarray(c2s, order='C')
33+
return _c2s[l,device_id,normalized]
3034

3135
def basis_seg_contraction(mol, allow_replica=1, sparse_coeff=False):
3236
'''transform generally contracted basis to segment contracted basis

gpu4pyscf/qmmm/pbc/itrf.py

+19-18
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
from cupyx.scipy.special import erfc, erf
3636

37-
def add_mm_charges(scf_method, atoms_or_coords, a, charges, radii=None,
37+
def add_mm_charges(scf_method, atoms_or_coords, a, charges, radii=None,
3838
rcut_ewald=None, rcut_hcore=None, unit=None):
3939
'''Embedding the one-electron (non-relativistic) potential generated by MM
4040
point charges into QM Hamiltonian.
@@ -43,8 +43,8 @@ def add_mm_charges(scf_method, atoms_or_coords, a, charges, radii=None,
4343
the nuclei in QM region and the MM charges, and the static Coulomb
4444
interaction between the electron density and the MM charges. The electrostatic
4545
interactions between reference cell and periodic images are also computed at
46-
point charge level. It does not include the static Coulomb interactions
47-
of the MM point charges, the MM energy, the vdw interaction or other
46+
point charge level. It does not include the static Coulomb interactions
47+
of the MM point charges, the MM energy, the vdw interaction or other
4848
bonding/non-bonding effects between QM region and MM particles.
4949
5050
Args:
@@ -79,7 +79,7 @@ def add_mm_charges(scf_method, atoms_or_coords, a, charges, radii=None,
7979
mol = scf_method.mol
8080
if unit is None:
8181
unit = mol.unit
82-
mm_mol = mm_mole.create_mm_mol(atoms_or_coords, a, charges, radii=radii,
82+
mm_mol = mm_mole.create_mm_mol(atoms_or_coords, a, charges, radii=radii,
8383
rcut_ewald=rcut_ewald, rcut_hcore=rcut_hcore, unit=unit)
8484
return qmmm_for_scf(scf_method, mm_mol)
8585

@@ -117,7 +117,8 @@ class QMMM:
117117
class QMMMSCF(QMMM):
118118
_keys = {'mm_mol', 's1r', 's1rr', 'mm_ewald_pot', 'qm_ewald_hess', 'e_nuc'}
119119

120-
to_cpu = NotImplemented
120+
to_cpu = NotImplemented
121+
as_scanner = NotImplemented
121122

122123
def __init__(self, method, mm_mol):
123124
self.__dict__.update(method.__dict__)
@@ -304,7 +305,7 @@ def get_qm_quadrupoles(self, dm, s1rr=None):
304305
def get_vdiff(self, mol, ewald_pot):
305306
'''
306307
vdiff_uv = d Q_I / d dm_uv ewald_pot[0]_I
307-
+ d D_Ix / d dm_uv ewald_pot[1]_Ix
308+
+ d D_Ix / d dm_uv ewald_pot[1]_Ix
308309
+ d O_Ixy / d dm_uv ewald_pot[2]_Ixy
309310
'''
310311
vdiff = cp.zeros((mol.nao, mol.nao))
@@ -406,7 +407,7 @@ def energy_nuc(self):
406407
mol = self.mol
407408
Ls = self.mm_mol.get_lattice_Ls()
408409
qm_center = np.mean(mol.atom_coords(), axis=0)
409-
all_coords = lib.direct_sum('ix+Lx->Lix',
410+
all_coords = lib.direct_sum('ix+Lx->Lix',
410411
self.mm_mol.atom_coords(), Ls).reshape(-1,3)
411412
all_charges = np.hstack([self.mm_mol.atom_charges()] * len(Ls))
412413
all_expnts = np.hstack([np.sqrt(self.mm_mol.get_zetas())] * len(Ls))
@@ -441,7 +442,7 @@ def nuc_grad_method(self):
441442
Gradients = nuc_grad_method
442443

443444

444-
def add_mm_charges_grad(scf_grad, atoms_or_coords, a, charges, radii=None,
445+
def add_mm_charges_grad(scf_grad, atoms_or_coords, a, charges, radii=None,
445446
rcut_ewald=None, rcut_hcore=None, unit=None):
446447
'''Apply the MM charges in the QM gradients' method. It affects both the
447448
electronic and nuclear parts of the QM fragment.
@@ -473,7 +474,7 @@ def add_mm_charges_grad(scf_grad, atoms_or_coords, a, charges, radii=None,
473474
mol = scf_grad.mol
474475
if unit is None:
475476
unit = mol.unit
476-
mm_mol = mm_mole.create_mm_mol(atoms_or_coords, a, charges, radii=radii,
477+
mm_mol = mm_mole.create_mm_mol(atoms_or_coords, a, charges, radii=radii,
477478
rcut_ewald=rcut_ewald, rcut_hcore=rcut_hcore, unit=unit)
478479
mm_grad = qmmm_grad_for_scf(scf_grad)
479480
mm_grad.base.mm_mol = mm_mol
@@ -581,7 +582,7 @@ def grad_ewald(self, dm=None, with_mm=False, mm_ewald_pot=None, qm_ewald_pot=Non
581582
s1r.append(
582583
cp.asarray(-mol.intor('int1e_irp', shls_slice=shlslc).
583584
reshape(3, 3, -1, mol.nao)))
584-
# s1rr[a,b,x,u,v] =
585+
# s1rr[a,b,x,u,v] =
585586
# \int phi_u [3/2*(r_a-Ri_a)(r_b-Ri_b)-1/2*(r-Ri)^2 delta_ab] (-\nable_x phi_v) dr
586587
s1rr_ = cp.asarray(-mol.intor('int1e_irrp', shls_slice=shlslc).
587588
reshape(3, 3, 3, -1, mol.nao))
@@ -635,8 +636,8 @@ def grad_ewald(self, dm=None, with_mm=False, mm_ewald_pot=None, qm_ewald_pot=Non
635636
grad_Tij = lambda R, r: get_multipole_tensors_pp(R, [1,2,3], r)
636637
grad_kTij = lambda R, r, eta: get_multipole_tensors_pg(R, eta, [1,2,3], r)
637638

638-
def grad_qm_multipole(Tija, Tijab, Tijabc,
639-
qm_charges, qm_dipoles, qm_quads,
639+
def grad_qm_multipole(Tija, Tijab, Tijabc,
640+
qm_charges, qm_dipoles, qm_quads,
640641
mm_charges):
641642
Tc = contract('ijx,j->ix', Tija, mm_charges)
642643
res = contract('i,ix->ix', qm_charges, Tc)
@@ -646,8 +647,8 @@ def grad_qm_multipole(Tija, Tijab, Tijabc,
646647
res += contract('iab,ixab->ix', qm_quads, Tc) / 3
647648
return res
648649

649-
def grad_mm_multipole(Tija, Tijab, Tijabc,
650-
qm_charges, qm_dipoles, qm_quads,
650+
def grad_mm_multipole(Tija, Tijab, Tijabc,
651+
qm_charges, qm_dipoles, qm_quads,
651652
mm_charges):
652653
Tc = contract('i,ijx->jx', qm_charges, Tija)
653654
Tc += contract('ia,ijxa->jx', qm_dipoles, Tijab)
@@ -771,7 +772,7 @@ def grad_mm_multipole(Tija, Tijab, Tijabc,
771772
# ---------------------------------------------- #
772773
# ---------- Ewald k-space gradient ------------ #
773774
# ---------------------------------------------- #
774-
775+
775776
mesh = cell.mesh
776777
Gv, Gvbase, weights = cell.get_Gv_weights(mesh)
777778
Gv = cp.asarray(Gv)
@@ -967,7 +968,7 @@ def grad_mm_multipole(Tija, Tijab, Tijabc,
967968
temp = contract('ag,bgx->abgx', temp, temp2)
968969
temp = contract('jg,abgx->abjx', cosGvRqm, temp)
969970
qm_ewg_grad -= contract('jab,abjx->jx', qm_quads, temp) / 3
970-
971+
971972
logger.timer(self, 'grad_ewald k-space', *cput2)
972973
logger.timer(self, 'grad_ewald', *cput0)
973974
if not with_mm:
@@ -1113,7 +1114,7 @@ def grad_nuc_mm(self, mol=None):
11131114
charges = mm_mol.atom_charges()
11141115
Ls = mm_mol.get_lattice_Ls()
11151116
qm_center = np.mean(mol.atom_coords(), axis=0)
1116-
all_coords = lib.direct_sum('ix+Lx->Lix',
1117+
all_coords = lib.direct_sum('ix+Lx->Lix',
11171118
mm_mol.atom_coords(), Ls).reshape(-1,3)
11181119
all_charges = np.hstack([mm_mol.atom_charges()] * len(Ls))
11191120
all_expnts = np.hstack([np.sqrt(mm_mol.get_zetas())] * len(Ls))
@@ -1130,7 +1131,7 @@ def grad_nuc_mm(self, mol=None):
11301131
r1 = mol.atom_coord(i)
11311132
r = lib.norm(r1-coords, axis=1)
11321133
g_mm[mask] += q1 * lib.einsum('i,ix,i->ix', charges, r1-coords, erf(expnts*r)/r**3)
1133-
g_mm[mask] -= q1 * lib.einsum('i,ix,i->ix', charges * expnts * 2 / np.sqrt(np.pi),
1134+
g_mm[mask] -= q1 * lib.einsum('i,ix,i->ix', charges * expnts * 2 / np.sqrt(np.pi),
11341135
r1-coords, np.exp(-expnts**2 * r**2)/r**2)
11351136
g_mm = g_mm.reshape(len(Ls), -1, 3)
11361137
g_mm = np.sum(g_mm, axis=0)

0 commit comments

Comments
 (0)