From 86d449d1ac5469619bc5b65a5701ee5226ff6a0b Mon Sep 17 00:00:00 2001 From: "xiaojie.wu" Date: Sat, 13 Jan 2024 01:32:13 +0800 Subject: [PATCH] optimized initialization --- examples/18-to_gpu0.py | 35 -------------------------- examples/19-pcm_optimize.py | 41 ------------------------------- examples/dft_driver.py | 4 +-- gpu4pyscf/df/df.py | 19 +++++++------- gpu4pyscf/df/df_jk.py | 1 - gpu4pyscf/dft/numint.py | 40 +++++++++++++++++------------- gpu4pyscf/grad/rks.py | 16 +++++++----- gpu4pyscf/hessian/rks.py | 8 ++++-- gpu4pyscf/lib/gdft/nr_eval_gto.cu | 12 +++++---- gpu4pyscf/solvent/grad/pcm.py | 17 ++++++++++--- gpu4pyscf/solvent/hessian/pcm.py | 5 ++-- gpu4pyscf/solvent/pcm.py | 2 +- 12 files changed, 76 insertions(+), 124 deletions(-) delete mode 100644 examples/18-to_gpu0.py delete mode 100644 examples/19-pcm_optimize.py diff --git a/examples/18-to_gpu0.py b/examples/18-to_gpu0.py deleted file mode 100644 index c8ab66eb..00000000 --- a/examples/18-to_gpu0.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2023 The GPU4PySCF Authors. All Rights Reserved. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import pyscf -from pyscf import lib -from pyscf.dft import rks -lib.num_threads(8) - -atom = ''' -O 0.0000000000 -0.0000000000 0.1174000000 -H -0.7570000000 -0.0000000000 -0.4696000000 -H 0.7570000000 0.0000000000 -0.4696000000 -''' - -mol = pyscf.M(atom=atom, basis='def2-tzvpp') - -mol.verbose = 4 -mf = rks.RKS(mol, xc='B3LYP').density_fit() -mf_GPU = mf.to_gpu() - -# Compute Energy -e_dft = mf_GPU.kernel() -print(f"total energy = {e_dft}") diff --git a/examples/19-pcm_optimize.py b/examples/19-pcm_optimize.py deleted file mode 100644 index 75ba681b..00000000 --- a/examples/19-pcm_optimize.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2023 The GPU4PySCF Authors. All Rights Reserved. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import numpy as np -import pyscf -from pyscf import lib, df -from gpu4pyscf.dft import rks -from pyscf.geomopt.geometric_solver import optimize -lib.num_threads(8) - -atom =''' -O 0.0000000000 -0.0000000000 0.1174000000 -H -0.7570000000 -0.0000000000 -0.4696000000 -H 0.7570000000 0.0000000000 -0.4696000000 -''' - -mol = pyscf.M(atom=atom, basis='def2-tzvpp', verbose=0) - -mf = rks.RKS(mol, xc='HYB_GGA_XC_B3LYP').density_fit() -mf = mf.PCM() -mf.verbose = 3 -mf.grids.atom_grid = (99,590) -mf.small_rho_cutoff = 1e-10 -mf.with_solvent.lebedev_order = 29 # 302 Lebedev grids -mf.with_solvent.method = 'C-PCM' -mf.with_solvent.eps = 78.3553 - -mol_eq = optimize(mf, maxsteps=20) - diff --git a/examples/dft_driver.py b/examples/dft_driver.py index 9d17560c..d7479292 100644 --- a/examples/dft_driver.py +++ b/examples/dft_driver.py @@ -35,10 +35,10 @@ basis=bas, max_memory=32000) # set verbose >= 6 for debugging timer -mol.verbose = 7 +mol.verbose = 4 mf_df = rks.RKS(mol, xc=args.xc).density_fit(auxbasis=args.auxbasis) -mf_df.verbose = 7 +mf_df.verbose = 4 if args.solvent: mf_df = mf_df.PCM() diff --git a/gpu4pyscf/df/df.py b/gpu4pyscf/df/df.py index e6cd9d21..054789f4 100644 --- a/gpu4pyscf/df/df.py +++ b/gpu4pyscf/df/df.py @@ -135,7 +135,7 @@ def loop(self, blksize=None, unpack=True): rows = self.intopt.cderi_row cols = self.intopt.cderi_col buf_prefetch = None - + buf_cderi = cupy.zeros([blksize,nao,nao]) data_stream = cupy.cuda.stream.Stream(non_blocking=True) compute_stream = cupy.cuda.get_current_stream() #compute_stream = cupy.cuda.stream.Stream() @@ -153,14 +153,15 @@ def loop(self, blksize=None, unpack=True): buf_prefetch.set(cderi_sparse[p1:p2,:]) stop_event = data_stream.record() if unpack: - buf2 = cupy.zeros([p1-p0,nao,nao]) - buf2[:p1-p0,rows,cols] = buf - buf2[:p1-p0,cols,rows] = buf + buf_cderi[:p1-p0,rows,cols] = buf + buf_cderi[:p1-p0,cols,rows] = buf + buf2 = buf_cderi[:p1-p0] else: buf2 = None yield buf2, buf.T compute_stream.wait_event(stop_event) - cupy.cuda.Device().synchronize() + if isinstance(cderi_sparse, np.ndarray): + cupy.cuda.Device().synchronize() if buf_prefetch is not None: buf = buf_prefetch @@ -205,8 +206,8 @@ def cholesky_eri_gpu(intopt, mol, auxmol, cd_low, omega=None, sr_only=False): cderi = np.ndarray([naux, npair], dtype=np.float64, order='C', buffer=mem) except Exception: raise RuntimeError('Out of CPU memory') - - data_stream = cupy.cuda.stream.Stream(non_blocking=False) + if(not use_gpu_memory): + data_stream = cupy.cuda.stream.Stream(non_blocking=False) count = 0 nq = len(intopt.log_qs) for cp_ij_id, _ in enumerate(intopt.log_qs): @@ -265,8 +266,8 @@ def cholesky_eri_gpu(intopt, mol, auxmol, cd_low, omega=None, sr_only=False): for i in range(naux): cderi_block[i].get(out=cderi[i,ij0:ij1]) t1 = log.timer_debug1(f'solve {cp_ij_id} / {nq}', *t1) - - cupy.cuda.Device().synchronize() + if not use_gpu_memory: + cupy.cuda.Device().synchronize() return cderi diff --git a/gpu4pyscf/df/df_jk.py b/gpu4pyscf/df/df_jk.py index fe3c748e..72c01e1d 100644 --- a/gpu4pyscf/df/df_jk.py +++ b/gpu4pyscf/df/df_jk.py @@ -63,7 +63,6 @@ def build_df(): rks.initialize_grids(mf, mf.mol, dm0) ni.build(mf.mol, mf.grids.coords) mf._numint.xcfuns = numint._init_xcfuns(mf.xc, dm0.ndim==3) - dm0 = cupy.asarray(dm0) return def _density_fit(mf, auxbasis=None, with_df=None, only_dfj=False): diff --git a/gpu4pyscf/dft/numint.py b/gpu4pyscf/dft/numint.py index 0ca4cd75..9a1d9512 100644 --- a/gpu4pyscf/dft/numint.py +++ b/gpu4pyscf/dft/numint.py @@ -36,7 +36,7 @@ MIN_BLK_SIZE = getattr(__config__, 'min_grid_blksize', 64*64) ALIGNED = getattr(__config__, 'grid_aligned', 16*16) AO_ALIGNMENT = getattr(__config__, 'ao_aligned', 16) -AO_THRESHOLD = 1e-12 +AO_THRESHOLD = 1e-10 # Should we release the cupy cache? FREE_CUPY_CACHE = False @@ -199,14 +199,15 @@ def eval_rho2(mol, ao, mo_coeff, mo_occ, non0tab=None, xctype='LDA', rho = _contract_rho(c0, c0) elif xctype in ('GGA', 'NLC'): rho = cupy.empty((4,ngrids)) - c0 = _dot_ao_dm(mol, ao[0], cpos, non0tab, shls_slice, ao_loc) + #c0 = _dot_ao_dm(mol, ao[0], cpos, non0tab, shls_slice, ao_loc) + c0 = contract('nig,io->nog', ao, cpos) #:rho[0] = numpy.einsum('pi,pi->p', c0, c0) - _contract_rho(c0, c0, rho=rho[0]) + _contract_rho(c0[0], c0[0], rho=rho[0]) for i in range(1, 4): - c1 = _dot_ao_dm(mol, ao[i], cpos, non0tab, shls_slice, ao_loc) + #c1 = _dot_ao_dm(mol, ao[i], cpos, non0tab, shls_slice, ao_loc) #:rho[i] = numpy.einsum('pi,pi->p', c0, c1) * 2 # *2 for +c.c. - _contract_rho(c0, c1, rho=rho[i]) - rho[i] *= 2 + _contract_rho(c0[0], c0[i], rho=rho[i]) + rho[1:] *= 2 else: # meta-GGA if with_lapl: # rho[4] = \nabla^2 rho, rho[5] = 1/2 |nabla f|^2 @@ -215,17 +216,18 @@ def eval_rho2(mol, ao, mo_coeff, mo_occ, non0tab=None, xctype='LDA', else: rho = cupy.empty((5,ngrids)) tau_idx = 4 - c0 = _dot_ao_dm(mol, ao[0], cpos, non0tab, shls_slice, ao_loc) + #c0 = _dot_ao_dm(mol, ao[0], cpos, non0tab, shls_slice, ao_loc) + c0 = contract('nig,io->nog', ao, cpos) #:rho[0] = numpy.einsum('pi,pi->p', c0, c0) - _contract_rho(c0, c0, rho=rho[0]) + _contract_rho(c0[0], c0[0], rho=rho[0]) rho[tau_idx] = 0 for i in range(1, 4): - c1 = _dot_ao_dm(mol, ao[i], cpos, non0tab, shls_slice, ao_loc) + #c1 = _dot_ao_dm(mol, ao[i], cpos, non0tab, shls_slice, ao_loc) #:rho[i] = numpy.einsum('pi,pi->p', c0, c1) * 2 # *2 for +c.c. #:rho[5] += numpy.einsum('pi,pi->p', c1, c1) - rho[i] = _contract_rho(c0, c1) * 2 - rho[tau_idx] += _contract_rho(c1, c1) + rho[i] = _contract_rho(c0[0], c0[i]) + rho[tau_idx] += _contract_rho(c0[i], c0[i]) if with_lapl: if ao.shape[0] > 4: @@ -233,11 +235,12 @@ def eval_rho2(mol, ao, mo_coeff, mo_occ, non0tab=None, xctype='LDA', ao2 = ao[XX] + ao[YY] + ao[ZZ] c1 = _dot_ao_dm(mol, ao2, cpos, non0tab, shls_slice, ao_loc) #:rho[4] = numpy.einsum('pi,pi->p', c0, c1) - rho[4] = _contract_rho(c0, c1) + rho[4] = _contract_rho(c0[0], c1) rho[4] += rho[5] rho[4] *= 2 else: rho[4] = 0 + rho[1:4] *= 2 rho[tau_idx] *= .5 return rho @@ -321,11 +324,14 @@ def eval_rho4(mol, ao, c0, mo1, non0tab=None, xctype='LDA', rho[i] = _contract_rho(c0, c_0[i]) rho *= 2.0 elif xctype in ('GGA', 'NLC'): + log = logger.new_logger(mol, mol.verbose) + t0 = log.init_timer() c_0 = contract('nig,aio->anog', ao, cpos1) + t0 = log.timer_debug1('ao * cpos', *t0) rho = cupy.empty([na, 4, ngrids]) for i in range(na): _contract_rho_gga(c0, c_0[i], rho=rho[i]) - + t0 = log.timer_debug1('contract rho', *t0) else: # meta-GGA if with_lapl: raise NotImplementedError("mGGA with lapl not implemented") @@ -454,7 +460,7 @@ def nr_rks(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, nset = len(dms) if mo_coeff is not None: - mo_coeff = coeff @ mo_coeff + mo_coeff = mo_coeff[opt.ao_idx] nelec = cupy.zeros(nset) excsum = cupy.zeros(nset) @@ -494,7 +500,7 @@ def nr_rks(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, mo_coeff_mask = mo_coeff[idx,:] rho_tot[i,:,p0:p1] = eval_rho2(mol, ao_mask, mo_coeff_mask, mo_occ, None, xctype) p0 = p1 - t1 = log.timer_debug2('eval rho', *t1) + t1 = log.timer_debug2('eval rho slice', *t1) t0 = log.timer_debug1('eval rho', *t0) wv = [] @@ -755,7 +761,7 @@ def nr_rks_fxc(ni, mol, grids, xc_code, dm0=None, dms=None, relativity=0, hermi= c0 = contract('nig,io->nog', ao, occ_coeff_mask) else: # mgga c0 = contract('nig,io->nog', ao, occ_coeff_mask) - + t1 = log.timer_debug2(f'eval occ_coeff, with mocc: {with_mocc}', *t1) if with_mocc: rho1 = eval_rho4(opt.mol, ao, c0, mo1[:,mask], xctype=xctype, with_lapl=False) else: @@ -1242,7 +1248,7 @@ def _block_loop(ni, mol, grids, nao=None, deriv=0, max_memory=2000, for ip0, ip1 in lib.prange(0, ngrids, blksize): coords = grids.coords[ip0:ip1] weight = grids.weights[ip0:ip1] - + t1 = log.init_timer() # cache ao indices if (block_id, blksize, ngrids) not in ni.non0ao_idx: stream = cupy.cuda.get_current_stream() diff --git a/gpu4pyscf/grad/rks.py b/gpu4pyscf/grad/rks.py index be6732d6..c3244c9a 100644 --- a/gpu4pyscf/grad/rks.py +++ b/gpu4pyscf/grad/rks.py @@ -233,8 +233,10 @@ def get_nlc_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1, vmat_tmp = _gga_grad_sum_(ao_mask, wv) add_sparse(vmat, vmat_tmp, mask) - vmat = contract('npq,qj->npj', vmat, coeff) - vmat = contract('pi,npj->nij', coeff, vmat) + #vmat = contract('npq,qj->npj', vmat, coeff) + #vmat = contract('pi,npj->nij', coeff, vmat) + rev_ao_idx = opt.rev_ao_idx + vmat = take_last2d(vmat, rev_ao_idx) exc = None # - sign because nabla_X = -nabla_x return exc, -vmat @@ -278,10 +280,12 @@ def _make_dR_dao_w(ao, wv): def _d1_dot_(ao1, ao2, out=None): if out is None: - vmat0 = cupy.dot(ao1[0], ao2) - vmat1 = cupy.dot(ao1[1], ao2) - vmat2 = cupy.dot(ao1[2], ao2) - return cupy.stack([vmat0,vmat1,vmat2]) + out = cupy.empty([3, ao1[0].shape[0], ao2.shape[1]]) + out[0] = cupy.dot(ao1[0], ao2) + out[1] = cupy.dot(ao1[1], ao2) + out[2] = cupy.dot(ao1[2], ao2) + return out + #return cupy.stack([vmat0,vmat1,vmat2]) else: cupy.dot(ao1[0], ao2, out=out[0]) cupy.dot(ao1[1], ao2, out=out[1]) diff --git a/gpu4pyscf/hessian/rks.py b/gpu4pyscf/hessian/rks.py index 3e36825c..14e8a100 100644 --- a/gpu4pyscf/hessian/rks.py +++ b/gpu4pyscf/hessian/rks.py @@ -354,12 +354,13 @@ def _d1d2_dot_(vmat, mol, ao1, ao2, mask, ao_loc, dR1_on_bra=True): for d2 in range(3): vmat[d1,d2] += numint._dot_ao_ao(mol, ao1[d1], ao2[d2], mask, shls_slice, ao_loc) + #vmat += contract('xig,yjg->xyij', ao1, ao2) else: # (d/dR2 bra) * (d/dR1 ket) for d1 in range(3): for d2 in range(3): vmat[d1,d2] += numint._dot_ao_ao(mol, ao1[d2], ao2[d1], mask, shls_slice, ao_loc) - + #vmat += contract('yig,xjg->xyij', ao1, ao2) def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): mol = hessobj.mol mf = hessobj.base @@ -461,7 +462,10 @@ def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory): for i in range(3): aow = rks_grad._make_dR_dao_w(ao_mask, wv[i]) rks_grad._d1_dot_(aow, ao_mask[0].T, out=vmat_tmp[i]) - aow = [numint._scale_ao(ao_mask[:4], wv[i,:4]) for i in range(3)] + ng = len(weight) + aow = cupy.empty([3,nao_non0,ng]) + for i in range(3): + aow[i] = numint._scale_ao(ao_mask[:4], wv[i,:4]) _d1d2_dot_(vmat_tmp, mol, ao_mask[1:4], aow, mask, ao_loc, False) #vmat_tmp = contract('pi,xypq->xyiq', coeff[mask], vmat_tmp) #vmat_tmp = contract('qj,xyiq->xyij', coeff[mask], vmat_tmp) diff --git a/gpu4pyscf/lib/gdft/nr_eval_gto.cu b/gpu4pyscf/lib/gdft/nr_eval_gto.cu index 1e2689d7..2f2139a3 100644 --- a/gpu4pyscf/lib/gdft/nr_eval_gto.cu +++ b/gpu4pyscf/lib/gdft/nr_eval_gto.cu @@ -28,7 +28,7 @@ #include "nr_eval_gto.cuh" #include "contract_rho.cuh" -#define NG_PER_BLOCK 128 +#define NG_PER_BLOCK 256 #define LMAX 8 #define GTO_MAX_CART 15 @@ -354,9 +354,10 @@ static void _cart_kernel_deriv1(BasOffsets offsets) double ce_2a = 0; for (int ip = 0; ip < offsets.nprim; ++ip) { double c = coeffs[ip]; - double e = exp(-exps[ip] * rr); + double exp_ip = exps[ip]; + double e = exp(-exp_ip * rr); ce += c * e; - ce_2a += c * e * exps[ip]; + ce_2a += c * e * exp_ip; } ce *= offsets.fac; ce_2a *= -2 * offsets.fac; @@ -1025,9 +1026,10 @@ static void _sph_kernel_deriv1(BasOffsets offsets) double ce_2a = 0; for (int ip = 0; ip < offsets.nprim; ++ip) { double c = coeffs[ip]; - double e = exp(-exps[ip] * rr); + double exp_ip = exps[ip]; + double e = exp(-exp_ip * rr); ce += c * e; - ce_2a += c * e * exps[ip]; + ce_2a += c * e * exp_ip; } ce *= offsets.fac; ce_2a *= -2 * offsets.fac; diff --git a/gpu4pyscf/solvent/grad/pcm.py b/gpu4pyscf/solvent/grad/pcm.py index be469508..cf6cda8f 100644 --- a/gpu4pyscf/solvent/grad/pcm.py +++ b/gpu4pyscf/solvent/grad/pcm.py @@ -114,6 +114,7 @@ def get_dD_dS(surface, dF, with_S=True, with_D=False): rij = cupy.linalg.norm(ri_rj, axis=-1) xi_r_ij = xi_ij * rij cupy.fill_diagonal(rij, 1) + xi_i = xi_j = None dS_dr = -(scipy.special.erf(xi_r_ij) - 2.0*xi_r_ij/PI**0.5*cupy.exp(-xi_r_ij**2))/rij**2 cupy.fill_diagonal(dS_dr, 0) @@ -134,13 +135,16 @@ def get_dD_dS(surface, dF, with_S=True, with_D=False): dD_dri = cupy.expand_dims(dD_dri, axis=-1) dD = dD_dri * drij + dS_dr * (-nj/rij + 3.0*nj_rij/rij**2 * drij) - + dD_dri = None dSii_dF = -exponents * (2.0/PI)**0.5 / switch_fun**2 dSii = cupy.expand_dims(dSii_dF, axis=(1,2)) * dF return dD, dS, dSii def grad_nuc(pcmobj, dm): + mol = pcmobj.mol + log = logger.new_logger(mol, mol.verbose) + t1 = log.init_timer() if not pcmobj._intermediates or 'q_sym' not in pcmobj._intermediates: pcmobj._get_vind(dm) @@ -168,6 +172,7 @@ def grad_nuc(pcmobj, dm): dv_g = numpy.einsum('gx,g->gx', dv_g, q_sym) de -= numpy.asarray([numpy.sum(dv_g[p0:p1], axis=0) for p0,p1 in gridslice]) + t1 = log.timer_debug1('grad nuc', *t1) return de def grad_qv(pcmobj, dm): @@ -176,7 +181,9 @@ def grad_qv(pcmobj, dm): ''' if not pcmobj._intermediates or 'q_sym' not in pcmobj._intermediates: pcmobj._get_vind(dm) - + mol = pcmobj.mol + log = logger.new_logger(mol, mol.verbose) + t1 = log.init_timer() gridslice = pcmobj.surface['gslice_by_atom'] q_sym = pcmobj._intermediates['q_sym'] @@ -199,6 +206,7 @@ def grad_qv(pcmobj, dm): dq = cupy.asarray([cupy.sum(dq[:,p0:p1], axis=1) for p0,p1 in gridslice]) dvj= 2.0 * cupy.asarray([cupy.sum(dvj[:,p0:p1], axis=1) for p0,p1 in aoslice[:,2:]]) de = dq + dvj + t1 = log.timer_debug1('grad qv', *t1) return de.get() def grad_solver(pcmobj, dm): @@ -206,6 +214,9 @@ def grad_solver(pcmobj, dm): dE = 0.5*v* d(K^-1 R) *v + q*dv v^T* d(K^-1 R)v = v^T*K^-1(dR - dK K^-1R)v = v^T K^-1(dR - dK q) ''' + mol = pcmobj.mol + log = logger.new_logger(mol, mol.verbose) + t1 = log.init_timer() if not pcmobj._intermediates or 'q_sym' not in pcmobj._intermediates: pcmobj._get_vind(dm) @@ -300,7 +311,7 @@ def contract_ket(a, B, c): de += de_dR - de_dK else: raise RuntimeError(f"Unknown implicit solvent model: {pcmobj.method}") - + t1 = log.timer_debug1('grad solver', *t1) return de.get() def make_grad_object(grad_method): diff --git a/gpu4pyscf/solvent/hessian/pcm.py b/gpu4pyscf/solvent/hessian/pcm.py index 4fe16261..ae28942c 100644 --- a/gpu4pyscf/solvent/hessian/pcm.py +++ b/gpu4pyscf/solvent/hessian/pcm.py @@ -132,7 +132,7 @@ def pcm_grad_scanner(mol): e, v = pcmobj._get_vind(dm) #return grad_elec(pcmobj, dm) return grad_nuc(pcmobj, dm) + grad_solver(pcmobj, dm) + grad_qv(pcmobj, dm) - + mol.verbose = 0 de = numpy.zeros([mol.natm, mol.natm, 3, 3]) eps = 1e-3 for ia in range(mol.natm): @@ -172,7 +172,8 @@ def pcm_vmat_scanner(mol): e, v = pcmobj._get_vind(dm) return v - vmat = cupy.zeros([len(atmlst), 3, nao, nocc]) + mol.verbose = 0 + vmat = cupy.empty([len(atmlst), 3, nao, nocc]) eps = 1e-3 for i0, ia in enumerate(atmlst): for ix in range(3): diff --git a/gpu4pyscf/solvent/pcm.py b/gpu4pyscf/solvent/pcm.py index d2a4e9b6..335de1f7 100644 --- a/gpu4pyscf/solvent/pcm.py +++ b/gpu4pyscf/solvent/pcm.py @@ -211,7 +211,7 @@ def get_D_S(surface, with_S=True, with_D=False): class PCM(ddcosmo.DDCOSMO): _keys = { - 'method', 'vdw_scale', 'surface' + 'method', 'vdw_scale', 'surface', 'r_probe', 'intopt' } def __init__(self, mol): ddcosmo.DDCOSMO.__init__(self, mol)