66 std::forward_as_tuple(bottom, top, lon, tra, isQW))
92 auto points = this->
mesh->getElementMesh();
94 std::map<size_t, ActiveRegion3D::Region> regions;
95 std::vector<bool> isQW(points->axis[2]->size());
97 for (
size_t lon = 0; lon < points->axis[0]->size(); ++lon) {
98 for (
size_t tra = 0; tra < points->axis[1]->size(); ++tra) {
99 std::fill(isQW.begin(), isQW.end(),
false);
102 for (
size_t ver = 0;
ver < points->axis[2]->size(); ++
ver) {
103 auto point = points->at(lon, tra,
ver);
104 auto roles = this->
geometry->getRolesAt(point);
106 for (
auto role : roles) {
108 if (role.substr(0, 6) ==
"active")
110 else if (role.substr(0, 8) ==
"junction")
114 if (
cur != 0)
throw BadInput(this->
getId(),
"multiple 'active'/'junction' roles specified");
115 if (role.size() == l)
119 cur = boost::lexical_cast<size_t>(role.substr(l)) + 1;
120 }
catch (boost::bad_lexical_cast&) {
121 throw BadInput(this->
getId(),
"bad active region number in role '{0}'", role);
126 summarizeActiveRegion(regions, num, start,
ver, lon, tra, isQW, points);
132 roles.find(
"QW") != roles.end() || roles.find(
"QD") != roles.end() || roles.find(
"carriers") != roles.end();
134 if (
found != regions.end()) {
136 if (region.
warn && lon != region.
lon && tra != region.
tra &&
137 *
this->geometry->getMaterial(points->at(lon, tra,
ver)) !=
138 *
this->geometry->getMaterial(points->at(region.
lon, region.
tra,
ver))) {
146 summarizeActiveRegion(regions, num, start, points->axis[2]->size(), lon, tra, isQW, points);
151 for (
auto&
ireg : regions) {
155 std::vector<double>
QWz;
156 std::vector<std::pair<size_t, size_t>>
QWbt;
157 double QWheight = 0.;
158 for (
size_t i = reg.
bottom; i < reg.
top; ++i) {
160 if (
QWbt.empty() ||
QWbt.back().second != i)
161 QWbt.emplace_back(i, i + 1);
163 QWbt.back().second = i + 1;
164 QWz.push_back(points->axis[2]->at(i));
165 QWheight += this->
mesh->vert()->at(i + 1) - this->
mesh->vert()->at(i);
169 throw Exception(
"{}: Active region {} does not contain quantum wells", this->
getId(), act);
172 active.emplace(std::piecewise_construct, std::forward_as_tuple(
act),
173 std::forward_as_tuple(
this, reg.
bottom, reg.
top, QWheight, std::move(
QWz), std::move(
QWbt)));
175 this->
writelog(
LOG_DETAIL,
"Total QWs thickness in active region {}: {}nm", act, 1
e3 * QWheight);
215 size_t nn =
active.mesh2->size(), ne =
active.emesh2->size();
217 size_t nm =
active.mesh2->lateralMesh->fullMesh.minorAxis()->size();
226 for (
size_t i = 0; i != ne; ++i) {
227 auto material = this->
geometry->getMaterial(
active.emesh2->at(i));
228 double T = temperature[i];
229 A[i] = material->A(T);
230 B[i] = material->B(T);
231 C[i] = material->C(T);
232 D[i] = 1
e8 * material->D(T);
239 J[i] = abs(js * j.c2);
243 std::vector<DataVector<Tensor2<double>>>
Ps;
244 std::vector<DataVector<double>>
nrs;
259 for (
size_t i = 0; i != nmodes; ++i) {
261 nrs.emplace_back(ne);
264 for (
size_t i = 0; i != ne; ++i) {
265 auto material = this->
geometry->getMaterial(
active.emesh2->at(i));
269 for (
size_t n = 0;
n != nmodes; ++
n) {
273 for (
size_t i = 0; i != nn; ++i) {
274 Ps[
n][i].c00 = (0.5 / Z0) *
real(P[i].c0 *
conj(P[i].c0) + P[i].c1 *
conj(P[i].c1));
275 Ps[
n][i].c11 = (0.5 / Z0) *
real(P[i].c2 *
conj(P[i].c2));
282 std::unique_ptr<FemMatrix>
K;
301 for (
size_t ie = 0;
ie < ne; ++
ie)
308 std::fill(
active.modesP.begin(),
active.modesP.end(), 0.);
309 for (
size_t n = 0;
n != nmodes; ++
n) {
311 double factor =
inv_hc * wavelength;
315 for (
size_t ie = 0;
ie < ne; ++
ie) {
348 double*
kend = K->data +
K->size;
354 for (
auto f =
F.begin(); f !=
F.end(); ++f) {
357 isnan(*f) ?
"nan" :
"inf");
362 for (
auto f =
F.begin(), r =
resid.begin(); f !=
F.end(); ++f, ++r) *r = -*f;
366 for (
auto r =
resid.begin(); r !=
resid.end(); ++r) err += *r * *r;
368 for (
auto f =
F.begin(); f !=
F.end(); ++f)
denorm += *f * *f;
369 err = 100. * sqrt(err /
denorm);
408 : solver(solver), destination_mesh(dest_mesh), interpolationFlags(
InterpolationFlags(solver->geometry)) {
416 auto point = destination_mesh->at(i);
418 Vec<2> wrapped_point;
419 size_t index0_lo, index0_hi, index1_lo, index1_hi;
421 if (!active.mesh2->lateralMesh->prepareInterpolation(vec(point.c0, point.c1), wrapped_point, index0_lo, index0_hi,
422 index1_lo, index1_hi, interpolationFlags))
425 double x = wrapped_point.c0 - active.mesh2->lateralMesh->fullMesh.getAxis0()->at(index0_lo);
426 double y = wrapped_point.c1 - active.mesh2->lateralMesh->fullMesh.getAxis1()->at(index1_lo);
428 ElementParams3D e(active, active.emesh2->lateralMesh->index(index0_lo, index1_lo));
430 const double x2 = x * x, y2 = y * y;
431 const double x3 = x2 * x, y3 = y2 * y;
432 const double X2 = e.X * e.X, Y2 = e.Y * e.Y;
433 const double X3 = X2 * e.X, Y3 = Y2 * e.Y;
436 (-x * y2 * (e.X - x) * (3 * e.Y - 2 * y) * active.U[e.i32] -
437 x * (e.X - x) * (Y3 - 3 * e.Y * y2 + 2 * y3) * active.U[e.i30] +
438 y2 * (3 * e.Y - 2 * y) * (X2 - 2 * e.X * x + x2) * active.U[e.i12] +
439 (X2 - 2 * e.X * x + x2) * (Y3 - 3 * e.Y * y2 + 2 * y3) *
442 (-x2 * y * (3 * e.X - 2 * x) * (e.Y - y) * active.U[e.i23] +
443 x2 * (3 * e.X - 2 * x) * (Y2 - 2 * e.Y * y + y2) * active.U[e.i21] -
444 y * (e.Y - y) * (X3 - 3 * e.X * x2 + 2 * x3) * active.U[e.i03] +
445 (X3 - 3 * e.X * x2 + 2 * x3) * (Y2 - 2 * e.Y * y + y2) *
447 x2 * y2 * (3 * e.X - 2 * x) * (3 * e.Y - 2 * y) * active.U[e.i22] +
448 x2 * (3 * e.X - 2 * x) * (Y3 - 3 * e.Y * y2 + 2 * y3) * active.U[e.i20] +
449 y2 * (3 * e.Y - 2 * y) * (X3 - 3 * e.X * x2 + 2 * x3) * active.U[e.i02] +
450 (X3 - 3 * e.X * x2 + 2 * x3) *
451 (Y3 - 3 * e.Y * y2 + 2 * y3) * active.U[e.i00]) /
465 auto res = interpolation.at(i);
466 if (isnan(res)) return 0.;