#ifndef GRID_ALGORITHM_LINEAR_OP_H #define GRID_ALGORITHM_LINEAR_OP_H #include namespace Grid { ///////////////////////////////////////////////////////////////////////////////////////////// // Interface defining what I expect of a general sparse matrix, such as a Fermion action ///////////////////////////////////////////////////////////////////////////////////////////// template class SparseMatrixBase { public: // Full checkerboar operations virtual void M (const Field &in, Field &out); virtual void Mdag (const Field &in, Field &out); virtual RealD MdagM(const Field &in, Field &out); // half checkerboard operaions virtual void Mpc (const Field &in, Field &out); virtual void MpcDag (const Field &in, Field &out); virtual RealD MpcDagMpc(const Field &in, Field &out); }; ///////////////////////////////////////////////////////////////////////////////////////////// // LinearOperators Take a something and return a something. ///////////////////////////////////////////////////////////////////////////////////////////// // // Hopefully linearity is satisfied and the AdjOp is indeed the Hermitian conjugate (transpose if real): // // i) F(a x + b y) = aF(x) + b F(y). // ii) = ^\ast // // Would be fun to have a test linearity & Herm Conj function! ///////////////////////////////////////////////////////////////////////////////////////////// template class LinearOperatorBase { public: virtual void Op (const Field &in, Field &out) = 0; // Abstract base virtual void AdjOp (const Field &in, Field &out) = 0; // Abstract base }; ///////////////////////////////////////////////////////////////////////////////////////////// // Hermitian operators are self adjoint and only require Op to be defined, so refine the base ///////////////////////////////////////////////////////////////////////////////////////////// template class HermitianOperatorBase : public LinearOperatorBase { public: virtual RealD OpAndNorm(const Field &in, Field &out); void AdjOp(const Field &in, Field &out) { Op(in,out); }; void Op(const Field &in, Field &out) { OpAndNorm(in,out); }; }; ///////////////////////////////////////////////////////////////////////////////////////////// // Whereas non hermitian takes a generic sparse matrix (e.g. lattice action) // conforming to sparse matrix interface and builds the full checkerboard non-herm operator // Op and AdjOp distinct. // 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. ///////////////////////////////////////////////////////////////////////////////////////////// template class NonHermitianOperator : public LinearOperatorBase { SparseMatrix &_Mat; public: NonHermitianOperator(SparseMatrix &Mat): _Mat(Mat){}; void Op (const Field &in, Field &out){ _Mat.M(in,out); } void AdjOp (const Field &in, Field &out){ _Mat.Mdag(in,out); } }; //////////////////////////////////////////////////////////////////////////////////// // Redblack Non hermitian wrapper //////////////////////////////////////////////////////////////////////////////////// template class NonHermitianRedBlackOperator : public LinearOperatorBase { SparseMatrix &_Mat; public: NonHermitianRedBlackOperator(SparseMatrix &Mat): _Mat(Mat){}; void Op (const Field &in, Field &out){ _Mat.Mpc(in,out); } void AdjOp (const Field &in, Field &out){ // _Mat.MpcDag(in,out); } }; //////////////////////////////////////////////////////////////////////////////////// // Hermitian wrapper //////////////////////////////////////////////////////////////////////////////////// template class HermitianOperator : public HermitianOperatorBase { SparseMatrix &_Mat; public: HermitianOperator(SparseMatrix &Mat): _Mat(Mat) {}; RealD OpAndNorm(const Field &in, Field &out){ return _Mat.MdagM(in,out); } }; //////////////////////////////////////////////////////////////////////////////////// // Hermitian RedBlack wrapper //////////////////////////////////////////////////////////////////////////////////// template class HermitianRedBlackOperator : public HermitianOperatorBase { SparseMatrix &_Mat; public: HermitianRedBlackOperator(SparseMatrix &Mat): _Mat(Mat) {}; RealD OpAndNorm(const Field &in, Field &out){ return _Mat.MpcDagMpc(in,out); } }; ///////////////////////////////////////////////////////////// // Base classes for functions of operators ///////////////////////////////////////////////////////////// template class OperatorFunction { public: virtual void operator() (LinearOperatorBase *Linop, const Field &in, Field &out) = 0; }; ///////////////////////////////////////////////////////////// // Base classes for polynomial functions of operators ? needed? ///////////////////////////////////////////////////////////// template class OperatorPolynomial : public OperatorFunction { public: virtual void operator() (LinearOperatorBase *Linop,const Field &in, Field &out) = 0; }; ///////////////////////////////////////////////////////////// // Base classes for iterative processes based on operators // single input vec, single output vec. ///////////////////////////////////////////////////////////// template class IterativeProcess : public OperatorFunction { public: RealD Tolerance; Integer MaxIterations; IterativeProcess(RealD tol,Integer maxit) : Tolerance(tol),MaxIterations(maxit) {}; virtual void operator() (LinearOperatorBase *Linop,const Field &in, Field &out) = 0; }; ///////////////////////////////////////////////////////////// // Grand daddy iterative method ///////////////////////////////////////////////////////////// template class ConjugateGradient : public IterativeProcess { public: virtual void operator() (HermitianOperatorBase *Linop,const Field &in, Field &out) = 0; }; ///////////////////////////////////////////////////////////// // A little more modern ///////////////////////////////////////////////////////////// template class PreconditionedConjugateGradient : public IterativeProcess { public: void operator() (HermitianOperatorBase *Linop, OperatorFunction *Preconditioner, const Field &in, Field &out) = 0; }; // 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 const Subset& subset() const {return all;} }; */ // Chroma interface defining GaugeAction /* template class GaugeAction virtual const CreateGaugeState& getCreateState() const = 0; virtual GaugeState* createState(const Q& q) const virtual const GaugeBC& getGaugeBC() const virtual const Set& getSet(void) const = 0; virtual void deriv(P& result, const Handle< GaugeState >& state) const virtual Double S(const Handle< GaugeState >& state) const = 0; class LinearGaugeAction : public GaugeAction< multi1d, multi1d > typedef multi1d P; typedef multi1d Q; virtual void staple(LatticeColorMatrix& result, const Handle< GaugeState >& state, int mu, int cb) const = 0; */ // Chroma interface defining FermionAction /* template class FermAct4D : public FermionAction virtual LinearOperator* linOp(Handle< FermState > state) const = 0; virtual LinearOperator* lMdagM(Handle< FermState > state) const = 0; virtual LinOpSystemSolver* invLinOp(Handle< FermState > state, virtual MdagMSystemSolver* invMdagM(Handle< FermState > state, virtual LinOpMultiSystemSolver* mInvLinOp(Handle< FermState > state, virtual MdagMMultiSystemSolver* mInvMdagM(Handle< FermState > state, virtual MdagMMultiSystemSolverAccumulate* mInvMdagMAcc(Handle< FermState > state, virtual SystemSolver* qprop(Handle< FermState > state, class DiffFermAct4D : public FermAct4D virtual DiffLinearOperator* linOp(Handle< FermState > state) const = 0; virtual DiffLinearOperator* lMdagM(Handle< FermState > state) const = 0; */ } #endif