31 enum Symmetry { SYMMETRY_DEFAULT, SYMMETRY_POSITIVE, SYMMETRY_NEGATIVE, SYMMETRY_NONE };
61 dcomplex ff, fb, bf,
bb;
63 Matrix(dcomplex t1, dcomplex t2, dcomplex t3, dcomplex t4) : ff(t1), fb(t2), bf(t3), bb(t4) {}
78 std::vector<Field, aligned_allocator<Field>>
xfields;
79 std::vector<double, aligned_allocator<double>>
xweights;
83 : solver(solver), have_fields(false), xfields(solver->xend), xweights(solver->xend), power(1.) {
88 if (solver->geometry->isSymmetric(Geometry::DIRECTION_TRAN)) {
89 if (sym == SYMMETRY_DEFAULT)
90 sym = SYMMETRY_POSITIVE;
91 else if (sym == SYMMETRY_NONE)
92 throw BadInput(solver->getId(),
"for symmetric geometry specify positive or negative symmetry");
94 if (sym == SYMMETRY_DEFAULT)
96 else if (sym != SYMMETRY_NONE)
97 throw BadInput(solver->getId(),
"for non-symmetric geometry no symmetry may be specified");
105 double loss()
const {
return -2e7 * imag(neff * solver->k0); }
120 std::vector<std::vector<dcomplex, aligned_allocator<dcomplex>>>
nrCache;
123 std::vector<Field, aligned_allocator<Field>>
yfields;
126 std::vector<double, aligned_allocator<double>>
yweights;
129 std::vector<dcomplex, aligned_allocator<dcomplex>>
epsilons;
186 std::string
getClassName()
const override {
return "optical.EffectiveIndex2D"; }
189 return "Calculate optical modes and optical field distribution using the effective index method "
190 "in Cartesian two-dimensional space.";
215 polarization = polar;
227 k0 = 2e3 *
PI / wavelength;
249 meshxy->setAxis0(meshx);
263 std::vector<dcomplex> searchVNeffs(plask::dcomplex neff1 = 0.,
264 plask::dcomplex neff2 = 0.,
265 size_t resteps = 256,
267 dcomplex eps = dcomplex(1
e-6, 1
e-9));
275 size_t findMode(dcomplex neff, Symmetry symmetry = SYMMETRY_DEFAULT);
287 std::vector<size_t> findModes(dcomplex neff1 = 0.,
289 Symmetry symmetry = SYMMETRY_DEFAULT,
290 size_t resteps = 256,
292 dcomplex eps = dcomplex(1
e-6, 1
e-9));
300 size_t stripe = mesh->tran()->findIndex(stripex);
303 else if (stripe >= xend)
305 return detS1(neff, nrCache[stripe]);
315 Mode mode(
this, sym);
316 dcomplex det = detS(neff, mode);
327 size_t setMode(dcomplex neff, Symmetry sym = SYMMETRY_DEFAULT);
336 double getTotalAbsorption(Mode& mode);
350 size_t i(
clamp(mesh->tran()->findIndex(geometry->isSymmetric(Geometry::DIRECTION_TRAN) ? abs(x) : x), xbegin, xend - 1));
351 return sqrt(epsilons[i]);
359 void onInitialize()
override;
362 void onInvalidate()
override;
372 double L = geometry->getExtrusion()->getLength();
373 if (isinf(L))
return 0.;
374 const double lambda =
real(2e3 *
PI / k0);
377 std::tie(R1, R2) = *mirrors;
379 const double n1 =
real(geometry->getFrontMaterial()->Nr(lambda, 300.)),
380 n2 =
real(geometry->getBackMaterial()->Nr(lambda, 300.));
381 R1 = abs((
n - n1) / (
n + n1));
382 R2 = abs((
n - n2) / (
n + n2));
384 return lambda * std::log(R1 * R2) / (4e3 *
PI * L);
403 void computeWeights(
size_t stripe);
424 dcomplex detS(
const dcomplex& x, Mode& mode,
bool save =
false);
428 for (
size_t i = 0; i != modes.size(); ++i)
429 if (modes[i] == mode)
return i;
430 modes.push_back(mode);
431 outNeff.fireChanged();
432 outLightMagnitude.fireChanged();
433 outLightE.fireChanged();
434 return modes.size() - 1;
438 size_t nmodes()
const {
return modes.size(); }
445 if (
n >= modes.size())
throw NoValue(ModeEffectiveIndex::NAME);
446 return modes[
n].neff;
449 template <
typename T>
struct FieldDataBase;
450 template <
typename T>
struct FieldDataInefficient;
451 template <
typename T>
struct FieldDataEfficient;
466 shared_ptr<
const MeshD<2>> dst_mesh,