void Jastrow_threebody_piece_diffspin::getParmDeriv(const Array3 <doublevar> & eibasis, const Array3 <doublevar> & eebasis, Parm_deriv_return & deriv) { //cout << "Jastrow_threebody_piece_diffspin::getParmDeriv" << endl; assert(eibasis.GetDim(1) >= parm_centers.GetDim(0)); int natoms=parm_centers.GetDim(0); int nelectrons=eebasis.GetDim(0); const doublevar tiny=1e-14; //cout << "updateLap " << endl; for(int at=0; at < natoms; at++) { int p=parm_centers(at); for(int i=0; i< _nparms(p); i++) { int k=klm(i,0), el=klm(i,1), m=klm(i,2); for(int e=0; e< nelectrons; e++) { if(fabs(eibasis(e,at,k)) > tiny || fabs(eibasis(e,at,el)) > tiny) { for(int j=e+1; j< nelectrons; j++) { int s=(j < nspin_up) != (e < nspin_up); int index=linear_parms(s)(p,i); doublevar vkl=(//eibasis(e,at,k)*eibasis(j,at,el) +eibasis(j,at,k)*eibasis(e,at,el)); deriv.gradient(index)+=vkl*eebasis(e,j,m); } } } } } }
//----------------------------------------------------------- void Jastrow_threebody_piece_diffspin::updateVal(int e, const Array4 <doublevar> & eibasis, const Array3 <doublevar> & eebasis, Array1 <doublevar> & updated_val) { assert(eibasis.GetDim(1) >= parm_centers.GetDim(0)); int natoms=parm_centers.GetDim(0); int nelectrons=eebasis.GetDim(0); int s; const doublevar tiny=1e-14; //cout << "updateLap " << endl; for(int at=0; at < natoms; at++) { int p=parm_centers(at); for(int i=0; i< _nparms(p); i++) { int k=klm(i,0), el=klm(i,1), m=klm(i,2); if(fabs(eibasis(e,at,k,0)) > tiny || fabs(eibasis(e,at,el,0)) > tiny) { for(int j=0; j< e; j++) { s=(j < nspin_up) != (e < nspin_up); doublevar vkl=unique_parameters_spin(s)(p,i)*(eibasis(e,at,k,0)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,0) ); updated_val(j)+=vkl*eebasis(j,m,0); } for(int j=e+1; j< nelectrons; j++) { s=(j < nspin_up) != (e < nspin_up); doublevar vkl=unique_parameters_spin(s)(p,i)*(//eibasis(e,at,k,0)*eibasis(j,at,el,0) +eibasis(j,at,k,0)*eibasis(e,at,el,0)); updated_val(j)+=vkl*eebasis(j,m,0); } } } } }
int Jastrow_threebody_piece_diffspin::writeinput(string & indent, ostream & os) { if(freeze) os << indent << "FREEZE" << endl; for(int i=0; i< unique_parameters_spin(0).GetDim(0); i++) { os << indent << "LIKE_COEFFICIENTS { " << parm_labels[i] << " "; for(int j=0; j< _nparms(i); j++) os << unique_parameters_spin(0)(i,j) << " "; os << " } " << endl; } for(int i=0; i< unique_parameters_spin(1).GetDim(0); i++) { os << indent << "UNLIKE_COEFFICIENTS { " << parm_labels[i] << " "; for(int j=0; j< _nparms(i); j++) os << unique_parameters_spin(1)(i,j) << " "; os << " } " << endl; } os << indent << "SM_TERMS {\n"; for(int i=0; i< klm.GetDim(0); i++) { os << indent << " "; for(int j=0; j< klm.GetDim(1); j++) { os << klm(i,j) << " "; } os << endl; } os << indent << "}\n"; return 1; }
//-------------------------------------------------------------------------- //start: added for ei back-flow void Jastrow_threebody_piece_diffspin::updateVal_E_I(int e, const Array4 <doublevar> & eibasis, const Array3 <doublevar> & eebasis, Array3 <doublevar> & lap) { //cout << "Jastrow_threebody_piece::updateLap_E_I" << endl; if(eebasis.GetDim(1)<eebasis_max) error("Need more eebasis functions in three-body spin"); int natoms=parm_centers.GetDim(0); int nelectrons=eebasis.GetDim(0); assert(lap.GetDim(2) >= 5); assert(lap.GetDim(0) >= nelectrons); assert(eibasis.GetDim(1) >= parm_centers.GetDim(0)); assert(lap.GetDim(1) >= natoms); int s; const doublevar tiny=1e-14; //cout << "updateLap " << endl; for(int at=0; at < natoms; at++) { int p=parm_centers(at); for(int i=0; i< _nparms(p); i++) { doublevar parm; int k=klm(i,0), el=klm(i,1), m=klm(i,2); if(fabs(eibasis(e,at,k,0)) > tiny || fabs(eibasis(e,at,el,0)) > tiny) { for(int j=0; j< e; j++) { s=(j < nspin_up) != (e < nspin_up); parm=unique_parameters_spin(s)(p,i); doublevar vkl=parm*(eibasis(e,at,k,0)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,0) ); lap(e,at,0)+=vkl*eebasis(j,m,0); } for(int j=e+1; j< nelectrons; j++) { s=(j < nspin_up) != (e < nspin_up); parm=unique_parameters_spin(s)(p,i); doublevar vkl=parm*(eibasis(e,at,k,0)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,0) ); lap(e,at,0)+=vkl*eebasis(j,m,0); } } } } }
///< The function evaluates the value of Y_l_m(p) coefficient up to lmax band. ///< coeffs array should have at least NumShTerms(lmax) elements. void ShEvaluate(float3 const& p, int lmax, float* coefs) { // Initialize the array by the values of Legendre polynomials EvaluateLegendrePolynomial(p.z, lmax, coefs); // Normalization coefficients std::vector<float> klm(NumShTerms(lmax)); for (int l = 0; l <= lmax; ++l) { for (int m = -l; m <= l; ++m) { klm[ShIndex(l, m)] = K(l, m); } } // Calculate cos(mphi) and sin(mphi) values std::vector<float> cosmphi(lmax + 1); std::vector<float> sinmphi(lmax + 1); float xylen = std::sqrt(std::max(0.f, 1.f - p.z*p.z)); // If degenerate set to 0 and 1 if (xylen == 0.f) { for (int i = 0; i <= lmax; ++i) { sinmphi[i] = 0.f; cosmphi[i] = 1.f; } } else { SinCosIndexed(p.y / xylen, p.x / xylen, lmax+1, &sinmphi[0], &cosmphi[0]); } // Multiply in normalization coeffs and sin and cos where needed const float sqrt2 = std::sqrt(2.f); for (int l = 0; l <= lmax; ++l) { // For negative multiply by sin and Klm for (int m = -l; m < 0; ++m) { coefs[ShIndex(l, m)] = sqrt2 * klm[ShIndex(l, m)] * coefs[ShIndex(l, -m)] * sinmphi[-m]; } // For 0 multiply by Klm coefs[ShIndex(l, 0)] *= klm[ShIndex(l, 0)]; // For positive multiply by cos and Klm for (int m = 1; m <= l; ++m) { coefs[ShIndex(l, m)] *= sqrt2 * klm[ShIndex(l, m)] * cosmphi[m]; } } }
void Jastrow_threebody_piece_diffspin::updateLap_E_I(int e, const Array4 <doublevar> & eibasis, const Array3 <doublevar> & eebasis, Array3 <doublevar> & lap) { //cout << "Jastrow_threebody_piece::updateLap_E_I" << endl; int natoms=parm_centers.GetDim(0); int nelectrons=eebasis.GetDim(0); if(eebasis.GetDim(1)<eebasis_max) error("Need more eebasis functions in three-body spin"); assert(lap.GetDim(2) >= 5); assert(lap.GetDim(0) >= nelectrons); assert(eibasis.GetDim(1) >= parm_centers.GetDim(0)); assert(lap.GetDim(1) >= natoms); Array1 <doublevar> vkl_e(5); //derivative wrt e of a_e a_j + a_j a_e Array1 <doublevar> vkl_j(5); //wrt j int s; const doublevar tiny=1e-14; //cout << "updateLap " << endl; for(int at=0; at < natoms; at++) { int p=parm_centers(at); for(int i=0; i< _nparms(p); i++) { doublevar parm; int k=klm(i,0), el=klm(i,1), m=klm(i,2); if(fabs(eibasis(e,at,k,0)) > tiny || fabs(eibasis(e,at,el,0)) > tiny) { for(int j=0; j< e; j++) { s=(j < nspin_up) != (e < nspin_up); parm=unique_parameters_spin(s)(p,i); doublevar vkl=parm*(eibasis(e,at,k,0)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,0) ); for(int d=1; d< 5; d++) { vkl_e[d]=parm*(eibasis(e,at,k,d)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,d) ); vkl_j[d]=parm*(eibasis(e,at,k,0)*eibasis(j,at,el,d) //+eibasis(j,at,k,d)*eibasis(e,at,el,0) ); } lap(e,at,0)+=vkl*eebasis(j,m,0); doublevar dot_e=0, dot_j=0; for(int d=1; d< 4; d++) { lap(e,at,d)+=vkl_e[d]*eebasis(j,m,0); lap(e,at,d)-=vkl*eebasis(j,m,d); lap(j,at,d)+=vkl_j[d]*eebasis(j,m,0); lap(j,at,d)+=vkl*eebasis(j,m,d); dot_e+=vkl_e[d]*eebasis(j,m,d); dot_j+=vkl_j[d]*eebasis(j,m,d); } lap(e,at,4)+=vkl*eebasis(j,m,4); lap(j,at,4)+=vkl*eebasis(j,m,4); lap(e,at,4)+=vkl_e[4]*eebasis(j,m,0); lap(j,at,4)+=vkl_j[4]*eebasis(j,m,0); lap(e,at,4)-=2*dot_e; lap(j,at,4)+=2*dot_j; } for(int j=e+1; j< nelectrons; j++) { s=(j < nspin_up) != (e < nspin_up); parm=unique_parameters_spin(s)(p,i); doublevar vkl=parm*(eibasis(e,at,k,0)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,0) ); for(int d=1; d< 5; d++) { vkl_e[d]=parm*(eibasis(e,at,k,d)*eibasis(j,at,el,0) //+eibasis(j,at,k,0)*eibasis(e,at,el,d) ); vkl_j[d]=parm*(eibasis(e,at,k,0)*eibasis(j,at,el,d) //+eibasis(j,at,k,d)*eibasis(e,at,el,0) ); } lap(e,at,0)+=vkl*eebasis(j,m,0); doublevar dot_e=0, dot_j=0; for(int d=1; d< 4; d++) { lap(e,at,d)+=vkl_e[d]*eebasis(j,m,0); lap(e,at,d)+=vkl*eebasis(j,m,d); lap(j,at,d)+=vkl_j[d]*eebasis(j,m,0); lap(j,at,d)-=vkl*eebasis(j,m,d); dot_e+=vkl_e[d]*eebasis(j,m,d); dot_j+=vkl_j[d]*eebasis(j,m,d); } lap(e,at,4)+=vkl*eebasis(j,m,4); lap(j,at,4)+=vkl*eebasis(j,m,4); lap(e,at,4)+=vkl_e[4]*eebasis(j,m,0); lap(j,at,4)+=vkl_j[4]*eebasis(j,m,0); lap(e,at,4)+=2*dot_e; lap(j,at,4)-=2*dot_j; } } } } //cout<<"Done"<<endl; }
int Jastrow_threebody_piece_diffspin::make_default_list() { klm.Resize(12,3); klm(0,0)=1; klm(0,1)=1; klm(0,2)=0; klm(1,0)=1; klm(1,1)=0; klm(1,2)=1; klm(2,0)=1; klm(2,1)=1; klm(2,2)=1; klm(3,0)=2; klm(3,1)=2; klm(3,2)=0; klm(4,0)=2; klm(4,1)=0; klm(4,2)=1; klm(5,0)=2; klm(5,1)=0; klm(5,2)=2; klm(6,0)=2; klm(6,1)=2; klm(6,2)=2; klm(7,0)=3; klm(7,1)=3; klm(7,2)=0; klm(8,0)=3; klm(8,1)=0; klm(8,2)=2; klm(9,0)=3; klm(9,1)=3; klm(9,2)=2; klm(10,0)=1; klm(10,1)=2; klm(10,2)=2; klm(11,0)=2; klm(11,1)=3; klm(11,2)=2; return 12; }
void Jastrow_threebody_piece_diffspin::set_up(vector <string> & words, System * sys) { //cout <<"Start Jastrow_threebody_piece_diffspin::set_up"<<endl; vector<string> atomnames; sys->getAtomicLabels(atomnames); unique_parameters_spin.Resize(2); linear_parms.Resize(2); int tmpcounter=0; for(int s=0;s<unique_parameters_spin.GetSize();s++){ get_onebody_parms_diffspin(words, atomnames, unique_parameters_spin(s),s, _nparms, parm_labels, linear_parms(s), tmpcounter, parm_centers); } if(unique_parameters_spin(0).GetDim(0)!=unique_parameters_spin(1).GetDim(0)) error("Need same amount of LIKE_COEFFICIENTS and UNLIKE_COEFFICIENTS sections in three body"); if(unique_parameters_spin(0).GetDim(1)!=unique_parameters_spin(1).GetDim(1)) error("Need same amount of LIKE_COEFFICIENTS and UNLIKE_COEFFICIENTS parameters in three body"); unsigned int pos=0; int maxnparms=0; vector <string> klm_list; if(readsection(words,pos=0,klm_list,"SM_TERMS")) { if(klm_list.size()%3 !=0) error("SM_TERMS must contain a multiple of 3 elements"); maxnparms=klm_list.size()/3; int counter=0; klm.Resize(maxnparms,3); for(int i=0; i< maxnparms; i++) { for(int j=0; j< 3; j++) { klm(i,j)=atoi(klm_list[counter++].c_str()); } } } else maxnparms=make_default_list(); int natoms=atomnames.size(); eebasis_max=0; eibasis_max.Resize(natoms); eibasis_max=0; for(int at=0; at< natoms; at++) { if(nparms(at) > maxnparms) error("too many three-body spin parameters on ", atomnames[at]); for(int p=0; p < nparms(at); p++) { if(eibasis_max(at) <= klm(p,0)) eibasis_max(at)=klm(p,0)+1; if(eibasis_max(at) <= klm(p,1)) eibasis_max(at)=klm(p,1)+1; if(eebasis_max <= klm(p,2)) eebasis_max=klm(p,2)+1; } } freeze=haskeyword(words, pos=0, "FREEZE"); nspin_up=sys->nelectrons(0); nelectrons=sys->nelectrons(0)+sys->nelectrons(1); //cout <<"End Jastrow_threebody_piece_diffspin::set_up"<<endl; }