ROBAST logo
// Author: Akira Okumura <mailto:oxon@mac.com>
/******************************************************************************
 * Copyright (C) 2006-, Akira Okumura                                         *
 * All rights reserved.                                                       *
 *****************************************************************************/

#ifndef A_MULTILAYER_H
#define A_MULTILAYER_H

#include <memory>
#include <thread>

#include <TH2.h>

#include "ARefractiveIndex.h"

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

class AMultilayer : public TObject {
 public:
  enum EPolarization { kS, kP };

 private:
  std::vector<std::shared_ptr<ARefractiveIndex>> fRefractiveIndexList;
  std::vector<Double_t> fThicknessList;
  std::size_t fNthreads;
  std::shared_ptr<TH2D> fPreCalculatedReflectanceMixed;
  std::shared_ptr<TH2D> fPreCalculatedTransmittanceMixed;

  Bool_t IsForwardAngle(std::complex<Double_t> n,
                        std::complex<Double_t> theta) const;
  void 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;
  void CoherentTMMMixedMultiAngle(
      std::vector<std::complex<Double_t>>::const_iterator th_0_cbegin,
      std::vector<std::complex<Double_t>>::const_iterator th_0_cend,
      Double_t lam_vac, std::vector<Double_t>::iterator reflectance_it,
      std::vector<Double_t>::iterator transmittance_it) {
    for (auto cit = th_0_cbegin; cit != th_0_cend; ++cit) {
      Double_t r, t;
      CoherentTMMMixed(*cit, lam_vac, r, t);
      *reflectance_it = r;
      *transmittance_it = t;
      ++reflectance_it;
      ++transmittance_it;
    }
  }
  void CoherentTMMMixedMultiWavelength(
      std::complex<Double_t> th_0,
      std::vector<Double_t>::const_iterator lam_vac_cbegin,
      std::vector<Double_t>::const_iterator lam_vac_cend,
      std::vector<Double_t>::iterator reflectance_it,
      std::vector<Double_t>::iterator transmittance_it) {
    for (auto cit = lam_vac_cbegin; cit != lam_vac_cend; ++cit) {
      Double_t r, t;
      CoherentTMMMixed(th_0, *cit, r, t);
      *reflectance_it = r;
      *transmittance_it = t;
      ++reflectance_it;
      ++transmittance_it;
    }
  }

 public:
  AMultilayer(std::shared_ptr<ARefractiveIndex> top,
              std::shared_ptr<ARefractiveIndex> bottom);
  virtual ~AMultilayer();

  void InsertLayer(std::shared_ptr<ARefractiveIndex> idx, Double_t thickness);
  void ChangeThickness(std::size_t i, Double_t thickness) {
    if (i < 1 || i > fThicknessList.size() - 2) {
      Error("ChangeThickness", "Cannot change the thickness of the %luth layer",
            i);
    } else {
      fThicknessList[i] = thickness;
    }
  }

