28 std::map<size_t, FreeCarrierGainSolver3D::Region>
regions;
29 std::vector<bool> isQW(points->axis[2]->size());
30 std::vector<shared_ptr<Material>> materials(points->axis[2]->size());
32 for (
size_t lon = 0; lon < points->axis[0]->size(); ++lon) {
33 for (
size_t tra = 0; tra < points->axis[1]->size(); ++tra) {
34 std::fill(isQW.begin(), isQW.end(),
false);
38 for (
size_t ver = 0;
ver < points->axis[2]->size(); ++
ver) {
39 auto point = points->at(lon, tra,
ver);
41 materials[
ver] = material;
42 auto roles = this->
geometry->getRolesAt(point);
44 for (
auto role : roles) {
45 if (role.substr(0, 6) ==
"active") {
46 if (
cur != 0)
throw BadInput(this->
getId(),
"multiple 'active' roles specified");
47 if (role.size() == 6) {
51 cur = boost::lexical_cast<size_t>(role.substr(6)) + 1;
52 }
catch (boost::bad_lexical_cast&) {
53 throw BadInput(this->
getId(),
"bad active region number in role '{0}'", role);
56 }
else if (role ==
"substrate") {
58 this->
writelog(
LOG_WARNING,
"Explicit substrate layer specified, role 'substrate' ignored");
63 throw Exception(
"{0}: Non-uniform substrate layer.", this->
getId());
67 if (cur == 0 && roles.find(
"QW") != roles.end())
68 throw Exception(
"{0}: All marked quantum wells must belong to marked active region.", this->
getId());
71 throw Exception(
"{0}: Different active regions {1} and {2} may not be directly adjacent", this->
getId(),
75 FreeCarrierGainSolver3D::Region& region =
77 .
emplace(std::piecewise_construct, std::forward_as_tuple(num),
78 std::forward_as_tuple(start,
ver, lon, tra, isQW, materials))
82 if (start != region.bottom ||
ver != region.top)
83 throw Exception(
"{0}: Active region {1} does not have top and bottom edges at constant heights",
84 this->
getId(), num - 1);
86 for (
size_t i = region.bottom; i < region.top; ++i) {
87 if (isQW[i] != region.isQW[i])
88 throw Exception(
"{0}: Active region {1} does not have QWs at constant heights", this->
getId(),
92 if (
found !=
regions.end() && lon != region.lon && tra != region.tra &&
93 *region.materials.back() != *material)
94 throw Exception(
"{0}: Active region {1} has non-uniform top cladding", this->
getId(), num - 1);
100 isQW[
ver] = roles.find(
"QW") != roles.end() ;
103 FreeCarrierGainSolver3D::Region& region =
found->second;
104 if (lon != region.lon && tra != region.tra) {
105 if (*materials[
ver] != *region.materials[
ver - region.bottom + 1])
106 throw Exception(
"{0}: Active region {1} is laterally non-uniform", this->
getId(), num - 1);
107 if (
ver == region.bottom && *materials[
ver - 1] != *region.materials[0])
108 throw Exception(
"{0}: Active region {1} has non-uniform bottom cladding", this->
getId(), num - 1);
114 if (num)
throw Exception(
"{0}: Active region cannot be located at the top of the structure.", this->
getId());
118 this->regions.clear();
121 FreeCarrierGainSolver3D::Region& reg =
ireg.second;
124 throw Exception(
"{0}: Active region cannot be located at the bottom of the structure.", this->
getId());
125 if (reg.top == points->axis[2]->size())
126 throw Exception(
"{0}: Active region cannot be located at the top of the structure.", this->
getId());
127 this->regions.emplace_back(mesh->at(0, 0, reg.bottom - 1));
128 auto region = &this->regions.back();
129 region->bottom = mesh->axis[2]->at(reg.bottom) - mesh->axis[2]->at(reg.bottom - 1);
130 region->top = mesh->axis[2]->at(reg.top + 1) - mesh->axis[2]->at(reg.top);
131 double dx = mesh->axis[0]->at(mesh->axis[0]->size() - 1) - mesh->axis[0]->at(0);
132 double dy = mesh->axis[1]->at(mesh->axis[1]->size() - 1) - mesh->axis[1]->at(0);
133 for (
size_t i = reg.bottom - 1, j = 0; i <= reg.top; ++i, ++j) {
134 bool QW = reg.isQW[i];
135 auto material = reg.materials[j];
136 double dz = mesh->axis[2]->at(i + 1) - mesh->axis[2]->at(i);
137 size_t n = region->layers->getChildrenCount();
142 assert(!last || (last->size.c0 ==
dx && last->size.c1 ==
dy));
143 if (last && material == last->getRepresentativeMaterial() &&
QW == region->isQW(region->size() - 1)) {
145 last->setSize(
dx,
dy, last->size.c1 + dz);
150 if (
QW) layer->addRole(
"QW");
151 region->layers->push_back(layer);
156 throw BadInput(this->
getId(),
"strained quantum wells requested but no layer with substrate role set");
158 this->
writelog(
LOG_DETAIL,
"Found {0} active region{1}", this->regions.size(), (
this->regions.size() == 1) ?
"" :
"s");
159 for (
auto& region : this->
regions) region.summarize(
this);