6 #ifndef __syssolver_mdagm_clover_qphix_h__
7 #define __syssolver_mdagm_clover_qphix_h__
32 #include "qphix/geometry.h"
33 #include "qphix/qdp_packer.h"
34 #include "qphix/clover.h"
35 #include "qphix/invcg.h"
36 #include "qphix/invbicgstab.h"
40 #include "qphix/blas_new_c.h"
47 namespace MdagMSysSolverQPhiXCloverEnv
59 using namespace QPhiXVecTraits;
61 template<
typename T,
typename U>
62 class MdagMSysSolverQPhiXClover :
public MdagMSystemSolver<T>
66 typedef typename WordType<T>::Type_t REALT;
67 typedef typename QPhiX::Geometry<REALT,VecTraits<REALT>::Vec,VecTraits<REALT>::Soa,VecTraits<REALT>::compress12>::FourSpinorBlock QPhiX_Spinor;
68 typedef typename QPhiX::Geometry<REALT,VecTraits<REALT>::Vec,VecTraits<REALT>::Soa,VecTraits<REALT>::compress12>::SU3MatrixBlock QPhiX_Gauge;
69 typedef typename QPhiX::Geometry<REALT,VecTraits<REALT>::Vec,VecTraits<REALT>::Soa,VecTraits<REALT>::compress12>::CloverBlock QPhiX_Clover;
77 MdagMSysSolverQPhiXClover(Handle< LinearOperator<T> > A_,
78 Handle< FermState<T,Q,Q> > state_,
79 const SysSolverQPhiXCloverParams& invParam_) :
82 QDPIO::cout <<
"MdagMSysSolverQPhiXClover:" << std::endl;
83 QDPIO::cout <<
"AntiPeriodicT is: " << invParam.AntiPeriodicT << std::endl;
86 QDPIO::cout <<
"Veclen is " << VecTraits<REALT>::Vec << std::endl;
87 QDPIO::cout <<
"Soalen is " << VecTraits<REALT>::Soa << std::endl;
88 if ( VecTraits<REALT>::Soa > VecTraits<REALT>::Vec ) {
89 QDPIO::cerr <<
"PROBLEM: Soalen > Veclen. Please set soalen appropriately (<=VECLEN) at compile time" << std::endl;
95 u[
mu] = state_->getLinks()[
mu];
99 multi1d<Real> aniso_coeffs(
Nd);
100 for(
int mu=0;
mu <
Nd;
mu++) aniso_coeffs[
mu] = Real(1);
102 bool anisotropy = invParam.CloverParams.anisoParam.anisoP;
104 aniso_coeffs =
makeFermCoeffs( invParam.CloverParams.anisoParam );
107 double t_boundary=(double)(1);
111 if (invParam.AntiPeriodicT) {
112 t_boundary=(double)(-1);
114 u[3] *= where(Layout::latticeCoordinate(3) == (Layout::lattSize()[3]-1),
115 Real(t_boundary), Real(1));
118 cbsize_in_blocks = rb[0].numSiteTable()/VecTraits<REALT>::Soa;
120 const QPhiX::QPhiXCLIArgs& QPhiXParams = TheQPhiXParams::Instance();
126 int pad_xy = QPhiXParams.getPxy();
127 int pad_xyz= QPhiXParams.getPxyz();
129 n_blas_simt = QPhiXParams.getSy()*QPhiXParams.getSz();
131 QDPIO::cout <<
"About to grap a Dslash" << std::endl;
132 geom =
new QPhiX::Geometry<REALT, VecTraits<REALT>::Vec, VecTraits<REALT>::Soa,VecTraits<REALT>::compress12>(Layout::subgridLattSize().slice(),
135 QPhiXParams.getNCores(),
140 QPhiXParams.getMinCt());
142 QDPIO::cout <<
" Allocating p and c" << std::endl << std::flush ;
144 #ifndef QPD_IS_QDPJIT
145 psi_qphix=(QPhiX_Spinor *)geom->allocCBFourSpinor();
146 chi_qphix=(QPhiX_Spinor *)geom->allocCBFourSpinor();
148 if( invParam.SolverType ==
BICGSTAB ) {
150 tmp_qphix=(QPhiX_Spinor *)geom->allocCBFourSpinor();
160 QDPIO::cout <<
" Allocating Clover" << std::endl << std::flush ;
161 QPhiX_Clover* A_cb0=(QPhiX_Clover *)geom->allocCBClov();
162 QPhiX_Clover* A_cb1=(QPhiX_Clover *)geom->allocCBClov();
163 clov_packed[0] = A_cb0;
164 clov_packed[1] = A_cb1;
166 QDPIO::cout <<
" Allocating CloverInv " << std::endl << std::flush ;
167 QPhiX_Clover* A_inv_cb0=(QPhiX_Clover *)geom->allocCBClov();
168 QPhiX_Clover* A_inv_cb1=(QPhiX_Clover *)geom->allocCBClov();
169 invclov_packed[0] = A_inv_cb0;
170 invclov_packed[1] = A_inv_cb1;
173 QDPIO::cout <<
"Packing gauge field..." << std::endl << std::flush ;
174 QPhiX_Gauge* packed_gauge_cb0=(QPhiX_Gauge *)geom->allocCBGauge();
175 QPhiX_Gauge* packed_gauge_cb1=(QPhiX_Gauge *)geom->allocCBGauge();
177 QPhiX::qdp_pack_gauge<>(
u, packed_gauge_cb0,packed_gauge_cb1, *geom);
178 u_packed[0] = packed_gauge_cb0;
179 u_packed[1] = packed_gauge_cb1;
182 QDPIO::cout <<
"Creating Clover Term" << std::endl;
184 clov->
create(state_, invParam.CloverParams);
185 QDPIO::cout <<
"Inverting Clover Term" << std::endl;
186 invclov->create(state_, invParam.CloverParams, (*clov));
187 for(
int cb=0;
cb < 2;
cb++) {
190 QDPIO::cout <<
"Done" << std::endl;
191 QDPIO::cout <<
"Packing Clover term..." << std::endl;
193 for(
int cb=0;
cb < 2;
cb++) {
194 QPhiX::qdp_pack_clover<>((*invclov), invclov_packed[
cb], *geom,
cb);
197 for(
int cb=0;
cb < 2;
cb++) {
198 QPhiX::qdp_pack_clover<>((*clov), clov_packed[
cb], *geom,
cb);
200 QDPIO::cout <<
"Done" << std::endl;
202 QDPIO::cout <<
"Creating the Even Odd Operator" << std::endl;
203 M=
new QPhiX::EvenOddCloverOperator<REALT,VecTraits<REALT>::Vec,VecTraits<REALT>::Soa,VecTraits<REALT>::compress12>(u_packed,
208 toDouble(aniso_coeffs[0]),
209 toDouble(aniso_coeffs[3]));
212 switch( invParam.SolverType ) {
215 QDPIO::cout <<
"Creating the CG Solver" << std::endl;
216 cg_solver =
new QPhiX::InvCG<REALT,VecTraits<REALT>::Vec, VecTraits<REALT>::Soa, VecTraits<REALT>::compress12>((*M), invParam.MaxIter);
220 QDPIO::cout <<
"Creating the BiCGStab Solver" << std::endl;
221 bicgstab_solver =
new QPhiX::InvBiCGStab<REALT,VecTraits<REALT>::Vec, VecTraits<REALT>::Soa, VecTraits<REALT>::compress12>((*M), invParam.MaxIter);
225 QDPIO::cerr <<
"UNKNOWN Solver Type" << std::endl;
233 ~MdagMSysSolverQPhiXClover()
237 QDPIO::cout <<
"Destructing" << std::endl;
239 #ifndef QDP_IS_QDPJIT
240 geom->free(psi_qphix);
241 geom->free(chi_qphix);
242 if( invParam.SolverType ==
BICGSTAB ) {
243 geom->free(tmp_qphix);
251 geom->free(invclov_packed[0]);
252 geom->free(invclov_packed[1]);
253 invclov_packed[0] =
nullptr;
254 invclov_packed[1] =
nullptr;
256 geom->free(clov_packed[0]);
257 geom->free(clov_packed[1]);
258 clov_packed[0] =
nullptr;
259 clov_packed[1] =
nullptr;
261 geom->free(u_packed[0]);
262 geom->free(u_packed[1]);
263 u_packed[0] =
nullptr;
264 u_packed[1] =
nullptr;
272 const Subset& subset()
const {
return A->subset();}
281 swatch.reset(); swatch.start();
283 SystemSolverResults_t res;
284 switch( invParam.SolverType ) {
287 res = cgSolve(
psi,
chi,predictor);
292 res = biCGStabSolve(
psi,
chi,predictor);
296 QDPIO::cout <<
"Unknown Solver " << std::endl;
301 QDPIO::cout <<
"QPHIX_MDAGM_SOLVER: total time: " << swatch.getTimeInSeconds() <<
" (sec)" << std::endl;
318 SystemSolverResults_t res;
319 Null4DChronoPredictor not_predicting;
320 res=(*this)(
psi,
chi, not_predicting);
332 MdagMSysSolverQPhiXClover() {}
336 Handle< LinearOperator<T> >
A;
337 const SysSolverQPhiXCloverParams invParam;
338 Handle< CloverTermT<T, U> > clov;
339 Handle< CloverTermT<T, U> > invclov;
341 QPhiX::Geometry<REALT, VecTraits<REALT>::Vec, VecTraits<REALT>::Soa, VecTraits<REALT>::compress12>* geom;
343 Handle< QPhiX::EvenOddCloverOperator<REALT, VecTraits<REALT>::Vec, VecTraits<REALT>::Soa, VecTraits<REALT>::compress12> > M;
345 Handle< QPhiX::InvCG<REALT,VecTraits<REALT>::Vec, VecTraits<REALT>::Soa, VecTraits<REALT>::compress12> > cg_solver;
347 Handle< QPhiX::InvBiCGStab<REALT,VecTraits<REALT>::Vec, VecTraits<REALT>::Soa, VecTraits<REALT>::compress12> > bicgstab_solver;
349 QPhiX_Clover* invclov_packed[2];
350 QPhiX_Clover* clov_packed[2];
351 QPhiX_Gauge* u_packed[2];
353 mutable QPhiX_Spinor* psi_qphix;
354 mutable QPhiX_Spinor* chi_qphix;
355 mutable QPhiX_Spinor* tmp_qphix;
357 size_t cbsize_in_blocks;
360 SystemSolverResults_t cgSolve(
T&
psi,
const T&
chi, AbsChronologicalPredictor4D<T>& predictor)
const
362 SystemSolverResults_t res;
363 Handle< LinearOperator<T> >
MdagM(
new MdagMLinOp<T>(
A) );
366 #ifndef QDP_IS_QDPJIT
368 QPhiX::qdp_pack_cb_spinor<>(
psi, psi_qphix, *geom,1);
369 QPhiX::qdp_pack_cb_spinor<>(
chi, chi_qphix, *geom,1);
371 psi_qphix = (QPhiX_Spinor*)(
psi.getFjit()) + cbsize_in_blocks;
372 chi_qphix = (QPhiX_Spinor*)(
chi.getFjit()) + cbsize_in_blocks;
375 unsigned long site_flops=0;
376 unsigned long mv_apps=0;
378 double start = omp_get_wtime();
380 (*cg_solver)(psi_qphix, chi_qphix, toDouble(invParam.RsdTarget), res.n_count, rsd_final, site_flops, mv_apps, my_isign, invParam.VerboseP);
381 double end = omp_get_wtime();
383 #ifndef QDP_IS_QDPJIT
384 QPhiX::qdp_unpack_cb_spinor<>(psi_qphix,
psi, *geom,1);
387 predictor.newVector(
psi);
400 Double rel_resid = sqrt(r2/b2);
401 res.resid = rel_resid;
402 QDPIO::cout <<
"QPHIX_CLOVER_CG_SOLVER: " << res.n_count <<
" iters, rsd_sq_final=" << rel_resid << std::endl;
404 QDPIO::cout <<
"QPHIX_CLOVER_CG_SOLVER: || r || / || b || = " << rel_resid << std::endl;
407 if ( !toBool ( rel_resid < invParam.RsdTarget*invParam.RsdToleranceFactor ) ) {
408 QDPIO::cout <<
"SOLVE FAILED" << std::endl;
414 int num_cb_sites = Layout::vol()/2;
415 unsigned long total_flops = (site_flops + (1320+504+1320+504+48)*mv_apps)*num_cb_sites;
416 double gflops = (double)(total_flops)/(1.0e9);
418 double total_time = end - start;
419 QDPIO::cout <<
"QPHIX_CLOVER_CG_SOLVER: Solver Time="<< total_time <<
" (sec) Performance=" << gflops / total_time <<
" GFLOPS" << std::endl;
427 SystemSolverResults_t biCGStabSolve(
T&
psi,
const T&
chi,AbsChronologicalPredictor4D<T>& predictor)
const
431 swatch.reset(); swatch.start();
433 SystemSolverResults_t res;
434 Handle< LinearOperator<T> >
MdagM(
new MdagMLinOp<T>(
A) );
437 Y[
A->subset() ] =
psi;
441 AbsTwoStepChronologicalPredictor4D<T>& two_step_predictor =
442 dynamic_cast<AbsTwoStepChronologicalPredictor4D<T>&
>(predictor);
446 two_step_predictor.predictY(Y,*
A,
chi);
449 catch( std::bad_cast) {
459 #ifndef QDP_IS_QDPJIT
460 QDPIO::cout <<
"Packing" << std::endl << std::flush ;
461 QPhiX::qdp_pack_cb_spinor<>(Y, tmp_qphix, *geom,1);
462 QPhiX::qdp_pack_cb_spinor<>(
psi, psi_qphix, *geom,1);
463 QPhiX::qdp_pack_cb_spinor<>(
chi, chi_qphix, *geom,1);
465 tmp_qphix = (QPhiX_Spinor *)(Y.getFjit()) + cbsize_in_blocks;
466 psi_qphix = (QPhiX_Spinor *)(
psi.getFjit()) + cbsize_in_blocks;
467 chi_qphix = (QPhiX_Spinor *)(
chi.getFjit()) + cbsize_in_blocks;
469 QDPIO::cout <<
"Done" << std::endl << std::flush;
471 int num_cb_sites = Layout::vol()/2;
473 unsigned long site_flops1=0;
474 unsigned long mv_apps1=0;
477 unsigned long site_flops2=0;
478 unsigned long mv_apps2=0;
481 QDPIO::cout <<
"Starting Y solve" << std::endl << std::flush ;
482 double start = omp_get_wtime();
483 (*bicgstab_solver)(tmp_qphix,chi_qphix, toDouble(invParam.RsdTarget), n_count1, rsd_final, site_flops1, mv_apps1, -1, invParam.VerboseP);
484 double end = omp_get_wtime();
487 unsigned long total_flops = (site_flops1 + (1320+504+1320+504+48)*mv_apps1)*num_cb_sites;
488 double gflops = (double)(total_flops)/(1.0e9);
489 double total_time = end - start;
491 Double r_final = sqrt(toDouble(rsd_final)/norm2(
chi,
A->subset()));
492 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_SOLVER: " << n_count1 <<
" iters, rsd_sq_final=" << rsd_final <<
" ||r||/||b|| (acc) = " << r_final <<std::endl;
493 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_SOLVER: Solver Time="<< total_time <<
" (sec) Performance=" << gflops / total_time <<
" GFLOPS" << std::endl;
495 QDPIO::cout <<
"Starting X solve" << std::endl << std::flush ;
496 start = omp_get_wtime();
497 (*bicgstab_solver)(psi_qphix,tmp_qphix, toDouble(invParam.RsdTarget), n_count2, rsd_final, site_flops2, mv_apps2, +1, invParam.VerboseP);
498 end = omp_get_wtime();
499 total_flops = (site_flops2 + (1320+504+1320+504+48)*mv_apps2)*num_cb_sites;
500 gflops = (double)(total_flops)/(1.0e9);
501 total_time = end - start;
503 #ifndef QDP_IS_QDPJIT
505 QPhiX::qdp_unpack_cb_spinor<>(tmp_qphix, Y, *geom,1);
508 QPhiX::norm2Spinor(norm2Y, tmp_qphix, *geom, n_blas_simt);
509 r_final = sqrt(toDouble(rsd_final)/norm2Y);
511 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_SOLVER: " << n_count2 <<
" iters, rsd_sq_final=" << rsd_final <<
" ||r||/||b|| (acc) = " << r_final << std::endl;
512 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_SOLVER: Solver Time="<< total_time <<
" (sec) Performance=" << gflops / total_time <<
" GFLOPS" << std::endl;
514 #ifndef QDP_IS_QDPJIT
515 QPhiX::qdp_unpack_cb_spinor<>(psi_qphix,
psi, *geom,1);
520 AbsTwoStepChronologicalPredictor4D<T>& two_step_predictor =
521 dynamic_cast<AbsTwoStepChronologicalPredictor4D<T>&
>(predictor);
522 two_step_predictor.newYVector(Y);
523 two_step_predictor.newXVector(
psi);
526 catch( std::bad_cast) {
530 predictor.newVector(
psi);
535 Y[
A->subset() ] =
chi;
541 Y[
A->subset() ] -=
tmp2;
544 Double r2 = norm2(Y,
A->subset());
546 Double rel_resid = sqrt(r2/b2);
548 res.n_count = n_count1 + n_count2;
549 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_SOLVER: total_iters="<<res.n_count<<
" || r || / || b || = " << res.resid << std::endl;
553 if ( !toBool ( rel_resid < invParam.RsdTarget*invParam.RsdToleranceFactor ) ) {
554 QDPIO::cout <<
"SOLVE FAILED" << std::endl;
560 QDPIO::cout <<
"QPHIX_MDAGM_SOLVER: total time: " << swatch.getTimeInSeconds() <<
" (sec)" << std::endl;
Abstract interface for a Chronological Solution predictor.
void create(Handle< FermState< T, multi1d< U >, multi1d< U > > > fs, const CloverFermActParams ¶m_)
Creation routine.
Include possibly optimized Clover terms.
Even-odd preconditioned Clover fermion linear operator.
Class for counted reference semantics.
M^dag*M composition of a linear operator.
bool registerAll()
Register all the factories.
multi1d< Hadron2PtContraction_t > operator()(const multi1d< LatticeColorMatrix > &u)
Asqtad Staggered-Dirac operator.
static multi1d< LatticeColorMatrix > u
LinOpSysSolverMGProtoClover::Q Q
QDPCloverTermT< T, U > CloverTermT
multi1d< Real > makeFermCoeffs(const AnisoParam_t &aniso)
Make fermion coefficients.
FloatingPoint< double > Double
Null predictor: Leaves input x0 unchanged.
multi1d< LatticeFermion > r(Ncb)
Periodic ferm state and a creator.
Fermion action factories.
Reunitarize in place a color matrix to SU(N)
Support class for fermion actions and linear operators.
Handle< LinearOperator< T > > MdagM
multi1d< LatticeColorMatrix > U
multi1d< LatticeColorMatrix > Q