⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transform.cc

📁 大型并行量子化学软件;支持密度泛函(DFT)。可以进行各种量子化学计算。支持CHARMM并行计算。非常具有应用价值。
💻 CC
字号:
//// transform.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB.  If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#if defined(__GNUC__)#pragma implementation#endif#include <stdlib.h>#include <string.h>#include <math.h>#include <float.h>#include <util/misc/formio.h>#include <math/scmat/matrix.h>#include <math/scmat/repl.h>#include <chemistry/qc/basis/transform.h>using namespace std;using namespace sc;#undef DEBUG////////////////////////////////////////////////////////////////////////////// Utility classes and routines to generate cartesian to pure transformation// matrices.class SafeUInt {  private:    unsigned long i_;  public:    SafeUInt(): i_(0) {}    SafeUInt(unsigned long i): i_(i) {}    void error() const {      ExEnv::errn() << "SafeUInt: integer size exceeded" << endl;      abort();    }    SafeUInt &operator ++ () { i_++; return *this; }    SafeUInt &operator ++ (int) { i_++; return *this; }    operator double() const { return i_; }    operator unsigned long() const { return i_; }    SafeUInt &operator =(const SafeUInt &i) { i_ = i.i_; return *this; }    int operator > (const SafeUInt& i) const { return i_>i.i_; }    int operator >= (const SafeUInt& i) const { return i_>=i.i_; }    int operator < (const SafeUInt& i) const { return i_<i.i_; }    int operator <= (const SafeUInt& i) const { return i_<=i.i_; }    int operator == (const SafeUInt& i) const { return i_==i.i_; }    int operator == (unsigned long i) const { return i_==i; }    int operator != (const SafeUInt& i) const { return i_!=i.i_; }    SafeUInt operator / (const SafeUInt& i) const { return SafeUInt(i_/i.i_); }    SafeUInt operator % (const SafeUInt& i) const { return SafeUInt(i_%i.i_); }    SafeUInt operator * (unsigned long i) const    {      unsigned long tmp = i_*i;      if (tmp/i != i_ || tmp%i != 0) {          error();        }      return SafeUInt(tmp);    }    SafeUInt operator * (const SafeUInt& i) const    {      return this->operator*(i.i_);    }    SafeUInt &operator = (unsigned long i) { i_ = i; return *this; }    SafeUInt &operator *= (unsigned long i) { *this = *this*i; return *this; }    SafeUInt &operator /= (unsigned long i) { i_ /= i; return *this; }};// there ordering here is arbitrary and doesn't have to match the// basis set orderingstatic inline int ncart(int l) { return (l>=0)?((((l)+2)*((l)+1))>>1):0; }static inline int npure(int l) { return 2*l+1; }static inline int icart(int a, int b, int c){  return (((((a+b+c+1)<<1)-a)*(a+1))>>1)-b-1;}static inline int ipure(int l, int m) { return m<0?2*-m:(m==0?0:2*m-1); }static inline int local_abs(int i) { return i<0? -i:i; }SafeUIntbinomial(int n, int c1){  SafeUInt num = 1;  SafeUInt den = 1;  int c2 = n - c1;  int i;  for (i=c2+1; i<=n; i++) {      num *= i;    }  for (i=2; i<=c1; i++) {      den *= i;    }  return num/den;}SafeUIntfact(int n){  SafeUInt r = 1;  for (int i=2; i<=n; i++) {      r *= i;    }  return r;}// compute nnum!/nden!, nden <= nnumSafeUIntfactoverfact(int nnum,int nden){  SafeUInt r = 1;  for (int i=nden+1; i<=nnum; i++) {      r *= i;    }  return r;}SafeUIntfactfact(int n){  SafeUInt result;  int i;  result = 1;  if (n&1) {      for (i=3; i<=n; i+=2) {          result *= i;        }    }  else {      for (i=2; i<=n; i+=2) {          result *= i;        }    }  return result;}voidreduce(SafeUInt &num, SafeUInt &den){  if (num > den) {      for (SafeUInt i=2; i<=den;) {          if (num%i == 0UL && den%i == 0UL) {              num /= i;              den /= i;            }          else i++;        }    }  else {      for (SafeUInt i=2; i<=num;) {          if (num%i == 0UL && den%i == 0UL) {              num /= i;              den /= i;            }          else i++;        }    }}SafeUIntpowll(SafeUInt n, unsigned long p){  SafeUInt result = 1;  for (unsigned long i=0; i<p; i++) result *= n;  return result;}////////////////////////////////////////////////////////////////////////////// SphericalTransform classSphericalTransform::SphericalTransform(){  n_ = 0;  l_ = 0;  subl_ = 0;  components_ = 0;}SphericalTransform::SphericalTransform(int l, int subl) : l_(l){  n_ = 0;  if (subl == -1) subl_ = l;  else subl_ = subl;  components_ = 0;}static voidsolidharmcontrib(int sign,                 const SafeUInt &bin,const SafeUInt &den,                 SafeUInt norm2num,SafeUInt norm2den,                 int r2,int x,int y,int z,                 const RefSCMatrix &coefmat, int pureindex){  if (r2>0) {      solidharmcontrib(sign,bin,den,norm2num,norm2den,r2-1,x+2,y,z,                       coefmat,pureindex);      solidharmcontrib(sign,bin,den,norm2num,norm2den,r2-1,x,y+2,z,                       coefmat,pureindex);      solidharmcontrib(sign,bin,den,norm2num,norm2den,r2-1,x,y,z+2,                       coefmat,pureindex);    }  else {      double coef = sign*double(bin)/double(den);      double norm = sqrt(double(norm2num)/double(norm2den));      coefmat->accumulate_element(icart(x,y,z), pureindex, coef*norm);#ifdef DEBUG      ExEnv::outn().form("    add(%d,%d,%d, % 4ld.0",                x,y,z, sign*long(bin));      if (den!=1) {          ExEnv::outn().form("/%-4.1f",double(den));        }      else {          ExEnv::outn().form("     ");        }      if (norm2num != 1 || norm2den != 1) {          ExEnv::outn().form(" * sqrt(%ld.0/%ld.0)",                    long(norm2num), long(norm2den));        }      ExEnv::outn().form(", i);");      ExEnv::outn() << endl;#endif    }}// l is the total angular momentum// m is the z component// r2 is the number of factors of r^2 that are includedstatic voidsolidharm(unsigned int l, int m, unsigned int r2, RefSCMatrix coefmat){  int pureindex = ipure(l,m);  for (unsigned int i=1; i<=r2; i++) pureindex += npure(l+2*i);    unsigned int absm = local_abs(m);  // the original norm2num and norm2den computation overflows 32bits for l=7  //SafeUInt norm2num = factoverfact(l+absm,l-absm);  //if (m != 0) norm2num *= 2;  //SafeUInt normden = factfact(2*absm)*binomial(l,absm);  //SafeUInt norm2den = normden*norm2den;  //reduce(norm2num,norm2den);  // this overflows 32bits for l=9  SafeUInt norm2num = factoverfact(l+absm,l);  SafeUInt norm2den = factoverfact(l,l-absm);  reduce(norm2num,norm2den);  norm2num *= fact(absm);  norm2den *= factfact(2*absm);  reduce(norm2num,norm2den);  norm2num *= fact(absm);  norm2den *= factfact(2*absm);  if (m != 0) norm2num *= 2;  reduce(norm2num,norm2den);#ifdef DEBUG  ExEnv::outn().form("    // l=%2d m=% 2d",l,m);  ExEnv::outn() << endl;#endif  for (unsigned int t=0; t <= (l - absm)/2; t++) {      for (unsigned int u=0; u<=t; u++) {          int v2m;          if (m >= 0) v2m = 0;          else v2m = 1;          for (unsigned int v2 = v2m; v2 <= absm; v2+=2) {              int x = 2*t + absm - 2*u - v2;              int y = 2*u + v2;              int z = l - x - y;              SafeUInt bin = binomial(l,t)                               *binomial(l-t,absm+t)                               *binomial(t,u)                               *binomial(absm,v2);              SafeUInt den = powll(4,t);              int sign;              if ((t + (v2-v2m)/2)%2) sign = -1;              else sign = 1;              reduce(bin,den);              solidharmcontrib(sign,bin,den,norm2num,norm2den,                               r2,x,y,z,coefmat,pureindex);            }        }    }#ifdef DEBUG  ExEnv::outn() << "    i++;" << endl;#endif}static voidsolidharm(int l, const RefSCMatrix &coefmat){  solidharm(l,0,0,coefmat);  for (int m=1; m<=l; m++) {      solidharm(l, m,0,coefmat);      solidharm(l,-m,0,coefmat);    }  for (int r=2; r<=l; r+=2) {      solidharm(l-r,0,r/2,coefmat);      for (int m=1; m<=l-r; m++) {          solidharm(l-r, m,r/2,coefmat);          solidharm(l-r,-m,r/2,coefmat);        }    }#ifdef DEBUG  ExEnv::outn() << coefmat;#endif}voidSphericalTransform::init(){  Ref<SCMatrixKit> matrixkit = new ReplSCMatrixKit;  RefSCDimension cartdim(new SCDimension(ncart(l_)));  RefSCMatrix coefmat(cartdim,cartdim,matrixkit);  coefmat->assign(0.0);  solidharm(l_,coefmat);#ifdef DEBUG  ExEnv::outn() << scprintf("---> generating l=%d subl=%d", l_, subl_) << endl;#endif  int pureoffset = 0;  for (int i=1; i<=(l_-subl_)/2; i++) pureoffset += npure(subl_+2*i);  for (int p=0; p<npure(subl_); p++) {    for (int a=0; a<=l_; a++) {      for (int b=0; (a+b)<=l_; b++) {        int c = l_ - a - b;        int cart = icart(a,b,c);        double coef = coefmat->get_element(cart,p+pureoffset);        if (fabs(coef) > DBL_EPSILON) {          add(a,b,c, coef, p);#ifdef DEBUG          ExEnv::outn() << scprintf("---> add(%d,%d,%d, %12.8f, %d)",                           a,b,c,coef,p) << endl;#endif        }      }    }  }}SphericalTransform::~SphericalTransform(){  if (components_) {    delete[] components_;    components_ = 0;  }}voidSphericalTransform::add(int a, int b, int c, double coef, int pureindex){  int i;  SphericalTransformComponent *ncomp = new_components();  for (i=0; i<n_; i++)    ncomp[i] = components_[i];  ncomp[i].init(a, b, c, coef, pureindex);  delete[] components_;  components_ = ncomp;  n_++;}///////////////////////////////////////////////////////////////////////////ISphericalTransform::ISphericalTransform() :  SphericalTransform(){}ISphericalTransform::ISphericalTransform(int l,int subl) :  SphericalTransform(l,subl){}voidISphericalTransform::init(){  Ref<SCMatrixKit> matrixkit = new ReplSCMatrixKit;  RefSCDimension cartdim(new SCDimension(ncart(l_)));  RefSCMatrix coefmat(cartdim,cartdim,matrixkit);  coefmat->assign(0.0);  solidharm(l_,coefmat);  coefmat->invert_this();  coefmat->transpose_this();#ifdef DEBUG  ExEnv::outn() << scprintf("---> IST: generating l=%d subl=%d", l_, subl_) << endl;#endif  int pureoffset = 0;  for (int i=1; i<=(l_-subl_)/2; i++) pureoffset += npure(subl_+2*i);  for (int p=0; p<npure(subl_); p++) {    for (int a=0; a<=l_; a++) {      for (int b=0; (a+b)<=l_; b++) {        int c = l_ - a - b;        int cart = icart(a,b,c);        double coef = coefmat->get_element(cart,p+pureoffset);        if (fabs(coef) > DBL_EPSILON) {          add(a,b,c, coef, p);#ifdef DEBUG          ExEnv::outn() << scprintf("---> IST: add(%d,%d,%d, %12.8f, %d)",                           a,b,c,coef,p) << endl;#endif        }      }    }  }}///////////////////////////////////////////////////////////////////////////SphericalTransformIter::SphericalTransformIter(){  transform_=0;}SphericalTransformIter::SphericalTransformIter(const SphericalTransform*t){  transform_ = t;}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "ETS"// End:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -