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);
	}
      }
    }
  }
}
示例#5
0
文件: sh.cpp 项目: yozhijk/Banshee
///< 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;  

}