ROBAST logo
/******************************************************************************
 * Copyright (C) 2006-, Akira Okumura                                         *
 * All rights reserved.                                                       *
 *****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
//
// AMultilayer
//
///////////////////////////////////////////////////////////////////////////////

#include "AMultilayer.h"
#include "A2x2ComplexMatrix.h"
#include "AOpticsManager.h"

#include <complex>
#include <iostream>

static const Double_t EPSILON = std::numeric_limits<double>::epsilon();
static const Double_t inf = std::numeric_limits<Double_t>::infinity();

ClassImp(AMultilayer);

AMultilayer::AMultilayer(std::shared_ptr<ARefractiveIndex> top,
                         std::shared_ptr<ARefractiveIndex> bottom)
    : fNthreads(1) {
  fRefractiveIndexList.push_back(bottom);
  fThicknessList.push_back(inf);
  InsertLayer(top, inf);
}

//______________________________________________________________________________
AMultilayer::~AMultilayer() {}

//______________________________________________________________________________
Bool_t AMultilayer::IsForwardAngle(std::complex<Double_t> n,
                                   std::complex<Double_t> theta) const {
  // Copied from tmm.is_forward_angle

  // if a wave is traveling at angle theta from normal in a medium with index n,
  // calculate whether or not this is the forward-traveling wave (i.e., the one
  // going from front to back of the stack, like the incoming or outgoing waves,
  // but unlike the reflected wave). For real n & theta, the criterion is simply
  // -pi/2 < theta < pi/2, but for complex n & theta, it's more complicated.
  // See https://arxiv.org/abs/1603.02720 appendix D. If theta is the forward
  // angle, then (pi-theta) is the backward angle and vice-versa.

  if (n.real() * n.imag() < 0) {
    Error("IsForwardAngle",
          "For materials with gain, it's ambiguous which "
          "beam is incoming vs outgoing. See "
          "https://arxiv.org/abs/1603.02720 Appendix C.\n"
          "n: %.3e + %.3ei   angle: %.3e + %.3ei",
          n.real(), n.imag(), theta.real(), theta.imag());
  }
  auto ncostheta = n * std::cos(theta);
  Bool_t answer;
  if (std::abs(ncostheta.imag()) > 100 * EPSILON) {
    // Either evanescent decay or lossy medium. Either way, the one that
    // decays is the forward-moving wave
    answer = ncostheta.imag() > 0;
  } else {
    // Forward is the one with positive Poynting vector
    // Poynting vector is Re[n cos(theta)] for s-polarization or
    // Re[n cos(theta*)] for p-polarization, but it turns out they're consistent
    // so I'll just assume s then check both below
    answer = ncostheta.real() > 0;
  }
  // double-check the answer ... can't be too careful!
  std::string error_string(
      Form("It's not clear which beam is incoming vs outgoing. Weird"
           " index maybe?\n"
           "n: %.3e + %.3ei   angle: %.3e + %.3ei",
           n.real(), n.imag(), theta.real(), theta.imag()));
  if (answer == true) {
    if (ncostheta.imag() <= -100 * EPSILON)
      Error("IsForwardAngle", "%s", error_string.c_str());
    if (ncostheta.real() <= -100 * EPSILON)
      Error("IsForwardAngle", "%s", error_string.c_str());
    if ((n * std::cos(std::conj(theta))).real() <= -100 * EPSILON)
      Error("IsForwardAngle", "%s", error_string.c_str());
  } else {
    if (ncostheta.imag() >= 100 * EPSILON)
      Error("IsForwardAngle", "%s", error_string.c_str());
    if (ncostheta.real() >= 100 * EPSILON)
      Error("IsForwardAngle", "%s", error_string.c_str());
    if ((n * std::cos(std::conj(theta))).real() < 100 * EPSILON)
      Error("IsForwardAngle", "%s", error_string.c_str());
  }
  return answer;
}

//______________________________________________________________________________
void AMultilayer::ListSnell(
    std::complex<Double_t> th_0,
    const std::vector<std::complex<Double_t>>& n_list,
    std::vector<std::complex<Double_t>>& th_list) const {
  // Copied from tmm.list_snell

  // return list of angle theta in each layer based on angle th_0 in layer 0,
  // using Snell's law. n_list is index of refraction of each layer. Note that
  // "angles" may be complex!!

  auto num_layers = fRefractiveIndexList.size();
  th_list.resize(num_layers);
  {
    auto n_i = n_list.cbegin();
    auto th_i = th_list.begin();
    auto n0_sinth0 = (*n_i) * std::sin(th_0);
    for (std::size_t i = 0; i < num_layers; ++i) {
      *th_i = std::asin(n0_sinth0 / *n_i);
      ++n_i;
      ++th_i;
    }
  }

  // The first and last entry need to be the forward angle (the intermediate
  // layers don't matter, see https://arxiv.org/abs/1603.02720 Section 5)
  if (!IsForwardAngle(n_list[0], th_list[0])) {
    th_list[0] = TMath::Pi() - th_list[0];
  }
  if (!IsForwardAngle(n_list.back(), th_list.back())) {
    th_list.back() = TMath::Pi() - th_list.back();
  }
}

//______________________________________________________________________________
void AMultilayer::InsertLayer(std::shared_ptr<ARefractiveIndex> idx,
                              Double_t thickness) {
  // ----------------- Top layer
  // ----------------- 1st layer
  // ----------------- 2nd layer
  // ...
  // ----------------- <------------- Insert a new layer here
  // ----------------- Bottom layer
  fRefractiveIndexList.insert(fRefractiveIndexList.end() - 1, idx);
  fThicknessList.insert(fThicknessList.end() - 1, thickness);
}

//______________________________________________________________________________
void AMultilayer::CoherentTMM(EPolarization polarization,
                              std::complex<Double_t> th_0, Double_t lam_vac,
                              Double_t& reflectance,
                              Double_t& transmittance) const {
  // Copied from tmm.ch_tmm

  // Main "coherent transfer matrix method" calc. Given parameters of a stack,
  // calculates everything you could ever want to know about how light
  // propagates in it. (If performance is an issue, you can delete some of the
  // calculations without affecting the rest.)
  //
  // pol is light polarization, "s" or "p".
  //
  // n_list is the list of refractive indices, in the order that the light would
  // pass through them. The 0'th element of the list should be the semi-infinite
  // medium from which the light enters, the last element should be the semi-
  // infinite medium to which the light exits (if any exits).
  //
  // th_0 is the angle of incidence: 0 for normal, pi/2 for glancing.
  // Remember, for a dissipative incoming medium (n_list[0] is not real), th_0
  // should be complex so that n0 sin(th0) is real (intensity is constant as
  // a function of lateral position).
  //
  // d_list is the list of layer thicknesses (front to back). Should correspond
  // one-to-one with elements of n_list. First and last elements should be
  // "inf".
  //
  // lam_vac is vacuum wavelength of the light.

  auto num_layers = fRefractiveIndexList.size();
  std::vector<std::complex<Double_t>> n_list(num_layers);

  {
    auto n_i = n_list.begin();
    auto ref_i = fRefractiveIndexList.cbegin();
    for (std::size_t i = 0; i < num_layers; ++i) {
      *n_i = (*ref_i)->GetComplexRefractiveIndex(lam_vac);
      ++n_i;
      ++ref_i;
    }
  }

  // Input tests
  if (std::abs((n_list[0] * std::sin(th_0)).imag()) >= 100 * EPSILON ||
      !IsForwardAngle(n_list[0], th_0)) {
    Error("CoherentTMM", "Error in n0 or th0!");
  }

  // th_list is a list with, for each layer, the angle that the light travels
  // through the layer. Computed with Snell's law. Note that the "angles" may be
  // complex!
  std::vector<std::complex<Double_t>> th_list;
  ListSnell(th_0, n_list, th_list);

  // kz is the z-component of (complex) angular wavevector for forward-moving
  // wave. Positive imaginary part means decaying.
  std::vector<std::complex<Double_t>> kz_list(num_layers);
  std::vector<std::complex<Double_t>> cos_th_list(num_layers);
  {
    auto kz_i = kz_list.begin();
    auto n_i = n_list.cbegin();
    auto th_i = th_list.cbegin();
    auto cos_th_i = cos_th_list.begin();
    for (std::size_t i = 0; i < num_layers; ++i) {
      *cos_th_i = std::cos(*th_i);
      *kz_i = TMath::TwoPi() * (*n_i) * (*cos_th_i) / lam_vac;
      ++kz_i;
      ++n_i;
      ++th_i;
      ++cos_th_i;
    }
  }

  // delta is the total phase accrued by traveling through a given layer.
  std::vector<std::complex<Double_t>> delta(num_layers);
  {
    auto delta_i = delta.begin();
    auto kz_i = kz_list.cbegin();
    auto thickness_i = fThicknessList.cbegin();
    for (std::size_t i = 0; i < num_layers; ++i) {
      *delta_i = (*kz_i) * (*thickness_i);
      ++delta_i;
      ++kz_i;
      ++thickness_i;
    }
  }

  // For a very opaque layer, reset delta to avoid divide-by-0 and similar
  // errors. The criterion imag(delta) > 35 corresponds to single-pass
  // transmission < 1e-30 --- small enough that the exact value doesn't
  // matter.
  static Bool_t opacity_warning = kFALSE;
  {
    auto delta_i = delta.begin();
    ++delta_i;  // start from i = 1
    for (std::size_t i = 1; i < num_layers - 1; ++i) {
      if ((*delta_i).imag() > 35) {
        *delta_i = (*delta_i).real() + std::complex<Double_t>(0, 35);
        if (opacity_warning == kFALSE) {
          opacity_warning = kTRUE;
          Error("CoherentTMM",
                "Warning: Layers that are almost perfectly opaque "
                "are modified to be slightly transmissive, "
                "allowing 1 photon in 10^30 to pass through. It's "
                "for numerical stability. This warning will not "
                "be shown again.");
        }
      }
      ++delta_i;
    }
  }

  // t_list[i,j] and r_list[i,j] are transmission and reflection amplitudes,
  // respectively, coming from i, going to j. Only need to calculate this when
  // j=i+1. (2D array is overkill but helps avoid confusion.)
  std::vector<std::complex<Double_t>> t_list(num_layers);
  std::vector<std::complex<Double_t>> r_list(num_layers);

  {
    auto t_i = t_list.begin();
    auto r_i = r_list.begin();
    auto th_i = th_list.cbegin();
    auto th_f = th_list.cbegin();
    ++th_f;  // increment to access th_f (th[i + 1])
    auto n_i = n_list.cbegin();
    auto n_f = n_list.cbegin();
    ++n_f;                                 // increment to access n_f (n[i + 1])
    auto cos_th_i = cos_th_list.cbegin();  // cos(th_i)
    auto cos_th_f = cos_th_list.cbegin();
    ++cos_th_f;  // increment to access cos(th_f)
    for (std::size_t i = 0; i < num_layers - 1; ++i) {
      auto ii = *n_i * (*cos_th_i);
      if (polarization == kS) {
        auto ff = *n_f * (*cos_th_f);
        *t_i = 2. * ii / (ii + ff);
        *r_i = (ii - ff) / (ii + ff);
      } else {
        auto fi = *n_f * (*cos_th_i);
        auto if_ = *n_i * (*cos_th_f);
        *t_i = 2. * ii / (fi + if_);
        *r_i = (fi - if_) / (fi + if_);
      }
      ++t_i;
      ++r_i;
      ++th_i;
      ++th_f;
      ++n_i;
      ++n_f;
      ++cos_th_i;
      ++cos_th_f;
    }
  }

  // At the interface between the (n-1)st and nth material, let v_n be the
  // amplitude of the wave on the nth side heading forwards (away from the
  // boundary), and let w_n be the amplitude on the nth side heading backwards
  // (towards the boundary). Then (v_n,w_n) = M_n (v_{n+1},w_{n+1}). M_n is
  // M_list[n]. M_0 and M_{num_layers-1} are not defined.
  // My M is a bit different than Sernelius's, but Mtilde is the same.

  // M_list[0] and M_list[-1] are filled with (0, 0, 0, 0) by default
  std::vector<A2x2ComplexMatrix> M_list(num_layers);
  {
    const std::complex<Double_t> j(0, 1);
    auto M_i = M_list.begin();
    ++M_i;  // start i from 1
    auto t_i = t_list.cbegin();
    ++t_i;
    auto r_i = r_list.cbegin();
    ++r_i;
    auto delta_i = delta.cbegin();
    ++delta_i;
    for (std::size_t i = 1; i < num_layers - 1; ++i) {
      auto j_delta_i = j * (*delta_i);
      *M_i =
          1. / (*t_i) *
          A2x2ComplexMatrix(std::exp(-j_delta_i), 0, 0, std::exp(j_delta_i)) *
          A2x2ComplexMatrix(1, *r_i, *r_i, 1);
      ++M_i;
      ++t_i;
      ++r_i;
      ++delta_i;
    }
  }

  A2x2ComplexMatrix Mtilde(1, 0, 0, 1);
  {
    auto M_i = M_list.cbegin();
    ++M_i;  // start i from 1
    for (std::size_t i = 1; i < num_layers - 1; ++i) {
      Mtilde = Mtilde * (*M_i);
      ++M_i;
    }
  }

  Mtilde = A2x2ComplexMatrix(1, r_list[0], r_list[0], 1) / t_list[0] * Mtilde;

  // Net complex transmission and reflection amplitudes
  auto r = Mtilde.Get10() / Mtilde.Get00();
  auto t = 1. / Mtilde.Get00();

  // vw_list[n] = [v_n, w_n]. v_0 and w_0 are undefined because the 0th medium
  // has no left interface.
  /* Will not be used at the moment (A.O.)
  std::vector<std::array<std::complex<Double_t>, 2>> vw_list(num_layers);

  std::complex<Double_t> vw[2] = {t, 0.};
  vw_list.back()[0] = vw[0];
  vw_list.back()[1] = vw[1];

  for(std::size_t i = num_layers - 2; i > 0; --i) {
    auto v = M_list[i].Get00() * vw[0] + M_list[i].Get01() * vw[1];
    auto w = M_list[i].Get10() * vw[0] + M_list[i].Get11() * vw[1];
    vw[0] = v;
    vw[1] = w;
    vw_list[i][0] = vw[0];
    vw_list[i][1] = vw[1];
  }
  */

  // Net transmitted and reflected power, as a proportion of the incoming light
  // power.
  reflectance = std::abs(r) * std::abs(r);
  auto n_i = n_list[0];
  auto n_f = n_list.back();
  auto th_i = th_0;
  auto th_f = th_list.back();
  if (polarization == kS) {
    transmittance = std::abs(t * t) * (((n_f * std::cos(th_f)).real()) /
                                       (n_i * std::cos(th_i)).real());
  } else {
    transmittance =
        std::abs(t * t) * (((n_f * std::conj(std::cos(th_f))).real()) /
                           (n_i * std::conj(std::cos(th_i))).real());
  }
}

