#ifndef QCD_PSEUDOFERMION_TWO_FLAVOUR_EVEN_ODD_H #define QCD_PSEUDOFERMION_TWO_FLAVOUR_EVEN_ODD_H namespace Grid{ namespace QCD{ //////////////////////////////////////////////////////////////////////// // Two flavour pseudofermion action for any EO prec dop //////////////////////////////////////////////////////////////////////// template class TwoFlavourEvenOddPseudoFermionAction : public Action { public: INHERIT_IMPL_TYPES(Impl); private: FermionOperator & FermOp;// the basic operator OperatorFunction &DerivativeSolver; OperatorFunction &ActionSolver; FermionField PhiOdd; // the pseudo fermion field for this trajectory FermionField PhiEven; // the pseudo fermion field for this trajectory public: ///////////////////////////////////////////////// // Pass in required objects. ///////////////////////////////////////////////// TwoFlavourEvenOddPseudoFermionAction(FermionOperator &Op, OperatorFunction & DS, OperatorFunction & AS ) : FermOp(Op), DerivativeSolver(DS), ActionSolver(AS), PhiEven(Op.FermionRedBlackGrid()), PhiOdd(Op.FermionRedBlackGrid()) {}; ////////////////////////////////////////////////////////////////////////////////////// // Push the gauge field in to the dops. Assume any BC's and smearing already applied ////////////////////////////////////////////////////////////////////////////////////// virtual void refresh(const GaugeField &U, GridParallelRNG& pRNG) { // P(phi) = e^{- phi^dag (MpcdagMpc)^-1 phi} // Phi = McpDag eta // P(eta) = e^{- eta^dag eta} // // e^{x^2/2 sig^2} => sig^2 = 0.5. RealD scale = std::sqrt(0.5); FermionField eta (FermOp.FermionGrid()); FermionField etaOdd (FermOp.FermionRedBlackGrid()); FermionField etaEven(FermOp.FermionRedBlackGrid()); gaussian(pRNG,eta); pickCheckerboard(Even,etaEven,eta); pickCheckerboard(Odd,etaOdd,eta); FermOp.ImportGauge(U); SchurDifferentiableOperator PCop(FermOp); PCop.MpcDag(etaOdd,PhiOdd); FermOp.MooeeDag(etaEven,PhiEven); PhiOdd =PhiOdd*scale; PhiEven=PhiEven*scale; }; ////////////////////////////////////////////////////// // S = phi^dag (Mdag M)^-1 phi (odd) // + phi^dag (Mdag M)^-1 phi (even) ////////////////////////////////////////////////////// virtual RealD S(const GaugeField &U) { FermOp.ImportGauge(U); FermionField X(FermOp.FermionRedBlackGrid()); FermionField Y(FermOp.FermionRedBlackGrid()); SchurDifferentiableOperator PCop(FermOp); X=zero; ActionSolver(PCop,PhiOdd,X); PCop.Op(X,Y); RealD action = norm2(Y); // The EE factorised block; normally can replace with zero if det is constant (gauge field indept) // Only really clover term that creates this. FermOp.MooeeInvDag(PhiEven,Y); action = action + norm2(Y); std::cout << GridLogMessage << "Pseudofermion EO action "< Mpc(FermOp); // Our conventions really make this UdSdU; We do not differentiate wrt Udag here. // So must take dSdU - adj(dSdU) and left multiply by mom to get dS/dt. X=zero; DerivativeSolver(Mpc,PhiOdd,X); Mpc.Mpc(X,Y); Mpc.MpcDeriv(tmp , Y, X ); dSdU=tmp; Mpc.MpcDagDeriv(tmp , X, Y); dSdU=dSdU+tmp; // Treat the EE case. (MdagM)^-1 = Minv Minvdag // Deriv defaults to zero. // FermOp.MooeeInvDag(PhiOdd,Y); // FermOp.MooeeInv(Y,X); // FermOp.MeeDeriv(tmp , Y, X,DaggerNo ); dSdU=tmp; // FermOp.MeeDeriv(tmp , X, Y,DaggerYes); dSdU=dSdU+tmp; assert(FermOp.ConstEE() == 1); /* FermOp.MooeeInvDag(PhiOdd,Y); FermOp.MooeeInv(Y,X); FermOp.MeeDeriv(tmp , Y, X,DaggerNo ); dSdU=tmp; FermOp.MeeDeriv(tmp , X, Y,DaggerYes); dSdU=dSdU+tmp; */ dSdU = Ta(dSdU); }; }; } } #endif