Ejemplo n.º 1
0
unsigned long CSysSolve::BCGSTAB_LinSolver(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
                                 CPreconditioner & precond, su2double tol, unsigned long m, su2double *residual, bool monitoring) {
	
  int rank = 0;
#ifdef HAVE_MPI
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
#endif
  
  /*--- Check the subspace size ---*/
  
  if (m < 1) {
    if (rank == MASTER_NODE) cerr << "CSysSolve::BCGSTAB: illegal value for subspace size, m = " << m << endl;
#ifndef HAVE_MPI
    exit(EXIT_FAILURE);
#else
	MPI_Abort(MPI_COMM_WORLD,1);
    MPI_Finalize();
#endif
  }
	
  CSysVector r(b);
  CSysVector r_0(b);
  CSysVector p(b);
	CSysVector v(b);
  CSysVector s(b);
	CSysVector t(b);
	CSysVector phat(b);
	CSysVector shat(b);
  CSysVector A_x(b);
  
  /*--- Calculate the initial residual, compute norm, and check if system is already solved ---*/
  
	mat_vec(x, A_x);
  r -= A_x; r_0 = r; // recall, r holds b initially
  su2double norm_r = r.norm();
  su2double norm0 = b.norm();
  if ( (norm_r < tol*norm0) || (norm_r < eps) ) {
    if (rank == MASTER_NODE) cout << "CSysSolve::BCGSTAB(): system solved by initial guess." << endl;
    return 0;
  }
	
	/*--- Initialization ---*/
  
  su2double alpha = 1.0, beta = 1.0, omega = 1.0, rho = 1.0, rho_prime = 1.0;
	
  /*--- Set the norm to the initial initial residual value ---*/
  
  norm0 = norm_r;
  
  /*--- Output header information including initial residual ---*/
  
  int i = 0;
  if ((monitoring) && (rank == MASTER_NODE)) {
    WriteHeader("BCGSTAB", tol, norm_r);
    WriteHistory(i, norm_r, norm0);
  }
	
  /*---  Loop over all search directions ---*/
  
  for (i = 0; i < (int)m; i++) {
		
		/*--- Compute rho_prime ---*/
    
		rho_prime = rho;
		
		/*--- Compute rho_i ---*/
    
		rho = dotProd(r, r_0);
		
		/*--- Compute beta ---*/
    
		beta = (rho / rho_prime) * (alpha /omega);
		
		/*--- p_{i} = r_{i-1} + beta * p_{i-1} - beta * omega * v_{i-1} ---*/
    
		su2double beta_omega = -beta*omega;
		p.Equals_AX_Plus_BY(beta, p, beta_omega, v);
		p.Plus_AX(1.0, r);
		
		/*--- Preconditioning step ---*/
    
		precond(p, phat);
		mat_vec(phat, v);

		/*--- Calculate step-length alpha ---*/
    
    su2double r_0_v = dotProd(r_0, v);
    alpha = rho / r_0_v;
    
		/*--- s_{i} = r_{i-1} - alpha * v_{i} ---*/
    
		s.Equals_AX_Plus_BY(1.0, r, -alpha, v);
		
		/*--- Preconditioning step ---*/
    
		precond(s, shat);
		mat_vec(shat, t);
    
		/*--- Calculate step-length omega ---*/
    
    omega = dotProd(t, s) / dotProd(t, t);
    
		/*--- Update solution and residual: ---*/
    
    x.Plus_AX(alpha, phat); x.Plus_AX(omega, shat);
		r.Equals_AX_Plus_BY(1.0, s, -omega, t);
    
    /*--- Check if solution has converged, else output the relative residual if necessary ---*/
    
    norm_r = r.norm();
    if (norm_r < tol*norm0) break;
    if (((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 50 == 0) && (rank == MASTER_NODE)) WriteHistory(i+1, norm_r, norm0);
    
  }
	  
  if ((monitoring) && (rank == MASTER_NODE)) {
    cout << "# BCGSTAB final (true) residual:" << endl;
    cout << "# Iteration = " << i << ": |res|/|res0| = "  << norm_r/norm0 << ".\n" << endl;
  }
	
//  /*--- Recalculate final residual (this should be optional) ---*/
//	mat_vec(x, A_x);
//  r = b; r -= A_x;
//  su2double true_res = r.norm();
//  
//  if ((fabs(true_res - norm_r) > tol*10.0) && (rank == MASTER_NODE)) {
//    cout << "# WARNING in CSysSolve::BCGSTAB(): " << endl;
//    cout << "# true residual norm and calculated residual norm do not agree." << endl;
//    cout << "# true_res - calc_res = " << true_res <<" "<< norm_r << endl;
//  }
	
  (*residual) = norm_r;
	return i;
}
Ejemplo n.º 2
0
void CSysSolve::MultiGrid_LinSolver(CSysMatrix **Jacobian, CSysVector **LinSysRes, CSysVector **LinSysSol, CMatrixVectorProduct & mat_vec, CGeometry **geometry, CConfig *config, unsigned short iMesh, unsigned short mu, double tol, unsigned long m, bool monitoring) {
  
  CSysVector A_x(*LinSysRes[iMesh]);
  CSysVector ResAux(*LinSysRes[iMesh]);
  CSysVector SolAux(*LinSysSol[iMesh]);
  
  unsigned short Smoother = config->GetKind_Linear_Solver_Prec();
  
  /*--- Smooth the solution in the fine grid Jac_h Sol_h = Res_h, because 
   the implementation (assumes that the initial guess is 0)... it is only possible 
   to perform one smoothing ---*/
  
  switch (Smoother) {
    case LU_SGS:
      Jacobian[iMesh]->ComputeLU_SGSPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config);
      break;
    case JACOBI:
      Jacobian[iMesh]->BuildJacobiPreconditioner();
      Jacobian[iMesh]->ComputeJacobiPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config);
      break;
    case ILU:
      Jacobian[iMesh]->BuildILUPreconditioner();
      Jacobian[iMesh]->ComputeILUPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config);
      break;
    case LINELET:
      Jacobian[iMesh]->BuildJacobiPreconditioner();
      Jacobian[iMesh]->ComputeLineletPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config);
      break;
  }
  
  if (iMesh < config->GetMGLevels()) {
    
    /*--- Compute the residual in the finesh grid ResAux_h = Jac_h.Sol_h - Res_h ---*/
    
    Jacobian[iMesh]->MatrixVectorProduct(*LinSysSol[iMesh], A_x, geometry[iMesh], config);
    
    ResAux -= A_x;
    
    /*--- Restrict the residual to the coarse grid Res_H = I^H_h.ResAux_h ---*/
    
    SetRestricted_Residual(&ResAux, LinSysRes[iMesh+1], geometry[iMesh+1], config);
    
    /*--- Recursive call to MultiGrid_Cycle ---*/
    
    for (unsigned short imu = 0; imu <= mu; imu++) {
      if (iMesh == config->GetMGLevels()-2)
        MultiGrid_LinSolver(Jacobian, LinSysRes, LinSysSol, mat_vec, geometry, config, iMesh+1, 0, tol, m, monitoring);
      else MultiGrid_LinSolver(Jacobian, LinSysRes, LinSysSol, mat_vec, geometry, config, iMesh+1, mu, tol, m, monitoring);
    }
    
    /*--- Prolongate solution to the fine grid solution SolAux_h = I^h_H.Sol_H ---*/
    
    SetProlongated_Solution(&SolAux, LinSysSol[iMesh+1], geometry[iMesh+1], config);

    /*--- Update the fine grid solution Sol_h += SolAux_h ---*/
    
    *LinSysSol[iMesh] += config->GetDamp_Correc_Prolong()*SolAux;
    
  }
 
}