| [0b990d] | 1 | //
 | 
|---|
 | 2 | // hsosscf.cc --- implementation of the high-spin open shell SCF class
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Edward Seidl <seidl@janed.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | // GNU Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #ifdef __GNUC__
 | 
|---|
 | 29 | #pragma implementation
 | 
|---|
 | 30 | #endif
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | #include <math.h>
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | #include <util/misc/timer.h>
 | 
|---|
 | 35 | #include <util/misc/formio.h>
 | 
|---|
 | 36 | #include <util/state/stateio.h>
 | 
|---|
 | 37 | 
 | 
|---|
 | 38 | #include <math/scmat/block.h>
 | 
|---|
 | 39 | #include <math/scmat/blocked.h>
 | 
|---|
 | 40 | #include <math/scmat/blkiter.h>
 | 
|---|
 | 41 | #include <math/scmat/local.h>
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 | #include <math/optimize/scextrapmat.h>
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | #include <chemistry/qc/basis/petite.h>
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 | #include <chemistry/qc/scf/scflocal.h>
 | 
|---|
 | 48 | #include <chemistry/qc/scf/scfops.h>
 | 
|---|
 | 49 | #include <chemistry/qc/scf/effh.h>
 | 
|---|
 | 50 | #include <chemistry/qc/scf/hsosscf.h>
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | #include <chemistry/qc/scf/ltbgrad.h>
 | 
|---|
 | 53 | #include <chemistry/qc/scf/hsoshftmpl.h>
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | using namespace std;
 | 
|---|
 | 56 | using namespace sc;
 | 
|---|
 | 57 | 
 | 
|---|
 | 58 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 59 | // HSOSSCF
 | 
|---|
 | 60 | 
 | 
|---|
 | 61 | static ClassDesc HSOSSCF_cd(
 | 
|---|
 | 62 |   typeid(HSOSSCF),"HSOSSCF",2,"public SCF",
 | 
|---|
 | 63 |   0, 0, 0);
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | HSOSSCF::HSOSSCF(StateIn& s) :
 | 
|---|
 | 66 |   SavableState(s),
 | 
|---|
 | 67 |   SCF(s),
 | 
|---|
 | 68 |   cl_fock_(this),
 | 
|---|
 | 69 |   op_fock_(this)
 | 
|---|
 | 70 | {
 | 
|---|
 | 71 |   cl_fock_.result_noupdate() =
 | 
|---|
 | 72 |     basis_matrixkit()->symmmatrix(so_dimension());
 | 
|---|
 | 73 |   cl_fock_.restore_state(s);
 | 
|---|
 | 74 |   cl_fock_.result_noupdate().restore(s);
 | 
|---|
 | 75 |   
 | 
|---|
 | 76 |   op_fock_.result_noupdate() =
 | 
|---|
 | 77 |     basis_matrixkit()->symmmatrix(so_dimension());
 | 
|---|
 | 78 |   op_fock_.restore_state(s);
 | 
|---|
 | 79 |   op_fock_.result_noupdate().restore(s);
 | 
|---|
 | 80 |   
 | 
|---|
 | 81 |   s.get(user_occupations_);
 | 
|---|
 | 82 |   s.get(tndocc_);
 | 
|---|
 | 83 |   s.get(tnsocc_);
 | 
|---|
 | 84 |   s.get(nirrep_);
 | 
|---|
 | 85 |   s.get(ndocc_);
 | 
|---|
 | 86 |   s.get(nsocc_);
 | 
|---|
 | 87 |   if (s.version(::class_desc<HSOSSCF>()) >= 2) {
 | 
|---|
 | 88 |     s.get(initial_ndocc_);
 | 
|---|
 | 89 |     s.get(initial_nsocc_);
 | 
|---|
 | 90 |     most_recent_pg_ << SavableState::restore_state(s);
 | 
|---|
 | 91 |   } else {
 | 
|---|
 | 92 |     initial_ndocc_ = new int[nirrep_];
 | 
|---|
 | 93 |     memcpy(initial_ndocc_, ndocc_, sizeof(int)*nirrep_);
 | 
|---|
 | 94 |     initial_nsocc_ = new int[nirrep_];
 | 
|---|
 | 95 |     memcpy(initial_nsocc_, nsocc_, sizeof(int)*nirrep_);
 | 
|---|
 | 96 |   }
 | 
|---|
 | 97 | 
 | 
|---|
 | 98 |   // now take care of memory stuff
 | 
|---|
 | 99 |   init_mem(4);
 | 
|---|
 | 100 | }
 | 
|---|
 | 101 | 
 | 
|---|
 | 102 | HSOSSCF::HSOSSCF(const Ref<KeyVal>& keyval) :
 | 
|---|
 | 103 |   SCF(keyval),
 | 
|---|
 | 104 |   cl_fock_(this),
 | 
|---|
 | 105 |   op_fock_(this)
 | 
