LCOV - code coverage report
Current view: top level - Preamplifier - TriodeFilter.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 101 106 95.3 %
Date: 2021-02-18 20:07:22 Functions: 65 90 72.2 %

          Line data    Source code
       1             : /**
       2             :  * \file TriodeFilter.cpp
       3             :  */
       4             : 
       5             : #include <ATK/Preamplifier/DempwolfTriodeFunction.h>
       6             : #include <ATK/Preamplifier/EnhancedKorenTriodeFunction.h>
       7             : #include <ATK/Preamplifier/KorenTriodeFunction.h>
       8             : #include <ATK/Preamplifier/LeachTriodeFunction.h>
       9             : #include <ATK/Preamplifier/MunroPiazzaTriodeFunction.h>
      10             : #include <ATK/Preamplifier/ModifiedMunroPiazzaTriodeFunction.h>
      11             : #include <ATK/Preamplifier/TriodeFilter.h>
      12             : #include <ATK/Utility/SimplifiedVectorizedNewtonRaphson.h>
      13             : #include <ATK/Utility/VectorizedNewtonRaphson.h>
      14             : 
      15             : #include <cassert>
      16             : 
      17             : namespace ATK
      18             : {
      19             :   template <typename DataType_, typename TriodeFunction>
      20             :   class TriodeFilter<DataType_, TriodeFunction>::CommonCathodeTriodeFunction
      21             :   {
      22             :     const DataType_ Rp;
      23             :     const DataType_ Rg;
      24             :     const DataType_ Ro;
      25             :     const DataType_ Rk;
      26             :     const DataType_ Vbias;
      27             :     const DataType_ Co;
      28             :     const DataType_ Ck;
      29             : 
      30             :     DataType_ ickeq;
      31             :     DataType_ icoeq;
      32             : 
      33             :     TriodeFunction& tube_function;
      34             : 
      35             :   public:
      36             :     using DataType = DataType_;
      37             :     using Vector = Eigen::Matrix<DataType, 4, 1>;
      38             :     using Matrix = Eigen::Matrix<DataType, 4, 4>;
      39             : 
      40             :     template<typename T>
      41           7 :     CommonCathodeTriodeFunction(DataType dt, DataType Rp, DataType Rg, DataType Ro, DataType Rk, DataType Vbias, DataType Co, DataType Ck, TriodeFunction& tube_function, const T& default_output)
      42           7 :       :Rp(1/Rp), Rg(1/Rg), Ro(1/Ro), Rk(1/Rk), Vbias(Vbias), Co(2 / dt * Co), Ck(2 / dt * Ck), ickeq(2 / dt * Ck * default_output[1]), icoeq(-2 / dt * Co * default_output[2]), tube_function(tube_function)
      43             :     {
      44           7 :     }
      45             : 
      46       25200 :     Vector estimate(gsl::index i, const DataType* const * ATK_RESTRICT input, DataType* const * ATK_RESTRICT output)
      47             :     {
      48       25200 :       return affine_estimate(i, input, output);
      49             :     }
      50             :         
      51       25200 :     Vector affine_estimate(gsl::index i, const DataType* const * ATK_RESTRICT input, DataType* const * ATK_RESTRICT output)
      52             :     {
      53       25200 :       auto Ib = tube_function.Lb(output[3][i - 1] - output[0][i - 1], output[2][i - 1] - output[0][i - 1]);
      54       25200 :       auto Ic = tube_function.Lc(output[3][i - 1] - output[0][i - 1], output[2][i - 1] - output[0][i - 1]);
      55             :       
      56       25200 :       auto Ib_Vbe = tube_function.Lb_Vbe(output[3][i - 1] - output[0][i - 1], output[2][i - 1] - output[0][i - 1]);
      57       25200 :       auto Ib_Vce = tube_function.Lb_Vce(output[3][i - 1] - output[0][i - 1], output[2][i - 1] - output[0][i - 1]);
      58             :       
      59       25200 :       auto Ic_Vbe = tube_function.Lc_Vbe(output[3][i - 1] - output[0][i - 1], output[2][i - 1] - output[0][i - 1]);
      60       25200 :       auto Ic_Vce = tube_function.Lc_Vce(output[3][i - 1] - output[0][i - 1], output[2][i - 1] - output[0][i - 1]);
      61             :       
      62           0 :       Vector y0(-ickeq - (Ib - Ib_Vbe * (output[3][i - 1] - output[0][i - 1]) - Ib_Vce * (output[2][i - 1] - output[0][i - 1]) + Ic - Ic_Vbe * (output[3][i - 1] - output[0][i - 1]) - Ic_Vce * (output[2][i - 1] - output[0][i - 1])),
      63       25200 :       -icoeq,
      64           0 :         Vbias * Rp - (Ic - Ic_Vbe * (output[3][i - 1] - output[0][i - 1]) - Ic_Vce * (output[2][i - 1] - output[0][i - 1])),
      65       25200 :         input[0][i] * Rg - (Ib - Ib_Vbe * (output[3][i - 1] - output[0][i - 1]) - Ib_Vce * (output[2][i - 1] - output[0][i - 1])));
      66             :       
      67       25200 :       Matrix M;
      68       50400 :       M << -(Ib_Vbe + Ic_Vbe + Ib_Vce + Ic_Vce) - (Rk + Ck), 0, (Ib_Vce + Ic_Vce), (Ib_Vbe + Ic_Vbe),
      69       25200 :         0, Ro + Co, Ro, 0,
      70       25200 :         -(Ic_Vbe + Ic_Vce), Ro, Rp + Ro + Ic_Vce, Ic_Vbe,
      71       50400 :         -(Ib_Vbe + Ib_Vce), 0, Ib_Vce, Ib_Vbe + Rg;
      72             :       
      73       50400 :       return M.inverse() * y0;
      74             :     }
      75             : 
      76       25200 :     void update_state(gsl::index i, const DataType* const * ATK_RESTRICT input, DataType* const * ATK_RESTRICT output)
      77             :     {
      78       25200 :       ickeq = 2 * Ck * output[1][i] - ickeq;
      79       25200 :       icoeq = -2 * Co * output[2][i] - icoeq;
      80       25200 :     }
      81             : 
      82       44916 :     Vector operator()(gsl::index i, const DataType* const * ATK_RESTRICT input, DataType* const * ATK_RESTRICT output, const Vector& y1)
      83             :     {
      84       44916 :       auto Ib = tube_function.Lb(y1(3) - y1(0), y1(2) - y1(0));
      85       44916 :       auto Ic = tube_function.Lc(y1(3) - y1(0), y1(2) - y1(0));
      86             : 
      87       44916 :       auto Ib_Vbe = tube_function.Lb_Vbe(y1(3) - y1(0), y1(2) - y1(0));
      88       44916 :       auto Ib_Vce = tube_function.Lb_Vce(y1(3) - y1(0), y1(2) - y1(0));
      89             : 
      90       44916 :       auto Ic_Vbe = tube_function.Lc_Vbe(y1(3) - y1(0), y1(2) - y1(0));
      91       44916 :       auto Ic_Vce = tube_function.Lc_Vce(y1(3) - y1(0), y1(2) - y1(0));
      92             : 
      93       44916 :       auto f1 = Ib + Ic + ickeq - y1(0) * (Rk + Ck);
      94       44916 :       auto f2 = icoeq + (y1(1) + y1(2)) * Ro + y1(1) * Co;
      95             : 
      96       44916 :       auto g1 = (y1(2) - Vbias) * Rp + (Ic + (y1(1) + y1(2)) * Ro);
      97       44916 :       auto g2 = (y1(3) - input[0][i]) * Rg + Ib;
      98             :       
      99       44916 :       Vector F(f1,
     100             :            f2,
     101             :            g1,
     102             :            g2);
     103             : 
     104       44916 :       Matrix M;
     105       89832 :       M << -(Ib_Vbe + Ic_Vbe + Ib_Vce + Ic_Vce) - (Rk + Ck), 0, (Ib_Vce + Ic_Vce), (Ib_Vbe + Ic_Vbe),
     106       44916 :             0, Ro + Co, Ro, 0,
     107       44916 :       -(Ic_Vbe + Ic_Vce), Ro, Rp + Ro + Ic_Vce, Ic_Vbe,
     108       89832 :             -(Ib_Vbe + Ib_Vce), 0, Ib_Vce, Ib_Vbe + Rg;
     109             :       
     110       89832 :       return M.inverse() * F;
     111             :     }
     112             : 
     113             :   };
     114             :   
     115             :   template <typename DataType_, typename TriodeFunction>
     116             :   class CommonCathodeTriodeInitialFunction
     117             :   {
     118             :     const DataType_ Rp;
     119             :     const DataType_ Rg;
     120             :     const DataType_ Ro;
     121             :     const DataType_ Rk;
     122             :     const DataType_ Vbias;
     123             : 
     124             :     TriodeFunction& tube_function;
     125             : 
     126             :   public:
     127             :     using DataType = DataType_;
     128             :     using Vector = Eigen::Matrix<DataType, 3, 1>;
     129             :     using Matrix = Eigen::Matrix<DataType, 3, 3>;
     130             : 
     131           7 :     CommonCathodeTriodeInitialFunction(DataType Rp, DataType Rg, DataType Ro, DataType Rk, DataType Vbias, TriodeFunction& tube_function)
     132           7 :       :Rp(Rp), Rg(Rg), Ro(Ro), Rk(Rk), Vbias(Vbias), tube_function(tube_function)
     133             :     {
     134           7 :     }
     135             : 
     136          97 :     Vector operator()(const Vector& y1)
     137             :     {
     138          97 :       auto Ib = tube_function.Lb(y1(1) - y1(2), y1(0) - y1(2));
     139          97 :       auto Ic = tube_function.Lc(y1(1) - y1(2), y1(0) - y1(2));
     140             : 
     141          97 :       auto Ib_Vbe = tube_function.Lb_Vbe(y1(1) - y1(2), y1(0) - y1(2));
     142          97 :       auto Ib_Vce = tube_function.Lb_Vce(y1(1) - y1(2), y1(0) - y1(2));
     143             : 
     144          97 :       auto Ic_Vbe = tube_function.Lc_Vbe(y1(1) - y1(2), y1(0) - y1(2));
     145          97 :       auto Ic_Vce = tube_function.Lc_Vce(y1(1) - y1(2), y1(0) - y1(2));
     146             : 
     147          97 :       Vector F(y1(0) - Vbias + Ic * Rp,
     148          97 :         Ib * Rg + y1(1),
     149          97 :         y1(2) - (Ib + Ic) * Rk);
     150             : 
     151          97 :       Matrix M;
     152         194 :       M << 1 + Rp * Ic_Vce, Rp * Ic_Vbe, -Rp * (Ic_Vbe + Ic_Vce),
     153          97 :         Ib_Vce * Rg, 1 + Rg * Ib_Vbe, -Rg * (Ib_Vbe + Ib_Vce),
     154         194 :         -(Ic_Vce + Ib_Vce) * Rk, -(Ic_Vbe + Ib_Vbe) * Rk, 1 + (Ic_Vbe + Ic_Vce + Ib_Vbe + Ib_Vce) * Rk;
     155             : 
     156         194 :       return M.inverse() * F;
     157             :     }
     158             :   };
     159             : 
     160             :   template <typename DataType, typename TriodeFunction>
     161           6 :   TriodeFilter<DataType, TriodeFunction>::TriodeFilter(DataType Rp, DataType Rg, DataType Ro, DataType Rk, DataType Vbias, DataType Co, DataType Ck, TriodeFunction&& tube_function)
     162           6 :   :Parent(1, 5), Rp(Rp), Rg(Rg), Ro(Ro), Rk(Rk), Vbias(Vbias), Co(Co), Ck(Ck), tube_function(std::move(tube_function))
     163             :   {
     164           6 :     input_delay = output_delay = 1;
     165           6 :   }
     166             : 
     167             :   template <typename DataType, typename TriodeFunction>
     168           0 :   TriodeFilter<DataType, TriodeFunction>::TriodeFilter(TriodeFilter&& other)
     169           0 :   :Parent(std::move(other)), Rp(other.Rp), Rg(other.Rg), Ro(other.Ro), Rk(other.Rk), Vbias(other.Vbias), Co(other.Co), Ck(other.Ck), tube_function(std::move(other.tube_function))
     170             :   {
     171           0 :   }
     172             : 
     173             :   template<typename DataType,  typename TriodeFunction>
     174           6 :   TriodeFilter<DataType, TriodeFunction>::~TriodeFilter()
     175             :   {
     176           6 :   }
     177             : 
     178             :   template<typename DataType,  typename TriodeFunction>
     179           7 :   void TriodeFilter<DataType, TriodeFunction>::setup()
     180             :   {
     181           7 :     Parent::setup();
     182           7 :     optimizer = std::make_unique<VectorizedNewtonRaphson<CommonCathodeTriodeFunction, 4, 10, true>>(CommonCathodeTriodeFunction(static_cast<DataType>(1. / input_sampling_rate),
     183           7 :       Rp, Rg, Ro, Rk, //R
     184           7 :       Vbias, // Vbias
     185           7 :       Co, Ck, // C
     186           7 :       tube_function, // tube
     187           7 :       default_output));
     188           7 :   }
     189             : 
     190             :   template<typename DataType, typename TriodeFunction>
     191           7 :   void TriodeFilter<DataType, TriodeFunction>::full_setup()
     192             :   {
     193           7 :     Eigen::Matrix<DataType, 3, 1> y0;
     194           7 :     y0 << Vbias, 0, 0;
     195             :     
     196             :     // setup default_output
     197           7 :     SimplifiedVectorizedNewtonRaphson<CommonCathodeTriodeInitialFunction<DataType, TriodeFunction>, 3, 20> custom(CommonCathodeTriodeInitialFunction<DataType, TriodeFunction>(
     198           7 :       Rp, Rg, Ro, Rk, //R
     199           7 :       Vbias, // Vbias
     200           7 :       tube_function // tube
     201           7 :       ), std::move(y0));
     202             : 
     203           7 :     auto stable = custom.optimize();
     204             : 
     205           7 :     default_output[0] = 0;
     206           7 :     default_output[1] = stable(2);
     207           7 :     default_output[2] = -stable(0);
     208           7 :     default_output[3] = stable(0);
     209           7 :     default_output[4] = stable(1);
     210             : 
     211           7 :     Parent::full_setup();
     212           7 :   }
     213             : 
     214             :   template<typename DataType, typename TriodeFunction>
     215           6 :   void TriodeFilter<DataType, TriodeFunction>::process_impl(gsl::index size) const
     216             :   {
     217           6 :     assert(input_sampling_rate == output_sampling_rate);
     218             : 
     219       25206 :     for(gsl::index i = 0; i < size; ++i)
     220             :     {
     221       25200 :       optimizer->optimize(i, converted_inputs.data(), outputs.data() + 1);
     222       25200 :       outputs[0][i] = outputs[2][i] + outputs[3][i];
     223       25200 :       optimizer->get_function().update_state(i, converted_inputs.data(), outputs.data());
     224             :     }
     225           6 :   }
     226             : 
     227             :   template<typename DataType, typename TriodeFunction>
     228           6 :   TriodeFilter<DataType, TriodeFunction> TriodeFilter<DataType, TriodeFunction>::build_standard_filter(DataType Rp, DataType Rg, DataType Ro, DataType Rk, DataType Vbias, DataType Co, DataType Ck, TriodeFunction function)
     229             :   {
     230             :     return TriodeFilter<DataType, TriodeFunction>(Rp, Rg, Ro, Rk, //R
     231             :                                                   Vbias, // Vbias
     232             :                                                   Co, Ck, // C
     233           6 :                                                   std::move(function) // tube
     234           6 :       );
     235             :   }
     236             : 
     237             : #if ATK_ENABLE_INSTANTIATION
     238             :   template class TriodeFilter<float, LeachTriodeFunction<float> >;
     239             :   template class TriodeFilter<float, MunroPiazzaTriodeFunction<float> >;
     240             :   template class TriodeFilter<float, ModifiedMunroPiazzaTriodeFunction<float> >;
     241             :   template class TriodeFilter<float, KorenTriodeFunction<float> >;
     242             :   template class TriodeFilter<float, EnhancedKorenTriodeFunction<float> >;
     243             :   template class TriodeFilter<float, DempwolfTriodeFunction<float> >;
     244             : #endif
     245             :   template class TriodeFilter<double, LeachTriodeFunction<double> >;
     246             :   template class TriodeFilter<double, MunroPiazzaTriodeFunction<double> >;
     247             :   template class TriodeFilter<double, ModifiedMunroPiazzaTriodeFunction<double> >;
     248             :   template class TriodeFilter<double, KorenTriodeFunction<double> >;
     249             :   template class TriodeFilter<double, EnhancedKorenTriodeFunction<double> >;
     250             :   template class TriodeFilter<double, DempwolfTriodeFunction<double> >;
     251             : }

Generated by: LCOV version TK-3.3.0-4-gdba42eea