AlmaBTE  1.3
A solver of the space- and time-dependent Boltzmann transport equation for phonons
structures.hpp
Go to the documentation of this file.
1 // Copyright 2015-2018 The ALMA Project Developers
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 // implied. See the License for the specific language governing
13 // permissions and limitations under the License.
14 
15 #pragma once
16 
19 
20 #include <map>
21 #include <array>
22 #include <vector>
23 #include <utility>
24 #include <numeric>
25 #include <limits>
26 #include <boost/math/special_functions/pow.hpp>
27 #include <boost/mpi.hpp>
28 #include <Eigen/Dense>
29 #include <Eigen/StdVector>
30 #include <cmakevars.hpp>
31 #include <constants.hpp>
32 #include <utilities.hpp>
33 #include <exceptions.hpp>
34 #include <periodic_table.hpp>
35 
36 namespace alma {
37 // Forward declarations placed here for convenience.
38 class Symmetry_operations;
39 class Gamma_grid;
40 class Threeph_process;
41 
43 using Triple_int = std::array<int, 3>;
44 
46 template <typename T>
47 using Triple_int_map =
48  std::map<Triple_int, T, Container_comparator<Triple_int>>;
49 
52 public:
54  const Eigen::Matrix3d lattvec;
56  const Eigen::Matrix<double, 3, Eigen::Dynamic> positions;
58  const std::vector<std::string> elements;
60  const double V;
62  const Eigen::MatrixXd rlattvec;
67  const std::vector<int> numbers;
69  Crystal_structure(Eigen::Matrix3d _lattvec,
70  Eigen::Matrix<double, 3, Eigen::Dynamic> _positions,
71  std::vector<std::string> _elements,
72  std::vector<int> _numbers)
73  : lattvec(std::move(_lattvec)), positions(std::move(_positions)),
74  elements(std::move(_elements)),
75  V(std::fabs(this->lattvec.determinant())),
76  rlattvec(2. * constants::pi * this->lattvec.inverse().transpose()),
77  numbers(std::move(_numbers)) {
78  std::partial_sum(this->numbers.begin(),
79  this->numbers.end(),
80  std::back_inserter(this->partsums));
81 
82  for (int i = 0; i < this->get_natoms(); ++i) {
83  this->masses.emplace_back(alma::get_mass(this->get_element(i)));
84  this->gfactors.emplace_back(
85  alma::get_gfactor(this->get_element(i)));
86  }
87  }
88 
90  Crystal_structure(Eigen::Matrix3d _lattvec,
91  Eigen::Matrix<double, 3, Eigen::Dynamic> _positions,
92  std::vector<std::string> _elements,
93  std::vector<int> _numbers,
94  std::vector<double> _masses)
95  : Crystal_structure(_lattvec, _positions, _elements, _numbers) {
96  if (_masses.size() != static_cast<std::size_t>(this->get_natoms())) {
97  throw value_error("one mass per atom must be provided");
98  }
99  for (int i = 0; i < this->get_natoms(); ++i) {
100  if (_masses[i] <= 0.) {
101  throw value_error("all masses must be positive");
102  }
103  this->masses[i] = _masses[i];
104  }
105  }
106 
108  inline std::vector<std::string>::size_type get_nelements() const {
109  return this->elements.size();
110  }
111 
112 
114  inline int get_natoms() const {
115  return this->positions.cols();
116  }
121  inline std::string get_element(int i) const {
122  if (i >= this->get_natoms())
123  throw value_error("invalid atom number");
124  return this->elements[std::distance(
125  this->partsums.begin(),
126  std::lower_bound(
127  this->partsums.begin(), this->partsums.end(), i + 1))];
128  }
129 
130 
135  inline double get_mass(int i) const {
136  if (i >= this->get_natoms())
137  throw value_error("invalid atom number");
138  return this->masses[i];
139  }
140 
141 
147  inline double get_gfactor(int i) const {
148  if (i >= this->get_natoms())
149  throw value_error("invalid atom number");
150  return this->gfactors[i];
151  }
152 
153 
158  inline bool is_alloy() const {
159  for (auto& e : this->elements)
160  if (e.find(";") != std::string::npos)
161  return true;
162 
163  return false;
164  }
165 
173  inline Eigen::MatrixXd map_to_firstbz(
174  const Eigen::Ref<const Eigen::Vector3d>& q) const {
175  constexpr int sbound = 1;
176  // Step 1: find a single image using a standard approach
177  Eigen::Vector3d qbz{this->rlattvec.colPivHouseholderQr().solve(q)};
178  qbz -= qbz.array().round().matrix().eval();
179  qbz = (this->rlattvec * qbz).eval();
180  double n2 = qbz.squaredNorm();
181  for (int i = -sbound; i <= sbound; ++i) {
182  for (int j = -sbound; j <= sbound; ++j) {
183  for (int k = -sbound; k <= sbound; ++k) {
184  Eigen::Vector3d qbzp{qbz + i * this->rlattvec.col(0) +
185  j * this->rlattvec.col(1) +
186  k * this->rlattvec.col(2)};
187  double n2p = qbzp.squaredNorm();
188  if (n2p < n2) {
189  n2 = n2p;
190  qbz = qbzp;
191  }
192  }
193  }
194  }
195  // Step 2: perform a search to find equivalent images.
196  std::size_t found = 0;
197  int ncols = boost::math::pow<3>(2 * sbound + 1);
198  Eigen::MatrixXd nruter(3, ncols);
199  for (int i = 0; i <= sbound; ++i) {
200  for (int j = -sbound; j <= sbound; ++j) {
201  for (int k = -sbound; k <= sbound; ++k) {
202  Eigen::Vector3d qbzp{qbz + i * this->rlattvec.col(0) +
203  j * this->rlattvec.col(1) +
204  k * this->rlattvec.col(2)};
205  double n2p = qbzp.squaredNorm();
206  if (alma::almost_equal(n2, n2p)) {
207  nruter.col(found) = qbzp;
208  ++found;
209  }
210  }
211  }
212  }
213  return nruter.leftCols(found);
214  }
215 
216 
217 private:
219  std::vector<int> partsums;
222  std::vector<double> masses;
226  std::vector<double> gfactors;
227 };
228 
233 template <class T> class General_harmonic_ifcs {
234 public:
237  const std::vector<Triple_int> pos;
239  const std::vector<T> ifcs;
242  const int na;
245  const int nb;
248  const int nc;
250  General_harmonic_ifcs(std::vector<Triple_int> _pos,
251  std::vector<T> _ifcs,
252  int _na,
253  int _nb,
254  int _nc)
255  : pos(std::move(_pos)), ifcs(std::move(_ifcs)), na(_na), nb(_nb),
256  nc(_nc) {
257  }
258 
259 
260  // Return the number of unit cells.
261  inline std::vector<std::string>::size_type get_ncells() const {
262  return this->pos.size();
263  }
264 };
265 
269 
273 public:
275  const std::vector<Eigen::MatrixXd> born;
277  const Eigen::Matrix3d epsilon;
279  Dielectric_parameters(std::vector<Eigen::MatrixXd> _born,
280  Eigen::Matrix3d _epsilon)
281  : born(std::move(_born)), epsilon(std::move(_epsilon)) {
282  }
283 
284 
287  }
288 };
289 
296 public:
298  const int index;
300  const int ia;
302  const int ib;
304  const int ic;
306  const int iatom;
307  // Basic constructor.
308  Supercell_index(const int _index,
309  const int _ia,
310  const int _ib,
311  const int _ic,
312  const int _iatom)
313  : index(_index), ia(_ia), ib(_ib), ic(_ic), iatom(_iatom) {
314  }
315 
316 
318  inline const Triple_int get_pos() const {
319  return Triple_int({{this->ia, this->ib, this->ic}});
320  }
321 };
322 
325 public:
327  const int na;
329  const int nb;
331  const int nc;
333  const int natoms;
335  Supercell_index_builder(const int _na,
336  const int _nb,
337  const int _nc,
338  const int _natoms);
340  Supercell_index create_index(const int index) const;
341 
343  Supercell_index create_index(const int ia,
344  const int ib,
345  const int ic,
346  const int iatom) const;
347 
350  Supercell_index create_index_safely(const int index) const;
351 
354  Supercell_index create_index_safely(const int ia,
355  const int ib,
356  const int ic,
357  const int iatom) const;
358 };
359 
371 public:
373  const Eigen::VectorXd rj;
375  const Eigen::VectorXd rk;
377  const std::size_t i;
379  const std::size_t j;
381  const std::size_t k;
390  double& ifc(std::size_t alpha, std::size_t beta, std::size_t gamma) {
391  return this->ifcs[gamma + 3 * (beta + 3 * alpha)];
392  }
393 
394 
403  const double& ifc(std::size_t alpha,
404  std::size_t beta,
405  std::size_t gamma) const {
406  return this->ifcs[gamma + 3 * (beta + 3 * alpha)];
407  }
408 
409 
412  Thirdorder_ifcs(const Eigen::VectorXd& _rj,
413  const Eigen::VectorXd& _rk,
414  std::size_t _i,
415  std::size_t _j,
416  std::size_t _k)
417  : rj(std::move(_rj)), rk(std::move(_rk)), i(_i), j(_j), k(_k) {
418  }
419 
420 
421 private:
423  std::array<double, 27> ifcs;
424 };
425 } // namespace alma
const Eigen::VectorXd rk
Cartesian coordinates of the third unit cell.
Definition: structures.hpp:375
const int ic
Unit cel index along the third axis.
Definition: structures.hpp:304
const double V
Volume of the unit cell.
Definition: structures.hpp:60
double get_mass(const std::string &element, bool disablev=false)
Compute the average mass of an element.
Definition: periodic_table.cpp:215
bool almost_equal(const double a, const double b, const double abstol=1e-8, const double reltol=1e-5)
Approximate comparation between doubles.
Definition: utilities.hpp:139
Definition: analytic1d.hpp:26
double get_gfactor(int i) const
Return the g factor of the i-th atom.
Definition: structures.hpp:147
const int nb
Dimension of the supercell originally used for the IFC calculations along the second axis...
Definition: structures.hpp:245
General_harmonic_ifcs(std::vector< Triple_int > _pos, std::vector< T > _ifcs, int _na, int _nb, int _nc)
Basic constructor.
Definition: structures.hpp:250
bool is_alloy() const
Check if any atom belongs to a virtual element.
Definition: structures.hpp:158
Exception related to the parameters passed to a function.
Definition: exceptions.hpp:33
Exceptions used in ALMA.
Phonopy-style atom index represented both as a single integer and as four indices.
Definition: structures.hpp:295
Hold information about the harmonic interactions between atoms.
Definition: structures.hpp:233
STL namespace.
const std::vector< Triple_int > pos
Coordinates of each unit cell for which constants are available.
Definition: structures.hpp:237
std::array< int, 3 > Triple_int
Convenient shorthand for an array of three ints.
Definition: structures.hpp:43
Hold information about the polarization properties of the structure.
Definition: structures.hpp:272
std::string get_element(int i) const
Return the chemical symbol for an atom.
Definition: structures.hpp:121
Thirdorder_ifcs(const Eigen::VectorXd &_rj, const Eigen::VectorXd &_rk, std::size_t _i, std::size_t _j, std::size_t _k)
Basic constructor.
Definition: structures.hpp:412
const Eigen::Matrix3d epsilon
Dielectric tensor.
Definition: structures.hpp:277
double get_mass(int i) const
Return the mass of the i-th atom.
Definition: structures.hpp:135
const int nb
Supercell dimension along the second axis.
Definition: structures.hpp:329
const int nc
Dimension of the supercell originally used for the IFC calculations along the third axis...
Definition: structures.hpp:248
Class representing the anharmonic (third-order) interaction between two atoms atoms.
Definition: structures.hpp:370
const std::size_t i
Index of the first atom.
Definition: structures.hpp:377
const std::vector< std::string > elements
Elements present in the structure.
Definition: structures.hpp:58
const int iatom
Atom index within the unit cell.
Definition: structures.hpp:306
Crystal_structure(Eigen::Matrix3d _lattvec, Eigen::Matrix< double, 3, Eigen::Dynamic > _positions, std::vector< std::string > _elements, std::vector< int > _numbers, std::vector< double > _masses)
Specialized constructor allowing for custom masses.
Definition: structures.hpp:90
Eigen::MatrixXd map_to_firstbz(const Eigen::Ref< const Eigen::Vector3d > &q) const
Find all images of a q point in the first Brillouin zone.
Definition: structures.hpp:173
const std::vector< T > ifcs
Force constants between unit cell 0 and each unit cell.
Definition: structures.hpp:239
const Triple_int get_pos() const
Return an array of three integers {ia, ib, ic}.
Definition: structures.hpp:318
double & ifc(std::size_t alpha, std::size_t beta, std::size_t gamma)
Access a particular ifc using three indexes.
Definition: structures.hpp:390
const Eigen::VectorXd rj
Cartesian coordinates of the second unit cell.
Definition: structures.hpp:373
const Eigen::Matrix< double, 3, Eigen::Dynamic > positions
Atomic positions in lattice coordinates.
Definition: structures.hpp:56
std::map< Triple_int, T, Container_comparator< Triple_int > > Triple_int_map
Specialized version of map whose keys are of class Triple_int.
Definition: structures.hpp:48
Builder for Supercell_index objects sharing the same na, nb, nc.
Definition: structures.hpp:324
const Eigen::MatrixXd rlattvec
Lattice vectors of the reciprocal lattice.
Definition: structures.hpp:62
const int nc
Supercell dimension along the third axis.
Definition: structures.hpp:331
const Eigen::Matrix3d lattvec
Lattice vectors in nm.
Definition: structures.hpp:54
Hold information about a crystal structure.
Definition: structures.hpp:51
const int ib
Unit cell index along the second axis.
Definition: structures.hpp:302
Crystal_structure(Eigen::Matrix3d _lattvec, Eigen::Matrix< double, 3, Eigen::Dynamic > _positions, std::vector< std::string > _elements, std::vector< int > _numbers)
Basic constructor.
Definition: structures.hpp:69
const std::vector< int > numbers
Number of atoms of each element.
Definition: structures.hpp:67
Physical, mathematical and miscellaneous constants used in alma.
int get_natoms() const
Return the number of atoms in the motif.
Definition: structures.hpp:114
const std::size_t j
Index of the second atom.
Definition: structures.hpp:379
const int na
Supercell dimension along the first axis.
Definition: structures.hpp:327
double get_gfactor(const std::string &element, bool disablev=false)
Compute the squared Pearson deviation factor of the mass distribution for an element.
Definition: periodic_table.cpp:243
Dielectric_parameters(std::vector< Eigen::MatrixXd > _born, Eigen::Matrix3d _epsilon)
Basic constructor.
Definition: structures.hpp:279
const std::size_t k
Index of the third atom.
Definition: structures.hpp:381
Dielectric_parameters()
Default constructor. Create an empty object.
Definition: structures.hpp:286
const double & ifc(std::size_t alpha, std::size_t beta, std::size_t gamma) const
Access a particular ifc using three indexes.
Definition: structures.hpp:403
Data about the elements in the periodic table.
const int index
Atom index within the supercell.
Definition: structures.hpp:298
const int ia
Unit cell index along the first axis.
Definition: structures.hpp:300
const int natoms
Number of atoms in the unit cell.
Definition: structures.hpp:333
const std::vector< Eigen::MatrixXd > born
Born charges.
Definition: structures.hpp:275
std::vector< std::string >::size_type get_nelements() const
Return the number of elements in the structure.
Definition: structures.hpp:108
const int na
Dimension of the supercell originally used for the IFC calculations along the first axis...
Definition: structures.hpp:242
Miscellaneous convenience resources.