|---|
 | 106 | {
 | 
|---|
 | 107 |   int i;
 | 
|---|
 | 108 |   
 | 
|---|
 | 109 |   cl_fock_.compute()=0;
 | 
|---|
 | 110 |   cl_fock_.computed()=0;
 | 
|---|
 | 111 |   
 | 
|---|
 | 112 |   op_fock_.compute()=0;
 | 
|---|
 | 113 |   op_fock_.computed()=0;
 | 
|---|
 | 114 |   
 | 
|---|
 | 115 |   // calculate the total nuclear charge
 | 
|---|
 | 116 |   double Znuc=molecule()->nuclear_charge();
 | 
|---|
 | 117 | 
 | 
|---|
 | 118 |   // check to see if this is to be a charged molecule
 | 
|---|
 | 119 |   double charge = keyval->doublevalue("total_charge");
 | 
|---|
 | 120 |   int nelectrons = (int)(Znuc-charge+1.0e-4);
 | 
|---|
 | 121 | 
 | 
|---|
 | 122 |   // first let's try to figure out how many open shells there are
 | 
|---|
 | 123 |   if (keyval->exists("nsocc")) {
 | 
|---|
 | 124 |     tnsocc_ = keyval->intvalue("nsocc");
 | 
|---|
 | 125 |   } else if (keyval->exists("multiplicity")) {
 | 
|---|
 | 126 |     tnsocc_ = keyval->intvalue("multiplicity")-1;
 | 
|---|
 | 127 |   } else {
 | 
|---|
 | 128 |     // if there's an odd number of electrons, then do a doublet, otherwise
 | 
|---|
 | 129 |     // do a triplet
 | 
|---|
 | 130 |     if (nelectrons%2)
 | 
|---|
 | 131 |       tnsocc_=1;
 | 
|---|
 | 132 |     else
 | 
|---|
 | 133 |       tnsocc_=2;
 | 
|---|
 | 134 |   }
 | 
|---|
 | 135 |   
 | 
|---|
 | 136 |   // now do the same for the number of doubly occupied shells
 | 
|---|
 | 137 |   if (keyval->exists("ndocc")) {
 | 
|---|
 | 138 |     tndocc_ = keyval->intvalue("ndocc");
 | 
|---|
 | 139 |   } else {
 | 
|---|
 | 140 |     tndocc_ = (nelectrons-tnsocc_)/2;
 | 
|---|
 | 141 |     if ((nelectrons-tnsocc_)%2) {
 | 
|---|
 | 142 |       ExEnv::err0() << endl << indent
 | 
|---|
 | 143 |            << "HSOSSCF::init: Warning, there's a leftover electron.\n"
 | 
|---|
 | 144 |            << incindent << indent << "total_charge = " << charge << endl
 | 
|---|
 | 145 |            << indent << "total nuclear charge = " << Znuc << endl
 | 
|---|
 | 146 |            << indent << "ndocc_ = " << tndocc_ << endl
 | 
|---|
 | 147 |            << indent << "nsocc_ = " << tnsocc_ << endl << decindent;
 | 
|---|
 | 148 |     }
 | 
|---|
 | 149 |   }
 | 
|---|
 | 150 | 
 | 
|---|
 | 151 |   ExEnv::out0() << endl << indent
 | 
|---|
 | 152 |        << "HSOSSCF::init: total charge = " << Znuc-2*tndocc_-tnsocc_
 | 
|---|
 | 153 |        << endl << endl;
 | 
|---|
 | 154 | 
 | 
|---|
 | 155 |   nirrep_ = molecule()->point_group()->char_table().ncomp();
 | 
|---|
 | 156 | 
 | 
|---|
 | 157 |   ndocc_ = read_occ(keyval, "docc", nirrep_);
 | 
|---|
 | 158 |   nsocc_ = read_occ(keyval, "socc", nirrep_);
 | 
|---|
 | 159 |   if (ndocc_ && nsocc_) {
 | 
|---|
 | 160 |     user_occupations_=1;
 | 
|---|
 | 161 |     initial_ndocc_ = new int[nirrep_];
 | 
|---|
 | 162 |     memcpy(initial_ndocc_, ndocc_, sizeof(int)*nirrep_);
 | 
|---|
 | 163 |     initial_nsocc_ = new int[nirrep_];
 | 
|---|
 | 164 |     memcpy(initial_nsocc_, nsocc_, sizeof(int)*nirrep_);
 | 
|---|
 | 165 |   }
 | 
|---|
 | 166 |   else if (ndocc_ && !nsocc_ || !ndocc_ && nsocc_) {
 | 
|---|
 | 167 |     ExEnv::outn() << "ERROR: HSOSSCF: only one of docc and socc specified: "
 | 
|---|
 | 168 |                  << "give both or none" << endl;
 | 
|---|
 | 169 |     abort();
 | 
|---|
 | 170 |   }
 | 
|---|
 | 171 |   else {
 | 
|---|
 | 172 |     ndocc_=0;
 | 
|---|
 | 173 |     nsocc_=0;
 | 
|---|
 | 174 |     initial_ndocc_=0;
 | 
|---|
 | 175 |     initial_nsocc_=0;
 | 
|---|
 | 176 |     user_occupations_=0;
 | 
|---|
 | 177 |     set_occupations(0);
 | 
|---|
 | 178 |   }
 | 
|---|
 | 179 | 
 | 
|---|
 | 180 |   ExEnv::out0() << indent << "docc = [";
 | 
|---|
 | 181 |   for (i=0; i < nirrep_; i++)
 | 
|---|
 | 182 |     ExEnv::out0() << " " << ndocc_[i];
 | 
|---|
 | 183 |   ExEnv::out0() << " ]\n";
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |   ExEnv::out0() << indent << "socc = [";
 | 
|---|
 | 186 |   for (i=0; i < nirrep_; i++)
 | 
|---|
 | 187 |     ExEnv::out0() << " " << nsocc_[i];
 | 
|---|
 | 188 |   ExEnv::out0() << " ]\n";
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 |   // check to see if this was done in SCF(keyval)
 | 
|---|
 | 191 |   if (!keyval->exists("maxiter"))
 | 
|---|
 | 192 |     maxiter_ = 100;
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 |   if (!keyval->exists("level_shift"))
 | 
|---|
 | 195 |     level_shift_ = 0.25;
 | 
|---|
 | 196 | 
 | 
|---|
 | 197 |   // now take care of memory stuff
 | 
|---|
 | 198 |   init_mem(4);
 | 
|---|
 | 199 | }
 | 
|---|
 | 200 | 
 | 
|---|
 | 201 | HSOSSCF::~HSOSSCF()
 | 
|---|
 | 202 | {
 | 
|---|
 | 203 |   if (ndocc_) {
 | 
|---|
 | 204 |     delete[] ndocc_;
 | 
|---|
 | 205 |     ndocc_=0;
 | 
|---|
 | 206 |   }
 | 
|---|
 | 207 |   if (nsocc_) {
 | 
|---|
 | 208 |     delete[] nsocc_;
 | 
|---|
 | 209 |     nsocc_=0;
 | 
|---|
 | 210 |   }
 | 
|---|
 | 211 |   delete[] initial_ndocc_;
 | 
|---|
 | 212 |   delete[] initial_nsocc_;
 | 
|---|
 | 213 | }
 | 
|---|
 | 214 | 
 | 
|---|
 | 215 | void
 | 
|---|
 | 216 | HSOSSCF::save_data_state(StateOut& s)
 | 
|---|
 | 217 | {
 | 
|---|
 | 218 |   SCF::save_data_state(s);
 | 
|---|
 | 219 | 
 | 
|---|
 | 220 |   cl_fock_.save_data_state(s);
 | 
|---|
 | 221 |   cl_fock_.result_noupdate().save(s);
 | 
|---|
 | 222 |   
 | 
|---|
 | 223 |   op_fock_.save_data_state(s);
 | 
|---|
 | 224 |   op_fock_.result_noupdate().save(s);
 | 
|---|
 | 225 |   
 | 
|---|
 | 226 |   s.put(user_occupations_);
 | 
|---|
 | 227 |   s.put(tndocc_);
 | 
|---|
 | 228 |   s.put(tnsocc_);
 | 
|---|
 | 229 |   s.put(nirrep_);
 | 
|---|
 | 230 |   s.put(ndocc_,nirrep_);
 | 
|---|
 | 231 |   s.put(nsocc_,nirrep_);
 | 
|---|
 | 232 |   s.put(initial_ndocc_,nirrep_);
 | 
|---|
 | 233 |   s.put(initial_nsocc_,nirrep_);
 | 
|---|
 | 234 |   SavableState::save_state(most_recent_pg_.pointer(),s);
 | 
|---|
 | 235 | }
 | 
|---|
 | 236 | 
 | 
|---|
 | 237 | double
 | 
|---|
 | 238 | HSOSSCF::occupation(int ir, int i)
 | 
