CHROMA
seoprec_linop.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*! @file
3  * @brief Base class for symmetric even-odd preconditioned 4D and 5D Linop
4  */
5 
6 #ifndef __seoprec_linop_h__
7 #define __seoprec_linop_h__
8 
9 #include "chromabase.h"
10 #include "linearop.h"
11 
12 using namespace QDP::Hints;
13 
14 namespace Chroma
15 {
16 
17 //----------------------------------------------------------------
18 //! Even-odd preconditioned linear operator
19 /*! @ingroup linop
20  *
21  * Support for even-odd preconditioned linear operators
22  * Given a matrix M written in block form:
23  *
24  * [ A D ]
25  * [ E,E E,O ]
26  * [ ]
27  * [ D A ]
28  * [ O,E O,O ]
29  *
30  * The preconditioning consists of factorizing as
31  *
32  *
33  * M_unprec = M_diag x M'
34  *
35  *
36  * M_diag = [ A_E,E 0 ]
37  * [ 0 A_O,O ]
38  *
39  * [ 1 M_E,O ]
40  * M' = [ ]
41  * [ M_O,E 1 ]
42  *
43  *
44  * M_E,O = A^{-1}_E,E D_E,O
45  * M_O,E = A^{-1}_O,O D_E,O
46  *
47  * We then do a schur precondition of M'
48  *
49  * as M' = L M R
50  *
51  *
52  * L = [ 1 0 ]
53  * [ ]
54  * [ M_O,E 1 ]
55  *
56  *
57  *
58  * R = [ 1 M_E,O ]
59  * [ ]
60  * [ 0 1 ]
61  *
62  *
63  * M = [ 1 0 ]
64  * [ ]
65  * [ 0 S ]
66  *
67  * where S = 1 - ( M_O,E )( M_E,O )
68  *
69  *
70  * L^{-1} = [ 1 0 ]
71  * [ ]
72  * [- M_O,E 1 ]
73  *
74  *
75  *
76  * R^{-1} = [ 1 - M_E,O ]
77  * [ ]
78  * [ 0 1 ]
79  *
80  *
81  *
82  * For props we need to solve:
83  *
84  * M x' = L^{-1} (M_diag)^{-1} b
85  *
86  * and then x = R^{-1} x' (backsubstitution)
87  *
88  * for HMC we have det(L)=1 det(R)=1
89  * det(M_diag) is handled by TraceLog/LogDet calls to clover
90  * and we pseudofermionize only the 'S' operators
91  *
92  *
93  * Structure: capture D_oe, D_eo, A_ee, A_oo, A^{-1}_oo and A^{-1}_ee
94  * as
95  * unprecEvenOddLinOp
96  * unprecOddEvenLinOp
97  * unprecEvenEvenLinOp
98  * unprecOddOddLinOp
99  * unprecOddOddInvLinOp
100  * unprecEvenEvenInvLinOp
101  *
102  * then we can write category defaults for:
103  *
104  * then
105  * evenOddLinOp is M_eo = A^{-1}_ee D_eo or h.c.
106  * oddEvenLinOp is M_oe = A^{-1}_oo D_oe or h.c.
107  *
108  * the so called Jacobi Operator:
109  * [ 1 M_eo ]
110  * [ M_oe 1 ]
111  *
112  * the Schur Operator: S = 1 - M_oe M_eo
113  *
114  * the Unprec Operator: diag( A_ee A_oo ) M_jacobi
115  *
116  * We can also write category default for the forces in terms
117  * of
118  * derivEvenOddLinOp
119  * and derivOddEvenLinOp
120  *
121  * Const-detness or log-det ness will depend on how the
122  * derivEvenOdd and derivOddEven operators are coded
123  *
124  * ConstDet will treat A as a constant (muliplicative factor)
125  * LogDet will evaluate chain rule in derivEvenOddLinOp
126  * and also provide lodDet terms and TraceLog forces
127  *
128  */
129 
130 template<typename T, typename P, typename Q>
132 {
133 public:
134  //! Virtual destructor to help with cleanup;
136 
137  //! Only defined on the odd lattice
138  const Subset& subset() const {return rb[1];}
139 
140  //! Return the fermion BC object for this linear operator
141  virtual const FermBC<T,P,Q>& getFermBC() const = 0;
142 
143  //! Apply the even-even block onto a source std::vector
144  /*! This does not need to be optimized */
145  virtual void unprecEvenEvenLinOp(T& chi, const T& psi,
146  enum PlusMinus isign) const = 0;
147 
148  //! Apply the inverse of the even-even block onto a source std::vector
149  virtual void unprecEvenEvenInvLinOp(T& chi, const T& psi,
150  enum PlusMinus isign) const = 0;
151 
152  //! Apply the the odd-odd block onto a source std::vector
153  virtual void unprecOddOddLinOp(T& chi, const T& psi,
154  enum PlusMinus isign) const = 0;
155 
156  //! Apply the inverse of the odd-odd block onto a source std::vector
157  virtual void unprecOddOddInvLinOp(T& chi, const T& psi,
158  enum PlusMinus isign) const = 0;
159 
160  //! Apply the the even-odd block onto a source std::vector
161  virtual void unprecEvenOddLinOp(T& chi, const T& psi,
162  enum PlusMinus isign) const = 0;
163 
164  //! Apply the the odd-even block onto a source std::vector
165  virtual void unprecOddEvenLinOp(T& chi, const T& psi,
166  enum PlusMinus isign) const = 0;
167 
168 
169  //! Apply the EvenOdd Linop for which we have a category default)
170  virtual void evenOddLinOp(T& chi, const T& psi,
171  enum PlusMinus isign) const {
172 
173  T tmp; moveToFastMemoryHint(tmp);
174 
175  if( isign == PLUS ) {
176  unprecEvenOddLinOp(tmp, psi, PLUS);
177  unprecEvenEvenInvLinOp(chi,tmp,PLUS);
178  }
179  else {
180  unprecOddOddInvLinOp(tmp, psi, MINUS);
181  unprecEvenOddLinOp(chi, tmp, MINUS);
182  }
183 
184  // Do I want to apply BC's here?
185  //getFermBC().modifyF(chi);
186  }
187 
188  virtual void oddEvenLinOp(T& chi, const T& psi,
189  enum PlusMinus isign) const {
190 
191  T tmp; moveToFastMemoryHint(tmp);
192 
193  if( isign == PLUS ) {
194  unprecOddEvenLinOp(tmp, psi, PLUS);
195  unprecOddOddInvLinOp(chi,tmp,PLUS);
196  }
197  else {
198  unprecEvenEvenInvLinOp(tmp, psi, MINUS);
199  unprecOddEvenLinOp(chi, tmp, MINUS);
200  }
201 
202  // Do I want to apply BCs here?
203  //getFermBC().modifyF(chi);
204  }
205 
206 
207  //! Apply the operator onto a source std::vector
208  virtual void operator() (T& chi, const T& psi,
209  enum PlusMinus isign) const
210  {
211  T tmp1; moveToFastMemoryHint(tmp1);
212  T tmp2; moveToFastMemoryHint(tmp2);
213 
214  /* t1 = M_eo psi */
215  evenOddLinOp(tmp1,psi,isign);
216 
217  /* t2 = M_oe t1 */
218  oddEvenLinOp(tmp2,tmp1,isign);
219 
220  /* chi = psi - M_oe M_eo psi = (1 - M_oe M_eo) psi */
221  /* NB: the construction takes care of daggering
222  * as the M_eo^\dagger will reverse operator order etc */
223  chi[rb[1]] = psi - tmp2;
224  getFermBC().modifyF(chi);
225  }
226 
227  //! Apply the Jacobi Operator
228  virtual void jacobiOp(T& chi, const T& psi,
229  enum PlusMinus isign) const
230  {
231  T tmp; moveToFastMemoryHint(tmp);
232 
233  // [ 1 A^{-1}_ee D_eo ]
234  // [ ]
235  // [ A^{-1}_oo D_oe 1 ]
236  //
237  // Or hermitian conjugate
238  chi = psi;
239  evenOddLinOp(tmp, psi, isign);
240  chi[ rb[0]] += tmp;
241  oddEvenLinOp(tmp, psi, isign);
242  chi[ rb[1]] += tmp;
243 
244  getFermBC().modifyF(chi);
245  }
246 
247  //! Apply the UNPRECONDITIONED operator onto a source std::vector
248  /*! Mainly intended for debugging */
249  virtual void unprecLinOp(T& chi, const T& psi,
250  enum PlusMinus isign) const
251  {
252  T tmp1; moveToFastMemoryHint(tmp1);
253  QDPIO::cout << "M_Unprec : " << std::endl;
254  if ( isign == PLUS ) {
255  // Apply Jacobi Operator and scale for M_unprec:
256  //
257  // [ A_ee 0 ] [ 1 A^{-1}_ee D_eo ]
258  // [ ] [ ]
259  // [ 0 A_oo ] [ A^{-1}_oo D_oe 1 ]
260  //
261  jacobiOp(tmp1, psi, isign);
262 
263  unprecEvenEvenLinOp(chi,tmp1,isign);
264  unprecOddOddLinOp(chi,tmp1, isign);
265  }
266  else {
267  // For Hermitian conjugate scale first then apply Jacobi operator
268  //
269  // [ 1 (D^\dag)_eo A^{-dag}_oo ] [ A^dag_ee 0 ]
270  // [ ] [ ]
271  // [ (D^\dag)_oe A^{-dag}_ee 1 ] [ 0 A^dag_oo ]
272  unprecEvenEvenLinOp(tmp1,psi,isign);
273  unprecOddOddLinOp(tmp1,psi,isign);
274  jacobiOp(chi,tmp1,isign);
275 
276  }
277  getFermBC().modifyF(chi);
278  }
279 
280 
281  //! Compute force coming from EvenOdd (A^{-1}_ee D_eo) term
282  virtual void derivEvenOddLinOp(P& ds_u, const T& chi, const T& psi,
283  enum PlusMinus isign) const = 0;
284 
285  //! Compute force coming from OddEven (A^{-1}_oo D_oe ) term
286  virtual void derivOddEvenLinOp(P& ds_u, const T& chi, const T& psi,
287  enum PlusMinus isign) const = 0;
288 
289 
290 
291  //! Deriv
292  virtual void deriv(P& ds_u, const T& chi, const T& psi,
293  enum PlusMinus isign) const
294  {
295  T M_eo_psi; moveToFastMemoryHint(M_eo_psi);
296  T M_oe_dag_chi; moveToFastMemoryHint(M_oe_dag_chi);
297 
298  enum PlusMinus msign = ( isign == PLUS ) ? MINUS : PLUS;
299 
300  evenOddLinOp( M_eo_psi, psi, isign);
301  evenOddLinOp( M_oe_dag_chi, chi, msign);
302 
303  ds_u.resize(Nd);
304  ds_u = zero;
305  P ds_tmp;
306  derivOddEvenLinOp(ds_tmp,chi,M_eo_psi,isign);
307  ds_u -= ds_tmp;
308 
309  derivEvenOddLinOp(ds_tmp, M_oe_dag_chi,psi,isign);
310  ds_u -= ds_tmp;
311 
312  getFermBC().zero(ds_u);
313  }
314 
315  //! Apply the derivative of the operator onto a source std::vector
316  /*! User should make sure deriv routines do a resize */
317  virtual void derivMultipole(P& ds_u, const multi1d<T>& chi, const multi1d<T>& psi,
318  enum PlusMinus isign) const
319  {
320  T M_eo_psi; moveToFastMemoryHint(M_eo_psi);
321  T M_oe_dag_chi; moveToFastMemoryHint(M_oe_dag_chi);
322 
323  enum PlusMinus msign = ( isign == PLUS ) ? MINUS : PLUS;
324 
325 
326  ds_u.resize(Nd);
327  ds_u = zero;
328  P ds_tmp;
329  for(int i=0; i < chi.size(); ++i) {
330  evenOddLinOp( M_eo_psi, psi[i], isign);
331  evenOddLinOp( M_oe_dag_chi, chi[i], msign);
332 
333  derivOddEvenLinOp(ds_tmp,chi[i],M_eo_psi,isign);
334  ds_u -= ds_tmp;
335  derivEvenOddLinOp(ds_tmp, M_oe_dag_chi,psi[i],isign);
336  ds_u -= ds_tmp;
337  }
338  getFermBC().zero(ds_u);
339 
340  }
341 
342 };
343 
344 
345 } // End namespace Chroma
346 
347 #endif
Primary include file for CHROMA library code.
Differentiable Linear Operator.
Definition: linearop.h:98
Base class for all fermion action boundary conditions.
Definition: fermbc.h:20
Even-odd preconditioned linear operator.
virtual void unprecOddOddInvLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the inverse of the odd-odd block onto a source std::vector.
virtual void evenOddLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the EvenOdd Linop for which we have a category default)
virtual void derivOddEvenLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const =0
Compute force coming from OddEven (A^{-1}_oo D_oe ) term.
virtual void derivMultipole(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const
Apply the derivative of the operator onto a source std::vector.
virtual void unprecEvenEvenInvLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the inverse of the even-even block onto a source std::vector.
virtual void jacobiOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the Jacobi Operator.
virtual void derivEvenOddLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const =0
Compute force coming from EvenOdd (A^{-1}_ee D_eo) term.
virtual void oddEvenLinOp(T &chi, const T &psi, enum PlusMinus isign) const
virtual void unprecOddEvenLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the the odd-even block onto a source std::vector.
virtual const FermBC< T, P, Q > & getFermBC() const =0
Return the fermion BC object for this linear operator.
virtual void deriv(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Deriv.
virtual void unprecLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the UNPRECONDITIONED operator onto a source std::vector.
virtual ~SymEvenOddPrecLinearOperator()
Virtual destructor to help with cleanup;.
virtual void unprecEvenOddLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the the even-odd block onto a source std::vector.
virtual void unprecEvenEvenLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the even-even block onto a source std::vector.
const Subset & subset() const
Only defined on the odd lattice.
virtual void unprecOddOddLinOp(T &chi, const T &psi, enum PlusMinus isign) const =0
Apply the the odd-odd block onto a source std::vector.
unsigned i
Definition: ldumul_w.cc:34
Linear Operators.
Double tmp
Definition: meslate.cc:60
Nd
Definition: meslate.cc:74
Double tmp2
Definition: mesq.cc:30
multi1d< Hadron2PtContraction_t > operator()(const multi1d< LatticeColorMatrix > &u)
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
LinOpSysSolverMGProtoClover::T T
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
Double zero
Definition: invbicg.cc:106
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
multi1d< LatticeColorMatrix > P
Definition: t_clover.cc:13