[0b990d] | 1 | //
|
---|
| 2 | // fdhess.cc
|
---|
| 3 | //
|
---|
| 4 | // Copyright (C) 1997 Limit Point Systems, Inc.
|
---|
| 5 | //
|
---|
| 6 | // Author: Curtis Janssen <cljanss@limitpt.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 <stdlib.h>
|
---|
| 33 | #include <sys/stat.h>
|
---|
| 34 |
|
---|
| 35 | #include <util/class/scexception.h>
|
---|
| 36 | #include <util/misc/formio.h>
|
---|
| 37 | #include <util/misc/timer.h>
|
---|
| 38 | #include <util/state/stateio.h>
|
---|
| 39 | #include <util/state/state_bin.h>
|
---|
| 40 | #include <util/group/mstate.h>
|
---|
| 41 | #include <util/keyval/keyval.h>
|
---|
| 42 | #include <math/scmat/blocked.h>
|
---|
| 43 | #include <math/symmetry/corrtab.h>
|
---|
| 44 | #include <chemistry/molecule/fdhess.h>
|
---|
| 45 |
|
---|
| 46 | using namespace std;
|
---|
| 47 | using namespace sc;
|
---|
| 48 |
|
---|
| 49 | #define DEFAULT_CHECKPOINT 1
|
---|
| 50 | #define DEFAULT_RESTART 1
|
---|
| 51 |
|
---|
| 52 | /////////////////////////////////////////////////////////////////
|
---|
| 53 | // FinDispMolecularHessian
|
---|
| 54 |
|
---|
| 55 | static ClassDesc FinDispMolecularHessian_cd(
|
---|
| 56 | typeid(FinDispMolecularHessian),"FinDispMolecularHessian",1,"public MolecularHessian",
|
---|
| 57 | 0, create<FinDispMolecularHessian>, create<FinDispMolecularHessian>);
|
---|
| 58 |
|
---|
| 59 | FinDispMolecularHessian::FinDispMolecularHessian(const Ref<MolecularEnergy> &e):
|
---|
| 60 | mole_(e)
|
---|
| 61 | {
|
---|
| 62 | only_totally_symmetric_ = 0;
|
---|
| 63 | eliminate_cubic_terms_ = 1;
|
---|
| 64 | do_null_displacement_ = 1;
|
---|
| 65 | disp_ = 1.0e-2;
|
---|
| 66 | ndisp_ = 0;
|
---|
| 67 | debug_ = 0;
|
---|
| 68 | gradients_ = 0;
|
---|
| 69 | accuracy_ = disp_/1000;
|
---|
| 70 | restart_ = DEFAULT_RESTART;
|
---|
| 71 | checkpoint_ = DEFAULT_CHECKPOINT;
|
---|
| 72 | checkpoint_file_ = 0;
|
---|
| 73 | restart_file_ = 0;
|
---|
| 74 | checkpoint_file_ = SCFormIO::fileext_to_filename(".ckpt.hess");
|
---|
| 75 | restart_file_ = SCFormIO::fileext_to_filename(".ckpt.hess");
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | FinDispMolecularHessian::FinDispMolecularHessian(const Ref<KeyVal>&keyval):
|
---|
| 79 | MolecularHessian(keyval)
|
---|
| 80 | {
|
---|
| 81 | mole_ << keyval->describedclassvalue("energy");
|
---|
| 82 |
|
---|
| 83 | debug_ = keyval->booleanvalue("debug");
|
---|
| 84 |
|
---|
| 85 | displacement_point_group_ << keyval->describedclassvalue("point_group");
|
---|
| 86 |
|
---|
| 87 | disp_ = keyval->doublevalue("displacement",KeyValValuedouble(1.0e-2));
|
---|
| 88 |
|
---|
| 89 | KeyValValueboolean def_restart(DEFAULT_RESTART);
|
---|
| 90 | KeyValValueboolean def_checkpoint(DEFAULT_CHECKPOINT);
|
---|
| 91 | KeyValValueboolean truevalue(1);
|
---|
| 92 | KeyValValueboolean falsevalue(0);
|
---|
| 93 |
|
---|
| 94 | restart_ = keyval->booleanvalue("restart", def_restart);
|
---|
| 95 | char *def_file = SCFormIO::fileext_to_filename(".ckpt.hess");
|
---|
| 96 | KeyValValueString def_restart_file(def_file,KeyValValueString::Steal);
|
---|
| 97 | restart_file_ = keyval->pcharvalue("restart_file", def_restart_file);
|
---|
| 98 | checkpoint_ = keyval->booleanvalue("checkpoint", def_checkpoint);
|
---|
| 99 | checkpoint_file_ = keyval->pcharvalue("checkpoint_file", def_restart_file);
|
---|
| 100 | only_totally_symmetric_ = keyval->booleanvalue("only_totally_symmetric",
|
---|
| 101 | falsevalue);
|
---|
| 102 | eliminate_cubic_terms_ = keyval->booleanvalue("eliminate_cubic_terms",
|
---|
| 103 | truevalue);
|
---|
| 104 |
|
---|
| 105 | do_null_displacement_ = keyval->booleanvalue("do_null_displacement",
|
---|
| 106 | truevalue);
|
---|
| 107 |
|
---|
| 108 | accuracy_ = keyval->doublevalue("gradient_accuracy",
|
---|
| 109 | KeyValValuedouble(disp_/1000));
|
---|
| 110 |
|
---|
| 111 | gradients_ = 0;
|
---|
| 112 | ndisp_ = 0;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | FinDispMolecularHessian::FinDispMolecularHessian(StateIn&s):
|
---|
| 116 | SavableState(s),
|
---|
| 117 | MolecularHessian(s)
|
---|
| 118 | {
|
---|
| 119 | mole_ << SavableState::restore_state(s);
|
---|
| 120 | s.get(checkpoint_);
|
---|
| 121 | s.get(debug_);
|
---|
| 122 | s.get(accuracy_);
|
---|
| 123 | s.getstring(checkpoint_file_);
|
---|
| 124 | s.getstring(restart_file_);
|
---|
| 125 |
|
---|
| 126 | gradients_ = 0;
|
---|
| 127 | restore_displacements(s);
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | FinDispMolecularHessian::~FinDispMolecularHessian()
|
---|
| 131 | {
|
---|
| 132 | delete[] gradients_;
|
---|
| 133 | delete[] checkpoint_file_;
|
---|
| 134 | delete[] restart_file_;
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | void
|
---|
| 138 | FinDispMolecularHessian::save_data_state(StateOut&s)
|
---|
| 139 | {
|
---|
| 140 | MolecularHessian::save_data_state(s);
|
---|
| 141 |
|
---|
| 142 | SavableState::save_state(mole_.pointer(),s);
|
---|
| 143 | s.put(checkpoint_);
|
---|
| 144 | s.put(debug_);
|
---|
| 145 | s.put(accuracy_);
|
---|
| 146 | s.putstring(checkpoint_file_);
|
---|
| 147 | s.putstring(restart_file_);
|
---|
| 148 |
|
---|
| 149 | checkpoint_displacements(s);
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | void
|
---|
| 153 | FinDispMolecularHessian::init()
|
---|
| 154 | {
|
---|
| 155 | if (mole_.null()) return;
|
---|
| 156 |
|
---|
| 157 | mol_ = mole_->molecule();
|
---|
| 158 |
|
---|
| 159 | if (displacement_point_group_.null()) {
|
---|
| 160 | displacement_point_group_
|
---|
| 161 | = new PointGroup(*mol_->point_group().pointer());
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | nirrep_ = displacement_point_group_->char_table().nirrep();
|
---|
| 165 |
|
---|
| 166 | original_point_group_ = mol_->point_group();
|
---|
| 167 | original_geometry_ = matrixkit()->vector(d3natom());
|
---|
| 168 |
|
---|
| 169 | int i, coor;
|
---|
| 170 | for (i=0, coor=0; i<mol_->natom(); i++) {
|
---|
| 171 | for (int j=0; j<3; j++, coor++) {
|
---|
| 172 | original_geometry_(coor) = mol_->r(i,j);
|
---|
| 173 | }
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | ndisp_ = 0;
|
---|
| 177 | symbasis_ = cartesian_to_symmetry(mol_,
|
---|
| 178 | displacement_point_group_,
|
---|
| 179 | matrixkit());
|
---|
| 180 | delete[] gradients_;
|
---|
| 181 | gradients_ = new RefSCVector[ndisplace()];
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 | void
|
---|
| 185 | FinDispMolecularHessian::set_energy(const Ref<MolecularEnergy> &energy)
|
---|
| 186 | {
|
---|
| 187 | mole_ = energy;
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 | MolecularEnergy*
|
---|
| 191 | FinDispMolecularHessian::energy() const
|
---|
| 192 | {
|
---|
| 193 | return mole_.pointer();
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | void
|
---|
| 197 | FinDispMolecularHessian::restart()
|
---|
| 198 | {
|
---|
| 199 | int statresult, statsize;
|
---|
| 200 | Ref<MessageGrp> grp = MessageGrp::get_default_messagegrp();
|
---|
| 201 | if (grp->me() == 0) {
|
---|
| 202 | struct stat sb;
|
---|
| 203 | statresult = stat(restart_file_,&sb);
|
---|
| 204 | statsize = (statresult==0) ? sb.st_size : 0;
|
---|
| 205 | }
|
---|
| 206 | grp->bcast(statsize);
|
---|
| 207 | if (statsize) {
|
---|
| 208 | BcastStateInBin si(grp,restart_file_);
|
---|
| 209 | restore_displacements(si);
|
---|
| 210 | mol_ = mole_->molecule();
|
---|
| 211 |
|
---|
| 212 | if (ndisplacements_done() >= ndisplace()) {
|
---|
| 213 | restart_=0;
|
---|
| 214 | return;
|
---|
| 215 | }
|
---|
| 216 | }
|
---|
| 217 |
|
---|
| 218 | if (ndisp_) {
|
---|
| 219 | int irrep, index;
|
---|
| 220 | double coef;
|
---|
| 221 | get_disp(ndisplacements_done(), irrep, index, coef);
|
---|
| 222 | if (irrep != 0 && index != 0) {
|
---|
| 223 | displace(ndisplacements_done());
|
---|
| 224 | mole_->symmetry_changed();
|
---|
| 225 | }
|
---|
| 226 | }
|
---|
| 227 | else {
|
---|
| 228 | init();
|
---|
| 229 | }
|
---|
| 230 | restart_ = 0;
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | void
|
---|
| 234 | FinDispMolecularHessian::restore_displacements(StateIn& s)
|
---|
| 235 | {
|
---|
| 236 | int i;
|
---|
| 237 | displacement_point_group_ << SavableState::restore_state(s);
|
---|
| 238 | original_point_group_ << SavableState::restore_state(s);
|
---|
| 239 | original_geometry_ = matrixkit()->vector(d3natom());
|
---|
| 240 | original_geometry_.restore(s);
|
---|
| 241 |
|
---|
| 242 | s.get(disp_);
|
---|
| 243 | s.get(ndisp_);
|
---|
| 244 | s.get(nirrep_);
|
---|
| 245 | s.get(only_totally_symmetric_);
|
---|
| 246 | s.get(eliminate_cubic_terms_);
|
---|
| 247 | s.get(do_null_displacement_);
|
---|
| 248 |
|
---|
| 249 | if (ndisp_) {
|
---|
| 250 | RefSCDimension symrow, symcol;
|
---|
| 251 | symrow << SavableState::restore_state(s);
|
---|
| 252 | symcol << SavableState::restore_state(s);
|
---|
| 253 | Ref<SCMatrixKit> symkit = new BlockedSCMatrixKit(matrixkit());
|
---|
| 254 | symbasis_ = symkit->matrix(symrow,symcol);
|
---|
| 255 | symbasis_.restore(s);
|
---|
| 256 |
|
---|
| 257 | delete[] gradients_;
|
---|
| 258 | gradients_ = new RefSCVector[ndisplace()];
|
---|
| 259 | for (i=0; i < ndisp_; i++) {
|
---|
| 260 | int ndisp;
|
---|
| 261 | s.get(ndisp);
|
---|
| 262 | RefSCDimension ddisp = new SCDimension(ndisp);
|
---|
| 263 | gradients_[i] = matrixkit()->vector(ddisp);
|
---|
| 264 | gradients_[i].restore(s);
|
---|
| 265 | }
|
---|
| 266 | }
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 | void
|
---|
| 270 | FinDispMolecularHessian::checkpoint_displacements(StateOut& s)
|
---|
| 271 | {
|
---|
| 272 | int i;
|
---|
| 273 | SavableState::save_state(displacement_point_group_.pointer(),s);
|
---|
| 274 | SavableState::save_state(original_point_group_.pointer(),s);
|
---|
| 275 | original_geometry_.save(s);
|
---|
| 276 |
|
---|
| 277 | s.put(disp_);
|
---|
| 278 | s.put(ndisp_);
|
---|
| 279 | s.put(nirrep_);
|
---|
| 280 | s.put(only_totally_symmetric_);
|
---|
| 281 | s.put(eliminate_cubic_terms_);
|
---|
| 282 | s.put(do_null_displacement_);
|
---|
| 283 |
|
---|
| 284 | if (ndisp_) {
|
---|
| 285 | SavableState::save_state(symbasis_.rowdim().pointer(),s);
|
---|
| 286 | SavableState::save_state(symbasis_.coldim().pointer(),s);
|
---|
| 287 | symbasis_.save(s);
|
---|
| 288 |
|
---|
| 289 | for (i=0; i < ndisp_; i++) {
|
---|
| 290 | s.put(gradients_[i].n());
|
---|
| 291 | gradients_[i].save(s);
|
---|
| 292 | }
|
---|
| 293 | }
|
---|
| 294 | }
|
---|
| 295 |
|
---|
| 296 | RefSCMatrix
|
---|
| 297 | FinDispMolecularHessian::displacements(int irrep) const
|
---|
| 298 | {
|
---|
| 299 | BlockedSCMatrix *bsymbasis = dynamic_cast<BlockedSCMatrix*>(symbasis_.pointer());
|
---|
| 300 | RefSCMatrix block = bsymbasis->block(irrep);
|
---|
| 301 | if (block.null() || (only_totally_symmetric_ && irrep > 0)) {
|
---|
| 302 | RefSCDimension zero = new SCDimension(0);
|
---|
| 303 | block = matrixkit()->matrix(zero,zero);
|
---|
| 304 | return block;
|
---|
| 305 | }
|
---|
| 306 | return block.t();
|
---|
| 307 | }
|
---|
| 308 |
|
---|
| 309 | void
|
---|
| 310 | FinDispMolecularHessian::get_disp(int disp, int &irrep,
|
---|
| 311 | int &index, double &coef)
|
---|
| 312 | {
|
---|
| 313 | int disp_offset = 0;
|
---|
| 314 |
|
---|
| 315 | if (do_null_displacement_ && disp == 0) {
|
---|
| 316 | irrep = 0;
|
---|
| 317 | coef = 0.0;
|
---|
| 318 | index = -1;
|
---|
| 319 | return;
|
---|
| 320 | }
|
---|
| 321 | disp_offset++;
|
---|
| 322 | // check for +ve totally symmetric displacements
|
---|
| 323 | if (disp < disp_offset + displacements(0).ncol()) {
|
---|
| 324 | irrep = 0;
|
---|
| 325 | coef = 1.0;
|
---|
| 326 | index = disp - disp_offset;
|
---|
| 327 | return;
|
---|
| 328 | }
|
---|
| 329 | disp_offset += displacements(0).ncol();
|
---|
| 330 | // check for -ve totally symmetric displacements
|
---|
| 331 | if (eliminate_cubic_terms_) {
|
---|
| 332 | if (disp < disp_offset + displacements(0).ncol()) {
|
---|
| 333 | irrep = 0;
|
---|
| 334 | coef = -1.0;
|
---|
| 335 | index = disp - disp_offset;
|
---|
| 336 | return;
|
---|
| 337 | }
|
---|
| 338 | disp_offset += displacements(0).ncol();
|
---|
| 339 | }
|
---|
| 340 | for (int i=1; i<nirrep_; i++) {
|
---|
| 341 | if (disp < disp_offset + displacements(i).ncol()) {
|
---|
| 342 | irrep = i;
|
---|
| 343 | coef = 1.0;
|
---|
| 344 | index = disp - disp_offset;
|
---|
| 345 | return;
|
---|
| 346 | }
|
---|
| 347 | disp_offset += displacements(i).ncol();
|
---|
| 348 | }
|
---|
| 349 | throw ProgrammingError("bad displacement number",
|
---|
| 350 | __FILE__, __LINE__, class_desc());
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | int
|
---|
| 354 | FinDispMolecularHessian::ndisplace() const
|
---|
| 355 | {
|
---|
| 356 | int ndisp = displacements(0).ncol();
|
---|
| 357 | if (eliminate_cubic_terms_) {
|
---|
| 358 | ndisp *= 2;
|
---|
| 359 | }
|
---|
| 360 | for (int i=1; i<nirrep_; i++) {
|
---|
| 361 | ndisp += displacements(i).ncol();
|
---|
| 362 | }
|
---|
| 363 | if (do_null_displacement_) ndisp++;
|
---|
| 364 | return ndisp;
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | void
|
---|
| 368 | FinDispMolecularHessian::displace(int disp)
|
---|
| 369 | {
|
---|
| 370 | int irrep, index;
|
---|
| 371 | double coef;
|
---|
| 372 | get_disp(disp, irrep, index, coef);
|
---|
| 373 |
|
---|
| 374 | if (mole_.nonnull()) mole_->obsolete();
|
---|
| 375 |
|
---|
| 376 | for (int i=0, coor=0; i<mol_->natom(); i++) {
|
---|
| 377 | for (int j=0; j<3; j++, coor++) {
|
---|
| 378 | if (index >= 0) {
|
---|
| 379 | mol_->r(i,j) = original_geometry_(coor)
|
---|
| 380 | + coef * disp_
|
---|
| 381 | * displacements(irrep)->get_element(coor,index);
|
---|
| 382 |
|
---|
| 383 | }
|
---|
| 384 | else {
|
---|
| 385 | mol_->r(i,j) = original_geometry_(coor);
|
---|
| 386 | }
|
---|
| 387 | }
|
---|
| 388 | }
|
---|
| 389 |
|
---|
| 390 | if (irrep == 0) {
|
---|
| 391 | mol_->set_point_group(original_point_group_);
|
---|
| 392 | }
|
---|
| 393 | else {
|
---|
| 394 | Ref<PointGroup> oldpg = mol_->point_group();
|
---|
| 395 | Ref<PointGroup> newpg = mol_->highest_point_group();
|
---|
| 396 | CorrelationTable corrtab;
|
---|
| 397 | if (corrtab.initialize_table(original_point_group_, newpg)) {
|
---|
| 398 | // something went wrong so use c1 symmetry
|
---|
| 399 | newpg = new PointGroup("c1");
|
---|
| 400 | }
|
---|
| 401 | if (!oldpg->equiv(newpg)) {
|
---|
| 402 | mol_->set_point_group(newpg);
|
---|
| 403 | mole_->symmetry_changed();
|
---|
| 404 | }
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 | #ifdef DEBUG
|
---|
| 408 | ExEnv::out0() << indent
|
---|
| 409 | << "Displacement point group: " << endl
|
---|
| 410 | << incindent << displacement_point_group_ << decindent;
|
---|
| 411 | ExEnv::out0() << indent
|
---|
| 412 | << "Displaced molecule: " << endl
|
---|
| 413 | << incindent << mol_ << decindent;
|
---|
| 414 | #endif
|
---|
| 415 |
|
---|
| 416 | ExEnv::out0() << indent
|
---|
| 417 | << "Displacement is "
|
---|
| 418 | << displacement_point_group_->char_table().gamma(irrep).symbol()
|
---|
| 419 | << " in " << displacement_point_group_->symbol()
|
---|
| 420 | << ". Using point group "
|
---|
| 421 | << mol_->point_group()->symbol()
|
---|
| 422 | << " for displaced molecule."
|
---|
| 423 | << endl;
|
---|
| 424 | }
|
---|
| 425 |
|
---|
| 426 | void
|
---|
| 427 | FinDispMolecularHessian::original_geometry()
|
---|
| 428 | {
|
---|
| 429 | if (mole_.nonnull()) mole_->obsolete();
|
---|
| 430 |
|
---|
| 431 | for (int i=0, coor=0; i<mol_->natom(); i++) {
|
---|
| 432 | for (int j=0; j<3; j++, coor++) {
|
---|
| 433 | mol_->r(i,j) = original_geometry_(coor);
|
---|
| 434 | }
|
---|
| 435 | }
|
---|
| 436 |
|
---|
| 437 | if (!mol_->point_group()->equiv(original_point_group_)) {
|
---|
| 438 | mol_->set_point_group(original_point_group_);
|
---|
| 439 | mole_->symmetry_changed();
|
---|
| 440 | }
|
---|
| 441 | }
|
---|
| 442 |
|
---|
| 443 | void
|
---|
| 444 | FinDispMolecularHessian::set_gradient(int disp, const RefSCVector &grad)
|
---|
| 445 | {
|
---|
| 446 | int irrep, index;
|
---|
| 447 | double coef;
|
---|
| 448 | get_disp(disp, irrep, index, coef);
|
---|
| 449 |
|
---|
| 450 | // transform the gradient into symmetrized coordinates
|
---|
| 451 | gradients_[disp] = displacements(irrep).t() * grad;
|
---|
| 452 | if (debug_) {
|
---|
| 453 | grad.print("cartesian gradient");
|
---|
| 454 | gradients_[disp].print("internal gradient");
|
---|
| 455 | }
|
---|
| 456 |
|
---|
| 457 | ndisp_++;
|
---|
| 458 | }
|
---|
| 459 |
|
---|
| 460 | RefSymmSCMatrix
|
---|
| 461 | FinDispMolecularHessian::compute_hessian_from_gradients()
|
---|
| 462 | {
|
---|
| 463 | int i;
|
---|
| 464 |
|
---|
| 465 | RefSymmSCMatrix dhessian;
|
---|
| 466 |
|
---|
| 467 | RefSymmSCMatrix xhessian = matrixkit()->symmmatrix(d3natom());
|
---|
| 468 | xhessian.assign(0.0);
|
---|
| 469 |
|
---|
| 470 | // start with the totally symmetric displacments
|
---|
| 471 | int offset = 0;
|
---|
| 472 | if (do_null_displacement_) offset++;
|
---|
| 473 | RefSCMatrix dtrans = displacements(0);
|
---|
| 474 | RefSCDimension ddim = dtrans.coldim();
|
---|
| 475 | dhessian = matrixkit()->symmmatrix(ddim);
|
---|
| 476 | for (i=0; i<ddim.n(); i++) {
|
---|
| 477 | for (int j=0; j<=i; j++) {
|
---|
| 478 | double hij = gradients_[i+offset](j) + gradients_[j+offset](i);
|
---|
| 479 | double ncontrib = 2.0;
|
---|
| 480 | if (do_null_displacement_) {
|
---|
| 481 | hij -= gradients_[0](j) + gradients_[0](i);
|
---|
| 482 | }
|
---|
| 483 | if (eliminate_cubic_terms_) {
|
---|
| 484 | hij -= gradients_[i+ddim.n()+offset](j)
|
---|
| 485 | + gradients_[j+ddim.n()+offset](i);
|
---|
| 486 | ncontrib += 2.0;
|
---|
| 487 | if (do_null_displacement_) {
|
---|
| 488 | hij += gradients_[0](j) + gradients_[0](i);
|
---|
| 489 | }
|
---|
| 490 | }
|
---|
| 491 | hij /= ncontrib*disp_;
|
---|
| 492 | dhessian(i,j) = hij;
|
---|
| 493 | }
|
---|
| 494 | }
|
---|
| 495 | do_hess_for_irrep(0, dhessian, xhessian);
|
---|
| 496 |
|
---|
| 497 | offset += ddim.n();
|
---|
| 498 | if (eliminate_cubic_terms_) offset += ddim.n();
|
---|
| 499 | for (int irrep=1; irrep<nirrep_; irrep++) {
|
---|
| 500 | dtrans = displacements(irrep);
|
---|
| 501 | ddim = dtrans.coldim();
|
---|
| 502 | if (ddim.n() == 0) continue;
|
---|
| 503 | dhessian = matrixkit()->symmmatrix(ddim);
|
---|
| 504 | for (i=0; i<ddim.n(); i++) {
|
---|
| 505 | for (int j=0; j<=i; j++) {
|
---|
| 506 | dhessian(i,j) = (gradients_[i+offset](j)
|
---|
| 507 | + gradients_[j+offset](i))
|
---|
| 508 | /(2.0*disp_);
|
---|
| 509 | }
|
---|
| 510 | }
|
---|
| 511 | do_hess_for_irrep(irrep, dhessian, xhessian);
|
---|
| 512 | offset += ddim.n();
|
---|
| 513 | }
|
---|
| 514 |
|
---|
| 515 | if (debug_) {
|
---|
| 516 | xhessian.print("xhessian");
|
---|
| 517 | }
|
---|
| 518 |
|
---|
| 519 | return xhessian;
|
---|
| 520 | }
|
---|
| 521 |
|
---|
| 522 | void
|
---|
| 523 | FinDispMolecularHessian::do_hess_for_irrep(int irrep,
|
---|
| 524 | const RefSymmSCMatrix &dhessian,
|
---|
| 525 | const RefSymmSCMatrix &xhessian)
|
---|
| 526 | {
|
---|
| 527 | RefSCMatrix dtrans = displacements(irrep);
|
---|
| 528 | RefSCDimension ddim = dtrans.coldim();
|
---|
| 529 | if (ddim.n() == 0) return;
|
---|
| 530 | if (debug_) {
|
---|
| 531 | dhessian.print("dhessian");
|
---|
| 532 | dtrans.print("dtrans");
|
---|
| 533 | }
|
---|
| 534 | xhessian.accumulate_transform(dtrans, dhessian);
|
---|
| 535 | }
|
---|
| 536 |
|
---|
| 537 | RefSymmSCMatrix
|
---|
| 538 | FinDispMolecularHessian::cartesian_hessian()
|
---|
| 539 | {
|
---|
| 540 | tim_enter("hessian");
|
---|
| 541 |
|
---|
| 542 | if (restart_) restart();
|
---|
| 543 | else init();
|
---|
| 544 |
|
---|
| 545 | ExEnv::out0() << indent
|
---|
| 546 | << "Computing molecular hessian from "
|
---|
| 547 | << ndisplace() << " displacements:" << endl
|
---|
| 548 | << indent << "Starting at displacement: "
|
---|
| 549 | << ndisplacements_done() << endl;
|
---|
| 550 | ExEnv::out0() << indent << "Hessian options: " << endl;
|
---|
| 551 | ExEnv::out0() << indent << " displacement: " << disp_
|
---|
| 552 | << " bohr" << endl;
|
---|
| 553 | ExEnv::out0() << indent << " gradient_accuracy: "
|
---|
| 554 | << accuracy_ << " au" << endl;
|
---|
| 555 | ExEnv::out0() << indent << " eliminate_cubic_terms: "
|
---|
| 556 | << (eliminate_cubic_terms_==0?"no":"yes") << endl;
|
---|
| 557 | ExEnv::out0() << indent << " only_totally_symmetric: "
|
---|
| 558 | << (only_totally_symmetric_==0?"no":"yes") << endl;
|
---|
| 559 |
|
---|
| 560 | for (int i=ndisplacements_done(); i<ndisplace(); i++) {
|
---|
| 561 | // This produces side-effects in mol and may even change
|
---|
| 562 | // its symmetry.
|
---|
| 563 | ExEnv::out0() << endl << indent
|
---|
| 564 | << "Beginning displacement " << i << ":" << endl;
|
---|
| 565 | displace(i);
|
---|
| 566 |
|
---|
| 567 | mole_->obsolete();
|
---|
| 568 | double original_accuracy;
|
---|
| 569 | original_accuracy = mole_->desired_gradient_accuracy();
|
---|
| 570 | if (accuracy_ > 0.0)
|
---|
| 571 | mole_->set_desired_gradient_accuracy(accuracy_);
|
---|
| 572 | else
|
---|
| 573 | mole_->set_desired_gradient_accuracy(disp_/1000.0);
|
---|
| 574 | RefSCVector gradv = mole_->get_cartesian_gradient();
|
---|
| 575 | mole_->set_desired_gradient_accuracy(original_accuracy);
|
---|
| 576 | set_gradient(i, gradv);
|
---|
| 577 |
|
---|
| 578 | if (checkpoint_) {
|
---|
| 579 | const char *hessckptfile;
|
---|
| 580 | if (MessageGrp::get_default_messagegrp()->me() == 0) {
|
---|
| 581 | hessckptfile = checkpoint_file_;
|
---|
| 582 | }
|
---|
| 583 | else {
|
---|
| 584 | hessckptfile = "/dev/null";
|
---|
| 585 | }
|
---|
| 586 | StateOutBin so(hessckptfile);
|
---|
| 587 | checkpoint_displacements(so);
|
---|
| 588 | }
|
---|
| 589 | }
|
---|
| 590 | original_geometry();
|
---|
| 591 | RefSymmSCMatrix xhessian = compute_hessian_from_gradients();
|
---|
| 592 | tim_exit("hessian");
|
---|
| 593 |
|
---|
| 594 | symbasis_ = 0;
|
---|
| 595 | delete[] gradients_;
|
---|
| 596 | gradients_ = 0;
|
---|
| 597 | ndisp_ = 0;
|
---|
| 598 |
|
---|
| 599 | return xhessian;
|
---|
| 600 | }
|
---|
| 601 |
|
---|
| 602 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 603 |
|
---|
| 604 | // Local Variables:
|
---|
| 605 | // mode: c++
|
---|
| 606 | // c-file-style: "CLJ-CONDENSED"
|
---|
| 607 | // End:
|
---|