GQCP
Loading...
Searching...
No Matches
Field.hpp
Go to the documentation of this file.
1// This file is part of GQCG-GQCP.
2//
3// Copyright (C) 2017-2020 the GQCG developers
4//
5// GQCG-GQCP is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GQCG-GQCP is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GQCG-GQCP. If not, see <http://www.gnu.org/licenses/>.
17
18#pragma once
19
20
24
25#include <algorithm>
26#include <functional>
27#include <vector>
28
29
30namespace GQCP {
31
32
38template <typename T_>
39class Field {
40public:
41 // The type of the evaluated function values.
42 using T = T_;
43
44private:
45 // The evaluated function values, in the order of the grid's loop.
46 std::vector<T> m_values;
47
48
49public:
50 /*
51 * MARK: Constructors
52 */
53
59 Field(const std::vector<T>& values) :
60 m_values {values} {}
61
62
63 /*
64 * MARK: Named constructors.
65 */
66
74 template <typename Z = T>
76
77 // Prepare the input file.
78 std::ifstream input_file_stream = validateAndOpen(filename, "cube");
79
80
81 // Skip the first two comment lines.
82 std::string line;
83 std::getline(input_file_stream, line);
84 std::getline(input_file_stream, line);
85
86
87 // Figure out the number of atoms, in order to ignore that information later on.
88 std::getline(input_file_stream, line);
89
90 // Split the line on any whitespace or tabs.
91 std::vector<std::string> splitted_line; // create a container for the line to be split in
92
93 boost::trim_if(line, boost::is_any_of(" \t"));
94 boost::split(splitted_line, line, boost::is_any_of(" \t"), boost::token_compress_on);
95
96 const auto number_of_atoms = std::stoi(splitted_line[0]);
97
98
99 // The next three lines contain the number of steps.
100 size_t grid_size {1}; // will contain the total grid size after parsing
101 for (size_t i = 0; i < 3; i++) {
102 std::getline(input_file_stream, line);
103
104 // Split the line on any whitespace or tabs.
105 boost::trim_if(line, boost::is_any_of(" \t"));
106 boost::split(splitted_line, line, boost::is_any_of(" \t"), boost::token_compress_on);
107
108 // The first column contains the number of steps.
109 grid_size *= static_cast<size_t>(std::stoll(splitted_line[0]));
110 }
111
112
113 // Skip the lines containing atomic information.
114 for (size_t i = 0; i < number_of_atoms; i++) {
115 std::getline(input_file_stream, line);
116 }
117
118
119 // Finally, read in all field values.
120 std::vector<double> field_values;
121 field_values.reserve(grid_size); // allocate memory for all the grid points
122
123 while (std::getline(input_file_stream, line)) {
124
125 // Split the line on any whitespace or tabs.
126 boost::trim_if(line, boost::is_any_of(" \t"));
127 boost::split(splitted_line, line, boost::is_any_of(" \t"), boost::token_compress_on);
128
129 // Add the field values from this line to the total array.
130 for (const auto& value : splitted_line) {
131 field_values.push_back(std::stod(value)); // no worries about push_back, since we have reserved enough memory up-front
132 }
133 }
134
135 input_file_stream.close();
136
137 return Field<double>(field_values);
138 }
139
140
161 template <int N>
162 static Field<Vector<double, N>> ReadGridFile(const std::string& filename) {
163
164 // Find the extension of the given path (https://stackoverflow.com/a/51992).
165 std::string filename_extension; // will contain the extension of the given filename
166 std::string::size_type idx = filename.rfind('.');
167
168 if (idx != std::string::npos) {
169 filename_extension = filename.substr(idx + 1);
170 } else {
171 throw std::invalid_argument("Field::ReadGridFile(const std::string&): I did not find an extension in your given file name.");
172 }
173
174
175 // Check if the user supplied an .rgrid- or .igrid-file.
176 if ((filename_extension != "rgrid") && (filename_extension != "igrid")) {
177 throw std::invalid_argument("Field::ReadGridFile(const std::string&): The given file is not an .igrid- or .rgrid-file.");
178 }
179
180
181 // If the filename isn't properly converted into an input file stream, we assume the user supplied a wrong file
182 std::ifstream input_file_stream {filename};
183 if (!input_file_stream.good()) {
184 throw std::invalid_argument("validateAndOpen(const std::string&, const std::string&): The provided file name is illegible. Maybe you specified a wrong path?");
185 }
186
187
188 // Do the actual parsing.
189 std::vector<Vector<double, N>> field_values;
190
191 std::string line;
192 while (std::getline(input_file_stream, line)) {
193 std::vector<std::string> splitted_line; // create a container for the line to be split in
194
195 // Split the line on any whitespace or tabs.
196 boost::trim_if(line, boost::is_any_of(" \t"));
197 boost::split(splitted_line, line, boost::is_any_of(" \t"), boost::token_compress_on);
198
199 // We can skip the first 4 columns (index and grid point coordinates).
200
201 // Read the field value by converting the string(s) to a double and using Eigen::Map to instantiate the correct Vector.
202 std::vector<double> field_value_vector;
203 for (size_t index = 4; index < 4 + N; index++) {
204 field_value_vector.push_back(std::stod(splitted_line[index]));
205 }
206 Eigen::Map<Eigen::VectorXd> field_value {field_value_vector.data(), N};
207 field_values.push_back(Vector<double, N>(field_value));
208
209
210 // We can skip the weight column as well.
211 }
212 input_file_stream.close();
213
214
215 // Convert the std::vector of weights to an Array.
216 return Field<Vector<double, N>>(field_values);
217 }
218
219
220 /*
221 * MARK: Canonical mathematical operators (https://en.cppreference.com/w/cpp/language/operators)
222 */
223
234
235 std::transform(this->m_values.begin(), this->m_values.end(), rhs.values().begin(),
236 this->m_values.begin(), std::plus<T>());
237
238 return *this;
239 }
240
241
252 friend Field<T> operator+(Field<T> lhs, const Field<T>& rhs) {
253
254 lhs += rhs;
255 return lhs;
256 }
257
258
265
266 std::vector<T> result;
267 result.reserve(this->size());
268
269 std::transform(this->m_values.begin(), this->m_values.end(),
270 std::back_inserter(result), std::negate<T>());
271
272 return result;
273 }
274
275
286
287 // Define subtraction as addition with the negation.
288 *this += (-rhs);
289 return *this;
290 }
291
292
303 friend Field<T> operator-(Field<T> lhs, const Field<T>& rhs) {
304
305 lhs -= rhs;
306 return lhs;
307 }
308
309
310 /*
311 * MARK: General information
312 */
313
317 size_t size() const { return this->m_values.size(); }
318
319
320 /*
321 * MARK: Mappings
322 */
323
329 void map(const std::function<T(const T&)>& function) {
330
331 std::transform(this->m_values.begin(), this->m_values.end(), this->m_values.begin(),
332 function);
333 }
334
335
343 Field<T> mapped(const std::function<T(const T&)>& function) const {
344
345 auto this_copy = *this;
346 this_copy.map(function);
347
348 return this_copy;
349 }
350
351
352 /*
353 * MARK: Access
354 */
355
363 const T& value(const size_t index) const { return this->m_values[index]; }
364
372 T& value(const size_t index) { return this->m_values[index]; }
373
377 const std::vector<T>& values() const { return this->m_values; }
378};
379
380
381/*
382 * Convenience aliases for fields.
383 */
384
385template <typename Scalar>
387
388template <typename Scalar>
390
391
392} // namespace GQCP
Definition: Field.hpp:39
T_ T
Definition: Field.hpp:42
Field< T > operator-() const
Definition: Field.hpp:264
friend Field< T > operator+(Field< T > lhs, const Field< T > &rhs)
Definition: Field.hpp:252
const T & value(const size_t index) const
Definition: Field.hpp:363
static enable_if_t< std::is_same< Z, double >::value, Field< double > > ReadCubeFile(const std::string &filename)
Definition: Field.hpp:75
const std::vector< T > & values() const
Definition: Field.hpp:377
void map(const std::function< T(const T &)> &function)
Definition: Field.hpp:329
T & value(const size_t index)
Definition: Field.hpp:372
Field(const std::vector< T > &values)
Definition: Field.hpp:59
size_t size() const
Definition: Field.hpp:317
friend Field< T > operator-(Field< T > lhs, const Field< T > &rhs)
Definition: Field.hpp:303
Field< T > & operator+=(const Field< T > &rhs)
Definition: Field.hpp:233
Field< T > mapped(const std::function< T(const T &)> &function) const
Definition: Field.hpp:343
Field< T > & operator-=(const Field< T > &rhs)
Definition: Field.hpp:285
static Field< Vector< double, N > > ReadGridFile(const std::string &filename)
Definition: Field.hpp:162
Definition: Matrix.hpp:47
Definition: BaseOneElectronIntegralBuffer.hpp:25
typename std::enable_if< B, T >::type enable_if_t
Definition: type_traits.hpp:37
std::ifstream validateAndOpen(const std::string &filename, const std::string &extension)
Definition: miscellaneous.cpp:266