//__________________________________________________________________________________
void AMultilayer::PrintLayers(Double_t lambda) const {
  auto n = fRefractiveIndexList.size();
  for (std::size_t i = 0; i < n; ++i) {
    std::cout << "----------------------------------------\n";
    std::cout << i << "\tn_i = "
              << fRefractiveIndexList[i]->GetComplexRefractiveIndex(lambda)
              << "\td_i = " << fThicknessList[i] / AOpticsManager::nm()
              << " (nm)\n";
  }
  std::cout << "----------------------------------------" << std::endl;
}

//__________________________________________________________________________________
void AMultilayer::SetNthreads(std::size_t n) {
  // Note that having n larger than 1 frequently decreases the total
  // performance. Use this method only when you feed a very long vector.
  if (n == 0) {
    fNthreads =
        std::thread::hardware_concurrency();  // can return 0 if n is unknown
    if (fNthreads == 0) fNthreads = 1;
  } else if (n > 0) {
    fNthreads = n;
  }
}
 AMultilayer.cxx:1
 AMultilayer.cxx:2
 AMultilayer.cxx:3
 AMultilayer.cxx:4
 AMultilayer.cxx:5
 AMultilayer.cxx:6
 AMultilayer.cxx:7
 AMultilayer.cxx:8
 AMultilayer.cxx:9
 AMultilayer.cxx:10
 AMultilayer.cxx:11
 AMultilayer.cxx:12
 AMultilayer.cxx:13
 AMultilayer.cxx:14
 AMultilayer.cxx:15
 AMultilayer.cxx:16
 AMultilayer.cxx:17
 AMultilayer.cxx:18
 AMultilayer.cxx:19
 AMultilayer.cxx:20
 AMultilayer.cxx:21
 AMultilayer.cxx:22
 AMultilayer.cxx:23
 AMultilayer.cxx:24
 AMultilayer.cxx:25
 AMultilayer.cxx:26
 AMultilayer.cxx:27
 AMultilayer.cxx:28
 AMultilayer.cxx:29
 AMultilayer.cxx:30
 AMultilayer.cxx:31
 AMultilayer.cxx:32
 AMultilayer.cxx:33
 AMultilayer.cxx:34
 AMultilayer.cxx:35
 AMultilayer.cxx:36
 AMultilayer.cxx:37
 AMultilayer.cxx:38
 AMultilayer.cxx:39
 AMultilayer.cxx:40
 AMultilayer.cxx:41
 AMultilayer.cxx:42
 AMultilayer.cxx:43
 AMultilayer.cxx:44
 AMultilayer.cxx:45
 AMultilayer.cxx:46
 AMultilayer.cxx:47
 AMultilayer.cxx:48
 AMultilayer.cxx:49
 AMultilayer.cxx:50
 AMultilayer.cxx:51
 AMultilayer.cxx:52
 AMultilayer.cxx:53
 AMultilayer.cxx:54
 AMultilayer.cxx:55
 AMultilayer.cxx:56
 AMultilayer.cxx:57
 AMultilayer.cxx:58
 AMultilayer.cxx:59
 AMultilayer.cxx:60
 AMultilayer.cxx:61
 AMultilayer.cxx:62
 AMultilayer.cxx:63
 AMultilayer.cxx:64
 AMultilayer.cxx:65
 AMultilayer.cxx:66
 AMultilayer.cxx:67
 AMultilayer.cxx:68
 AMultilayer.cxx:69
 AMultilayer.cxx:70
 AMultilayer.cxx:71
 AMultilayer.cxx:72
 AMultilayer.cxx:73
 AMultilayer.cxx:74
 AMultilayer.cxx:75
 AMultilayer.cxx:76
 AMultilayer.cxx:77
 AMultilayer.cxx:78
 AMultilayer.cxx:79
 AMultilayer.cxx:80
 AMultilayer.cxx:81
 AMultilayer.cxx:82
 AMultilayer.cxx:83
 AMultilayer.cxx:84
 AMultilayer.cxx:85
 AMultilayer.cxx:86
 AMultilayer.cxx:87
 AMultilayer.cxx:88
 AMultilayer.cxx:89
 AMultilayer.cxx:90
 AMultilayer.cxx:91
 AMultilayer.cxx:92
 AMultilayer.cxx:93
 AMultilayer.cxx:94
 AMultilayer.cxx:95
 AMultilayer.cxx:96
 AMultilayer.cxx:97
 AMultilayer.cxx:98
 AMultilayer.cxx:99
 AMultilayer.cxx:100
 AMultilayer.cxx:101
 AMultilayer.cxx:102
 AMultilayer.cxx:103
 AMultilayer.cxx:104
 AMultilayer.cxx:105
 AMultilayer.cxx:106
 AMultilayer.cxx:107
 AMultilayer.cxx:108
 AMultilayer.cxx:109
 AMultilayer.cxx:110
 AMultilayer.cxx:111
 AMultilayer.cxx:112
 AMultilayer.cxx:113
 AMultilayer.cxx:114
 AMultilayer.cxx:115
 AMultilayer.cxx:116
 AMultilayer.cxx:117
 AMultilayer.cxx:118
 AMultilayer.cxx:119
 AMultilayer.cxx:120
 AMultilayer.cxx:121
 AMultilayer.cxx:122
 AMultilayer.cxx:123
 AMultilayer.cxx:124
 AMultilayer.cxx:125
 AMultilayer.cxx:126
 AMultilayer.cxx:127
 AMultilayer.cxx:128
 AMultilayer.cxx:129
 AMultilayer.cxx:130
 AMultilayer.cxx:131
 AMultilayer.cxx:132
 AMultilayer.cxx:133
 AMultilayer.cxx:134
 AMultilayer.cxx:135
 AMultilayer.cxx:136
 AMultilayer.cxx:137
 AMultilayer.cxx:138
 AMultilayer.cxx:139
 AMultilayer.cxx:140
 AMultilayer.cxx:141
 AMultilayer.cxx:142
 AMultilayer.cxx:143
 AMultilayer.cxx:144
 AMultilayer.cxx:145
 AMultilayer.cxx:146
 AMultilayer.cxx:147
 AMultilayer.cxx:148
 AMultilayer.cxx:149
 AMultilayer.cxx:150
 AMultilayer.cxx:151
 AMultilayer.cxx:152
 AMultilayer.cxx:153
 AMultilayer.cxx:154
 AMultilayer.cxx:155
 AMultilayer.cxx:156
 AMultilayer.cxx:157
 AMultilayer.cxx:158
 AMultilayer.cxx:159
 AMultilayer.cxx:160
 AMultilayer.cxx:161
 AMultilayer.cxx:162
 AMultilayer.cxx:163
 AMultilayer.cxx:164
 AMultilayer.cxx:165
 AMultilayer.cxx:166
 AMultilayer.cxx:167
 AMultilayer.cxx:168
 AMultilayer.cxx:169
 AMultilayer.cxx:170
 AMultilayer.cxx:171
 AMultilayer.cxx:172
 AMultilayer.cxx:173
 AMultilayer.cxx:174
 AMultilayer.cxx:175
 AMultilayer.cxx:176
 AMultilayer.cxx:177
 AMultilayer.cxx:178
 AMultilayer.cxx:179
 AMultilayer.cxx:180
 AMultilayer.cxx:181
 AMultilayer.cxx:182
 AMultilayer.cxx:183
 AMultilayer.cxx:184
 AMultilayer.cxx:185
 AMultilayer.cxx:186
 AMultilayer.cxx:187
 AMultilayer.cxx:188
 AMultilayer.cxx:189
 AMultilayer.cxx:190
 AMultilayer.cxx:191
 AMultilayer.cxx:192
 AMultilayer.cxx:193
 AMultilayer.cxx:194
 AMultilayer.cxx:195
 AMultilayer.cxx:196
 AMultilayer.cxx:197
 AMultilayer.cxx:198
 AMultilayer.cxx:199
 AMultilayer.cxx:200
 AMultilayer.cxx:201
 AMultilayer.cxx:202
 AMultilayer.cxx:203
 AMultilayer.cxx:204
 AMultilayer.cxx:205
 AMultilayer.cxx:206
 AMultilayer.cxx:207
 AMultilayer.cxx:208
 AMultilayer.cxx:209
 AMultilayer.cxx:210
 AMultilayer.cxx:211
 AMultilayer.cxx:212
 AMultilayer.cxx:213
 AMultilayer.cxx:214
 AMultilayer.cxx:215
 AMultilayer.cxx:216
 AMultilayer.cxx:217
 AMultilayer.cxx:218
 AMultilayer.cxx:219
 AMultilayer.cxx:220
 AMultilayer.cxx:221
 AMultilayer.cxx:222
 AMultilayer.cxx:223
 AMultilayer.cxx:224
 AMultilayer.cxx:225
 AMultilayer.cxx:226
 AMultilayer.cxx:227
 AMultilayer.cxx:228
 AMultilayer.cxx:229
 AMultilayer.cxx:230
 AMultilayer.cxx:231
 AMultilayer.cxx:232
 AMultilayer.cxx:233
 AMultilayer.cxx:234
 AMultilayer.cxx:235
 AMultilayer.cxx:236
 AMultilayer.cxx:237
 AMultilayer.cxx:238
 AMultilayer.cxx:239
 AMultilayer.cxx:240
 AMultilayer.cxx:241
 AMultilayer.cxx:242
 AMultilayer.cxx:243
 AMultilayer.cxx:244
 AMultilayer.cxx:245
 AMultilayer.cxx:246
 AMultilayer.cxx:247
 AMultilayer.cxx:248
 AMultilayer.cxx:249
 AMultilayer.cxx:250
 AMultilayer.cxx:251
 AMultilayer.cxx:252
 AMultilayer.cxx:253
 AMultilayer.cxx:254
 AMultilayer.cxx:255
 AMultilayer.cxx:256
 AMultilayer.cxx:257
 AMultilayer.cxx:258
 AMultilayer.cxx:259
 AMultilayer.cxx:260
 AMultilayer.cxx:261
 AMultilayer.cxx:262
 AMultilayer.cxx:263
 AMultilayer.cxx:264
 AMultilayer.cxx:265
 AMultilayer.cxx:266
 AMultilayer.cxx:267
 AMultilayer.cxx:268
 AMultilayer.cxx:269
 AMultilayer.cxx:270
 AMultilayer.cxx:271
 AMultilayer.cxx:272
 AMultilayer.cxx:273
 AMultilayer.cxx:274
 AMultilayer.cxx:275
 AMultilayer.cxx:276
 AMultilayer.cxx:277
 AMultilayer.cxx:278
 AMultilayer.cxx:279
 AMultilayer.cxx:280
 AMultilayer.cxx:281
 AMultilayer.cxx:282
 AMultilayer.cxx:283
 AMultilayer.cxx:284
 AMultilayer.cxx:285
 AMultilayer.cxx:286
 AMultilayer.cxx:287
 AMultilayer.cxx:288
 AMultilayer.cxx:289
 AMultilayer.cxx:290
 AMultilayer.cxx:291
 AMultilayer.cxx:292
 AMultilayer.cxx:293
 AMultilayer.cxx:294
 AMultilayer.cxx:295
 AMultilayer.cxx:296
 AMultilayer.cxx:297
 AMultilayer.cxx:298
 AMultilayer.cxx:299
 AMultilayer.cxx:300
 AMultilayer.cxx:301
 AMultilayer.cxx:302
 AMultilayer.cxx:303
 AMultilayer.cxx:304
 AMultilayer.cxx:305
 AMultilayer.cxx:306
 AMultilayer.cxx:307
 AMultilayer.cxx:308
 AMultilayer.cxx:309
 AMultilayer.cxx:310
 AMultilayer.cxx:311
 AMultilayer.cxx:312
 AMultilayer.cxx:313
 AMultilayer.cxx:314
 AMultilayer.cxx:315
 AMultilayer.cxx:316
 AMultilayer.cxx:317
 AMultilayer.cxx:318
 AMultilayer.cxx:319
 AMultilayer.cxx:320
 AMultilayer.cxx:321
 AMultilayer.cxx:322
 AMultilayer.cxx:323
 AMultilayer.cxx:324
 AMultilayer.cxx:325
 AMultilayer.cxx:326
 AMultilayer.cxx:327
 AMultilayer.cxx:328
 AMultilayer.cxx:329
 AMultilayer.cxx:330
 AMultilayer.cxx:331
 AMultilayer.cxx:332
 AMultilayer.cxx:333
 AMultilayer.cxx:334
 AMultilayer.cxx:335
 AMultilayer.cxx:336
 AMultilayer.cxx:337
 AMultilayer.cxx:338
 AMultilayer.cxx:339
 AMultilayer.cxx:340
 AMultilayer.cxx:341
 AMultilayer.cxx:342
 AMultilayer.cxx:343
 AMultilayer.cxx:344
 AMultilayer.cxx:345
 AMultilayer.cxx:346
 AMultilayer.cxx:347
 AMultilayer.cxx:348
 AMultilayer.cxx:349
 AMultilayer.cxx:350
 AMultilayer.cxx:351
 AMultilayer.cxx:352
 AMultilayer.cxx:353
 AMultilayer.cxx:354
 AMultilayer.cxx:355
 AMultilayer.cxx:356
 AMultilayer.cxx:357
 AMultilayer.cxx:358
 AMultilayer.cxx:359
 AMultilayer.cxx:360
 AMultilayer.cxx:361
 AMultilayer.cxx:362
 AMultilayer.cxx:363
 AMultilayer.cxx:364
 AMultilayer.cxx:365
 AMultilayer.cxx:366
 AMultilayer.cxx:367
 AMultilayer.cxx:368
 AMultilayer.cxx:369
 AMultilayer.cxx:370
 AMultilayer.cxx:371
 AMultilayer.cxx:372
 AMultilayer.cxx:373
 AMultilayer.cxx:374
 AMultilayer.cxx:375
 AMultilayer.cxx:376
 AMultilayer.cxx:377
 AMultilayer.cxx:378
 AMultilayer.cxx:379
 AMultilayer.cxx:380
 AMultilayer.cxx:381
 AMultilayer.cxx:382
 AMultilayer.cxx:383
 AMultilayer.cxx:384
 AMultilayer.cxx:385
 AMultilayer.cxx:386
 AMultilayer.cxx:387
 AMultilayer.cxx:388
 AMultilayer.cxx:389
 AMultilayer.cxx:390
 AMultilayer.cxx:391
 AMultilayer.cxx:392
 AMultilayer.cxx:393
 AMultilayer.cxx:394
 AMultilayer.cxx:395
 AMultilayer.cxx:396
 AMultilayer.cxx:397
 AMultilayer.cxx:398
 AMultilayer.cxx:399
 AMultilayer.cxx:400
 AMultilayer.cxx:401
 AMultilayer.cxx:402