From 7fd668b5472c8eeee923f40732b05ed585192120 Mon Sep 17 00:00:00 2001 From: rcclay Date: Thu, 18 Apr 2019 21:55:13 -0600 Subject: [PATCH 01/13] Finite difference ionic derivative reference vals added to gen_mo.py --- src/QMCWaveFunctions/tests/gen_mo.py | 77 +++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/src/QMCWaveFunctions/tests/gen_mo.py b/src/QMCWaveFunctions/tests/gen_mo.py index 0167e55b34..9a537f711f 100644 --- a/src/QMCWaveFunctions/tests/gen_mo.py +++ b/src/QMCWaveFunctions/tests/gen_mo.py @@ -166,8 +166,81 @@ def gen_HCN(): print ' REQUIRE(dghpsi[%d][8] == Approx(%15.10g));'%(i,mo_gh[i][8]) print ' REQUIRE(dghpsi[%d][9] == Approx(%15.10g));'%(i,mo_gh[i][9]) print '' - + + +def gen_HCN_force(): + basis_sets, MO_matrix = read_qmcpack.parse_qmc_wf("hcn.wfnoj.xml",['N','C','H']) + ionpos, elements = read_qmcpack.read_structure_file("hcn.structure.xml") + + pos = [0.02, -0.1, 0.05] + + delta=1.0e-6 + deltainv=1.0/delta + + Natom=ionpos.shape[0]; + norb=7 + for iat in xrange(0,Natom): + for idim in xrange(0,3): + ionpos_p=np.array(ionpos) + ionpos_m=np.array(ionpos) + + ionpos_p[iat][idim]+=delta + ionpos_m[iat][idim]-=delta + + gtos_p = gaussian_orbitals.GTO_centers(ionpos_p, elements, basis_sets) + gtos_m = gaussian_orbitals.GTO_centers(ionpos_m, elements, basis_sets) + + atomic_orbs_p = gtos_p.eval_v(*pos) + atomic_orbs_m = gtos_m.eval_v(*pos) + + mol_orbs_p = np.dot(MO_matrix, atomic_orbs_p) + mol_orbs_m = np.dot(MO_matrix, atomic_orbs_m) + + v_p,g_p,l_p = gtos_p.eval_vgl(*pos) + mo_v_p = np.dot(MO_matrix, v_p) + mo_g_p = np.dot(MO_matrix, g_p) + mo_l_p = np.dot(MO_matrix, l_p) + + v_m,g_m,l_m = gtos_m.eval_vgl(*pos) + mo_v_m = np.dot(MO_matrix, v_m) + mo_g_m = np.dot(MO_matrix, g_m) + mo_l_m = np.dot(MO_matrix, l_m) + + dmo_v = 2.0*deltainv*(mo_v_p-mo_v_m) + dmo_g = 2.0*deltainv*(mo_g_p-mo_g_m) + dmo_l = 2.0*deltainv*(mo_l_p-mo_l_m) + print "//============== Ion ",iat," Component ",idim,"===================" + for iorb in xrange(0,norb): + print ' d %d v = %15.10g '%(iorb,dmo_v[iorb]) + print ' d %d gx = %15.10g '%(iorb,dmo_g[iorb][0]) + print ' d %d gy = %15.10g '%(iorb,dmo_g[iorb][1]) + print ' d %d gz = %15.10g '%(iorb,dmo_g[iorb][2]) + print ' d %d l = %15.10g '%(iorb,dmo_l[iorb]) + + print ' // Generated from gen_mo.py for position %s'%str(pos) + # for i in range(7): + # print ' REQUIRE(values[%d] == Approx(%15.10g));'%(i,mol_orbs[i]) + +# v,g,l = gtos.eval_vgl(*pos) +# mo_v = np.dot(MO_matrix, v) +# mo_g = np.dot(MO_matrix, g) +# mo_l = np.dot(MO_matrix, l) +# print ' // Generated from gen_mo.py for position %s'%str(pos) +# for i in range(7): +# print ' REQUIRE(values[%d] == Approx(%15.10g));'%(i,mo_v[i]) +# print ' REQUIRE(dpsi[%d][0] == Approx(%15.10g));'%(i,mo_g[i][0]) +# print ' REQUIRE(d2psi[%d] == Approx(%15.10g));'%(i,mo_l[i]) +# print '' + +# v,g,h = gtos.eval_vgh(*pos) +# gh = gtos.eval_gradhess(*pos) +# mo_v = np.dot(MO_matrix,v) +# mo_g = np.dot(MO_matrix,g) +# mo_h = np.dot(MO_matrix,h) +# mo_gh = np.dot(MO_matrix,gh) + if __name__ == '__main__': #gen_He() #gen_Ne() - gen_HCN() + #gen_HCN() + gen_HCN_force() From 22c2da8ba0dce31ecd1d53ef076cfd1e9957a45f Mon Sep 17 00:00:00 2001 From: rcclay Date: Thu, 18 Apr 2019 22:04:28 -0600 Subject: [PATCH 02/13] Change formatting for gen_mo.py --- src/QMCWaveFunctions/tests/gen_mo.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/QMCWaveFunctions/tests/gen_mo.py b/src/QMCWaveFunctions/tests/gen_mo.py index 9a537f711f..86b953d314 100644 --- a/src/QMCWaveFunctions/tests/gen_mo.py +++ b/src/QMCWaveFunctions/tests/gen_mo.py @@ -211,11 +211,11 @@ def gen_HCN_force(): dmo_l = 2.0*deltainv*(mo_l_p-mo_l_m) print "//============== Ion ",iat," Component ",idim,"===================" for iorb in xrange(0,norb): - print ' d %d v = %15.10g '%(iorb,dmo_v[iorb]) - print ' d %d gx = %15.10g '%(iorb,dmo_g[iorb][0]) - print ' d %d gy = %15.10g '%(iorb,dmo_g[iorb][1]) - print ' d %d gz = %15.10g '%(iorb,dmo_g[iorb][2]) - print ' d %d l = %15.10g '%(iorb,dmo_l[iorb]) + print ' REQUIRE( dv[%d][%d] == Approx(%15.10g) ); '%(idim,iorb,dmo_v[iorb]) + print ' REQUIRE( dg[%d][%d][0] == Approx(%15.10g) ); '%(idim,iorb,dmo_g[iorb][0]) + print ' REQUIRE( dg[%d][%d][1] == Approx(%15.10g) ); '%(idim,iorb,dmo_g[iorb][0]) + print ' REQUIRE( dg[%d][%d][2] == Approx(%15.10g) ); '%(idim,iorb,dmo_g[iorb][0]) + print ' REQUIRE( dl[%d][%d] == Approx(%15.10g) ); '%(idim,iorb,dmo_v[iorb]) print ' // Generated from gen_mo.py for position %s'%str(pos) # for i in range(7): From 1090857a7292d1285aeff56610ed6e0bf264b54e Mon Sep 17 00:00:00 2001 From: rcclay Date: Thu, 18 Apr 2019 22:07:46 -0600 Subject: [PATCH 03/13] Output tweak --- src/QMCWaveFunctions/tests/gen_mo.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/QMCWaveFunctions/tests/gen_mo.py b/src/QMCWaveFunctions/tests/gen_mo.py index 86b953d314..85749292bd 100644 --- a/src/QMCWaveFunctions/tests/gen_mo.py +++ b/src/QMCWaveFunctions/tests/gen_mo.py @@ -179,6 +179,9 @@ def gen_HCN_force(): Natom=ionpos.shape[0]; norb=7 + + print ' // Generated from gen_mo.py for position %s'%str(pos) + for iat in xrange(0,Natom): for idim in xrange(0,3): ionpos_p=np.array(ionpos) From 1a5029250eb3a99269766d8a5cb41cc5b48c8f6e Mon Sep 17 00:00:00 2001 From: rcclay Date: Sun, 21 Apr 2019 18:28:27 -0600 Subject: [PATCH 04/13] Add evaluateGradSource function to LCAOrbitalSet --- src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 15 ++++++++ src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 16 ++++++++ src/QMCWaveFunctions/tests/gen_mo.py | 10 ++--- src/QMCWaveFunctions/tests/test_MO.cpp | 41 +++++++++++++++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index 4f6ff470c2..56ffcba1e2 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -490,6 +490,21 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P, } } +void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last, + const ParticleSet& source, int iat_src, + GradMatrix_t& gradphi) +{ + +} + +void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last, + const ParticleSet& source, int iat_src, + GradMatrix_t& grad_phi, HessMatrix_t& grad_grad_phi, + GradMatrix_t& grad_lapl_phi) +{ + +} + void LCAOrbitalSet::evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet) { APP_ABORT("LCAOrbitalSet::evaluateThirdDeriv(P,istart,istop,ggg_logdet) not implemented\n"); diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index d68f472928..729d3953f5 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -223,6 +223,22 @@ struct LCAOrbitalSet : public SPOSet HessMatrix_t& grad_grad_logdet, GGGMatrix_t& grad_grad_grad_logdet); + void evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix_t& gradphi); + + void evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix_t& grad_phi, + HessMatrix_t& grad_grad_phi, + GradMatrix_t& grad_lapl_phi); + void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet); private: diff --git a/src/QMCWaveFunctions/tests/gen_mo.py b/src/QMCWaveFunctions/tests/gen_mo.py index 85749292bd..6a4a045bb2 100644 --- a/src/QMCWaveFunctions/tests/gen_mo.py +++ b/src/QMCWaveFunctions/tests/gen_mo.py @@ -214,11 +214,11 @@ def gen_HCN_force(): dmo_l = 2.0*deltainv*(mo_l_p-mo_l_m) print "//============== Ion ",iat," Component ",idim,"===================" for iorb in xrange(0,norb): - print ' REQUIRE( dv[%d][%d] == Approx(%15.10g) ); '%(idim,iorb,dmo_v[iorb]) - print ' REQUIRE( dg[%d][%d][0] == Approx(%15.10g) ); '%(idim,iorb,dmo_g[iorb][0]) - print ' REQUIRE( dg[%d][%d][1] == Approx(%15.10g) ); '%(idim,iorb,dmo_g[iorb][0]) - print ' REQUIRE( dg[%d][%d][2] == Approx(%15.10g) ); '%(idim,iorb,dmo_g[iorb][0]) - print ' REQUIRE( dl[%d][%d] == Approx(%15.10g) ); '%(idim,iorb,dmo_v[iorb]) + print ' REQUIRE( dionpsi[0][%d][%d] == Approx(%15.10g) ); '%(iorb,idim,dmo_v[iorb]) + print ' REQUIRE( diongradpsi[0][%d](%d,0) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][0]) + print ' REQUIRE( diongradpsi[0][%d](%d,1) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][0]) + print ' REQUIRE( diongradpsi[0][%d](%d,2) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][0]) + print ' REQUIRE( dionlaplpsi[0][%d][%d] == Approx(%15.10g) ); '%(iorb,idim,dmo_v[iorb]) print ' // Generated from gen_mo.py for position %s'%str(pos) # for i in range(7): diff --git a/src/QMCWaveFunctions/tests/test_MO.cpp b/src/QMCWaveFunctions/tests/test_MO.cpp index d4c85bef05..b56a9e54b9 100644 --- a/src/QMCWaveFunctions/tests/test_MO.cpp +++ b/src/QMCWaveFunctions/tests/test_MO.cpp @@ -539,7 +539,48 @@ void test_HCN(bool transform) REQUIRE(d3psiV[0][2][1](2,2) == Approx( 0)); REQUIRE(d3psiV[0][2][2](2,2) == Approx( 0)); + SPOSet::GradMatrix_t dionpsi(elec.R.size(), sposet->getOrbitalSetSize()); + SPOSet::HessMatrix_t diongradpsi(elec.R.size(), sposet->getOrbitalSetSize()); + SPOSet::GradMatrix_t dionlaplpsi(elec.R.size(), sposet->getOrbitalSetSize()); + + sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,0, dionpsi,diongradpsi,dionlaplpsi); + //============== Ion 0 Component 0 =================== + REQUIRE( dionpsi[0][0][0] == Approx( 0.1812448328) ); + REQUIRE( diongradpsi[0][0](0,0) == Approx( -1.177405598) ); + REQUIRE( diongradpsi[0][0](0,1) == Approx( -1.177405598) ); + REQUIRE( diongradpsi[0][0](0,2) == Approx( -1.177405598) ); + REQUIRE( dionlaplpsi[0][0][0] == Approx( 0.1812448328) ); + REQUIRE( dionpsi[0][1][0] == Approx(-0.002589527849) ); + REQUIRE( diongradpsi[0][1](0,0) == Approx( 0.001885363005) ); + REQUIRE( diongradpsi[0][1](0,1) == Approx( 0.001885363005) ); + REQUIRE( diongradpsi[0][1](0,2) == Approx( 0.001885363005) ); + REQUIRE( dionlaplpsi[0][1][0] == Approx(-0.002589527849) ); + REQUIRE( dionpsi[0][2][0] == Approx( 1.062313344) ); + REQUIRE( diongradpsi[0][2](0,0) == Approx( -0.3474321646) ); + REQUIRE( diongradpsi[0][2](0,1) == Approx( -0.3474321646) ); + REQUIRE( diongradpsi[0][2](0,2) == Approx( -0.3474321646) ); + REQUIRE( dionlaplpsi[0][2][0] == Approx( 1.062313344) ); + REQUIRE( dionpsi[0][3][0] == Approx( -0.2577722392) ); + REQUIRE( diongradpsi[0][3](0,0) == Approx(-0.008052607692) ); + REQUIRE( diongradpsi[0][3](0,1) == Approx(-0.008052607692) ); + REQUIRE( diongradpsi[0][3](0,2) == Approx(-0.008052607692) ); + REQUIRE( dionlaplpsi[0][3][0] == Approx( -0.2577722392) ); + REQUIRE( dionpsi[0][4][0] == Approx( 0.5817430905) ); + REQUIRE( diongradpsi[0][4](0,0) == Approx( -0.9321997722) ); + REQUIRE( diongradpsi[0][4](0,1) == Approx( -0.9321997722) ); + REQUIRE( diongradpsi[0][4](0,2) == Approx( -0.9321997722) ); + REQUIRE( dionlaplpsi[0][4][0] == Approx( 0.5817430905) ); + REQUIRE( dionpsi[0][5][0] == Approx( -0.1731994034) ); + REQUIRE( diongradpsi[0][5](0,0) == Approx( 0.3620797322) ); + REQUIRE( diongradpsi[0][5](0,1) == Approx( 0.3620797322) ); + REQUIRE( diongradpsi[0][5](0,2) == Approx( 0.3620797322) ); + REQUIRE( dionlaplpsi[0][5][0] == Approx( -0.1731994034) ); + REQUIRE( dionpsi[0][6][0] == Approx( 0.0483016471) ); + REQUIRE( diongradpsi[0][6](0,0) == Approx( -0.1009762174) ); + REQUIRE( diongradpsi[0][6](0,1) == Approx( -0.1009762174) ); + REQUIRE( diongradpsi[0][6](0,2) == Approx( -0.1009762174) ); + REQUIRE( dionlaplpsi[0][6][0] == Approx( 0.0483016471) ); SPOSetBuilderFactory::clear(); } From b9755df27300a9af73927027cee8af47b15101a8 Mon Sep 17 00:00:00 2001 From: rcclay Date: Sun, 21 Apr 2019 19:15:12 -0600 Subject: [PATCH 05/13] Add evaluateGradSourceVGL to SoaLocalizedBasisSet --- src/QMCWaveFunctions/BasisSetBase.h | 2 ++ src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 36 +++++++++++++++++-- .../lcao/SoaLocalizedBasisSet.h | 10 ++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/QMCWaveFunctions/BasisSetBase.h b/src/QMCWaveFunctions/BasisSetBase.h index e941ca0a26..e5444de4c2 100644 --- a/src/QMCWaveFunctions/BasisSetBase.h +++ b/src/QMCWaveFunctions/BasisSetBase.h @@ -160,6 +160,8 @@ struct SoaBasisSetBase virtual void evaluateVGL(const ParticleSet& P, int iat, vgl_type& vgl)=0; virtual void evaluateVGH(const ParticleSet& P, int iat, vgh_type& vgh)=0; virtual void evaluateVGHGH(const ParticleSet& P, int iat, vghgh_type& vghgh)=0; + virtual void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh)=0; + virtual void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh)=0; virtual void evaluateV(const ParticleSet& P, int iat, value_type* restrict vals)=0; virtual bool is_S_orbital(int mo_idx, int ao_idx) { return false;} diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index 56ffcba1e2..ce74ffbcdc 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -494,7 +494,23 @@ void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last const ParticleSet& source, int iat_src, GradMatrix_t& gradphi) { - + if (Identity) + { + for (size_t i = 0, iat = first; iat < last; i++, iat++) + { + myBasisSet->evaluateVGHGH(P, iat, Tempgh); + // evaluate_vghgh_impl(Tempgh, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + } + } + else + { + for (size_t i = 0, iat = first; iat < last; i++, iat++) + { + // myBasisSet->evaluateVGHGH(P, iat, Tempgh); + Product_ABt(Tempgh, *C, Tempghv); + // evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + } + } } void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last, @@ -502,7 +518,23 @@ void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last GradMatrix_t& grad_phi, HessMatrix_t& grad_grad_phi, GradMatrix_t& grad_lapl_phi) { - + if (Identity) + { + for (size_t i = 0, iat = first; iat < last; i++, iat++) + { + // myBasisSet->evaluateVGHGH(P, iat, Tempgh); + // evaluate_vghgh_impl(Tempgh, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + } + } + else + { + for (size_t i = 0, iat = first; iat < last; i++, iat++) + { + // myBasisSet->evaluateVGHGH(P, iat, Tempgh); + Product_ABt(Tempgh, *C, Tempghv); + // evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + } + } } void LCAOrbitalSet::evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet) diff --git a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h index 01d981a77b..e78d1f13b6 100644 --- a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h +++ b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h @@ -228,7 +228,17 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase LOBasisSet[IonID[c]]->evaluateV(P.Lattice, dist[c], displ[c], vals + BasisOffset[c]); } } + + + inline void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) + { + + } + inline void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) + { + + } /** add a new set of Centered Atomic Orbitals * @param icenter the index of the center * @param aos a set of Centered Atomic Orbitals From 3fa7d147d10b387c2151571dbb4e0f8aac2cb796 Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 11:49:32 -0600 Subject: [PATCH 06/13] 1/(2delta). Not 2/delta. I'm dumb --- src/QMCWaveFunctions/tests/gen_mo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/QMCWaveFunctions/tests/gen_mo.py b/src/QMCWaveFunctions/tests/gen_mo.py index 6a4a045bb2..3d634f4b61 100644 --- a/src/QMCWaveFunctions/tests/gen_mo.py +++ b/src/QMCWaveFunctions/tests/gen_mo.py @@ -209,9 +209,9 @@ def gen_HCN_force(): mo_g_m = np.dot(MO_matrix, g_m) mo_l_m = np.dot(MO_matrix, l_m) - dmo_v = 2.0*deltainv*(mo_v_p-mo_v_m) - dmo_g = 2.0*deltainv*(mo_g_p-mo_g_m) - dmo_l = 2.0*deltainv*(mo_l_p-mo_l_m) + dmo_v = 0.5*deltainv*(mo_v_p-mo_v_m) + dmo_g = 0.5*deltainv*(mo_g_p-mo_g_m) + dmo_l = 0.5*deltainv*(mo_l_p-mo_l_m) print "//============== Ion ",iat," Component ",idim,"===================" for iorb in xrange(0,norb): print ' REQUIRE( dionpsi[0][%d][%d] == Approx(%15.10g) ); '%(iorb,idim,dmo_v[iorb]) From fe8913ab579d40ea99258d7545c470f5dc2c6dd5 Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 12:37:36 -0600 Subject: [PATCH 07/13] Some bug fixes to gen_mo.py reference script --- src/QMCWaveFunctions/tests/gen_mo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/QMCWaveFunctions/tests/gen_mo.py b/src/QMCWaveFunctions/tests/gen_mo.py index 3d634f4b61..871c8cac4c 100644 --- a/src/QMCWaveFunctions/tests/gen_mo.py +++ b/src/QMCWaveFunctions/tests/gen_mo.py @@ -216,9 +216,9 @@ def gen_HCN_force(): for iorb in xrange(0,norb): print ' REQUIRE( dionpsi[0][%d][%d] == Approx(%15.10g) ); '%(iorb,idim,dmo_v[iorb]) print ' REQUIRE( diongradpsi[0][%d](%d,0) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][0]) - print ' REQUIRE( diongradpsi[0][%d](%d,1) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][0]) - print ' REQUIRE( diongradpsi[0][%d](%d,2) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][0]) - print ' REQUIRE( dionlaplpsi[0][%d][%d] == Approx(%15.10g) ); '%(iorb,idim,dmo_v[iorb]) + print ' REQUIRE( diongradpsi[0][%d](%d,1) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][1]) + print ' REQUIRE( diongradpsi[0][%d](%d,2) == Approx(%15.10g) ); '%(iorb,idim,dmo_g[iorb][2]) + print ' REQUIRE( dionlaplpsi[0][%d][%d] == Approx(%15.10g) ); '%(iorb,idim,dmo_l[iorb]) print ' // Generated from gen_mo.py for position %s'%str(pos) # for i in range(7): From e07dcebac87dd1aea89aa1af2382f132f43b13ab Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 12:39:18 -0600 Subject: [PATCH 08/13] Add helper function to LCAOrbitalSet. --- src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 58 +++++++++++++++++++-- src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 6 +++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index ce74ffbcdc..eb831c6c12 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -411,6 +411,56 @@ inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, } } +inline void LCAOrbitalSet::evaluate_ionderiv_vgl_impl(const vghgh_type& temp, + int i, + GradMatrix_t& dpsi, + HessMatrix_t& dgpsi, + GradMatrix_t& dlpsi) const +{ + // std::copy_n(temp.data(0), OrbitalSetSize, psi.data()); + const ValueType* restrict gx = temp.data(1); + const ValueType* restrict gy = temp.data(2); + const ValueType* restrict gz = temp.data(3); + const ValueType* restrict hxx = temp.data(4); + const ValueType* restrict hxy = temp.data(5); + const ValueType* restrict hxz = temp.data(6); + const ValueType* restrict hyy = temp.data(7); + const ValueType* restrict hyz = temp.data(8); + const ValueType* restrict hzz = temp.data(9); + const ValueType* restrict gh_xxx = temp.data(10); + const ValueType* restrict gh_xxy = temp.data(11); + const ValueType* restrict gh_xxz = temp.data(12); + const ValueType* restrict gh_xyy = temp.data(13); + const ValueType* restrict gh_xyz = temp.data(14); + const ValueType* restrict gh_xzz = temp.data(15); + const ValueType* restrict gh_yyy = temp.data(16); + const ValueType* restrict gh_yyz = temp.data(17); + const ValueType* restrict gh_yzz = temp.data(18); + const ValueType* restrict gh_zzz = temp.data(19); + + for (size_t j = 0; j < OrbitalSetSize; j++) + { + //As mentioned in SoaLocalizedBasisSet, LCAO's have a nice property that + // for an atomic center, the ion gradient is the negative of the elecron gradient. + // Hence minus signs for each of these. + dpsi[i][j][0] = -gx[j]; + dpsi[i][j][1] = -gy[j]; + dpsi[i][j][2] = -gz[j]; + + dgpsi[i][j](0,0) = -hxx[j]; + dgpsi[i][j](0,1) = dgpsi[i][j](1,0) = -hxy[j]; + dgpsi[i][j](0,2) = dgpsi[i][j](2,0) = -hxz[j]; + dgpsi[i][j](1,1) = -hyy[j]; + dgpsi[i][j](2,1) = dgpsi[i][j](1,2) = -hyz[j]; + dgpsi[i][j](2,2) = -hzz[j]; + + //Since this returns the ion gradient of the laplacian, we have to trace the grad hessian vector. + dlpsi[i][j][0] = -(gh_xxx[j]+gh_xyy[j]+gh_xzz[j]); + dlpsi[i][j][1] = -(gh_xxy[j]+gh_yyy[j]+gh_yzz[j]); + dlpsi[i][j][2] = -(gh_xxz[j]+gh_yyz[j]+gh_zzz[j]); + } +} + void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P, int first, int last, @@ -518,20 +568,22 @@ void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last GradMatrix_t& grad_phi, HessMatrix_t& grad_grad_phi, GradMatrix_t& grad_lapl_phi) { + if (Identity) { for (size_t i = 0, iat = first; iat < last; i++, iat++) { - // myBasisSet->evaluateVGHGH(P, iat, Tempgh); - // evaluate_vghgh_impl(Tempgh, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + myBasisSet->evaluateGradSourceVGL(P, iat, source, iat_src, Tempgh); + evaluate_ionderiv_vgl_impl(Tempgh, i, grad_phi, grad_grad_phi, grad_lapl_phi); } } else { for (size_t i = 0, iat = first; iat < last; i++, iat++) { - // myBasisSet->evaluateVGHGH(P, iat, Tempgh); + myBasisSet->evaluateGradSourceVGL(P, iat, source, iat_src, Tempgh); Product_ABt(Tempgh, *C, Tempghv); + evaluate_ionderiv_vgl_impl(Tempghv, i, grad_phi, grad_grad_phi, grad_lapl_phi); // evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); } } diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index 729d3953f5..6153db96e0 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -275,6 +275,12 @@ struct LCAOrbitalSet : public SPOSet HessMatrix_t& dhlogdet, GGGMatrix_t& dghlogdet) const; + void evaluate_ionderiv_vgl_impl(const vghgh_type& temp, + int i, + GradMatrix_t& dlogdet, + HessMatrix_t& dglogdet, + GradMatrix_t& dllogdet) const; + #if !defined(QMC_COMPLEX) //function to perform orbital rotations From 3d755e46e6b5c9990110760b37861f29ff25a3a8 Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 12:41:10 -0600 Subject: [PATCH 09/13] Evaluate AOBasis ion derivatives. --- .../lcao/SoaLocalizedBasisSet.h | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h index e78d1f13b6..14cb0b6db9 100644 --- a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h +++ b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h @@ -229,15 +229,73 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase } } - + //These are going to use the vghgh containers as temporary arrays. The main difference between + //replacing an ion derivative with an electron derivative is the -1 factor incurred. This will be taken care of + //in LCAO orbital set. inline void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) { - + const DistanceTableData* d_table = P.DistTables[myTableIndex]; + const RealType* restrict dist = (P.activePtcl == iat) ? d_table->Temp_r.data() : d_table->Distances[iat]; + const auto& displ = (P.activePtcl == iat) ? d_table->Temp_dr : d_table->Displacements[iat]; + + LOBasisSet[IonID[jion]]->evaluateVGH(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vghgh); } inline void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) { + auto* restrict gx = vghgh.data(1); + auto* restrict gy = vghgh.data(2); + auto* restrict gz = vghgh.data(3); + + auto* restrict hxx = vghgh.data(4); + auto* restrict hxy = vghgh.data(5); + auto* restrict hxz = vghgh.data(6); + auto* restrict hyy = vghgh.data(7); + auto* restrict hyz = vghgh.data(8); + auto* restrict hzz = vghgh.data(9); + + auto* restrict gxxx = vghgh.data(10); + auto* restrict gxxy = vghgh.data(11); + auto* restrict gxxz = vghgh.data(12); + auto* restrict gxyy = vghgh.data(13); + auto* restrict gxyz = vghgh.data(14); + auto* restrict gxzz = vghgh.data(15); + auto* restrict gyyy = vghgh.data(16); + auto* restrict gyyz = vghgh.data(17); + auto* restrict gyzz = vghgh.data(18); + auto* restrict gzzz = vghgh.data(19); + + for(int ib=0; ibTemp_r.data() : d_table->Distances[iat]; + const auto& displ = (P.activePtcl == iat) ? d_table->Temp_dr : d_table->Displacements[iat]; + + LOBasisSet[IonID[jion]]->evaluateVGHGH(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vghgh); + } /** add a new set of Centered Atomic Orbitals * @param icenter the index of the center From 640f4f747296306bdfd591fc59922a10931804f0 Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 12:45:20 -0600 Subject: [PATCH 10/13] Add/update test values for ion derivatives. --- src/QMCWaveFunctions/tests/test_MO.cpp | 160 +++++++++++++++++++------ 1 file changed, 123 insertions(+), 37 deletions(-) diff --git a/src/QMCWaveFunctions/tests/test_MO.cpp b/src/QMCWaveFunctions/tests/test_MO.cpp index b56a9e54b9..777542854b 100644 --- a/src/QMCWaveFunctions/tests/test_MO.cpp +++ b/src/QMCWaveFunctions/tests/test_MO.cpp @@ -538,6 +538,13 @@ void test_HCN(bool transform) REQUIRE(d3psiV[0][2][1](1,2) == Approx( 0)); REQUIRE(d3psiV[0][2][1](2,2) == Approx( 0)); REQUIRE(d3psiV[0][2][2](2,2) == Approx( 0)); + + + //Move electron 0 to some nontrivial position: + ParticleSet::SingleParticlePos_t disp(0.02, -0.1, 0.05); + elec.makeMove(0, disp); + + SPOSet::GradMatrix_t dionpsi(elec.R.size(), sposet->getOrbitalSetSize()); SPOSet::HessMatrix_t diongradpsi(elec.R.size(), sposet->getOrbitalSetSize()); @@ -545,43 +552,122 @@ void test_HCN(bool transform) sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,0, dionpsi,diongradpsi,dionlaplpsi); - //============== Ion 0 Component 0 =================== - REQUIRE( dionpsi[0][0][0] == Approx( 0.1812448328) ); - REQUIRE( diongradpsi[0][0](0,0) == Approx( -1.177405598) ); - REQUIRE( diongradpsi[0][0](0,1) == Approx( -1.177405598) ); - REQUIRE( diongradpsi[0][0](0,2) == Approx( -1.177405598) ); - REQUIRE( dionlaplpsi[0][0][0] == Approx( 0.1812448328) ); - REQUIRE( dionpsi[0][1][0] == Approx(-0.002589527849) ); - REQUIRE( diongradpsi[0][1](0,0) == Approx( 0.001885363005) ); - REQUIRE( diongradpsi[0][1](0,1) == Approx( 0.001885363005) ); - REQUIRE( diongradpsi[0][1](0,2) == Approx( 0.001885363005) ); - REQUIRE( dionlaplpsi[0][1][0] == Approx(-0.002589527849) ); - REQUIRE( dionpsi[0][2][0] == Approx( 1.062313344) ); - REQUIRE( diongradpsi[0][2](0,0) == Approx( -0.3474321646) ); - REQUIRE( diongradpsi[0][2](0,1) == Approx( -0.3474321646) ); - REQUIRE( diongradpsi[0][2](0,2) == Approx( -0.3474321646) ); - REQUIRE( dionlaplpsi[0][2][0] == Approx( 1.062313344) ); - REQUIRE( dionpsi[0][3][0] == Approx( -0.2577722392) ); - REQUIRE( diongradpsi[0][3](0,0) == Approx(-0.008052607692) ); - REQUIRE( diongradpsi[0][3](0,1) == Approx(-0.008052607692) ); - REQUIRE( diongradpsi[0][3](0,2) == Approx(-0.008052607692) ); - REQUIRE( dionlaplpsi[0][3][0] == Approx( -0.2577722392) ); - REQUIRE( dionpsi[0][4][0] == Approx( 0.5817430905) ); - REQUIRE( diongradpsi[0][4](0,0) == Approx( -0.9321997722) ); - REQUIRE( diongradpsi[0][4](0,1) == Approx( -0.9321997722) ); - REQUIRE( diongradpsi[0][4](0,2) == Approx( -0.9321997722) ); - REQUIRE( dionlaplpsi[0][4][0] == Approx( 0.5817430905) ); - REQUIRE( dionpsi[0][5][0] == Approx( -0.1731994034) ); - REQUIRE( diongradpsi[0][5](0,0) == Approx( 0.3620797322) ); - REQUIRE( diongradpsi[0][5](0,1) == Approx( 0.3620797322) ); - REQUIRE( diongradpsi[0][5](0,2) == Approx( 0.3620797322) ); - REQUIRE( dionlaplpsi[0][5][0] == Approx( -0.1731994034) ); - REQUIRE( dionpsi[0][6][0] == Approx( 0.0483016471) ); - REQUIRE( diongradpsi[0][6](0,0) == Approx( -0.1009762174) ); - REQUIRE( diongradpsi[0][6](0,1) == Approx( -0.1009762174) ); - REQUIRE( diongradpsi[0][6](0,2) == Approx( -0.1009762174) ); - REQUIRE( dionlaplpsi[0][6][0] == Approx( 0.0483016471) ); - + //============== Ion 0 Component 0 =================== + REQUIRE( dionpsi[0][0][0] == Approx( 0.0453112082) ); + REQUIRE( diongradpsi[0][0](0,0) == Approx( -0.2943513994) ); + REQUIRE( diongradpsi[0][0](0,1) == Approx( 0.030468047) ); + REQUIRE( diongradpsi[0][0](0,2) == Approx( -0.0152340235) ); + REQUIRE( dionlaplpsi[0][0][0] == Approx( 1.333755581) ); + REQUIRE( dionpsi[0][1][0] == Approx(-0.0006473819623) ); + REQUIRE( diongradpsi[0][1](0,0) == Approx(0.0004713407512) ); + REQUIRE( diongradpsi[0][1](0,1) == Approx(-0.0001254975603) ); + REQUIRE( diongradpsi[0][1](0,2) == Approx(6.274878013e-05) ); + REQUIRE( dionlaplpsi[0][1][0] == Approx( 0.001057940846) ); + REQUIRE( dionpsi[0][2][0] == Approx( 0.265578336) ); + REQUIRE( diongradpsi[0][2](0,0) == Approx( -0.08685804115) ); + REQUIRE( diongradpsi[0][2](0,1) == Approx( 0.05438178417) ); + REQUIRE( diongradpsi[0][2](0,2) == Approx( -0.02719089209) ); + REQUIRE( dionlaplpsi[0][2][0] == Approx( -1.882489819) ); + REQUIRE( dionpsi[0][3][0] == Approx( -0.06444305979) ); + REQUIRE( diongradpsi[0][3](0,0) == Approx(-0.002013151923) ); + REQUIRE( diongradpsi[0][3](0,1) == Approx(-0.002535923431) ); + REQUIRE( diongradpsi[0][3](0,2) == Approx( 0.001267961716) ); + REQUIRE( dionlaplpsi[0][3][0] == Approx( 0.4547401581) ); + REQUIRE( dionpsi[0][4][0] == Approx( 0.1454357726) ); + REQUIRE( diongradpsi[0][4](0,0) == Approx( -0.2330499431) ); + REQUIRE( diongradpsi[0][4](0,1) == Approx( 0.09667641762) ); + REQUIRE( diongradpsi[0][4](0,2) == Approx( -0.04833820881) ); + REQUIRE( dionlaplpsi[0][4][0] == Approx( -0.9197558839) ); + REQUIRE( dionpsi[0][5][0] == Approx( -0.04329985085) ); + REQUIRE( diongradpsi[0][5](0,0) == Approx( 0.09051993304) ); + REQUIRE( diongradpsi[0][5](0,1) == Approx( 0.382375474) ); + REQUIRE( diongradpsi[0][5](0,2) == Approx( -0.07043361927) ); + REQUIRE( dionlaplpsi[0][5][0] == Approx( 0.2201672051) ); + REQUIRE( dionpsi[0][6][0] == Approx( 0.01207541177) ); + REQUIRE( diongradpsi[0][6](0,0) == Approx( -0.02524405435) ); + REQUIRE( diongradpsi[0][6](0,1) == Approx( 0.0800332842) ); + REQUIRE( diongradpsi[0][6](0,2) == Approx( 0.3929818664) ); + REQUIRE( dionlaplpsi[0][6][0] == Approx( -0.0614000824) ); + + + sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,1, dionpsi,diongradpsi,dionlaplpsi); + + //============== Ion 1 Component 1 =================== + REQUIRE( dionpsi[0][0][1] == Approx(0.0001412373768) ); + REQUIRE( diongradpsi[0][0](1,0) == Approx(0.0001124265646) ); + REQUIRE( diongradpsi[0][0](1,1) == Approx(-0.001383378615) ); + REQUIRE( diongradpsi[0][0](1,2) == Approx(-1.449757545e-05) ); + REQUIRE( dionlaplpsi[0][0][1] == Approx(-0.001252043663) ); + REQUIRE( dionpsi[0][1][1] == Approx( -0.01029290716) ); + REQUIRE( diongradpsi[0][1](1,0) == Approx( -0.06178485148) ); + REQUIRE( diongradpsi[0][1](1,1) == Approx( 0.0971577216) ); + REQUIRE( diongradpsi[0][1](1,2) == Approx( 0.002885675005) ); + REQUIRE( dionlaplpsi[0][1][1] == Approx( -0.1403103458) ); + REQUIRE( dionpsi[0][2][1] == Approx( -0.0230872583) ); + REQUIRE( diongradpsi[0][2](1,0) == Approx( -0.02537847709) ); + REQUIRE( diongradpsi[0][2](1,1) == Approx( 0.2268946564) ); + REQUIRE( diongradpsi[0][2](1,2) == Approx( 0.001988963201) ); + REQUIRE( dionlaplpsi[0][2][1] == Approx( 0.2028851421) ); + REQUIRE( dionpsi[0][3][1] == Approx( 0.01850231814) ); + REQUIRE( diongradpsi[0][3](1,0) == Approx( 0.05709948475) ); + REQUIRE( diongradpsi[0][3](1,1) == Approx( -0.1776515965) ); + REQUIRE( diongradpsi[0][3](1,2) == Approx(-0.003685792479) ); + REQUIRE( dionlaplpsi[0][3][1] == Approx( -0.1280699725) ); + REQUIRE( dionpsi[0][4][1] == Approx( -0.02136209962) ); + REQUIRE( diongradpsi[0][4](1,0) == Approx( -0.03836586276) ); + REQUIRE( diongradpsi[0][4](1,1) == Approx( 0.2084578148) ); + REQUIRE( diongradpsi[0][4](1,2) == Approx( 0.002581590766) ); + REQUIRE( dionlaplpsi[0][4][1] == Approx( 0.1792683544) ); + REQUIRE( dionpsi[0][5][1] == Approx( -0.1942343714) ); + REQUIRE( diongradpsi[0][5](1,0) == Approx( -0.3037357197) ); + REQUIRE( diongradpsi[0][5](1,1) == Approx( -0.09561978734) ); + REQUIRE( diongradpsi[0][5](1,2) == Approx( 0.02118492506) ); + REQUIRE( dionlaplpsi[0][5][1] == Approx( 0.6410434658) ); + REQUIRE( dionpsi[0][6][1] == Approx( -0.03930992259) ); + REQUIRE( diongradpsi[0][6](1,0) == Approx( -0.06331544695) ); + REQUIRE( diongradpsi[0][6](1,1) == Approx(-0.002807368817) ); + REQUIRE( diongradpsi[0][6](1,2) == Approx( -0.02801340823) ); + REQUIRE( dionlaplpsi[0][6][1] == Approx( 0.1369061053) ); + + sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,2, dionpsi,diongradpsi,dionlaplpsi); + + //============== Ion 2 Component 2 =================== + REQUIRE( dionpsi[0][0][2] == Approx(1.302648961e-06) ); + REQUIRE( diongradpsi[0][0](2,0) == Approx(1.865129579e-06) ); + REQUIRE( diongradpsi[0][0](2,1) == Approx(6.142092043e-08) ); + REQUIRE( diongradpsi[0][0](2,2) == Approx(2.602225618e-05) ); + REQUIRE( dionlaplpsi[0][0][2] == Approx(1.234692903e-06) ); + REQUIRE( dionpsi[0][1][2] == Approx(3.248738084e-07) ); + REQUIRE( diongradpsi[0][1](2,0) == Approx(-2.044420189e-06) ); + REQUIRE( diongradpsi[0][1](2,1) == Approx(-7.011145137e-08) ); + REQUIRE( diongradpsi[0][1](2,2) == Approx(6.532522353e-06) ); + REQUIRE( dionlaplpsi[0][1][2] == Approx(-6.10958506e-06) ); + REQUIRE( dionpsi[0][2][2] == Approx(3.264249981e-06) ); + REQUIRE( diongradpsi[0][2](2,0) == Approx(2.820971234e-05) ); + REQUIRE( diongradpsi[0][2](2,1) == Approx(9.405184964e-07) ); + REQUIRE( diongradpsi[0][2](2,2) == Approx(6.481420782e-05) ); + REQUIRE( dionlaplpsi[0][2][2] == Approx( 5.73961989e-05) ); + REQUIRE( dionpsi[0][3][2] == Approx(0.0001288974413) ); + REQUIRE( diongradpsi[0][3](2,0) == Approx(0.0002840756879) ); + REQUIRE( diongradpsi[0][3](2,1) == Approx(9.281700408e-06) ); + REQUIRE( diongradpsi[0][3](2,2) == Approx( 0.002573308008) ); + REQUIRE( dionlaplpsi[0][3][2] == Approx(0.0003025314443) ); + REQUIRE( dionpsi[0][4][2] == Approx(-7.300043903e-05) ); + REQUIRE( diongradpsi[0][4](2,0) == Approx(-0.0001000016834) ); + REQUIRE( diongradpsi[0][4](2,1) == Approx(-3.233243534e-06) ); + REQUIRE( diongradpsi[0][4](2,2) == Approx(-0.001458391774) ); + REQUIRE( dionlaplpsi[0][4][2] == Approx(-3.546690719e-05) ); + REQUIRE( dionpsi[0][5][2] == Approx(2.910525987e-06) ); + REQUIRE( diongradpsi[0][5](2,0) == Approx(1.307065133e-05) ); + REQUIRE( diongradpsi[0][5](2,1) == Approx(1.560390706e-06) ); + REQUIRE( diongradpsi[0][5](2,2) == Approx(-2.92731811e-06) ); + REQUIRE( dionlaplpsi[0][5][2] == Approx(3.797816228e-05) ); + REQUIRE( dionpsi[0][6][2] == Approx(-1.56074936e-05) ); + REQUIRE( diongradpsi[0][6](2,0) == Approx(-7.009049656e-05) ); + REQUIRE( diongradpsi[0][6](2,1) == Approx(-2.048666792e-06) ); + REQUIRE( diongradpsi[0][6](2,2) == Approx(2.967709412e-06) ); + REQUIRE( dionlaplpsi[0][6][2] == Approx(-0.0002018111858) ); + SPOSetBuilderFactory::clear(); } } From 9480c4a4dcdc8903a6c8347f88c867b4013e5091 Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 13:10:53 -0600 Subject: [PATCH 11/13] Test ion derivatives if SoA build only --- src/QMCWaveFunctions/tests/test_MO.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/QMCWaveFunctions/tests/test_MO.cpp b/src/QMCWaveFunctions/tests/test_MO.cpp index 777542854b..1e05cc8c4e 100644 --- a/src/QMCWaveFunctions/tests/test_MO.cpp +++ b/src/QMCWaveFunctions/tests/test_MO.cpp @@ -545,7 +545,7 @@ void test_HCN(bool transform) elec.makeMove(0, disp); - +#if defined(ENABLE_SOA) SPOSet::GradMatrix_t dionpsi(elec.R.size(), sposet->getOrbitalSetSize()); SPOSet::HessMatrix_t diongradpsi(elec.R.size(), sposet->getOrbitalSetSize()); SPOSet::GradMatrix_t dionlaplpsi(elec.R.size(), sposet->getOrbitalSetSize()); @@ -667,6 +667,7 @@ void test_HCN(bool transform) REQUIRE( diongradpsi[0][6](2,1) == Approx(-2.048666792e-06) ); REQUIRE( diongradpsi[0][6](2,2) == Approx(2.967709412e-06) ); REQUIRE( dionlaplpsi[0][6][2] == Approx(-0.0002018111858) ); +#endif SPOSetBuilderFactory::clear(); } From 1315c025f5e7a21cbdda5b09b2be4412bd327c4c Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 13:46:19 -0600 Subject: [PATCH 12/13] Add evaluateGradSource for gradients only. Update unit test --- src/QMCWaveFunctions/BasisSetBase.h | 2 +- src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 30 ++++++++++++++--- src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 4 +++ .../lcao/SoaLocalizedBasisSet.h | 17 ++++++++-- src/QMCWaveFunctions/tests/test_MO.cpp | 32 +++++++++++++++++++ 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/QMCWaveFunctions/BasisSetBase.h b/src/QMCWaveFunctions/BasisSetBase.h index e5444de4c2..3a4a8af1af 100644 --- a/src/QMCWaveFunctions/BasisSetBase.h +++ b/src/QMCWaveFunctions/BasisSetBase.h @@ -160,7 +160,7 @@ struct SoaBasisSetBase virtual void evaluateVGL(const ParticleSet& P, int iat, vgl_type& vgl)=0; virtual void evaluateVGH(const ParticleSet& P, int iat, vgh_type& vgh)=0; virtual void evaluateVGHGH(const ParticleSet& P, int iat, vghgh_type& vghgh)=0; - virtual void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh)=0; + virtual void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vgl_type& vgl)=0; virtual void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh)=0; virtual void evaluateV(const ParticleSet& P, int iat, value_type* restrict vals)=0; virtual bool is_S_orbital(int mo_idx, int ao_idx) { return false;} diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index eb831c6c12..a830a33397 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -411,6 +411,26 @@ inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, } } +inline void LCAOrbitalSet::evaluate_ionderiv_v_impl(const vgl_type& temp, + int i, + GradMatrix_t& dpsi) const +{ + // std::copy_n(temp.data(0), OrbitalSetSize, psi.data()); + const ValueType* restrict gx = temp.data(1); + const ValueType* restrict gy = temp.data(2); + const ValueType* restrict gz = temp.data(3); + + for (size_t j = 0; j < OrbitalSetSize; j++) + { + //As mentioned in SoaLocalizedBasisSet, LCAO's have a nice property that + // for an atomic center, the ion gradient is the negative of the elecron gradient. + // Hence minus signs for each of these. + dpsi[i][j][0] = -gx[j]; + dpsi[i][j][1] = -gy[j]; + dpsi[i][j][2] = -gz[j]; + } +} + inline void LCAOrbitalSet::evaluate_ionderiv_vgl_impl(const vghgh_type& temp, int i, GradMatrix_t& dpsi, @@ -548,17 +568,17 @@ void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P, int first, int last { for (size_t i = 0, iat = first; iat < last; i++, iat++) { - myBasisSet->evaluateVGHGH(P, iat, Tempgh); - // evaluate_vghgh_impl(Tempgh, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + myBasisSet->evaluateGradSourceV(P, iat, source, iat_src, Temp); + evaluate_ionderiv_v_impl(Temp, i, gradphi); } } else { for (size_t i = 0, iat = first; iat < last; i++, iat++) { - // myBasisSet->evaluateVGHGH(P, iat, Tempgh); - Product_ABt(Tempgh, *C, Tempghv); - // evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + myBasisSet->evaluateGradSourceV(P, iat, source, iat_src, Temp); + Product_ABt(Temp, *C, Tempv); + evaluate_ionderiv_v_impl(Tempv, i, gradphi); } } } diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index 6153db96e0..59aaf2aa36 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -275,6 +275,10 @@ struct LCAOrbitalSet : public SPOSet HessMatrix_t& dhlogdet, GGGMatrix_t& dghlogdet) const; + void evaluate_ionderiv_v_impl(const vgl_type& temp, + int i, + GradMatrix_t& dlogdet) const; + void evaluate_ionderiv_vgl_impl(const vghgh_type& temp, int i, GradMatrix_t& dlogdet, diff --git a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h index 14cb0b6db9..e8b1d16fc1 100644 --- a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h +++ b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h @@ -232,13 +232,26 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase //These are going to use the vghgh containers as temporary arrays. The main difference between //replacing an ion derivative with an electron derivative is the -1 factor incurred. This will be taken care of //in LCAO orbital set. - inline void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) + inline void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vgl_type& vgl) { + + auto* restrict gx = vgl.data(1); + auto* restrict gy = vgl.data(2); + auto* restrict gz = vgl.data(3); + + for(int ib=0; ibTemp_r.data() : d_table->Distances[iat]; const auto& displ = (P.activePtcl == iat) ? d_table->Temp_dr : d_table->Displacements[iat]; - LOBasisSet[IonID[jion]]->evaluateVGH(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vghgh); + LOBasisSet[IonID[jion]]->evaluateVGL(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vgl); + } inline void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) diff --git a/src/QMCWaveFunctions/tests/test_MO.cpp b/src/QMCWaveFunctions/tests/test_MO.cpp index 1e05cc8c4e..8285082b83 100644 --- a/src/QMCWaveFunctions/tests/test_MO.cpp +++ b/src/QMCWaveFunctions/tests/test_MO.cpp @@ -667,6 +667,38 @@ void test_HCN(bool transform) REQUIRE( diongradpsi[0][6](2,1) == Approx(-2.048666792e-06) ); REQUIRE( diongradpsi[0][6](2,2) == Approx(2.967709412e-06) ); REQUIRE( dionlaplpsi[0][6][2] == Approx(-0.0002018111858) ); + + //Same tests as before, but for the gradient only. + + sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,0, dionpsi); + //============== Ion 0 Component 0 =================== + REQUIRE( dionpsi[0][0][0] == Approx( 0.0453112082) ); + REQUIRE( dionpsi[0][1][0] == Approx(-0.0006473819623) ); + REQUIRE( dionpsi[0][2][0] == Approx( 0.265578336) ); + REQUIRE( dionpsi[0][3][0] == Approx( -0.06444305979) ); + REQUIRE( dionpsi[0][4][0] == Approx( 0.1454357726) ); + REQUIRE( dionpsi[0][5][0] == Approx( -0.04329985085) ); + REQUIRE( dionpsi[0][6][0] == Approx( 0.01207541177) ); + + sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,1, dionpsi); + //============== Ion 1 Component 1 =================== + REQUIRE( dionpsi[0][0][1] == Approx(0.0001412373768) ); + REQUIRE( dionpsi[0][1][1] == Approx( -0.01029290716) ); + REQUIRE( dionpsi[0][2][1] == Approx( -0.0230872583) ); + REQUIRE( dionpsi[0][3][1] == Approx( 0.01850231814) ); + REQUIRE( dionpsi[0][4][1] == Approx( -0.02136209962) ); + REQUIRE( dionpsi[0][5][1] == Approx( -0.1942343714) ); + REQUIRE( dionpsi[0][6][1] == Approx( -0.03930992259) ); + + sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,2, dionpsi); + //============== Ion 2 Component 2 =================== + REQUIRE( dionpsi[0][0][2] == Approx(1.302648961e-06) ); + REQUIRE( dionpsi[0][1][2] == Approx(3.248738084e-07) ); + REQUIRE( dionpsi[0][2][2] == Approx(3.264249981e-06) ); + REQUIRE( dionpsi[0][3][2] == Approx(0.0001288974413) ); + REQUIRE( dionpsi[0][4][2] == Approx(-7.300043903e-05) ); + REQUIRE( dionpsi[0][5][2] == Approx(2.910525987e-06) ); + REQUIRE( dionpsi[0][6][2] == Approx(-1.56074936e-05) ); #endif SPOSetBuilderFactory::clear(); From 9978b3c231b2fed334851ed2cf30fb82f369a267 Mon Sep 17 00:00:00 2001 From: rcclay Date: Mon, 22 Apr 2019 14:14:33 -0600 Subject: [PATCH 13/13] Add comments --- src/QMCWaveFunctions/BasisSetBase.h | 7 +++ src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 59 ++++++++++++++++++- .../lcao/SoaLocalizedBasisSet.h | 17 +++--- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/QMCWaveFunctions/BasisSetBase.h b/src/QMCWaveFunctions/BasisSetBase.h index 3a4a8af1af..1f587f145c 100644 --- a/src/QMCWaveFunctions/BasisSetBase.h +++ b/src/QMCWaveFunctions/BasisSetBase.h @@ -157,10 +157,17 @@ struct SoaBasisSetBase virtual SoaBasisSetBase* makeClone() const = 0; virtual void setBasisSetSize(int nbs)=0; + + //Evaluates value, gradient, and laplacian for electron "iat". Parks them into a temporary data structure "vgl". virtual void evaluateVGL(const ParticleSet& P, int iat, vgl_type& vgl)=0; + //Evaluates value, gradient, and Hessian for electron "iat". Parks them into a temporary data structure "vgh". virtual void evaluateVGH(const ParticleSet& P, int iat, vgh_type& vgh)=0; + //Evaluates value, gradient, and Hessian, and Gradient Hessian for electron "iat". Parks them into a temporary data structure "vghgh". virtual void evaluateVGHGH(const ParticleSet& P, int iat, vghgh_type& vghgh)=0; + //Evaluates the x,y, and z components of ionic gradient associated with "jion" of value. Parks the raw data into "vgl" container. virtual void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vgl_type& vgl)=0; + //Evaluates the x,y, and z components of ionic gradient associated with "jion" value, gradient, and laplacian. + // Parks the raw data into "vghgh" container. virtual void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh)=0; virtual void evaluateV(const ParticleSet& P, int iat, value_type* restrict vals)=0; virtual bool is_S_orbital(int mo_idx, int ao_idx) { return false;} diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index 59aaf2aa36..a7840ee7de 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -223,13 +223,62 @@ struct LCAOrbitalSet : public SPOSet HessMatrix_t& grad_grad_logdet, GGGMatrix_t& grad_grad_grad_logdet); + //NOTE: The data types get complicated here, so here's an overview of the + // data types associated with ionic derivatives, and how to get their data. + // + //NOTE: These data structures hold the data for one particular ion, and so the ID is implicit. + // It's up to the user to keep track of which ion these derivatives refer to. + // + // 1.) GradMatrix_t grad_phi: Holds the ionic derivatives of each SPO for each electron. + // Example: grad_phi[iel][iorb][idim]. iel -- electron index. + // iorb -- orbital index. + // idim -- cartesian index of ionic derivative. + // X=0, Y=1, Z=2. + // + // 2.) HessMatrix_t grad_grad_phi: Holds the ionic derivatives of the electron gradient components + // for each SPO and each electron. + // Example: grad_grad_phi[iel][iorb](idim,edim) iel -- electron index. + // iorb -- orbital index. + // idim -- ionic derivative's cartesian index. + // X=0, Y=1, Z=2 + // edim -- electron derivative's cartesian index. + // x=0, y=1, z=2. + // + // 3.) GradMatrix_t grad_lapl_phi: Holds the ionic derivatives of the electron laplacian for each SPO and each electron. + // Example: grad_lapl_phi[iel][iorb][idim]. iel -- electron index. + // iorb -- orbital index. + // idim -- cartesian index of ionic derivative. + // X=0, Y=1, Z=2. + + /** + * \brief Calculate ion derivatives of SPO's. + * + * @param P Electron particle set. + * @param first index of first electron + * @@param last index of last electron + * @param source Ion particle set. + * @param iat_src Index of ion. + * @param gradphi Container storing ion gradients for all particles and all orbitals. + */ void evaluateGradSource(const ParticleSet& P, int first, int last, const ParticleSet& source, int iat_src, - GradMatrix_t& gradphi); - + GradMatrix_t& grad_phi); + + /** + * \brief Calculate ion derivatives of SPO's, their gradients, and their laplacians. + * + * @param P Electron particle set. + * @param first index of first electron. + * @@param last index of last electron + * @param source Ion particle set. + * @param iat_src Index of ion. + * @param grad_phi Container storing ion gradients for all particles and all orbitals. + * @param grad_grad_phi Container storing ion gradients of electron gradients for all particles and all orbitals. + * @param grad_lapl_phi Container storing ion gradients of SPO laplacians for all particles and all orbitals. + */ void evaluateGradSource(const ParticleSet& P, int first, int last, @@ -274,11 +323,15 @@ struct LCAOrbitalSet : public SPOSet GradMatrix_t& dlogdet, HessMatrix_t& dhlogdet, GGGMatrix_t& dghlogdet) const; - + + + //Unpacks data in vgl object and calculates/places ionic gradient result into dlogdet. void evaluate_ionderiv_v_impl(const vgl_type& temp, int i, GradMatrix_t& dlogdet) const; + //Unpacks data in vgl object and calculates/places ionic gradient of value, + // electron gradient, and electron laplacian result into dlogdet, dglogdet, and dllogdet respectively. void evaluate_ionderiv_vgl_impl(const vghgh_type& temp, int i, GradMatrix_t& dlogdet, diff --git a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h index e8b1d16fc1..70a5eadf8d 100644 --- a/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h +++ b/src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h @@ -182,8 +182,6 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase */ inline void evaluateVGH(const ParticleSet& P, int iat, vgh_type& vgh) { - // APP_ABORT("SoaLocalizedBasisSet::evaluateVGH() not implemented\n"); - const DistanceTableData* d_table = P.DistTables[myTableIndex]; const RealType* restrict dist = (P.activePtcl == iat) ? d_table->Temp_r.data() : d_table->Distances[iat]; const auto& displ = (P.activePtcl == iat) ? d_table->Temp_dr : d_table->Displacements[iat]; @@ -229,12 +227,9 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase } } - //These are going to use the vghgh containers as temporary arrays. The main difference between - //replacing an ion derivative with an electron derivative is the -1 factor incurred. This will be taken care of - //in LCAO orbital set. inline void evaluateGradSourceV(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vgl_type& vgl) { - + //We need to zero out the temporary array vgl. auto* restrict gx = vgl.data(1); auto* restrict gy = vgl.data(2); auto* restrict gz = vgl.data(3); @@ -249,13 +244,17 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase const DistanceTableData* d_table = P.DistTables[myTableIndex]; const RealType* restrict dist = (P.activePtcl == iat) ? d_table->Temp_r.data() : d_table->Distances[iat]; const auto& displ = (P.activePtcl == iat) ? d_table->Temp_dr : d_table->Displacements[iat]; - + + //Since LCAO's are written only in terms of (r-R), ionic derivatives only exist for the atomic center + //that we wish to take derivatives of. Moreover, we can obtain an ion derivative by multiplying an electron + //derivative by -1.0. Handling this sign is left to LCAOrbitalSet. For now, just note this is the electron VGL function. LOBasisSet[IonID[jion]]->evaluateVGL(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vgl); } inline void evaluateGradSourceVGL(const ParticleSet& P, int iat, const ParticleSet& ions, int jion, vghgh_type& vghgh) { + //We need to zero out the temporary array vghgh. auto* restrict gx = vghgh.data(1); auto* restrict gy = vghgh.data(2); auto* restrict gz = vghgh.data(3); @@ -303,10 +302,14 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase gyzz[ib]=0; gzzz[ib]=0; } + const DistanceTableData* d_table = P.DistTables[myTableIndex]; const RealType* restrict dist = (P.activePtcl == iat) ? d_table->Temp_r.data() : d_table->Distances[iat]; const auto& displ = (P.activePtcl == iat) ? d_table->Temp_dr : d_table->Displacements[iat]; + //Since LCAO's are written only in terms of (r-R), ionic derivatives only exist for the atomic center + //that we wish to take derivatives of. Moreover, we can obtain an ion derivative by multiplying an electron + //derivative by -1.0. Handling this sign is left to LCAOrbitalSet. For now, just note this is the electron VGL function. LOBasisSet[IonID[jion]]->evaluateVGHGH(P.Lattice, dist[jion], displ[jion], BasisOffset[jion], vghgh); }