|---|
 | 239 | {
 | 
|---|
 | 240 |   if (i < ndocc_[ir]) return 2.0;
 | 
|---|
 | 241 |   else if (i < ndocc_[ir] + nsocc_[ir]) return 1.0;
 | 
|---|
 | 242 |   return 0.0;
 | 
|---|
 | 243 | }
 | 
|---|
 | 244 | 
 | 
|---|
 | 245 | double
 | 
|---|
 | 246 | HSOSSCF::alpha_occupation(int ir, int i)
 | 
|---|
 | 247 | {
 | 
|---|
 | 248 |   if (i < ndocc_[ir] + nsocc_[ir]) return 1.0;
 | 
|---|
 | 249 |   return 0.0;
 | 
|---|
 | 250 | }
 | 
|---|
 | 251 | 
 | 
|---|
 | 252 | double
 | 
|---|
 | 253 | HSOSSCF::beta_occupation(int ir, int i)
 | 
|---|
 | 254 | {
 | 
|---|
 | 255 |   if (i < ndocc_[ir]) return 1.0;
 | 
|---|
 | 256 |   return 0.0;
 | 
|---|
 | 257 | }
 | 
|---|
 | 258 | 
 | 
|---|
 | 259 | int
 | 
|---|
 | 260 | HSOSSCF::n_fock_matrices() const
 | 
|---|
 | 261 | {
 | 
|---|
 | 262 |   return 2;
 | 
|---|
 | 263 | }
 | 
|---|
 | 264 | 
 | 
|---|
 | 265 | RefSymmSCMatrix
 | 
|---|
 | 266 | HSOSSCF::fock(int n)
 | 
|---|
 | 267 | {
 | 
|---|
 | 268 |   if (n > 1) {
 | 
|---|
 | 269 |     ExEnv::err0() << indent
 | 
|---|
 | 270 |          << "HSOSSCF::fock: there are only two fock matrices, "
 | 
|---|
 | 271 |          << scprintf("but fock(%d) was requested\n",n);
 | 
|---|
 | 272 |     abort();
 | 
|---|
 | 273 |   }
 | 
|---|
 | 274 | 
 | 
|---|
 | 275 |   if (n==0)
 | 
|---|
 | 276 |     return cl_fock_.result();
 | 
|---|
 | 277 |   else
 | 
|---|
 | 278 |     return op_fock_.result();
 | 
|---|
 | 279 | }
 | 
|---|
 | 280 | 
 | 
|---|
 | 281 | int
 | 
|---|
 | 282 | HSOSSCF::spin_polarized()
 | 
|---|
 | 283 | {
 | 
|---|
 | 284 |   return 1;
 | 
|---|
 | 285 | }
 | 
|---|
 | 286 | 
 | 
|---|
 | 287 | void
 | 
|---|
 | 288 | HSOSSCF::print(ostream&o) const
 | 
|---|
 | 289 | {
 | 
|---|
 | 290 |   int i;
 | 
|---|
 | 291 |   
 | 
|---|
 | 292 |   SCF::print(o);
 | 
|---|
 | 293 |   o << indent << "HSOSSCF Parameters:\n" << incindent
 | 
|---|
 | 294 |     << indent << "charge = " << molecule()->nuclear_charge()
 | 
|---|
 | 295 |                                 - 2*tndocc_ - tnsocc_ << endl
 | 
|---|
 | 296 |     << indent << "ndocc = " << tndocc_ << endl
 | 
|---|
 | 297 |     << indent << "nsocc = " << tnsocc_ << endl
 | 
|---|
 | 298 |     << indent << "docc = [";
 | 
|---|
 | 299 |   for (i=0; i < nirrep_; i++)
 | 
|---|
 | 300 |     o << " " << ndocc_[i];
 | 
|---|
 | 301 |   o << " ]" << endl;
 | 
|---|
 | 302 | 
 | 
|---|
 | 303 |   o << indent << "socc = [";
 | 
|---|
 | 304 |   for (i=0; i < nirrep_; i++)
 | 
|---|
 | 305 |     o << " " << nsocc_[i];
 | 
|---|
 | 306 |   o << " ]" << endl << decindent << endl;
 | 
|---|
 | 307 | }
 | 
|---|
 | 308 | 
 | 
|---|
 | 309 | //////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 310 | 
 | 
|---|
 | 311 | void
 | 
|---|
 | 312 | HSOSSCF::set_occupations(const RefDiagSCMatrix& ev)
 | 
