Пример #1
0
  void idata::set_region (int r_pvt,int r_sat, int r_eql, int r_fip)
  {
    props->set_i ("pvt_region", r_pvt);
    props->set_i ("fip_region", r_fip);
    props->set_i ("sat_region", r_sat);
    props->set_i ("eql_region", r_eql);

    // check
    if (r_pvt <= 0 || r_sat <= 0 || r_eql <= 0 || r_fip <= 0)
      {
        bs_throw_exception ("One of init parameters <= 0");
      }
    
    t_long def_val = -1;
    
    rock->init (r_pvt, def_val);
    p_ref->init (r_pvt, def_val);

    equil->resize (EQUIL_TOTAL * r_eql); //!TODO: EQUIL_TOTAL instead of 3

    pvto.resize (r_pvt);
    pvtdo.resize (r_pvt);
    pvtg.resize (r_pvt);
    pvtw.resize (r_pvt);
    
    swof.resize (r_sat);
    sgof.resize (r_sat);
    swfn.resize (r_sat);
    sgfn.resize (r_sat);
    sof2.resize (r_sat);
    sof3.resize (r_sat);
  }
Пример #2
0
bs_mesh_grdecl::bs_mesh_grdecl(const bs_mesh_grdecl& src)
    : bs_refcounter (src)
{
    // TODO: BUG:
    bs_throw_exception ("NOT IMPL YET");
    //*this = src;
}
Пример #3
0
  keyword_info_base::keyword_info_base(const keyword_info_base& src)
 : bs_refcounter (src), objbase (src)
   {
     // TODO: BUG:
     bs_throw_exception ("NOT IMPL YET");
     //*this = src;
   }
Пример #4
0
  // FIXME:
  void
  jacobian::restore_sec_solution ()
  {
    if (secondary > 0)
      {
        if (phases != matrix->get_matrix ("flux")->get_n_block_size ())
          {
            bs_throw_exception ("phases and flux block_size mismatch");
          }

        spv_long rows     = matrix->get_matrix ("flux")->get_rows_ptr ();
        t_float *sp_diag  = sp_diagonal->data ();
        t_double *sol     = solution->data ();
        t_double *sec_sol = sec_solution->data ();
        t_float *sec_rhs_ = sec_rhs->data ();

        // OPENMP
        for (t_long i = 0, cnt = (t_long)rows->size (); i < cnt - 1; ++i)
          {
            t_float *sp_block   = &sp_diag[secondary * phases * i];
            t_double *sol_block = &sol[phases * i];
            sec_sol[i]          = sec_rhs_[i];

            VV_PROD_M (phases, sp_block, sol_block, sec_sol[i]);
          }
      }
  }
Пример #5
0
 smesh_keywords::smesh_keywords(const smesh_keywords& src)
 : bs_refcounter (src), base_t (src)
 {
   // TODO: BUG:
   bs_throw_exception ("NOT IMPL YET");
   //*this = src;
 }
Пример #6
0
  void idata::set_density (spv_float density)
  {
    if ((density->size() % 3 != 0) || (density->size()<3))
      {
        bs_throw_exception ("Not enough valid arguments yet");
      }

    set_density_internal(&(*density)[0]);
  }
Пример #7
0
void mesh_base::check_data() const
{

#ifndef PURE_MESH
  if (n_elements <= 0)
    bs_throw_exception (boost::format ("n_elements = %d is out of range")% n_elements);
  if (n_active_elements <= 0)
    bs_throw_exception (boost::format ("n_active_elements = %d is out of range")% n_active_elements);

  
//   if (n_connections <= 0)
//     bs_throw_exception (boost::format ("n_connections = %d is out of range")% n_connections);
    
  if (!volumes->size ())
    bs_throw_exception ("volumes array is not initialized");
  if (!ext_to_int->size ())
    bs_throw_exception ("ext_to_int array is not initialized");
 #endif
}
Пример #8
0
    /**
    * @brief setup for CGS
    *
    * @param matrix -- input matrix
    *
    * @return 0 if success
    */
     int
    gs_solver::setup (sp_matrix_t matrix)
    {
      if (!matrix)
        {
          bs_throw_exception ("gs: Passed matrix is null");
        }

      return 0;
    }
