NESSi  v1.0.2
The NonEquilibrium Systems Simulation Library
cntr_response_convolution_impl.hpp
Go to the documentation of this file.
1 #ifndef CNTR_RESPONSE_CONVOLUTION_IMPL_H
2 #define CNTR_RESPONSE_CONVOLUTION_IMPL_H
3 
5 
6 namespace cntr {
7 
8 /*////////////////////////////////////////////////////////////////
9 
10  computing the response to a retarded response function
11 
12  c(t) = \int_C dt' W(t,t') f(t')
13 
14  NOTES:
15  - assumes that W is hermitian
16  - uses points 0...kt if t<kt (thus a version using W only as timestep
17  works only for t>=kt and t==-1
18 
20 
21 #define CPLX std::complex<T>
22 
23 // res = int_0^n dt f(t), f(i*dt)=f[sf*i+idxf], i=0..,n
25 template <typename T>
26 void response_integrate(int n, T dt, CPLX &res, CPLX *f, int sf, int idxf,
27  integration::Integrator<T> &I) {
28  int kt = I.k(), i, k2 = 2 * (kt + 1);
29  res = 0;
30  if (n >= k2) {
31  for (i = 0; i <= kt; i++)
32  res += f[i * sf + idxf] * I.gregory_weights(n, i);
33  for (i = kt + 1; i < n - kt; i++)
34  res += f[i * sf + idxf];
35  for (i = n - kt; i <= n; i++)
36  res += f[i * sf + idxf] * I.gregory_weights(n, i);
37  } else if (n > 0) {
38  int n1 = (n <= kt ? kt : n);
39  for (i = 0; i <= n1; i++)
40  res += f[i * sf + idxf] * I.gregory_weights(n, i);
41  }
42  res *= dt;
43 }
44 // res = int_0^n dt f(t)g(t), f(i*dt)=f[sf*i+idxf], g(i*dt)=g[sg*i+idxg], i=0..,n
46 template <typename T>
47 void response_integrate(int n, T dt, CPLX &res, CPLX *f, int sf, int idxf, CPLX *g, int sg,
48  int idxg, integration::Integrator<T> &I) {
49  int kt = I.k(), i, k2 = 2 * (kt + 1);
50  res = 0;
51  if (n >= k2) {
52  for (i = 0; i <= kt; i++)
53  res += f[i * sf + idxf] * g[i * sg + idxg] * I.gregory_weights(n, i);
54  for (i = kt + 1; i < n - kt; i++)
55  res += f[i * sf + idxf] * g[i * sg + idxg];
56  for (i = n - kt; i <= n; i++)
57  res += f[i * sf + idxf] * g[i * sg + idxg] * I.gregory_weights(n, i);
58  } else if (n > 0) {
59  int n1 = (n <= kt ? kt : n);
60  for (i = 0; i <= n1; i++)
61  res += f[i * sf + idxf] * g[i * sg + idxg] * I.gregory_weights(n, i);
62  }
63  res *= dt;
64 }
65 
66 // USING THE ASSUMPTION THAT W IS HERMITIAN
67 template <typename T>
68 void response_convolution(int tstp, CPLX &cc, GREEN_TSTP &W, int a1, int a2, function<T> &f,
69  int b1, int b2, int SolveOrder, T beta, T h) {
70  int ntau = W.ntau();
71  T dtau = beta / ntau;
72  int sizew = W.size1(), idxw = a1 * sizew + a2, sw = sizew * sizew;
73  int sizef = f.size1(), idxf = b1 * sizef + b2, sf = sizef * sizef;
74  CPLX res;
75 
76  assert(W.tstp() >= tstp);
77  assert(tstp == -1 || tstp >= SolveOrder);
78  assert(SolveOrder <= ntau);
79  assert(b1 >= 0 && b1 <= sizef-1);
80  assert(b2 >= 0 && b2 <= sizef-1);
81  assert(a1 >= 0 && a1 <= sizew-1);
82  assert(a2 >= 0 && a2 <= sizew-1);
83 
84  if (tstp == -1) {
85  response_integrate<T>(ntau, dtau, res, W.matptr(0), sw, idxw, integration::I<T>(SolveOrder));
86  cc = res * f.ptr(-1)[idxf];
87  } else {
88  response_integrate<T>(ntau, dtau, res, W.tvptr(0), sw, idxw, integration::I<T>(SolveOrder));
89  cc = res * (CPLX(0, -1.0) * f.ptr(-1)[idxf]);
90  response_integrate<T>(tstp, h, res, W.retptr(0), sw, idxw, f.ptr(0), sf, idxf,
91  integration::I<T>(SolveOrder));
92  cc += res;
93  }
94 }
95 template <typename T>
96 void response_convolution(int tstp, CPLX &cc, GREEN &W, int a1, int a2, function<T> &f,
97  int b1, int b2, int SolveOrder, T beta, T h) {
98  int ntau = W.ntau();
99  T dtau = beta / ntau;
100  int sizew = W.size1(), idxw = a1 * sizew + a2, sw = sizew * sizew;
101  int sizef = f.size1(), idxf = b1 * sizef + b2, sf = sizef * sizef;
102  int n1 = (tstp == -1 || tstp >= SolveOrder ? SolveOrder : SolveOrder);
103  CPLX res;
104 
105  assert(W.nt() >= tstp);
106  assert(tstp == -1 || tstp >= SolveOrder);
107  assert(SolveOrder <= ntau);
108  assert(b1 >= 0 && b1 <= sizef-1);
109  assert(b2 >= 0 && b2 <= sizef-1);
110  assert(a1 >= 0 && a1 <= sizew-1);
111  assert(a2 >= 0 && a2 <= sizew-1);
112 
113  if (tstp == -1) {
114  response_integrate<T>(ntau, dtau, res, W.matptr(0), sw, idxw, integration::I<T>(SolveOrder));
115  cc = res * f.ptr(-1)[idxf];
116  } else if (tstp >= SolveOrder) {
117  response_integrate<T>(ntau, dtau, res, W.tvptr(tstp, 0), sw, idxw,
118  integration::I<T>(SolveOrder));
119  cc = res * (CPLX(0, -1.0) * f.ptr(-1)[idxf]);
120  response_integrate<T>(tstp, h, res, W.retptr(tstp, 0), sw, idxw, f.ptr(0), sf, idxf,
121  integration::I<T>(SolveOrder));
122  cc += res;
123  } else {
124  response_integrate<T>(ntau, dtau, res, W.tvptr(tstp, 0), sw, idxw,
125  integration::I<T>(SolveOrder));
126  cc = res * (CPLX(0, -1.0) * f.ptr(-1)[idxf]);
127  // need to extrapolate W(t,t') for t'>t
128  // ** USING THE ASSUMPTION THAT W IS HERMITIAN**
129  // i.e., Wret(t,t') = -Wret(t',t)^*
130  CPLX *wtmp = new CPLX[SolveOrder + 1];
131  for (int i = 0; i <= tstp; i++)
132  wtmp[i] = W.retptr(tstp, i)[a1 * sizew + a2];
133  for (int i = tstp + 1; i <= SolveOrder; i++)
134  wtmp[i] = -conj(W.retptr(i, tstp)[a2 * sizew + a1]);
135  response_integrate<T>(tstp, h, res, wtmp, 1, 0, f.ptr(0), sf, idxf,
136  integration::I<T>(SolveOrder));
137  cc += res;
138  delete[] wtmp;
139  }
140 }
141 
142 #undef GREEN
143 #undef GREEN_TSTP
144 #undef CPLX
145 
146 } // namespace cntr
147 
148 #endif // CNTR_RESPONSE_CONVOLUTION_IMPL_H