|---|
 | 313 | {
 | 
|---|
 | 314 |   if (user_occupations_ || (initial_ndocc_ && initial_nsocc_ && ev.null())) {
 | 
|---|
 | 315 |     if (form_occupations(ndocc_, initial_ndocc_)
 | 
|---|
 | 316 |         &&form_occupations(nsocc_, initial_nsocc_)) {
 | 
|---|
 | 317 |       most_recent_pg_ = new PointGroup(molecule()->point_group());
 | 
|---|
 | 318 |       return;
 | 
|---|
 | 319 |     }
 | 
|---|
 | 320 |     delete[] ndocc_; ndocc_ = 0;
 | 
|---|
 | 321 |     delete[] nsocc_; nsocc_ = 0;
 | 
|---|
 | 322 |     ExEnv::out0() << indent
 | 
|---|
 | 323 |          << "HSOSSCF: WARNING: reforming occupation vectors from scratch"
 | 
|---|
 | 324 |          << endl;
 | 
|---|
 | 325 |   }
 | 
|---|
 | 326 |   
 | 
|---|
 | 327 |   if (nirrep_==1) {
 | 
|---|
 | 328 |     delete[] ndocc_;
 | 
|---|
 | 329 |     ndocc_=new int[1];
 | 
|---|
 | 330 |     ndocc_[0]=tndocc_;
 | 
|---|
 | 331 |     if (!initial_ndocc_) {
 | 
|---|
 | 332 |       initial_ndocc_=new int[1];
 | 
|---|
 | 333 |       initial_ndocc_[0]=tndocc_;
 | 
|---|
 | 334 |     }
 | 
|---|
 | 335 | 
 | 
|---|
 | 336 |     delete[] nsocc_;
 | 
|---|
 | 337 |     nsocc_=new int[1];
 | 
|---|
 | 338 |     nsocc_[0]=tnsocc_;
 | 
|---|
 | 339 |     if (!initial_nsocc_) {
 | 
|---|
 | 340 |       initial_nsocc_=new int[1];
 | 
|---|
 | 341 |       initial_nsocc_[0]=tnsocc_;
 | 
|---|
 | 342 |     }
 | 
|---|
 | 343 | 
 | 
|---|
 | 344 |     return;
 | 
|---|
 | 345 |   }
 | 
|---|
 | 346 |   
 | 
|---|
 | 347 |   int i,j;
 | 
|---|
 | 348 |   
 | 
|---|
 | 349 |   RefDiagSCMatrix evals;
 | 
|---|
 | 350 |   
 | 
|---|
 | 351 |   if (ev.null()) {
 | 
|---|
 | 352 |     initial_vector(0);
 | 
|---|
 | 353 |     evals = eigenvalues_.result_noupdate();
 | 
|---|
 | 354 |   }
 | 
|---|
 | 355 |   else
 | 
|---|
 | 356 |     evals = ev;
 | 
|---|
 | 357 | 
 | 
|---|
 | 358 |   // first convert evals to something we can deal with easily
 | 
|---|
 | 359 |   BlockedDiagSCMatrix *evalsb = require_dynamic_cast<BlockedDiagSCMatrix*>(evals,
 | 
|---|
 | 360 |                                                  "HSOSSCF::set_occupations");
 | 
|---|
 | 361 |   
 | 
|---|
 | 362 |   double **vals = new double*[nirrep_];
 | 
|---|
 | 363 |   for (i=0; i < nirrep_; i++) {
 | 
|---|
 | 364 |     int nf=oso_dimension()->blocks()->size(i);
 | 
|---|
 | 365 |     if (nf) {
 | 
|---|
 | 366 |       vals[i] = new double[nf];
 | 
|---|
 | 367 |       evalsb->block(i)->convert(vals[i]);
 | 
|---|
 | 368 |     } else {
 | 
|---|
 | 369 |       vals[i] = 0;
 | 
|---|
 | 370 |     }
 | 
|---|
 | 371 |   }
 | 
|---|
 | 372 | 
 | 
|---|
 | 373 |   // now loop to find the tndocc_ lowest eigenvalues and populate those
 | 
|---|
 | 374 |   // MO's
 | 
|---|
 | 375 |   int *newdocc = new int[nirrep_];
 | 
|---|
 | 376 |   memset(newdocc,0,sizeof(int)*nirrep_);
 | 
|---|
 | 377 | 
 | 
|---|
 | 378 |   for (i=0; i < tndocc_; i++) {
 | 
|---|
 | 379 |     // find lowest eigenvalue
 | 
|---|
 | 380 |     int lir=0,ln=0;
 | 
|---|
 | 381 |     double lowest=999999999;
 | 
|---|
 | 382 | 
 | 
|---|
 | 383 |     for (int ir=0; ir < nirrep_; ir++) {
 | 
|---|
 | 384 |       int nf=oso_dimension()->blocks()->size(ir);
 | 
|---|
 | 385 |       if (!nf)
 | 
|---|
 | 386 |         continue;
 | 
|---|
 | 387 |       for (j=0; j < nf; j++) {
 | 
|---|
 | 388 |         if (vals[ir][j] < lowest) {
 | 
|---|
 | 389 |           lowest=vals[ir][j];
 | 
|---|
 | 390 |           lir=ir;
 | 
|---|
 | 391 |           ln=j;
 | 
|---|
 | 392 |         }
 | 
|---|
 | 393 |       }
 | 
|---|
 | 394 |     }
 | 
|---|
 | 395 |     vals[lir][ln]=999999999;
 | 
|---|
 | 396 |     newdocc[lir]++;
 | 
|---|
 | 397 |   }
 | 
|---|
 | 398 | 
 | 
|---|
 | 399 |   int *newsocc = new int[nirrep_];
 | 
|---|
 | 400 |   memset(newsocc,0,sizeof(int)*nirrep_);
 | 
|---|
 | 401 | 
 | 
|---|
 | 402 |   for (i=0; i < tnsocc_; i++) {
 | 
|---|
 | 403 |     // find lowest eigenvalue
 | 
|---|
 | 404 |     int lir=0,ln=0;
 | 
|---|
 | 405 |     double lowest=999999999;
 | 
|---|
 | 406 | 
 | 
|---|
 | 407 |     for (int ir=0; ir < nirrep_; ir++) {
 | 
|---|
 | 408 |       int nf=oso_dimension()->blocks()->size(ir);
 | 
|---|
 | 409 |       if (!nf)
 | 
|---|
 | 410 |         continue;
 | 
|---|
 | 411 |       for (j=0; j < nf; j++) {
 | 
|---|
 | 412 |         if (vals[ir][j] < lowest) {
 | 
|---|
 | 413 |           lowest=vals[ir][j];
 | 
|---|
 | 414 |           lir=ir;
 | 
|---|
 | 415 |           ln=j;
 | 
|---|
 | 416 |         }
 | 
|---|
 | 417 |       }
 | 
|---|
 | 418 |     }
 | 
|---|
 | 419 |     vals[lir][ln]=999999999;
 | 
|---|
 | 420 |     newsocc[lir]++;
 | 
|---|
 | 421 |   }
 | 
|---|
 | 422 | 
 | 
|---|
 | 423 |   // get rid of vals
 | 
|---|
 | 424 |   for (i=0; i < nirrep_; i++)
 | 
|---|
 | 425 |     if (vals[i])
 | 
|---|
 | 426 |       delete[] vals[i];
 | 
|---|
 | 427 |   delete[] vals;
 | 
|---|
 | 428 | 
 | 
|---|
 | 429 |   if (!ndocc_) {
 | 
|---|
 | 430 |     ndocc_=newdocc;
 | 
|---|
 | 431 |     nsocc_=newsocc;
 | 
|---|
 | 432 |   } else if (most_recent_pg_.nonnull()
 | 
|---|
 | 433 |              && most_recent_pg_->equiv(molecule()->point_group())) {
 | 
|---|
 | 434 |     // test to see if newocc is different from ndocc_
 | 
|---|
 | 435 |     for (i=0; i < nirrep_; i++) {
 | 
|---|
 | 436 |       if (ndocc_[i] != newdocc[i]) {
 | 
|---|
 | 437 |         ExEnv::err0() << indent << "HSOSSCF::set_occupations:  WARNING!!!!\n"
 | 
|---|
 | 438 |              << incindent << indent
 | 
|---|
 | 439 |              << scprintf("occupations for irrep %d have changed\n",i+1)
 | 
|---|
 | 440 |              << indent
 | 
|---|
 | 441 |              << scprintf("ndocc was %d, changed to %d", ndocc_[i], newdocc[i])
 | 
|---|
 | 442 |              << endl << decindent;
 | 
|---|
 | 443 |       }
 | 
|---|
 | 444 |       if (nsocc_[i] != newsocc[i]) {
 | 
|---|
 | 445 |         ExEnv::err0() << indent << "HSOSSCF::set_occupations:  WARNING!!!!\n"
 | 
|---|
 | 446 |              << incindent << indent
 | 
|---|
 | 447 |              << scprintf("occupations for irrep %d have changed\n",i+1)
 | 
|---|
 | 448 |              << indent
 | 
|---|
 | 449 |              << scprintf("nsocc was %d, changed to %d", nsocc_[i], newsocc[i])
 | 
|---|
 | 450 |              << endl << decindent;
 | 
|---|
 | 451 |       }
 | 
|---|
 | 452 |     }
 | 
|---|
 | 453 | 
 | 
|---|
 | 454 |     memcpy(ndocc_,newdocc,sizeof(int)*nirrep_);
 | 
|---|
 | 455 |     memcpy(nsocc_,newsocc,sizeof(int)*nirrep_);
 | 
|---|
 | 456 |     delete[] newdocc;
 | 
|---|
 | 457 |     delete[] newsocc;
 | 
|---|
 | 458 |   }
 | 
|---|
 | 459 | 
 | 
|---|
 | 460 |   if (!initial_ndocc_
 | 
|---|
 | 461 |       || initial_pg_->equiv(molecule()->point_group())) {
 | 
|---|
 | 462 |     delete[] initial_ndocc_;
 | 
|---|
 | 463 |     initial_ndocc_ = new int[nirrep_];
 | 
|---|
 | 464 |     memcpy(initial_ndocc_,ndocc_,sizeof(int)*nirrep_);
 | 
|---|
 | 465 |   }
 | 
|---|
 | 466 | 
 | 
|---|
 | 467 |   if (!initial_nsocc_
 | 
|---|
 | 468 |       || initial_pg_->equiv(molecule()->point_group())) {
 | 
|---|
 | 469 |     delete[] initial_nsocc_;
 | 
|---|
 | 470 |     initial_nsocc_ = new int[nirrep_];
 | 
|---|
 | 471 |     memcpy(initial_nsocc_,nsocc_,sizeof(int)*nirrep_);
 | 
|---|
 | 472 |   }
 | 
|---|
 | 473 | 
 | 
|---|
 | 474 |   most_recent_pg_ = new PointGroup(molecule()->point_group());
 | 
|---|
 | 475 | }
 | 
