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

📄 scfvector.cc

📁 大型并行量子化学软件;支持密度泛函(DFT)。可以进行各种量子化学计算。支持CHARMM并行计算。非常具有应用价值。
💻 CC
字号:
//// scfvector.cc --- implementation of SCF::compute_vector//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Edward Seidl <seidl@janed.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.//#include <unistd.h>#include <stdlib.h>#include <util/misc/timer.h>#include <util/misc/formio.h>#include <util/state/state_bin.h>#include <util/group/mstate.h>#include <math/scmat/offset.h>#include <math/scmat/blocked.h>#include <math/scmat/blkiter.h>#include <math/optimize/diis.h>#include <math/optimize/scextrapmat.h>#include <chemistry/qc/basis/symmint.h>#include <chemistry/qc/scf/scf.h>#include <chemistry/qc/scf/scfops.h>#include <chemistry/qc/scf/scflocal.h>#include <errno.h>using namespace std;using namespace sc;#undef GENERALIZED_EIGENSOLVERnamespace sc {///////////////////////////////////////////////////////////////////////////extern "C" {  void  dsygv_(int *ITYPE, const char *JOBZ, const char *UPLO,         int *N, double *A, int *LDA, double *B, int *LDB,         double *W, double *WORK, int *LWORK, int *INFO);}voidSCF::savestate_iter(int iter){  char *ckptfile=0, *oldckptfile=0;  const char *devnull=0;  const char *filename=0;   bool savestate = if_to_checkpoint();  int savestate_freq = checkpoint_freq();    if (savestate && ( (iter+1)%savestate_freq==0) ) {    devnull = "/dev/null";    filename = checkpoint_file();    if (scf_grp_->me() == 0) {      ckptfile = new char[strlen(filename)+10];      sprintf(ckptfile,"%s.%d.tmp",filename,iter+1);      oldckptfile = new char[strlen(filename)+10];      sprintf(oldckptfile,"%s.%d.tmp",filename,(iter+1-savestate_freq));    }    else {      ckptfile = new char[strlen(devnull)+1];      strcpy(ckptfile, devnull);    }    // save temporary checkpoint file after each SCF iteration    StateOutBin so(ckptfile);    save_state(this,so);    if (scf_grp_->me() == 0) {      if (oldckptfile != NULL && (iter+1-savestate_freq)>=savestate_freq) {        if (unlink(oldckptfile))           ExEnv::out0() << " SCF::compute_vector() Temporary "                        << "checkpoint file failed to delete. " << endl;      }      delete [] oldckptfile;    }    delete [] ckptfile;    so.close();    free((void*)filename);  }}doubleSCF::compute_vector(double& eelec){  tim_enter("vector");  int i;  // reinitialize the extrapolation object  extrap_->reinitialize();    // create level shifter  LevelShift *level_shift = new LevelShift(this);  level_shift->reference();    // calculate the core Hamiltonian  hcore_ = core_hamiltonian();  // add density independant contributions to Hcore  accumdih_->accum(hcore_);  // set up subclass for vector calculation  init_vector();    // calculate the nuclear repulsion energy  double nucrep = molecule()->nuclear_repulsion_energy();  ExEnv::out0() << indent       << scprintf("nuclear repulsion energy = %15.10f", nucrep)       << endl << endl;  RefDiagSCMatrix evals(oso_dimension(), basis_matrixkit());  double delta = 1.0;  int iter, iter_since_reset = 0;  double accuracy = 1.0;  for (iter=0; iter < maxiter_; iter++, iter_since_reset++) {    // form the density from the current vector     tim_enter("density");    delta = new_density();    tim_exit("density");        // check convergence    if (delta < desired_value_accuracy()        && accuracy < desired_value_accuracy()) break;    // reset the density from time to time    if (iter_since_reset && !(iter_since_reset%dens_reset_freq_)) {      reset_density();      iter_since_reset = 0;    }          // form the AO basis fock matrix & add density dependant H    tim_enter("fock");    double base_accuracy = delta;    if (base_accuracy < desired_value_accuracy())      base_accuracy = desired_value_accuracy();    double new_accuracy = 0.01 * base_accuracy;    if (new_accuracy > 0.001) new_accuracy = 0.001;    if (iter == 0) accuracy = new_accuracy;    else if (new_accuracy < accuracy) {      accuracy = new_accuracy/10.0;      if (iter_since_reset > 0) {        reset_density();        iter_since_reset = 0;      }    }    ao_fock(accuracy);    tim_exit("fock");    // calculate the electronic energy    eelec = scf_energy();    double eother = 0.0;    if (accumddh_.nonnull()) eother = accumddh_->e();    ExEnv::out0() << indent                  << scprintf("iter %5d energy = %15.10f delta = %10.5e",                              iter+1, eelec+eother+nucrep, delta)                  << endl;    // now extrapolate the fock matrix    tim_enter("extrap");    Ref<SCExtrapData> data = extrap_data();    Ref<SCExtrapError> error = extrap_error();    extrap_->extrapolate(data,error);    data=0;    error=0;    tim_exit("extrap");#ifdef GENERALIZED_EIGENSOLVER    // Get the fock matrix and overlap in the SO basis.  The fock matrix    // used here works for CLOSED SHELL ONLY.    RefSymmSCMatrix bfmatref = fock(0);    RefSymmSCMatrix bsmatref = overlap();    BlockedSymmSCMatrix *bfmat      = dynamic_cast<BlockedSymmSCMatrix*>(bfmatref.pointer());    BlockedSymmSCMatrix *bsmat      = dynamic_cast<BlockedSymmSCMatrix*>(bsmatref.pointer());    BlockedDiagSCMatrix *bevals      = dynamic_cast<BlockedDiagSCMatrix*>(evals.pointer());    BlockedSCMatrix *bvec      = dynamic_cast<BlockedSCMatrix*>(oso_scf_vector_.pointer());    ExEnv::out0() << indent                  << "solving generalized eigenvalue problem" << endl;    for (int iblock=0; iblock<bfmat->nblocks(); iblock++) {      RefSymmSCMatrix fmat = bfmat->block(iblock);      RefSymmSCMatrix smat = bsmat->block(iblock);      RefDiagSCMatrix evalblock = bevals->block(iblock);      RefSCMatrix oso_scf_vector_block = bvec->block(iblock);      int nbasis = fmat.dim().n();      int nbasis2 = nbasis*nbasis;      if (!nbasis) continue;      // Convert to the lapack storage format.      double *fso = new double[nbasis2];      double *sso = new double[nbasis2];      int ij=0;      for (int i=0; i<nbasis; i++) {        for (int j=0; j<nbasis; j++,ij++) {          fso[ij] = fmat(i,j);          sso[ij] = smat(i,j);        }      }      // solve generalized eigenvalue problem with DSYGV      int itype = 1;      double *epsilon = new double[nbasis];      int lwork = -1;      int info;      double optlwork;      dsygv_(&itype,"V","U",&nbasis,fso,&nbasis,sso,&nbasis,             epsilon,&optlwork,&lwork,&info);      if (info) {        ExEnv::outn() << "dsygv could not determine work size: info = "                      << info << endl;        abort();      }      lwork = (int)optlwork;      double *work = new double[lwork];      dsygv_(&itype,"V","U",&nbasis,fso,&nbasis,sso,&nbasis,             epsilon,work,&lwork,&info);      if (info) {        ExEnv::outn() << "dsygv could not diagonalize matrix: info = "                      << info << endl;        abort();      }      double *z = fso; // the vector is placed in fso      // make sure everyone agrees on the new arrays      scf_grp_->bcast(z, nbasis2);      scf_grp_->bcast(epsilon, nbasis);      evalblock->assign(epsilon);      oso_scf_vector_block->assign(z);      // cleanup      delete[] fso;      delete[] work;      delete[] sso;      delete[] epsilon;    }    oso_scf_vector_ = (oso_scf_vector_ * so_to_orthog_so_inverse()).t();#else    // diagonalize effective MO fock to get MO vector    tim_enter("evals");    RefSCMatrix nvector(oso_dimension(),oso_dimension(),basis_matrixkit());      RefSymmSCMatrix eff = effective_fock();    // level shift effective fock    level_shift->set_shift(level_shift_);    eff.element_op(level_shift);    if (debug_>1) {      eff.print("effective 1 body hamiltonian in current mo basis");    }    // transform eff to the oso basis to diagonalize it    RefSymmSCMatrix oso_eff(oso_dimension(), basis_matrixkit());    oso_eff.assign(0.0);    oso_eff.accumulate_transform(oso_scf_vector_,eff);    eff = 0;    oso_eff.diagonalize(evals, oso_scf_vector_);    tim_exit("evals");    if (debug_>0 && level_shift_ != 0.0) {      evals.print("level shifted scf eigenvalues");    }    // now un-level shift eigenvalues    level_shift->set_shift(-level_shift_);    evals.element_op(level_shift);#endif    if (debug_>0) {      evals.print("scf eigenvalues");    }        if (reset_occ_)      set_occupations(evals);    if (debug_>1) {      oso_scf_vector_.print("OSO basis scf vector");      (oso_scf_vector_.t()*oso_scf_vector_).print(        "vOSO.t()*vOSO",ExEnv::out0(),14);    }    savestate_iter(iter);  }      eigenvalues_ = evals;  eigenvalues_.computed() = 1;  eigenvalues_.set_actual_accuracy(accuracy<delta?delta:accuracy);  // search for HOMO and LUMO  // first convert evals to something we can deal with easily  BlockedDiagSCMatrix *evalsb = require_dynamic_cast<BlockedDiagSCMatrix*>(evals,                                                 "SCF::compute_vector");    CharacterTable ct = molecule()->point_group()->char_table();    int homo_ir=0, lumo_ir=0;  int homo_mo = -1, lumo_mo = -1;  double homo=-1e99, lumo=1e99;  for (i=0; i < oso_dimension()->blocks()->nblock(); i++) {    int nf=oso_dimension()->blocks()->size(i);    if (nf) {      double *vals = new double[nf];      evalsb->block(i)->convert(vals);      for (int mo=0; mo < nf; mo++) {        if (occupation(i, mo) > 0.0) {          if (vals[mo] > homo) {            homo = vals[mo];            homo_ir = i;            homo_mo = mo;          }        } else {          if (vals[mo] < lumo) {            lumo = vals[mo];            lumo_ir = i;            lumo_mo = mo;          }        }      }      if (print_all_evals_ || print_occ_evals_) {        ExEnv::out0() << endl             << indent << ct.gamma(i).symbol() << endl << incindent;        for (int m=0; m < nf; m++) {          if (occupation(i,m) < 1e-8 && !print_all_evals_)            break;          ExEnv::out0() << indent               << scprintf("%5d %10.5f %10.5f", m+1, vals[m], occupation(i,m))               << endl;        }        ExEnv::out0() << decindent;      }      delete[] vals;    }  }  if (homo_mo >= 0) {    ExEnv::out0() << endl << indent         << scprintf("HOMO is %5d %3s = %10.6f",                     homo_mo+1,                      ct.gamma(homo_ir).symbol(),                     homo)         << endl;  }  if (lumo_mo >= 0) {    ExEnv::out0() << indent         << scprintf("LUMO is %5d %3s = %10.6f",                     lumo_mo+1,                      ct.gamma(lumo_ir).symbol(),                     lumo)         << endl;  }  // free up evals  evals = 0;    oso_eigenvectors_ = oso_scf_vector_;  oso_eigenvectors_.computed() = 1;  oso_eigenvectors_.set_actual_accuracy(delta);  // now clean up  done_vector();  hcore_ = 0;  level_shift->dereference();  delete level_shift;  tim_exit("vector");  //tim_print(0);  return delta;}////////////////////////////////////////////////////////////////////////////class ExtrapErrorOp : public BlockedSCElementOp {  private:    SCF *scf_;  public:    ExtrapErrorOp(SCF *s) : scf_(s) {}    ~ExtrapErrorOp() {}    int has_side_effects() { return 1; }    void process(SCMatrixBlockIter& bi) {      int ir=current_block();            for (bi.reset(); bi; bi++) {        int i=bi.i();        int j=bi.j();        if (scf_->occupation(ir,i) == scf_->occupation(ir,j))          bi.set(0.0);      }    }};Ref<SCExtrapError>SCF::extrap_error(){  RefSymmSCMatrix mofock = effective_fock();    Ref<SCElementOp> op = new ExtrapErrorOp(this);  mofock.element_op(op);    RefSymmSCMatrix aoerror(so_dimension(), basis_matrixkit());  aoerror.assign(0.0);  aoerror.accumulate_transform(so_to_orthog_so().t()*oso_scf_vector_, mofock);  mofock=0;  Ref<SCExtrapError> error = new SymmSCMatrixSCExtrapError(aoerror);  aoerror=0;  return error;}/////////////////////////////////////////////////////////////////////////////}// Local Variables:// mode: c++// c-file-style: "ETS"// End:

⌨️ 快捷键说明

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