예제 #1
0
unsigned long CSysSolve::FGMRES_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::FGMRES: illegal value for subspace size, m = " << m << endl;
#ifndef HAVE_MPI
    exit(EXIT_FAILURE);
#else
	MPI_Abort(MPI_COMM_WORLD,1);
    MPI_Finalize();
#endif
  }

  /*---  Check the subspace size ---*/
  
  if (m > 1000) {
    if (rank == MASTER_NODE) cerr << "CSysSolve::FGMRES: illegal value for subspace size (too high), m = " << m << endl;
#ifndef HAVE_MPI
    exit(EXIT_FAILURE);
#else
	MPI_Abort(MPI_COMM_WORLD,1);
    MPI_Finalize();
#endif
  }
  
  /*---  Define various arrays
	 Note: elements in w and z are initialized to x to avoid creating
	 a temporary CSysVector object for the copy constructor ---*/
  
  vector<CSysVector> w(m+1, x);
  vector<CSysVector> z(m+1, x);
  vector<su2double> g(m+1, 0.0);
  vector<su2double> sn(m+1, 0.0);
  vector<su2double> cs(m+1, 0.0);
  vector<su2double> y(m, 0.0);
  vector<vector<su2double> > H(m+1, vector<su2double>(m, 0.0));
  
  /*---  Calculate the norm of the rhs vector ---*/
  
  su2double norm0 = b.norm();
  
  /*---  Calculate the initial residual (actually the negative residual)
	 and compute its norm ---*/
  
  mat_vec(x, w[0]);
  w[0] -= b;
  
  su2double beta = w[0].norm();
  
  if ( (beta < tol*norm0) || (beta < eps) ) {
    
    /*---  System is already solved ---*/
    
    if (rank == MASTER_NODE) cout << "CSysSolve::FGMRES(): system solved by initial guess." << endl;
    return 0;
  }
  
  /*---  Normalize residual to get w_{0} (the negative sign is because w[0]
	 holds the negative residual, as mentioned above) ---*/
  
  w[0] /= -beta;
  
  /*---  Initialize the RHS of the reduced system ---*/
  
  g[0] = beta;
  
  /*--- Set the norm to the initial residual value ---*/
  
  norm0 = beta;

  /*---  Output header information including initial residual ---*/
  
  int i = 0;
  if ((monitoring) && (rank == MASTER_NODE)) {
    WriteHeader("FGMRES", tol, beta);
    WriteHistory(i, beta, norm0);
  }
  
  /*---  Loop over all search directions ---*/
  
  for (i = 0; i < (int)m; i++) {
    
    /*---  Check if solution has converged ---*/
    
    if (beta < tol*norm0) break;
    
    /*---  Precondition the CSysVector w[i] and store result in z[i] ---*/
    
    precond(w[i], z[i]);
    
    /*---  Add to Krylov subspace ---*/
    
    mat_vec(z[i], w[i+1]);
    
    /*---  Modified Gram-Schmidt orthogonalization ---*/
    
    ModGramSchmidt(i, H, w);
    
    /*---  Apply old Givens rotations to new column of the Hessenberg matrix
		 then generate the new Givens rotation matrix and apply it to
		 the last two elements of H[:][i] and g ---*/
    
    for (int k = 0; k < i; k++)
      ApplyGivens(sn[k], cs[k], H[k][i], H[k+1][i]);
    GenerateGivens(H[i][i], H[i+1][i], sn[i], cs[i]);
    ApplyGivens(sn[i], cs[i], g[i], g[i+1]);
    
    /*---  Set L2 norm of residual and check if solution has converged ---*/
    
    beta = fabs(g[i+1]);
    
    /*---  Output the relative residual if necessary ---*/
    
    if ((((monitoring) && (rank == MASTER_NODE)) && ((i+1) % 50 == 0)) && (rank == MASTER_NODE)) WriteHistory(i+1, beta, norm0);
    
  }

  /*---  Solve the least-squares system and update solution ---*/
  
  SolveReduced(i, H, g, y);
  for (int k = 0; k < i; k++) {
    x.Plus_AX(y[k], z[k]);
  }
  
  if ((monitoring) && (rank == MASTER_NODE)) {
    cout << "# FGMRES final (true) residual:" << endl;
    cout << "# Iteration = " << i << ": |res|/|res0| = " << beta/norm0 << ".\n" << endl;
  }
  
//  /*---  Recalculate final (neg.) residual (this should be optional) ---*/
//  mat_vec(x, w[0]);
//  w[0] -= b;
//  su2double res = w[0].norm();
//
//  if (fabs(res - beta) > tol*10) {
//    if (rank == MASTER_NODE) {
//      cout << "# WARNING in CSysSolve::FGMRES(): " << endl;
//      cout << "# true residual norm and calculated residual norm do not agree." << endl;
//      cout << "# res - beta = " << res - beta << endl;
//    }
//  }
	
  (*residual) = beta;
	return i;
  
}
예제 #2
0
파일: Divsol.c 프로젝트: Artem-B/test-suite
Matrix DivideAndSolve(Matrix A,int p)
{
  double a,b,d,e,s,c,mu,i;
  int h,j,k,l,m,o,rowstartt,colstartt,rowendt,colendt;
  Vector v,u,x,y,z;
  Matrix B,C,D,E,Q,U,H;

  U = newIdMatrix();
  H = newMatrix();
  v = newVector();

  i = p+1;

  rowstartt = i; 
  colstartt = 0;

  while (rowstartt<n)
    {
      rowendt = (rowstartt+i-1<n-1)?rowstartt+i-1:n-1; 
      colstartt = rowstartt-i;
      colendt = colstartt+i-1;
      
      /* Now T_i has dimension (p-h)x(p-h) */

      /* First zero all but row 1 in T_i */

      for (m=colstartt;m<=colendt;m++)
	{
	  if (norm(A,m,rowstartt,rowendt)!=0.0)
	    {
	      /* Find Householder(A(h:p,m)) */
	      House(A,v,m,rowstartt,rowendt);
	      for (o=0;o<rowstartt;o++)
		v[o]=0.0;
	      for (o=rowendt+1;o<n;o++)
		v[o]=0.0;
	      ApplyHouse(A,v,rowstartt,rowendt);
	    }
	  printf("m=%i, rowstart=%i, rowend=%i\n",m,rowstartt,rowendt);
	  printVector(v);
	  printMatrix(A);
	}

      /* Now zero all but the last entry in row 1 */

      WeirdHouse(A,v,rowstartt,colstartt,colendt);

      /* Apply the HouseHolder */

      ApplyHouse(A,v,colstartt,colendt);

      /* Now T_i has one single non-zero entry */

      /* Iterate with explicit shift to zero the last
	 non-zero entry */

      while (A[rowstartt][colendt]>
	     (A[rowstartt-1][colendt]-A[rowstartt][colendt+1])*epsilon)
	{
	  printMatrix(A);
	  /* Wilkonson Shift?? */
	  d  =(A[rowstartt-1][colendt]-A[rowstartt][colendt+1])/2.0;
	  b = A[rowstartt][colendt];
	  mu = A[rowstartt][colendt+1]+d-sign(d)*sqrt(d*d+b*b);

	  /* Determine the givens */
	  Givens(A[rowstartt-1][colendt]-mu,
		 A[rowstartt][colendt],&s,&c);
	  
	  /* Apply the givens */
	  ApplyGivens(A,s,c,rowstartt-1,rowstartt,0,n-1);
	  printf("%e\n",A[colstartt][colendt]);
	}

      rowstartt+=i;
      colstartt+=i;
    }				    
}