  void CoherentTMM(EPolarization polarization, std::complex<Double_t> th_0,
                   Double_t lam_vac, Double_t& reflectance,
                   Double_t& transmittance) const;
  void CoherentTMMMixed(std::complex<Double_t> th_0, Double_t lam_vac,
                        Double_t& reflectance, Double_t& transmittance) const {
    if(fPreCalculatedReflectanceMixed and fPreCalculatedTransmittanceMixed) {
      reflectance = fPreCalculatedReflectanceMixed->Interpolate(lam_vac, th_0.real());
      transmittance = fPreCalculatedTransmittanceMixed->Interpolate(lam_vac, th_0.real());
      return;
    }
    Double_t r = 0;
    Double_t t = 0;
    CoherentTMMP(th_0, lam_vac, reflectance, transmittance);
    r += reflectance;
    t += transmittance;
    CoherentTMMS(th_0, lam_vac, reflectance, transmittance);
    r += reflectance;
    t += transmittance;

    reflectance = r / 2.;
    transmittance = t / 2.;
  }
  void CoherentTMMMixed(std::vector<std::complex<Double_t>>& th_0,
                        Double_t lam_vac, std::vector<Double_t>& reflectance,
                        std::vector<Double_t>& transmittance) const {
    auto n = th_0.size();
    reflectance.resize(n);
    transmittance.resize(n);
    if(fPreCalculatedReflectanceMixed and fPreCalculatedTransmittanceMixed) {
      for(std::size_t i = 0; i < n; ++i){
        auto th = th_0[i].real();
        reflectance[i] =  fPreCalculatedReflectanceMixed->Interpolate(lam_vac, th);
        transmittance[i] = fPreCalculatedTransmittanceMixed->Interpolate(lam_vac, th);
      }
      return;
    }

    std::vector<std::thread> threads(fNthreads);

    auto th_0_cbegin = th_0.cbegin();
    auto th_0_cend = th_0.end();
    auto reflectance_begin = reflectance.begin();
    auto transmittance_begin = transmittance.begin();

    auto step = n / fNthreads;

    for (std::size_t i = 0; i < fNthreads; ++i) {
      if (i == fNthreads - 1) {
        threads[i] =
            std::thread(&AMultilayer::CoherentTMMMixedMultiAngle, *this,
                        th_0_cbegin, th_0_cbegin + step, lam_vac,
                        reflectance_begin, transmittance_begin);
        th_0_cbegin += step;
      } else {
        threads[i] = std::thread(&AMultilayer::CoherentTMMMixedMultiAngle,
                                 *this, th_0_cbegin, th_0_cend, lam_vac,
                                 reflectance_begin, transmittance_begin);
      }
    }
    for (std::size_t i = 0; i < fNthreads; ++i) {
      threads[i].join();
    }
  }
  void CoherentTMMMixed(std::complex<Double_t> th_0,
                        std::vector<Double_t>& lam_vac,
                        std::vector<Double_t>& reflectance,
                        std::vector<Double_t>& transmittance) const {
    auto n = lam_vac.size();
    reflectance.resize(n);
    transmittance.resize(n);

    std::vector<std::thread> threads(fNthreads);

    auto lam_vac_cbegin = lam_vac.cbegin();
    auto lam_vac_cend = lam_vac.end();
    auto reflectance_begin = reflectance.begin();
    auto transmittance_begin = transmittance.begin();

    auto step = n / fNthreads;

    for (std::size_t i = 0; i < fNthreads; ++i) {
      if (i == fNthreads - 1) {
        threads[i] =
            std::thread(&AMultilayer::CoherentTMMMixedMultiWavelength, *this,
                        th_0, lam_vac_cbegin, lam_vac_cbegin + step,
                        reflectance_begin, transmittance_begin);
        lam_vac_cbegin += step;
      } else {
        threads[i] = std::thread(&AMultilayer::CoherentTMMMixedMultiWavelength,
                                 *this, th_0, lam_vac_cbegin, lam_vac_cend,
                                 reflectance_begin, transmittance_begin);
      }
    }
    for (std::size_t i = 0; i < fNthreads; ++i) {
      threads[i].join();
    }
  }
  void CoherentTMMP(std::complex<Double_t> th_0, Double_t lam_vac,
                    Double_t& reflectance, Double_t& transmittance) const {
    CoherentTMM(kP, th_0, lam_vac, reflectance, transmittance);
  }
  void CoherentTMMS(std::complex<Double_t> th_0, Double_t lam_vac,
                    Double_t& reflectance, Double_t& transmittance) const {
    CoherentTMM(kS, th_0, lam_vac, reflectance, transmittance);
  }
  void PreCalculateTMM(Int_t lam_nbins, Double_t lam_min, Double_t lam_max,
                            Int_t th_nbins, Double_t th_min, Double_t th_max) {
    fPreCalculatedReflectanceMixed = std::make_shared<TH2D>("", "", lam_nbins, lam_min, lam_max, th_nbins, th_min, th_max);
    fPreCalculatedTransmittanceMixed = std::make_shared<TH2D>("", "", lam_nbins, lam_min, lam_max, th_nbins, th_min, th_max);
    for (Int_t j = 1; j <= th_nbins; ++j) {
      Double_t th = fPreCalculatedReflectanceMixed->GetYaxis()->GetBinCenter(j);
      for (Int_t i = 1; i <= lam_nbins; ++i) {
        Double_t lam = fPreCalculatedReflectanceMixed->GetXaxis()->GetBinCenter(i);
        Double_t reflectance, transmittance;
        CoherentTMMMixed(th, lam, reflectance, transmittance);
        fPreCalculatedReflectanceMixed->SetBinContent(i, j, reflectance);
        fPreCalculatedTransmittanceMixed->SetBinContent(i, j, transmittance);
      }
    }
  }
  const std::shared_ptr<const TH2D> GetPrecalculatedReflectanceMixed() const {
    return fPreCalculatedReflectanceMixed;
  }
  const std::shared_ptr<const TH2D> GetPrecalculatedTransmittanceMixed() const {
    return fPreCalculatedTransmittanceMixed;
  }
  void PrintLayers(Double_t lambda) const;
  void SetNthreads(std::size_t n);

