votca 2024.2-dev
Loading...
Searching...
No Matches
potentialfunctioncbspl.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
19#include <boost/lexical_cast.hpp>
20#include <iostream>
21#include <votca/tools/table.h>
22
23using namespace std;
24using namespace votca::tools;
25
26namespace votca {
27namespace csg {
28
30 double min, double max)
31 : PotentialFunction(name, nlam, min, max) {
32
33 /* Here nlam_ is the total number of coeff values that are to be optimized
34 * To ensure that potential and force go to zero smoothly near cut-off,
35 * as suggested in Ref. PCCP, 11, 1901, 2009, coeff values leading up to
36 * cut-off and beyond take a value of zero.
37 *
38 * Since region less than rmin is not sampled sufficiently for stability
39 * first nexcl_ coefficients are not optimized instead their values are
40 * extrapolated from first statistically significant knot values near rmin
41 */
42
43 Index nknots;
44
45 nknots = lam_.size();
46
47 nbreak_ = nknots - 2;
48
49 dr_ = (cut_off_) / (double(nbreak_ - 1));
50
51 // break point locations
52 // since ncoeff = nbreak +2 , r values for last two coefficients are also
53 // computed
54 rbreak_ = Eigen::VectorXd::Zero(nknots);
55
56 for (Index i = 0; i < nknots; i++) {
57 rbreak_(i) = double(i) * dr_;
58 }
59
60 // exclude knots corresponding to r <= min_
61 nexcl_ = std::min((Index)(min_ / dr_), nbreak_ - 2) + 1;
62
63 // account for finite numerical division of min_/ dr_
64 // e.g. 0.24/0.02 may result in 11.99999999999999
65 if (rbreak_(nexcl_) == min_) {
66 nexcl_++;
67 }
68
69 // fixing last 4 knots to zeros is reasonable
70 ncutcoeff_ = 4;
71
72 // check if we have enough parameters to optimize
73 if ((Index(lam_.size()) - nexcl_ - ncutcoeff_) < 1) {
74 throw std::runtime_error(
75 "In potential " + name_ +
76 ": no parameters to optimize!\n"
77 "All the knot values fall in the range of either excluded (due to high "
78 "repulsive region) or cut-off region.\n"
79 "This issue can be resolved by one or combination of following steps:\n"
80 "1. Make sure you are using large-enough cut-off for this CG "
81 "potential.\n"
82 "2. Make sure the CG-MD runs are sufficiently Index and CG-MD RDF are "
83 "statistically reliable.\n"
84 "3. Use more knot values.\n");
85 }
86
87 M_ = Eigen::MatrixXd::Zero(4, 4);
88 M_(0, 0) = 1.0;
89 M_(0, 1) = 4.0;
90 M_(0, 2) = 1.0;
91 M_(0, 3) = 0.0;
92 M_(1, 0) = -3.0;
93 M_(1, 1) = 0.0;
94 M_(1, 2) = 3.0;
95 M_(1, 3) = 0.0;
96 M_(2, 0) = 3.0;
97 M_(2, 1) = -6.0;
98 M_(2, 2) = 3.0;
99 M_(2, 3) = 0.0;
100 M_(3, 0) = -1.0;
101 M_(3, 1) = 3.0;
102 M_(3, 2) = -3.0;
103 M_(3, 3) = 1.0;
104 M_ /= 6.0;
105}
106
108
109 return lam_.size() - nexcl_ - ncutcoeff_;
110}
111
112void PotentialFunctionCBSPL::setParam(string filename) {
113
114 Table param;
115 param.Load(filename);
116 lam_.setZero();
117
118 if (param.size() != lam_.size()) {
119
120 throw std::runtime_error("In potential " + name_ +
121 ": parameters size mismatch!\n"
122 "Check input parameter file \"" +
123 filename + "\" \nThere should be " +
124 boost::lexical_cast<string>(lam_.size()) +
125 " parameters");
126 } else {
127 // force last ncutcoeff_ to zero
128 Index nonzero = lam_.size() - ncutcoeff_;
129 lam_.head(nonzero) = param.y().head(nonzero);
130 }
131}
132
133void PotentialFunctionCBSPL::SaveParam(const string &filename) {
134
136
137 Table param;
138 param.SetHasYErr(false);
139 param.resize(lam_.size());
140
141 // write extrapolated knots with flag 'o'
142 // points close to rmin can also be stastically not reliable
143 // so flag 3 more points next to rmin as 'o'
144 for (Index i = 0; i < nexcl_ + 3; i++) {
145 param.set(i, rbreak_(i), lam_(i), 'o');
146 }
147
148 for (Index i = nexcl_ + 3; i < lam_.size(); i++) {
149 param.set(i, rbreak_(i), lam_(i), 'i');
150 }
151
152 param.Save(filename);
153}
154
155void PotentialFunctionCBSPL::SavePotTab(const string &filename, double step,
156 double rmin, double rcut) {
158 PotentialFunction::SavePotTab(filename, step, rmin, rcut);
159}
160
161void PotentialFunctionCBSPL::SavePotTab(const string &filename, double step) {
163 PotentialFunction::SavePotTab(filename, step);
164}
165
167
168 double u0 = lam_(nexcl_);
169 double m = (lam_(nexcl_ + 1) - lam_(nexcl_)) /
170 (rbreak_(nexcl_ + 1) - rbreak_(nexcl_));
171 double r0 = rbreak_(nexcl_);
172
173 /* If the slope m is positive then the potential core
174 * will be attractive. So, artificially forcing core to be
175 * repulsive by setting m = -m
176 */
177 if (m > 0) {
178 cout << name_ << " potential's extrapolated core is attractive!" << endl;
179 cout << "Artifically enforcing repulsive core.\n" << endl;
180 m *= -1.0;
181 }
182 // using linear extrapolation
183 // u(r) = ar + b
184 // a = m
185 // b = - m*r0 + u0
186 // m = (u1-u0)/(r1-r0)
187
188 double a = m;
189 double b = -1.0 * m * r0 + u0;
190 for (Index i = 0; i < nexcl_; i++) {
191 lam_(i) = a * rbreak_(i) + b;
192 }
193}
194
196
197 lam_(i + nexcl_) = val;
198}
199
201
202 return lam_(i + nexcl_);
203}
204
206
207 if (r <= cut_off_) {
208
209 double u = 0.0;
210 Index indx = std::min((Index)(r / dr_), nbreak_ - 2);
211 double rk = (double)indx * dr_;
212 double t = (r - rk) / dr_;
213
214 Eigen::Vector4d R = Eigen::Vector4d::Zero();
215 R(0) = 1.0;
216 R(1) = t;
217 R(2) = t * t;
218 R(3) = t * t * t;
219 Eigen::Vector4d B = lam_.segment<4>(indx);
220 u += ((R.transpose() * M_) * B).value();
221 return u;
222
223 } else {
224 return 0.0;
225 }
226}
227
228// calculate first derivative w.r.t. ith parameter
230
231 // since first nexcl_ parameters are not optimized for stability reasons
232
233 if (r <= cut_off_) {
234
235 Index i_opt = i + nexcl_;
236 Index indx;
237 double rk;
238
239 indx = std::min((Index)(r / dr_), nbreak_ - 2);
240 rk = (double)indx * dr_;
241
242 if (i_opt >= indx && i_opt <= indx + 3) {
243
244 Eigen::Vector4d R = Eigen::Vector4d::Zero();
245
246 double t = (r - rk) / dr_;
247
248 R(0) = 1.0;
249 R(1) = t;
250 R(2) = t * t;
251 R(3) = t * t * t;
252
253 Eigen::Vector4d RM = R.transpose() * M_;
254
255 return RM(i_opt - indx);
256
257 } else {
258 return 0.0;
259 }
260
261 } else {
262 return 0.0;
263 }
264}
265
266// calculate second derivative w.r.t. ith parameter
268
269 return 0.0;
270}
271
272} // namespace csg
273} // namespace votca
void SaveParam(const std::string &filename) override
double getOptParam(const Index i) const override
double CalculateDF(const Index i, const double r) const override
double CalculateF(const double r) const override
PotentialFunctionCBSPL(const std::string &name, const Index nlam, const double min=0.0, const double max=10.0)
void SavePotTab(const std::string &filename, const double step) override
double CalculateD2F(const Index i, const Index j, const double r) const override
void setOptParam(const Index i, const double val) override
void setParam(std::string filename) override
virtual void SavePotTab(const std::string &filename, double step)
class to store tables like rdfs, tabulated potentials, etc
Definition table.h:36
Index size() const
Definition table.h:42
void SetHasYErr(bool has_yerr)
Definition table.h:81
void set(const Index &i, const double &x, const double &y)
Definition table.h:52
void Load(std::string filename)
Definition table.cc:47
void resize(Index N)
Definition table.cc:38
double & y(Index i)
Definition table.h:45
void Save(std::string filename) const
Definition table.cc:59
STL namespace.
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26