2016-01-02 14:51:32 +00:00
|
|
|
/*************************************************************************************
|
|
|
|
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
|
|
|
|
Source file: ./lib/algorithms/iterative/SchurRedBlack.h
|
|
|
|
|
|
|
|
Copyright (C) 2015
|
|
|
|
|
|
|
|
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-18 07:47:05 +01:00
|
|
|
#ifndef GRID_SCHUR_RED_BLACK_H
|
|
|
|
#define GRID_SCHUR_RED_BLACK_H
|
|
|
|
|
2015-05-25 13:43:58 +01:00
|
|
|
|
2015-05-18 07:47:05 +01:00
|
|
|
/*
|
|
|
|
* Red black Schur decomposition
|
|
|
|
*
|
|
|
|
* M = (Mee Meo) = (1 0 ) (Mee 0 ) (1 Mee^{-1} Meo)
|
|
|
|
* (Moe Moo) (Moe Mee^-1 1 ) (0 Moo-Moe Mee^-1 Meo) (0 1 )
|
|
|
|
* = L D U
|
|
|
|
*
|
|
|
|
* L^-1 = (1 0 )
|
|
|
|
* (-MoeMee^{-1} 1 )
|
|
|
|
* L^{dag} = ( 1 Mee^{-dag} Moe^{dag} )
|
|
|
|
* ( 0 1 )
|
|
|
|
* L^{-d} = ( 1 -Mee^{-dag} Moe^{dag} )
|
|
|
|
* ( 0 1 )
|
|
|
|
*
|
|
|
|
* U^-1 = (1 -Mee^{-1} Meo)
|
|
|
|
* (0 1 )
|
|
|
|
* U^{dag} = ( 1 0)
|
|
|
|
* (Meo^dag Mee^{-dag} 1)
|
|
|
|
* U^{-dag} = ( 1 0)
|
|
|
|
* (-Meo^dag Mee^{-dag} 1)
|
|
|
|
***********************
|
|
|
|
* M psi = eta
|
|
|
|
***********************
|
|
|
|
*Odd
|
2017-10-10 13:49:31 +01:00
|
|
|
* i) D_oo psi_o = L^{-1} eta_o
|
2015-05-25 13:43:58 +01:00
|
|
|
* eta_o' = (D_oo)^dag (eta_o - Moe Mee^{-1} eta_e)
|
2017-10-26 20:58:46 +01:00
|
|
|
*
|
|
|
|
* Wilson:
|
2017-10-10 13:49:31 +01:00
|
|
|
* (D_oo)^{\dag} D_oo psi_o = (D_oo)^dag L^{-1} eta_o
|
2017-10-26 20:58:46 +01:00
|
|
|
* Stag:
|
|
|
|
* D_oo psi_o = L^{-1} eta = (eta_o - Moe Mee^{-1} eta_e)
|
|
|
|
*
|
|
|
|
* L^-1 eta_o= (1 0 ) (e
|
|
|
|
* (-MoeMee^{-1} 1 )
|
|
|
|
*
|
2015-05-18 07:47:05 +01:00
|
|
|
*Even
|
|
|
|
* ii) Mee psi_e + Meo psi_o = src_e
|
|
|
|
*
|
|
|
|
* => sol_e = M_ee^-1 * ( src_e - Meo sol_o )...
|
|
|
|
*
|
2017-10-10 13:49:31 +01:00
|
|
|
*
|
|
|
|
* TODO: Other options:
|
|
|
|
*
|
|
|
|
* a) change checkerboards for Schur e<->o
|
|
|
|
*
|
|
|
|
* Left precon by Moo^-1
|
|
|
|
* b) Doo^{dag} M_oo^-dag Moo^-1 Doo psi_0 = (D_oo)^dag M_oo^-dag Moo^-1 L^{-1} eta_o
|
|
|
|
* eta_o' = (D_oo)^dag M_oo^-dag Moo^-1 (eta_o - Moe Mee^{-1} eta_e)
|
|
|
|
*
|
|
|
|
* Right precon by Moo^-1
|
|
|
|
* c) M_oo^-dag Doo^{dag} Doo Moo^-1 phi_0 = M_oo^-dag (D_oo)^dag L^{-1} eta_o
|
|
|
|
* eta_o' = M_oo^-dag (D_oo)^dag (eta_o - Moe Mee^{-1} eta_e)
|
|
|
|
* psi_o = M_oo^-1 phi_o
|
|
|
|
* TODO: Deflation
|
2015-05-18 07:47:05 +01:00
|
|
|
*/
|
|
|
|
namespace Grid {
|
|
|
|
|
2017-10-10 10:00:43 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Take a matrix and form a Red Black solver calling a Herm solver
|
|
|
|
// Use of RB info prevents making SchurRedBlackSolve conform to standard interface
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
2017-11-07 14:48:45 +00:00
|
|
|
// Now make the norm reflect extra factor of Mee
|
2017-10-10 10:00:43 +01:00
|
|
|
template<class Field> class SchurRedBlackStaggeredSolve {
|
|
|
|
private:
|
|
|
|
OperatorFunction<Field> & _HermitianRBSolver;
|
|
|
|
int CBfactorise;
|
2018-05-31 17:16:20 +01:00
|
|
|
bool subGuess;
|
2017-10-10 10:00:43 +01:00
|
|
|
public:
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// Wrap the usual normal equations Schur trick
|
|
|
|
/////////////////////////////////////////////////////
|
2018-05-31 17:16:20 +01:00
|
|
|
SchurRedBlackStaggeredSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false) :
|
2017-10-10 10:00:43 +01:00
|
|
|
_HermitianRBSolver(HermitianRBSolver)
|
|
|
|
{
|
|
|
|
CBfactorise=0;
|
2018-05-31 17:16:20 +01:00
|
|
|
subtractGuess(initSubGuess);
|
2017-10-10 10:00:43 +01:00
|
|
|
};
|
2018-05-31 17:16:20 +01:00
|
|
|
void subtractGuess(const bool initSubGuess)
|
|
|
|
{
|
|
|
|
subGuess = initSubGuess;
|
|
|
|
}
|
|
|
|
bool isSubtractGuess(void)
|
|
|
|
{
|
|
|
|
return subGuess;
|
|
|
|
}
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
template<class Matrix>
|
2018-02-20 14:28:38 +00:00
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out){
|
2018-03-14 14:54:25 +00:00
|
|
|
ZeroGuesser<Field> guess;
|
2018-02-20 14:28:38 +00:00
|
|
|
(*this)(_Matrix,in,out,guess);
|
|
|
|
}
|
|
|
|
template<class Matrix, class Guesser>
|
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out, Guesser &guess){
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
// FIXME CGdiagonalMee not implemented virtual function
|
|
|
|
// FIXME use CBfactorise to control schur decomp
|
|
|
|
GridBase *grid = _Matrix.RedBlackGrid();
|
|
|
|
GridBase *fgrid= _Matrix.Grid();
|
|
|
|
|
|
|
|
SchurStaggeredOperator<Matrix,Field> _HermOpEO(_Matrix);
|
|
|
|
|
|
|
|
Field src_e(grid);
|
|
|
|
Field src_o(grid);
|
|
|
|
Field sol_e(grid);
|
|
|
|
Field sol_o(grid);
|
|
|
|
Field tmp(grid);
|
|
|
|
Field Mtmp(grid);
|
|
|
|
Field resid(fgrid);
|
2017-11-24 14:18:30 +00:00
|
|
|
|
|
|
|
std::cout << GridLogMessage << " SchurRedBlackStaggeredSolve " <<std::endl;
|
2017-10-10 10:00:43 +01:00
|
|
|
pickCheckerboard(Even,src_e,in);
|
|
|
|
pickCheckerboard(Odd ,src_o,in);
|
|
|
|
pickCheckerboard(Even,sol_e,out);
|
|
|
|
pickCheckerboard(Odd ,sol_o,out);
|
2017-11-24 14:18:30 +00:00
|
|
|
std::cout << GridLogMessage << " SchurRedBlackStaggeredSolve checkerboards picked" <<std::endl;
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
2017-10-26 20:58:46 +01:00
|
|
|
// src_o = (source_o - Moe MeeInv source_e)
|
2017-10-10 10:00:43 +01:00
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
_Matrix.MooeeInv(src_e,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
_Matrix.Meooe (tmp,Mtmp); assert( Mtmp.checkerboard ==Odd);
|
|
|
|
tmp=src_o-Mtmp; assert( tmp.checkerboard ==Odd);
|
|
|
|
|
2017-11-07 14:48:45 +00:00
|
|
|
//src_o = tmp; assert(src_o.checkerboard ==Odd);
|
|
|
|
_Matrix.Mooee(tmp,src_o); // Extra factor of "m" in source from dumb choice of matrix norm.
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// Call the red-black solver
|
|
|
|
//////////////////////////////////////////////////////////////
|
2017-10-26 20:58:46 +01:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackStaggeredSolver calling the Mpc solver" <<std::endl;
|
2018-06-20 16:07:40 +01:00
|
|
|
guess(src_o, sol_o);
|
|
|
|
Mtmp = sol_o;
|
|
|
|
_HermitianRBSolver(_HermOpEO,src_o,sol_o); assert(sol_o.checkerboard==Odd);
|
2017-11-24 14:18:30 +00:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackStaggeredSolver called the Mpc solver" <<std::endl;
|
2018-06-20 16:07:40 +01:00
|
|
|
// Fionn A2A boolean behavioural control
|
|
|
|
if (subGuess) sol_o = sol_o-Mtmp;
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
// sol_e = M_ee^-1 * ( src_e - Meo sol_o )...
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
_Matrix.Meooe(sol_o,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
src_e = src_e-tmp; assert( src_e.checkerboard ==Even);
|
|
|
|
_Matrix.MooeeInv(src_e,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
|
2017-11-24 14:18:30 +00:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackStaggeredSolver reconstructed other CB" <<std::endl;
|
2017-10-10 10:00:43 +01:00
|
|
|
setCheckerboard(out,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
setCheckerboard(out,sol_o); assert( sol_o.checkerboard ==Odd );
|
2017-11-24 14:18:30 +00:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackStaggeredSolver inserted solution" <<std::endl;
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
// Verify the unprec residual
|
2018-06-20 16:07:40 +01:00
|
|
|
if ( ! subGuess ) {
|
|
|
|
_Matrix.M(out,resid);
|
|
|
|
resid = resid-in;
|
|
|
|
RealD ns = norm2(in);
|
|
|
|
RealD nr = norm2(resid);
|
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackStaggered solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl;
|
|
|
|
}
|
2017-10-10 10:00:43 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
template<class Field> using SchurRedBlackStagSolve = SchurRedBlackStaggeredSolve<Field>;
|
|
|
|
|
2015-05-18 07:47:05 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Take a matrix and form a Red Black solver calling a Herm solver
|
|
|
|
// Use of RB info prevents making SchurRedBlackSolve conform to standard interface
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
2015-06-05 10:17:10 +01:00
|
|
|
template<class Field> class SchurRedBlackDiagMooeeSolve {
|
2015-05-18 07:47:05 +01:00
|
|
|
private:
|
2015-06-05 10:17:10 +01:00
|
|
|
OperatorFunction<Field> & _HermitianRBSolver;
|
2015-05-18 07:47:05 +01:00
|
|
|
int CBfactorise;
|
2018-05-31 17:16:20 +01:00
|
|
|
bool subGuess;
|
2015-05-18 07:47:05 +01:00
|
|
|
public:
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// Wrap the usual normal equations Schur trick
|
|
|
|
/////////////////////////////////////////////////////
|
2018-05-31 17:16:20 +01:00
|
|
|
SchurRedBlackDiagMooeeSolve(OperatorFunction<Field> &HermitianRBSolver,int cb=0, const bool initSubGuess = false) : _HermitianRBSolver(HermitianRBSolver)
|
2017-10-10 13:49:31 +01:00
|
|
|
{
|
|
|
|
CBfactorise=cb;
|
2018-05-31 17:16:20 +01:00
|
|
|
subtractGuess(initSubGuess);
|
2017-10-10 13:49:31 +01:00
|
|
|
};
|
2018-05-31 17:16:20 +01:00
|
|
|
void subtractGuess(const bool initSubGuess)
|
|
|
|
{
|
|
|
|
subGuess = initSubGuess;
|
|
|
|
}
|
|
|
|
bool isSubtractGuess(void)
|
|
|
|
{
|
|
|
|
return subGuess;
|
|
|
|
}
|
2015-05-25 13:43:58 +01:00
|
|
|
template<class Matrix>
|
2018-02-20 14:28:38 +00:00
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out){
|
2018-03-14 14:54:25 +00:00
|
|
|
ZeroGuesser<Field> guess;
|
2018-02-20 14:28:38 +00:00
|
|
|
(*this)(_Matrix,in,out,guess);
|
|
|
|
}
|
|
|
|
template<class Matrix, class Guesser>
|
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out,Guesser &guess){
|
2015-05-18 07:47:05 +01:00
|
|
|
|
|
|
|
// FIXME CGdiagonalMee not implemented virtual function
|
|
|
|
// FIXME use CBfactorise to control schur decomp
|
2015-05-31 15:09:02 +01:00
|
|
|
GridBase *grid = _Matrix.RedBlackGrid();
|
|
|
|
GridBase *fgrid= _Matrix.Grid();
|
2015-06-05 10:17:10 +01:00
|
|
|
|
|
|
|
SchurDiagMooeeOperator<Matrix,Field> _HermOpEO(_Matrix);
|
2015-05-18 07:47:05 +01:00
|
|
|
|
2015-05-25 13:43:58 +01:00
|
|
|
Field src_e(grid);
|
|
|
|
Field src_o(grid);
|
|
|
|
Field sol_e(grid);
|
|
|
|
Field sol_o(grid);
|
|
|
|
Field tmp(grid);
|
|
|
|
Field Mtmp(grid);
|
|
|
|
Field resid(fgrid);
|
|
|
|
|
2015-05-18 07:47:05 +01:00
|
|
|
pickCheckerboard(Even,src_e,in);
|
|
|
|
pickCheckerboard(Odd ,src_o,in);
|
2016-05-02 00:07:55 +01:00
|
|
|
pickCheckerboard(Even,sol_e,out);
|
|
|
|
pickCheckerboard(Odd ,sol_o,out);
|
|
|
|
|
2015-05-18 07:47:05 +01:00
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// src_o = Mdag * (source_o - Moe MeeInv source_e)
|
|
|
|
/////////////////////////////////////////////////////
|
2015-05-25 13:43:58 +01:00
|
|
|
_Matrix.MooeeInv(src_e,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
_Matrix.Meooe (tmp,Mtmp); assert( Mtmp.checkerboard ==Odd);
|
|
|
|
tmp=src_o-Mtmp; assert( tmp.checkerboard ==Odd);
|
2015-06-05 10:17:10 +01:00
|
|
|
|
|
|
|
// get the right MpcDag
|
|
|
|
_HermOpEO.MpcDag(tmp,src_o); assert(src_o.checkerboard ==Odd);
|
2015-05-18 07:47:05 +01:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// Call the red-black solver
|
|
|
|
//////////////////////////////////////////////////////////////
|
2015-07-23 17:31:13 +01:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlack solver calling the MpcDagMp solver" <<std::endl;
|
2018-02-20 14:28:38 +00:00
|
|
|
guess(src_o,sol_o);
|
2018-06-20 16:07:40 +01:00
|
|
|
Mtmp = sol_o;
|
|
|
|
_HermitianRBSolver(_HermOpEO,src_o,sol_o); assert(sol_o.checkerboard==Odd);
|
|
|
|
// Fionn A2A boolean behavioural control
|
|
|
|
if (subGuess) sol_o = sol_o-Mtmp;
|
2015-05-18 07:47:05 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
// sol_e = M_ee^-1 * ( src_e - Meo sol_o )...
|
|
|
|
///////////////////////////////////////////////////
|
2015-05-25 13:43:58 +01:00
|
|
|
_Matrix.Meooe(sol_o,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
src_e = src_e-tmp; assert( src_e.checkerboard ==Even);
|
|
|
|
_Matrix.MooeeInv(src_e,sol_e); assert( sol_e.checkerboard ==Even);
|
2015-05-18 07:47:05 +01:00
|
|
|
|
2015-05-25 13:43:58 +01:00
|
|
|
setCheckerboard(out,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
setCheckerboard(out,sol_o); assert( sol_o.checkerboard ==Odd );
|
|
|
|
|
|
|
|
// Verify the unprec residual
|
2018-06-20 16:07:40 +01:00
|
|
|
if ( ! subGuess ) {
|
|
|
|
_Matrix.M(out,resid);
|
|
|
|
resid = resid-in;
|
|
|
|
RealD ns = norm2(in);
|
|
|
|
RealD nr = norm2(resid);
|
2015-05-25 13:43:58 +01:00
|
|
|
|
2018-06-20 16:07:40 +01:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackDiagMooee solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl;
|
|
|
|
}
|
2015-05-18 07:47:05 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Take a matrix and form a Red Black solver calling a Herm solver
|
|
|
|
// Use of RB info prevents making SchurRedBlackSolve conform to standard interface
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class Field> class SchurRedBlackDiagTwoSolve {
|
|
|
|
private:
|
|
|
|
OperatorFunction<Field> & _HermitianRBSolver;
|
|
|
|
int CBfactorise;
|
2018-05-31 17:16:20 +01:00
|
|
|
bool subGuess;
|
2017-10-10 10:00:43 +01:00
|
|
|
public:
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// Wrap the usual normal equations Schur trick
|
|
|
|
/////////////////////////////////////////////////////
|
2018-05-31 17:16:20 +01:00
|
|
|
SchurRedBlackDiagTwoSolve(OperatorFunction<Field> &HermitianRBSolver, const bool initSubGuess = false) :
|
2017-10-10 10:00:43 +01:00
|
|
|
_HermitianRBSolver(HermitianRBSolver)
|
|
|
|
{
|
2018-05-31 17:16:20 +01:00
|
|
|
CBfactorise = 0;
|
|
|
|
subtractGuess(initSubGuess);
|
2017-10-10 10:00:43 +01:00
|
|
|
};
|
2018-05-31 17:16:20 +01:00
|
|
|
void subtractGuess(const bool initSubGuess)
|
|
|
|
{
|
|
|
|
subGuess = initSubGuess;
|
|
|
|
}
|
|
|
|
bool isSubtractGuess(void)
|
|
|
|
{
|
|
|
|
return subGuess;
|
|
|
|
}
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
template<class Matrix>
|
2018-02-20 14:28:38 +00:00
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out){
|
2018-03-14 14:54:25 +00:00
|
|
|
ZeroGuesser<Field> guess;
|
2018-02-20 14:28:38 +00:00
|
|
|
(*this)(_Matrix,in,out,guess);
|
|
|
|
}
|
|
|
|
template<class Matrix,class Guesser>
|
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out,Guesser &guess){
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
// FIXME CGdiagonalMee not implemented virtual function
|
|
|
|
// FIXME use CBfactorise to control schur decomp
|
|
|
|
GridBase *grid = _Matrix.RedBlackGrid();
|
|
|
|
GridBase *fgrid= _Matrix.Grid();
|
|
|
|
|
|
|
|
SchurDiagTwoOperator<Matrix,Field> _HermOpEO(_Matrix);
|
|
|
|
|
|
|
|
Field src_e(grid);
|
|
|
|
Field src_o(grid);
|
|
|
|
Field sol_e(grid);
|
|
|
|
Field sol_o(grid);
|
|
|
|
Field tmp(grid);
|
|
|
|
Field Mtmp(grid);
|
|
|
|
Field resid(fgrid);
|
|
|
|
|
|
|
|
pickCheckerboard(Even,src_e,in);
|
|
|
|
pickCheckerboard(Odd ,src_o,in);
|
|
|
|
pickCheckerboard(Even,sol_e,out);
|
|
|
|
pickCheckerboard(Odd ,sol_o,out);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// src_o = Mdag * (source_o - Moe MeeInv source_e)
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
_Matrix.MooeeInv(src_e,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
_Matrix.Meooe (tmp,Mtmp); assert( Mtmp.checkerboard ==Odd);
|
|
|
|
tmp=src_o-Mtmp; assert( tmp.checkerboard ==Odd);
|
|
|
|
|
|
|
|
// get the right MpcDag
|
|
|
|
_HermOpEO.MpcDag(tmp,src_o); assert(src_o.checkerboard ==Odd);
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// Call the red-black solver
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
std::cout<<GridLogMessage << "SchurRedBlack solver calling the MpcDagMp solver" <<std::endl;
|
|
|
|
// _HermitianRBSolver(_HermOpEO,src_o,sol_o); assert(sol_o.checkerboard==Odd);
|
2018-02-20 14:28:38 +00:00
|
|
|
guess(src_o,tmp);
|
2018-06-20 16:07:40 +01:00
|
|
|
Mtmp = tmp;
|
|
|
|
_HermitianRBSolver(_HermOpEO,src_o,tmp); assert(tmp.checkerboard==Odd);
|
|
|
|
// Fionn A2A boolean behavioural control
|
|
|
|
if (subGuess) tmp = tmp-Mtmp;
|
|
|
|
_Matrix.MooeeInv(tmp,sol_o); assert( sol_o.checkerboard ==Odd);
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
// sol_e = M_ee^-1 * ( src_e - Meo sol_o )...
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
_Matrix.Meooe(sol_o,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
src_e = src_e-tmp; assert( src_e.checkerboard ==Even);
|
|
|
|
_Matrix.MooeeInv(src_e,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
|
|
|
|
setCheckerboard(out,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
setCheckerboard(out,sol_o); assert( sol_o.checkerboard ==Odd );
|
|
|
|
|
|
|
|
// Verify the unprec residual
|
2018-06-20 16:07:40 +01:00
|
|
|
if ( ! subGuess ) {
|
|
|
|
_Matrix.M(out,resid);
|
|
|
|
resid = resid-in;
|
|
|
|
RealD ns = norm2(in);
|
|
|
|
RealD nr = norm2(resid);
|
2017-10-10 10:00:43 +01:00
|
|
|
|
2018-06-20 16:07:40 +01:00
|
|
|
std::cout<<GridLogMessage << "SchurRedBlackDiagTwo solver true unprec resid "<< std::sqrt(nr/ns) <<" nr "<< nr <<" ns "<<ns << std::endl;
|
|
|
|
}
|
2017-10-10 10:00:43 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Take a matrix and form a Red Black solver calling a Herm solver
|
|
|
|
// Use of RB info prevents making SchurRedBlackSolve conform to standard interface
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class Field> class SchurRedBlackDiagTwoMixed {
|
|
|
|
private:
|
|
|
|
LinearFunction<Field> & _HermitianRBSolver;
|
|
|
|
int CBfactorise;
|
2018-05-31 17:16:20 +01:00
|
|
|
bool subGuess;
|
2017-10-10 10:00:43 +01:00
|
|
|
public:
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// Wrap the usual normal equations Schur trick
|
|
|
|
/////////////////////////////////////////////////////
|
2018-05-31 17:16:20 +01:00
|
|
|
SchurRedBlackDiagTwoMixed(LinearFunction<Field> &HermitianRBSolver, const bool initSubGuess = false) :
|
2017-10-10 10:00:43 +01:00
|
|
|
_HermitianRBSolver(HermitianRBSolver)
|
|
|
|
{
|
|
|
|
CBfactorise=0;
|
2018-05-31 17:16:20 +01:00
|
|
|
subtractGuess(initSubGuess);
|
2017-10-10 10:00:43 +01:00
|
|
|
};
|
2018-05-31 17:16:20 +01:00
|
|
|
void subtractGuess(const bool initSubGuess)
|
|
|
|
{
|
|
|
|
subGuess = initSubGuess;
|
|
|
|
}
|
|
|
|
bool isSubtractGuess(void)
|
|
|
|
{
|
|
|
|
return subGuess;
|
|
|
|
}
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
template<class Matrix>
|
2018-02-20 14:28:38 +00:00
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out){
|
2018-03-14 14:54:25 +00:00
|
|
|
ZeroGuesser<Field> guess;
|
2018-02-20 14:28:38 +00:00
|
|
|
(*this)(_Matrix,in,out,guess);
|
|
|
|
}
|
|
|
|
template<class Matrix, class Guesser>
|
|
|
|
void operator() (Matrix & _Matrix,const Field &in, Field &out,Guesser &guess){
|
2017-10-10 10:00:43 +01:00
|
|
|
|
|
|
|
// FIXME CGdiagonalMee not implemented virtual function
|
|
|
|
// FIXME use CBfactorise to control schur decomp
|
|
|
|
GridBase *grid = _Matrix.RedBlackGrid();
|
|
|
|
GridBase *fgrid= _Matrix.Grid();
|
|
|
|
|
|
|
|
SchurDiagTwoOperator<Matrix,Field> _HermOpEO(_Matrix);
|
|
|
|
|
|
|
|
Field src_e(grid);
|
|
|
|
Field src_o(grid);
|
|
|
|
Field sol_e(grid);
|
|
|
|
Field sol_o(grid);
|
|
|
|
Field tmp(grid);
|
|
|
|
Field Mtmp(grid);
|
|
|
|
Field resid(fgrid);
|
|
|
|
|
|
|
|
pickCheckerboard(Even,src_e,in);
|
|
|
|
pickCheckerboard(Odd ,src_o,in);
|
|
|
|
pickCheckerboard(Even,sol_e,out);
|
|
|
|
pickCheckerboard(Odd ,sol_o,out);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// src_o = Mdag * (source_o - Moe MeeInv source_e)
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
_Matrix.MooeeInv(src_e,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
_Matrix.Meooe (tmp,Mtmp); assert( Mtmp.checkerboard ==Odd);
|
|
|
|
tmp=src_o-Mtmp; assert( tmp.checkerboard ==Odd);
|
|
|
|
|
|
|
|
// get the right MpcDag
|
|
|
|
_HermOpEO.MpcDag(tmp,src_o); assert(src_o.checkerboard ==Odd);
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
// Call the red-black solver
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
std::cout<<GridLogMessage << "SchurRedBlack solver calling the MpcDagMp solver" <<std::endl;
|
|
|
|
// _HermitianRBSolver(_HermOpEO,src_o,sol_o); assert(sol_o.checkerboard==Odd);
|
|
|
|
// _HermitianRBSolver(_HermOpEO,src_o,tmp); assert(tmp.checkerboard==Odd);
|
2018-02-20 14:28:38 +00:00
|
|
|
guess(src_o,tmp);
|
2018-06-20 16:07:40 +01:00
|
|
|
Mtmp = tmp;
|
|
|
|
_HermitianRBSolver(_HermOpEO,src_o,tmp); assert(tmp.checkerboard==Odd);
|
|
|
|
// Fionn A2A boolean behavioural control
|
|
|
|
if (subGuess) tmp = tmp-Mtmp;
|
2017-10-10 10:00:43 +01:00
|
|
|
_Matrix.MooeeInv(tmp,sol_o); assert( sol_o.checkerboard ==Odd);
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
// sol_e = M_ee^-1 * ( src_e - Meo sol_o )...
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
_Matrix.Meooe(sol_o,tmp); assert( tmp.checkerboard ==Even);
|
|
|
|
src_e = src_e-tmp; assert( src_e.checkerboard ==Even);
|
|
|
|
_Matrix.MooeeInv(src_e,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
|
|
|
|
setCheckerboard(out,sol_e); assert( sol_e.checkerboard ==Even);
|
|
|
|
setCheckerboard(out,sol_o); assert( sol_o.checkerboard ==Odd );
|
|
|
|
|
|
|
|
// Verify the unprec residual
|
2018-06-20 16:07:40 +01:00
|
|
|
if ( ! subGuess ) {
|
|
|
|
_Matrix.M(out,resid);
|
|
|
|
resid = resid-in;
|
|
|
|
RealD ns = norm2(in);
|
|
|
|
RealD nr = norm2(resid);
|
2017-10-10 10:00:43 +01:00
|
|
|
|
2018-06-20 16:07:40 +01:00
|
|
|
std::cout << GridLogMessage << "SchurRedBlackDiagTwo solver true unprec resid " << std::sqrt(nr / ns) << " nr " << nr << " ns " << ns << std::endl;
|
|
|
|
}
|
2017-10-10 10:00:43 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-05-18 07:47:05 +01:00
|
|
|
}
|
|
|
|
#endif
|