Пример #9
0
    void
    bs_stream::add_section (int section, int level)
    {
      if (sections_.find (section) != sections_.end ())
        {
          bs_throw_exception ("Section already exists");
        }

      sections_.insert (std::make_pair (section, level));
    }
Пример #10
0
element_plane_orientation_t get_reverse_orientation (element_plane_orientation_t orient)
  {
    switch (orient)
      {
        case x_axis_plus:   return x_axis_minus;
        case x_axis_minus:  return x_axis_plus;
        case y_axis_plus:   return y_axis_minus;
        case y_axis_minus:  return y_axis_plus;
        case z_axis_plus:   return z_axis_minus;
        case z_axis_minus:  return z_axis_plus;
        default: bs_throw_exception ("Invalid orientation!");
      }
  }
Пример #11
0
  bs_channel::sp_stream_t
  bs_channel::get_stream (const std::string &name) const
  {
    for (size_t i = 0, cnt = output_streams_.size (); i < cnt; ++i)
      {
        if (output_streams_[i]->get_name () == name)
          {
            return output_streams_[i];
          }
      }

    bs_throw_exception (boost::format ("Unknown stream name %s") % name);
  }
Пример #12
0
    /**
    * @brief setup for CGS
    *
    * @param matrix -- input matrix
    *
    * @return 0 if success
    */
     int
    cgs_solver::setup (sp_matrix_t matrix)
    {
      if (!matrix)
        {
          bs_throw_exception ("CGS: Passed matrix is null");
        }

      BS_ASSERT (prop);
      if (prec)
        {
          return prec->setup (matrix);
        }

      return 0;
    }
Пример #13
0
// FIXME: in release symbol not found if inlined
//inline 
void
mesh_element3d::get_plane (element_plane_orientation_t orientation, plane_t &plane) const
{
  switch (orientation)
    {
      case x_axis_minus:  //left_cross
        plane[0] = corners[0];
        plane[1] = corners[2];
        plane[2] = corners[4];
        plane[3] = corners[6];
        break;
      case x_axis_plus:   //right_cross
        plane[0] = corners[1];
        plane[1] = corners[3];
        plane[2] = corners[5];
        plane[3] = corners[7];
        break;
      case y_axis_minus:  //top_cross
        plane[0] = corners[0];
        plane[1] = corners[1];
        plane[2] = corners[4];
        plane[3] = corners[5];
        break;
      case y_axis_plus:   //bottom_cross
        plane[0] = corners[2];
        plane[1] = corners[3];
        plane[2] = corners[6];
        plane[3] = corners[7];
        break;
      case z_axis_minus:  //lower_cross
        plane[0] = corners[0];
        plane[1] = corners[2];
        plane[2] = corners[1];
        plane[3] = corners[3];
        break;
      case z_axis_plus:   //upper_cross
        plane[0] = corners[4];
        plane[1] = corners[6];
        plane[2] = corners[5];
        plane[3] = corners[7];
        break;
      
      
      default:
        bs_throw_exception ("Invalid orientation!");;
    }
}
Пример #14
0
  // FIXME:
  void
  jacobian::summ_rhs ()
  {
    if (rhs->size () != rhs_flux->size ())
      {
        bs_throw_exception ("rhs and rhs_flux size mismatch");
      }

    t_float *rhs_ = rhs->data ();
    t_float *rhs_flux_ = rhs_flux->data ();

    // OPENMP:
    for (size_t i = 0, cnt = rhs->size (); i < cnt; ++i)
      {
        rhs_[i] += rhs_flux_[i];
      }
  }
