📄 bragg_transmission.cpp
字号:
/* Copyright (C) 2005-2008 Massachusetts Institute of Technology. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* Compute the transmission spectrum through a 4-layer 1d Bragg mirror, and compare to the result from the analytical transfer matrices. The transmission spectrum is computed via the dft_flux feature, which dynamically updates the DFTs of the fields on the flux plane as we go along. */#include <stdio.h>#include <stdlib.h>#include <math.h>#include <meep.hpp>using namespace meep;const double nhi = 3, nlo = 1;const double wlo = nhi / (nlo + nhi);const int Nperiods = 4;const double zsize = 10;double eps_nlo(const vec &) { return nlo*nlo; }double eps_bragg(const vec &v) { double z = v.z() - zsize * 0.5; if (fabs(z)*2 > Nperiods) return nlo*nlo; else { double zi; double zf = modf(z, &zi); if (zf < 0) zf += 1; if (zf < wlo) return (nlo*nlo); else return (nhi*nhi); }}typedef complex<double> matrix2x2[2][2];/* multiply m by transfer matrix from n1 to n2 */inline void byT12(matrix2x2 m, double n1, double n2){ complex<double> m00, m01, m10, m11; double td, tod; double n12 = n1 / n2; td = 0.5 * (1 + n12); tod = 0.5 * (1 - n12); m00 = m[0][0]; m01 = m[0][1]; m10 = m[1][0]; m11 = m[1][1]; m[0][0] = m00 * td + m01 * tod; m[0][1] = m00 * tod + m01 * td; m[1][0] = m10 * td + m11 * tod; m[1][1] = m10 * tod + m11 * td;}/* multiply m by propagation matrix through dz of index n, frequency w */inline void byP(matrix2x2 m, double n, double w, double dz){ complex<double> p, pc; p = exp(complex<double>(0, n * w * dz)); pc = conj(p); m[0][0] *= p; m[0][1] *= pc; m[1][0] *= p; m[1][1] *= pc;}inline double abs2(complex<double> x) { double ax = abs(x); return ax*ax; }void bragg_transmission_analytic(double freq_min, double freq_max, int nfreq, double *T, double *R){ for (int i = 0; i < nfreq; ++i) { double omega = 2*pi * (freq_min + i * (freq_max - freq_min) / (nfreq - 1)); matrix2x2 Tm = { { 1, 0 }, { 0, 1 } }; for (int j = 0; j < Nperiods; ++j) { byT12(Tm, nlo, nhi); byP(Tm, nhi, omega, 1 - wlo); byT12(Tm, nhi, nlo); byP(Tm, nlo, omega, wlo); } complex<double> refl = - Tm[1][0] / Tm[1][1]; T[i] = abs2(Tm[0][0] + refl * Tm[0][1]); R[i] = abs2(refl); }}void bragg_transmission(double a, double freq_min, double freq_max, int nfreq, double *T, double *R, bool use_hdf5) { const volume v = volone(zsize, a); structure s(v, eps_bragg, pml(0.5)); fields f(&s); f.use_real_fields(); structure s0(v, eps_nlo, pml(0.5)); fields f0(&s0); f0.use_real_fields(); vec srcpt(0.1), Tfluxpt(zsize - 0.1), Rfluxpt(0.1); gaussian_src_time src((freq_min + freq_max) * 0.5, 0.5 / fabs(freq_max - freq_min), 0, 5 / fabs(freq_max - freq_min)); f.add_point_source(Ex, src, srcpt); f0.add_point_source(Ex, src, srcpt); dft_flux ft = f.add_dft_flux_plane(Tfluxpt, freq_min, freq_max, nfreq); dft_flux fr = f.add_dft_flux_plane(Rfluxpt, freq_min, freq_max, nfreq); dft_flux ft0 = f0.add_dft_flux_plane(Tfluxpt, freq_min, freq_max, nfreq); dft_flux fr0 = f0.add_dft_flux_plane(Rfluxpt, freq_min, freq_max, nfreq); while (f0.time() < nfreq / fabs(freq_max - freq_min) / 2) f0.step(); /* we want to subtract the fields for the reflection... */ if (use_hdf5) { /* simulate a case where the normalization is done by a separate run and saved to a file */ fr0.save_hdf5(f, "flux", "reflection"); fr.load_hdf5(f, "flux", "reflection"); fr.scale_dfts(-1.0); // clean up after ourselves: delete the file h5file *ff = f.open_h5file("flux", h5file::READONLY); ff->remove(); delete ff; } else fr -= fr0; while (f.time() < nfreq / fabs(freq_max - freq_min) / 2) f.step(); double *flux = ft.flux(); double *flux0 = ft0.flux(); for (int i = 0; i < nfreq; ++i) T[i] = flux[i] / flux0[i]; delete[] flux; flux = fr.flux(); for (int i = 0; i < nfreq; ++i) R[i] = -flux[i] / flux0[i]; delete[] flux; delete[] flux0;}inline double max2(double a, double b) { return (a > b ? a : b); }inline double min2(double a, double b) { return (a < b ? a : b); }inline double max2a(double a, double b) { return max2(abs(a), abs(b)); }inline double sqr(double x) { return x*x; }/* The discretization errors tend to result in a *shift* of the spectral features more than a change in their amplitude. Because these features are very sharp (e.g. at the gap edges), it is more appropriate to compute errors via the distance from a point to the curve, rather than just the difference of the abscissae. That's what this function does. */double distance_from_curve(int n, double dx, double ys[], double x, double y){ double d = infinity; for (int i = 1; i < n; ++i) { double theta = atan2(ys[i] - ys[i-1], dx); double L = sqrt(sqr(dx) + sqr(ys[i]-ys[i-1])); double x0 = x - (i-1) * dx; double y0 = y - ys[i-1]; double x0p = x0 * cos(theta) + y0 * sin(theta); double y0p = y0 * cos(theta) - x0 * sin(theta); if (x0p < 0) d = min2(sqrt(sqr(x0) + sqr(y0)), d); else if (x0p > L) d = min2(sqrt(sqr(x-i*dx) + sqr(y-ys[i])), d); else d = min2(abs(y0p), d); } return d;}void doit(bool use_hdf5) { const int nfreq = 100; const double freq_min = 0.1, freq_max = 0.5; double *T = new double[nfreq]; double *R = new double[nfreq]; bragg_transmission(40.0, freq_min, freq_max, nfreq, T, R, use_hdf5); double *T0 = new double[nfreq]; double *R0 = new double[nfreq]; bragg_transmission_analytic(freq_min, freq_max, nfreq, T0, R0); double dfreq = (freq_max - freq_min) / (nfreq - 1); if (0) { // output transmission & reflection spectra for debugging master_printf("transmission:, freq (c/a), T, R, T0, R0\n"); for (int i = 0; i < nfreq; ++i) master_printf("transmission:, %g, %g, %g, %g, %g\n", freq_min + i * dfreq, T[i], R[i], T0[i], R0[i]); } double maxerrT = 0, maxerrR = 0; for (int i = 0; i < nfreq; ++i) { double errT = distance_from_curve(nfreq, dfreq, T0, i * dfreq, T[i]); double errR = distance_from_curve(nfreq, dfreq, R0, i * dfreq, R[i]); if (errT > maxerrT) maxerrT = errT; if (errR > maxerrR) maxerrR = errR; if (errT * sqr(freq_min / (freq_min + i*dfreq)) > 0.01) abort("large error %g at freq = %g: T = %g instead of %g\n", errT, freq_min + i*dfreq, T[i], T0[i]); if (errR * sqr(freq_min / (freq_min + i*dfreq)) > 0.01) abort("large error %g at freq = %g: R = %g instead of %g\n", errR, freq_min + i*dfreq, R[i], R0[i]); } master_printf("Done (max. err in T = %e, in R = %e)\n", maxerrT, maxerrR); delete[] R0; delete[] T0; delete[] R; delete[] T;}int main(int argc, char **argv) { initialize mpi(argc, argv); quiet = true;#ifdef HAVE_HDF5 doit(true);#endif doit(false); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -