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:
|
---|