Пример #15
0
  /**
   * \brief setup preconditioner (merge matrices if needed)
   *
   * \param matrix Various matrix
   * \return 0 if success
   */
  int
  bcsr_ilu_prec::setup (sp_matrix_t matrix)
  {
    BS_ASSERT (matrix);


    t_long n;     
    t_long nb;    
    t_long b_sqr; 
    bool ff = prop->get_b (use_internal_matrix);


    sp_bcsr_matrix_t ilu;

    if (dynamic_cast<bcsr_matrix_iface_t *> (matrix.lock ()))
      {
        ilu = matrix;
        BS_ASSERT (ilu);
      }

    if (ff)
      {
        if (!lu_matrix)
          {
            lu_matrix = BS_KERNEL.create_object (matrix->bs_resolve_type ());
            if (!lu_matrix)
              {
                bs_throw_exception ("Can not create matrix");
              }
          }
        if (lu_matrix->copy (ilu))
          {
            bs_throw_exception ("Can not make matrix copy");
          }

        n              = lu_matrix->get_n_rows ();
        nb             = lu_matrix->get_n_block_size ();
      }
    else
      {
        n              = ilu->get_n_rows ();
        nb             = ilu->get_n_block_size ();
      }

    spv_long sp_ilu_rows                    = ff ? lu_matrix->get_rows_ptr () : ilu->get_rows_ptr ();       
    spv_long sp_ilu_cols                    = ff ? lu_matrix->get_cols_ind () : ilu->get_cols_ind ();       
    spv_float  sp_ilu_values        = ff ? lu_matrix->get_values ()   : ilu->get_values (); 

    t_long *ilu_rows                          = &(*sp_ilu_rows)[0];
    t_long *ilu_cols                          = &(*sp_ilu_cols)[0];
    t_float *ilu_values               = &(*sp_ilu_values)[0];

    b_sqr          = nb * nb;

    // common
    //int r_code = 0;
    t_long i, j, j1, j2, j3, cl, k;

    t_float *block;



    //ilu.ascii_write_in_csr_format ("ilu_set_internal");

    //  ilu.write_matrix_to_file ("matrix.out");
    // ----------------------
    // STAGE 3: build ilu factorization
    t_long i_str;
    //fp_type *d_block, *dd_block;
    t_float *d_block, *dd_block;
    t_double d;
    t_long jj, jj1, jj2;

    // loop through all rows
    for (i = 0; i < n; ++i)
      {
        // update i-th row by 0..i-1 row
        j1 = ilu_rows[i];
        j2 = j1;//ilu_diag_ind[i];
        j3 = ilu_rows[i + 1];

        BS_ASSERT (j1 == j2) (j1) (j2);

        // for all nonzero elements in i-th string (in L part)
        // update it by diagonal element and update all other nonzero elements
        // in i-th string
        for (j = j1 + 1; j < j3; ++j)
          {
            // find corresponding diagonal element
            i_str = ilu_cols[j];
            if (i_str < i)
              {
                // update by diagonal element
                block   = &ilu_values[j * b_sqr];
                d_block = &ilu_values[ilu_rows[i_str]/*ilu_diag_ind[i_str]*/ * b_sqr];
                //BS_ASSERT (ilu_diag_ind[i_str] == ilu_rows[i_str]) (ilu_diag_ind[i_str]) (ilu_rows[i_str]);
                uLU_SEEK_L (nb, d_block, block, d);

                jj1 = ilu_rows[i_str];
                jj2 = ilu_rows[i_str + 1];
                k = j + 1;

                for (jj = jj1; jj < jj2; ++jj)
                  {
                    cl = ilu_cols[jj];
                    if (cl <= i_str)
                      continue;

                    if (ilu_cols[j1] == cl)
                      {
                        // upgrade by corresponding element
                        d_block   = &ilu_values[jj * b_sqr];
                        dd_block  = &ilu_values[j1 * b_sqr];
                        LU_UPGRADE(nb, block, d_block, dd_block);
                      }
                    for (; k < j3 && ilu_cols[k] < cl; ++k)
                      ;

                    if (k < j3 && ilu_cols[k] == cl)
                      {
                        // upgrade by corresponding element
                        d_block   = &ilu_values[jj * b_sqr];
                        dd_block  = &ilu_values[k * b_sqr];
                        LU_UPGRADE(nb, block, d_block, dd_block);
                      }
                    else if (k >= j3)
                      break;
                  }
              }
            else 
              break;
          }

        // factorize i-th string
        block = &ilu_values[j2 * b_sqr];
        uLU (nb, block, d);

        for (j = j1; j < j3; ++j)
          {
            t_long cl = ilu_cols[j];
            if (cl > i)
              {
                d_block = &ilu_values[j * b_sqr];
                uLU_SEEK_U (nb, block, d_block);
              }
          }
      }
    // ----------------------
    return 0;
  }
