66 dcomplex c22,
c00, ic00, c11, ic11, c01;
69 Coeff(
const dcomplex& val): c22(val),
70 c00(val), ic00((val != 0.)? 1. / val : 0.),
71 c11(val), ic11((val != 0.)? 1. / val : 0.),
74 dcomplex det = eps.c00 * eps.c11 - eps.c01 *
conj(eps.c01);
75 ic00 = (det != 0.)? eps.c11 / det : 0.;
76 ic11 = (det != 0.)? eps.c00 / det : 0.;
79 c22 *= a; c00 *= a; ic00 *= a; c11 *= a; ic11 *= a; c01 *= a;
84 c00 = eps.c00; ic00 = (eps.c00 != 0.)? 1. / eps.c00 : 0.;
85 c11 = eps.c11; ic11 = (eps.c11 != 0.)? 1. / eps.c11 : 0.;
113 c2 = norm.c0 * norm.c0;
114 cs = norm.c0 * norm.c1;
123 bool isnan()
const { return ::isnan(c2.real()); }
136 shared_ptr<RectangularMesh<3>>
mesh;
167 void prepareField()
override;
169 void cleanupField()
override;
172 const shared_ptr<const typename LevelsAdapter::Level>& level,
176 const shared_ptr<const typename LevelsAdapter::Level>& level,
180 const shared_ptr<const typename LevelsAdapter::Level>& level,
184 const std::function<std::pair<dcomplex,dcomplex>(
size_t,
size_t)>& vertical)
override;
186 double integratePoyntingVert(
const cvector& E,
const cvector& H)
override;
195 void addToeplitzMatrix(
cmatrix& work,
int ordl,
int ordt,
size_t lay,
int c,
char syml,
char symt,
double a = 1.) {
196 for (
int it = (symt ? 0 : -ordt); it <= ordt; ++it) {
197 size_t It = (it >= 0)? it : it + Nt;
198 for (
int il = (syml ? 0 : -ordl); il <= ordl; ++il) {
199 size_t Il = (il >= 0)? il : il + Nl;
200 for (
int jt = -ordt; jt <= ordt; ++jt) {
201 size_t Jt = (jt >= 0)? jt : (symt)? -jt : jt + Nt;
202 int ijt = it - jt;
if (symt && ijt < 0) ijt = -ijt;
203 for (
int jl = -ordl; jl <= ordl; ++jl) {
204 size_t Jl = (jl >= 0)? jl : (syml)? -jl : jl + Nl;
206 if (syml && jl < 0) { f *= syml; }
207 if (symt && jt < 0) { f *= symt; }
208 int ijl = il - jl;
if (syml && ijl < 0) ijl = -ijl;
209 work(Nl * It + Il, Nl * Jt + Jl) += a * f * eps(lay, ijl, ijt, c);
216 void makeToeplitzMatrix(cmatrix& work,
int ordl,
int ordt,
size_t lay,
int c,
char syml,
char symt,
double a = 1.) {
218 addToeplitzMatrix(work, ordl, ordt, lay, c, syml, symt, a);
221 void makeToeplitzMatrix(cmatrix& workc2, cmatrix& workcs,
const DataVector<Gradient>& norms,
222 int ordl,
int ordt,
char syml,
char symt) {
225 for (
int it = (symt ? 0 : -ordt); it <= ordt; ++it) {
226 size_t It = (it >= 0)? it : it + Nt;
227 for (
int il = (syml ? 0 : -ordl); il <= ordl; ++il) {
228 size_t Il = (il >= 0)? il : il + Nl;
229 size_t I = Nl * It + Il;
230 for (
int jt = -ordt; jt <= ordt; ++jt) {
231 size_t Jt = (jt >= 0)? jt : (symt)? -jt : jt + Nt;
232 int ijt = it - jt;
if (ijt < 0) ijt = symt? -ijt : ijt + nNt;
233 for (
int jl = -ordl; jl <= ordl; ++jl) {
234 size_t Jl = (jl >= 0)? jl : (syml)? -jl : jl + Nl;
235 double fc = 1., fs = 1.;
236 if (syml && jl < 0) { fc *= syml; fs *= -syml; }
237 if (symt && jt < 0) { fc *= symt; fs *= -symt; }
238 int ijl = il - jl;
if (ijl < 0) ijl = syml? -ijl : ijl + nNl;
239 size_t J = Nl * Jt + Jl, ij = nNl * ijt + ijl;
240 workc2(I,J) += fc * norms[ij].c2;
241 workcs(I,J) += fs * norms[ij].cs;
256 void beforeLayersIntegrals(dcomplex lam, dcomplex glam)
override;
258 void layerIntegrals(
size_t layer,
double lam,
double glam)
override;
266 solver->clearFields();
274 solver->clearFields();
280 if (sym != symmetry_long) {
282 solver->clearFields();
288 if (sym != symmetry_tran) {
290 solver->clearFields();
295 size_t idx(
int l,
int t) {
296 if (l < 0) {
if (symmetric_long()) l = -l;
else l += int(Nl); }
297 if (t < 0) {
if (symmetric_tran()) t = -t;
else t += int(Nt); }
298 assert(0 <= l && std::size_t(l) < Nl);
299 assert(0 <= t && std::size_t(t) < Nt);
305 if (l < 0) l += int(eNl);
306 if (t < 0) t += int(eNt);
307 assert(0 <= l && std::size_t(l) < eNl);
308 assert(0 <= t && std::size_t(t) < eNt);
313 dcomplex
epsxx(
size_t lay,
int l,
int t) {
314 if (l < 0) l += int(nNl);
315 if (t < 0) t += int(nNt);
316 return coeffs[lay][nNl * t + l].c00;
320 dcomplex
epsyy(
size_t lay,
int l,
int t) {
321 if (l < 0) l += int(nNl);
322 if (t < 0) t += int(nNt);
323 return coeffs[lay][nNl * t + l].c11;
327 dcomplex
iepszz(
size_t lay,
int l,
int t) {
328 if (l < 0) l += int(nNl);
329 if (t < 0) t += int(nNt);
330 return coeffs[lay][nNl * t + l].c22;
334 dcomplex
iepszz(
size_t lay,
int il,
int jl,
int it,
int jt) {
335 if (jl < 0) {
if (symmetric_long())
return 0.;
else jl += int(Nl); }
336 if (jt < 0) {
if (symmetric_tran())
return 0.;
else jt += int(Nt); }
337 if (il < 0) il += int(Nl);
338 if (it < 0) it += int(Nt);
339 return coeffs_ezz[lay](Nl * it + il, Nl * jt + jl);
343 dcomplex
epsxy(
size_t lay,
int l,
int t) {
344 if (l < 0) l += int(nNl);
345 if (t < 0) t += int(nNt);
346 return coeffs[lay][nNl * t + l].c01;
350 dcomplex
eps(
size_t lay,
int l,
int t,
int c) {
351 if (l < 0) l += int(nNl);
352 if (t < 0) t += int(nNt);
353 return *(
reinterpret_cast<dcomplex*
>(coeffs[lay].data() + (nNl * t + l)) + c);
357 dcomplex
epsyx(
size_t lay,
int l,
int t) {
return conj(epsxy(lay, l, t)); }
360 dcomplex
muxx(
size_t PLASK_UNUSED(lay),
int l,
int t) {
return mag_long[(l>=0)?l:l+nNl].c11 * mag_tran[(t>=0)?t:t+nNt].c00; }
363 dcomplex
muyy(
size_t PLASK_UNUSED(lay),
int l,
int t) {
return mag_long[(l>=0)?l:l+nNl].c00 * mag_tran[(t>=0)?t:t+nNt].c11; }
366 dcomplex
imuzz(
size_t PLASK_UNUSED(lay),
int l,
int t) {
return mag_long[(l>=0)?l:l+nNl].c11 * mag_tran[(t>=0)?t:t+nNt].c11; }
369 size_t iEx(
int l,
int t) {
370 return 2 * idx(l, t);
374 size_t iEy(
int l,
int t) {
375 return 2 * idx(l, t) + 1;
379 size_t iHx(
int l,
int t) {
380 return 2 * idx(l, t) + 1;
384 size_t iHy(
int l,
int t) {
385 return 2 * idx(l, t);