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

📄 hsosscf.cc

📁 大型并行量子化学软件;支持密度泛函(DFT)。可以进行各种量子化学计算。支持CHARMM并行计算。非常具有应用价值。
💻 CC
📖 第 1 页 / 共 2 页
字号:
//// hsosscf.cc --- implementation of the high-spin open shell SCF class//// 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.//#ifdef __GNUC__#pragma implementation#endif#include <math.h>#include <util/misc/timer.h>#include <util/misc/formio.h>#include <util/state/stateio.h>#include <math/scmat/block.h>#include <math/scmat/blocked.h>#include <math/scmat/blkiter.h>#include <math/scmat/local.h>#include <math/optimize/scextrapmat.h>#include <chemistry/qc/basis/petite.h>#include <chemistry/qc/scf/scflocal.h>#include <chemistry/qc/scf/scfops.h>#include <chemistry/qc/scf/effh.h>#include <chemistry/qc/scf/hsosscf.h>#include <chemistry/qc/scf/ltbgrad.h>#include <chemistry/qc/scf/hsoshftmpl.h>using namespace std;using namespace sc;///////////////////////////////////////////////////////////////////////////// HSOSSCFstatic ClassDesc HSOSSCF_cd(  typeid(HSOSSCF),"HSOSSCF",2,"public SCF",  0, 0, 0);HSOSSCF::HSOSSCF(StateIn& s) :  SavableState(s),  SCF(s),  cl_fock_(this),  op_fock_(this){  cl_fock_.result_noupdate() =    basis_matrixkit()->symmmatrix(so_dimension());  cl_fock_.restore_state(s);  cl_fock_.result_noupdate().restore(s);    op_fock_.result_noupdate() =    basis_matrixkit()->symmmatrix(so_dimension());  op_fock_.restore_state(s);  op_fock_.result_noupdate().restore(s);    s.get(user_occupations_);  s.get(tndocc_);  s.get(tnsocc_);  s.get(nirrep_);  s.get(ndocc_);  s.get(nsocc_);  if (s.version(::class_desc<HSOSSCF>()) >= 2) {    s.get(initial_ndocc_);    s.get(initial_nsocc_);    most_recent_pg_ << SavableState::restore_state(s);  } else {    initial_ndocc_ = new int[nirrep_];    memcpy(initial_ndocc_, ndocc_, sizeof(int)*nirrep_);    initial_nsocc_ = new int[nirrep_];    memcpy(initial_nsocc_, nsocc_, sizeof(int)*nirrep_);  }  // now take care of memory stuff  init_mem(4);}HSOSSCF::HSOSSCF(const Ref<KeyVal>& keyval) :  SCF(keyval),  cl_fock_(this),  op_fock_(this){  int i;    cl_fock_.compute()=0;  cl_fock_.computed()=0;    op_fock_.compute()=0;  op_fock_.computed()=0;    // calculate the total nuclear charge  double Znuc=molecule()->nuclear_charge();  // check to see if this is to be a charged molecule  double charge = keyval->doublevalue("total_charge");  int nelectrons = (int)(Znuc-charge+1.0e-4);  // first let's try to figure out how many open shells there are  if (keyval->exists("nsocc")) {    tnsocc_ = keyval->intvalue("nsocc");  } else if (keyval->exists("multiplicity")) {    tnsocc_ = keyval->intvalue("multiplicity")-1;  } else {    // if there's an odd number of electrons, then do a doublet, otherwise    // do a triplet    if (nelectrons%2)      tnsocc_=1;    else      tnsocc_=2;  }    // now do the same for the number of doubly occupied shells  if (keyval->exists("ndocc")) {    tndocc_ = keyval->intvalue("ndocc");  } else {    tndocc_ = (nelectrons-tnsocc_)/2;    if ((nelectrons-tnsocc_)%2) {      ExEnv::err0() << endl << indent           << "HSOSSCF::init: Warning, there's a leftover electron.\n"           << incindent << indent << "total_charge = " << charge << endl           << indent << "total nuclear charge = " << Znuc << endl           << indent << "ndocc_ = " << tndocc_ << endl           << indent << "nsocc_ = " << tnsocc_ << endl << decindent;    }  }  ExEnv::out0() << endl << indent       << "HSOSSCF::init: total charge = " << Znuc-2*tndocc_-tnsocc_       << endl << endl;  nirrep_ = molecule()->point_group()->char_table().ncomp();  ndocc_ = read_occ(keyval, "docc", nirrep_);  nsocc_ = read_occ(keyval, "socc", nirrep_);  if (ndocc_ && nsocc_) {    user_occupations_=1;    initial_ndocc_ = new int[nirrep_];    memcpy(initial_ndocc_, ndocc_, sizeof(int)*nirrep_);    initial_nsocc_ = new int[nirrep_];    memcpy(initial_nsocc_, nsocc_, sizeof(int)*nirrep_);  }  else if (ndocc_ && !nsocc_ || !ndocc_ && nsocc_) {    ExEnv::outn() << "ERROR: HSOSSCF: only one of docc and socc specified: "                 << "give both or none" << endl;    abort();  }  else {    ndocc_=0;    nsocc_=0;    initial_ndocc_=0;    initial_nsocc_=0;    user_occupations_=0;    set_occupations(0);  }  ExEnv::out0() << indent << "docc = [";  for (i=0; i < nirrep_; i++)    ExEnv::out0() << " " << ndocc_[i];  ExEnv::out0() << " ]\n";  ExEnv::out0() << indent << "socc = [";  for (i=0; i < nirrep_; i++)    ExEnv::out0() << " " << nsocc_[i];  ExEnv::out0() << " ]\n";  // check to see if this was done in SCF(keyval)  if (!keyval->exists("maxiter"))    maxiter_ = 100;  if (!keyval->exists("level_shift"))    level_shift_ = 0.25;  // now take care of memory stuff  init_mem(4);}HSOSSCF::~HSOSSCF(){  if (ndocc_) {    delete[] ndocc_;    ndocc_=0;  }  if (nsocc_) {    delete[] nsocc_;    nsocc_=0;  }  delete[] initial_ndocc_;  delete[] initial_nsocc_;}voidHSOSSCF::save_data_state(StateOut& s){  SCF::save_data_state(s);  cl_fock_.save_data_state(s);  cl_fock_.result_noupdate().save(s);    op_fock_.save_data_state(s);  op_fock_.result_noupdate().save(s);    s.put(user_occupations_);  s.put(tndocc_);  s.put(tnsocc_);  s.put(nirrep_);  s.put(ndocc_,nirrep_);  s.put(nsocc_,nirrep_);  s.put(initial_ndocc_,nirrep_);  s.put(initial_nsocc_,nirrep_);  SavableState::save_state(most_recent_pg_.pointer(),s);}doubleHSOSSCF::occupation(int ir, int i){  if (i < ndocc_[ir]) return 2.0;  else if (i < ndocc_[ir] + nsocc_[ir]) return 1.0;  return 0.0;}doubleHSOSSCF::alpha_occupation(int ir, int i){  if (i < ndocc_[ir] + nsocc_[ir]) return 1.0;  return 0.0;}doubleHSOSSCF::beta_occupation(int ir, int i){  if (i < ndocc_[ir]) return 1.0;  return 0.0;}intHSOSSCF::n_fock_matrices() const{  return 2;}RefSymmSCMatrixHSOSSCF::fock(int n){  if (n > 1) {    ExEnv::err0() << indent         << "HSOSSCF::fock: there are only two fock matrices, "         << scprintf("but fock(%d) was requested\n",n);    abort();  }  if (n==0)    return cl_fock_.result();  else    return op_fock_.result();}intHSOSSCF::spin_polarized(){  return 1;}voidHSOSSCF::print(ostream&o) const{  int i;    SCF::print(o);  o << indent << "HSOSSCF Parameters:\n" << incindent    << indent << "charge = " << molecule()->nuclear_charge()                                - 2*tndocc_ - tnsocc_ << endl    << indent << "ndocc = " << tndocc_ << endl    << indent << "nsocc = " << tnsocc_ << endl    << indent << "docc = [";  for (i=0; i < nirrep_; i++)    o << " " << ndocc_[i];  o << " ]" << endl;  o << indent << "socc = [";  for (i=0; i < nirrep_; i++)    o << " " << nsocc_[i];  o << " ]" << endl << decindent << endl;}//////////////////////////////////////////////////////////////////////////////voidHSOSSCF::set_occupations(const RefDiagSCMatrix& ev){  if (user_occupations_ || (initial_ndocc_ && initial_nsocc_ && ev.null())) {    if (form_occupations(ndocc_, initial_ndocc_)        &&form_occupations(nsocc_, initial_nsocc_)) {      most_recent_pg_ = new PointGroup(molecule()->point_group());      return;    }    delete[] ndocc_; ndocc_ = 0;    delete[] nsocc_; nsocc_ = 0;    ExEnv::out0() << indent         << "HSOSSCF: WARNING: reforming occupation vectors from scratch"         << endl;  }    if (nirrep_==1) {    delete[] ndocc_;    ndocc_=new int[1];    ndocc_[0]=tndocc_;    if (!initial_ndocc_) {      initial_ndocc_=new int[1];      initial_ndocc_[0]=tndocc_;    }    delete[] nsocc_;    nsocc_=new int[1];    nsocc_[0]=tnsocc_;    if (!initial_nsocc_) {      initial_nsocc_=new int[1];      initial_nsocc_[0]=tnsocc_;    }    return;  }    int i,j;    RefDiagSCMatrix evals;    if (ev.null()) {    initial_vector(0);    evals = eigenvalues_.result_noupdate();  }  else    evals = ev;  // first convert evals to something we can deal with easily  BlockedDiagSCMatrix *evalsb = require_dynamic_cast<BlockedDiagSCMatrix*>(evals,                                                 "HSOSSCF::set_occupations");    double **vals = new double*[nirrep_];  for (i=0; i < nirrep_; i++) {    int nf=oso_dimension()->blocks()->size(i);    if (nf) {      vals[i] = new double[nf];      evalsb->block(i)->convert(vals[i]);    } else {      vals[i] = 0;    }  }  // now loop to find the tndocc_ lowest eigenvalues and populate those  // MO's  int *newdocc = new int[nirrep_];  memset(newdocc,0,sizeof(int)*nirrep_);  for (i=0; i < tndocc_; i++) {    // find lowest eigenvalue    int lir=0,ln=0;    double lowest=999999999;    for (int ir=0; ir < nirrep_; ir++) {      int nf=oso_dimension()->blocks()->size(ir);      if (!nf)        continue;      for (j=0; j < nf; j++) {        if (vals[ir][j] < lowest) {          lowest=vals[ir][j];          lir=ir;          ln=j;        }      }    }    vals[lir][ln]=999999999;    newdocc[lir]++;  }  int *newsocc = new int[nirrep_];  memset(newsocc,0,sizeof(int)*nirrep_);  for (i=0; i < tnsocc_; i++) {    // find lowest eigenvalue    int lir=0,ln=0;    double lowest=999999999;    for (int ir=0; ir < nirrep_; ir++) {      int nf=oso_dimension()->blocks()->size(ir);      if (!nf)        continue;      for (j=0; j < nf; j++) {        if (vals[ir][j] < lowest) {          lowest=vals[ir][j];          lir=ir;          ln=j;        }      }    }    vals[lir][ln]=999999999;    newsocc[lir]++;  }  // get rid of vals  for (i=0; i < nirrep_; i++)    if (vals[i])      delete[] vals[i];  delete[] vals;  if (!ndocc_) {    ndocc_=newdocc;    nsocc_=newsocc;  } else if (most_recent_pg_.nonnull()             && most_recent_pg_->equiv(molecule()->point_group())) {    // test to see if newocc is different from ndocc_    for (i=0; i < nirrep_; i++) {      if (ndocc_[i] != newdocc[i]) {        ExEnv::err0() << indent << "HSOSSCF::set_occupations:  WARNING!!!!\n"

⌨️ 快捷键说明

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