source: ThirdParty/mpqc_open/src/lib/chemistry/molecule/hess.cc@ 47b463

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 47b463 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 15.8 KB
Line 
1//
2// hess.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 <fstream>
34
35#include <util/class/scexception.h>
36#include <util/misc/formio.h>
37#include <util/keyval/keyval.h>
38#include <util/state/stateio.h>
39#include <math/scmat/blocked.h>
40#include <chemistry/molecule/hess.h>
41#include <chemistry/molecule/molfreq.h>
42
43using namespace std;
44using namespace sc;
45
46/////////////////////////////////////////////////////////////////
47// MolecularHessian
48
49static ClassDesc MolecularHessian_cd(
50 typeid(MolecularHessian),"MolecularHessian",1,"public SavableState",
51 0, 0, 0);
52
53MolecularHessian::MolecularHessian()
54{
55 matrixkit_ = SCMatrixKit::default_matrixkit();
56}
57
58MolecularHessian::MolecularHessian(const Ref<KeyVal>&keyval)
59{
60 mol_ << keyval->describedclassvalue("molecule");
61 matrixkit_ = SCMatrixKit::default_matrixkit();
62}
63
64MolecularHessian::MolecularHessian(StateIn&s):
65 SavableState(s)
66{
67 mol_ << SavableState::restore_state(s);
68 d3natom_ << SavableState::restore_state(s);
69 matrixkit_ = SCMatrixKit::default_matrixkit();
70}
71
72MolecularHessian::~MolecularHessian()
73{
74}
75
76void
77MolecularHessian::save_data_state(StateOut&s)
78{
79 SavableState::save_state(mol_.pointer(),s);
80 SavableState::save_state(d3natom_.pointer(),s);
81}
82
83RefSCDimension
84MolecularHessian::d3natom()
85{
86 if (d3natom_.null()) d3natom_ = new SCDimension(mol_->natom()*3);
87 return d3natom_;
88}
89
90RefSCMatrix
91MolecularHessian::cartesian_to_symmetry(const Ref<Molecule> &mol,
92 Ref<PointGroup> pg,
93 Ref<SCMatrixKit> kit)
94{
95 int i;
96
97 if (pg.null()) pg = mol->point_group();
98 if (kit.null()) kit = SCMatrixKit::default_matrixkit();
99
100 // create the character table for the point group
101 CharacterTable ct = pg->char_table();
102
103 int ng = ct.order();
104 int nirrep = ct.nirrep();
105 int natom = mol->natom();
106 RefSCDimension d3natom = new SCDimension(3*natom);
107
108 // Form the matrix of basis vectors in cartesian coordinates
109 RefSCMatrix cartbasis(d3natom,d3natom,kit);
110 cartbasis.assign(0.0);
111 for (i=0; i<3*natom; i++) {
112 cartbasis(i,i) = 1.0;
113 }
114
115 // Project out translations and rotations
116 RefSCDimension dext(new SCDimension(6));
117 // form a basis for the translation and rotation coordinates
118 RefSCMatrix externalbasis(d3natom,dext,kit);
119 externalbasis.assign(0.0);
120 for (i=0; i<natom; i++) {
121 SCVector3 atom(mol->r(i));
122 for (int j=0; j<3; j++) {
123 externalbasis(i*3 + j,j) = 1.0;
124 }
125 externalbasis(i*3 + 1, 3 + 0) = atom[2];
126 externalbasis(i*3 + 2, 3 + 0) = -atom[1];
127 externalbasis(i*3 + 0, 3 + 1) = atom[2];
128 externalbasis(i*3 + 2, 3 + 1) = -atom[0];
129 externalbasis(i*3 + 0, 3 + 2) = atom[1];
130 externalbasis(i*3 + 1, 3 + 2) = -atom[0];
131 }
132 // do an SVD on the external basis
133 RefSCMatrix Uext(d3natom,d3natom,kit);
134 RefSCMatrix Vext(dext,dext,kit);
135 RefSCDimension min;
136 if (d3natom.n()<dext.n()) min = d3natom;
137 else min = dext;
138 int nmin = min.n();
139 RefDiagSCMatrix sigmaext(min,kit);
140 externalbasis.svd(Uext,sigmaext,Vext);
141 // find the epsilon rank
142 const double epsilonext = 1.0e-4;
143 int rankext = 0;
144 for (i=0; i<nmin; i++) {
145 if (sigmaext(i) > epsilonext) rankext++;
146 }
147 ExEnv::out0() << indent << "The external rank is " << rankext << endl;
148 // find the projection onto the externalbasis perp space
149 if (rankext) {
150 RefSCDimension drankext_tilde = new SCDimension(d3natom.n() - rankext);
151 RefSCMatrix Uextr_tilde(d3natom,drankext_tilde,kit);
152 Uextr_tilde.assign_subblock(Uext,
153 0, d3natom.n()-1,
154 0, drankext_tilde.n()-1,
155 0, rankext);
156 RefSymmSCMatrix projext_perp(d3natom, kit);
157 projext_perp.assign(0.0);
158 projext_perp.accumulate_symmetric_product(Uextr_tilde);
159 cartbasis = projext_perp * cartbasis;
160 }
161
162 // Form the mapping of atom numbers to transformed atom number
163 int **atom_map = new int*[natom];
164 for (i=0; i < natom; i++) atom_map[i] = new int[ng];
165 // loop over all centers
166 for (i=0; i < natom; i++) {
167 SCVector3 ac(mol->r(i));
168 // then for each symop in the pointgroup, transform the coordinates of
169 // center "i" and see which atom it maps into
170 for (int g=0; g < ng; g++) {
171 double np[3];
172 SymmetryOperation so = ct.symm_operation(g);
173 for (int ii=0; ii < 3; ii++) {
174 np[ii] = 0;
175 for (int jj=0; jj < 3; jj++) np[ii] += so(ii,jj) * ac[jj];
176 }
177 atom_map[i][g] = mol->atom_at_position(np, 0.05);
178 if (atom_map[i][g] < 0) {
179 throw ProgrammingError("atom mapping bad",
180 __FILE__, __LINE__);
181 }
182 }
183 }
184
185 int *dims = new int[nirrep];
186
187 RefSCMatrix *symmbasis = new RefSCMatrix[nirrep];
188
189 // Project the cartesian basis into each irrep
190 SymmetryOperation so;
191 for (i=0; i<nirrep; i++) {
192 IrreducibleRepresentation irrep = ct.gamma(i);
193 RefSCMatrix *components = new RefSCMatrix[irrep.degeneracy()];
194 // loop over the components of this irrep
195 int j;
196 for (j=0; j<irrep.degeneracy(); j++) {
197 // form the projection matrix for this component of this irrep
198 RefSCMatrix projmat(d3natom,d3natom,kit);
199 projmat.assign(0.0);
200 // form the projection matrix for irrep i component j
201 // loop over the symmetry operators
202 for (int g=0; g < ng; g++) {
203 double coef = ((double)irrep.character(g)*irrep.degeneracy())/ng;
204 so = ct.symm_operation(g);
205 for (int atom=0; atom<natom; atom++) {
206 for (int ii=0; ii < 3; ii++) {
207 for (int jj=0; jj < 3; jj++) {
208 projmat.accumulate_element(atom_map[atom][g]*3+ii,
209 atom*3 + jj,
210 coef * so(ii,jj));
211 }
212 }
213 }
214 }
215 // projection matrix for irrep i, component j is formed
216 RefSCMatrix cartbasis_ij = projmat * cartbasis;
217 RefSCMatrix U(d3natom, d3natom, kit);
218 RefSCMatrix V(d3natom, d3natom, kit);
219 RefDiagSCMatrix sigma(d3natom, kit);
220 cartbasis_ij.svd(U, sigma, V);
221 // Compute the epsilon rank of cartbasis ij
222 const double epsilon = 1.0e-3;
223 int k, rank = 0;
224 for (k=0; k<3*natom; k++) {
225 if (sigma(k) > epsilon) rank++;
226 }
227 if (!rank) continue;
228 // Find an orthogonal matrix that spans the range of cartbasis ij
229 RefSCDimension drank = new SCDimension(rank);
230 RefSCMatrix Ur(d3natom,drank,kit);
231 Ur.assign_subblock(U,0, d3natom.n()-1, 0, drank.n()-1, 0, 0);
232 // Reassign cartbasis_ij to the orthonormal basis
233 cartbasis_ij = Ur;
234 components[j] = cartbasis_ij;
235 }
236 int nbasisinirrep = 0;
237 for (j=0; j<irrep.degeneracy(); j++) {
238 nbasisinirrep += components[j].ncol();
239 }
240
241 dims[i] = nbasisinirrep;
242 RefSCDimension dirrep = new SCDimension(nbasisinirrep);
243 symmbasis[i] = kit->matrix(d3natom,dirrep);
244 int offset = 0;
245 for (j=0; j<irrep.degeneracy(); j++) {
246 symmbasis[i]->assign_subblock(
247 components[j],
248 0, d3natom.n()-1,
249 offset, offset+components[j].ncol()-1,
250 0, 0);
251 offset += components[j].ncol();
252 }
253 delete[] components;
254 }
255
256 int total = 0;
257 for (i=0; i<nirrep; i++) {
258 total += dims[i];
259 }
260 Ref<SCBlockInfo> bi = new SCBlockInfo(total, nirrep, dims);
261 for (i=0; i<nirrep; i++) {
262 bi->set_subdim(i, symmbasis[i]->coldim());
263 }
264 RefSCDimension dsym = new SCDimension(bi);
265
266 RefSCDimension bd3natom = new SCDimension(3*mol->natom());
267 bd3natom->blocks()->set_subdim(0,d3natom);
268
269 Ref<SCMatrixKit> symkit = new BlockedSCMatrixKit(kit);
270 RefSCMatrix result(dsym, bd3natom, symkit);
271 BlockedSCMatrix *bresult = dynamic_cast<BlockedSCMatrix*>(result.pointer());
272
273 // put the symmetric basis in the result matrix
274 for (i=0; i<nirrep; i++) {
275 if (dims[i]>0) bresult->block(i).assign(symmbasis[i].t());
276 }
277
278 delete[] symmbasis;
279
280 for (i=0; i<natom; i++) delete[] atom_map[i];
281 delete[] atom_map;
282
283 delete[] dims;
284 return result;
285}
286
287void
288MolecularHessian::set_energy(const Ref<MolecularEnergy> &)
289{
290}
291
292MolecularEnergy*
293MolecularHessian::energy() const
294{
295 return 0;
296}
297
298void
299MolecularHessian::write_cartesian_hessian(const char *filename,
300 const Ref<Molecule> &mol,
301 const RefSymmSCMatrix &hess)
302{
303 int ntri = (3*mol->natom()*(3*mol->natom()+1))/2;
304 double *hessv = new double[ntri];
305 hess->convert(hessv);
306 if (MessageGrp::get_default_messagegrp()->me() == 0) {
307 int i,j;
308 ofstream out(filename);
309 // file format is version text 1
310 out << "Hessian VT1" << endl;
311 out << mol->natom() << " atoms" << endl;
312 for (i=0; i<mol->natom(); i++) {
313 out << scprintf("%2d % 15.12f % 15.12f % 15.12f",
314 mol->Z(i), mol->r(i,0), mol->r(i,1), mol->r(i,2))
315 << endl;
316
317 }
318 const int nrow = 5;
319 for (i=0; i<ntri; ) {
320 for (j=0; j<nrow && i<ntri; j++,i++) {
321 if (j>0) out << " ";
322 out << scprintf("% 15.12f", hessv[i]);
323 }
324 out << endl;
325 }
326 out << "End Hessian" << endl;
327 }
328 delete[] hessv;
329}
330
331void
332MolecularHessian::read_cartesian_hessian(const char *filename,
333 const Ref<Molecule> &mol,
334 const RefSymmSCMatrix &hess)
335{
336 int ntri = (3*mol->natom()*(3*mol->natom()+1))/2;
337 double *hessv = new double[ntri];
338 Ref<MessageGrp> grp = MessageGrp::get_default_messagegrp();
339 if (grp->me() == 0) {
340 int i;
341 ifstream in(filename);
342 const int nline = 100;
343 char linebuf[nline];
344 in.getline(linebuf, nline);
345 if (strcmp(linebuf,"Hessian VT1")) {
346 throw FileOperationFailed("not given a hessian file",
347 __FILE__, __LINE__, filename,
348 FileOperationFailed::Corrupt);
349 }
350 int natom;
351 in >> natom;
352 if (natom != mol->natom()) {
353 throw FileOperationFailed("wrong number of atoms in hessian file",
354 __FILE__, __LINE__, filename,
355 FileOperationFailed::Corrupt);
356 }
357 in.getline(linebuf,nline);
358 //ExEnv::outn() << "READ: should be atoms: " << linebuf << endl;
359 for (i=0; i<mol->natom(); i++) {
360 int Z;
361 double x, y, z;
362 in >> Z >> x >> y >> z;
363 //ExEnv::outn() << "READ: " << Z << " " << x << " " << y << " " << z << endl;
364 }
365 for (i=0; i<ntri; i++) {
366 in >> hessv[i];
367 //ExEnv::outn() << "READ: hess[" << i << "] = " << hessv[i] << endl;
368 }
369 in.getline(linebuf, nline);
370 //ExEnv::outn() << "READ: last line = " << linebuf << endl;
371 if (strcmp(linebuf,"End Hessian")) {
372 // try once more since there could be a left over new line
373 in.getline(linebuf, nline);
374 if (strcmp(linebuf,"End Hessian")) {
375 //ExEnv::outn() << "READ: last line = " << linebuf << endl;
376 throw FileOperationFailed("hessian file seems to be truncated",
377 __FILE__, __LINE__, filename,
378 FileOperationFailed::Corrupt);
379 }
380 }
381 }
382 grp->bcast(hessv,ntri);
383 hess->assign(hessv);
384 delete[] hessv;
385}
386
387/////////////////////////////////////////////////////////////////
388// ReadMolecularHessian
389
390static ClassDesc ReadMolecularHessian_cd(
391 typeid(ReadMolecularHessian),"ReadMolecularHessian",1,"public MolecularHessian",
392 0, create<ReadMolecularHessian>, create<ReadMolecularHessian>);
393
394ReadMolecularHessian::ReadMolecularHessian(const Ref<KeyVal>&keyval):
395 MolecularHessian(keyval)
396{
397 KeyValValueString default_filename(SCFormIO::fileext_to_filename(".hess"),
398 KeyValValueString::Steal);
399 filename_ = keyval->pcharvalue("filename", default_filename);
400}
401
402ReadMolecularHessian::ReadMolecularHessian(StateIn&s):
403 SavableState(s),
404 MolecularHessian(s)
405{
406 s.getstring(filename_);
407}
408
409ReadMolecularHessian::~ReadMolecularHessian()
410{
411 delete[] filename_;
412}
413
414void
415ReadMolecularHessian::save_data_state(StateOut&s)
416{
417 MolecularHessian::save_data_state(s);
418 s.putstring(filename_);
419}
420
421RefSymmSCMatrix
422ReadMolecularHessian::cartesian_hessian()
423{
424 RefSymmSCMatrix hess = matrixkit()->symmmatrix(d3natom());
425 read_cartesian_hessian(filename_, mol_, hess);
426 return hess;
427}
428
429/////////////////////////////////////////////////////////////////
430// GuessMolecularHessian
431
432static ClassDesc GuessMolecularHessian_cd(
433 typeid(GuessMolecularHessian),"GuessMolecularHessian",1,"public MolecularHessian",
434 0, create<GuessMolecularHessian>, create<GuessMolecularHessian>);
435
436GuessMolecularHessian::GuessMolecularHessian(const Ref<KeyVal>&keyval):
437 MolecularHessian(keyval)
438{
439 coor_ << keyval->describedclassvalue("coor");
440 if (mol_.null()) mol_ = coor_->molecule();
441}
442
443GuessMolecularHessian::GuessMolecularHessian(StateIn&s):
444 SavableState(s),
445 MolecularHessian(s)
446{
447 coor_ << SavableState::restore_state(s);
448}
449
450GuessMolecularHessian::~GuessMolecularHessian()
451{
452}
453
454void
455GuessMolecularHessian::save_data_state(StateOut&s)
456{
457 MolecularHessian::save_data_state(s);
458 SavableState::save_state(coor_.pointer(),s);
459}
460
461RefSymmSCMatrix
462GuessMolecularHessian::cartesian_hessian()
463{
464 RefSymmSCMatrix hessian(coor_->dim(), coor_->matrixkit());
465 coor_->guess_hessian(hessian);
466 RefSymmSCMatrix xhessian(coor_->dim_natom3(), coor_->matrixkit());
467 coor_->to_cartesian(xhessian,hessian);
468 return xhessian;
469}
470
471/////////////////////////////////////////////////////////////////
472// DiagMolecularHessian
473
474static ClassDesc DiagMolecularHessian_cd(
475 typeid(DiagMolecularHessian),"DiagMolecularHessian",1,"public MolecularHessian",
476 0, create<DiagMolecularHessian>, create<DiagMolecularHessian>);
477
478DiagMolecularHessian::DiagMolecularHessian(const Ref<KeyVal>&keyval):
479 MolecularHessian(keyval)
480{
481 diag_ = keyval->doublevalue("diag",KeyValValuedouble(1.0));
482}
483
484DiagMolecularHessian::DiagMolecularHessian(StateIn&s):
485 SavableState(s),
486 MolecularHessian(s)
487{
488 s.get(diag_);
489}
490
491DiagMolecularHessian::~DiagMolecularHessian()
492{
493}
494
495void
496DiagMolecularHessian::save_data_state(StateOut&s)
497{
498 MolecularHessian::save_data_state(s);
499 s.put(diag_);
500}
501
502RefSymmSCMatrix
503DiagMolecularHessian::cartesian_hessian()
504{
505 RefSymmSCMatrix xhessian(d3natom(), matrixkit());
506 xhessian->assign(0.0);
507 xhessian->shift_diagonal(diag_);
508 return xhessian;
509}
510
511/////////////////////////////////////////////////////////////////////////////
512
513// Local Variables:
514// mode: c++
515// c-file-style: "CLJ"
516// End:
Note: See TracBrowser for help on using the repository browser.