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

📄 orthog.cc

📁 大型并行量子化学软件;支持密度泛函(DFT)。可以进行各种量子化学计算。支持CHARMM并行计算。非常具有应用价值。
💻 CC
字号:
//// orthog.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@ca.sandia.gov>// 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.//#ifdef __GNUC__#pragma implementation#endif#include <stdlib.h>#include <math.h>#include <iostream>#include <chemistry/qc/basis/orthog.h>#include <math/scmat/elemop.h>#include <math/scmat/blocked.h>using namespace std;using namespace sc;OverlapOrthog::OverlapOrthog(  OrthogMethod method,  const RefSymmSCMatrix &overlap,  const Ref<SCMatrixKit> &result_kit,  double lindep_tolerance,  int debug){  reinit(method,overlap,result_kit,lindep_tolerance,debug);}voidOverlapOrthog::reinit(  OrthogMethod method,  const RefSymmSCMatrix &overlap,  const Ref<SCMatrixKit> &result_kit,  double lindep_tolerance,  int debug){  orthog_method_ = method;  overlap_ = overlap;  lindep_tol_ = lindep_tolerance;  debug_ = debug;  dim_ = overlap_.dim();  result_kit_ = result_kit;}Ref<OverlapOrthog>OverlapOrthog::copy() const{  Ref<OverlapOrthog> orthog    = new OverlapOrthog(orthog_method_,                        overlap_,                        result_kit_,                        lindep_tol_,                        debug_);  orthog->orthog_trans_ = orthog_trans_.copy();  orthog->orthog_trans_inverse_ = orthog_trans_inverse_.copy();  orthog->orthog_dim_ = orthog_dim_;  orthog->min_orthog_res_ = min_orthog_res_;  orthog->max_orthog_res_ = max_orthog_res_;  return orthog;}// computes intermediates needed to form orthogonalization matrices// and their inverses.voidOverlapOrthog::compute_overlap_eig(RefSCMatrix& overlap_eigvec,                    RefDiagSCMatrix& overlap_isqrt_eigval,                    RefDiagSCMatrix& overlap_sqrt_eigval){  // first calculate S  RefSymmSCMatrix M = overlap_;  // Diagonalize M to get m and U  RefSCMatrix U(M.dim(), M.dim(), M.kit());  RefDiagSCMatrix m(M.dim(), M.kit());  M.diagonalize(m,U);  M = 0;  Ref<SCElementMaxAbs> maxabsop = new SCElementMaxAbs;  m.element_op(maxabsop.pointer());  double maxabs = maxabsop->result();  double s_tol = lindep_tol_ * maxabs;  double minabs = maxabs;  BlockedDiagSCMatrix *bm = dynamic_cast<BlockedDiagSCMatrix*>(m.pointer());  bool blocked;  int nblocks;  if (bm == 0) {    blocked = false;    nblocks = 1;    }  else {    blocked = true;    nblocks = bm->nblocks();    }  int i, j;  double *pm_sqrt = new double[m->dim()->n()];  double *pm_isqrt = new double[m->dim()->n()];  int *pm_index = new int[m->dim()->n()];  int *nfunc = new int[nblocks];  int nfunctot = 0;  int nlindep = 0;  for (i=0; i<nblocks; i++) {      nfunc[i] = 0;      if (blocked && bm->block(i).null()) continue;      int n;      if (blocked) n = bm->block(i)->dim()->n();      else n = m->dim()->n();      double *pm = new double[n];      if (blocked) bm->block(i)->convert(pm);      else m->convert(pm);      for (j=0; j<n; j++) {          if (pm[j] > s_tol) {              if (pm[j] < minabs) { minabs = pm[j]; }              pm_sqrt[nfunctot] = sqrt(pm[j]);              pm_isqrt[nfunctot] = 1.0/pm_sqrt[nfunctot];              pm_index[nfunctot] = j;              nfunc[i]++;              nfunctot++;            }          else if (orthog_method_ == Symmetric) {              pm_sqrt[nfunctot] = 0.0;              pm_isqrt[nfunctot] = 0.0;              pm_index[nfunctot] = j;              nfunc[i]++;              nfunctot++;              nlindep++;            }          else {              nlindep++;            }        }      delete[] pm;    }  if (nlindep > 0 && orthog_method_ == Symmetric) {    ExEnv::out0() << indent                 << "WARNING: " << nlindep                 << " basis function"                 << (dim_.n()-orthog_dim_.n()>1?"s":"")                 << " ignored in symmetric orthogonalization."                 << endl;  }  // make sure all nodes end up with exactly the same data  MessageGrp::get_default_messagegrp()->bcast(nfunctot);  MessageGrp::get_default_messagegrp()->bcast(nfunc, nblocks);  MessageGrp::get_default_messagegrp()->bcast(pm_sqrt,nfunctot);  MessageGrp::get_default_messagegrp()->bcast(pm_isqrt,nfunctot);  MessageGrp::get_default_messagegrp()->bcast(pm_index,nfunctot);  if (orthog_method_ == Symmetric) {    orthog_dim_ = new SCDimension(m->dim()->blocks(),                                  "ortho basis (symmetric)");    }  else {      orthog_dim_ = new SCDimension(nfunctot, nblocks,                                nfunc, "ortho basis (canonical)");      for (i=0; i<nblocks; i++) {        orthog_dim_->blocks()->set_subdim(i, new SCDimension(nfunc[i]));      }    }  overlap_eigvec = result_kit_->matrix(dim_, orthog_dim_);  if (orthog_method_ == Symmetric) {      overlap_eigvec.assign(U);    }  else {      BlockedSCMatrix *bev          = dynamic_cast<BlockedSCMatrix*>(overlap_eigvec.pointer());      BlockedSCMatrix *bU          = dynamic_cast<BlockedSCMatrix*>(U.pointer());      int ifunc = 0;      for (i=0; i<bev->nblocks(); i++) {          if (bev->block(i).null()) continue;          for (j=0; j<nfunc[i]; j++) {              RefSCVector col = bU->block(i)->get_column(pm_index[ifunc]);              bev->block(i)->assign_column(col,j);              col = 0;              ifunc++;            }        }    }  overlap_sqrt_eigval = result_kit_->diagmatrix(orthog_dim_);  overlap_sqrt_eigval->assign(pm_sqrt);  overlap_isqrt_eigval = result_kit_->diagmatrix(orthog_dim_);  overlap_isqrt_eigval->assign(pm_isqrt);  delete[] nfunc;  delete[] pm_sqrt;  delete[] pm_isqrt;  delete[] pm_index;    max_orthog_res_ = maxabs;  min_orthog_res_ = minabs;  if (debug_ > 1) {    overlap_.print("S");    overlap_eigvec.print("S eigvec");    overlap_isqrt_eigval.print("s^(-1/2) eigval");    overlap_sqrt_eigval.print("s^(1/2) eigval");  }}voidOverlapOrthog::compute_symmetric_orthog(){  RefSCMatrix overlap_eigvec;  RefDiagSCMatrix overlap_isqrt_eigval;  RefDiagSCMatrix overlap_sqrt_eigval;  compute_overlap_eig(overlap_eigvec,                      overlap_isqrt_eigval,                      overlap_sqrt_eigval);  orthog_trans_ = overlap_eigvec    * overlap_isqrt_eigval    * overlap_eigvec.t();  orthog_trans_inverse_ = overlap_eigvec    * overlap_sqrt_eigval    * overlap_eigvec.t();}voidOverlapOrthog::compute_canonical_orthog(){  RefSCMatrix overlap_eigvec;  RefDiagSCMatrix overlap_isqrt_eigval;  RefDiagSCMatrix overlap_sqrt_eigval;  compute_overlap_eig(overlap_eigvec,                      overlap_isqrt_eigval,                      overlap_sqrt_eigval);  orthog_trans_ = overlap_isqrt_eigval * overlap_eigvec.t();  orthog_trans_inverse_ = overlap_eigvec * overlap_sqrt_eigval;}voidOverlapOrthog::compute_gs_orthog(){  // Orthogonalize each subblock of the overlap.  max_orthog_res_ = 1.0;  min_orthog_res_ = 1.0;  BlockedSymmSCMatrix *S    = dynamic_cast<BlockedSymmSCMatrix *>(overlap_.pointer());  int nblock = S->nblocks();  Ref<BlockedSCMatrixKit> kit    = dynamic_cast<BlockedSCMatrixKit*>(S->kit().pointer());  Ref<SCMatrixKit> subkit = kit->subkit();  RefSCMatrix *blockorthogs = new RefSCMatrix[nblock];  int *nblockorthogs = new int[nblock];  int northog = 0;  for (int i=0; i<nblock; i++) {    RefSymmSCMatrix Sblock = S->block(i);    if (Sblock.null()) {      blockorthogs[i] = 0;      nblockorthogs[i] = 0;      continue;      }    RefSCDimension dim = Sblock->dim();    RefSCMatrix blockorthog(dim,dim,subkit);    blockorthog->unit();    double res;    int nblockorthog = blockorthog->schmidt_orthog_tol(Sblock, lindep_tol_,                                                       &res);    if (res < min_orthog_res_) min_orthog_res_ = res;    blockorthogs[i] = blockorthog;    nblockorthogs[i] = nblockorthog;    northog += nblockorthog;  }  // Construct the orthog basis SCDimension object.  Ref<SCBlockInfo> blockinfo    = new SCBlockInfo(northog, nblock, nblockorthogs);  for (int i=0; i<nblock; i++) {    blockinfo->set_subdim(i, new SCDimension(nblockorthogs[i]));  }  orthog_dim_ = new SCDimension(blockinfo, "ortho (Gram-Schmidt)");  // Replace each blockorthog by a matrix with only linear independent columns  for (int i=0; i<nblock; i++) {    if (nblockorthogs[i] == 0) continue;    RefSCMatrix old_blockorthog = blockorthogs[i];    blockorthogs[i] = subkit->matrix(dim_->blocks()->subdim(i),                                     orthog_dim_->blocks()->subdim(i));    blockorthogs[i].assign_subblock(old_blockorthog,                                    0, dim_->blocks()->subdim(i).n()-1,                                    0, orthog_dim_->blocks()->subdim(i).n()-1);  }  // Compute the inverse of each orthogonalization block.  RefSCMatrix *inverse_blockorthogs = new RefSCMatrix[nblock];  for (int i=0; i<nblock; i++) {    if (nblockorthogs[i] == 0) {      inverse_blockorthogs[i] = 0;      }    else {      inverse_blockorthogs[i] = blockorthogs[i].gi();      }  }  // Construct the complete transformation matrices  orthog_trans_ = result_kit_->matrix(dim_, orthog_dim_);  orthog_trans_inverse_ = result_kit_->matrix(orthog_dim_, dim_);  orthog_trans_.assign(0.0);  orthog_trans_inverse_.assign(0.0);  BlockedSCMatrix *X    = dynamic_cast<BlockedSCMatrix*>(orthog_trans_.pointer());  BlockedSCMatrix *Xi    = dynamic_cast<BlockedSCMatrix*>(orthog_trans_inverse_.pointer());  for (int i=0; i<nblock; i++) {    if (nblockorthogs[i] == 0) continue;    int nrow = blockorthogs[i].rowdim().n();    int ncol = blockorthogs[i].coldim().n();    X->block(i).assign_subblock(blockorthogs[i],                                0, nrow-1, 0, ncol-1,                                0, 0);    Xi->block(i).assign_subblock(inverse_blockorthogs[i],                                 0, ncol-1, 0, nrow-1,                                 0, 0);  }  orthog_trans_ = orthog_trans_.t();  orthog_trans_inverse_ = orthog_trans_inverse_.t();  delete[] blockorthogs;  delete[] inverse_blockorthogs;  delete[] nblockorthogs;}voidOverlapOrthog::compute_orthog_trans(){  switch(orthog_method_) {  case GramSchmidt:    ExEnv::out0() << indent                 << "Using Gram-Schmidt orthogonalization."                 << endl;    compute_gs_orthog();    break;  case Symmetric:    compute_symmetric_orthog();    ExEnv::out0() << indent                 << "Using symmetric orthogonalization."                 << endl;    break;  case Canonical:    compute_canonical_orthog();    ExEnv::out0() << indent                 << "Using canonical orthogonalization."                 << endl;    break;  default:    ExEnv::outn() << "OverlapOrthog::compute_orthog_trans(): bad orthog method"                 << endl;    abort();  }  ExEnv::out0() << indent               << "n(basis): ";  for (int i=0; i<dim_->blocks()->nblock(); i++) {    ExEnv::out0() << scprintf(" %5d", dim_->blocks()->size(i));  }  ExEnv::out0() << endl;  if (dim_.n() != orthog_dim_.n()) {    ExEnv::out0() << indent                 << "n(orthog basis): ";    for (int i=0; i<orthog_dim_->blocks()->nblock(); i++) {      ExEnv::out0() << scprintf(" %5d", orthog_dim_->blocks()->size(i));      }    ExEnv::out0() << endl;    ExEnv::out0() << indent                 << "WARNING: " << dim_.n() - orthog_dim_.n()                 << " basis function"                 << (dim_.n()-orthog_dim_.n()>1?"s":"")                 << " discarded."                 << endl;    }  ExEnv::out0() << indent               << "Maximum orthogonalization residual = "               << max_orthog_res_ << endl               << indent               << "Minimum orthogonalization residual = "               << min_orthog_res_ << endl;  if (debug_ > 0) {    dim_.print();    orthog_dim_.print();    if (debug_ > 1) {      orthog_trans_.print("basis to orthog basis");      orthog_trans_inverse_.print("basos to orthog basis inverse");      (orthog_trans_*overlap_       *orthog_trans_.t()).print("X*S*X'",ExEnv::out0(),14);      (orthog_trans_inverse_.t()*overlap_.gi()       *orthog_trans_inverse_).print("X'^(-1)*S^(-1)*X^(-1)",                                     ExEnv::out0(),14);      (orthog_trans_       *orthog_trans_inverse_).print("X*X^(-1)",ExEnv::out0(),14);    }  }}// returns the orthogonalization matrixRefSCMatrixOverlapOrthog::basis_to_orthog_basis(){  if (orthog_trans_.null()) {    compute_orthog_trans();  }  return orthog_trans_;}RefSCMatrixOverlapOrthog::basis_to_orthog_basis_inverse(){  if (orthog_trans_inverse_.null()) {    compute_orthog_trans();  }  return orthog_trans_inverse_;}RefSCDimensionOverlapOrthog::dim(){  return dim_;}RefSCDimensionOverlapOrthog::orthog_dim(){  if (orthog_dim_.null()) compute_orthog_trans();  return orthog_dim_;}/////////////////////////////////////////////////////////////////////////////// Local Variables:// mode: c++// c-file-style: "CLJ-CONDENSED"// End:

⌨️ 快捷键说明

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