40 std::ifstream stream(path);
42 throw std::runtime_error(
"Cannot read cube file: " + path);
45 std::string first_comment;
46 std::string second_comment;
47 std::getline(stream, first_comment);
48 std::getline(stream, second_comment);
51 int number_of_atoms = 0;
53 read_line_values(stream, path, number_of_atoms, origin);
54 if (number_of_atoms < 0) {
55 throw std::runtime_error(
56 "Cube file '" + path +
57 "' declares a negative atom count, which marks a multi-dataset (orbital) cube. "
58 "Q3 reads single-field cubes only.");
61 for (
int axis = 0; axis < 3; axis++) {
64 read_line_values(stream, path, voxel_count, voxel);
70 const int dimension = voxel_count < 0 ? -voxel_count : voxel_count;
72 throw std::runtime_error(
"Cube file '" + path +
"' has a zero grid dimension.");
74 for (
int component = 0; component < 3; component++)
76 voxel[component] * to_bohr * dimension;
79 for (
int atom_index = 0; atom_index < number_of_atoms; atom_index++) {
80 std::istringstream line = next_content_line(stream, path);
81 int atomic_number = 0;
84 line >> atomic_number >> charge >> position.
x >> position.
y >> position.
z;
86 throw std::runtime_error(
"Cube file '" + path +
"' ends inside its atom list.");
93 field.
values.reserve(number_of_grid_points);
95 while (
static_cast<int>(field.
values.size()) < number_of_grid_points && stream >> value)
96 field.
values.push_back(value);
97 if (
static_cast<int>(field.
values.size()) != number_of_grid_points) {
98 throw std::runtime_error(
"Cube file '" + path +
"' holds " +
99 std::to_string(field.
values.size()) +
" values but declares " +
100 std::to_string(number_of_grid_points) +
".");
136 static Vector3D to_crystal_coordinates(
const Matrix3x3& lattice_vectors_bohr,