33 enum WhichLevel :
size_t { EL = EnergyLevels::ELECTRONS, HH = EnergyLevels::HEAVY_HOLES, LH = EnergyLevels::LIGHT_HOLES };
37 enum { DIM = GeometryType::DIM };
39 struct ActiveRegionParams;
57 shared_ptr<StackContainer<DIM>>
layers;
63 size_t size()
const {
return layers->getChildrenCount(); }
68 if (
auto m = block->singleMaterial())
return m;
86 bool contains(
const Vec<DIM>& point)
const {
return getBoundingBox().contains(point); }
90 if (!contains(point))
return false;
91 assert(
layers->getChildForHeight(point.vert() - origin.vert()));
92 return layers->getChildForHeight(point.vert() - origin.vert())->getChild()->hasRole(
"QW");
95 double averageNr(
double lam,
double T,
double conc = 0.)
const {
97 for (
size_t i = 0; i != materials.size(); ++i)
98 if (isQW(i)) nr += thicknesses[i] * materials[i]->Nr(lam, T, conc).real();
128 std::vector<double> U[3];
129 std::vector<Tensor2<double>> M[3];
132 std::vector<Level> levels[3];
150 for (
size_t which = 0; which < 3; ++which) {
152 levels[which].reserve(ref.
levels[which].size());
153 for (
Level level : ref.
levels[which]) levels[which].emplace_back(level.E + shift, level.M, level.thickness);
157 double sideU(
WhichLevel which)
const {
return 0.5 * (U[which][0] + U[which][U[which].size() - 1]); }
162 assert(U[which].size() == ref.
U[which].size());
164 for (
size_t i = 0; i < U[which].size(); ++i) {
165 delta += U[which][i] - ref.
U[which][i];
167 return delta / double(U[which].size());
203 bool explicitSubstrate =
false;
223 void estimateWellLevels(WhichLevel which, ActiveRegionParams& params,
size_t qw)
const;
226 void estimateAboveLevels(WhichLevel which, ActiveRegionParams& params)
const;
231 double a = guess - 0.5 * step,
b = guess + 0.5 * step;
232 double fa = f(a), fb = f(
b);
233 if (fa == 0.)
return std::make_pair(a, a);
234 if (fb == 0.)
return std::make_pair(
b,
b);
235 boost::uintmax_t count = max_iter - 1;
236 if ((fa < 0.) == (fa < fb)) {
237 while ((fa < 0.) == (fb < 0.)) {
238 if (count == 0)
return std::make_pair(a,
b);
243 if (fb == 0.)
return std::make_pair(
b,
b);
247 while ((fb < 0.) == (fa < 0.)) {
248 if (count == 0)
return std::make_pair(a,
b);
253 if (fa == 0.)
return std::make_pair(a, a);
257 auto res = toms748_solve(
258 f, a,
b, fa, fb, [
this](
double l,
double r) {
return r - l < levelsep; }, count);
267 double getN(
double F,
double T,
const ActiveRegionParams& params)
const;
270 double getP(
double F,
double T,
const ActiveRegionParams& params)
const;
284 void estimateLevels();
287 void onInitialize()
override;
290 void onInvalidate()
override;
294 outGain.fireChanged();
326 return level(EL,
E, params, well - 1);
328 return level(EL,
E, params);
332 return level(HH,
E, params, well - 1);
334 return level(HH,
E, params);
338 return level(LH,
E, params, well - 1);
340 return level(LH,
E, params);
345 shared_ptr<Material>
getSubstrate()
const {
return substrateMaterial; }
349 bool invalid = substrateMaterial != material;
350 substrateMaterial = material;
351 explicitSubstrate = bool(material);
352 if (invalid) this->invalidate();
356 void findFermiLevels(
double& Fc,
double& Fv,
double n,
double T,
const ActiveRegionParams& params)
const;
359 Tensor2<double> getGain0(
double hw,
double Fc,
double Fv,
double T,
double nr,
const ActiveRegionParams& params)
const;
362 Tensor2<double> getGain(
double hw,
double Fc,
double Fv,
double T,
double nr,
const ActiveRegionParams& params)
const;
375 matrixelem = iMatrixElem;
380 void setStrained(
bool value) {
388 this->initCalculation();
389 return make_shared<GainSpectrum<BaseT>>(
this, point);