JUK1
ForceCausal.hpp
Go to the documentation of this file.
1 #ifndef _FORCECAUSAL_HPP_INC_
2 #define _FORCECAUSAL_HPP_INC_
3 #include "Maths/dft.hpp"
4 
5 namespace ForceCausal {
6 
7 // TODO: Maybe this could be made more efficient by worrying about vectorisation
8 // of the calculations. I.E storing precomputed F values etc
9 
10 template<typename T>
11 std::complex<T>
12 F(const std::vector<T> & freq, const std::vector<std::complex<T> > & data, T tau,
13  T k, size_t n) {
14  return (data[n] - k) *
15  exp(std::complex<T>(0, -2 * std::numbers::pi * freq[n] * tau));
16 }
17 
18 template<typename T>
19 T
20 K(const std::vector<T> & freq, const std::vector<std::complex<T> > & data, T tau) {
21  return std::real(data.back()) -
22  std::imag(data.back()) /
23  std::tan(2 * std::numbers::pi * freq.back() * tau);
24 }
25 
26 template<typename T>
27 T
28 f0(const std::vector<T> & freq, const std::vector<std::complex<T> > & data, T tau) {
29  std::complex<T> toRet = 0;
30  T k = K(freq, data, tau);
31  for (size_t i = 1; i < freq.size() - 1; i++) {
32  toRet += 2 * (std::real(F(freq, data, tau, k, i)));
33  }
34  toRet += F(freq, data, tau, k, 0);
35  toRet += std::real(F(freq, data, tau, k, freq.size() - 1));
36  toRet *= 1e3 / (2 * freq.size() - 2);
37  return std::real(toRet);
38 }
39 
40 template<typename T>
41 T
42 f0derivative(const std::vector<T> & freq, const std::vector<std::complex<T> > & data,
43  T tau, T step) {
44  return (f0(freq, data, tau + step) - f0(freq, data, tau)) / step;
45 }
46 
47 
48 template<typename T>
49 T
50 getTau(const std::vector<T> & freq, const std::vector<std::complex<T> > & data,
51  T tol = 1e-7, size_t maxIter = 30, T step = 1e-8) {
52  T currentGuess = 1e-8;
53  for (size_t i = 0; i < maxIter; i++) {
54  T f0Curr = f0(freq, data, currentGuess);
55  if (f0Curr * f0Curr < tol) {
56  break;
57  }
58  T diff = (f0(freq, data, currentGuess + step) - f0Curr) / step;
59  currentGuess = currentGuess - f0Curr / diff;
60  }
61  return currentGuess;
62 }
63 
67 template<typename T>
68 struct CausalData {
69  T tau;
70  T Ts;
71  std::vector<T> data;
72 };
73 
74 } // namespace ForceCausal
75 
76 template<typename T>
78 forceCausal(const std::vector<T> & freq,
79  const std::vector<std::complex<T> > & data) {
81  toRet.data = std::vector<T>(2 * freq.size() - 2);
82  toRet.Ts = 1.0 / (toRet.data.size() * (freq[1] - freq[0]));
83  // Add in conjugate Symmetric Data
84  std::vector<std::complex<T> > hermitianData(2 * freq.size() - 2);
85  T k = 0;
86 
87  if (abs(std::imag(data.back())) < 1e-5) {
88  toRet.tau = 0;
89 
90  for (size_t i = 0; i < freq.size() - 1; i++) {
91  hermitianData[i] = data[i];
92  }
93 
94  for (size_t i = 1; i < freq.size(); i++) {
95  hermitianData[hermitianData.size() - i] = std::conj(data[i]);
96  }
97 
98  } else {
99  toRet.tau = ForceCausal::getTau(freq, data);
100  k = ForceCausal::K(freq, data, toRet.tau);
101 
102  for (size_t i = 0; i < freq.size() - 1; i++) {
103  hermitianData[i] = ForceCausal::F(freq, data, toRet.tau, k, i);
104  }
105 
106  for (size_t i = 1; i < freq.size(); i++) {
107  hermitianData[hermitianData.size() - i] = std::conj(
108  ForceCausal::F(freq, data, toRet.tau, k, i));
109  }
110  }
111 
112  auto idftVal = idft(hermitianData);
113  for (size_t i = 0; i < idftVal.size(); i++) {
114  toRet.data[i] = std::real(idftVal[i]);
115  }
116 
117  if (abs(std::imag(data.back())) >= 1e-5) {
118  toRet.data[0] = k;
119  }
120  return toRet;
121 }
122 
123 
124 #endif
ForceCausal::CausalData< T > forceCausal(const std::vector< T > &freq, const std::vector< std::complex< T > > &data)
Definition: ForceCausal.hpp:78
pi
Definition: Freq.m:24
step
Definition: Freq.m:3
PURPOSE j at all freq
Definition: QPpassive.m:44
std::vector< std::complex< T > > idft(const std::vector< std::complex< T > > &inputData)
Definition: dft.hpp:37
for i
hermitianData
for k
Definition: interch.m:15
end if abs(real(dotprod))>rstoerst rstoerst
std::complex< T > F(const std::vector< T > &freq, const std::vector< std::complex< T > > &data, T tau, T k, size_t n)
Definition: ForceCausal.hpp:12
T K(const std::vector< T > &freq, const std::vector< std::complex< T > > &data, T tau)
Definition: ForceCausal.hpp:20
T getTau(const std::vector< T > &freq, const std::vector< std::complex< T > > &data, T tol=1e-7, size_t maxIter=30, T step=1e-8)
Definition: ForceCausal.hpp:50
T f0derivative(const std::vector< T > &freq, const std::vector< std::complex< T > > &data, T tau, T step)
Definition: ForceCausal.hpp:42
T f0(const std::vector< T > &freq, const std::vector< std::complex< T > > &data, T tau)
Definition: ForceCausal.hpp:28
a helper struct to return the result of the forced causal IDFT
Definition: ForceCausal.hpp:68
std::vector< T > data
Definition: ForceCausal.hpp:71