Super-Charged Pow() for Faster Mobility
This MR adds a "new" mobility model called canali_fast
which provides a significantly faster calculation ob charge carrier mobilities from the Canali model. The main culprit of the model'\s function are the two calls to std::pow(x, y)
:
\mu(E) = \frac{v_m}{E_c} \frac{1}{\left(1 + (E / E_c)^\beta \right)^{1 / \beta}}
where \beta
is a floating-point number. In some simulations, exactly these calculations were representing by far the hottest code snippet of the entire framework as demonstrated in this Intel OneAPI VTune snippet (bottom-up list):
What can we do about it? There are loads of (sometimes wonky) approximations to power calculations around - but would we really want to include something that affects our charge carrier velocity in odd and abrupt ways like this?
Certainly not. This might be good enough for a game engine, but not a scientific simulation.
But wait - can't we have a closer look at our equation? Do we really need the full power (haha, pun intended) of std::pow(double, double)
? After all, out \beta
is a constant (and also 1/\beta
fwiw). How about making a nice table of std::pow(x, beta)
for all the values we need?
So this is what this MR implements - a TabulatedPow
class that pre-calculates a table of std::pow(x, Y)
values where Y
is fixed and x
has a specified range. Values are looked up from this table and linearly interpolated between the neighboring bins such that the distribution is smooth.
The following parameter values have been chose:
- 1000 bins per table - this seems reasonable and is definitely enough judging from the precision plots below
- For the two
std::pow
calls with different exponents (and also for the two carrier types) separate tables are calculated.- For the
\beta
table, the range is set to[0, 100kV/cm/E_c]
- For the
1/\beta
table, the range is configured as[1, (100kV/cm/E_c)^{\beta}]
- For the
- The ranges are chosen such that a smooth interpolation is provided for electric field strengths (this is
\sqrt{\vec{E}}
and therefore positive!) between 0kV/cm and 100kV/cm, and a linear extrapolation beyond those ranges.
Now - bring it on, how precise is it in comparison with the regular Canali implementation? Well, here's the inverse mobility:
And the drift velocity:
Less than 0.2% uncertainty on the drift velocity at very low electric field values - where drift will play a significant role.
Enjoy.