  ClassDef(AMultilayer, 1)
};

#endif  // A_MULTILAYER_H
 AMultilayer.h:1
 AMultilayer.h:2
 AMultilayer.h:3
 AMultilayer.h:4
 AMultilayer.h:5
 AMultilayer.h:6
 AMultilayer.h:7
 AMultilayer.h:8
 AMultilayer.h:9
 AMultilayer.h:10
 AMultilayer.h:11
 AMultilayer.h:12
 AMultilayer.h:13
 AMultilayer.h:14
 AMultilayer.h:15
 AMultilayer.h:16
 AMultilayer.h:17
 AMultilayer.h:18
 AMultilayer.h:19
 AMultilayer.h:20
 AMultilayer.h:21
 AMultilayer.h:22
 AMultilayer.h:23
 AMultilayer.h:24
 AMultilayer.h:25
 AMultilayer.h:26
 AMultilayer.h:27
 AMultilayer.h:28
 AMultilayer.h:29
 AMultilayer.h:30
 AMultilayer.h:31
 AMultilayer.h:32
 AMultilayer.h:33
 AMultilayer.h:34
 AMultilayer.h:35
 AMultilayer.h:36
 AMultilayer.h:37
 AMultilayer.h:38
 AMultilayer.h:39
 AMultilayer.h:40
 AMultilayer.h:41
 AMultilayer.h:42
 AMultilayer.h:43
 AMultilayer.h:44
 AMultilayer.h:45
 AMultilayer.h:46
 AMultilayer.h:47
 AMultilayer.h:48
 AMultilayer.h:49
 AMultilayer.h:50
 AMultilayer.h:51
 AMultilayer.h:52
 AMultilayer.h:53
 AMultilayer.h:54
 AMultilayer.h:55
 AMultilayer.h:56
 AMultilayer.h:57
 AMultilayer.h:58
 AMultilayer.h:59
 AMultilayer.h:60
 AMultilayer.h:61
 AMultilayer.h:62
 AMultilayer.h:63
 AMultilayer.h:64
 AMultilayer.h:65
 AMultilayer.h:66
 AMultilayer.h:67
 AMultilayer.h:68
 AMultilayer.h:69
 AMultilayer.h:70
 AMultilayer.h:71
 AMultilayer.h:72
 AMultilayer.h:73
 AMultilayer.h:74
 AMultilayer.h:75
 AMultilayer.h:76
 AMultilayer.h:77
 AMultilayer.h:78
 AMultilayer.h:79
 AMultilayer.h:80
 AMultilayer.h:81
 AMultilayer.h:82
 AMultilayer.h:83
 AMultilayer.h:84
 AMultilayer.h:85
 AMultilayer.h:86
 AMultilayer.h:87
 AMultilayer.h:88
 AMultilayer.h:89
 AMultilayer.h:90
 AMultilayer.h:91
 AMultilayer.h:92
 AMultilayer.h:93
 AMultilayer.h:94
 AMultilayer.h:95
 AMultilayer.h:96
 AMultilayer.h:97
 AMultilayer.h:98
 AMultilayer.h:99
 AMultilayer.h:100
 AMultilayer.h:101
 AMultilayer.h:102
 AMultilayer.h:103
 AMultilayer.h:104
 AMultilayer.h:105
 AMultilayer.h:106
 AMultilayer.h:107
 AMultilayer.h:108
 AMultilayer.h:109
 AMultilayer.h:110
 AMultilayer.h:111
 AMultilayer.h:112
 AMultilayer.h:113
 AMultilayer.h:114
 AMultilayer.h:115
 AMultilayer.h:116
 AMultilayer.h:117
 AMultilayer.h:118
 AMultilayer.h:119
 AMultilayer.h:120
 AMultilayer.h:121
 AMultilayer.h:122
 AMultilayer.h:123
 AMultilayer.h:124
 AMultilayer.h:125
 AMultilayer.h:126
 AMultilayer.h:127
 AMultilayer.h:128
 AMultilayer.h:129
 AMultilayer.h:130
 AMultilayer.h:131
 AMultilayer.h:132
 AMultilayer.h:133
 AMultilayer.h:134
 AMultilayer.h:135
 AMultilayer.h:136
 AMultilayer.h:137
 AMultilayer.h:138
 AMultilayer.h:139
 AMultilayer.h:140
 AMultilayer.h:141
 AMultilayer.h:142
 AMultilayer.h:143
 AMultilayer.h:144
 AMultilayer.h:145
 AMultilayer.h:146
 AMultilayer.h:147
 AMultilayer.h:148
 AMultilayer.h:149
 AMultilayer.h:150
 AMultilayer.h:151
 AMultilayer.h:152
 AMultilayer.h:153
 AMultilayer.h:154
 AMultilayer.h:155
 AMultilayer.h:156
 AMultilayer.h:157
 AMultilayer.h:158
 AMultilayer.h:159
 AMultilayer.h:160
 AMultilayer.h:161
 AMultilayer.h:162
 AMultilayer.h:163
 AMultilayer.h:164
 AMultilayer.h:165
 AMultilayer.h:166
 AMultilayer.h:167
 AMultilayer.h:168
 AMultilayer.h:169
 AMultilayer.h:170
 AMultilayer.h:171
 AMultilayer.h:172
 AMultilayer.h:173
 AMultilayer.h:174
 AMultilayer.h:175
 AMultilayer.h:176
 AMultilayer.h:177
 AMultilayer.h:178
 AMultilayer.h:179
 AMultilayer.h:180
 AMultilayer.h:181
 AMultilayer.h:182
 AMultilayer.h:183
 AMultilayer.h:184
 AMultilayer.h:185
 AMultilayer.h:186
 AMultilayer.h:187
 AMultilayer.h:188
 AMultilayer.h:189
 AMultilayer.h:190
 AMultilayer.h:191
 AMultilayer.h:192
 AMultilayer.h:193
 AMultilayer.h:194
 AMultilayer.h:195
 AMultilayer.h:196
 AMultilayer.h:197
 AMultilayer.h:198
 AMultilayer.h:199
 AMultilayer.h:200
 AMultilayer.h:201
 AMultilayer.h:202
 AMultilayer.h:203
 AMultilayer.h:204
 AMultilayer.h:205
 AMultilayer.h:206
 AMultilayer.h:207
 AMultilayer.h:208
 AMultilayer.h:209
 AMultilayer.h:210
 AMultilayer.h:211
 AMultilayer.h:212
 AMultilayer.h:213
 AMultilayer.h:214
 AMultilayer.h:215
 AMultilayer.h:216