Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Ionic Derivatives of LCAO-type SPO's for SoA #1559

Merged
merged 15 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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