Пример #16
0
    int tfqmr_solver::solve (sp_matrix_t matrix, spv_double sp_rhs, spv_double sp_sol)
    {
      BOSOUT (section::solvers, level::debug) << "TFQMR\n" << bs_end;

      BS_ERROR (matrix, "tfqmr_solve");
      BS_ERROR (sp_rhs->size (), "tfqmr_solve");
      BS_ERROR (sp_sol->size (), "tfqmr_solve");
      BS_ERROR (prop, "tfqmr_solve");


      t_double rho_1, rho_2 = 1, alpha = 1, beta, sigma;
      int iter;
      const double epsmac = 1e-24;
      t_double r_norm, b_norm, den_norm, w_norm, eta, nu, tau, c;
      //fp_type *x = solution;

      //OMP_TIME_MEASURE_START (tfqmr_solve_timer);

      t_double *rhs = &(*sp_rhs)[0];
      t_double *sol = &(*sp_sol)[0];
      t_double tol = prop->get_f (tol_idx);
      tol *= tol;
      //resid = prop->get_residuals ();
      //convergence_rate = prop->get_convergence_rate ();

      int max_iter  = prop->get_i (max_iters_idx);
      t_long n         = matrix->get_n_rows () * matrix->get_n_block_size ();

      sp_p->resize (n);
      sp_v->resize (n);
      sp_w->resize (n);
      sp_u->resize (n);
      sp_q->resize (n);
      sp_d->resize (n);
      sp_res->resize (n);
      sp_r->resize (n);
      sp_rtilde->resize (n);
      sp_tmp->resize (n);
      sp_rhat->resize (n);
      sp_y->resize (n);
      //x_cgs = y + n;

      prop->set_b (success_idx, false);

      // solution = {0}
      sp_sol->assign (0);
      // r = {0}
      sp_r->assign (0);
       // TODO:paste
      sp_tmp->assign (0);
      sp_p->assign (0);
      sp_v->assign (0);
      sp_q->assign (0);
      sp_d->assign (0);

      t_double *r              = &(*sp_r)[0];
      t_double *p              = &(*sp_p)[0];
      t_double *v              = &(*sp_v)[0];
      t_double *w              = &(*sp_w)[0];
      t_double *u              = &(*sp_u)[0];
      t_double *q              = &(*sp_q)[0];
      t_double *d              = &(*sp_d)[0];
      t_double *res            = &(*sp_res)[0];
      t_double *rtilde         = &(*sp_rtilde)[0];
      t_double *tmp            = &(*sp_tmp)[0];
      t_double *rhat           = &(*sp_rhat)[0];
      t_double *y              = &(*sp_y)[0];

      // r = Ax0 - b
      matrix->calc_lin_comb (-1.0, 1.0, sp_sol, sp_rhs, sp_r);
      memcpy (rtilde, r, sizeof (t_double) * n);
      //rtilde.assign (r.begin (), r.end ());

      // p0 = u0 = r0;
      //memcpy (p, r, n * sizeof (double));
      memcpy (u, r, sizeof (t_double) * n);
      memcpy (p, r, sizeof (t_double) * n);
      memcpy (w, r, sizeof (t_double) * n);
      //u.assign (r.begin (), r.end ());
      //p.assign (r.begin (), r.end ());
      //w.assign (r.begin (), r.end ());

      // tmp = M^(-1) * u;
      if (prec)
        {
          if (prec->solve_prec (matrix, sp_u, sp_tmp))
            {
              bs_throw_exception ("TFQMR: Preconditioner failed");
            }
              memcpy (u, tmp, sizeof (t_double) * n);
              memcpy (p, tmp, sizeof (t_double) * n);
	      //u.assign (tmp.begin (), tmp.end ());
	      //p.assign (u.begin (), u.end ());
        }

      matrix->matrix_vector_product (sp_p, sp_v);

      //tools::save_seq_vector (tools::string_formater ("1_well_bhp.%s.txt", it->first).str).save (it->second);

      r_norm = mv_vector_inner_product_n (r, r, n);


      if (r_norm <= tol) // initial guess quite good
        return 0;

      tau = sqrt (r_norm);
      rho_1 = r_norm;
      rho_2 = r_norm;
      b_norm = sqrt (mv_vector_inner_product_n (rhs, rhs, n));


      if (b_norm > epsmac) // choose convergence criterion
        {
          // |r_i|/|b| <= eps if |b| > 0
          tol *= b_norm;
          den_norm = b_norm;
        }
      else // (r_norm > epsmac)
        {
          // |r_i|/|r0| <= eps if |b| = 0
          tol *= r_norm;
          den_norm = r_norm;
        }

      // set up initial norm and convergense factor
      //prop->set_relative_factor (den_norm);

      int m, count;
      // main loop
      for (iter = 0; iter < max_iter; ++iter)
        {
          //printf ("TFQMR iteration: %d, resid = %le\n", iter, r_norm);
          //fflush (stdout);
          // TODO: paste
          if (iter)
            {
             //rho_1 = mv_vector_inner_product (r, rtilde, n);//in first iter equals to r_norm
              if (rho_1 == 0) // failure
                {
                  if (den_norm > epsmac)
                    prop->set_f (final_res_idx, r_norm / den_norm);
                  else
                    prop->set_f (final_res_idx, r_norm);
                  
                  bs_throw_exception ("TFQMR: Failure - rho_1 == 0");
                }
               sum_vector_n (u, (t_double)1., res, beta, p, n); //p[n] = u[n]+beta*res

               //v.assign (n, 0);
               memset (v, 0, sizeof (t_double) * n);
               matrix->matrix_vector_product (sp_p, sp_v); //v[n]=Ap[n]
             }

           sigma = mv_vector_inner_product_n (rtilde, v, n); //sigma=(rtilde,v[n-1])

           alpha = rho_1/sigma;

           // tmp = M^(-1)*v
           if (prec)
             {
               if (prec->solve_prec (matrix, sp_v, sp_tmp))
                {
                  bs_throw_exception ("TFQMR: Preconditioner failed");
                }
                   memcpy (v, tmp, sizeof (t_double) * n);
	           //v.assign (tmp.begin (), tmp.end ());
             }

           sum_vector_n (u, (t_double)1., v, -alpha, q, n); //q[n] = u[n-1]-alpha*v[n-1]
           sum_vector_n (u, (t_double)1., q, (t_double)1., res, n); //res = u[n-1]+q[n]

           //tmp.assign (n, 0);
           memset (tmp, 0, sizeof (t_double) * n);
           matrix->matrix_vector_product (sp_res, sp_tmp);// tmp=A*res
           sum_vector_n (r, (t_double)1., tmp, -alpha, r, n);// r=r-alpha*res

           //r_norm_old = r_norm;
           r_norm = mv_vector_inner_product_n (r, r, n);

           for (m = 1; m <= 2 ; m++)
             {
               if (m == 1) // m is odd
                 {
                   memcpy (y, u, sizeof (t_double) * n);
                   //y.assign (u.begin (), u.end ());
                   w_norm = sqrt(r_norm * r_norm);
                 }
               else // m is even
                 {
                   memcpy (y, q, sizeof (t_double) * n);
                   //y.assign (q.begin (), q.end ());
                   w_norm = sqrt(r_norm);
                 }

               sum_vector_n (y, (t_double)1., d, eta*nu*nu/alpha, d, n); //d[m] = y[m] + (eta[m-1]*nu[m-1]^2/alpha[n-1])*d[m-1]
               nu = w_norm/tau; //nu[m]=||w[m+1]||/tau[m-1]
               c = 1./sqrt (1. + nu*nu);
               tau = tau*c*nu; //tau[m]=tau[m-1]nu[m]c[m]
               eta = c*c*alpha; //eta[m]=c[m]^2*alpha[n-1]
               //SUM_VECTOR(x,d,1,alpha,x_cgs,k,n); //x_cgs[n] = x[2n-1]+alpha[n-1]*d[2n]
               sum_vector_n (sol, (t_double)1., d, eta, sol, n); //x[m] = x[m-1]+eta[m]*d[m]
               if (r_norm <= tol)
                 {
                   count = 1;
                   break;
                 }
             }

           if (r_norm <= tol)
             break;

           rho_1 = mv_vector_inner_product_n (r, rtilde, n);//in first iter equals to r_norm
           beta = rho_1 / rho_2;

           // rhat = M^(-1) * r;
           if (prec)
             {
               if (prec->solve_prec (matrix, sp_r, sp_rhat))
                {
                  bs_throw_exception ("TFQMR: Preconditioner failed");
                }
             }
           else // no precondition (preconditioner=identity_matrix)
             {
               memcpy (rhat, r, sizeof (t_double) * n);
               //rhat.assign (r.begin (), r.end ());
             }

          sum_vector_n (rhat, (t_double)1., q, beta, u, n); //u[n] = r[n]+beta*q[n]
          sum_vector_n (q, (t_double)1., p, beta, res, n); //res = q[n]+beta*p[n-1]

          rho_2 = rho_1;
     }

     //TODO: end
     prop->set_i (iters_idx, iter + 1);
     prop->set_b (success_idx, true);

      /*
      //additional checking convergence
      mv_calc_lin_comb (matrix, -1.0, 1.0, solution, rhs, r);
      r_norm = mv_vector_inner_product (r, r, n);
      */
      if (den_norm > epsmac)
        prop->set_f (final_res_idx, r_norm / den_norm);
      else
        prop->set_f (final_res_idx, r_norm);

      //printf ("TFQMR OK! iters = %d, resid = %le\n", lprop->iters, lprop->final_resid);
      //OMP_TIME_MEASURE_END (tfqmr_solve_timer);

      return 0;
    }
