AlmaBTE  1.3
A solver of the space- and time-dependent Boltzmann transport equation for phonons
aux_cubic.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 
21 
22 #include <cmath>
23 #include <boost/math/special_functions/pow.hpp>
24 
25 namespace alma {
26 namespace aux_cubic {
28 inline double I1(double x0) {
29  return std::log(std::abs((1. - x0) / x0));
30 }
31 
33 inline double I2(double dd, double ee) {
34  double den{std::sqrt(4. * ee - boost::math::pow<2>(dd))};
35 
36  return -2. * (std::atan(dd / den) - std::atan((dd + 2. * ee) / den)) / den;
37 }
38 
40 inline double I3(double dd, double ee) {
41  double den = std::sqrt(4. * ee - boost::math::pow<2>(dd));
42 
43  return (2. * dd * (std::atan(dd / den) - std::atan((dd + 2. * ee) / den)) +
44  den * std::log1p(dd + ee)) /
45  (2 * ee * den);
46 }
47 
52 private:
54  const std::array<double, 4> coeff;
55 
56 public:
63  Cubic_segment(double a, double b, double ap, double bp)
64  : coeff({{-(2. * a + ap - 2. * b + bp),
65  -(-3. * a - 2. * ap + 3. * b - bp),
66  -ap,
67  -a}}) {
68  }
76  std::array<double, 4> calc_integrals(double ener) const {
77  // Coefficients of the full polynomial in the
78  // denominator.
79  std::array<double, 4> p(this->coeff);
80  p[3] += ener;
81  // Get the number of roots based on the value of the
82  // discriminant for the third-order equation.
83  double a{p[1] / p[0]};
84  double b{p[2] / p[0]};
85  double c{p[3] / p[0]};
86  double a2{boost::math::pow<2>(a)};
87  double q{(a2 - 3. * b) / 9.};
88  double r{(a * (2. * a2 - 9. * b) + 27. * c) / 54.};
89  double r2{boost::math::pow<2>(r)};
90  double q3{boost::math::pow<3>(q)};
91  std::array<double, 4> nruter({{0., 0., 0., 0.}});
92 
93  // And use the formulae specific to each case.
94  if (r2 < q3) {
95  // Three real roots.
96  double th{std::acos(r / std::sqrt(q3))};
97  double q12{std::sqrt(q)};
98  double x0{-2. * q12 * std::cos(th / 3.) - a / 3.};
99  double x1{-2. * q12 * std::cos((th + 2. * constants::pi) / 3.) -
100  a / 3.};
101  double x2{-2. * q12 * std::cos((th - 2. * constants::pi) / 3.) -
102  a / 3.};
103  double pref{-x0 * x1 * x2 / p[3]};
104  double aa{pref / ((x0 - x1) * (x0 - x2))};
105  double bb{pref / ((x1 - x0) * (x1 - x2))};
106  double cc{pref / ((x2 - x0) * (x2 - x1))};
107  nruter[0] = aa * I1(x0) + bb * I1(x1) + cc * I1(x2);
108  double aax{x0 * aa};
109  double bbx{x1 * bb};
110  double ccx{x2 * cc};
111  nruter[1] = aax * I1(x0) + bbx * I1(x1) + ccx * I1(x2);
112 
113  if ((0. < x0) && (x0 < 1.)) {
114  nruter[2] += std::abs(aa);
115  nruter[3] += std::abs(aax);
116  }
117 
118  if ((0. < x1) && (x1 < 1.)) {
119  nruter[2] += std::abs(bb);
120  nruter[3] += std::abs(bbx);
121  }
122 
123  if ((0. < x2) && (x2 < 1.)) {
124  nruter[2] += std::abs(cc);
125  nruter[3] += std::abs(ccx);
126  }
127  nruter[2] *= constants::pi;
128  nruter[3] *= constants::pi;
129  }
130  else {
131  // Only one real root.
132  double A{-signum(r) * std::cbrt(std::abs(r) + std::sqrt(r2 - q3))};
133  double B{(A == 0. ? 0. : q / A)};
134  double x0{A + B - a / 3.};
135  double dd{A + B + 2. * a / 3.};
136  double ee{boost::math::pow<2>(dd / 2.) +
137  .75 * boost::math::pow<2>(A - B)};
138  double pref{-x0 * ee / p[3]};
139  double aa{pref / (x0 * (x0 + dd) + ee)};
140  double bb{-(x0 + dd) * aa};
141  double cc{-aa};
142  double aax{x0 * aa};
143  double bbx{ee * aa};
144  double ccx{-aax};
145  nruter[0] = aa * I1(x0) + (bb / ee) * I2(dd / ee, 1. / ee) +
146  (cc / ee) * I3(dd / ee, 1. / ee);
147  nruter[1] = aax * I1(x0) + (bbx / ee) * I2(dd / ee, 1. / ee) +
148  (ccx / ee) * I3(dd / ee, 1. / ee);
149 
150  if ((0. < x0) && (x0 < 1.)) {
151  nruter[2] = constants::pi * std::abs(aa);
152  nruter[3] = constants::pi * std::abs(aax);
153  }
154  }
155  return nruter;
156  }
157 };
158 } // namespace aux_cubic
159 } // namespace alma
Definition: analytic1d.hpp:26
Objects of this class perform rational integrals of the kind found when approximating bands by piecew...
Definition: aux_cubic.hpp:51
double I2(double dd, double ee)
Auxiliary function used when computing rational integrals.
Definition: aux_cubic.hpp:33
double I3(double dd, double ee)
Auxiliary function used when computing rational integrals.
Definition: aux_cubic.hpp:40
std::array< double, 4 > calc_integrals(double ener) const
Obtain the values of the four integrals needed for the calculation of the Green&#39;s function at a parti...
Definition: aux_cubic.hpp:76
double I1(double x0)
Auxiliary function used when computing rational integrals.
Definition: aux_cubic.hpp:28
Cubic_segment(double a, double b, double ap, double bp)
Constructor.
Definition: aux_cubic.hpp:63
int signum(const T &arg)
Compute the sign of an argument.
Definition: utilities.hpp:224