2016-01-02 14:51:32 +00:00
|
|
|
/*************************************************************************************
|
|
|
|
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
|
|
|
|
Source file: ./lib/algorithms/LinearOperator.h
|
|
|
|
|
|
|
|
Copyright (C) 2015
|
|
|
|
|
|
|
|
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
|
|
|
|
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
|
|
|
See the full license in the file "LICENSE" in the top level distribution directory
|
|
|
|
*************************************************************************************/
|
|
|
|
/* END LEGAL */
|
2015-05-13 11:25:34 +01:00
|
|
|
#ifndef GRID_ALGORITHM_LINEAR_OP_H
|
|
|
|
#define GRID_ALGORITHM_LINEAR_OP_H
|
|
|
|
|
|
|
|
namespace Grid {
|
|
|
|
|
2015-05-16 23:35:08 +01:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// LinearOperators Take a something and return a something.
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2015-05-19 13:57:35 +01:00
|
|
|
// Hopefully linearity is satisfied and the AdjOp is indeed the Hermitian conjugateugate (transpose if real):
|
|
|
|
//SBase
|
2015-05-16 23:35:08 +01:00
|
|
|
// i) F(a x + b y) = aF(x) + b F(y).
|
|
|
|
// ii) <x|Op|y> = <y|AdjOp|x>^\ast
|
|
|
|
//
|
|
|
|
// Would be fun to have a test linearity & Herm Conj function!
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class Field> class LinearOperatorBase {
|
2015-05-13 11:25:34 +01:00
|
|
|
public:
|
2015-06-08 12:02:53 +01:00
|
|
|
|
|
|
|
// Support for coarsening to a multigrid
|
|
|
|
virtual void OpDiag (const Field &in, Field &out) = 0; // Abstract base
|
|
|
|
virtual void OpDir (const Field &in, Field &out,int dir,int disp) = 0; // Abstract base
|
|
|
|
|
2015-05-16 23:35:08 +01:00
|
|
|
virtual void Op (const Field &in, Field &out) = 0; // Abstract base
|
|
|
|
virtual void AdjOp (const Field &in, Field &out) = 0; // Abstract base
|
2015-06-05 18:16:25 +01:00
|
|
|
virtual void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2)=0;
|
|
|
|
virtual void HermOp(const Field &in, Field &out)=0;
|
2015-05-13 11:25:34 +01:00
|
|
|
};
|
|
|
|
|
2015-05-16 23:35:08 +01:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// By sharing the class for Sparse Matrix across multiple operator wrappers, we can share code
|
|
|
|
// between RB and non-RB variants. Sparse matrix is like the fermion action def, and then
|
|
|
|
// the wrappers implement the specialisation of "Op" and "AdjOp" to the cases minimising
|
|
|
|
// replication of code.
|
2015-06-05 10:17:10 +01:00
|
|
|
//
|
|
|
|
// I'm not entirely happy with implementation; to share the Schur code between herm and non-herm
|
|
|
|
// while still having a "OpAndNorm" in the abstract base I had to implement it in both cases
|
|
|
|
// with an assert trap in the non-herm. This isn't right; there must be a better C++ way to
|
|
|
|
// do it, but I fear it required multiple inheritance and mixed in abstract base classes
|
2015-05-16 23:35:08 +01:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
2015-06-05 10:17:10 +01:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Construct herm op from non-herm matrix
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2015-05-18 07:47:05 +01:00
|
|
|
template<class Matrix,class Field>
|
2015-06-05 10:17:10 +01:00
|
|
|
class MdagMLinearOperator : public LinearOperatorBase<Field> {
|
2015-05-18 07:47:05 +01:00
|
|
|
Matrix &_Mat;
|
2015-05-16 23:35:08 +01:00
|
|
|
public:
|
2015-06-05 10:17:10 +01:00
|
|
|
MdagMLinearOperator(Matrix &Mat): _Mat(Mat){};
|
2015-06-08 12:02:53 +01:00
|
|
|
|
|
|
|
// Support for coarsening to a multigrid
|
|
|
|
void OpDiag (const Field &in, Field &out) {
|
|
|
|
_Mat.Mdiag(in,out);
|
|
|
|
}
|
|
|
|
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
|
|
|
_Mat.Mdir(in,out,dir,disp);
|
|
|
|
}
|
2015-05-16 23:35:08 +01:00
|
|
|
void Op (const Field &in, Field &out){
|
|
|
|
_Mat.M(in,out);
|
|
|
|
}
|
|
|
|
void AdjOp (const Field &in, Field &out){
|
|
|
|
_Mat.Mdag(in,out);
|
|
|
|
}
|
2015-06-05 18:16:25 +01:00
|
|
|
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
2015-06-05 10:17:10 +01:00
|
|
|
_Mat.MdagM(in,out,n1,n2);
|
|
|
|
}
|
2015-06-05 18:16:25 +01:00
|
|
|
void HermOp(const Field &in, Field &out){
|
|
|
|
RealD n1,n2;
|
2015-07-21 05:54:09 +01:00
|
|
|
HermOpAndNorm(in,out,n1,n2);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Construct herm op and shift it for mgrid smoother
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
template<class Matrix,class Field>
|
|
|
|
class ShiftedMdagMLinearOperator : public LinearOperatorBase<Field> {
|
|
|
|
Matrix &_Mat;
|
|
|
|
RealD _shift;
|
|
|
|
public:
|
|
|
|
ShiftedMdagMLinearOperator(Matrix &Mat,RealD shift): _Mat(Mat), _shift(shift){};
|
|
|
|
// Support for coarsening to a multigrid
|
|
|
|
void OpDiag (const Field &in, Field &out) {
|
|
|
|
_Mat.Mdiag(in,out);
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
|
|
|
_Mat.Mdir(in,out,dir,disp);
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
void Op (const Field &in, Field &out){
|
|
|
|
_Mat.M(in,out);
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
void AdjOp (const Field &in, Field &out){
|
|
|
|
_Mat.Mdag(in,out);
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
|
|
|
_Mat.MdagM(in,out,n1,n2);
|
|
|
|
out = out + _shift*in;
|
|
|
|
|
|
|
|
ComplexD dot;
|
|
|
|
dot= innerProduct(in,out);
|
|
|
|
n1=real(dot);
|
|
|
|
n2=norm2(out);
|
|
|
|
}
|
|
|
|
void HermOp(const Field &in, Field &out){
|
|
|
|
RealD n1,n2;
|
2015-06-05 18:16:25 +01:00
|
|
|
HermOpAndNorm(in,out,n1,n2);
|
|
|
|
}
|
2015-05-16 23:35:08 +01:00
|
|
|
};
|
2015-06-05 10:17:10 +01:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Wrap an already herm matrix
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2015-05-18 07:47:05 +01:00
|
|
|
template<class Matrix,class Field>
|
2015-06-05 10:17:10 +01:00
|
|
|
class HermitianLinearOperator : public LinearOperatorBase<Field> {
|
2015-05-18 07:47:05 +01:00
|
|
|
Matrix &_Mat;
|
2015-05-16 23:35:08 +01:00
|
|
|
public:
|
2015-06-05 10:17:10 +01:00
|
|
|
HermitianLinearOperator(Matrix &Mat): _Mat(Mat){};
|
2015-06-08 12:02:53 +01:00
|
|
|
// Support for coarsening to a multigrid
|
|
|
|
void OpDiag (const Field &in, Field &out) {
|
|
|
|
_Mat.Mdiag(in,out);
|
|
|
|
}
|
|
|
|
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
|
|
|
_Mat.Mdir(in,out,dir,disp);
|
|
|
|
}
|
2015-05-16 23:35:08 +01:00
|
|
|
void Op (const Field &in, Field &out){
|
2015-06-05 10:17:10 +01:00
|
|
|
_Mat.M(in,out);
|
2015-05-16 23:35:08 +01:00
|
|
|
}
|
2015-06-05 10:17:10 +01:00
|
|
|
void AdjOp (const Field &in, Field &out){
|
|
|
|
_Mat.M(in,out);
|
|
|
|
}
|
2015-06-05 18:16:25 +01:00
|
|
|
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
2015-06-05 10:17:10 +01:00
|
|
|
ComplexD dot;
|
|
|
|
|
|
|
|
_Mat.M(in,out);
|
|
|
|
|
|
|
|
dot= innerProduct(in,out);
|
|
|
|
n1=real(dot);
|
|
|
|
|
|
|
|
dot = innerProduct(out,out);
|
|
|
|
n2=real(dot);
|
2015-05-16 23:35:08 +01:00
|
|
|
}
|
2015-06-05 18:16:25 +01:00
|
|
|
void HermOp(const Field &in, Field &out){
|
|
|
|
_Mat.M(in,out);
|
|
|
|
}
|
2015-05-16 23:35:08 +01:00
|
|
|
};
|
|
|
|
|
2015-06-05 10:17:10 +01:00
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
// Even Odd Schur decomp operators; there are several
|
|
|
|
// ways to introduce the even odd checkerboarding
|
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
template<class Field>
|
|
|
|
class SchurOperatorBase : public LinearOperatorBase<Field> {
|
|
|
|
public:
|
|
|
|
virtual RealD Mpc (const Field &in, Field &out) =0;
|
|
|
|
virtual RealD MpcDag (const Field &in, Field &out) =0;
|
|
|
|
virtual void MpcDagMpc(const Field &in, Field &out,RealD &ni,RealD &no) {
|
|
|
|
Field tmp(in._grid);
|
|
|
|
ni=Mpc(in,tmp);
|
|
|
|
no=MpcDag(tmp,out);
|
|
|
|
}
|
|
|
|
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2){
|
|
|
|
MpcDagMpc(in,out,n1,n2);
|
|
|
|
}
|
2015-06-05 18:16:25 +01:00
|
|
|
void HermOp(const Field &in, Field &out){
|
|
|
|
RealD n1,n2;
|
|
|
|
HermOpAndNorm(in,out,n1,n2);
|
|
|
|
}
|
2015-06-05 10:17:10 +01:00
|
|
|
void Op (const Field &in, Field &out){
|
|
|
|
Mpc(in,out);
|
|
|
|
}
|
|
|
|
void AdjOp (const Field &in, Field &out){
|
|
|
|
MpcDag(in,out);
|
|
|
|
}
|
2015-06-08 12:02:53 +01:00
|
|
|
// Support for coarsening to a multigrid
|
|
|
|
void OpDiag (const Field &in, Field &out) {
|
|
|
|
assert(0); // must coarsen the unpreconditioned system
|
|
|
|
}
|
|
|
|
void OpDir (const Field &in, Field &out,int dir,int disp) {
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
2015-06-05 10:17:10 +01:00
|
|
|
};
|
2015-05-18 07:47:05 +01:00
|
|
|
template<class Matrix,class Field>
|
2015-06-05 10:17:10 +01:00
|
|
|
class SchurDiagMooeeOperator : public SchurOperatorBase<Field> {
|
2015-08-07 08:37:15 +01:00
|
|
|
protected:
|
2015-05-18 07:47:05 +01:00
|
|
|
Matrix &_Mat;
|
2015-05-16 23:35:08 +01:00
|
|
|
public:
|
2015-06-05 10:17:10 +01:00
|
|
|
SchurDiagMooeeOperator (Matrix &Mat): _Mat(Mat){};
|
|
|
|
virtual RealD Mpc (const Field &in, Field &out) {
|
|
|
|
Field tmp(in._grid);
|
2016-02-20 07:50:32 +00:00
|
|
|
// std::cout <<"grid pointers: in._grid="<< in._grid << " out._grid=" << out._grid << " _Mat.Grid=" << _Mat.Grid() << " _Mat.RedBlackGrid=" << _Mat.RedBlackGrid() << std::endl;
|
2015-06-05 10:17:10 +01:00
|
|
|
|
|
|
|
_Mat.Meooe(in,tmp);
|
|
|
|
_Mat.MooeeInv(tmp,out);
|
|
|
|
_Mat.Meooe(out,tmp);
|
|
|
|
|
|
|
|
_Mat.Mooee(in,out);
|
|
|
|
return axpy_norm(out,-1.0,tmp,out);
|
2015-05-16 23:35:08 +01:00
|
|
|
}
|
2015-06-05 10:17:10 +01:00
|
|
|
virtual RealD MpcDag (const Field &in, Field &out){
|
|
|
|
Field tmp(in._grid);
|
2015-05-16 23:35:08 +01:00
|
|
|
|
2015-06-05 10:17:10 +01:00
|
|
|
_Mat.MeooeDag(in,tmp);
|
|
|
|
_Mat.MooeeInvDag(tmp,out);
|
|
|
|
_Mat.MeooeDag(out,tmp);
|
|
|
|
|
|
|
|
_Mat.MooeeDag(in,out);
|
|
|
|
return axpy_norm(out,-1.0,tmp,out);
|
|
|
|
}
|
|
|
|
};
|
2015-05-18 07:47:05 +01:00
|
|
|
template<class Matrix,class Field>
|
2015-06-05 10:17:10 +01:00
|
|
|
class SchurDiagOneOperator : public SchurOperatorBase<Field> {
|
2015-08-07 08:37:15 +01:00
|
|
|
protected:
|
2015-05-18 07:47:05 +01:00
|
|
|
Matrix &_Mat;
|
2015-05-16 23:35:08 +01:00
|
|
|
public:
|
2015-06-05 10:17:10 +01:00
|
|
|
SchurDiagOneOperator (Matrix &Mat): _Mat(Mat){};
|
|
|
|
|
|
|
|
virtual RealD Mpc (const Field &in, Field &out) {
|
|
|
|
Field tmp(in._grid);
|
|
|
|
|
2016-02-20 07:50:32 +00:00
|
|
|
_Mat.Meooe(in,out);
|
|
|
|
_Mat.MooeeInv(out,tmp);
|
|
|
|
_Mat.Meooe(tmp,out);
|
|
|
|
_Mat.MooeeInv(out,tmp);
|
2015-06-05 10:17:10 +01:00
|
|
|
|
|
|
|
return axpy_norm(out,-1.0,tmp,in);
|
|
|
|
}
|
|
|
|
virtual RealD MpcDag (const Field &in, Field &out){
|
|
|
|
Field tmp(in._grid);
|
|
|
|
|
|
|
|
_Mat.MooeeInvDag(in,out);
|
|
|
|
_Mat.MeooeDag(out,tmp);
|
|
|
|
_Mat.MooeeInvDag(tmp,out);
|
|
|
|
_Mat.MeooeDag(out,tmp);
|
|
|
|
|
|
|
|
return axpy_norm(out,-1.0,tmp,in);
|
2015-05-16 23:35:08 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-01-25 06:26:25 +00:00
|
|
|
template<class Matrix,class Field>
|
|
|
|
class SchurDiagTwoOperator : public SchurOperatorBase<Field> {
|
|
|
|
protected:
|
|
|
|
Matrix &_Mat;
|
|
|
|
public:
|
|
|
|
SchurDiagTwoOperator (Matrix &Mat): _Mat(Mat){};
|
|
|
|
|
|
|
|
virtual RealD Mpc (const Field &in, Field &out) {
|
|
|
|
Field tmp(in._grid);
|
|
|
|
|
|
|
|
_Mat.MooeeInv(in,out);
|
|
|
|
_Mat.Meooe(out,tmp);
|
|
|
|
_Mat.MooeeInv(tmp,out);
|
|
|
|
_Mat.Meooe(out,tmp);
|
|
|
|
|
|
|
|
return axpy_norm(out,-1.0,tmp,in);
|
|
|
|
}
|
|
|
|
virtual RealD MpcDag (const Field &in, Field &out){
|
|
|
|
Field tmp(in._grid);
|
|
|
|
|
|
|
|
_Mat.MeooeDag(in,out);
|
|
|
|
_Mat.MooeeInvDag(out,tmp);
|
|
|
|
_Mat.MeooeDag(tmp,out);
|
|
|
|
_Mat.MooeeInvDag(out,tmp);
|
|
|
|
|
|
|
|
return axpy_norm(out,-1.0,tmp,in);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-08-07 08:37:15 +01:00
|
|
|
|
2015-05-16 23:35:08 +01:00
|
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
// Base classes for functions of operators
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
template<class Field> class OperatorFunction {
|
|
|
|
public:
|
2015-05-18 07:47:05 +01:00
|
|
|
virtual void operator() (LinearOperatorBase<Field> &Linop, const Field &in, Field &out) = 0;
|
2015-06-21 10:58:46 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template<class Field> class LinearFunction {
|
|
|
|
public:
|
|
|
|
virtual void operator() (const Field &in, Field &out) = 0;
|
2015-05-16 23:35:08 +01:00
|
|
|
};
|
|
|
|
|
2015-06-08 11:52:44 +01:00
|
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
// Base classes for Multishift solvers for operators
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
template<class Field> class OperatorMultiFunction {
|
|
|
|
public:
|
|
|
|
virtual void operator() (LinearOperatorBase<Field> &Linop, const Field &in, std::vector<Field> &out) = 0;
|
|
|
|
};
|
|
|
|
|
2015-05-16 23:35:08 +01:00
|
|
|
// FIXME : To think about
|
|
|
|
|
|
|
|
// Chroma functionality list defining LinearOperator
|
|
|
|
/*
|
|
|
|
virtual void operator() (T& chi, const T& psi, enum PlusMinus isign) const = 0;
|
|
|
|
virtual void operator() (T& chi, const T& psi, enum PlusMinus isign, Real epsilon) const
|
|
|
|
virtual const Subset& subset() const = 0;
|
|
|
|
virtual unsigned long nFlops() const { return 0; }
|
|
|
|
virtual void deriv(P& ds_u, const T& chi, const T& psi, enum PlusMinus isign) const
|
|
|
|
class UnprecLinearOperator : public DiffLinearOperator<T,P,Q>
|
|
|
|
const Subset& subset() const {return all;}
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2015-05-13 11:25:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|