42 std::vector<Region2D> regions;
44 for (
size_t r = 0; r < points->vert()->size(); ++r) {
47 for (
size_t c = 0; c < points->tran()->size(); ++c) {
48 auto point = points->at(c, r);
51 auto roles = this->geometry->getRolesAt(point);
52 for (
const auto& role : roles) {
53 if (role.substr(0, 6) ==
"active") {
54 if (num != 0)
throw BadInput(this->getId(),
"multiple 'active' roles specified");
55 if (role.size() == 6) {
59 num = boost::lexical_cast<size_t>(role.substr(6)) + 1;
60 }
catch (boost::bad_lexical_cast&) {
61 throw BadInput(this->getId(),
"bad active region number in role '{0}'", role);
64 }
else if (role ==
"substrate") {
65 if (this->explicitSubstrate)
66 this->
writelog(
LOG_WARNING,
"Explicit substrate layer specified, role 'substrate' ignored");
68 if (!this->substrateMaterial)
69 this->substrateMaterial = this->geometry->getMaterial(point);
70 else if (*this->substrateMaterial != *this->geometry->getMaterial(point))
71 throw Exception(
"{0}: Non-uniform substrate layer.", this->getId());
75 if (num == 0 && roles.find(
"QW") != roles.end())
76 throw Exception(
"{0}: All marked quantum wells must belong to marked active region.", this->getId());
79 if (regions.size() >= num) {
81 material = this->geometry->getMaterial(points->at(c, r));
82 else if (*material != *this->geometry->getMaterial(points->at(c, r))) {
83 throw Exception(
"{0}: Active region {1} is laterally non-uniform", this->getId(), num - 1);
86 regions.resize(
max(regions.size(), num));
87 auto& reg = regions[num - 1];
90 throw Exception(
"{0}: Active region {1} is disjoint", this->getId(), num - 1);
94 else if (reg.rowr <= c)
95 throw Exception(
"{0}: Active region {1} is disjoint", this->getId(), num - 1);
98 if (reg.left > reg.rowl) reg.left = reg.rowl;
101 if (prev && prev != num) {
102 auto& reg = regions[prev - 1];
103 if (reg.bottom < r && reg.rowl >= c)
throw Exception(
"{0}: Active region {1} is disjoint", this->getId(), prev - 1);
105 if (reg.right < reg.rowr) reg.right = reg.rowr;
110 regions[prev - 1].rowr = regions[prev - 1].right = points->tran()->size();
113 this->regions.clear();
115 for (
auto& reg : regions) {
116 if (reg.bottom == std::numeric_limits<size_t>::max()) {
121 throw Exception(
"{0}: Active region cannot be located at the bottom of the structure.", this->getId());
122 if (reg.top == points->axis[1]->size())
123 throw Exception(
"{0}: Active region cannot be located at the top of the structure.", this->getId());
124 this->regions.emplace_back(mesh->at(reg.left, reg.bottom - 1));
125 auto region = &this->regions.back();
126 region->bottom = mesh->axis[1]->at(reg.bottom) - mesh->axis[1]->at(reg.bottom - 1);
127 region->top = mesh->axis[1]->at(reg.top + 1) - mesh->axis[1]->at(reg.top);
128 double width = mesh->axis[0]->at(reg.right) - mesh->axis[0]->at(reg.left);
129 for (
size_t r = reg.bottom - 1, j = 0; r <= reg.top; ++r, ++j) {
131 for (
size_t c = reg.left; c < reg.right; ++c) {
133 auto point = points->at(c, r);
134 double height = mesh->axis[1]->at(r + 1) - mesh->axis[1]->at(r);
135 auto roles = this->geometry->getRolesAt(point);
136 bool QW = roles.find(
"QW") != roles.end() ;
138 auto material = this->geometry->getMaterial(point);
139 size_t n = region->layers->getChildrenCount();
144 assert(!last || last->size.c0 == width);
145 if (last && material == last->getRepresentativeMaterial() &&
QW == region->isQW(region->size() - 1)) {
147 last->setSize(width, last->size.c1 + height);
152 if (
QW) layer->addRole(
"QW");
153 region->layers->push_back(layer);
156 throw Exception(
"{}: Quantum wells in active region {} are not consistent", this->getId(),
act);
162 if (this->strained && !this->substrateMaterial)
163 throw BadInput(this->getId(),
"strained quantum wells requested but no layer with substrate role set");
165 this->
writelog(
LOG_DETAIL,
"Found {0} active region{1}", this->regions.size(), (
this->regions.size() == 1) ?
"" :
"s");
166 for (
auto& region : this->regions) region.summarize(
this);