source: ThirdParty/mpqc_open/src/lib/chemistry/molecule/taylor.cc@ 7516f6

Action_Thermostats Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.1 ChemicalSpaceEvaluator Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Exclude_Hydrogens_annealWithBondGraph Fix_Verbose_Codepatterns ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion Gui_displays_atomic_force_velocity JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool PythonUI_with_named_parameters Recreated_GuiChecks StoppableMakroAction TremoloParser_IncreasedPrecision
Last change on this file since 7516f6 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: 7.7 KB
Line 
1//
2// taylor.cc
3//
4// Copyright (C) 1996 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 <util/class/scexception.h>
33#include <util/misc/formio.h>
34#include <util/state/stateio.h>
35#include <math/scmat/local.h>
36#include <chemistry/molecule/taylor.h>
37
38using namespace std;
39using namespace sc;
40
41static ClassDesc TaylorMolecularEnergy_cd(
42 typeid(TaylorMolecularEnergy),"TaylorMolecularEnergy",1,"public MolecularEnergy",
43 0, create<TaylorMolecularEnergy>, create<TaylorMolecularEnergy>);
44
45// Note: this gets the values of the coordinates from the current molecule
46// rather than the coordinates.
47TaylorMolecularEnergy::TaylorMolecularEnergy(const Ref<KeyVal>&keyval):
48 MolecularEnergy(keyval)
49{
50 coordinates_ << keyval->describedclassvalue("coordinates");
51 // if coordinates is nonnull use cartesian coordinates
52 if (coordinates_.nonnull()) {
53 dim_ = new SCDimension(coordinates_->n());
54 }
55 else {
56 dim_ = moldim();
57 }
58 if (coordinates_.nonnull()) {
59 expansion_point_ = matrixkit()->vector(dim_);
60 coordinates_->update_values(molecule());
61 coordinates_->values_to_vector(expansion_point_);
62 }
63 else {
64 expansion_point_ = get_cartesian_x();
65 }
66
67 e0_ = keyval->doublevalue("e0");
68
69 // count the number of force constants
70 int i;
71 int n_fc1 = keyval->count("force_constants_1");
72 int n_fc = keyval->count("force_constants");
73
74 int use_guess_hessian = 0;
75 if (coordinates_.null() && n_fc == 0) {
76 use_guess_hessian = 1;
77 n_fc = (moldim().n()*(moldim().n()+1))/2;
78 maxorder_ = 2;
79 }
80
81 force_constant_index_.resize(n_fc1+n_fc);
82 force_constant_value_.resize(n_fc1+n_fc);
83 maxorder_ = 0;
84 if (n_fc1 > 0) maxorder_ = 1;
85
86 // first read in the short hand notation for first derivatives
87 for (i=0; i<n_fc1; i++) {
88 force_constant_value_[i] = keyval->doublevalue("force_constants_1", i);
89 force_constant_index_[i].resize(1);
90 force_constant_index_[i][0] = i;
91 }
92
93 if (use_guess_hessian) {
94 RefSymmSCMatrix hess(moldim(), matrixkit());
95 guess_hessian(hess);
96 int ifc,j;
97 for (ifc=i=0; i<moldim().n(); i++) {
98 for (j=0; j<=i; j++, ifc++) {
99 force_constant_index_[n_fc1+ifc].resize(2);
100 force_constant_index_[n_fc1+ifc][0] = i;
101 force_constant_index_[n_fc1+ifc][1] = j;
102 force_constant_value_[n_fc1+ifc] = hess->get_element(i,j);
103 }
104 }
105 }
106 else {
107 // read in the general force constants
108 for (i=0; i<n_fc; i++) {
109 int order = keyval->count("force_constants", i) - 1;
110 force_constant_value_[n_fc1+i]
111 = keyval->doublevalue("force_constants", i,order);
112 force_constant_index_[n_fc1+i].resize(order);
113 if (maxorder_ < order) maxorder_ = order;
114 for (int j=0; j<order; j++) {
115 force_constant_index_[n_fc1+i][j]
116 = keyval->intvalue("force_constants",i,j) - 1;
117 }
118 }
119 }
120}
121
122TaylorMolecularEnergy::~TaylorMolecularEnergy()
123{
124}
125
126TaylorMolecularEnergy::TaylorMolecularEnergy(StateIn&s):
127 SavableState(s),
128 MolecularEnergy(s)
129{
130 throw ProgrammingError("cannot save state for this class",
131 __FILE__, __LINE__, class_desc());
132}
133
134void
135TaylorMolecularEnergy::save_data_state(StateOut&s)
136{
137 MolecularEnergy::save_data_state(s);
138 throw ProgrammingError("cannot save state for this class",
139 __FILE__, __LINE__, class_desc());
140}
141
142void
143TaylorMolecularEnergy::print(ostream&o) const
144{
145 MolecularEnergy::print(o);
146 if (coordinates_.nonnull()) coordinates_->print_details(molecule(), o);
147 int nfc = force_constant_index_.size();
148 o << indent << "Force Constants:" << endl;
149 o << incindent;
150 for (int i=0; i<nfc; i++) {
151 int order = force_constant_index_[i].size();
152 for (int j=0; j<order; j++) {
153 o << indent << scprintf("%5d",force_constant_index_[i][j]+1);
154 }
155 o << indent
156 << scprintf(" %*.*f",14,10,force_constant_value_[i])
157 << endl;
158 }
159 o << decindent;
160}
161
162// this is used by the factor function
163static int
164factorial(int i)
165{
166 if (i<2) return 1;
167 return i*factorial(i-1);
168}
169
170// Compute the factors such as 1/4!, etc. assuming that only unique
171// force constants we given.
172static double
173factor(std::vector<int>&indices)
174{
175 std::map<int,int> n_occur;
176 int i;
177 for (i=0; i<indices.size(); i++) {
178 n_occur[indices[i]] = 0;
179 }
180 for (i=0; i<indices.size(); i++) {
181 n_occur[indices[i]]++;
182 }
183 int n_indices = indices.size();
184 int int_factor = 1;
185 std::map<int,int>::iterator I;
186 for (I=n_occur.begin(); I!=n_occur.end(); I++) {
187 int n = I->second;
188 int_factor *= factorial(n_indices)
189 /(factorial(n)*factorial(n_indices-n));
190 n_indices -= n;
191 }
192 double term = ((double)int_factor) / factorial(indices.size());
193 return term;
194}
195
196void
197TaylorMolecularEnergy::compute()
198{
199 RefSCVector geometry;
200
201 if (coordinates_.nonnull()) {
202 coordinates_->update_values(molecule());
203 geometry = expansion_point_.clone();
204 coordinates_->values_to_vector(geometry);
205 }
206 else {
207 geometry = get_cartesian_x();
208 }
209
210 RefSCVector displacement = geometry - expansion_point_;
211
212 if (value_needed()) {
213 double e = e0_;
214 for (int i=0; i<force_constant_index_.size(); i++) {
215 double term = force_constant_value_[i]
216 * factor(force_constant_index_[i]);
217 for (int j=0; j<force_constant_index_[i].size(); j++) {
218 term *= displacement(force_constant_index_[i][j]);
219 }
220 e += term;
221 }
222 set_energy(e);
223 set_actual_value_accuracy(desired_value_accuracy());
224 }
225 if (gradient_needed()) {
226 RefSCVector gradient = expansion_point_.clone();
227 gradient.assign(0.0);
228
229 for (int i=0; i<force_constant_index_.size(); i++) {
230 double f = force_constant_value_[i]
231 * factor(force_constant_index_[i]);
232 for (int k=0; k<force_constant_index_[i].size(); k++) {
233 double t = 1.0;
234 for (int l=0; l<force_constant_index_[i].size(); l++) {
235 if (l == k) continue;
236 t *= displacement(force_constant_index_[i][l]);
237 }
238 gradient.accumulate_element(force_constant_index_[i][k],f*t);
239 }
240 }
241
242 // this will only work for cartesian coordinates
243 set_gradient(gradient);
244 set_actual_gradient_accuracy(desired_gradient_accuracy());
245 }
246}
247
248int
249TaylorMolecularEnergy::value_implemented() const
250{
251 return 1;
252}
253
254int
255TaylorMolecularEnergy::gradient_implemented() const
256{
257 return coordinates_.null() && maxorder_ >= 1;
258}
259
260int
261TaylorMolecularEnergy::hessian_implemented() const
262{
263 return 0;
264}
265
266/////////////////////////////////////////////////////////////////////////////
267
268// Local Variables:
269// mode: c++
270// c-file-style: "CLJ"
271// End:
Note: See TracBrowser for help on using the repository browser.