|---|
 | 476 | 
 | 
|---|
 | 477 | void
 | 
|---|
 | 478 | HSOSSCF::symmetry_changed()
 | 
|---|
 | 479 | {
 | 
|---|
 | 480 |   SCF::symmetry_changed();
 | 
|---|
 | 481 |   cl_fock_.result_noupdate()=0;
 | 
|---|
 | 482 |   op_fock_.result_noupdate()=0;
 | 
|---|
 | 483 |   nirrep_ = molecule()->point_group()->char_table().ncomp();
 | 
|---|
 | 484 |   set_occupations(0);
 | 
|---|
 | 485 | }
 | 
|---|
 | 486 | 
 | 
|---|
 | 487 | //////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 488 | //
 | 
|---|
 | 489 | // scf things
 | 
|---|
 | 490 | //
 | 
|---|
 | 491 | 
 | 
|---|
 | 492 | void
 | 
|---|
 | 493 | HSOSSCF::init_vector()
 | 
|---|
 | 494 | {
 | 
|---|
 | 495 |   init_threads();
 | 
|---|
 | 496 | 
 | 
|---|
 | 497 |   // allocate storage for other temp matrices
 | 
|---|
 | 498 |   cl_dens_ = hcore_.clone();
 | 
|---|
 | 499 |   cl_dens_.assign(0.0);
 | 
|---|
 | 500 |   
 | 
|---|
 | 501 |   cl_dens_diff_ = hcore_.clone();
 | 
|---|
 | 502 |   cl_dens_diff_.assign(0.0);
 | 
|---|
 | 503 | 
 | 
|---|
 | 504 |   op_dens_ = hcore_.clone();
 | 
|---|
 | 505 |   op_dens_.assign(0.0);
 | 
|---|
 | 506 |   
 | 
|---|
 | 507 |   op_dens_diff_ = hcore_.clone();
 | 
|---|
 | 508 |   op_dens_diff_.assign(0.0);
 | 
|---|
 | 509 | 
 | 
|---|
 | 510 |   // gmat is in AO basis
 | 
|---|
 | 511 |   cl_gmat_ = basis()->matrixkit()->symmmatrix(basis()->basisdim());
 | 
|---|
 | 512 |   cl_gmat_.assign(0.0);
 | 
|---|
 | 513 | 
 | 
|---|
 | 514 |   op_gmat_ = cl_gmat_.clone();
 | 
|---|
 | 515 |   op_gmat_.assign(0.0);
 | 
|---|
 | 516 | 
 | 
|---|
 | 517 |   if (cl_fock_.result_noupdate().null()) {
 | 
|---|
 | 518 |     cl_fock_ = hcore_.clone();
 | 
|---|
 | 519 |     cl_fock_.result_noupdate().assign(0.0);
 | 
|---|
 | 520 |     op_fock_ = hcore_.clone();
 | 
|---|
 | 521 |     op_fock_.result_noupdate().assign(0.0);
 | 
|---|
 | 522 |   }
 | 
|---|
 | 523 | 
 | 
|---|
 | 524 |   // set up trial vector
 | 
|---|
 | 525 |   initial_vector(1);
 | 
|---|
 | 526 |     
 | 
|---|
 | 527 |   oso_scf_vector_ = oso_eigenvectors_.result_noupdate();
 | 
|---|
 | 528 | }
 | 
|---|
 | 529 | 
 | 
|---|
 | 530 | void
 | 
|---|
 | 531 | HSOSSCF::done_vector()
 | 
|---|
 | 532 | {
 | 
|---|
 | 533 |   done_threads();
 | 
|---|
 | 534 | 
 | 
|---|
 | 535 |   cl_gmat_ = 0;
 | 
|---|
 | 536 |   cl_dens_ = 0;
 | 
|---|
 | 537 |   cl_dens_diff_ = 0;
 | 
|---|
 | 538 |   op_gmat_ = 0;
 | 
|---|
 | 539 |   op_dens_ = 0;
 | 
|---|
 | 540 |   op_dens_diff_ = 0;
 | 
|---|
 | 541 | 
 | 
|---|
 | 542 |   oso_scf_vector_ = 0;
 | 
|---|
 | 543 | }
 | 
|---|
 | 544 | 
 | 
|---|
 | 545 | RefSymmSCMatrix
 | 
|---|
 | 546 | HSOSSCF::alpha_density()
 | 
|---|
 | 547 | {
 | 
|---|
 | 548 |   RefSymmSCMatrix dens1(so_dimension(), basis_matrixkit());
 | 
|---|
 | 549 |   RefSymmSCMatrix dens2(so_dimension(), basis_matrixkit());
 | 
|---|
 | 550 | 
 | 
|---|
 | 551 |   so_density(dens1, 2.0);
 | 
|---|
 | 552 |   so_density(dens2, 1.0);
 | 
|---|
 | 553 |   dens1.accumulate(dens2);
 | 
|---|
 | 554 |   dens2=0;
 | 
|---|
 | 555 | 
 | 
|---|
 | 556 |   return dens1;
 | 
|---|
 | 557 | }
 | 
|---|
 | 558 | 
 | 
|---|
 | 559 | RefSymmSCMatrix
 | 
