fcdft 1.0.2__tar.gz → 1.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fcdft-1.0.2 → fcdft-1.1.4}/MANIFEST.in +1 -0
- fcdft-1.1.4/PKG-INFO +6 -0
- fcdft-1.1.4/fcdft/__init__.py +1 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/df/df_jk.py +65 -2
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/df/grad/rks.py +27 -13
- fcdft-1.1.4/fcdft/dft/gen_grid.py +88 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/grad/rks.py +3 -3
- fcdft-1.1.4/fcdft/gto/mole.py +110 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/CMakeLists.txt +1 -0
- fcdft-1.1.4/fcdft/lib/df/CMakeLists.txt +8 -0
- fcdft-1.1.4/fcdft/lib/df/nr_contract_k.c +13 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/dft/quadrature.c +44 -4
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/fcdft_helper.c +11921 -12167
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/pbe/CMakeLists.txt +3 -2
- fcdft-1.1.4/fcdft/lib/pbe/poisson.c +152 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/pbe_helper.c +17872 -18275
- fcdft-1.1.4/fcdft/solvent/AMGX.json +32 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/solvent/_attach_solvent.py +5 -1
- fcdft-1.1.4/fcdft/solvent/boundary.py +384 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/solvent/calculus_helper.py +39 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/solvent/esp.py +8 -12
- fcdft-1.1.4/fcdft/solvent/grad/__init__.py +0 -0
- fcdft-1.1.4/fcdft/solvent/grad/pbe.py +416 -0
- fcdft-1.1.4/fcdft/solvent/ions.py +159 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/solvent/pbe.py +109 -308
- fcdft-1.1.4/fcdft/solvent/solver.py +281 -0
- fcdft-1.1.4/fcdft/tools/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/tools/molden.py +2 -1
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/wbl/rks.py +40 -28
- fcdft-1.1.4/fcdft.egg-info/PKG-INFO +6 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft.egg-info/SOURCES.txt +12 -1
- fcdft-1.0.2/PKG-INFO +0 -5
- fcdft-1.0.2/fcdft/__init__.py +0 -1
- fcdft-1.0.2/fcdft/solvent/pbe_grad.py +0 -299
- fcdft-1.0.2/fcdft.egg-info/PKG-INFO +0 -5
- {fcdft-1.0.2 → fcdft-1.1.4}/AUTHORS +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/LICENSE +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/README.md +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/df/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/df/grad/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/df/grad/uks.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/dft/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/dft/numint.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/grad/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/grad/lifcdft.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/grad/uks.py +0 -0
- {fcdft-1.0.2/fcdft/hessian → fcdft-1.1.4/fcdft/gto}/__init__.py +0 -0
- {fcdft-1.0.2/fcdft/jellium → fcdft-1.1.4/fcdft/hessian}/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/hessian/lifcdft.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/hessian/numhess.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/hessian/thermo.py +0 -0
- {fcdft-1.0.2/fcdft/lifcdft → fcdft-1.1.4/fcdft/jellium}/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/jellium/jellium.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/dft/CMakeLists.txt +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/dft/nr_numint.c +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/dft/nr_numint.h +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/fcdft_helper.pyx +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/misc.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/pbe/boundary_condition.c +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/pbe/boundary_condition.h +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/pbe/constant.h +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lib/pbe_helper.pyx +0 -0
- {fcdft-1.0.2/fcdft/solvent → fcdft-1.1.4/fcdft/lifcdft}/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/lifcdft/lifcdft.py +0 -0
- {fcdft-1.0.2/fcdft/tools → fcdft-1.1.4/fcdft/solvent}/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/solvent/radii.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/tools/addons.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/wbl/__init__.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/wbl/abscissas.npy +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/wbl/uks.py +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft/wbl/weights.npy +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft.egg-info/dependency_links.txt +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/fcdft.egg-info/top_level.txt +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/setup.cfg +0 -0
- {fcdft-1.0.2 → fcdft-1.1.4}/setup.py +0 -0
fcdft-1.1.4/PKG-INFO
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '1.1.4'
|
|
@@ -4,6 +4,12 @@ from pyscf.df import df_jk
|
|
|
4
4
|
from pyscf import lib
|
|
5
5
|
from pyscf.lib import logger
|
|
6
6
|
from fcdft import wbl
|
|
7
|
+
import ctypes
|
|
8
|
+
import os
|
|
9
|
+
import fcdft
|
|
10
|
+
from pyscf.lib.numpy_helper import _dgemm
|
|
11
|
+
|
|
12
|
+
libdf = lib.load_library(os.path.join(fcdft.__path__[0], 'lib', 'libdf'))
|
|
7
13
|
|
|
8
14
|
def density_fit(mf, auxbasis=None, with_df=None, only_dfj=False):
|
|
9
15
|
from pyscf import df
|
|
@@ -128,13 +134,71 @@ def get_j(dfobj, dm, hermi=0, direct_scf_tol=1e-13):
|
|
|
128
134
|
logger.timer(dfobj, 'df-vj', *t0)
|
|
129
135
|
return numpy.asarray(vj).reshape(dm_shape)
|
|
130
136
|
|
|
137
|
+
# numpy.einsum replaced by custom dgemm for computational efficiency.
|
|
138
|
+
def get_jk(dfobj, dm, hermi=0, with_j=True, with_k=True, direct_scf_tol=1e-13):
|
|
139
|
+
assert (with_j or with_k)
|
|
140
|
+
if (not with_k and not dfobj.mol.incore_anyway and
|
|
141
|
+
# 3-center integral tensor is not initialized
|
|
142
|
+
dfobj._cderi is None):
|
|
143
|
+
return get_j(dfobj, dm, hermi, direct_scf_tol), None
|
|
144
|
+
|
|
145
|
+
t0 = t1 = (logger.process_clock(), logger.perf_counter())
|
|
146
|
+
log = logger.Logger(dfobj.stdout, dfobj.verbose)
|
|
147
|
+
|
|
148
|
+
dms = numpy.asarray(dm)
|
|
149
|
+
dm_shape = dms.shape
|
|
150
|
+
nao = dm_shape[-1]
|
|
151
|
+
dms = dms.reshape(-1,nao,nao)
|
|
152
|
+
nset = dms.shape[0]
|
|
153
|
+
vj = 0
|
|
154
|
+
vk = numpy.zeros_like(dms)
|
|
155
|
+
|
|
156
|
+
fdrv = libdf.nr_mapdm1
|
|
157
|
+
|
|
158
|
+
if numpy.iscomplexobj(dms):
|
|
159
|
+
if with_j:
|
|
160
|
+
vj = numpy.zeros_like(dms)
|
|
161
|
+
max_memory = dfobj.max_memory - lib.current_memory()[0]
|
|
162
|
+
blksize = max(4, int(min(dfobj.blockdim, max_memory*.22e6/8/nao**2)))
|
|
163
|
+
buf = numpy.empty((blksize,nao,nao))
|
|
164
|
+
for eri1 in dfobj.loop(blksize):
|
|
165
|
+
naux, nao_pair = eri1.shape
|
|
166
|
+
eri1 = lib.unpack_tril(eri1, out=buf)
|
|
167
|
+
if with_j:
|
|
168
|
+
tmp = numpy.tensordot(eri1, dms.real, axes=([1,2],[2,1]))
|
|
169
|
+
vj.real += numpy.tensordot(tmp.T, eri1, axes=([1],[0]))
|
|
170
|
+
tmp = numpy.tensordot(eri1, dms.imag, axes=([1,2],[2,1]))
|
|
171
|
+
vj.imag += numpy.tensordot(tmp.T, eri1, axes=([1],[0]))
|
|
172
|
+
buf2 = numpy.empty((naux,nao,nao), dtype=numpy.float64, order='C')
|
|
173
|
+
for k in range(nset):
|
|
174
|
+
dmsRe = numpy.asarray(dms[k].real, dtype=numpy.float64, order='C')
|
|
175
|
+
dmsIm = numpy.asarray(dms[k].imag, dtype=numpy.float64, order='C')
|
|
176
|
+
fdrv(buf2.ctypes.data_as(ctypes.c_void_p),
|
|
177
|
+
eri1.ctypes.data_as(ctypes.c_void_p),
|
|
178
|
+
dmsRe.ctypes.data_as(ctypes.c_void_p),
|
|
179
|
+
ctypes.c_int(nao), ctypes.c_int(naux))
|
|
180
|
+
vk[k].real += numpy.tensordot(buf2, eri1, axes=([0,2],[0,1]))
|
|
181
|
+
fdrv(buf2.ctypes.data_as(ctypes.c_void_p),
|
|
182
|
+
eri1.ctypes.data_as(ctypes.c_void_p),
|
|
183
|
+
dmsIm.ctypes.data_as(ctypes.c_void_p),
|
|
184
|
+
ctypes.c_int(nao), ctypes.c_int(naux))
|
|
185
|
+
vk[k].imag += numpy.tensordot(buf2, eri1, axes=([0,2],[0,1]))
|
|
186
|
+
t1 = log.timer_debug1('jk', *t1)
|
|
187
|
+
if with_j: vj = vj.reshape(dm_shape)
|
|
188
|
+
if with_k: vk = vk.reshape(dm_shape)
|
|
189
|
+
logger.timer(dfobj, 'df vj and vk', *t0)
|
|
190
|
+
return vj, vk
|
|
191
|
+
|
|
192
|
+
else:
|
|
193
|
+
return df_jk.get_jk(dfobj, dm, hermi, with_j, with_k, direct_scf_tol)
|
|
194
|
+
|
|
131
195
|
class _DFHF(df_jk._DFHF):
|
|
132
196
|
def get_jk(self, mol=None, dm=None, hermi=0, with_j=True, with_k=True, omega=None):
|
|
133
197
|
if dm is None: dm = self.make_rdm1()
|
|
134
198
|
if not with_k:
|
|
135
199
|
return get_j(self.with_df, dm, hermi, self.direct_scf_tol), None
|
|
136
200
|
else:
|
|
137
|
-
return
|
|
201
|
+
return get_jk(self.with_df, dm, hermi, with_j, with_k, self.direct_scf_tol)
|
|
138
202
|
|
|
139
203
|
def nuc_grad_method(self):
|
|
140
204
|
from fcdft.df.grad import rks, uks
|
|
@@ -152,4 +216,3 @@ class _DFHF(df_jk._DFHF):
|
|
|
152
216
|
|
|
153
217
|
def to_gpu(self):
|
|
154
218
|
raise NotImplementedError
|
|
155
|
-
|
|
@@ -15,7 +15,7 @@ LINEAR_DEP_THRESHOLD = LINEAR_DEP_THR
|
|
|
15
15
|
|
|
16
16
|
def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
17
17
|
decompose_j2c='CD', lindep=LINEAR_DEP_THRESHOLD):
|
|
18
|
-
"""Copied from pyscf.df.grad.rhf and
|
|
18
|
+
"""Copied from pyscf.df.grad.rhf and some parts modified to handle complex density matrices."""
|
|
19
19
|
assert (with_j or with_k)
|
|
20
20
|
if not with_k:
|
|
21
21
|
return get_j (mf_grad, mol=mol, dm=dm, hermi=hermi), None
|
|
@@ -57,7 +57,7 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
57
57
|
vk = numpy.zeros((nset,3,nao,nao), dtype=numpy.complex128)
|
|
58
58
|
get_int3c_ip1 = df_rhf_grad._int3c_wrapper(mol, auxmol, 'int3c2e_ip1', 's1')
|
|
59
59
|
max_memory = mf_grad.max_memory - lib.current_memory()[0]
|
|
60
|
-
blksize = int(min(max(max_memory * .5e6/8 / (nao**2*3), 20), naux,
|
|
60
|
+
blksize = int(min(max(max_memory * .5e6/8 / (nao**2*3), 20), naux, 80)) # 240 -> 80 for handling complex128
|
|
61
61
|
ao_ranges = df_rhf_grad.balance_partition(aux_loc, blksize)
|
|
62
62
|
fmmm = _ao2mo.libao2mo.AO2MOmmm_bra_nr_s1 # MO output index slower than AO output index; input AOs are asymmetric
|
|
63
63
|
fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv # comp and aux indices are slower
|
|
@@ -74,10 +74,11 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
74
74
|
vj[i,1] += numpy.dot (rhoj[i,p0:p1], int3c[1].reshape (p1-p0, -1)).reshape (nao, nao).T
|
|
75
75
|
vj[i,2] += numpy.dot (rhoj[i,p0:p1], int3c[2].reshape (p1-p0, -1)).reshape (nao, nao).T
|
|
76
76
|
t2 = logger.timer_debug1 (mf_grad, "df grad einsum rho_P (P|mn') rho_P", *t2)
|
|
77
|
+
tmp = numpy.empty ((3,p1-p0,nocc[i],nao), dtype=numpy.complex128)
|
|
77
78
|
tmpRe = numpy.empty ((3,p1-p0,nocc[i],nao), dtype=numpy.float64)
|
|
78
79
|
tmpIm = numpy.empty ((3,p1-p0,nocc[i],nao), dtype=numpy.float64)
|
|
79
80
|
orbolRe = numpy.asarray(orbol[i].real, order='F')
|
|
80
|
-
orbolIm = numpy.asarray(orbol[i].imag, order='F')
|
|
81
|
+
orbolIm = numpy.asarray(orbol[i].imag, order='F')
|
|
81
82
|
fdrv(ftrans, fmmm, # lib.einsum ('xpmn,mi->xpin', int3c, orbol[i])
|
|
82
83
|
tmpRe.ctypes.data_as(ctypes.c_void_p),
|
|
83
84
|
int3c.ctypes.data_as(ctypes.c_void_p),
|
|
@@ -85,6 +86,7 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
85
86
|
ctypes.c_int (3*(p1-p0)), ctypes.c_int (nao),
|
|
86
87
|
(ctypes.c_int*4)(0, nocc[i], 0, nao),
|
|
87
88
|
null, ctypes.c_int(0))
|
|
89
|
+
orbolRe = None
|
|
88
90
|
fdrv(ftrans, fmmm, # lib.einsum ('xpmn,mi->xpin', int3c, orbol[i])
|
|
89
91
|
tmpIm.ctypes.data_as(ctypes.c_void_p),
|
|
90
92
|
int3c.ctypes.data_as(ctypes.c_void_p),
|
|
@@ -92,10 +94,13 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
92
94
|
ctypes.c_int (3*(p1-p0)), ctypes.c_int (nao),
|
|
93
95
|
(ctypes.c_int*4)(0, nocc[i], 0, nao),
|
|
94
96
|
null, ctypes.c_int(0))
|
|
95
|
-
tmp = tmpRe + 1.0j * tmpIm
|
|
97
|
+
# tmp = tmpRe + 1.0j * tmpIm
|
|
98
|
+
orbolIm = None
|
|
99
|
+
tmp.real, tmp.imag = tmpRe, tmpIm
|
|
100
|
+
tmpRe = tmpIm = None
|
|
96
101
|
t2 = logger.timer_debug1 (mf_grad, "df grad einsum (P|mn') u_mi = dg_Pin", *t2)
|
|
97
102
|
rhok = get_rhok (i, p0, p1)
|
|
98
|
-
vk[i] +=
|
|
103
|
+
vk[i] += numpy.tensordot(tmp, rhok, axes=([1,2],[0,1]))
|
|
99
104
|
t2 = logger.timer_debug1 (mf_grad, "df grad einsum D_Pim dg_Pin = v_ij", *t2)
|
|
100
105
|
rhok = tmp = None
|
|
101
106
|
int3c = None
|
|
@@ -114,10 +119,12 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
114
119
|
# dPiu C_uj -> dPij. *Not* symmetric i<->j: "i" has an occupancy
|
|
115
120
|
# factor and "j" must not.
|
|
116
121
|
max_memory = mf_grad.max_memory - lib.current_memory()[0]
|
|
117
|
-
blksize = int(min(max(max_memory * .5e6/8 / (nao*max (nocc)), 20), naux))
|
|
122
|
+
# blksize = int(min(max(max_memory * .5e6/8 / (nao*max (nocc)), 20), naux))
|
|
123
|
+
# In principe, all occupation numbers are non-zero for open quantum systems.
|
|
124
|
+
blksize = int(min(max(max_memory * .5e6/8 / (nao*nao), 20), naux) / 3) # Divided by 3 for handling complex128
|
|
118
125
|
rhok_oo = []
|
|
119
126
|
for i, j in product (range (nset), repeat=2):
|
|
120
|
-
tmp = numpy.empty ((naux,nocc[i],nocc[j]), numpy.complex128)
|
|
127
|
+
tmp = numpy.empty ((naux,nocc[i],nocc[j]), dtype=numpy.complex128)
|
|
121
128
|
for p0, p1 in lib.prange(0, naux, blksize):
|
|
122
129
|
rhok = get_rhok (i, p0, p1).reshape ((p1-p0)*nocc[i], nao)
|
|
123
130
|
tmp[p0:p1] = lib.dot (rhok, orbol[j]).reshape (p1-p0, nocc[i], nocc[j])
|
|
@@ -147,8 +154,9 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
147
154
|
# Here, the sparse matrix int3c is transformed into the smaller MO
|
|
148
155
|
# basis. The latter approach is obviously more performant.
|
|
149
156
|
for i in range (nset):
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
buf = numpy.empty((3, p1-p0, nocc[i], nao), dtype=numpy.complex128)
|
|
158
|
+
bufRe = numpy.empty((3, p1-p0, nocc[i], nao), dtype=numpy.float64)
|
|
159
|
+
bufIm = numpy.empty((3, p1-p0, nocc[i], nao), dtype=numpy.float64)
|
|
152
160
|
orbolRe = numpy.asarray(orbol[i].real, order='F')
|
|
153
161
|
orbolIm = numpy.asarray(orbol[i].imag, order='F')
|
|
154
162
|
fdrv(ftrans, fmmm, # lib.einsum ('pmn,ni->pim', int3c, orbol[i])
|
|
@@ -165,14 +173,18 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
165
173
|
ctypes.c_int (3*(p1-p0)), ctypes.c_int (nao),
|
|
166
174
|
(ctypes.c_int*4)(0, nocc[i], 0, nao),
|
|
167
175
|
null, ctypes.c_int(0))
|
|
168
|
-
buf = bufRe
|
|
176
|
+
buf.real, buf.imag = bufRe, bufIm
|
|
169
177
|
for j in range (nset): # lib.einsum ('pim,mj->pij', buf, orbor[j])
|
|
170
178
|
int3c_ij = lib.dot (buf.reshape (-1, nao), orbor[j])
|
|
171
179
|
int3c_ij = int3c_ij.reshape (3, p1-p0, nocc[i], nocc[j])
|
|
172
180
|
rhok_oo_ij = rhok_oo[(i*nset)+j][p0:p1]
|
|
173
181
|
vkaux[i,j,:,p0:p1] += lib.einsum('xpij,pij->xp', int3c_ij,
|
|
174
182
|
rhok_oo_ij)
|
|
183
|
+
int3c = None
|
|
175
184
|
t2 = logger.timer_debug1 (mf_grad, "df grad vk aux (P'|mn) eval", *t2)
|
|
185
|
+
orbol = orbor = None
|
|
186
|
+
buf = bufRe = bufIm = orbolRe = orbolIm = None
|
|
187
|
+
dm_tril = None
|
|
176
188
|
int3c = tmp = None
|
|
177
189
|
t1 = logger.timer_debug1 (mf_grad, "df grad vj and vk aux (P'|mn) eval", *t1)
|
|
178
190
|
|
|
@@ -182,7 +194,9 @@ def get_jk(mf_grad, mol=None, dm=None, hermi=0, with_j=True, with_k=True,
|
|
|
182
194
|
for i, j in product (range (nset), repeat=2):
|
|
183
195
|
k = (i*nset) + j
|
|
184
196
|
l = (j*nset) + i
|
|
185
|
-
tmp =
|
|
197
|
+
tmp = numpy.zeros((naux,naux), dtype=numpy.complex128)
|
|
198
|
+
for p0, p1 in lib.prange(0, nao, blksize):
|
|
199
|
+
tmp += numpy.tensordot(rhok_oo[k][:,p0:p1,:], rhok_oo[l][:,:,p0:p1], axes=([1,2], [2,1]))
|
|
186
200
|
vkaux[i,j] -= lib.einsum('xpq,pq->xp', int2c_e1, tmp)
|
|
187
201
|
t1 = logger.timer_debug1 (mf_grad, "df grad vj and vk aux (P'|Q) eval", *t1)
|
|
188
202
|
|
|
@@ -229,7 +243,7 @@ def get_j(mf_grad, mol=None, dm=None, hermi=0):
|
|
|
229
243
|
|
|
230
244
|
aux_loc = auxmol.ao_loc
|
|
231
245
|
max_memory = mf_grad.max_memory - lib.current_memory()[0]
|
|
232
|
-
blksize = int(min(max(max_memory * .5e6/8 / (nao**2*3), 20), naux,
|
|
246
|
+
blksize = int(min(max(max_memory * .5e6/8 / (nao**2*3), 20), naux, 80)) # 240 -> 80 for handling complex128
|
|
233
247
|
ao_ranges = df_rhf_grad.balance_partition(aux_loc, blksize)
|
|
234
248
|
|
|
235
249
|
# (ij|P), (nao, nao, naux)
|
|
@@ -292,7 +306,7 @@ def _cho_solve_rhojk (mf_grad, mol, auxmol, orbol, orbor,
|
|
|
292
306
|
f_rhok = lib.H5TmpFile()
|
|
293
307
|
t1 = (logger.process_clock (), logger.perf_counter ())
|
|
294
308
|
max_memory = mf_grad.max_memory - lib.current_memory()[0]
|
|
295
|
-
blksize = max_memory * .5e6/8 / (naux*nao)
|
|
309
|
+
blksize = max_memory * .5e6/8 / (naux*nao) / 3 # Divided by 3 for handling complex128 safely (complex + buffer)
|
|
296
310
|
mol_ao_ranges = df_rhf_grad.balance_partition(ao_loc, blksize)
|
|
297
311
|
nsteps = len(mol_ao_ranges)
|
|
298
312
|
t2 = t1
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import numpy
|
|
2
|
+
from pyscf.dft import gen_grid
|
|
3
|
+
from pyscf.dft import radi
|
|
4
|
+
from pyscf.lib import logger
|
|
5
|
+
from fcdft.gto.mole import split_mol
|
|
6
|
+
import ipdb
|
|
7
|
+
|
|
8
|
+
# Grid for equilibrium DFT object.
|
|
9
|
+
|
|
10
|
+
def get_partition(mol, atom_slice, *args, **kwargs):
|
|
11
|
+
mol1, mol2 = split_mol(mol, atom_slice)
|
|
12
|
+
coords1, weights1 = gen_grid.get_partition(mol1, *args, **kwargs)
|
|
13
|
+
coords2, weights2 = gen_grid.get_partition(mol2, *args, **kwargs)
|
|
14
|
+
coords_all = [coords1, coords2]
|
|
15
|
+
weights_all = [weights1, weights2]
|
|
16
|
+
return coords_all, weights_all
|
|
17
|
+
|
|
18
|
+
class Grids(gen_grid.Grids):
|
|
19
|
+
_keys = {'atom_slice'}
|
|
20
|
+
|
|
21
|
+
def __init__(self, mol, atom_slice):
|
|
22
|
+
gen_grid.Grids.__init__(self, mol)
|
|
23
|
+
self.atom_slice = atom_slice
|
|
24
|
+
|
|
25
|
+
def build(self, mol=None, with_non0tab=False, sort_grids=True, **kwargs):
|
|
26
|
+
if mol is None: mol = self.mol
|
|
27
|
+
if self.verbose >= logger.WARN:
|
|
28
|
+
self.check_sanity()
|
|
29
|
+
atom_grids_tab = self.gen_atomic_grids(
|
|
30
|
+
mol, self.atom_grid, self.radi_method, self.level, self.prune, **kwargs)
|
|
31
|
+
self.coords, self.weights = self.get_partition(
|
|
32
|
+
mol, self.atom_slice, atom_grids_tab, self.radii_adjust, self.atomic_radii, self.becke_scheme)
|
|
33
|
+
mol1, mol2 = split_mol(mol, self.atom_slice)
|
|
34
|
+
mol = [mol1, mol2]
|
|
35
|
+
atm_idx1 = numpy.empty(self.coords[0].shape[0], dtype=numpy.int32)
|
|
36
|
+
atm_idx2 = numpy.empty(self.coords[1].shape[0], dtype=numpy.int32)
|
|
37
|
+
atm_idx = [atm_idx1, atm_idx2]
|
|
38
|
+
quad_weights1 = numpy.empty(self.coords[0].shape[0])
|
|
39
|
+
quad_weights2 = numpy.empty(self.coords[1].shape[0])
|
|
40
|
+
quadrature_weights = [quad_weights1, quad_weights2]
|
|
41
|
+
for i in range(2):
|
|
42
|
+
p0 = p1 = 0
|
|
43
|
+
for ia in range(mol[i].natm):
|
|
44
|
+
r, vol = atom_grids_tab[mol[i].atom_symbol(ia)]
|
|
45
|
+
p0, p1 = p1, p1 + vol.size
|
|
46
|
+
atm_idx[i][p0:p1] = ia
|
|
47
|
+
quadrature_weights[i][p0:p1] = vol
|
|
48
|
+
self.atm_idx = atm_idx
|
|
49
|
+
self.quadrature_weights = quadrature_weights
|
|
50
|
+
if sort_grids:
|
|
51
|
+
for i in range(2):
|
|
52
|
+
idx = gen_grid.arg_group_grids(mol[i], self.coords[i])
|
|
53
|
+
self.coords[i] = self.coords[i][idx]
|
|
54
|
+
self.weights[i] = self.weights[i][idx]
|
|
55
|
+
self.atm_idx[i] = self.atm_idx[i][idx]
|
|
56
|
+
self.quadrature_weights[i] = self.quadrature_weights[i][idx]
|
|
57
|
+
# ??
|
|
58
|
+
if self.alignment > 1:
|
|
59
|
+
padding = gen_grid._padding_size(self.size, self.alignment)
|
|
60
|
+
logger.debug(self, 'Padding %d grids', padding)
|
|
61
|
+
if padding > 0:
|
|
62
|
+
self.coords = numpy.vstack(
|
|
63
|
+
[self.coords, numpy.repeat([[1e-4]*3], padding, axis=0)])
|
|
64
|
+
self.weights = numpy.hstack([self.weights, numpy.zeros(padding)])
|
|
65
|
+
self.atm_idx = numpy.hstack([self.atm_idx, numpy.full(padding, -1, dtype=numpy.int32)])
|
|
66
|
+
self.quadrature_weights = numpy.hstack([self.quadrature_weights, numpy.zeros(padding)])
|
|
67
|
+
if with_non0tab:
|
|
68
|
+
non0tab = []
|
|
69
|
+
for i in range(2):
|
|
70
|
+
non0tab.append(self.make_mask(mol[i], self.coords[i]))
|
|
71
|
+
self.non0tab = non0tab
|
|
72
|
+
self.screen_index = self.non0tab
|
|
73
|
+
else:
|
|
74
|
+
self.screen_index = self.non0tab = None
|
|
75
|
+
logger.info(self, 'tot grids = %d', len(self.weights[0]) + len(self.weights[1]))
|
|
76
|
+
return self
|
|
77
|
+
|
|
78
|
+
def kernel(self, **kwargs):
|
|
79
|
+
self.dump_flags()
|
|
80
|
+
return self.build(**kwargs)
|
|
81
|
+
|
|
82
|
+
def get_partition(self, mol, atom_slice, atom_grids_tab=None,
|
|
83
|
+
radii_adjust=None, atomic_radii=radi.BRAGG_RADII,
|
|
84
|
+
becke_scheme=gen_grid.original_becke, concat=True):
|
|
85
|
+
if atom_grids_tab is None:
|
|
86
|
+
atom_grids_tab = self.gen_atomic_grids(mol)
|
|
87
|
+
return get_partition(mol, atom_slice, atom_grids_tab, radii_adjust, atomic_radii,
|
|
88
|
+
becke_scheme, concat=concat)
|
|
@@ -42,10 +42,10 @@ def grad_elec(mf_grad, mo_energy=None, mo_coeff=None, mo_occ=None, atmlst=None):
|
|
|
42
42
|
for k, ia in enumerate(atmlst):
|
|
43
43
|
p0, p1 = aoslices [ia,2:]
|
|
44
44
|
h1ao = hcore_deriv(ia)
|
|
45
|
-
de[k] += numpy.
|
|
45
|
+
de[k] += numpy.tensordot(h1ao, dm0, axes=([1,2], [0,1]))
|
|
46
46
|
# nabla was applied on bra in vhf, *2 for the contributions of nabla|ket>
|
|
47
|
-
de[k] += numpy.
|
|
48
|
-
de[k] -= numpy.
|
|
47
|
+
de[k] += numpy.tensordot(vhf[:,p0:p1], dm0[p0:p1], axes=([1,2], [0,1])) * 2
|
|
48
|
+
de[k] -= numpy.tensordot(s1[:,p0:p1], dme0[p0:p1], axes=([1,2], [0,1])) * 2
|
|
49
49
|
|
|
50
50
|
de[k] += mf_grad.extra_force(ia, locals())
|
|
51
51
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from pyscf.gto.mole import Mole
|
|
2
|
+
from pyscf.lib import logger
|
|
3
|
+
|
|
4
|
+
# def split_env(mol, atm, bas, env, atom_id):
|
|
5
|
+
# symbols = [mol.atom_symbol(i) for i in range(mol.natm)]
|
|
6
|
+
# sym1 = symbols[:atom_id]
|
|
7
|
+
# from pyscf.gto.mole import make_bas_env
|
|
8
|
+
# len_env = 0
|
|
9
|
+
# for symb, basis_add in mol._basis.items():
|
|
10
|
+
# if symb in sym1:
|
|
11
|
+
# _, env0 = make_bas_env(basis_add, 0, 0)
|
|
12
|
+
# len_env += len(env0)
|
|
13
|
+
|
|
14
|
+
# env1, env2 = [numpy.zeros(PTR_ENV_START)], [numpy.zeros(PTR_ENV_START)]
|
|
15
|
+
# env1.append(env[PTR_ENV_START:PTR_ENV_START+4*atom_id])
|
|
16
|
+
# env2.append(env[PTR_ENV_START+4*atom_id:PTR_ENV_START+4*len(atm)])
|
|
17
|
+
# env1, env2 = env[:len_env], env[len_env:]
|
|
18
|
+
# idx = numpy.where(bas[:,0] == atom_id)[0][0]
|
|
19
|
+
# bas1, bas2 = bas[:idx].copy(), bas[idx:].copy()
|
|
20
|
+
# off = len(env1)
|
|
21
|
+
# natm_off = atom_id
|
|
22
|
+
# atm1, atm2 = atm[:atom_id].copy(), atm[atom_id:].copy()
|
|
23
|
+
# atm2[:,PTR_COORD] -= off
|
|
24
|
+
# atm2[:,PTR_ZETA ] -= off
|
|
25
|
+
# bas2[:,ATOM_OF ] -= natm_off
|
|
26
|
+
# bas2[:,PTR_EXP ] -= off
|
|
27
|
+
# bas2[:,PTR_COEFF] -= off
|
|
28
|
+
# return atm1, bas1, env1, atm2, bas2, env2
|
|
29
|
+
|
|
30
|
+
def conc_mol(mol1, mol2):
|
|
31
|
+
from pyscf.gto import mole
|
|
32
|
+
mol = mole.conc_mol(mol1, mol2)
|
|
33
|
+
if mol1.basis == mol2.basis:
|
|
34
|
+
mol.basis = mol1.basis
|
|
35
|
+
return mol
|
|
36
|
+
|
|
37
|
+
def split_mol(mol, atom_id):
|
|
38
|
+
'''Split the molecule into two Mole objects.
|
|
39
|
+
Reverse of conc_mol in pyscf.gto.mole
|
|
40
|
+
'''
|
|
41
|
+
if not mol._built:
|
|
42
|
+
logger.warn(mol, 'Warning: object %s not initialized. Initializing %s',
|
|
43
|
+
mol, mol)
|
|
44
|
+
mol.build()
|
|
45
|
+
|
|
46
|
+
# TODO: mol.stdout for logger
|
|
47
|
+
mol1, mol2 = Mole(), Mole()
|
|
48
|
+
mol1.basis = mol2.basis = mol.basis
|
|
49
|
+
mol1.verbose = mol2.verbose = mol.verbose
|
|
50
|
+
mol1.stdout = mol2.stdout = mol.stdout
|
|
51
|
+
mol1.output = mol2.output = mol.output
|
|
52
|
+
mol1.max_memory = mol2.max_memory = mol.max_memory
|
|
53
|
+
mol1.spin = mol2.spin = 0
|
|
54
|
+
mol1.symmetry = mol2.symmetry = False
|
|
55
|
+
mol1.symmetry_subgroup = mol2.symmetry_subgroup = None
|
|
56
|
+
mol1.cart = mol2.cart = mol.cart
|
|
57
|
+
mol1._atom = mol._atom[:atom_id]
|
|
58
|
+
mol2._atom = mol._atom[atom_id:]
|
|
59
|
+
mol1.unit = mol2.unit = 'Bohr'
|
|
60
|
+
mol1.build(), mol2.build()
|
|
61
|
+
|
|
62
|
+
return mol1, mol2
|
|
63
|
+
|
|
64
|
+
if __name__=='__main__':
|
|
65
|
+
from pyscf import gto
|
|
66
|
+
mol1 = gto.M(
|
|
67
|
+
atom='''
|
|
68
|
+
C -1.1367537947 0.1104289172 2.4844663896
|
|
69
|
+
C -1.1385831318 0.1723328088 3.8772156394
|
|
70
|
+
C 0.0819843127 0.0788096973 1.7730802291
|
|
71
|
+
H -2.0846565855 0.1966185690 4.4236084687
|
|
72
|
+
C 0.0806058727 0.2041086872 4.5921211233
|
|
73
|
+
C 1.2993389981 0.1104289172 2.4844663896
|
|
74
|
+
H 2.2526138470 0.0865980845 1.9483127672
|
|
75
|
+
C 1.2994126658 0.1723829840 3.8783367991
|
|
76
|
+
H 2.2453411518 0.1966879024 4.4251589385
|
|
77
|
+
H -2.0869454458 0.0863720324 1.9432143952
|
|
78
|
+
C 0.0810980584 0.2676328718 6.0213144069
|
|
79
|
+
N 0.0819851974 0.3199013851 7.1972568519
|
|
80
|
+
S 0.0000000000 0.0000000000 0.0000000000
|
|
81
|
+
H 1.3390319419 -0.0095801980 -0.2157234144''',
|
|
82
|
+
charge=0, basis='6-31g**', verbose=5)
|
|
83
|
+
mol2 = gto.M(
|
|
84
|
+
atom='''
|
|
85
|
+
C -0.8476079365 0.0026700202 -3.5281035617
|
|
86
|
+
C -2.0218283577 -0.2604683627 -2.8073958219
|
|
87
|
+
C 0.3353012600 0.2642432684 -2.8231212050
|
|
88
|
+
H -2.9520951875 -0.4549635668 -3.3338745954
|
|
89
|
+
H 1.2611570861 0.4600128780 -3.3568350109
|
|
90
|
+
C -2.0073245682 -0.2604462093 -1.4139657047
|
|
91
|
+
C 0.3383704802 0.2619859179 -1.4285927349
|
|
92
|
+
H -2.9349818456 -0.4420746761 -0.8791308006
|
|
93
|
+
H 1.2732326220 0.4430128273 -0.9060391242
|
|
94
|
+
C -0.8293545128 0.0002996322 -0.6916543989
|
|
95
|
+
C -0.8192397451 -0.0006201775 0.7937732451
|
|
96
|
+
C -1.5616839183 -0.9482725602 1.5218647171
|
|
97
|
+
C -0.0671411632 0.9462610490 1.5129186979
|
|
98
|
+
C -1.5541603792 -0.9481485004 2.9180008413
|
|
99
|
+
C -0.0558307025 0.9446630867 2.9090260355
|
|
100
|
+
C -0.8001707945 -0.0022152441 3.6187748549
|
|
101
|
+
H -2.1295491966 -1.7060626237 0.9896596517
|
|
102
|
+
H 0.4930453218 1.7050509252 0.9740007250
|
|
103
|
+
H -2.1296311282 -1.6947234290 3.4583587491
|
|
104
|
+
H 0.5267024257 1.6907508988 3.4424644381
|
|
105
|
+
H -0.7929373074 -0.0027907562 4.7049223527
|
|
106
|
+
S -0.9353266992 -0.0162143726 -5.3112847893
|
|
107
|
+
H 0.3533301599 0.3018611373 -5.5386460312''',
|
|
108
|
+
charge=0, basis='6-31g**', verbose=5)
|
|
109
|
+
mol = gto.conc_mol(mol1, mol2)
|
|
110
|
+
_mol1, _mol2 = split_mol(mol, 14)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#include <stdlib.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <stdint.h>
|
|
4
|
+
#include <omp.h>
|
|
5
|
+
#include "cblas.h"
|
|
6
|
+
|
|
7
|
+
void nr_mapdm1(double *buf, double *eri, double *dms, int nao, int naux) {
|
|
8
|
+
// vk shape: (nao, nao), (155,155)
|
|
9
|
+
// eri shape: (naux, nao, nao) (240,155,155)
|
|
10
|
+
// dms shape: (nao, nao) (155,155)
|
|
11
|
+
// buf shape: (naux, nao, nao) (240,155,155)
|
|
12
|
+
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, naux*nao, nao, nao, 1.0, eri, nao, dms, nao, 0.0, buf, nao);
|
|
13
|
+
}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
#include <omp.h>
|
|
5
5
|
#include <stdio.h>
|
|
6
6
|
|
|
7
|
+
double const TWO_PI = 2.0 * M_PI;
|
|
8
|
+
|
|
7
9
|
void roots_legendre(int n, double *abscissas, double *weights){
|
|
8
10
|
double z, z1, pp, p1, p2, p3;
|
|
9
11
|
int m = (n + 1) / 2;
|
|
@@ -34,26 +36,64 @@ void roots_legendre(int n, double *abscissas, double *weights){
|
|
|
34
36
|
|
|
35
37
|
double occ_drv(double sampling, double moe_energy, double fermi, double broad, double smear) {
|
|
36
38
|
double dist = 1 / (exp((sampling - fermi)/smear) + 1);
|
|
37
|
-
|
|
39
|
+
double a = sampling - moe_energy;
|
|
40
|
+
double b = broad / 2.0;
|
|
41
|
+
return dist * broad / (a*a + b*b) / TWO_PI;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
double occ_grad_drv(double sampling, double moe_energy, double fermi, double broad, double smear) {
|
|
41
45
|
double dist = 1 / (exp((sampling - fermi)/smear) + 1);
|
|
42
|
-
|
|
46
|
+
double a = sampling - moe_energy;
|
|
47
|
+
double b = broad / 2.0;
|
|
48
|
+
return dist * (1 - dist) * broad / (a*a + b*b) / TWO_PI / smear;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
void fermi_level_drv(double *moe_energy, double *abscissas, double *weights, double fermi, double broad, double smear, double window, int pts, int nbas, double *mo_occ, double *mo_grad) {
|
|
46
52
|
int i, n;
|
|
47
53
|
double sampling;
|
|
48
54
|
double _mo_grad = 0.0;
|
|
55
|
+
double *window_weights = (double *)malloc(sizeof(double) * pts);
|
|
56
|
+
|
|
57
|
+
#pragma omp parallel for private(n)
|
|
58
|
+
for (n = 0; n < pts; n++) {
|
|
59
|
+
window_weights[n] = window * weights[n];
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
#pragma omp parallel for private(n, sampling) reduction(+:_mo_grad)
|
|
50
63
|
for (i = 0; i < nbas; i++) {
|
|
51
64
|
mo_occ[i] = 0;
|
|
52
65
|
for (n = 0; n < pts; n++) {
|
|
53
66
|
sampling = abscissas[n] * window + moe_energy[i];
|
|
54
|
-
mo_occ[i] +=
|
|
55
|
-
_mo_grad +=
|
|
67
|
+
mo_occ[i] += window_weights[n] * occ_drv(sampling, moe_energy[i], fermi, broad, smear);
|
|
68
|
+
_mo_grad += window_weights[n] * occ_grad_drv(sampling, moe_energy[i], fermi, broad, smear);
|
|
56
69
|
}
|
|
57
70
|
}
|
|
58
71
|
*mo_grad = _mo_grad;
|
|
72
|
+
free(window_weights);
|
|
59
73
|
}
|
|
74
|
+
|
|
75
|
+
void occupation_drv(double *moe_energy, double *abscissas, double *weights, double fermi, double broad, double smear, double window, int pts, int nbas, double *mo_occ) {
|
|
76
|
+
int i, n;
|
|
77
|
+
double sampling;
|
|
78
|
+
#pragma omp parallel for private(n, sampling)
|
|
79
|
+
for (i = 0; i < nbas; i++) {
|
|
80
|
+
mo_occ[i] = 0;
|
|
81
|
+
for (n = 0; n < pts; n++) {
|
|
82
|
+
sampling = abscissas[n] * window + moe_energy[i];
|
|
83
|
+
mo_occ[i] += window * weights[n] * occ_drv(sampling, moe_energy[i], fermi, broad, smear);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
void occupation_grad_drv(double *moe_energy, double *abscissas, double *weights, double fermi, double broad, double smear, double window, int pts, int nbas, double *occ_grad) {
|
|
89
|
+
int i, n;
|
|
90
|
+
double sampling;
|
|
91
|
+
#pragma omp parallel for private(n, sampling)
|
|
92
|
+
for (i = 0; i < nbas; i++) {
|
|
93
|
+
occ_grad[i] = 0;
|
|
94
|
+
for (n = 0; n < pts; n++) {
|
|
95
|
+
sampling = abscissas[n] * window + moe_energy[i];
|
|
96
|
+
occ_grad[i] += window * weights[n] * occ_grad_drv(sampling, moe_energy[i], fermi, broad, smear);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|