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);
    }
Exemplo n.º 2
0
//------------------------------------------------------------------
// 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;
}
Exemplo n.º 3
0
//----------------------------------------------------------------------
// 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;
}