|---|
 | 560 | HSOSSCF::beta_density()
 | 
|---|
 | 561 | {
 | 
|---|
 | 562 |   RefSymmSCMatrix dens(so_dimension(), basis_matrixkit());
 | 
|---|
 | 563 |   so_density(dens, 2.0);
 | 
|---|
 | 564 |   return dens;
 | 
|---|
 | 565 | }
 | 
|---|
 | 566 | 
 | 
|---|
 | 567 | void
 | 
|---|
 | 568 | HSOSSCF::reset_density()
 | 
|---|
 | 569 | {
 | 
|---|
 | 570 |   cl_gmat_.assign(0.0);
 | 
|---|
 | 571 |   cl_dens_diff_.assign(cl_dens_);
 | 
|---|
 | 572 | 
 | 
|---|
 | 573 |   op_gmat_.assign(0.0);
 | 
|---|
 | 574 |   op_dens_diff_.assign(op_dens_);
 | 
|---|
 | 575 | }
 | 
|---|
 | 576 | 
 | 
|---|
 | 577 | double
 | 
|---|
 | 578 | HSOSSCF::new_density()
 | 
|---|
 | 579 | {
 | 
|---|
 | 580 |   // copy current density into density diff and scale by -1.  later we'll
 | 
|---|
 | 581 |   // add the new density to this to get the density difference.
 | 
|---|
 | 582 |   cl_dens_diff_.assign(cl_dens_);
 | 
|---|
 | 583 |   cl_dens_diff_.scale(-1.0);
 | 
|---|
 | 584 | 
 | 
|---|
 | 585 |   op_dens_diff_.assign(op_dens_);
 | 
|---|
 | 586 |   op_dens_diff_.scale(-1.0);
 | 
|---|
 | 587 | 
 | 
|---|
 | 588 |   so_density(cl_dens_, 2.0);
 | 
|---|
 | 589 |   cl_dens_.scale(2.0);
 | 
|---|
 | 590 | 
 | 
|---|
 | 591 |   so_density(op_dens_, 1.0);
 | 
|---|
 | 592 | 
 | 
|---|
 | 593 |   cl_dens_.accumulate(op_dens_);
 | 
|---|
 | 594 |   
 | 
|---|
 | 595 |   cl_dens_diff_.accumulate(cl_dens_);
 | 
|---|
 | 596 |   op_dens_diff_.accumulate(op_dens_);
 | 
|---|
 | 597 | 
 | 
|---|
 | 598 |   Ref<SCElementScalarProduct> sp(new SCElementScalarProduct);
 | 
|---|
 | 599 |   cl_dens_diff_.element_op(sp.pointer(), cl_dens_diff_);
 | 
|---|
 | 600 |   
 | 
|---|
 | 601 |   double delta = sp->result();
 | 
|---|
 | 602 |   delta = sqrt(delta/i_offset(cl_dens_diff_.n()));
 | 
|---|
 | 603 | 
 | 
|---|
 | 604 |   return delta;
 | 
|---|
 | 605 | }
 | 
|---|
 | 606 | 
 | 
|---|
 | 607 | RefSymmSCMatrix
 | 
|---|
 | 608 | HSOSSCF::density()
 | 
|---|
 | 609 | {
 | 
|---|
 | 610 |   if (!density_.computed()) {
 | 
|---|
 | 611 |     RefSymmSCMatrix dens(so_dimension(), basis_matrixkit());
 | 
|---|
 | 612 |     RefSymmSCMatrix dens1(so_dimension(), basis_matrixkit());
 | 
|---|
 | 613 |     so_density(dens, 2.0);
 | 
|---|
 | 614 |     dens.scale(2.0);
 | 
|---|
 | 615 | 
 | 
|---|
 | 616 |     so_density(dens1, 1.0);
 | 
|---|
 | 617 |     dens.accumulate(dens1);
 | 
|---|
 | 618 |     dens1=0;
 | 
|---|
 | 619 |     
 | 
|---|
 | 620 |     density_ = dens;
 | 
|---|
 | 621 |     // only flag the density as computed if the calc is converged
 | 
|---|
 | 622 |     if (!value_needed()) density_.computed() = 1;
 | 
|---|
 | 623 |   }
 | 
|---|
 | 624 | 
 | 
|---|
 | 625 |   return density_.result_noupdate();
 | 
|---|
 | 626 | }
 | 
|---|
 | 627 | 
 | 
|---|
 | 628 | double
 | 
|---|
 | 629 | HSOSSCF::scf_energy()
 | 
|---|
 | 630 | {
 | 
|---|
 | 631 |   RefSymmSCMatrix t = cl_fock_.result_noupdate().copy();
 | 
|---|
 | 632 |   t.accumulate(hcore_);
 | 
|---|
 | 633 | 
 | 
|---|
 | 634 |   RefSymmSCMatrix go = op_fock_.result_noupdate().copy();
 | 
|---|
 | 635 |   go.scale(-1.0);
 | 
|---|
 | 636 |   go.accumulate(cl_fock_.result_noupdate());
 | 
|---|
 | 637 |   
 | 
|---|
 | 638 |   SCFEnergy *eop = new SCFEnergy;
 | 
|---|
 | 639 |   eop->reference();
 | 
|---|
 | 640 |   Ref<SCElementOp2> op = eop;
 | 
|---|
 | 641 |   t.element_op(op, cl_dens_);
 | 
|---|
 | 642 | 
 | 
|---|
 | 643 |   double cl_e = eop->result();
 | 
|---|
 | 644 |   
 | 
|---|
 | 645 |   eop->reset();
 | 
|---|
 | 646 |   go.element_op(op, op_dens_);
 | 
|---|
 | 647 |   double op_e = eop->result();
 | 
|---|
 | 648 | 
 | 
|---|
 | 649 |   op=0;
 | 
|---|
 | 650 |   eop->dereference();
 | 
|---|
 | 651 |   delete eop;
 | 
|---|
 | 652 | 
 | 
|---|
 | 653 |   return cl_e-op_e;
 | 
|---|
 | 654 | }
 | 
|---|
 | 655 | 
 | 
|---|
 | 656 | Ref<SCExtrapData>
 | 
|---|
 | 657 | HSOSSCF::extrap_data()
 | 
|---|
 | 658 | {
 | 
|---|
 | 659 |   Ref<SCExtrapData> data =
 | 
|---|
 | 660 |     new SymmSCMatrix2SCExtrapData(cl_fock_.result_noupdate(),
 | 
|---|
 | 661 |                                   op_fock_.result_noupdate());
 | 
|---|
 | 662 |   return data;
 | 
|---|
 | 663 | }
 | 
|---|
 | 664 | 
 | 
|---|
 | 665 | RefSymmSCMatrix
 | 
|---|
 | 666 | HSOSSCF::effective_fock()
 | 