Пример #17
0
    int cgs_solver::solve (sp_matrix_t matrix, spv_double sp_rhs, spv_double sp_sol)
    {
#ifdef _DEBUG
      BOSOUT (section::solvers, level::debug) << "CGS\n" << bs_end;
#endif
      BS_ERROR (sp_rhs->size (), "cgs_solve");
      BS_ERROR (sp_sol->size (), "cgs_solve");
      BS_ERROR (prop, "cgs_solve");

      t_double rho_1, rho_2 = 1, alpha = 1, beta, sigma;
      int iter;
      const double epsmac = 1e-24;
      t_double r_norm, b_norm, den_norm;
      //fp_type *x = solution;
      t_double *rhs = &(*sp_rhs)[0];
      t_double *sol = &(*sp_sol)[0];

      const t_double one = 1.0;
      //OMP_TIME_MEASURE_START (cgs_solve_timer);

      t_double tol = prop->get_f (tol_idx);
      tol *= tol;
      //resid = prop->get_residuals ();
      //convergence_rate = prop->get_convergence_rate ();

      int max_iter  = prop->get_i (max_iters_idx);
      t_long n    = matrix->get_n_rows () * matrix->get_n_block_size ();
      BS_ASSERT (n == (t_long)sp_sol->size ());
      
      t_double *p               = &(*sp_p)[0];
      t_double *phat            = &(*sp_phat)[0];
      t_double *v               = &(*sp_v)[0];
      t_double *tmp             = &(*sp_tmp)[0];
      t_double *q               = &(*sp_q)[0];
      t_double *u               = &(*sp_u)[0];
      t_double *d               = &(*sp_d)[0];
      t_double *dhat            = &(*sp_dhat)[0];
      t_double *r               = &(*sp_r)[0];
      t_double *rtilde          = &(*sp_rtilde)[0];
      //t_double *r_old           = &(*sp_r_old)[0];

      prop->set_b (success_idx, false);

      // solution = {0}
      //assign (solution, n, 0);
      memset (sol, 0, sizeof (t_double) * n);
      //solution.assign (n, 0);

      sp_p->resize (n);
      sp_phat->resize (n);
      sp_v->resize (n);
      sp_tmp->resize (n);
      sp_q->resize (n);
      sp_u->resize (n);
      sp_d->resize (n);
      sp_dhat->resize (n);
      sp_r->resize (n);
      sp_rtilde->resize (n);
      sp_r_old->resize (n);

      // r = {0}
      //r.assign (n, 0);
      memset (r, 0, sizeof (t_double) * n);
      memset (tmp, 0, sizeof (t_double) * n);
      memset (p, 0, sizeof (t_double) * n);
      memset (v, 0, sizeof (t_double) * n);
      memset (q, 0, sizeof (t_double) * n);

      
       // TODO:paste
      //tmp.assign (n, 0);
      //p.assign (n, 0);
      //v.assign (n, 0);
      //q.assign (n, 0);

      // p0 = u0 = r0;
      //u.assign (r.begin (), r.end ());
      memcpy (u, r, sizeof (t_double) * n);
      // TODO:end

      // r = Ax0 - b
      matrix->calc_lin_comb (-1.0, 1.0, sp_sol, sp_rhs, sp_r);
      //rtilde.assign (r.begin (), r.end ());
      memcpy (rtilde, r, sizeof (t_double) * n);

      //tools::save_seq_vector (tools::string_formater ("1_well_bhp.%s.txt", it->first).str).save (it->second);

      r_norm = mv_vector_inner_product_n (r, r, n);

      if (r_norm <= tol) // initial guess quite good
        return 0;

      rho_1 = r_norm;
      b_norm = sqrt (mv_vector_inner_product_n (rhs, rhs, n));

      // TODO:delete
      //p.assign      (r.begin (), r.end ());
      //rtilde.assign (r.begin (), r.end ());
      //v.assign      (n, 0);
      // TODO:end

      if (b_norm > epsmac) // choose convergence criterion
        {
          // |r_i|/|b| <= eps if |b| > 0
          tol *= b_norm;
          den_norm = b_norm;
        }
      else // (r_norm > epsmac)
        {
          // |r_i|/|r0| <= eps if |b| = 0
          tol *= r_norm;
          den_norm = r_norm;
        }

      // set up initial norm and convergense factor
      //prop->set_relative_factor (den_norm);

      // main loop
      for (iter = 0; iter < max_iter; ++iter)
        {
          //printf ("CGS iteration: %d, resid = %le\n", iter, r_norm);
          //fflush (stdout);
          // TODO: paste
          if (iter)
            {
              //rho_1 = (r,rtilde)
              rho_1 = mv_vector_inner_product_n (r, rtilde, n); //in first iter equals to r_norm
              if (rho_1 == 0) // failure
                {
                  if (den_norm > epsmac)
                    prop->set_f (final_res_idx, r_norm / den_norm);
                  else
                    prop->set_f (final_res_idx, r_norm);
                  bs_throw_exception ("CGS: Failure - rho_1 == 0");
                }
            }

           beta = rho_1/rho_2; // beta = rho_n/rho_n-1
           rho_2 = rho_1;

           // u = r + beta*q
           sum_vector_n (r, one, q, beta, u, n);
           // tmp = q+beta*p_old
           sum_vector_n (q, one, p, beta, tmp, n);
           // p_new = u + beta*tmp
           sum_vector_n (u, one, tmp, beta, p, n);

           //temp_p.assign (p.begin (), p.end ());
           if (prec)
             {
               if (prec->solve_prec (matrix, sp_p, sp_phat))
                 {
                   bs_throw_exception ("CGS: Preconditioner failed");
                 }
             }
           else // no precondition (preconditioner=identity_matrix)
             {
               memcpy (phat, p, sizeof (t_double) * n);
               //phat.assign (p.begin (), p.end ());
             }

          // v = A * phat = A * p, if no precondition;
          //v.assign (n, 0);
          memset (v, 0, sizeof (t_double) * n);

          matrix->matrix_vector_product (sp_phat, sp_v);
          // sigma = (v,rtilde)
          sigma = mv_vector_inner_product_n (rtilde, v, n);

          if (sigma > epsmac || sigma < -epsmac)
          // alpha = rho_1/sigma
            alpha = rho_1 / sigma;
          else // failure
            {
              if (den_norm > epsmac)
                prop->set_f (final_res_idx, r_norm / den_norm);
              else
                prop->set_f (final_res_idx, r_norm);
              bs_throw_exception ("CGS: Failure - sigma == 0");
            }

          // q = u - alpha*v
          sum_vector_n (u, one, v, -alpha, q, n);
          // d = u + q
          sum_vector_n (u, one, q, one, d, n);

          // dhat = M^(-1) * d;
          //temp_d.assign (d.begin (), d.end ());
          if (prec)
            {
              if(prec->solve_prec (matrix, sp_d, sp_dhat))
                {
                  bs_throw_exception ("CGS: Preconditioner failed");
                }
            }
          else // no precondition (preconditioner=identity_matrix)
            {
              //dhat.assign (d.begin (), d.end ());
              memcpy (dhat, d, sizeof (t_double) * n);
            }

          //tmp.assign (n, 0);
          memset (tmp, 0, sizeof (t_double) * n);
          // tmp = A*d
          matrix->matrix_vector_product (sp_dhat, sp_tmp);

          // r = r - alpha*tmp
          sum_vector_n (r, one, tmp, -alpha, r, n);
          // x = x + alpha*dhat
          sum_vector_n (sol, one, dhat, alpha, sol, n);

          r_norm = mv_vector_inner_product_n (r, r, n);


          if (r_norm <= tol) // && check_resid_for_matbalance (n_rows, nb, r, matb_tol))
            break;
     }

     //tools::save_seq_vector ("solution.txt").save(solution);

     //TODO: end
     prop->set_i (iters_idx, iter + 1);
     prop->set_b (success_idx, true);

      /*
      //additional checking convergence
      mv_calc_lin_comb (matrix, -1.0, 1.0, solution, rhs, r);
      r_norm = mv_vector_inner_product (r, r, n);
      */
      if (den_norm > epsmac)
        prop->set_f (final_res_idx, r_norm / den_norm);
      else
        prop->set_f (final_res_idx, r_norm);

      //printf ("CGS OK! iters = %d, resid = %le\n", lprop->iters, lprop->final_resid);
      //OMP_TIME_MEASURE_END (bicgstab_solve_timer);

      return 0;
    }