Phoebe developer's documentation  1.1.0
Phonon and Electron Boltzmann Equations
scattering_matrix.h
1 #ifndef SCATTERING_H
2 #define SCATTERING_H
3 
4 #include "Matrix.h"
5 #include "context.h"
6 #include "delta_function.h"
7 #include "vector_bte.h"
8 
9 // 3 cases:
10 // we compute and store in memory the scattering matrix and the diagonal
11 // we compute the action of the scattering matrix on the in vector, returning outVec = sMatrix*vector
12 // we compute only the linewidths
13 enum MatrixCase {
14  fullMatrix,
15  matrixVectorProduct,
16  linewidthOnly
17 };
18 
23 public:
36  ScatteringMatrix(Context &context_, StatisticsSweep &statisticsSweep_,
37  BaseBandStructure &innerBandStructure_,
38  BaseBandStructure &outerBandStructure_);
39 
42 
50  void setup();
51 
58 
64  double& operator()(const int &row, const int &col);
65 
70  VectorBTE offDiagonalDot(VectorBTE &inPopulation);
71  std::vector<VectorBTE> offDiagonalDot(std::vector<VectorBTE> &inPopulations);
72 
77  VectorBTE dot(VectorBTE &inPopulation);
78  std::vector<VectorBTE> dot(std::vector<VectorBTE> &inPopulations);
79 
80 // /** Computes the product A*B, where A is the scattering matrix, and
81 // * B is an Eigen::MatrixXd. This can be used to compute products of the
82 // * scattering matrix with other vectors.
83 // */
84 // ParallelMatrix<double> dot(const ParallelMatrix<double> &otherMatrix);
85 
90 
97 
103  void setLinewidths(VectorBTE &linewidths);
104 
112  VectorBTE getSingleModeTimes(const VectorBTE& anyInternalDiagonal);
113 
134  VectorBTE getLinewidths(const VectorBTE& anyInternalDiagonal);
135 
144  void a2Omega();
145 
148  void omega2A();
149 
157  std::tuple<Eigen::VectorXd, ParallelMatrix<double>>
158  diagonalize(int numEigenvalues = 0);
159 
173  int getSMatrixIndex(BteIndex &bteIndex, CartIndex &cartIndex);
174 
189  std::tuple<BteIndex, CartIndex> getSMatrixIndex(const int &iMat);
190 
193  void symmetrize();
194 
201  void relaxonsToJSON(const std::string& fileName, const Eigen::VectorXd& eigenvalues);
202 
212  static void symmetrizeCoupling(Eigen::Tensor<double,3>& coupling,
213  const Eigen::VectorXd& energies1,
214  const Eigen::VectorXd& energies2,
215  const Eigen::VectorXd& energies3);
216 
221  std::vector<std::tuple<int, int>> getAllLocalStates();
222 
223  // IO operations ---------
224 
228  void outputToHDF5(const std::string &outFileName);
229 
230  protected:
231 
232  Context &context;
233  StatisticsSweep &statisticsSweep;
234 
235  // Smearing is a pointer created in constructor with a smearing factory
236  // Used in the construction of the scattering matrix to approximate the
237  // Dirac-delta function in transition rates.
238  //DeltaFunction *smearing; // moved to specific ph and el base scatteringMatrix objs
239 
240  BaseBandStructure &innerBandStructure;
241  BaseBandStructure &outerBandStructure;
242 
243  enum MatrixCase matrixCase;
244 
245  // constant relaxation time approximation -> the matrix is just a scalar
246  // and there are simplified evaluations taking place
247  bool constantRTA = false;
248  bool highMemory = true; // whether the matrix is kept in memory
249  bool outputUNTimes = false; // whether to output U and N processes in RTA
250 
251  double boundaryLength;
252  bool doBoundary;
253 
254  // NOTE: about the definition of A
255  // A acts on the canonical population, omega on the population
256  // A acts on f, Omega on n, with n = bose(bose+1)f e.g. for phonons
257  //
258  // Generally: A_out = diagonal of the scattering matrix.
259  // In the case of phonons, A_out = linewidth * n(n+1)
260  // In the case of electrons, A_out = linewidht
261  bool isMatrixOmega = false; // whether the matrix is Omega or A
262 
263  // if we're using the coupled matrix, we need to use this to
264  // save the scattering rates differently
265  bool isCoupled = false;
266 
267  /* function which shifts the indices to the correct quadrant in the CBTE case.
268  * for a pure ph or el matrix, does nothing (default defined here)
269  * @param iBte1, iBte2: the bte indices used to index this quadrant.
270  * @param p1, p2: the particle types indicating the desired quadrant
271  * @return: a tuple containing the shifted indices
272  */
273  std::function<std::tuple<long,long>(long, long, const Particle&, const Particle &)> shiftToCoupledIndices
274  = [](long iBte1, long iBte2, [[maybe_unused]] const Particle &p1, [[maybe_unused]] const Particle &p2){
275  return std::make_tuple(iBte1, iBte2); };
276 
277  // we save the diagonal matrix element in a dedicated vector
278  std::shared_ptr<VectorBTE> internalDiagonal, internalDiagonalUmklapp, internalDiagonalNormal;
279  // the scattering matrix, initialized if highMemory==true
280  ParallelMatrix<double> theMatrix;
281 
282  int numStates; // number of Bloch states (i.e. the size of theMatrix)
283  int numCalculations; // number of "Calculations", i.e. number of temperatures and
284  // chemical potentials on which we compute scattering.
285  int dimensionality_;
286 
287  // number of states for shifting to the coupled matrix
288  int numElStates = 0; // this will never be used unless it's a coupled matrix
289  // however, it still needs to be here because the coupled
290  // shift incides function unfortunately also has to be here. For the case of the
291  // ph matrix, we call phScattering using the BasePh object -- even if the
292  // matrix supplied is a Coupled matrix, the base class's function is called.
293 
294  // this is to exclude problematic Bloch states, e.g. acoustic phonon modes
295  // at gamma, which have zero frequencies and thus have several non-analytic
296  // behaviors (e.g. Bose--Einstein population=infinity). We set to zero
297  // terms related to these states.
298  std::vector<int> excludeIndices;
299 
303  virtual void builder(std::shared_ptr<VectorBTE> linewidth,
304  std::vector<VectorBTE> &inPopulations,
305  std::vector<VectorBTE> &outPopulations) = 0;
306 
324  std::vector<std::tuple<std::vector<int>, int>> getIteratorWavevectorPairs(
325  const bool &rowMajor = false);
326 
338  void degeneracyAveragingLinewidths(std::shared_ptr<VectorBTE> linewidth);
339 
345  Eigen::MatrixXd precomputeOccupations(BaseBandStructure &bandStructure);
346 
352  std::vector<int> getExcludeIndices(BaseBandStructure& bandStructure);
353 
354  /* Set the use case of the scattering matrix into a class enum.
355  * Choices are
356  * we compute and store in memory the scattering matrix and the diagonal
357  * we compute the action of the scattering matrix on the in vector, returning outVec = sMatrix*vector
358  * we compute only the linewidths
359  * @param linewidths pointer to a vectorBTE containing the internal diagonal of the scattering matrix
360  * @param inPopulations particle population the scattering matrix acts on
361  * @param outPopulations particle population Smatrix * inPopulation
362  */
363  void setMatrixCase(std::shared_ptr<VectorBTE> linewidth,
364  std::vector<VectorBTE> &inPopulations,
365  std::vector<VectorBTE> &outPopulations);
366 
377  void addRateToMatrix(const Context &context, double linewidthRate, double matrixRate,
378  int iCalc, int is1, int is2Irr, int iBte1, int iBte2,
379  const Particle &p1, const Particle &p2,
380  const Eigen::Matrix3d &rotation,
381  std::shared_ptr<VectorBTE> linewidth,
382  const std::vector<VectorBTE> &inPopulations,
383  std::vector<VectorBTE> &outPopulations);
384 
388  void enforceDetailedBalance();
389 
393 
397  std::tuple<BaseBandStructure*,BaseBandStructure*> getStateBandStructures(const BteIndex& iBte1,
398  const BteIndex& iBte2);
399 
406  std::tuple<int,int> coupledToBandStructureIndices(const int& iBte1, const int& iBte2,
407  const Particle& p1, const Particle& p2);
408 
417  template <size_t n>
418  void addUNRates(int iCalc, int iBte, double rate,
419  const std::array<Point, n> &crysPoints, auto momentumConsExpr) {
420 
421  if(outputUNTimes) {
422  // Note : for the purpose of folding bzToWs for points,
423  // the bandstructure we use doesn't matter, only the points object
424 
425  // get vectors in ws cell
426  std::array<Eigen::Vector3d, n> wsVectors;
427  for(size_t ipt = 0; ipt < n; ipt++) {
428  Eigen::Vector3d wvCart = crysPoints[ipt].getCoordinates(Points::cartesianCoordinates);
429  Eigen::Vector3d wvWS = outerBandStructure.getPoints().bzToWs(wvCart, Points::cartesianCoordinates);
430  wsVectors[ipt] = wvWS;
431  }
432 
433  // check if this process is umklapp
434  Eigen::Vector3d wvFinalCart = std::apply(momentumConsExpr, wsVectors);
435  Eigen::Vector3d wvFinalFold = outerBandStructure.getPoints().bzToWs(wvFinalCart, Points::cartesianCoordinates);
436  if(abs((wvFinalCart-wvFinalFold).norm()) > 1e-6) {
437  internalDiagonalUmklapp->operator()(iCalc, 0, iBte) += rate;
438  } else {
439  internalDiagonalNormal->operator()(iCalc, 0, iBte) += rate;
440  }
441  }
442  }
443 
444  // friend functions for scattering
445  friend void addBoundaryScattering(ScatteringMatrix &matrix, Context &context,
446  std::vector<VectorBTE> &inPopulations,
447  std::vector<VectorBTE> &outPopulations,
448  BaseBandStructure &outerBandStructure,
449  std::shared_ptr<VectorBTE> linewidth);
450 
451 };
452 
453 #endif
Base class for describing objects containing the band structure, i.e.
Definition: bandstructure.h:15
virtual Points getPoints()=0
Returns the wavevectors on which the band structure is computed.
Class containing the user input variables.
Definition: context.h:15
Class for implementing strong typing.
Definition: utilities.h:51
Determines whether we are dealing with phonons or electrons.
Definition: particle.h:17
Eigen::Vector3d bzToWs(const Eigen::Vector3d &point, const int &basis)
Folds a wavevector in crystal coordinates to the Wigner Seitz zone.
Definition: points.cpp:478
Base class of the scattering matrix.
Definition: scattering_matrix.h:22
VectorBTE offDiagonalDot(VectorBTE &inPopulation)
Computes the product A*f - diagonal(A)*f where A is the scattering matrix and f is the vector of quas...
Definition: scattering_matrix.cpp:188
void replaceMatrixLinewidths()
Replace the linewidths of the scatterng matrix with the supplied VectorBTE values.
Definition: scattering_matrix.cpp:1322
void relaxonsToJSON(const std::string &fileName, const Eigen::VectorXd &eigenvalues)
Output relaxons scattering matrix quantities to file (particularly the tau values) Jenny's note: Howe...
Definition: scattering_matrix.cpp:668
std::tuple< int, int > coupledToBandStructureIndices(const int &iBte1, const int &iBte2, const Particle &p1, const Particle &p2)
If we have a coupled scattering matrix, we need to shift the matrix element indices back to those ass...
Definition: scattering_matrix.cpp:1362
void symmetrize()
Reinforce the condition that the matrix is symmetric.
Definition: scattering_matrix.cpp:1001
VectorBTE getLinewidths()
Converts symmetrized internal scattering matrix diagonal to linewidths and returns the result.
Definition: scattering_matrix.cpp:534
VectorBTE dot(VectorBTE &inPopulation)
Computes the product A*f where A is the scattering matrix and f is the vector of quasiparticle popula...
Definition: scattering_matrix.cpp:276
std::vector< std::tuple< int, int > > getAllLocalStates()
Call the underlying PMatrix function to return the iterator of all elements of the matrix which are l...
Definition: scattering_matrix.cpp:1315
void setLinewidths(VectorBTE &linewidths)
Call to set the single-particle linewidths.
Definition: scattering_matrix.cpp:592
void a2Omega()
Converts the scattering matrix from the form A to the symmetrised Omega.
Definition: scattering_matrix.cpp:366
virtual void builder(std::shared_ptr< VectorBTE > linewidth, std::vector< VectorBTE > &inPopulations, std::vector< VectorBTE > &outPopulations)=0
Method that actually computes the scattering matrix.
std::vector< std::tuple< std::vector< int >, int > > getIteratorWavevectorPairs(const bool &rowMajor=false)
Returns a vector of pairs of wavevector indices to iterate over during the construction of the scatte...
Definition: scattering_matrix.cpp:763
std::vector< int > getExcludeIndices(BaseBandStructure &bandStructure)
Method which for a phonon bandstructure returns the indices to be discarded in a phonon calculation d...
Definition: scattering_matrix.cpp:1289
void enforceDetailedBalance()
A function to fix the linewidths to agree with the off diagonal elements, to enforce finding the spec...
Definition: scattering_matrix.cpp:1432
void addRateToMatrix(const Context &context, double linewidthRate, double matrixRate, int iCalc, int is1, int is2Irr, int iBte1, int iBte2, const Particle &p1, const Particle &p2, const Eigen::Matrix3d &rotation, std::shared_ptr< VectorBTE > linewidth, const std::vector< VectorBTE > &inPopulations, std::vector< VectorBTE > &outPopulations)
Method to add scattering rate to matrix and linewidth containers.
Definition: scattering_matrix.cpp:1071
void outputToHDF5(const std::string &outFileName)
Outputs the matrix to an hdf5 file.
Definition: scattering_matrix.cpp:661
void setup()
This method needs to be called right after the constructor.
Definition: scattering_matrix.cpp:94
VectorBTE diagonal()
Returns the diagonal matrix elements.
Definition: scattering_matrix.cpp:178
double & operator()(const int &row, const int &col)
Get and set operator.
Definition: scattering_matrix.cpp:172
void degeneracyAveragingLinewidths(std::shared_ptr< VectorBTE > linewidth)
Performs an average of the linewidths over degenerate states.
Definition: scattering_matrix.cpp:1029
std::tuple< BaseBandStructure *, BaseBandStructure * > getStateBandStructures(const BteIndex &iBte1, const BteIndex &iBte2)
Returns a tuple of final and initial particles for a give state.
Definition: scattering_matrix.cpp:1391
VectorBTE getSingleModeTimes()
Call to obtain the single-particle relaxation times of the systems.
Definition: scattering_matrix.cpp:531
int getSMatrixIndex(BteIndex &bteIndex, CartIndex &cartIndex)
Function to combine a BTE index and a cartesian index into one index of the scattering matrix.
Definition: scattering_matrix.cpp:982
Eigen::MatrixXd precomputeOccupations(BaseBandStructure &bandStructure)
Function to precompute particle populations before scattering rates are calculated.
Definition: scattering_matrix.cpp:1259
ScatteringMatrix()
Default constructor.
void omega2A()
The inverse of a2Omega, converts the matrix Omega to A.
Definition: scattering_matrix.cpp:435
std::tuple< Eigen::VectorXd, ParallelMatrix< double > > diagonalize(int numEigenvalues=0)
Diagonalize the scattering matrix.
Definition: scattering_matrix.cpp:721
static void symmetrizeCoupling(Eigen::Tensor< double, 3 > &coupling, const Eigen::VectorXd &energies1, const Eigen::VectorXd &energies2, const Eigen::VectorXd &energies3)
Average the coupling for degenerate states.
Definition: scattering_matrix.cpp:1147
void addUNRates(int iCalc, int iBte, double rate, const std::array< Point, n > &crysPoints, auto momentumConsExpr)
Generic function to add UN times to their containers.
Definition: scattering_matrix.h:418
Class for managing a (serial) matrix stored in memory.
Definition: SMatrix.h:20
Object for controlling the loop over temperatures and chemical potentials.
Definition: statistics_sweep.h:26
Class used to store the "vector" of out-of-equilibrium populations.
Definition: vector_bte.h:16