|---|
 | 667 | {
 | 
|---|
 | 668 |   // use fock() instead of cl_fock_ just in case this is called from
 | 
|---|
 | 669 |   // someplace outside SCF::compute_vector()
 | 
|---|
 | 670 |   RefSymmSCMatrix mofock(oso_dimension(), basis_matrixkit());
 | 
|---|
 | 671 |   mofock.assign(0.0);
 | 
|---|
 | 672 | 
 | 
|---|
 | 673 |   RefSymmSCMatrix mofocko(oso_dimension(), basis_matrixkit());
 | 
|---|
 | 674 |   mofocko.assign(0.0);
 | 
|---|
 | 675 | 
 | 
|---|
 | 676 |   // use eigenvectors if oso_scf_vector_ is null
 | 
|---|
 | 677 |   if (oso_scf_vector_.null()) {
 | 
|---|
 | 678 |     mofock.accumulate_transform(eigenvectors(), fock(0),
 | 
|---|
 | 679 |                                 SCMatrix::TransposeTransform);
 | 
|---|
 | 680 |     mofocko.accumulate_transform(eigenvectors(), fock(1),
 | 
|---|
 | 681 |                                  SCMatrix::TransposeTransform);
 | 
|---|
 | 682 |   } else {
 | 
|---|
 | 683 |     RefSCMatrix so_to_oso_tr = so_to_orthog_so().t();
 | 
|---|
 | 684 |     mofock.accumulate_transform(so_to_oso_tr * oso_scf_vector_, fock(0),
 | 
|---|
 | 685 |                                 SCMatrix::TransposeTransform);
 | 
|---|
 | 686 |     mofocko.accumulate_transform(so_to_oso_tr * oso_scf_vector_, fock(1),
 | 
|---|
 | 687 |                                  SCMatrix::TransposeTransform);
 | 
|---|
 | 688 |   }
 | 
|---|
 | 689 | 
 | 
|---|
 | 690 |   Ref<SCElementOp2> op = new GSGeneralEffH(this);
 | 
|---|
 | 691 |   mofock.element_op(op, mofocko);
 | 
|---|
 | 692 | 
 | 
|---|
 | 693 |   return mofock;
 | 
|---|
 | 694 | }
 | 
|---|
 | 695 | 
 | 
|---|
 | 696 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 697 | 
 | 
|---|
 | 698 | void
 | 
|---|
 | 699 | HSOSSCF::init_gradient()
 | 
|---|
 | 700 | {
 | 
|---|
 | 701 |   // presumably the eigenvectors have already been computed by the time
 | 
|---|
 | 702 |   // we get here
 | 
|---|
 | 703 |   oso_scf_vector_ = oso_eigenvectors_.result_noupdate();
 | 
|---|
 | 704 | }
 | 
|---|
 | 705 | 
 | 
|---|
 | 706 | void
 | 
|---|
 | 707 | HSOSSCF::done_gradient()
 | 
|---|
 | 708 | {
 | 
|---|
 | 709 |   cl_dens_=0;
 | 
|---|
 | 710 |   op_dens_=0;
 | 
|---|
 | 711 |   oso_scf_vector_ = 0;
 | 
|---|
 | 712 | }
 | 
|---|
 | 713 | 
 | 
|---|
 | 714 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 715 | 
 | 
|---|
 | 716 | // MO lagrangian
 | 
|---|
 | 717 | //       c    o   v
 | 
|---|
 | 718 | //  c  |2*FC|2*FC|0|
 | 
|---|
 | 719 | //     -------------
 | 
|---|
 | 720 | //  o  |2*FC| FO |0|
 | 
|---|
 | 721 | //     -------------
 | 
|---|
 | 722 | //  v  | 0  |  0 |0|
 | 
|---|
 | 723 | //
 | 
|---|
 | 724 | RefSymmSCMatrix
 | 
|---|
 | 725 | HSOSSCF::lagrangian()
 | 
|---|
 | 726 | {
 | 
|---|
 | 727 |   RefSCMatrix so_to_oso_tr = so_to_orthog_so().t();
 | 
|---|
 | 728 | 
 | 
|---|
 | 729 |   RefSymmSCMatrix mofock(oso_dimension(), basis_matrixkit());
 | 
|---|
 | 730 |   mofock.assign(0.0);
 | 
|---|
 | 731 |   mofock.accumulate_transform(so_to_oso_tr * oso_scf_vector_,
 | 
|---|
 | 732 |                               cl_fock_.result_noupdate(),
 | 
|---|
 | 733 |                               SCMatrix::TransposeTransform);
 | 
|---|
 | 734 | 
 | 
|---|
 | 735 |   RefSymmSCMatrix mofocko(oso_dimension(), basis_matrixkit());
 | 
|---|
 | 736 |   mofocko.assign(0.0);
 | 
|---|
 | 737 |   mofocko.accumulate_transform(so_to_oso_tr * oso_scf_vector_,
 | 
|---|
 | 738 |                                op_fock_.result_noupdate(),
 | 
|---|
 | 739 |                                SCMatrix::TransposeTransform);
 | 
|---|
 | 740 | 
 | 
|---|
 | 741 |   mofock.scale(2.0);
 | 
|---|
 | 742 |   
 | 
|---|
 | 743 |   Ref<SCElementOp2> op = new MOLagrangian(this);
 | 
|---|
 | 744 |   mofock.element_op(op, mofocko);
 | 
|---|
 | 745 |   mofocko=0;
 | 
|---|
 | 746 | 
 | 
|---|
 | 747 |   // transform MO lagrangian to SO basis
 | 
|---|
 | 748 |   RefSymmSCMatrix so_lag(so_dimension(), basis_matrixkit());
 | 
|---|
 | 749 |   so_lag.assign(0.0);
 | 
|---|
 | 750 |   so_lag.accumulate_transform(so_to_oso_tr * oso_scf_vector_, mofock);
 | 
|---|
 | 751 |   
 | 
|---|
 | 752 |   // and then from SO to AO
 | 
|---|
 | 753 |   Ref<PetiteList> pl = integral()->petite_list();
 | 
|---|
 | 754 |   RefSymmSCMatrix ao_lag = pl->to_AO_basis(so_lag);
 | 
|---|
 | 755 | 
 | 
|---|
 | 756 |   ao_lag.scale(-1.0);
 | 
|---|
 | 757 | 
 | 
|---|
 | 758 |   return ao_lag;
 | 
|---|
 | 759 | }
 | 
|---|
 | 760 | 
 | 
|---|
 | 761 | RefSymmSCMatrix
 | 
|---|
 | 762 | HSOSSCF::gradient_density()
 | 
