コード例 #1
0
ファイル: sLinsysRootAggregation.C プロジェクト: fqiang/PIPS
void sLinsysRootAggregation::Dsolve( sData *prob, OoqpVector& rhs )
{
  StochVector& b = dynamic_cast<StochVector&>(rhs);
  int myRank; MPI_Comm_rank(mpiComm,&myRank);

  SimpleVector& b0 = dynamic_cast<SimpleVector&>(*b.vec);

  if(0==myRank)
    solveReduced(prob, b0);
  
  // broadcast b0 from rank 0 to others
  MPI_Bcast(b0.elements(), b0.length(), MPI_DOUBLE, 0, mpiComm);
}
コード例 #2
0
ファイル: sLinsysRoot.C プロジェクト: qiakeyufeiniao/PIPS
void sLinsysRoot::Dsolve( sData *prob, OoqpVector& x )
{
//#ifdef TIMING
//    double tTot = MPI_Wtime();
//#endif
  StochVector& b = dynamic_cast<StochVector&>(x);

  //! commented - already done in addLnizi - cpetra
  //  for(size_t it=0; it<children.size(); it++) {
  //  children[it]->Dsolve(prob->children[it], *b.children[it]);
  //}

  SimpleVector& b0 = dynamic_cast<SimpleVector&>(*b.vec);
#ifdef TIMING
  stochNode->resMon.eDsolve.clear();
  stochNode->resMon.recDsolveTmLocal_start();
#endif
  solveReduced(prob, b0);
#ifdef TIMING
  stochNode->resMon.recDsolveTmLocal_stop();
#endif
}
コード例 #3
0
unsigned long CSysSolve::FGMRES(const CSysVector & b, CSysVector & x, CMatrixVectorProduct & mat_vec,
                               CPreconditioner & precond, double tol, unsigned long m, bool monitoring) {
	
int rank = 0;

#ifndef NO_MPI
#ifdef WINDOWS
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
#else
	rank = MPI::COMM_WORLD.Get_rank();
#endif
#endif
  
  /*---  Check the subspace size ---*/
  if (m < 1) {
    if (rank == 0) cerr << "CSysSolve::FGMRES: illegal value for subspace size, m = " << m << endl;
#ifdef NO_MPI
    exit(1);
#else
#ifdef WINDOWS
	MPI_Abort(MPI_COMM_WORLD,1);
    MPI_Finalize();
#else
    MPI::COMM_WORLD.Abort(1);
    MPI::Finalize();
#endif
#endif
  }

  /*---  Check the subspace size ---*/
  if (m > 1000) {
    if (rank == 0) cerr << "CSysSolve::FGMRES: illegal value for subspace size (too high), m = " << m << endl;
#ifdef NO_MPI
    exit(1);
#else
#ifdef WINDOWS
	MPI_Abort(MPI_COMM_WORLD,1);
    MPI_Finalize();
#else
    MPI::COMM_WORLD.Abort(1);
    MPI::Finalize();
#endif
#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<double> g(m+1, 0.0);
  vector<double> sn(m+1, 0.0);
  vector<double> cs(m+1, 0.0);
  vector<double> y(m, 0.0);
  vector<vector<double> > H(m+1, vector<double>(m, 0.0));
  
  /*---  Calculate the norm of the rhs vector ---*/
  double norm0 = b.norm();
  
  /*---  Calculate the initial residual (actually the negative residual)
	 and compute its norm ---*/
  mat_vec(x,w[0]);
  w[0] -= b;
  
  double beta = w[0].norm();
  
  if ( (beta < tol*norm0) || (beta < eps) ) {
    /*---  System is already solved ---*/
    if (rank == 0) 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 == 0)) {
    writeHeader("FGMRES", tol, beta);
    writeHistory(i, beta, norm0);
  }
  
  /*---  Loop over all search directions ---*/
  for (i = 0; i < 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 == 0)) && ((i+1) % 100 == 0)) && (rank == 0)) 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 == 0)) {
    cout << "# FGMRES final (true) residual:" << endl;
    cout << "# Iteration = " << i << ": |res|/|res0| = " << beta/norm0 << endl;
  }
  
//  /*---  Recalculate final (neg.) residual (this should be optional) ---*/
//  mat_vec(x, w[0]);
//  w[0] -= b;
//  double res = w[0].norm();
//  
//  if (fabs(res - beta) > tol*10) {
//    if (rank == 0) {
//      cout << "# WARNING in CSysSolve::FGMRES(): " << endl;
//      cout << "# true residual norm and calculated residual norm do not agree." << endl;
//      cout << "# res - beta = " << res - beta << endl;
//    }
//  }
	
	return i;
  
}
コード例 #4
0
void
QpGenStochLinsysRootAugRedPrecond::Dsolve( QpGenStochData *prob, OoqpVector& b_ )
{
    StochVector& bst = dynamic_cast<StochVector&>(b_);
    for(int it=0; it<children.size(); it++) {
        children[it]->Dsolve(prob->children[it], *bst.children[it]);
    }

    int n = locnx+locmy;
    int N=n+locmz;


    SimpleVector& b = dynamic_cast<SimpleVector&>(*bst.vec);
    assert(b.length()==N);

    int rankMe      = stochNode->rankMe;
    int rankPrcnd   = stochNode->rankPrcnd;
    int rankZeroW   = stochNode->rankZeroW;
    int commP2ZeroW = stochNode->commP2ZeroW;

    ///////////////////////////////////////////////////////////////////////
    // precond waits to be signaled
    ///////////////////////////////////////////////////////////////////////
    if(me==ePrecond) {
        if(NULL==tmpVec1) tmpVec1 = new double[n+PREC_EXTRA_DOUBLES];

        SimpleVector rhs(tmpVec1, n);
        MPI_Status status;
        while(true) {
            MPI_Recv(tmpVec1, n+PREC_EXTRA_DOUBLES, MPI_DOUBLE,
                     rankZeroW, 1, mpiComm,
                     &status);
            if(tmpVec1[n+PREC_EXTRA_DOUBLES-1]==1) break;

            solver->solve(rhs);

            iErr = MPI_Send(&rhs[0], n, MPI_DOUBLE,
                            rankZeroW, 2, mpiComm);

            assert(iErr==MPI_SUCCESS);
        }
    }

    ///////////////////////////////////////////////////////////////////////
    // special worker
    //   - signals the precond and waits for Px matVec via BiCGStabSolver
    //   - broadcasts the solution to the other workers
    ///////////////////////////////////////////////////////////////////////
    if(me==eSpecialWorker) {
        if(NULL==tmpVec1) tmpVec1 = new double[n+PREC_EXTRA_DOUBLES];
        //allocate the buffer here reuse these buffer in the MatVec
        Pmult->setTmpVec1(tmpVec1);

        solveReduced(prob, b);

        // notify the preconditioner that we converged;
        // the rest of buffer does not matter.
        tmpVec1[n+PREC_EXTRA_DOUBLES-1] = 1;
        MPI_Send(tmpVec1, n+PREC_EXTRA_DOUBLES, MPI_DOUBLE, rankPrcnd, 1, mpiComm);
    }

    ///////////////////////////////////////////////////////////////////////
    // the rest of the workers wait for special worker to converge
    // and obtain the solution
    ///////////////////////////////////////////////////////////////////////
    MPI_Bcast(&b[0], N, MPI_DOUBLE, rankZeroW, mpiComm);

    //printf("DSolve rank[%d] finished!!!!!!!\n", rankMe);
}