votca 2024.2-dev
Loading...
Searching...
No Matches
csg_resample.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2021 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
18// Standard includes
19#include <iostream>
20
21// Third party includes
22#include <boost/program_options.hpp>
23
24// VOTCA includes
28#include <votca/tools/spline.h>
29#include <votca/tools/table.h>
31
32// Local VOTCA includes
33#include "votca/csg/version.h"
34
35using namespace std;
36namespace po = boost::program_options;
37using namespace votca::csg;
38using namespace votca::tools;
39
40void help_text() {
41 votca::csg::HelpTextHeader("csg_resample");
42 cout << "Change grid and interval of any sort of table files.\n"
43 "Mainly called internally by inverse script, can also be\n"
44 "used to manually prepare input files for coarse-grained\n"
45 "simulations.\n\n";
46}
47
48void check_option(po::options_description &desc, po::variables_map &vm,
49 const string &option) {
50 if (!vm.count(option)) {
51 cout << "csg_resample \n\n";
52 cout << desc << endl << "parameter " << option << " is not specified\n";
53 exit(1);
54 }
55}
56
57int main(int argc, char **argv) {
58
59 string in_file, out_file, grid, fitgrid, comment, type, boundaries;
60
61 Table in, out, der;
62 // program options
63 po::options_description desc("Allowed options");
64
65 desc.add_options()("help", "produce this help message")(
66 "in", po::value<string>(&in_file), "table to read")(
67 "out", po::value<string>(&out_file), "table to write")(
68 "derivative", po::value<string>(), "table to write")(
69 "grid", po::value<string>(&grid),
70 "new grid spacing (min:step:max). If 'grid' is specified only, "
71 "interpolation is performed.")(
72 "type", po::value<string>(&type)->default_value("akima"),
73 "[cubic|akima|linear]. If option is not specified, the default type "
74 "'akima' is assumed.")("fitgrid", po::value<string>(&fitgrid),
75 "specify fit grid (min:step:max). If 'grid' and "
76 "'fitgrid' are specified, a fit is performed.")(
77 "nocut",
78 "Option for fitgrid: Normally, values out of fitgrid boundaries are cut "
79 "off. If they shouldn't, choose --nocut.")(
80 "comment", po::value<string>(&comment),
81 "store a comment in the output table")(
82 "boundaries", po::value<string>(&boundaries),
83 "(natural|periodic|derivativezero) sets boundary conditions");
84
85 po::variables_map vm;
86 try {
87 po::store(po::parse_command_line(argc, argv, desc), vm);
88 po::notify(vm);
89 } catch (po::error &err) {
90 cout << "error parsing command line: " << err.what() << endl;
91 return -1;
92 }
93
94 try {
95 // does the user want help?
96 if (vm.count("help")) {
97 help_text();
98 cout << desc << endl;
99 return 0;
100 }
101
102 check_option(desc, vm, "in");
103 check_option(desc, vm, "out");
104
105 if (!(vm.count("grid") || vm.count("fitgrid"))) {
106 cout << "Need grid for interpolation or fitgrid for fit.\n";
107 return 1;
108 }
109
110 if ((!vm.count("grid")) && vm.count("fitgrid")) {
111 cout << "Need a grid for fitting as well.\n";
112 return 1;
113 }
114
115 double min, max, step;
116 {
117 vector<string> toks = Tokenizer(grid, ":").ToVector();
118 if (toks.size() != 3) {
119 cout << "wrong range format, use min:step:max\n";
120 return 1;
121 }
122 min = stod(toks[0]);
123 step = stod(toks[1]);
124 max = stod(toks[2]);
125 }
126
127 in.Load(in_file);
128 std::unique_ptr<Spline> spline;
129 if (vm.count("type")) {
130 if (type == "cubic") {
131 spline = std::make_unique<CubicSpline>(CubicSpline());
132 } else if (type == "akima") {
133 spline = std::make_unique<AkimaSpline>(AkimaSpline());
134 } else if (type == "linear") {
135 spline = std::make_unique<LinSpline>(LinSpline());
136 } else {
137 throw std::runtime_error("unknown spline type:" + type);
138 }
139 }
140 spline->setBC(Spline::splineNormal);
141
142 if (vm.count("boundaries")) {
143 if (boundaries == "periodic") {
144 spline->setBC(Spline::splinePeriodic);
145 }
146 if (boundaries == "derivativezero") {
147 spline->setBC(Spline::splineDerivativeZero);
148 }
149 // default: normal
150 }
151
152 // in case fit is specified
153 if (vm.count("fitgrid")) {
154 vector<string> toks = Tokenizer(fitgrid, ":").ToVector();
155 if (toks.size() != 3) {
156 cout << "wrong range format in fitgrid, use min:step:max\n";
157 return 1;
158 }
159 double sp_min, sp_max, sp_step;
160 sp_min = stod(toks[0]);
161 sp_step = stod(toks[1]);
162 sp_max = stod(toks[2]);
163 cout << "doing " << type << " fit " << sp_min << ":" << sp_step << ":"
164 << sp_max << endl;
165
166 // cut off any values out of fitgrid boundaries (exception: do nothing in
167 // case of --nocut)
168 Eigen::VectorXd x_copy;
169 Eigen::VectorXd y_copy;
170 if (!vm.count("nocut")) {
171 // determine vector size
172 votca::Index minindex = -1, maxindex = -1;
173 for (votca::Index i = 0; i < in.x().size(); i++) {
174 if (in.x(i) < sp_min) {
175 minindex = i;
176 }
177 if (in.x(i) <= sp_max) {
178 maxindex = i;
179 }
180 }
181 // copy data values in [sp_min,sp_max] into new vectors
182 minindex++;
183 x_copy = Eigen::VectorXd::Zero(maxindex - minindex + 1);
184 y_copy = Eigen::VectorXd::Zero(maxindex - minindex + 1);
185 for (votca::Index i = minindex; i <= maxindex; i++) {
186 x_copy(i - minindex) = in.x(i);
187 y_copy(i - minindex) = in.y(i);
188 }
189 }
190
191 // fitting
192 spline->GenerateGrid(sp_min, sp_max, sp_step);
193 try {
194 if (vm.count("nocut")) {
195 spline->Fit(in.x(), in.y());
196 } else {
197 spline->Fit(x_copy, y_copy);
198 }
199 } catch (const char *message) {
200 if (strcmp("qrsolve_zero_column_in_matrix", message)) {
201 throw std::runtime_error(
202 "error in Linalg::linalg_qrsolve : Not enough data for fit, "
203 "please adjust grid (zero row in fit matrix)");
204 } else if (strcmp("constrained_qrsolve_zero_column_in_matrix",
205 message)) {
206 throw std::runtime_error(
207 "error in Linalg::linalg_constrained_qrsolve : Not enough data "
208 "for fit, please adjust grid (zero row in fit matrix)");
209 } else {
210 throw std::runtime_error(
211 "Unknown error in csg_resample while fitting.");
212 }
213 }
214 } else {
215 // otherwise do interpolation (default = cubic)
216 try {
217 spline->Interpolate(in.x(), in.y());
218 } catch (const char *message) {
219 if (strcmp("qrsolve_zero_column_in_matrix", message)) {
220 throw std::runtime_error(
221 "error in Linalg::linalg_qrsolve : Not enough data, please "
222 "adjust grid (zero row in fit matrix)");
223 } else if (strcmp("constrained_qrsolve_zero_column_in_matrix",
224 message)) {
225 throw std::runtime_error(
226 "error in Linalg::linalg_constrained_qrsolve : Not enough data, "
227 "please adjust grid (zero row in fit matrix)");
228 } else {
229 throw std::runtime_error(
230 "Unknown error in csg_resample while interpolating.");
231 }
232 }
233 }
234
235 out.GenerateGridSpacing(min, max, step);
236 out.y() = spline->Calculate(out.x());
237
238 // store a comment line
239 if (vm.count("comment")) {
240 out.set_comment(comment);
241 }
242 out.flags() = std::vector<char>(out.flags().size(), 'o');
243
244 der.GenerateGridSpacing(min, max, step);
245 der.flags() = std::vector<char>(der.flags().size(), 'o');
246
247 votca::Index i = 0;
248 for (i = 0; out.x(i) < in.x(0) && i < out.size(); ++i) {
249 ;
250 }
251
252 votca::Index j = 0;
253 for (; i < out.size(); ++i) {
254 for (; j < in.size(); ++j) {
255 if (in.x(j) >= out.x(i) ||
256 std::abs(in.x(j) - out.x(i)) < 1e-12) { // fix for precision errors
257 break;
258 }
259 }
260 if (in.size() == j) {
261 break;
262 }
263 out.flags(i) = in.flags(j);
264 der.flags(i) = in.flags(j);
265 }
266
267 out.Save(out_file);
268
269 if (vm.count("derivative")) {
270 der.y() = spline->CalculateDerivative(der.x());
271
272 der.Save(vm["derivative"].as<string>());
273 }
274
275 } catch (std::exception &error) {
276 cerr << "an error occurred:\n" << error.what() << endl;
277 return -1;
278 }
279 return 0;
280}
An Akima Spline Class.
Definition akimaspline.h:44
A cubic spline class.
Definition cubicspline.h:54
A Linear Spline Class.
Definition linspline.h:34
@ splineDerivativeZero
derivatives and end-points are zero.
Definition spline.h:76
@ splinePeriodic
periodic boundary conditions:
Definition spline.h:75
@ splineNormal
normal boundary conditions:
Definition spline.h:74
class to store tables like rdfs, tabulated potentials, etc
Definition table.h:36
double & x(Index i)
Definition table.h:44
Index size() const
Definition table.h:42
void GenerateGridSpacing(double min, double max, double spacing)
Definition table.cc:180
void Load(std::string filename)
Definition table.cc:47
char & flags(Index i)
Definition table.h:49
void set_comment(const std::string comment)
Definition table.h:70
double & y(Index i)
Definition table.h:45
void Save(std::string filename) const
Definition table.cc:59
break string into words
Definition tokenizer.h:72
std::vector< T > ToVector()
store all words in a vector of type T, does type conversion.
Definition tokenizer.h:109
int main(int argc, char **argv)
void help_text()
void check_option(po::options_description &desc, po::variables_map &vm, const string &option)
STL namespace.
void HelpTextHeader(const std::string &tool_name)
Definition version.cc:42
Eigen::Index Index
Definition types.h:26