Skip to content

Commit

Permalink
Merge pull request #1559 from rcclay/lcao_ion_deriv
Browse files Browse the repository at this point in the history
Implement Ionic Derivatives of LCAO-type SPO's for SoA
  • Loading branch information
ye-luo authored Apr 23, 2019
2 parents fa70b3a + 5cb872e commit 32067fc
Show file tree
Hide file tree
Showing 6 changed files with 533 additions and 6 deletions.
9 changes: 9 additions & 0 deletions src/QMCWaveFunctions/BasisSetBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,18 @@ struct SoaBasisSetBase

virtual SoaBasisSetBase<T>* 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;}

Expand Down
119 changes: 119 additions & 0 deletions src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,76 @@ 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,
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,
Expand Down Expand Up @@ -490,6 +560,55 @@ 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)
{
if (Identity)
{
for (size_t i = 0, iat = first; iat < last; i++, iat++)
{
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->evaluateGradSourceV(P, iat, source, iat_src, Temp);
Product_ABt(Temp, *C, Tempv);
evaluate_ionderiv_v_impl(Tempv, i, 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)
{

if (Identity)
{
for (size_t i = 0, iat = first; iat < last; i++, iat++)
{
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->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);
}
}
}

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");
Expand Down
79 changes: 79 additions & 0 deletions src/QMCWaveFunctions/lcao/LCAOrbitalSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,71 @@ 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& 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,
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:
Expand Down Expand Up @@ -258,6 +323,20 @@ 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,
HessMatrix_t& dglogdet,
GradMatrix_t& dllogdet) const;


#if !defined(QMC_COMPLEX)
Expand Down
88 changes: 86 additions & 2 deletions src/QMCWaveFunctions/lcao/SoaLocalizedBasisSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,6 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase<ORBT>
*/
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];
Expand Down Expand Up @@ -228,7 +226,93 @@ struct SoaLocalizedBasisSet : public SoaBasisSetBase<ORBT>
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, 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);

for(int ib=0; ib<BasisSetSize; ib++)
{
gx[ib]=0;
gy[ib]=0;
gz[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]]->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);

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; ib<BasisSetSize; ib++)
{
gx[ib]=0;
gy[ib]=0;
gz[ib]=0;

hxx[ib]=0;
hxy[ib]=0;
hxz[ib]=0;
hyy[ib]=0;
hyz[ib]=0;
hzz[ib]=0;

gxxx[ib]=0;
gxxy[ib]=0;
gxxz[ib]=0;
gxyy[ib]=0;
gxyz[ib]=0;
gxzz[ib]=0;
gyyy[ib]=0;
gyyz[ib]=0;
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);

}
/** add a new set of Centered Atomic Orbitals
* @param icenter the index of the center
* @param aos a set of Centered Atomic Orbitals
Expand Down
Loading

0 comments on commit 32067fc

Please sign in to comment.