30#ifdef MX_INCLUDE_BOOST 
   31    #include <boost/math/tools/minima.hpp> 
   38#include "../../sys/timeUtils.hpp" 
   40#include "../../math/constants.hpp" 
   52template <
typename realT>
 
   53struct clGainOptOptGain_OL;
 
   62template <
typename _realT>
 
   74    std::vector<realT> 
m_b;  
 
   75    std::vector<realT> 
m_a;  
 
   77    std::vector<realT> 
m_f;  
 
   83    Eigen::Array<
realT, -1, -1> m_cs;
 
   84    Eigen::Array<
realT, -1, -1> m_ss;
 
   86    std::vector<std::complex<realT>> m_H_dm;
 
   87    std::vector<std::complex<realT>> m_H_wfs;
 
   88    std::vector<std::complex<realT>> m_H_ma;
 
   89    std::vector<std::complex<realT>> m_H_del;
 
   90    std::vector<std::complex<realT>> m_H_con;
 
  146    void Ti( realT newTi  );
 
  162    void b( 
const std::vector<realT> &newB  );
 
  167    void b( 
const Eigen::Array<realT, -1, -1>
 
  183    const std::vector<realT> &
b()
 
 
  188    void bScale( realT scale );
 
  193    void a( 
const std::vector<realT> &newA  );
 
  198    void a( 
const Eigen::Array<realT, -1, -1> &newA 
 
  212    const std::vector<realT> &
a()
 
 
  217    void aScale( realT scale );
 
  242    void f( std::vector<realT> &newF  );
 
  345                      const std::vector<realT> &PSDerr,   
 
  346                      const std::vector<realT> &PSDnoise, 
 
  358                      const std::vector<realT> &PSDnoise, 
 
  408                           const std::vector<realT> &PSDerr,   
 
  409                           const std::vector<realT> &PSDnoise, 
 
  419                           const std::vector<realT> &PSDerr,   
 
  420                           const std::vector<realT> &PSDnoise, 
 
  436    int nyquist( std::vector<realT> &re, std::vector<realT> &im, realT g );
 
  439template <
typename realT>
 
  445template <
typename realT>
 
  454template <
typename realT>
 
  459    setLeakyIntegrator( 1.0 );
 
  467    m_minFindMaxFact = 0.999;
 
  468    m_minFindBits = std::numeric_limits<realT>::digits;
 
  469    m_minFindMaxIter = 10000;
 
 
  475template <
typename realT>
 
  481template <
typename realT>
 
  493template <
typename realT>
 
  499template <
typename realT>
 
  511template <
typename realT>
 
  517template <
typename realT>
 
  520    if( m_tau == newTau )
 
 
  529template <
typename realT>
 
  532    if( newB.size() > (
size_t)m_cs.cols() )
 
 
  541template <
typename realT>
 
  544    if( newB.cols() > m_cs.cols() )
 
  549    m_b.resize( newB.cols() );
 
  551    for( 
size_t i = 0; i < m_b.size(); ++i )
 
  553        m_b[i] = newB( 0, i );
 
 
  559template <
typename realT>
 
  562        for( 
size_t n = 0; n < m_b.size(); ++n )
 
  570template <
typename realT>
 
  573    if( newA.size() + 1 > (
size_t)m_cs.cols() )
 
 
  582template <
typename realT>
 
  585    if( newA.cols() + 1 > m_cs.cols() )
 
  590    m_a.resize( newA.cols() );
 
  592    for( 
size_t i = 0; i < m_a.size(); ++i )
 
  594        m_a[i] = newA( 0, i );
 
 
  600template <
typename realT>
 
  603    for( 
size_t n = 0; n < m_a.size(); ++n )
 
  611template <
typename realT>
 
  614    if(m_remember != rem)
 
 
  624template <
typename realT>
 
  630template <
typename realT>
 
  633    if(m_b.size() != 1 || m_a.size() != 1 || m_b[0] != 1.0 || m_a[0] != 1.0 || m_remember != remember)
 
  651        m_remember = remember;
 
 
  657template <
typename realT>
 
  661    for( 
int i = 0; i < nF; ++i )
 
 
  670template <
typename realT>
 
  679template <
typename realT>
 
  686template <
typename realT>
 
  693    return olXfer( fi, H_dm, H_del, H_con );
 
 
  700template <
typename realT>
 
  720        size_t jmax = std::max( m_a.size() + 1, m_b.size() );
 
  722        m_cs.resize( m_f.size(), jmax );
 
  723        m_ss.resize( m_f.size(), jmax );
 
  725        for( 
size_t i = 0; i < m_f.size(); ++i )
 
  730            for( 
size_t j = 1; j < jmax; ++j )
 
  743        m_H_dm.resize( m_f.size(), 0 );
 
  744        m_H_wfs.resize( m_f.size(), 0 );
 
  745        m_H_ma.resize( m_f.size(), 0 );
 
  746        m_H_del.resize( m_f.size(), 0 );
 
  747        m_H_con.resize( m_f.size(), 0 );
 
  749        size_t jmax = std::min( m_a.size(), m_b.size() );
 
  752        for( 
size_t i = 0; i < m_f.size(); ++i )
 
  768                m_H_dm[i] = std::complex<realT>( 1, 0 );
 
  772                m_H_dm[i] = ( 
realT( 1 ) - expsT ) / ( s * m_Ti );
 
  775            m_H_wfs[i] = m_H_dm[i];
 
  779            m_H_del[i] = exp( -s * m_tau );
 
  784            for( 
size_t j = 1; j < jmax; ++j )
 
  787                realT cs = m_cs( i, j );
 
  788                realT ss = m_ss( i, j );
 
  789                FIR += m_b[j] * 
complexT( cs, -ss );
 
  790                IIR += m_remember * m_a[j - 1] * 
complexT( cs, -ss );
 
  793                FIR += m_b[j] * expZ;
 
  794                IIR += m_remember * m_a[j - 1] * expZ;
 
  798            for( 
size_t jj = jmax; jj < m_a.size() + 1; ++jj )
 
  801                realT cs = m_cs( i, jj );
 
  802                realT ss = m_ss( i, jj );
 
  803                IIR += m_remember * m_a[jj - 1] * 
complexT( cs, -ss );
 
  806                IIR += m_remember * m_a[jj - 1] * expZ;
 
  810            for( 
size_t jj = jmax; jj < m_b.size(); ++jj )
 
  813                realT cs = m_cs( i, jj );
 
  814                realT ss = m_ss( i, jj );
 
  815                FIR += m_b[jj] * 
complexT( cs, -ss );
 
  818                FIR += m_b[jj] * expZ;
 
  822            m_H_con[i] = FIR / ( 
realT( 1.0 ) - IIR );
 
  840    return ( m_H_dm[fi] * m_H_wfs[fi] * m_H_del[fi] * m_H_con[fi] );
 
 
  843template <
typename realT>
 
  854    return ( 
realT( 1 ) / ( 
realT( 1 ) + g * olXfer( fi ) ) );
 
 
  857template <
typename realT>
 
  868    return std::arg( ( 
realT( 1 ) / ( 
realT( 1 ) + g * olXfer( fi ) ) ) );
 
 
  871template <
typename realT>
 
  882    return norm( 
realT( 1 ) / ( 
realT( 1 ) + g * olXfer( fi ) ) );
 
 
  885template <
typename realT>
 
  898    complexT olX = olXfer( fi, H_dm, H_del, H_con ); 
 
  900    return -( H_dm * H_del * g * H_con ) / ( 
realT( 1 ) + g * olX );
 
 
  903template <
typename realT>
 
  916    complexT olX = olXfer( fi, H_dm, H_del, H_con ); 
 
  918    complexT NTF = -( H_dm * H_del * g * H_con ) / ( 
realT( 1 ) + g * olX );
 
 
  923template <
typename realT>
 
  939    complexT olX = olXfer( fi, H_dm, H_del, H_con ); 
 
  945    ETF = norm( 
realT( 1 ) / ( 
realT( 1 ) + g * olX ) );
 
  946    NTF = norm( -( H_dm * H_del * g * H_con ) / ( 
realT( 1 ) + g * olX ) );
 
 
  954template <
typename realT>
 
  956    realT &varErr, 
realT &varNoise, 
const std::vector<realT> &PSDerr, 
const std::vector<realT> &PSDnoise, 
realT g )
 
  958    if( m_f.size() != PSDerr.size() || m_f.size() != PSDnoise.size() )
 
  960        std::cerr << 
"clVariance: Frequency grid and PSDs must be same size." << std::endl;
 
  969    df = m_f[1] - m_f[0];
 
  971    for( 
size_t i = 0; i < PSDerr.size(); ++i )
 
  980            clTF2( ETF, NTF, i, g );
 
  982        varErr += ETF * PSDerr[i] * df;
 
  983        varNoise += NTF * PSDnoise[i] * df;
 
  986    return varErr + varNoise;
 
 
  989template <
typename realT>
 
  995    return clVariance( varErr, varNoise, PSDerr, PSDnoise, g );
 
 
  998template <
typename realT>
 
 1001    static_cast<void>( ul );
 
 1003    std::vector<realT> re, im;
 
 1008    nyquist( re, im, 1.0 );
 
 1010    int gi_c = re.size() - 1;
 
 1012    for( 
int gi = re.size() - 2; gi >= 0; --gi )
 
 1014        if( -1.0 / re[gi] < ll )
 
 1017        if( ( re[gi] < 0 ) && ( im[gi + 1] >= 0 && im[gi] < 0 ) )
 
 1020            if( re[gi] <= re[gi_c] )
 
 1025    return -1.0 / re[gi_c];
 
 
 1028template <
typename realT>
 
 1029realT maxStableGain( 
const realT &ll, 
const realT &ul )
 
 1034    maxStableGain( rll, rul );
 
 1037template <
typename realT>
 
 1041    realT ll = m_maxFindMin;
 
 1043    return maxStableGain( ll, ul );
 
 
 1050template <
typename realT>
 
 1054                       const realT &minFindMin,
 
 1055                       const realT &minFindMaxFact,
 
 1057                       uintmax_t minFindMaxIter,
 
 1060#ifdef MX_INCLUDE_BOOST 
 1065        std::pair<realT, realT> brack;
 
 1066        brack = boost::math::tools::brentm_findm_minima<clGainOptOptGain_OL<realT>, realT>( olgo,
 
 1068                                                                                            minFindMaxFact * 
gmax,
 
 1077        std::cerr << 
"optGainOpenLoop: No root found\n";
 
 1078        gopt = minFindMaxFact * 
gmax;
 
 1084    staticm_assert( std::is_fundamental<realT>::value || !std::is_fundamental<realT>::value,
 
 1085                    "impl::optGainOpenLoop<realT> is not specialized for type realT, and MX_INCLUDE_BOOST is not " 
 1086                    "defined, so I can't just use boost." );
 
 1092float optGainOpenLoop<float>( clGainOptOptGain_OL<float> &olgo,
 
 1095                              const float &minFindMin,
 
 1096                              const float &minFindMaxFact,
 
 1098                              uintmax_t minFindMaxIter,
 
 1102double optGainOpenLoop<double>( clGainOptOptGain_OL<double> &olgo,
 
 1105                                const double &minFindMin,
 
 1106                                const double &minFindMaxFact,
 
 1108                                uintmax_t minFindMaxIter,
 
 1112long double optGainOpenLoop<long double>( clGainOptOptGain_OL<long double> &olgo,
 
 1114                                          const long double &
gmax,
 
 1115                                          const long double &minFindMin,
 
 1116                                          const long double &minFindMaxFact,
 
 1118                                          uintmax_t minFindMaxIter,
 
 1123_m_float128 optGainOpenLoop<_m_float128>( clGainOptOptGain_OL<_m_float128> &olgo,
 
 1125                                          const _m_float128 &
gmax,
 
 1126                                          const _m_float128 &minFindMin,
 
 1127                                          const _m_float128 &minFindMaxFact,
 
 1129                                          uintmax_t minFindMaxIter,
 
 1135template <
typename realT>
 
 1137                                         const std::vector<realT> &PSDerr,
 
 1138                                         const std::vector<realT> &PSDnoise,
 
 1142    return optGainOpenLoop( var, PSDerr, PSDnoise, 
gmax, gridSearch );
 
 
 1145template <
typename realT>
 
 1147    realT &var, 
const std::vector<realT> &PSDerr, 
const std::vector<realT> &PSDnoise, 
realT &
gmax, 
bool gridSearch )
 
 1151    olgo.PSDerr = &PSDerr;
 
 1152    olgo.PSDnoise = &PSDnoise;
 
 1155        gmax = maxStableGain();
 
 1157    realT ming = m_minFindMin;
 
 1162        realT gstpsz = 0.05;
 
 1164        realT var0 = clVariance( PSDerr, PSDnoise, gg );
 
 1167        while( gg > m_minFindMin )
 
 1170            realT var1 = clVariance( PSDerr, PSDnoise, gg );
 
 1179        ming = mingg - gstpsz;
 
 1180        maxg = mingg + gstpsz;
 
 1182        if( ming < m_minFindMin )
 
 1183            ming = m_minFindMin;
 
 1190        impl::optGainOpenLoop( olgo, var, maxg, ming, m_minFindMaxFact, m_minFindBits, m_minFindMaxIter, iters );
 
 1192    if( iters >= m_minFindMaxIter )
 
 1196            std::cerr << 
"\nclGainOpt<realT>::optGainOpenLoop: minFindMaxIter (" << m_minFindMaxIter << 
") reached\n";
 
 
 1203template <
typename realT>
 
 1207    for( 
int f = 0; f < m_f.size(); ++f )
 
 1212            PSD[f] = PSD[f] / e;
 
 
 
 1218template <
typename realT>
 
 1221    re.resize( m_f.size() );
 
 1222    im.resize( m_f.size() );
 
 1226    for( 
size_t f = 0; f < m_f.size(); ++f )
 
 1228        etf = g * olXfer( f ); 
 
 1229        re[f] = real( etf );
 
 1230        im[f] = imag( etf );
 
 1239template <
typename realT>
 
 1243    const std::vector<realT> *PSDerr;
 
 1244    const std::vector<realT> *PSDnoise;
 
 1246    realT operator()( 
const realT &g )
 
 1248        return go->
clVariance( *PSDerr, *PSDnoise, g );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
#define gmax(A, B)
max(A,B) - larger (most +ve) of two numbers (generic) (defined in the SOFA library sofam....
Bisection worker struct for finding optimum closed loop gain from open loop PSDs.
A class to manage optimizing closed-loop gains.
complexT olXfer(int fi)
Calculate the open-loop transfer function.
realT clVariance(const std::vector< realT > &PSDerr, const std::vector< realT > &PSDnoise, realT g)
Calculate the closed loop variance given open-loop PSDs and gain.
void f(std::vector< realT > &newF)
Set the vector of frequencies.
void Ti(realT newTi)
Set the loop sampling interval.
realT f(size_t i)
Get the i-th value of frequency.
void init()
Initialize this instance.
realT maxStableGain()
Find the maximum stable gain for the loop parameters.
void a(const std::vector< realT > &newA)
Set the vector of IIR coefficients.
clGainOpt(realT Ti, realT tau)
C'tor setting the loop timings.
void N(int newN)
Set the number of integrations in the moving average.
void b(const Eigen::Array< realT, -1, -1 > &newB)
Set the vector of FIR coefficients.
realT a(size_t i)
Get a single IIR coefficient.
int pseudoOpenLoop(std::vector< realT > &PSD, realT g)
Calculate the pseudo open-loop PSD given a closed loop PSD.
realT b(size_t i)
Get a single FIR coefficient.
complexT clNTF(int fi, realT g)
Return the closed loop noise transfer function (NTF) at frequency f for gain g.
void tau(realT newTau)
Set the loop delay.
std::vector< realT > m_f
Vector of frequencies.
void b(const std::vector< realT > &newB)
Set the vector of FIR coefficients.
realT optGainOpenLoop(realT &var, const std::vector< realT > &PSDerr, const std::vector< realT > &PSDnoise, bool gridSearch)
Return the optimum closed loop gain given an open loop PSD.
realT optGainOpenLoop(realT &var, const std::vector< realT > &PSDerr, const std::vector< realT > &PSDnoise, realT &gmax, bool gridSearch)
Return the optimum closed loop gain given an open loop PSD.
realT clNTF2(int fi, realT g)
Return the norm of the closed loop noise transfer function (NTF) at frequency f for gain g.
std::vector< realT > m_b
Vector of FIR coefficients.
realT Ti()
Get the loop sampling interval.
realT maxStableGain(realT &ll, realT &ul)
Find the maximum stable gain for the loop parameters.
realT m_tau
The loop delay.
void a(const Eigen::Array< realT, -1, -1 > &newA)
Set the vector of IIR coefficients.
int N()
Get the number of integrations in the (optional) moving average.
realT remember()
Get the remember factor.
const std::vector< realT > & b()
Get the vector of FIR coefficients.
realT clVariance(realT &varErr, realT &varNoise, const std::vector< realT > &PSDerr, const std::vector< realT > &PSDnoise, realT g)
Calculate the closed loop variance given open-loop PSDs and gain.
bool m_changed
True if any of the members which make up the basic transfer functions are changed.
realT m_minFindMaxFact
The maximum value, as a multiplicative factor of maximum gain.
size_t f_size()
Get the size of the frequency vector.
realT m_maxFindMin
The Minimum value for the maximum stable gain finding algorithm.
void remember(const realT &rem)
Set the remember factor for a leaky integrator.
complexT clETF(int fi, realT g)
Return the closed loop error transfer function (ETF) at frequency f for gain g.
clGainOpt()
Default c'tor.
complexT olXfer(int fi, complexT &H_dm, complexT &H_del, complexT &H_con)
Calculate the open-loop transfer function.
_realT realT
The real data type.
realT tau()
Get the loop delay.
void f(realT *newF, size_t nF)
Set the vector of frequencies.
std::complex< _realT > complexT
The complex data type.
uintmax_t m_minFindMaxIter
The maximum iterations allowed for minimization.
realT clETFPhase(int fi, realT g)
Return the closed loop error transfer function (ETF) phase at frequency f for gain g.
int m_N
Number of integrations in the (optional) moving average. Default is 1.
realT m_Ti
The loop sampling interval.
const std::vector< realT > & a()
Get the vector of IIR coefficients.
realT maxStableGain(const realT &ll, const realT &ul)
Find the maximum stable gain for the loop parameters.
void setLeakyIntegrator(realT remember)
Set the FIR and IIR coefficients so that the control law is a leaky integrator.
realT m_remember
The leaky integrator forget factor.
bool m_fChanged
True if frequency or max size of m_a and m_b changes.
realT m_minFindMin
The Minimum value for the minimum finding algorithm.
realT clETF2(int fi, realT g)
Return the norm of the closed loop error transfer function (ETF) at frequency f for gain g.
void clTF2(realT &ETF, realT &NTF, int fi, realT g)
Return the norm of the closed loop transfer functions at frequency f for gain g.
std::vector< realT > m_a
Vector of IIR coefficients.