|---|
 | 763 | {
 | 
|---|
 | 764 |   cl_dens_ = basis_matrixkit()->symmmatrix(so_dimension());
 | 
|---|
 | 765 |   op_dens_ = cl_dens_.clone();
 | 
|---|
 | 766 |   
 | 
|---|
 | 767 |   so_density(cl_dens_, 2.0);
 | 
|---|
 | 768 |   cl_dens_.scale(2.0);
 | 
|---|
 | 769 |   
 | 
|---|
 | 770 |   so_density(op_dens_, 1.0);
 | 
|---|
 | 771 |   
 | 
|---|
 | 772 |   Ref<PetiteList> pl = integral()->petite_list(basis());
 | 
|---|
 | 773 |   
 | 
|---|
 | 774 |   cl_dens_ = pl->to_AO_basis(cl_dens_);
 | 
|---|
 | 775 |   op_dens_ = pl->to_AO_basis(op_dens_);
 | 
|---|
 | 776 | 
 | 
|---|
 | 777 |   RefSymmSCMatrix tdens = cl_dens_.copy();
 | 
|---|
 | 778 |   tdens.accumulate(op_dens_);
 | 
|---|
 | 779 | 
 | 
|---|
 | 780 |   op_dens_.scale(2.0);
 | 
|---|
 | 781 |   
 | 
|---|
 | 782 |   return tdens;
 | 
|---|
 | 783 | }
 | 
|---|
 | 784 | 
 | 
|---|
 | 785 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 786 | 
 | 
|---|
 | 787 | void
 | 
|---|
 | 788 | HSOSSCF::init_hessian()
 | 
|---|
 | 789 | {
 | 
|---|
 | 790 | }
 | 
|---|
 | 791 | 
 | 
|---|
 | 792 | void
 | 
|---|
 | 793 | HSOSSCF::done_hessian()
 | 
|---|
 | 794 | {
 | 
|---|
 | 795 | }
 | 
|---|
 | 796 | 
 | 
|---|
 | 797 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 798 | 
 | 
|---|
 | 799 | void
 | 
|---|
 | 800 | HSOSSCF::two_body_deriv_hf(double * tbgrad, double exchange_fraction)
 | 
|---|
 | 801 | {
 | 
|---|
 | 802 |   Ref<SCElementMaxAbs> m = new SCElementMaxAbs;
 | 
|---|
 | 803 |   cl_dens_.element_op(m.pointer());
 | 
|---|
 | 804 |   op_dens_.element_op(m.pointer());
 | 
|---|
 | 805 |   double pmax = m->result();
 | 
|---|
 | 806 |   m=0;
 | 
|---|
 | 807 | 
 | 
|---|
 | 808 |   // now try to figure out the matrix specialization we're dealing with.
 | 
|---|
 | 809 |   // if we're using Local matrices, then there's just one subblock, or
 | 
|---|
 | 810 |   // see if we can convert P to local matrices
 | 
|---|
 | 811 | 
 | 
|---|
 | 812 |   if (local_ || local_dens_) {
 | 
|---|
 | 813 |     // grab the data pointers from the P matrices
 | 
|---|
 | 814 |     double *pmat, *pmato;
 | 
|---|
 | 815 |     RefSymmSCMatrix ptmp = get_local_data(cl_dens_, pmat, SCF::Read);
 | 
|---|
 | 816 |     RefSymmSCMatrix potmp = get_local_data(op_dens_, pmato, SCF::Read);
 | 
|---|
 | 817 |   
 | 
|---|
 | 818 |     Ref<PetiteList> pl = integral()->petite_list();
 | 
|---|
 | 819 |     LocalHSOSGradContribution l(pmat,pmato);
 | 
|---|
 | 820 |     
 | 
|---|
 | 821 |     int i;
 | 
|---|
 | 822 |     int na3 = molecule()->natom()*3;
 | 
|---|
 | 823 |     int nthread = threadgrp_->nthread();
 | 
|---|
 | 824 |     double **grads = new double*[nthread];
 | 
|---|
 | 825 |     Ref<TwoBodyDerivInt> *tbis = new Ref<TwoBodyDerivInt>[nthread];
 | 
|---|
 | 826 |     for (i=0; i < nthread; i++) { 
 | 
|---|
 | 827 |       tbis[i] = integral()->electron_repulsion_deriv();
 | 
|---|
 | 828 |       grads[i] = new double[na3];
 | 
|---|
 | 829 |       memset(grads[i], 0, sizeof(double)*na3);
 | 
|---|
 | 830 |     }
 | 
|---|
 | 831 | 
 | 
|---|
 | 832 |     LocalTBGrad<LocalHSOSGradContribution> **tblds =
 | 
|---|
 | 833 |       new LocalTBGrad<LocalHSOSGradContribution>*[nthread];
 | 
|---|
 | 834 | 
 | 
|---|
 | 835 |     for (i=0; i < nthread; i++) {
 | 
|---|
 | 836 |       tblds[i] = new LocalTBGrad<LocalHSOSGradContribution>(
 | 
|---|
 | 837 |         l, tbis[i], pl, basis(), scf_grp_, grads[i], pmax,
 | 
|---|
 | 838 |         desired_gradient_accuracy(), nthread, i, exchange_fraction);
 | 
|---|
 | 839 |       threadgrp_->add_thread(i, tblds[i]);
 | 
|---|
 | 840 |     }
 | 
|---|
 | 841 | 
 | 
|---|
 | 842 |     if (threadgrp_->start_threads() < 0
 | 
|---|
 | 843 |         ||threadgrp_->wait_threads() < 0) {
 | 
|---|
 | 844 |       ExEnv::err0() << indent
 | 
|---|
 | 845 |            << "HSOSSCF: error running threads" << endl;
 | 
|---|
 | 846 |       abort();
 | 
|---|
 | 847 |     }
 | 
|---|
 | 848 | 
 | 
|---|
 | 849 |     for (i=0; i < nthread; i++) {
 | 
|---|
 | 850 |       for (int j=0; j < na3; j++)
 | 
|---|
 | 851 |         tbgrad[j] += grads[i][j];
 | 
|---|
 | 852 | 
 | 
|---|
 | 853 |       delete[] grads[i];
 | 
|---|
 | 854 |       delete tblds[i];
 | 
|---|
 | 855 |     }
 | 
|---|
 | 856 | 
 | 
|---|
 | 857 |     scf_grp_->sum(tbgrad, na3);
 | 
|---|
 | 858 |   }
 | 
|---|
 | 859 | 
 | 
|---|
 | 860 |   // for now quit
 | 
|---|
 | 861 |   else {
 | 
|---|
 | 862 |     ExEnv::err0() << indent
 | 
|---|
 | 863 |          << "HSOSSCF::two_body_deriv: can't do gradient yet\n";
 | 
|---|
 | 864 |     abort();
 | 
|---|
 | 865 |   }
 | 
|---|
 | 866 | }
 | 
|---|
 | 867 | 
 | 
|---|
 | 868 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 869 | 
 | 
|---|
 | 870 | // Local Variables:
 | 
|---|
 | 871 | // mode: c++
 | 
|---|
 | 872 | // c-file-style: "ETS"
 | 
|---|
 | 873 | // End:
 | 
|---|