6 #ifndef __syssolver_linop_clover_qphix_iter_refine_h__
7 #define __syssolver_linop_clover_qphix_iter_refine_h__
30 #include "qphix/geometry.h"
31 #include "qphix/qdp_packer.h"
32 #include "qphix/clover.h"
33 #include "qphix/invbicgstab.h"
34 #include "qphix/inv_richardson_multiprec.h"
42 namespace LinOpSysSolverQPhiXCloverIterRefineEnv
55 using namespace QPhiXVecTraits;
56 template<
typename T,
typename U>
57 class LinOpSysSolverQPhiXCloverIterRefine :
public LinOpSystemSolver<T>
61 typedef typename WordType<T>::Type_t REALT;
62 typedef CHROMA_QPHIX_INNER_TYPE InnerReal;
64 typedef typename QPhiX::Geometry<REALT,MixedVecTraits<REALT,InnerReal>::Vec,MixedVecTraits<REALT,InnerReal>::Soa,MixedVecTraits<REALT,InnerReal>::compress12>::FourSpinorBlock QPhiX_Spinor;
65 typedef typename QPhiX::Geometry<REALT,MixedVecTraits<REALT,InnerReal>::Vec,MixedVecTraits<REALT,InnerReal>::Soa,MixedVecTraits<REALT,InnerReal>::compress12>::SU3MatrixBlock QPhiX_Gauge;
66 typedef typename QPhiX::Geometry<REALT,MixedVecTraits<REALT,InnerReal>::Vec,MixedVecTraits<REALT,InnerReal>::Soa,MixedVecTraits<REALT,InnerReal>::compress12>::CloverBlock QPhiX_Clover;
68 typedef typename QPhiX::Geometry<InnerReal,MixedVecTraits<REALT,InnerReal>::VecInner,
69 MixedVecTraits<REALT,InnerReal>::SoaInner,
70 MixedVecTraits<REALT,InnerReal>::compress12>::FourSpinorBlock QPhiX_InnerSpinor;
72 typedef typename QPhiX::Geometry<InnerReal,MixedVecTraits<REALT,InnerReal>::VecInner,
73 MixedVecTraits<REALT,InnerReal>::SoaInner,
74 MixedVecTraits<REALT,InnerReal>::compress12>::SU3MatrixBlock QPhiX_InnerGauge;
76 typedef typename QPhiX::Geometry<InnerReal,MixedVecTraits<REALT,InnerReal>::VecInner,
77 MixedVecTraits<REALT,InnerReal>::SoaInner,
78 MixedVecTraits<REALT,InnerReal>::compress12>::CloverBlock QPhiX_InnerClover;
86 LinOpSysSolverQPhiXCloverIterRefine(Handle< LinearOperator<T> > A_,
87 Handle< FermState<T,Q,Q> > state_,
88 const SysSolverQPhiXCloverParams& invParam_) :
93 QDPIO::cout <<
"LinOpSysSolverQPhiXCloverIterRefine:" << std::endl;
95 if ( toBool( invParam.Delta < 0 ) ) {
96 QDPIO::cout <<
"Error: Delta parameter for solve should be set" << std::endl;
100 QDPIO::cout <<
"AntiPeriodicT is: " << invParam.AntiPeriodicT << std::endl;
103 QDPIO::cout <<
"Veclen is " << MixedVecTraits<REALT,InnerReal>::Vec << std::endl;
104 QDPIO::cout <<
"Soalen is " << MixedVecTraits<REALT,InnerReal>::Soa << std::endl;
105 QDPIO::cout <<
"Inner Veclen is " << MixedVecTraits<REALT,InnerReal>::VecInner << std::endl;
106 QDPIO::cout <<
"Inner Soalen is " << MixedVecTraits<REALT,InnerReal>::SoaInner << std::endl;
108 if ( MixedVecTraits<REALT,InnerReal>::Soa > MixedVecTraits<REALT,InnerReal>::Vec ) {
109 QDPIO::cerr <<
"PROBLEM: Soalen > Veclen. Please set soalen appropriately (<=VECLEN) at compile time" << std::endl;
113 if ( MixedVecTraits<REALT,InnerReal>::SoaInner > MixedVecTraits<REALT,InnerReal>::VecInner ) {
114 QDPIO::cerr <<
"PROBLEM: Inner Soalen > Inner Veclen. Please set soalen appropriately at compile time" << std::endl;
120 u[
mu] = state_->getLinks()[
mu];
124 multi1d<Real> aniso_coeffs(
Nd);
125 for(
int mu=0;
mu <
Nd;
mu++) aniso_coeffs[
mu] = Real(1);
127 bool anisotropy = invParam.CloverParams.anisoParam.anisoP;
129 aniso_coeffs =
makeFermCoeffs( invParam.CloverParams.anisoParam );
132 double t_boundary=(double)(1);
136 if (invParam.AntiPeriodicT) {
137 t_boundary=(double)(-1);
139 u[3] *= where(Layout::latticeCoordinate(3) == (Layout::lattSize()[3]-1),
140 Real(t_boundary), Real(1));
143 cbsize_in_blocks = rb[0].numSiteTable()/MixedVecTraits<REALT,InnerReal>::Soa;
144 const QPhiX::QPhiXCLIArgs& QPhiXParams = TheQPhiXParams::Instance();
149 int pad_xy = QPhiXParams.getPxy();
150 int pad_xyz = QPhiXParams.getPxyz();
154 geom_outer =
new QPhiX::Geometry<REALT,
155 MixedVecTraits<REALT,InnerReal>::Vec,
156 MixedVecTraits<REALT,InnerReal>::Soa,
157 MixedVecTraits<REALT,InnerReal>::compress12>(Layout::subgridLattSize().slice(),
160 QPhiXParams.getNCores(),
165 QPhiXParams.getMinCt());
168 geom_inner =
new QPhiX::Geometry<InnerReal,
169 MixedVecTraits<REALT,InnerReal>::VecInner,
170 MixedVecTraits<REALT,InnerReal>::SoaInner,
171 MixedVecTraits<REALT,InnerReal>::compress12>(Layout::subgridLattSize().slice(),
174 QPhiXParams.getNCores(),
180 QPhiXParams.getMinCt());
184 #ifndef QDP_IS_QDPJIT
185 p_even=(QPhiX_Spinor *)geom_outer->allocCBFourSpinor();
186 p_odd=(QPhiX_Spinor *)geom_outer->allocCBFourSpinor();
187 c_even=(QPhiX_Spinor *)geom_outer->allocCBFourSpinor();
188 c_odd=(QPhiX_Spinor *)geom_outer->allocCBFourSpinor();
201 QDPIO::cout <<
"Packing gauge field..." ;
203 QPhiX_Gauge* packed_gauge_cb0=(QPhiX_Gauge *)geom_outer->allocCBGauge();
204 QPhiX_Gauge* packed_gauge_cb1=(QPhiX_Gauge *)geom_outer->allocCBGauge();
207 QPhiX_InnerGauge* packed_gauge_cb0_inner=(QPhiX_InnerGauge *)geom_inner->allocCBGauge();
208 QPhiX_InnerGauge* packed_gauge_cb1_inner=(QPhiX_InnerGauge *)geom_inner->allocCBGauge();
211 QPhiX::qdp_pack_gauge<>(
u, packed_gauge_cb0,packed_gauge_cb1, *geom_outer);
212 u_packed[0] = packed_gauge_cb0;
213 u_packed[1] = packed_gauge_cb1;
216 QPhiX::qdp_pack_gauge<>(
u, packed_gauge_cb0_inner,packed_gauge_cb1_inner, *geom_inner);
217 u_packed_i[0] = packed_gauge_cb0_inner;
218 u_packed_i[1] = packed_gauge_cb1_inner;
221 QDPIO::cout <<
"Creating Clover Term" << std::endl;
223 clov->
create(state_, invParam.CloverParams);
224 QDPIO::cout <<
"Inverting Clover Term" << std::endl;
225 invclov->create(state_, invParam.CloverParams, (*clov));
226 for(
int cb=0;
cb < 2;
cb++) {
229 QDPIO::cout <<
"Done" << std::endl;
231 QPhiX_Clover* A_cb0=(QPhiX_Clover *)geom_outer->allocCBClov();
232 QPhiX_Clover* A_cb1=(QPhiX_Clover *)geom_outer->allocCBClov();
233 clov_packed[0] = A_cb0;
234 clov_packed[1] = A_cb1;
236 QPhiX_Clover* A_inv_cb0=(QPhiX_Clover *)geom_outer->allocCBClov();
237 QPhiX_Clover* A_inv_cb1=(QPhiX_Clover *)geom_outer->allocCBClov();
238 invclov_packed[0] = A_inv_cb0;
239 invclov_packed[1] = A_inv_cb1;
242 QPhiX_InnerClover* A_cb0_inner=(QPhiX_InnerClover *)geom_inner->allocCBClov();
243 QPhiX_InnerClover* A_cb1_inner=(QPhiX_InnerClover *)geom_inner->allocCBClov();
244 clov_packed_i[0] = A_cb0_inner;
245 clov_packed_i[1] = A_cb1_inner;
247 QPhiX_InnerClover* A_inv_cb0_inner=(QPhiX_InnerClover *)geom_inner->allocCBClov();
248 QPhiX_InnerClover* A_inv_cb1_inner=(QPhiX_InnerClover *)geom_inner->allocCBClov();
249 invclov_packed_i[0] = A_inv_cb0_inner;
250 invclov_packed_i[1] = A_inv_cb1_inner;
253 QDPIO::cout <<
"Packing Clover term..." << std::endl;
256 for(
int cb=0;
cb < 2;
cb++) {
257 QPhiX::qdp_pack_clover<>((*invclov), invclov_packed[
cb], *geom_outer,
cb);
261 for(
int cb=0;
cb < 2;
cb++) {
262 QPhiX::qdp_pack_clover<>((*clov), clov_packed[
cb], *geom_outer,
cb);
266 for(
int cb=0;
cb < 2;
cb++) {
267 QPhiX::qdp_pack_clover<>((*invclov), invclov_packed_i[
cb], *geom_inner,
cb);
271 for(
int cb=0;
cb < 2;
cb++) {
272 QPhiX::qdp_pack_clover<>((*clov), clov_packed_i[
cb], *geom_inner,
cb);
274 QDPIO::cout <<
"Done" << std::endl;
277 M_outer=
new QPhiX::EvenOddCloverOperator<REALT,
278 MixedVecTraits<REALT,InnerReal>::Vec,
279 MixedVecTraits<REALT,InnerReal>::Soa,
280 MixedVecTraits<REALT,InnerReal>::compress12>(u_packed,
285 toDouble(aniso_coeffs[0]),
286 toDouble(aniso_coeffs[3]));
288 M_inner=
new QPhiX::EvenOddCloverOperator<InnerReal,
289 MixedVecTraits<REALT,InnerReal>::VecInner,
290 MixedVecTraits<REALT,InnerReal>::SoaInner,
291 MixedVecTraits<REALT,InnerReal>::compress12>(u_packed_i,
296 toDouble(aniso_coeffs[0]),
297 toDouble(aniso_coeffs[3]));
300 bicgstab_inner_solver =
new QPhiX::InvBiCGStab<InnerReal,MixedVecTraits<REALT,InnerReal>::VecInner, MixedVecTraits<REALT,InnerReal>::SoaInner, MixedVecTraits<REALT,InnerReal>::compress12>((*M_inner), invParam.MaxIter);
302 mixed_solver =
new QPhiX::InvRichardsonMultiPrec<REALT,
303 MixedVecTraits<REALT,InnerReal>::Vec,
304 MixedVecTraits<REALT,InnerReal>::Soa,
305 MixedVecTraits<REALT,InnerReal>::compress12,
307 MixedVecTraits<REALT,InnerReal>::VecInner,
308 MixedVecTraits<REALT,InnerReal>::SoaInner,
310 MixedVecTraits<REALT,InnerReal>::compress12>((*M_outer), (*bicgstab_inner_solver), toDouble(invParam.Delta),invParam.MaxIter);
316 ~LinOpSysSolverQPhiXCloverIterRefine()
321 QDPIO::cout <<
"Destructing" << std::endl;
322 #ifndef QDP_IS_QDPJIT
323 geom_outer->free(p_even);
324 geom_outer->free(p_odd);
325 geom_outer->free(c_even);
326 geom_outer->free(c_odd);
333 geom_outer->free(invclov_packed[0]);
334 geom_outer->free(invclov_packed[1]);
335 invclov_packed[0] =
nullptr;
336 invclov_packed[1] =
nullptr;
339 geom_outer->free(clov_packed[0]);
340 geom_outer->free(clov_packed[1]);
341 clov_packed[0] =
nullptr;
342 clov_packed[1] =
nullptr;
345 geom_outer->free(u_packed[0]);
346 geom_outer->free(u_packed[1]);
347 u_packed[0] =
nullptr;
348 u_packed[1] =
nullptr;
351 geom_inner->free(invclov_packed_i[0]);
352 geom_inner->free(invclov_packed_i[1]);
353 invclov_packed_i[0] =
nullptr;
354 invclov_packed_i[1] =
nullptr;
357 geom_inner->free(clov_packed_i[0]);
358 geom_inner->free(clov_packed_i[1]);
359 clov_packed_i[0] =
nullptr;
360 clov_packed_i[1] =
nullptr;
363 geom_inner->free(u_packed_i[0]);
364 geom_inner->free(u_packed_i[1]);
365 u_packed_i[0] =
nullptr;
366 u_packed_i[1] =
nullptr;
375 const Subset& subset()
const {
return A->subset();}
388 SystemSolverResults_t res;
389 #ifndef QDP_IS_QDPJIT
390 QDPIO::cout <<
"Packing Spinors" << std::endl << std::flush ;
392 QPhiX::qdp_pack_cb_spinor<>(
psi,psi_s[1], (*M_outer).getGeometry(),1);
393 QPhiX::qdp_pack_cb_spinor<>(
chi,chi_s[1], (*M_outer).getGeometry(),1);
395 QDPIO::cout <<
"Done" << std::endl << std::flush;
397 psi_s[0] = (QPhiX_Spinor *)(
psi.getFjit());
398 psi_s[1] = (QPhiX_Spinor *)(
psi.getFjit() ) + cbsize_in_blocks;
399 chi_s[0] = (QPhiX_Spinor *)(
chi.getFjit());
400 chi_s[1] = (QPhiX_Spinor *)(
chi.getFjit() ) + cbsize_in_blocks;
403 unsigned long site_flops=0;
404 unsigned long mv_apps=0;
406 QDPIO::cout <<
"Starting solve" << std::endl << std::flush ;
407 double start = omp_get_wtime();
409 (*mixed_solver)(psi_s[1],chi_s[1], toDouble(invParam.RsdTarget), res.n_count, rsd_final, site_flops, mv_apps, my_isign,invParam.VerboseP);
410 double end = omp_get_wtime();
412 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_ITER_REFINE_SOLVER: " << res.n_count <<
" iters, rsd_sq_final=" << rsd_final << std::endl;
413 #ifndef QDP_IS_QDPJIT
414 QPhiX::qdp_unpack_cb_spinor<>(psi_s[1],
psi, (*M_outer).getGeometry(),1);
423 r[
A->subset() ] -=
tmp;
427 Double rel_resid = sqrt(r2/b2);
429 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_ITER_REFINE_SOLVER: || r || / || b || = " << rel_resid << std::endl;
432 if ( !toBool ( rel_resid < invParam.RsdTarget*invParam.RsdToleranceFactor ) ) {
433 QDPIO::cout <<
"SOLVE FAILED" << std::endl;
438 int num_cb_sites = Layout::vol()/2;
439 unsigned long total_flops = (site_flops + (1320+504+1320+504+48)*mv_apps)*num_cb_sites;
440 double gflops = (double)(total_flops)/(1.0e9);
442 double total_time = end - start;
443 QDPIO::cout <<
"QPHIX_CLOVER_BICGSTAB_ITER_REFINE_SOLVER: Solver Time="<< total_time <<
" (sec) Performance=" << gflops / total_time <<
" GFLOPS" << std::endl;
455 LinOpSysSolverQPhiXCloverIterRefine() {}
459 Handle< LinearOperator<T> >
A;
460 const SysSolverQPhiXCloverParams invParam;
461 Handle< CloverTermT<T, U> > clov;
462 Handle< CloverTermT<T, U> > invclov;
464 QPhiX::Geometry<REALT,
465 MixedVecTraits<REALT,InnerReal>::Vec,
466 MixedVecTraits<REALT,InnerReal>::Soa,
467 MixedVecTraits<REALT,InnerReal>::compress12>* geom_outer;
469 QPhiX::Geometry<InnerReal,
470 MixedVecTraits<REALT,InnerReal>::VecInner,
471 MixedVecTraits<REALT,InnerReal>::SoaInner,
472 MixedVecTraits<REALT,InnerReal>::compress12>* geom_inner;
474 Handle< QPhiX::EvenOddCloverOperator<REALT,
475 MixedVecTraits<REALT,InnerReal>::Vec,
476 MixedVecTraits<REALT,InnerReal>::Soa,
477 MixedVecTraits<REALT,InnerReal>::compress12> > M_outer;
479 Handle< QPhiX::EvenOddCloverOperator<InnerReal,
480 MixedVecTraits<REALT,InnerReal>::VecInner,
481 MixedVecTraits<REALT,InnerReal>::SoaInner,
482 MixedVecTraits<REALT,InnerReal>::compress12> > M_inner;
486 MixedVecTraits<REALT,InnerReal>::VecInner,
487 MixedVecTraits<REALT,InnerReal>::SoaInner,
488 MixedVecTraits<REALT,InnerReal>::compress12> > bicgstab_inner_solver;
490 Handle< QPhiX::InvRichardsonMultiPrec<REALT,
491 MixedVecTraits<REALT,InnerReal>::Vec,
492 MixedVecTraits<REALT,InnerReal>::Soa,
493 MixedVecTraits<REALT,InnerReal>::compress12,
495 MixedVecTraits<REALT,InnerReal>::VecInner,
496 MixedVecTraits<REALT,InnerReal>::SoaInner,
497 MixedVecTraits<REALT,InnerReal>::compress12> > mixed_solver;
499 QPhiX_Clover* invclov_packed[2];
500 QPhiX_Clover* clov_packed[2];
501 QPhiX_Gauge* u_packed[2];
503 QPhiX_InnerClover* invclov_packed_i[2];
504 QPhiX_InnerClover* clov_packed_i[2];
505 QPhiX_InnerGauge* u_packed_i[2];
507 QPhiX_Spinor* p_even;
509 QPhiX_Spinor* c_even;
511 mutable QPhiX_Spinor* psi_s[2];
512 mutable QPhiX_Spinor* chi_s[2];
513 size_t cbsize_in_blocks;
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.
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
SystemSolverResults_t InvBiCGStab(const LinearOperator< LatticeFermionF > &A, const LatticeFermionF &chi, LatticeFermionF &psi, const Real &RsdBiCGStab, int MaxBiCGStab, enum PlusMinus isign)
multi1d< LatticeFermion > chi(Ncb)
QDPCloverTermT< T, U > CloverTermT
multi1d< Real > makeFermCoeffs(const AnisoParam_t &aniso)
Make fermion coefficients.
FloatingPoint< double > Double
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.
multi1d< LatticeColorMatrix > U
multi1d< LatticeColorMatrix > Q