📄 clscf.cc
字号:
//// clscf.cc --- implementation of the closed 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/clscf.h>#include <chemistry/qc/scf/ltbgrad.h>#include <chemistry/qc/scf/clhftmpl.h>using namespace std;using namespace sc;namespace sc {///////////////////////////////////////////////////////////////////////////// CLSCFstatic ClassDesc CLSCF_cd( typeid(CLSCF),"CLSCF",2,"public SCF", 0, 0, 0);CLSCF::CLSCF(StateIn& s) : SavableState(s), SCF(s), cl_fock_(this){ cl_fock_.result_noupdate() = basis_matrixkit()->symmmatrix(so_dimension()); cl_fock_.restore_state(s); cl_fock_.result_noupdate().restore(s); s.get(user_occupations_); s.get(tndocc_); s.get(nirrep_); s.get(ndocc_); if (s.version(::class_desc<CLSCF>()) >= 2) { s.get(initial_ndocc_); most_recent_pg_ << SavableState::restore_state(s); } else { initial_ndocc_ = new int[nirrep_]; memcpy(initial_ndocc_, ndocc_, sizeof(int)*nirrep_); } // now take care of memory stuff init_mem(2);}CLSCF::CLSCF(const Ref<KeyVal>& keyval) : SCF(keyval), cl_fock_(this){ int i; int me = scf_grp_->me(); cl_fock_.compute()=0; cl_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->intvalue("total_charge"); int nelectron = (int)((Znuc-charge+1.0e-4)); // now see if ndocc was specified if (keyval->exists("ndocc")) { tndocc_ = keyval->intvalue("ndocc"); } else { tndocc_ = nelectron/2; if (nelectron%2 && me==0) { ExEnv::err0() << endl << indent << "CLSCF::init: Warning, there's a leftover electron.\n" << incindent << indent << "total_charge = " << charge << endl << indent << "total nuclear charge = " << Znuc << endl << indent << "ndocc_ = " << tndocc_ << endl << decindent; } } ExEnv::out0() << endl << indent << "CLSCF::init: total charge = " << Znuc-2*tndocc_ << endl << endl; nirrep_ = molecule()->point_group()->char_table().ncomp(); ndocc_ = read_occ(keyval, "docc", nirrep_); if (ndocc_) { user_occupations_=1; initial_ndocc_ = new int[nirrep_]; memcpy(initial_ndocc_, ndocc_, sizeof(int)*nirrep_); } else { initial_ndocc_=0; ndocc_=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 << "nbasis = " << basis()->nbasis() << endl; // check to see if this was done in SCF(keyval) if (!keyval->exists("maxiter")) maxiter_ = 40; // now take care of memory stuff init_mem(2);}CLSCF::~CLSCF(){ if (ndocc_) { delete[] ndocc_; ndocc_=0; } delete[] initial_ndocc_;}voidCLSCF::save_data_state(StateOut& s){ SCF::save_data_state(s); cl_fock_.save_data_state(s); cl_fock_.result_noupdate().save(s); s.put(user_occupations_); s.put(tndocc_); s.put(nirrep_); s.put(ndocc_,nirrep_); s.put(initial_ndocc_,nirrep_); SavableState::save_state(most_recent_pg_.pointer(),s);}doubleCLSCF::occupation(int ir, int i){ if (i < ndocc_[ir]) return 2.0; return 0.0;}intCLSCF::n_fock_matrices() const{ return 1;}RefSymmSCMatrixCLSCF::fock(int n){ if (n > 0) { ExEnv::err0() << indent << "CLSCF::fock: there is only one fock matrix, " << scprintf("but fock(%d) was requested\n",n); abort(); } return cl_fock_.result();}intCLSCF::spin_polarized(){ return 0;}voidCLSCF::print(ostream&o) const{ SCF::print(o); o << indent << "CLSCF Parameters:\n" << incindent << indent << "charge = " << molecule()->nuclear_charge()-2*tndocc_ << endl << indent << "ndocc = " << tndocc_ << endl << indent << "docc = ["; for (int i=0; i < nirrep_; i++) o << " " << ndocc_[i]; o << " ]" << endl << decindent << endl;}//////////////////////////////////////////////////////////////////////////////voidCLSCF::set_occupations(const RefDiagSCMatrix& ev){ if (user_occupations_ || (initial_ndocc_ && ev.null())) { if (form_occupations(ndocc_, initial_ndocc_)) { most_recent_pg_ = new PointGroup(molecule()->point_group()); return; } ExEnv::out0() << indent << "CLSCF: WARNING: reforming occupation vector 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_; } 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, "CLSCF::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 *newocc = new int[nirrep_]; memset(newocc,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; newocc[lir]++; } // get rid of vals for (i=0; i < nirrep_; i++) if (vals[i]) delete[] vals[i]; delete[] vals; if (!ndocc_) { ndocc_=newocc; } 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] != newocc[i]) { ExEnv::err0() << indent << "CLSCF::set_occupations: WARNING!!!!\n" << incindent << indent << scprintf("occupations for irrep %d have changed\n",i+1) << indent << scprintf("ndocc was %d, changed to %d", ndocc_[i],newocc[i]) << endl << decindent; } } memcpy(ndocc_,newocc,sizeof(int)*nirrep_); delete[] newocc; } if (!initial_ndocc_ || initial_pg_->equiv(molecule()->point_group())) { delete[] initial_ndocc_; initial_ndocc_ = new int[nirrep_]; memcpy(initial_ndocc_,ndocc_,sizeof(int)*nirrep_); } most_recent_pg_ = new PointGroup(molecule()->point_group());}voidCLSCF::symmetry_changed(){ SCF::symmetry_changed(); cl_fock_.result_noupdate()=0; nirrep_ = molecule()->point_group()->char_table().ncomp(); set_occupations(0);}////////////////////////////////////////////////////////////////////////////////// scf things//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -