void ImplicitEulerScheme::step(array_type& a, Time t) { QL_REQUIRE(t-dt_ > -1e-8, "a step towards negative time given"); map_->setTime(std::max(0.0, t-dt_), t); bcSet_.setTime(std::max(0.0, t-dt_)); bcSet_.applyBeforeSolving(*map_, a); a = BiCGstab( boost::function<Disposable<Array>(const Array&)>( boost::bind(&ImplicitEulerScheme::apply, this, _1)), 10*a.size(), relTol_, boost::function<Disposable<Array>(const Array&)>( boost::bind(&FdmLinearOpComposite::preconditioner, map_, _1, -dt_)) ).solve(a).x; bcSet_.applyAfterSolving(a); }
//------------------------------------------------------------------ // int MatInv(Vector *out, Vector *in, // Float *true_res, PreserveType prs_in); // The inverse of the unconditioned Dirac Operator // using Conjugate gradient. // If true_res !=0 the value of the true residual is returned // in true_res. // *true_res = |src - MatPcDagMatPc * sol| / |src| // prs_in is used to specify if the source // in should be preserved or not. If not the memory usage // is less by half the size of a fermion vector. // The function returns the total number of CG iterations. //------------------------------------------------------------------ int DiracOpWilson::MatInv(Vector *out, Vector *in, Float *true_res, PreserveType prs_in) { char *fname = "MatInv(V*,V*,F*)"; VRB.Func(cname,fname); Vector *temp2; int temp_size = GJP.VolNodeSites() * lat.FsiteSize() / 2; // check out if converted //for (int ii = 0; ii < 2 * temp_size; ii++) { // VRB.Result(cname, fname, "in[%d] = %e\n", ii, // *((Float *)in + ii)); // VRB.Result(cname, fname, "out[%d] = %e\n", ii, // *((Float *)out + ii)); //} Vector *temp = (Vector *) smalloc(temp_size * sizeof(Float)); if (temp == 0) ERR.Pointer(cname, fname, "temp"); VRB.Smalloc(cname,fname, "temp", temp, temp_size * sizeof(Float)); if(prs_in == PRESERVE_YES){ temp2 = (Vector *) smalloc(2*temp_size * sizeof(Float)); if (temp2 == 0) ERR.Pointer(cname, fname, "temp2"); VRB.Smalloc(cname,fname, "temp2", temp2, temp_size * sizeof(Float)); } // save source if(prs_in == PRESERVE_YES){ moveMem((Float *)temp2, (Float *)in, 2*temp_size*sizeof(Float)); } #if 0 { printf("in(before)=\n"); IFloat *temp_p = (IFloat *)in; for(int ii = 0; ii< GJP.VolNodeSites();ii++){ for(int jj = 0; jj< lat.FsiteSize();jj++){ if (fabs(*temp_p)>1e-7){ printf("i=%d j=%d\n",ii,jj); printf("%e\n",*(temp_p)); } temp_p++; } } } #endif // points to the even part of fermion source Vector *even_in = (Vector *) ( (Float *) in + temp_size ); // points to the even part of fermion solution Vector *even_out = (Vector *) ( (Float *) out + temp_size ); Dslash(temp, even_in, CHKB_EVEN, DAG_NO); fTimesV1PlusV2((Float *)temp, (Float) kappa, (Float *)temp, (Float *)in, temp_size); #if 0 { printf("temp(before)=\n"); IFloat *temp_p = (IFloat *)temp; for(int ii = 0; ii< GJP.VolNodeSites();ii++){ for(int jj = 0; jj< lat.FsiteSize();jj++){ if (fabs(*temp_p)>1e-7){ printf("i=%d j=%d\n",ii,jj); printf("%e\n",*(temp_p)); } temp_p++; } } } #endif int iter; switch (dirac_arg->Inverter) { case CG: MatPcDag(in, temp); iter = InvCg(out,in,true_res); break; case BICGSTAB: iter = BiCGstab(out,temp,0.0,dirac_arg->bicgstab_n,true_res); break; default: ERR.General(cname,fname,"InverterType %d not implemented\n", dirac_arg->Inverter); } Dslash(temp, out, CHKB_ODD, DAG_NO); fTimesV1PlusV2((Float *)even_out, (Float) kappa, (Float *)temp, (Float *) even_in, temp_size); VRB.Sfree(cname, fname, "temp", temp); sfree(temp); // restore source if(prs_in == PRESERVE_YES){ moveMem((Float *)in, (Float *)temp2, 2*temp_size*sizeof(Float)); } #if 0 { printf("in(after)=\n"); IFloat *temp_p = (IFloat *)in; for(int ii = 0; ii< GJP.VolNodeSites();ii++){ for(int jj = 0; jj< lat.FsiteSize();jj++){ if (fabs(*temp_p)>1e-7){ printf("i=%d j=%d\n",ii,jj); printf("%e\n",*(temp_p)); } temp_p++; } } } #endif #if 0 { printf("temp2(after)=\n"); IFloat *temp_p = (IFloat *)temp2; for(int ii = 0; ii< GJP.VolNodeSites();ii++){ for(int jj = 0; jj< lat.FsiteSize();jj++){ if (fabs(*temp_p)>1e-7){ printf("i=%d j=%d\n",ii,jj); printf("%e\n",*(temp_p)); } temp_p++; } } } #endif if(prs_in == PRESERVE_YES){ VRB.Sfree(cname, fname, "temp2", temp2); sfree(temp2); } return iter; }
//---------------------------------------------------------------------- // int MatInv(Vector *out, Vector *in, Float *true_res); //---------------------------------------------------------------------- // Purpose: // calculates out where A * out = in // Arguments: // A: the fermion matrix (Dirac operator) with no preconditioning. // in: the fermion field source vector, defined on the whole lattice. // unchanged on return. // out: the initial guess, defined on the whole lattice. // on return is the solution. // true_res: if not 0, // on return holds the value of the true residual of the CG. // *true_res = |src - MatPcDagMatPc * sol| / |src| // return: // the total number of CG iterations. // Algorithm: // i. The preconditioned matrix is inverted with // i.1: on the odd checkerboard: the conjugate gradient // i.2: on the even checkerboard: explicit inversion of // those local and hermitian // clover matrices. // ii. steps: (no extra storage required) // 1. out_even0 = Aee^inv in_even // 2. out_odd = (MatPcDagMatPc)^inv MatPcDag // (kappa Doe out_even0 + in_odd) // 3. out_even = Aee^inv (kappa Deo out_odd + in_even) //---------------------------------------------------------------------- int DiracOpClover::MatInv(Vector *out, Vector *in, Float *true_res, PreserveType prs_in) { char *fname = "MatInv(V*,V*,F*)"; VRB.Func(cname,fname); // Initializations //-------------------------------------------------------------------- int half_sites = GJP.VolNodeSites()/2; int vec_size = lat.FsiteSize() * half_sites; IFloat *in_even = (IFloat *)in + vec_size; IFloat *out_even = (IFloat *)out+ vec_size; IFloat *A_even = (IFloat *)lat.Aux0Ptr(); // out_even = out_even0 = Aee^inv even_in //-------------------------------------------------------------------- clover_mat_mlt(out_even, A_even, in_even, half_sites); // use clover_lib_arg->frm_buf1 as local buffer //-------------------------------------------------------------------- Vector *frm_buf1 = (Vector *)(clover_lib_arg->frm_buf1); Wilson* wilson_p = clover_lib_arg->wilson_p; // frm_buf1 = kappe Doe out_even0 + in_odd //-------------------------------------------------------------------- wilson_dslash((IFloat *)frm_buf1, (IFloat *)gauge_field, (IFloat *)out_even, 0, 0, wilson_p); // frm_buf1 = Doe out_even0 fTimesV1PlusV2((IFloat *)frm_buf1, kappa, (const IFloat *)frm_buf1, (const IFloat *)in, vec_size); int iter; switch (dirac_arg->Inverter) { case CG: // out_even = MatPcDag [kappe * Doe out_even0 + in_odd] MatPcDag((Vector *)out_even, frm_buf1); // out_odd = (MatPcDagMatPc)^inv MatPcDag // [kappe * Doe out_even0 + in_odd] done! iter = InvCg(out, (Vector *)out_even, true_res); break; case BICGSTAB: iter = BiCGstab(out,frm_buf1,0.0,dirac_arg->bicgstab_n,true_res); break; default: ERR.General(cname,fname,"InverterType %d not implemented\n", dirac_arg->Inverter); } // frm_buf1 = kappa Deo out_odd + in_even //-------------------------------------------------------------------- wilson_dslash((IFloat *)out_even, (IFloat *)gauge_field, (IFloat *)out, 1, 0, wilson_p); // out_even = Deo out_odd fTimesV1PlusV2((IFloat *)frm_buf1, kappa, (const IFloat *)out_even, (const IFloat *)in_even, vec_size); // out_even = Aee^inv (kappa Deo out_odd + in_even) done! //-------------------------------------------------------------------- clover_mat_mlt((IFloat *)out_even, A_even, (const IFloat*)frm_buf1, half_sites); VRB.FuncEnd(cname,fname); return iter; }