//---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( EpetraPointJacobiPreconditioner, tridiag_matrix ) { typedef Epetra_RowMatrix MatrixType; typedef Epetra_Vector VectorType; typedef MCLS::VectorTraits<VectorType> VT; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm ); int comm_size = comm->getSize(); int local_num_rows = 10; int global_num_rows = local_num_rows*comm_size; Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 3 ); double diag_val = 2.0; Teuchos::Array<double> values( 3, diag_val ); for ( int i = 1; i < global_num_rows-1; ++i ) { global_columns[0] = i-1; global_columns[1] = i; global_columns[2] = i+1; A->InsertGlobalValues( i, global_columns().size(), &values[0], &global_columns[0] ); } Teuchos::Array<int> single_col(1,0); Teuchos::Array<double> diag_elem(1,diag_val); A->InsertGlobalValues( 0, 1, diag_elem.getRawPtr(), single_col.getRawPtr() ); single_col[0] = global_num_rows-1; A->InsertGlobalValues( global_num_rows-1, 1, diag_elem.getRawPtr(), single_col.getRawPtr() ); A->FillComplete(); // Build the preconditioner. Teuchos::RCP<MCLS::Preconditioner<MatrixType> > preconditioner = Teuchos::rcp( new MCLS::EpetraPointJacobiPreconditioner() ); preconditioner->setOperator( A ); preconditioner->buildPreconditioner(); Teuchos::RCP<const MatrixType> M = preconditioner->getLeftPreconditioner(); // Check the preconditioner. Teuchos::RCP<VectorType> X = MT::cloneVectorFromMatrixRows(*A); MT::getLocalDiagCopy( *M, *X ); Teuchos::ArrayRCP<const double> X_view = VT::view( *X ); Teuchos::ArrayRCP<const double>::const_iterator view_iterator; for ( view_iterator = X_view.begin(); view_iterator != X_view.end(); ++view_iterator ) { TEST_EQUALITY( *view_iterator, 1.0/diag_val ); } }
Teuchos::RCP<Epetra_CrsMatrix> buildMatrix(int nx, Epetra_Comm & comm) { Epetra_Map map(nx*comm.NumProc(),0,comm); Teuchos::RCP<Epetra_CrsMatrix> mat = Teuchos::rcp(new Epetra_CrsMatrix(Copy,map,3)); int offsets[3] = {-1, 0, 1 }; double values[3] = { -1, 2, -1}; int maxGid = map.MaxAllGID(); for(int lid=0;lid<nx;lid++) { int gid = mat->GRID(lid); int numEntries = 3, offset = 0; int indices[3] = { gid+offsets[0], gid+offsets[1], gid+offsets[2] }; if(gid==0) { // left end point numEntries = 2; offset = 1; } // right end point else if(gid==maxGid) numEntries = 2; // insert rows mat->InsertGlobalValues(gid,numEntries,values+offset,indices+offset); } mat->FillComplete(); return mat; }
/// building the stencil void PoissonSolver::StencilGeometry(Teuchos::RCP<Epetra_Vector> & RHS, Teuchos::RCP<Epetra_CrsMatrix> & A) { const Epetra_BlockMap & MyMap = RHS->Map(); int NumMyElements = MyMap.NumMyElements(); int* MyGlobalElements = MyMap.MyGlobalElements(); double * rhsvalues = RHS->Values(); std::vector<double> Values(5); std::vector<int> Indices(5); const auto & inside = _bend.getInsideMask(); for (int lid = 0; lid < NumMyElements; ++ lid) { size_t NumEntries = 0; const size_t & gid = MyGlobalElements[lid]; cutoffStencil(Indices, Values, rhsvalues[lid], NumEntries, inside, gid); A->InsertGlobalValues(gid, NumEntries, &Values[0], &Indices[0]); } A->FillComplete(); A->OptimizeStorage(); }
Teuchos::RCP<Epetra_CrsMatrix> buildH( const Teuchos::RCP<Epetra_CrsMatrix> &A) { Teuchos::RCP<Epetra_CrsMatrix> H = Teuchos::rcp( new Epetra_CrsMatrix(Copy, A->RowMap(), A->GlobalMaxNumEntries() ) ); int N = A->NumGlobalRows(); std::vector<double> A_values( N ); std::vector<int> A_indices( N ); int A_size = 0; double local_H; bool found_diag = false; for ( int i = 0; i < N; ++i ) { A->ExtractGlobalRowCopy( i, N, A_size, &A_values[0], &A_indices[0] ); for ( int j = 0; j < A_size; ++j ) { if ( i == A_indices[j] ) { local_H = 1.0 - A_values[j]; H->InsertGlobalValues( i, 1, &local_H, &A_indices[j] ); found_diag = true; } else { local_H = -A_values[j]; H->InsertGlobalValues( i, 1, &local_H, &A_indices[j] ); } } if ( !found_diag ) { local_H = 1.0; H->InsertGlobalValues( i, 1, &local_H, &i ); } } H->FillComplete(); return H; }
TEUCHOS_UNIT_TEST( OperatorTools, spectral_radius_test) { int problem_size = 100; Epetra_SerialComm comm; Epetra_Map map( problem_size, 0, comm ); // Build A. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, map, problem_size ) ); double lower_diag = -1.0; double diag = 2.0; double upper_diag = -1.0; int global_row = 0; int lower_row = 0; int upper_row = 0; for ( int i = 0; i < problem_size; ++i ) { global_row = A->GRID(i); lower_row = i-1; upper_row = i+1; if ( lower_row > -1 ) { A->InsertGlobalValues( global_row, 1, &lower_diag, &lower_row ); } A->InsertGlobalValues( global_row, 1, &diag, &global_row ); if ( upper_row < problem_size ) { A->InsertGlobalValues( global_row, 1, &upper_diag, &upper_row ); } } A->FillComplete(); double spec_rad_A = HMCSA::OperatorTools::spectralRadius( A ); std::cout << spec_rad_A << std::endl; }
Teuchos::RCP<Epetra_CrsMatrix> Epetra_Operator_to_Epetra_Matrix::constructInverseMatrix(const Epetra_Operator &op, const Epetra_Map &map) { int numEntriesPerRow = 0; Teuchos::RCP<Epetra_FECrsMatrix> matrix = Teuchos::rcp(new Epetra_FECrsMatrix(::Copy, map, numEntriesPerRow)); int numRows = map.NumGlobalElements(); Epetra_Vector X(map); Epetra_Vector Y(map); double tol = 1e-15; // values below this will be considered 0 for (int rowIndex=0; rowIndex<numRows; rowIndex++) { int lid = map.LID(rowIndex); if (lid != -1) { X[lid] = 1.0; } op.ApplyInverse(X, Y); if (lid != -1) { X[lid] = 0.0; } std::vector<double> values; std::vector<int> indices; for (int i=0; i<map.NumMyElements(); i++) { if (abs(Y[i]) > tol) { values.push_back(Y[i]); indices.push_back(map.GID(i)); } } matrix->InsertGlobalValues(rowIndex, values.size(), &values[0], &indices[0]); } matrix->GlobalAssemble(); return matrix; }
// **************************************************************************** void DG_Prob::DG_EI_Epetra_Outflow(const EDGE border, Teuchos::RCP<Epetra_FECrsMatrix> A, Teuchos::RCP<Epetra_FEVector> RHS) { MyElem e0; e0=el[border.elemento[0]]; const int ntot = e0.show_ptr_stdel(sat)->nn_val() + e0.show_ptr_stdel(pres)->nn_val(); double mx [ntot*ntot]; double B [ntot]; int indx[ntot]; const int ntot1 = DG_EI_Outflow(border,mx,B,indx); if(ntot1 > ntot){ cout<<"DG_EI_Epetra_Outflow: ntot1 > ntot\n"; exit(1); } A->InsertGlobalValues(ntot1,&indx[0],&mx[0],Epetra_FECrsMatrix::ROW_MAJOR); RHS->SumIntoGlobalValues(ntot1,&indx[0],&B[0]); };
void createEpetraProblem (const Teuchos::RCP<const Epetra_Comm>& epetraComm, const std::string& filename, Teuchos::RCP<Epetra_Map>& rowMap, Teuchos::RCP<Epetra_CrsMatrix>& A, Teuchos::RCP<Epetra_MultiVector>& B, Teuchos::RCP<Epetra_MultiVector>& X, int& numRHS) { using Teuchos::inOutArg; using Teuchos::ptr; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::set_extra_data; const int MyPID = epetraComm->MyPID(); int n_nonzeros, N_update; int *bindx = NULL, *update = NULL, *col_inds = NULL; double *val = NULL, *row_vals = NULL; double *xguess = NULL, *b = NULL, *xexact = NULL; // // Set up the problem to be solved // int NumGlobalElements; // total # of rows in matrix try { // Read in matrix from HB file Trilinos_Util_read_hb (const_cast<char *> (filename.c_str()), MyPID, &NumGlobalElements, &n_nonzeros, &val, &bindx, &xguess, &b, &xexact); // Distribute data among processors Trilinos_Util_distrib_msr_matrix (*epetraComm, &NumGlobalElements, &n_nonzeros, &N_update, &update, &val, &bindx, &xguess, &b, &xexact); // // Construct the matrix // int NumMyElements = N_update; // # local rows of matrix on processor // // Create an int array NumNz that is used to build the Petra Matrix. // NumNz[i] is the number of OFF-DIAGONAL terms for the i-th global // equation on this processor. // std::vector<int> NumNz (NumMyElements); for (int i = 0; i < NumMyElements; ++i) { NumNz[i] = bindx[i+1] - bindx[i] + 1; } rowMap = rcp (new Epetra_Map (NumGlobalElements, NumMyElements, update, 0, *epetraComm)); //set_extra_data (epetraComm, "Map::Comm", inOutArg (rowMap)); // Create an Epetra sparse matrix. if (NumMyElements == 0) { A = rcp (new Epetra_CrsMatrix (Copy, *rowMap, static_cast<int*>(NULL))); } else { A = rcp (new Epetra_CrsMatrix (Copy, *rowMap, &NumNz[0])); } //set_extra_data (rowMap, "Operator::Map", ptr (A)); // Add rows to the sparse matrix one at a time. int NumEntries; for (int i = 0; i < NumMyElements; ++i) { row_vals = val + bindx[i]; col_inds = bindx + bindx[i]; NumEntries = bindx[i+1] - bindx[i]; int info = A->InsertGlobalValues (update[i], NumEntries, row_vals, col_inds); TEUCHOS_TEST_FOR_EXCEPTION( info != 0, std::logic_error, "Failed to insert global value into A." ); info = A->InsertGlobalValues (update[i], 1, val+i, update+i); TEUCHOS_TEST_FOR_EXCEPTION( info != 0, std::logic_error, "Failed to insert global value into A." ); } // Finish initializing the sparse matrix. int info = A->FillComplete(); TEUCHOS_TEST_FOR_EXCEPTION( info != 0, std::logic_error, "FillComplete() failed on the sparse matrix A."); info = A->OptimizeStorage(); TEUCHOS_TEST_FOR_EXCEPTION( info != 0, std::logic_error, "OptimizeStorage() failed on the sparse matrix A."); A->SetTracebackMode (1); // Shut down Epetra warning tracebacks // // Construct the right-hand side and solution multivectors. // if (false && b != NULL) { B = rcp (new Epetra_MultiVector (::Copy, *rowMap, b, NumMyElements, 1)); numRHS = 1; } else { B = rcp (new Epetra_MultiVector (*rowMap, numRHS)); B->Random (); } X = rcp (new Epetra_MultiVector (*rowMap, numRHS)); X->PutScalar (0.0); //set_extra_data (rowMap, "X::Map", Teuchos::ptr (X)); //set_extra_data (rowMap, "B::Map", Teuchos::ptr (B)); } catch (std::exception& e) { // Free up memory before rethrowing the exception. if (update) free(update); if (val) free(val); if (bindx) free(bindx); if (xexact) free(xexact); if (xguess) free(xguess); if (b) free(b); throw e; // Rethrow the exception. } catch (...) { // Epetra sometimes throws an int "object." // Free up memory before rethrowing the exception. if (update) free(update); if (val) free(val); if (bindx) free(bindx); if (xexact) free(xexact); if (xguess) free(xguess); if (b) free(b); TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Generating the Epetra problem to solve failed " "with an unknown error."); } //if (false) { // // Create workspace // //Teuchos::set_default_workspace_store (rcp (new Teuchos::WorkspaceStoreInitializeable(static_cast<size_t>(2e+6)))); //} // // Free up memory. // if (update) free(update); if (val) free(val); if (bindx) free(bindx); if (xexact) free(xexact); if (xguess) free(xguess); if (b) free(b); }
//---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( UniformForwardSource, nh_set ) { typedef Epetra_Vector VectorType; typedef MCLS::VectorTraits<VectorType> VT; typedef Epetra_RowMatrix MatrixType; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; typedef MCLS::ForwardHistory<int> HistoryType; typedef std::mt19937 rng_type; typedef MCLS::ForwardDomain<VectorType,MatrixType,rng_type> DomainType; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm ); int comm_size = comm->getSize(); int local_num_rows = 10; int global_num_rows = local_num_rows*comm_size; Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); // Build the linear system. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 1 ); Teuchos::Array<double> values( 1 ); for ( int i = 1; i < global_num_rows; ++i ) { global_columns[0] = i-1; values[0] = -0.5; A->InsertGlobalValues( i, global_columns().size(), &values[0], &global_columns[0] ); } global_columns[0] = global_num_rows-1; values[0] = -0.5; A->InsertGlobalValues( global_num_rows-1, global_columns().size(), &values[0], &global_columns[0] ); A->FillComplete(); Teuchos::RCP<MatrixType> A_T = MT::copyTranspose(*A); Teuchos::RCP<VectorType> x = MT::cloneVectorFromMatrixRows( *A ); Teuchos::RCP<VectorType> b = MT::cloneVectorFromMatrixRows( *A ); VT::putScalar( *b, -1.0 ); // Build the forward domain. Teuchos::ParameterList plist; plist.set<int>( "Overlap Size", 0 ); Teuchos::RCP<DomainType> domain = Teuchos::rcp( new DomainType( A_T, x, plist ) ); // History setup. HistoryType::setByteSize(); // Create the forward source with a set number of histories. int mult = 10; double cutoff = 1.0e-8; plist.set<double>("Sample Ratio",mult); plist.set<double>("Weight Cutoff", cutoff); MCLS::UniformForwardSource<DomainType> source( b, domain, comm, comm->getSize(), comm->getRank(), plist ); TEST_ASSERT( source.empty() ); TEST_EQUALITY( source.numToTransport(), 0 ); TEST_EQUALITY( source.numToTransportInSet(), mult*global_num_rows ); TEST_EQUALITY( source.numRequested(), mult*global_num_rows ); TEST_EQUALITY( source.numLeft(), 0 ); TEST_EQUALITY( source.numEmitted(), 0 ); // Build the source. source.buildSource(); TEST_ASSERT( !source.empty() ); TEST_EQUALITY( source.numToTransport(), mult*local_num_rows ); TEST_EQUALITY( source.numToTransportInSet(), mult*global_num_rows ); TEST_EQUALITY( source.numRequested(), mult*global_num_rows ); TEST_EQUALITY( source.numLeft(), mult*local_num_rows ); TEST_EQUALITY( source.numEmitted(), 0 ); // Sample the source. Teuchos::RCP<MCLS::PRNG<rng_type> > rng = Teuchos::rcp( new MCLS::PRNG<rng_type>(comm->getRank()) ); source.setRNG( rng ); for ( int i = 0; i < mult*local_num_rows; ++i ) { TEST_ASSERT( !source.empty() ); TEST_EQUALITY( source.numLeft(), mult*local_num_rows-i ); TEST_EQUALITY( source.numEmitted(), i ); Teuchos::RCP<HistoryType> history = source.getHistory(); TEST_EQUALITY( history->weight(), 1.0 ); TEST_ASSERT( domain->isGlobalState( history->globalState() ) ); TEST_ASSERT( history->alive() ); TEST_ASSERT( VT::isGlobalRow( *x, history->globalState() ) ); } TEST_ASSERT( source.empty() ); TEST_EQUALITY( source.numLeft(), 0 ); TEST_EQUALITY( source.numEmitted(), mult*local_num_rows ); }
int main(int argc, char** argv) { #if defined(HAVE_MPI) && defined(HAVE_EPETRA) int numProcs = 1; int localProc = 0; //first, set up our MPI environment... MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &localProc); MPI_Comm_size(MPI_COMM_WORLD, &numProcs); // This program can only run on 3 processors, to make things // work out easy. // if (numProcs != 3) { std::cout << "num-procs="<<numProcs<<". This program can only " << "run on 3 procs. Exiting."<<std::endl; MPI_Finalize(); return(0); } //Consider the following mesh of 4 2-D quad elements: // // *-------*-------* // 8| 7| 6| // | E2 | E3 | // *-------*-------* // 3| 2| 5| // | E0 | E1 | // *-------*-------* // 0 1 4 // // Node-ids are to the lower-left of each node (*). // // Mimicing a finite-element application, we will say that // each node has 1 scalar degree-of-freedom, and assemble // a matrix which would have 9 global rows and columns. // // Each processor will have 3 rows. We'll set up a strange // initial map, where nodes are distributed as follows: // // proc 0: nodes 0,3,8, // proc 1: nodes 1,2,7 // proc 2: nodes 4,5,6. // // After we assemble our matrix, we'll create another matrix // and populate it with graph edge weights such that the // partitioner repartitions the problem so that nodes are // laid out as follows: // // proc 0: nodes 0, 1, 4 // proc 1: nodes 3, 2, 5 // proc 2: nodes 8, 7, 6 // int nodesPerElem = 4; int global_n = 9; //First, set up the initial map: std::vector<int> mynodes(3); if (localProc == 0) { mynodes[0] = 0; mynodes[1] = 3; mynodes[2] = 8; } if (localProc == 1) { mynodes[0] = 1; mynodes[1] = 2; mynodes[2] = 7; } if (localProc == 2) { mynodes[0] = 4; mynodes[1] = 5; mynodes[2] = 6; } Epetra_MpiComm comm(MPI_COMM_WORLD); Epetra_Map origmap(global_n, 3, &mynodes[0], 0, comm); Teuchos::RCP<Epetra_FECrsMatrix> matrix = Teuchos::rcp(new Epetra_FECrsMatrix(Copy, origmap, 0)); //We'll assemble elements E0 and E1 on proc 0, // element E2 or proc 1, // element E3 on proc 2. std::vector<int> indices(nodesPerElem); std::vector<double> coefs(nodesPerElem*nodesPerElem,2.0); if (localProc == 0) { //element E0: indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 3; matrix->InsertGlobalValues(nodesPerElem, &indices[0], &coefs[0]); //element E1: indices[0] = 1; indices[1] = 4; indices[2] = 5; indices[3] = 2; matrix->InsertGlobalValues(nodesPerElem, &indices[0], &coefs[0]); } else if (localProc == 1) { //element E2: indices[0] = 3; indices[1] = 2; indices[2] = 7; indices[3] = 8; matrix->InsertGlobalValues(nodesPerElem, &indices[0], &coefs[0]); } else { //localProc==2 //element E3: indices[0] = 2; indices[1] = 5; indices[2] = 6; indices[3] = 7; matrix->InsertGlobalValues(nodesPerElem, &indices[0], &coefs[0]); } int err = matrix->GlobalAssemble(); if (err != 0) { std::cout << "err="<<err<<" returned from matrix->GlobalAssemble()" << std::endl; } // std::cout << "matrix: " << std::endl; // std::cout << *matrix << std::endl; //We'll need a Teuchos::ParameterList object to pass to the //Isorropia::Epetra::Partitioner class. Teuchos::ParameterList paramlist; #ifdef HAVE_ISORROPIA_ZOLTAN // If Zoltan is available, we'll specify that the Zoltan package be // used for the partitioning operation, by creating a parameter // sublist named "Zoltan". // In the sublist, we'll set parameters that we want sent to Zoltan. paramlist.set("PARTITIONING METHOD", "GRAPH"); paramlist.set("PRINT ZOLTAN METRICS", "2"); Teuchos::ParameterList& sublist = paramlist.sublist("Zoltan"); sublist.set("GRAPH_PACKAGE", "PHG"); //sublist.set("DEBUG_LEVEL", "1"); // Zoltan will print out parameters //sublist.set("DEBUG_LEVEL", "5"); // proc 0 will trace Zoltan calls //sublist.set("DEBUG_MEMORY", "2"); // Zoltan will trace alloc & free #else // If Zoltan is not available, a simple linear partitioner will be // used to partition such that the number of nonzeros is equal (or // close to equal) on each processor. No parameter is necessary to // specify this. #endif Teuchos::RCP<Isorropia::Epetra::CostDescriber> costs = Teuchos::rcp(new Isorropia::Epetra::CostDescriber); //Next create a matrix which is a copy of the matrix we just //assembled, but we'll replace the values with graph edge weights. Teuchos::RCP<Epetra_FECrsMatrix> ge_weights = Teuchos::rcp(new Epetra_FECrsMatrix(*matrix)); Teuchos::RCP<Epetra_CrsMatrix> crs_ge_weights; crs_ge_weights = ge_weights; //Fill the matrix with a "default" weight of 1.0. crs_ge_weights->PutScalar(1.0); //Now we'll put a "large" weight on edges that connect nodes //0 and 1, 1 and 4, //3 and 2, 2 and 5, //8 and 7, 7 and 6. double weight = 500.0; if (localProc == 0) { //row 0, edge 1 indices[0] = 1; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(0, 1, &coefs[0], &indices[0]); //row 3, edge 2 indices[0] = 2; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(3, 1, &coefs[0], &indices[0]); //row 8, edge 7 indices[0] = 7; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(8, 1, &coefs[0], &indices[0]); } if (localProc == 1) { //row 1, edges 0 and 4 indices[0] = 0; indices[1] = 4; coefs[0] = weight; coefs[1] = weight; crs_ge_weights->ReplaceGlobalValues(1, 2, &coefs[0], &indices[0]); //row 2, edges 3 and 5 indices[0] = 3; indices[1] = 5; coefs[0] = weight; coefs[1] = weight; crs_ge_weights->ReplaceGlobalValues(2, 2, &coefs[0], &indices[0]); //row 7, edges 6 and 8 indices[0] = 6; indices[1] = 8; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(7, 2, &coefs[0], &indices[0]); } if (localProc == 2) { //row 4, edge 1 indices[0] = 1; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(4, 1, &coefs[0], &indices[0]); //row 5, edge 2 indices[0] = 2; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(5, 1, &coefs[0], &indices[0]); //row 6, edge 7 indices[0] = 7; coefs[0] = weight; crs_ge_weights->ReplaceGlobalValues(6, 1, &coefs[0], &indices[0]); } // std::cout << "crs_ge_weights: " << std::endl // << *crs_ge_weights << std::endl; //Now give the graph edge weights to the CostDescriber: costs->setGraphEdgeWeights(crs_ge_weights); Teuchos::RCP<const Epetra_RowMatrix> rowmatrix; rowmatrix = matrix; //Now create the partitioner object using an Isorropia factory-like //function... Teuchos::RCP<Isorropia::Epetra::Partitioner> partitioner = Teuchos::rcp(new Isorropia::Epetra::Partitioner(rowmatrix, costs, paramlist)); //Next create a Redistributor object and use it to create a //repartitioned copy of the matrix Isorropia::Epetra::Redistributor rd(partitioner); Teuchos::RCP<Epetra_CrsMatrix> bal_matrix; //Use a try-catch block because Isorropia will throw an exception //if it encounters an error. if (localProc == 0) { std::cout << " calling Isorropia::Epetra::Redistributor::redistribute..." << std::endl; } try { bal_matrix = rd.redistribute(*rowmatrix); } catch(std::exception& exc) { std::cout << "linsys example: Isorropia::Epetra::Redistributor threw " << "exception '" << exc.what() << "' on proc " << localProc << std::endl; MPI_Finalize(); return(-1); } // Results double bal0, bal1, cutn0, cutn1, cutl0, cutl1, cutWgt0, cutWgt1; int numCuts0, numCuts1; #if 1 // Balance and cut quality before partitioning double goalWeight = 1.0 / (double)numProcs; ispatest::compute_graph_metrics(*rowmatrix, *costs, goalWeight, bal0, numCuts0, cutWgt0, cutn0, cutl0); // Balance and cut quality after partitioning Teuchos::RCP<Epetra_CrsMatrix> new_weights = rd.redistribute(*crs_ge_weights); Isorropia::Epetra::CostDescriber new_costs; new_costs.setGraphEdgeWeights(new_weights); ispatest::compute_graph_metrics(*bal_matrix, new_costs, goalWeight, bal1, numCuts1, cutWgt1, cutn1, cutl1); #else std::vector<double> bal(2), cutwgt(2), cutn(2), cutl(2); std::vector<int >ncuts(2); Epetra_Import &importer = rd.get_importer(); costs->compareBeforeAndAfterGraph(*rowmatrix, *bal_matrix, importer, bal, ncuts, cutwgt, cutn, cutl); bal0 = bal[0]; cutn0 = cutn[0]; cutl0 = cutl[0]; cutWgt0 = cutwgt[0]; numCuts0 = ncuts[0]; bal1 = bal[1]; cutn1 = cutn[1]; cutl1 = cutl[1]; cutWgt1 = cutwgt[1]; numCuts1 = ncuts[1]; #endif bal_matrix.release(); if (localProc == 0){ std::cout << "Before partitioning: Number of cuts " << numCuts0 << " Cut weight " << cutWgt0 << std::endl; std::cout << " Balance " << bal0 << " cutN " << cutn0 << " cutL " << cutl0; std::cout << std::endl; std::cout << "After partitioning: Number of cuts " << numCuts1 << " Cut weight " << cutWgt1 << std::endl; std::cout << " Balance " << bal1 << " cutN " << cutn1 << " cutL " << cutl1; std::cout << std::endl; } MPI_Finalize(); #else std::cout << "part_redist: must have both MPI and EPETRA. Make sure Trilinos " << "is configured with --enable-mpi and --enable-epetra." << std::endl; #endif return(0); }
int main(int argc, char *argv[]) { using Teuchos::rcp_implicit_cast; int i, ierr, gerr; gerr = 0; #ifdef HAVE_MPI // Initialize MPI and setup an Epetra communicator MPI_Init(&argc,&argv); Teuchos::RCP<Epetra_MpiComm> Comm = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_WORLD) ); #else // If we aren't using MPI, then setup a serial communicator. Teuchos::RCP<Epetra_SerialComm> Comm = Teuchos::rcp( new Epetra_SerialComm() ); #endif // number of global elements int dim = 100; int blockSize = 3; // PID info int MyPID = Comm->MyPID(); bool verbose = 0; if (argc>1) { if (argv[1][0]=='-' && argv[1][1]=='v') { verbose = true; } } // Construct a Map that puts approximately the same number of // equations on each processor. Teuchos::RCP<Epetra_Map> Map = Teuchos::rcp( new Epetra_Map(dim, 0, *Comm) ); // Get update list and number of local equations from newly created Map. int NumMyElements = Map->NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map->MyGlobalElements(&MyGlobalElements[0]); // Create an integer std::vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of OFF-DIAGONAL term for the ith global equation // on this processor std::vector<int> NumNz(NumMyElements); // We are building a tridiagonal matrix where each row has (-1 2 -1) // So we need 2 off-diagonal terms (except for the first and last equation) for (i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0 || MyGlobalElements[i] == dim-1) { NumNz[i] = 2; } else { NumNz[i] = 3; } } // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, *Map, &NumNz[0]) ); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 std::vector<double> Values(2); Values[0] = -1.0; Values[1] = -1.0; std::vector<int> Indices(2); double two = 2.0; int NumEntries; for (i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (MyGlobalElements[i] == dim-1) { Indices[0] = dim-2; NumEntries = 1; } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; NumEntries = 2; } ierr = A->InsertGlobalValues(MyGlobalElements[i],NumEntries,&Values[0],&Indices[0]); assert(ierr==0); // Put in the diagonal entry ierr = A->InsertGlobalValues(MyGlobalElements[i],1,&two,&MyGlobalElements[i]); assert(ierr==0); } // Finish building the epetra matrix A ierr = A->FillComplete(); assert(ierr==0); // Create an Belos::EpetraOp from this Epetra_CrsMatrix Teuchos::RCP<Belos::EpetraOp> op = Teuchos::rcp(new Belos::EpetraOp(A)); // Issue several useful typedefs; typedef Belos::MultiVec<double> EMV; typedef Belos::Operator<double> EOP; // Create an Epetra_MultiVector for an initial std::vector to start the solver. // Note that this needs to have the same number of columns as the blocksize. Teuchos::RCP<Belos::EpetraMultiVec> ivec = Teuchos::rcp( new Belos::EpetraMultiVec(*Map, blockSize) ); ivec->Random(); // Create an output manager to handle the I/O from the solver Teuchos::RCP<Belos::OutputManager<double> > MyOM = Teuchos::rcp( new Belos::OutputManager<double>( MyPID ) ); if (verbose) { MyOM->setVerbosity( Belos::Errors + Belos::Warnings ); } #ifdef HAVE_EPETRA_THYRA typedef Thyra::MultiVectorBase<double> TMVB; typedef Thyra::LinearOpBase<double> TLOB; // create thyra objects from the epetra objects // first, a Thyra::VectorSpaceBase Teuchos::RCP<const Thyra::VectorSpaceBase<double> > epetra_vs = Thyra::create_VectorSpace(Map); // then, a MultiVectorBase (from the Epetra_MultiVector) Teuchos::RCP<Thyra::MultiVectorBase<double> > thyra_ivec = Thyra::create_MultiVector(rcp_implicit_cast<Epetra_MultiVector>(ivec),epetra_vs); // then, a LinearOpBase (from the Epetra_CrsMatrix) Teuchos::RCP<Thyra::LinearOpBase<double> > thyra_op = Teuchos::rcp( new Thyra::EpetraLinearOp(A) ); // test the Thyra adapter multivector ierr = Belos::TestMultiVecTraits<double,TMVB>(MyOM,thyra_ivec); gerr |= ierr; switch (ierr) { case Belos::Ok: if ( verbose && MyPID==0 ) { std::cout << "*** ThyraAdapter PASSED TestMultiVecTraits()" << std::endl; } break; case Belos::Error: if ( verbose && MyPID==0 ) { std::cout << "*** ThyraAdapter FAILED TestMultiVecTraits() ***" << std::endl << std::endl; } break; } // test the Thyra adapter operator ierr = Belos::TestOperatorTraits<double,TMVB,TLOB>(MyOM,thyra_ivec,thyra_op); gerr |= ierr; switch (ierr) { case Belos::Ok: if ( verbose && MyPID==0 ) { std::cout << "*** ThyraAdapter PASSED TestOperatorTraits()" << std::endl; } break; case Belos::Error: if ( verbose && MyPID==0 ) { std::cout << "*** ThyraAdapter FAILED TestOperatorTraits() ***" << std::endl << std::endl; } break; } #endif #ifdef HAVE_MPI MPI_Finalize(); #endif if (gerr) { if (verbose && MyPID==0) std::cout << "End Result: TEST FAILED" << std::endl; return -1; } // // Default return value // if (verbose && MyPID==0) std::cout << "End Result: TEST PASSED" << std::endl; return 0; }
int main(int argc, char *argv[]) { #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif bool testFailed; bool boolret; int MyPID = Comm.MyPID(); bool verbose = true; bool debug = false; std::string which("SM"); Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","nodebug",&debug,"Print debugging information."); cmdp.setOption("sort",&which,"Targetted eigenvalues (SM,LM,SR,LR,SI,or LI)."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } typedef double ScalarType; typedef Teuchos::ScalarTraits<ScalarType> ScalarTypeTraits; typedef ScalarTypeTraits::magnitudeType MagnitudeType; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<ScalarType,MV> MVTraits; typedef Anasazi::OperatorTraits<ScalarType,MV,OP> OpTraits; // Dimension of the matrix int nx = 10; // Discretization points in any one direction. int NumGlobalElements = nx*nx; // Size of matrix nx*nx // Construct a Map that puts approximately the same number of // equations on each processor. Epetra_Map Map(NumGlobalElements, 0, Comm); // Get update list and number of local equations from newly created Map. int NumMyElements = Map.NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map.MyGlobalElements(&MyGlobalElements[0]); // Create an integer vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of OFF-DIAGONAL term for the ith global equation // on this processor std::vector<int> NumNz(NumMyElements); /* We are building a matrix of block structure: | T -I | |-I T -I | | -I T | | ... -I| | -I T| where each block is dimension nx by nx and the matrix is on the order of nx*nx. The block T is a tridiagonal matrix. */ for (int i=0; i<NumMyElements; i++) { if (MyGlobalElements[i] == 0 || MyGlobalElements[i] == NumGlobalElements-1 || MyGlobalElements[i] == nx-1 || MyGlobalElements[i] == nx*(nx-1) ) { NumNz[i] = 3; } else if (MyGlobalElements[i] < nx || MyGlobalElements[i] > nx*(nx-1) || MyGlobalElements[i]%nx == 0 || (MyGlobalElements[i]+1)%nx == 0) { NumNz[i] = 4; } else { NumNz[i] = 5; } } // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, Map, &NumNz[0]) ); // Diffusion coefficient, can be set by user. // When rho*h/2 <= 1, the discrete convection-diffusion operator has real eigenvalues. // When rho*h/2 > 1, the operator has complex eigenvalues. double rho = 2*(nx+1); // Compute coefficients for discrete convection-diffution operator const double one = 1.0; std::vector<double> Values(4); std::vector<int> Indices(4); double h = one /(nx+1); double h2 = h*h; double c = 5.0e-01*rho/ h; Values[0] = -one/h2 - c; Values[1] = -one/h2 + c; Values[2] = -one/h2; Values[3]= -one/h2; double diag = 4.0 / h2; int NumEntries, info; for (int i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0) { Indices[0] = 1; Indices[1] = nx; NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == nx*(nx-1)) { Indices[0] = nx*(nx-1)+1; Indices[1] = nx*(nx-2); NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == nx-1) { Indices[0] = nx-2; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); Indices[0] = 2*nx-1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == NumGlobalElements-1) { Indices[0] = NumGlobalElements-2; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); Indices[0] = nx*(nx-1)-1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] < nx) { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]+nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] > nx*(nx-1)) { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]-nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i]%nx == 0) { Indices[0] = MyGlobalElements[i]+1; Indices[1] = MyGlobalElements[i]-nx; Indices[2] = MyGlobalElements[i]+nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if ((MyGlobalElements[i]+1)%nx == 0) { Indices[0] = MyGlobalElements[i]-nx; Indices[1] = MyGlobalElements[i]+nx; NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); Indices[0] = MyGlobalElements[i]-1; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]-nx; Indices[3] = MyGlobalElements[i]+nx; NumEntries = 4; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } // Put in the diagonal entry info = A->InsertGlobalValues(MyGlobalElements[i], 1, &diag, &MyGlobalElements[i]); assert( info==0 ); } // Finish up info = A->FillComplete(); assert( info==0 ); A->SetTracebackMode(1); // Shutdown Epetra Warning tracebacks //************************************ // Start the block Davidson iteration //*********************************** // // Variables used for the Generalized Davidson Method // int nev = 4; int blockSize = 1; int maxDim = 50; int restartDim = 10; int maxRestarts = 500; double tol = 1e-10; // Set verbosity level int verbosity = Anasazi::Errors + Anasazi::Warnings; if (verbose) { verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails; } if (debug) { verbosity += Anasazi::Debug; } // // Create parameter list to pass into solver manager // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Maximum Subspace Dimension", maxDim); MyPL.set( "Restart Dimension", restartDim); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); MyPL.set( "Relative Convergence Tolerance", true ); MyPL.set( "Initial Guess", "User" ); // Create an Epetra_MultiVector for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(Map, blockSize) ); ivec->Random(); // Create the eigenproblem. Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double,MV,OP>() ); MyProblem->setA(A); MyProblem->setInitVec(ivec); // Inform the eigenproblem that the operator A is non-Hermitian MyProblem->setHermitian(false); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finishing passing it information boolret = MyProblem->setProblem(); if (boolret != true) { if (verbose && MyPID == 0) { std::cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << std::endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::GeneralizedDavidsonSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); testFailed = false; if (returnCode != Anasazi::Converged && MyPID==0 && verbose) { testFailed = true; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<ScalarType,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<ScalarType> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; std::vector<int> index = sol.index; int numev = sol.numVecs; // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { int numritz = (int)evals.size(); std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<std::endl<< "Computed Ritz Values"<< std::endl; std::cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::endl; std::cout<<"-----------------------------------------------------------"<<std::endl; for (int i=0; i<numritz; i++) { std::cout<< std::setw(16) << evals[i].realpart << std::setw(16) << evals[i].imagpart << std::endl; } std::cout<<"-----------------------------------------------------------"<<std::endl; } if (numev > 0) { // Compute residuals. Teuchos::LAPACK<int,double> lapack; std::vector<double> normA(numev); // The problem is non-Hermitian. int i=0; std::vector<int> curind(1); std::vector<double> resnorm(1), tempnrm(1); Teuchos::RCP<MV> tempAevec; Teuchos::RCP<const MV> evecr, eveci; Epetra_MultiVector Aevec(Map,numev); // Compute A*evecs OpTraits::Apply( *A, *evecs, Aevec ); Teuchos::SerialDenseMatrix<int,double> Breal(1,1), Bimag(1,1); while (i<numev) { if (index[i]==0) { // Get a view of the current eigenvector (evecr) curind[0] = i; evecr = MVTraits::CloneView( *evecs, curind ); // Get a copy of A*evecr tempAevec = MVTraits::CloneCopy( Aevec, curind ); // Compute A*evecr - lambda*evecr Breal(0,0) = evals[i].realpart; MVTraits::MvTimesMatAddMv( -1.0, *evecr, Breal, 1.0, *tempAevec ); // Compute the norm of the residual and increment counter MVTraits::MvNorm( *tempAevec, resnorm ); normA[i] = resnorm[0] / Teuchos::ScalarTraits<MagnitudeType>::magnitude( evals[i].realpart ); i++; } else { // Get a view of the real part of the eigenvector (evecr) curind[0] = i; evecr = MVTraits::CloneView( *evecs, curind ); // Get a copy of A*evecr tempAevec = MVTraits::CloneCopy( Aevec, curind ); // Get a view of the imaginary part of the eigenvector (eveci) curind[0] = i+1; eveci = MVTraits::CloneView( *evecs, curind ); // Set the eigenvalue into Breal and Bimag Breal(0,0) = evals[i].realpart; Bimag(0,0) = evals[i].imagpart; // Compute A*evecr - evecr*lambdar + eveci*lambdai MVTraits::MvTimesMatAddMv( -1.0, *evecr, Breal, 1.0, *tempAevec ); MVTraits::MvTimesMatAddMv( 1.0, *eveci, Bimag, 1.0, *tempAevec ); MVTraits::MvNorm( *tempAevec, tempnrm ); // Get a copy of A*eveci tempAevec = MVTraits::CloneCopy( Aevec, curind ); // Compute A*eveci - eveci*lambdar - evecr*lambdai MVTraits::MvTimesMatAddMv( -1.0, *evecr, Bimag, 1.0, *tempAevec ); MVTraits::MvTimesMatAddMv( -1.0, *eveci, Breal, 1.0, *tempAevec ); MVTraits::MvNorm( *tempAevec, resnorm ); // Compute the norms and scale by magnitude of eigenvalue normA[i] = lapack.LAPY2( tempnrm[0], resnorm[0] ) / lapack.LAPY2( evals[i].realpart, evals[i].imagpart ); normA[i+1] = normA[i]; i=i+2; } } // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<std::endl<< "Actual Residuals"<<std::endl; std::cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::setw(20) << "Direct Residual"<< std::endl; std::cout<<"-----------------------------------------------------------"<<std::endl; for (int j=0; j<numev; j++) { std::cout<< std::setw(16) << evals[j].realpart << std::setw(16) << evals[j].imagpart << std::setw(20) << normA[j] << std::endl; if ( normA[j] > tol ) { testFailed = true; } } std::cout<<"-----------------------------------------------------------"<<std::endl; } } #ifdef EPETRA_MPI MPI_Finalize(); #endif if (testFailed) { if (verbose && MyPID==0) { std::cout << "End Result: TEST FAILED" << std::endl; } return -1; } // // Default return value // if (verbose && MyPID==0) { std::cout << "End Result: TEST PASSED" << std::endl; } return 0; }
int extract_matrices ( Epetra_CrsMatrix *A, // i/p: A matrix shylu_symbolic *ssym, // symbolic structure shylu_data *data, // numeric structure, TODO: Required ? shylu_config *config, // i/p: library configuration bool insertValues // true implies values will be inserted and fill // complete will be called. false implies values // will be replaced. ) { Teuchos::RCP<Epetra_CrsMatrix> D = ssym->D; Teuchos::RCP<Epetra_CrsMatrix> C = ssym->C; Teuchos::RCP<Epetra_CrsMatrix> R = ssym->R; Teuchos::RCP<Epetra_CrsMatrix> G = ssym->G; Teuchos::RCP<Epetra_CrsGraph> Sg = ssym->Sg; int *DColElems = data->DColElems; int *gvals = data->gvals; double Sdiagfactor = config->Sdiagfactor; int *LeftIndex = new int[data->lmax]; double *LeftValues = new double[data->lmax]; int *RightIndex = new int[data->rmax]; double *RightValues = new double[data->rmax]; int err; int lcnt, rcnt ; int gcid; int gid; int *Ai; double *Ax; int nrows = A->RowMap().NumMyElements(); int *rows = A->RowMap().MyGlobalElements(); for (int i = 0; i < nrows ; i++) { int NumEntries; err = A->ExtractMyRowView(i, NumEntries, Ax, Ai); lcnt = 0; rcnt = 0; // Place the entry in the correct sub matrix, Works only for sym gid = rows[i]; int lcid; for (int j = 0 ; j < NumEntries ; j++) { // O(nnz) ! Careful what you do inside // Row permutation does not matter here gcid = A->GCID(Ai[j]); assert(gcid != -1); //Either in D or R if ((gvals[gid] != 1 && gvals[gcid] == 1) || (gvals[gid] == 1 && A->LRID(gcid) != -1 && gvals[gcid] == 1)) { assert(lcnt < data->lmax); if (insertValues) LeftIndex[lcnt] = gcid; else { //local column id lcid = (gvals[gid] == 1 ? D->LCID(gcid) : R->LCID(gcid)); assert(lcid != -1); LeftIndex[lcnt] = lcid; } LeftValues[lcnt++] = Ax[j]; } else { assert(rcnt < data->rmax); if (insertValues) RightIndex[rcnt] = gcid; else { //local column id lcid = (gvals[gid] == 1 ? C->LCID(gcid) : G->LCID(gcid)); assert(lcid != -1); RightIndex[rcnt] = lcid; } RightValues[rcnt++] = Ax[j]; } } if (gvals[gid] == 1) { // D or C row if (insertValues) { err = D->InsertGlobalValues(gid, lcnt, LeftValues, LeftIndex); assert(err == 0); err = C->InsertGlobalValues(gid, rcnt, RightValues, RightIndex); assert(err == 0); } else { err = D->ReplaceMyValues(D->LRID(gid), lcnt, LeftValues, LeftIndex); assert(err == 0); err = C->ReplaceMyValues(C->LRID(gid), rcnt, RightValues, RightIndex); assert(err == 0); } } else { // R or S row //assert(lcnt > 0); // TODO: Enable this once using narrow sep. if (insertValues) { assert(rcnt > 0); err = R->InsertGlobalValues(gid, lcnt, LeftValues, LeftIndex); assert(err == 0); err = G->InsertGlobalValues(gid, rcnt, RightValues, RightIndex); assert(err == 0); if (config->schurApproxMethod == 1) { err = Sg->InsertGlobalIndices(gid, rcnt, RightIndex); assert(err == 0); } } else { assert(rcnt > 0); err = R->ReplaceMyValues(R->LRID(gid), lcnt, LeftValues, LeftIndex); assert(err == 0); err = G->ReplaceMyValues(G->LRID(gid), rcnt, RightValues, RightIndex); assert(err == 0); } } } if (insertValues) { /* ------------- Create the maps for the DBBD form ------------------ */ Epetra_Map *DRowMap, *SRowMap, *DColMap; Epetra_SerialComm LComm; if (config->sep_type != 1) { DRowMap = new Epetra_Map(-1, data->Dnr, data->DRowElems, 0, A->Comm()); SRowMap = new Epetra_Map(-1, data->Snr, data->SRowElems, 0, A->Comm()); DColMap = new Epetra_Map(-1, data->Dnc, DColElems, 0, A->Comm()); } else { DRowMap = new Epetra_Map(-1, data->Dnr, data->DRowElems, 0, LComm); SRowMap = new Epetra_Map(-1, data->Snr, data->SRowElems, 0, LComm); DColMap = new Epetra_Map(-1, data->Dnc, DColElems, 0, LComm); } D->FillComplete(); //config->dm.print(5, "Done D fillcomplete"); G->FillComplete(); //config->dm.print(5, "Done G fillcomplete"); C->FillComplete(*SRowMap, *DRowMap); //TODO:Won't work if permutation is // unsymmetric SRowMap //config->dm.print(5, "Done C fillcomplete"); R->FillComplete(*DColMap, *SRowMap); //config->dm.print(5, "Done R fillcomplete"); int Sdiag = (int) data->Snr * Sdiagfactor; Sdiag = MIN(Sdiag, data->Snr-1); Sdiag = MAX(Sdiag, 0); // Add the diagonals to Sg for (int i = 0; config->schurApproxMethod == 1 && i < nrows ; i++) { gid = rows[i]; if (gvals[gid] == 1) continue; // not a row in S if (data->Snr == 0) assert(0 == 1); rcnt = 0; //TODO Will be trouble if SNumGlobalCols != Snc //assert(SNumGlobalCols == Snc); //for (int j = MAX(i-Sdiag,0) ; j<MIN(SNumGlobalCols, i+Sdiag); j++) for (int j = MAX(i-Sdiag, 0) ; j < MIN(data->Snr, i+Sdiag); j++) { // find the adjacent columns from the row map of S //assert (j >= 0 && j < Snr); RightIndex[rcnt++] = data->SRowElems[j]; } err = Sg->InsertGlobalIndices(gid, rcnt, RightIndex); assert(err == 0); // Always insert the diagonals, if it is added twice that is fine. err = Sg->InsertGlobalIndices(gid, 1, &gid); assert(err == 0); } if (config->schurApproxMethod == 1) Sg->FillComplete(); delete DRowMap; delete SRowMap; delete DColMap; } #if 0 if (insertValues) { #ifdef TIMING_OUTPUT Teuchos::Time ttime("transpose time"); ttime.start(); #endif bool MakeDataContiguous = true; ssym->transposer = Teuchos::RCP<EpetraExt::RowMatrix_Transpose>(new EpetraExt::RowMatrix_Transpose(MakeDataContiguous)); ssym->DT = Teuchos::rcp( dynamic_cast<Epetra_CrsMatrix *>(&(*ssym->transposer)(*D)), false); #ifdef TIMING_OUTPUT ttime.stop(); cout << "Transpose Time" << ttime.totalElapsedTime() << endl; ttime.reset(); #endif } else { ssym->transposer->fwd(); //ssym->ReIdx_LP->fwd(); // TODO: Needed ? } #endif // A is no longer needed delete[] LeftIndex; delete[] LeftValues; delete[] RightIndex; delete[] RightValues; //cout << msg << "S rows=" << S.NumGlobalRows() << " S cols=" << //S.NumGlobalCols() << "#cols in column map="<< //S.ColMap().NumMyElements() << endl; //cout << msg << "C rows=" << Cptr->NumGlobalRows() << " C cols=" << //Cptr->NumGlobalCols() << "#cols in column map="<< //Cptr->ColMap().NumMyElements() << endl; //cout << msg << "D rows=" << D.NumGlobalRows() << " D cols=" << //D.NumGlobalCols() << "#cols in column map="<< //D.ColMap().NumMyElements() << endl; //cout << msg << "R rows=" << Rptr->NumGlobalRows() << " R cols=" << //Rptr->NumGlobalCols() << "#cols in column map="<< //Rptr->ColMap().NumMyElements() << endl; // ] return 0; }
//---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( DomainTransporter, Boundary ) { typedef Epetra_Vector VectorType; typedef Epetra_RowMatrix MatrixType; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; typedef MCLS::AdjointHistory<int> HistoryType; typedef std::mt19937 rng_type; typedef MCLS::AdjointDomain<VectorType,MatrixType,rng_type> DomainType; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm ); int comm_size = comm->getSize(); int comm_rank = comm->getRank(); // This test really needs a decomposed domain such that we can check // hitting the local domain boundary. if ( comm_size > 1 ) { int local_num_rows = 10; int global_num_rows = local_num_rows*comm_size; Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); // Build the linear operator and solution vector. This operator will // be assymetric so we quickly move the histories out of the domain // before they hit the low weight cutoff. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 3 ); Teuchos::Array<double> values( 3 ); global_columns[0] = 0; global_columns[1] = 1; global_columns[2] = 2; values[0] = 1.0; values[1] = 0.49; values[2] = 0.49; A->InsertGlobalValues( 0, global_columns.size(), &values[0], &global_columns[0] ); for ( int i = 1; i < global_num_rows-1; ++i ) { global_columns[0] = i-1; global_columns[1] = i; global_columns[2] = i+1; values[0] = 0.49; values[1] = 1.0; values[2] = 0.49; A->InsertGlobalValues( i, global_columns.size(), &values[0], &global_columns[0] ); } global_columns[0] = global_num_rows-3; global_columns[1] = global_num_rows-2; global_columns[2] = global_num_rows-1; values[0] = 0.49; values[1] = 0.49; values[2] = 1.0; A->InsertGlobalValues( global_num_rows-1, global_columns().size(), &values[0], &global_columns[0] ); A->FillComplete(); Teuchos::RCP<MatrixType> B = MT::copyTranspose(*A); Teuchos::RCP<VectorType> x = MT::cloneVectorFromMatrixRows( *A ); // Build the adjoint domain. Teuchos::ParameterList plist; plist.set<int>( "Overlap Size", 2 ); Teuchos::RCP<DomainType> domain = Teuchos::rcp( new DomainType( B, x, plist ) ); Teuchos::RCP<MCLS::PRNG<rng_type> > rng = Teuchos::rcp( new MCLS::PRNG<rng_type>( comm->getRank() ) ); domain->setRNG( rng ); // Build the domain transporter. MCLS::DomainTransporter<DomainType> transporter( domain, plist ); domain->setCutoff( 1.0e-12 ); // Transport histories through the domain until they hit a boundary. double weight = 3.0; for ( int i = 0; i < global_num_rows-1; ++i ) { if ( comm_rank == comm_size - 1 ) { if ( i >= local_num_rows*comm_rank && i < local_num_rows*(comm_rank+1) ) { HistoryType history( i, i, weight ); history.live(); transporter.transport( history ); TEST_ASSERT( history.event() == MCLS::Event::BOUNDARY || MCLS::Event::CUTOFF ); TEST_ASSERT( !history.alive() ); } } else { if ( i >= local_num_rows*comm_rank && i < 2+local_num_rows*(comm_rank+1) ) { HistoryType history( i, i, weight ); history.live(); transporter.transport( history ); TEST_ASSERT( history.event() == MCLS::Event::BOUNDARY || MCLS::Event::CUTOFF ); TEST_ASSERT( !history.alive() ); } } } } }
int main(int argc, char *argv[]) { int i, j, info; const double one = 1.0; const double zero = 0.0; Teuchos::LAPACK<int,double> lapack; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int MyPID = Comm.MyPID(); // Dimension of the matrix int m = 500; int n = 100; // Construct a Map that puts approximately the same number of // equations on each processor. Epetra_Map RowMap(m, 0, Comm); Epetra_Map ColMap(n, 0, Comm); // Get update list and number of local equations from newly created Map. int NumMyRowElements = RowMap.NumMyElements(); std::vector<int> MyGlobalRowElements(NumMyRowElements); RowMap.MyGlobalElements(&MyGlobalRowElements[0]); /* We are building an m by n matrix with entries A(i,j) = k*(si)*(tj - 1) if i <= j = k*(tj)*(si - 1) if i > j where si = i/(m+1) and tj = j/(n+1) and k = 1/(n+1). */ // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, RowMap, n) ); // Compute coefficients for discrete integral operator std::vector<double> Values(n); std::vector<int> Indices(n); double inv_mp1 = one/(m+1); double inv_np1 = one/(n+1); for (i=0; i<n; i++) { Indices[i] = i; } for (i=0; i<NumMyRowElements; i++) { // for (j=0; j<n; j++) { // if ( MyGlobalRowElements[i] <= j ) { Values[j] = inv_np1 * ( (MyGlobalRowElements[i]+one)*inv_mp1 ) * ( (j+one)*inv_np1 - one ); // k*(si)*(tj-1) } else { Values[j] = inv_np1 * ( (j+one)*inv_np1 ) * ( (MyGlobalRowElements[i]+one)*inv_mp1 - one ); // k*(tj)*(si-1) } } info = A->InsertGlobalValues(MyGlobalRowElements[i], n, &Values[0], &Indices[0]); assert( info==0 ); } // Finish up info = A->FillComplete(ColMap, RowMap); assert( info==0 ); info = A->OptimizeStorage(); assert( info==0 ); A->SetTracebackMode(1); // Shutdown Epetra Warning tracebacks //************************************ // Start the block Arnoldi iteration //*********************************** // // Variables used for the Block Arnoldi Method // int nev = 4; int blockSize = 1; int numBlocks = 10; int maxRestarts = 20; int verbosity = Anasazi::Errors + Anasazi::Warnings + Anasazi::FinalSummary; double tol = lapack.LAMCH('E'); std::string which = "LM"; // // Create parameter list to pass into solver // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Num Blocks", numBlocks ); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); typedef Anasazi::MultiVec<double> MV; typedef Anasazi::Operator<double> OP; // Create an Anasazi::EpetraMultiVec for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. Teuchos::RCP<Anasazi::EpetraMultiVec> ivec = Teuchos::rcp( new Anasazi::EpetraMultiVec(ColMap, blockSize) ); ivec->MvRandom(); // Call the constructor for the (A^T*A) operator Teuchos::RCP<Anasazi::EpetraSymOp> Amat = Teuchos::rcp( new Anasazi::EpetraSymOp(A) ); Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(Amat, ivec) ); // Inform the eigenproblem that the matrix A is symmetric MyProblem->setHermitian(true); // Set the number of eigenvalues requested and the blocksize the solver should use MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finished passing it information bool boolret = MyProblem->setProblem(); if (boolret != true) { if (MyPID == 0) { cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::BlockKrylovSchurSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); if (returnCode != Anasazi::Converged && MyPID==0) { cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << endl; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<double,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<double> > evals = sol.Evals; int numev = sol.numVecs; if (numev > 0) { // Compute singular values/vectors and direct residuals. // // Compute singular values which are the square root of the eigenvalues if (MyPID==0) { cout<<"------------------------------------------------------"<<endl; cout<<"Computed Singular Values: "<<endl; cout<<"------------------------------------------------------"<<endl; } for (i=0; i<numev; i++) { evals[i].realpart = Teuchos::ScalarTraits<double>::squareroot( evals[i].realpart ); } // // Compute left singular vectors : u = Av/sigma // std::vector<double> tempnrm(numev), directnrm(numev); std::vector<int> index(numev); for (i=0; i<numev; i++) { index[i] = i; } Anasazi::EpetraMultiVec Av(RowMap,numev), u(RowMap,numev); Anasazi::EpetraMultiVec* evecs = dynamic_cast<Anasazi::EpetraMultiVec* >(sol.Evecs->CloneViewNonConst( index )); Teuchos::SerialDenseMatrix<int,double> S(numev,numev); A->Apply( *evecs, Av ); Av.MvNorm( tempnrm ); for (i=0; i<numev; i++) { S(i,i) = one/tempnrm[i]; }; u.MvTimesMatAddMv( one, Av, S, zero ); // // Compute direct residuals : || Av - sigma*u || // for (i=0; i<numev; i++) { S(i,i) = evals[i].realpart; } Av.MvTimesMatAddMv( -one, u, S, one ); Av.MvNorm( directnrm ); if (MyPID==0) { cout.setf(std::ios_base::right, std::ios_base::adjustfield); cout<<std::setw(16)<<"Singular Value" <<std::setw(20)<<"Direct Residual" <<endl; cout<<"------------------------------------------------------"<<endl; for (i=0; i<numev; i++) { cout<<std::setw(16)<<evals[i].realpart <<std::setw(20)<<directnrm[i] <<endl; } cout<<"------------------------------------------------------"<<endl; } } #ifdef EPETRA_MPI MPI_Finalize() ; #endif return 0; }
/* Apply an identity matrix to the Schur complement operator. Drop the entries entries using a relative threshold. Assemble the result in a Crs Matrix which will be our approximate Schur complement. */ Teuchos::RCP<Epetra_CrsMatrix> computeApproxSchur(shylu_config *config, shylu_symbolic *sym, Epetra_CrsMatrix *G, Epetra_CrsMatrix *R, Epetra_LinearProblem *LP, Amesos_BaseSolver *solver, Ifpack_Preconditioner *ifSolver, Epetra_CrsMatrix *C, Epetra_Map *localDRowMap) { double relative_thres = config->relative_threshold; int nvectors = 16; ShyLU_Probing_Operator probeop(config, sym, G, R, LP, solver, ifSolver, C, localDRowMap, nvectors); // Get row map Epetra_Map rMap = G->RowMap(); int *rows = rMap.MyGlobalElements(); int totalElems = rMap.NumGlobalElements(); int localElems = rMap.NumMyElements(); //cout << " totalElems in Schur Complement" << totalElems << endl; //cout << myPID << " localElems" << localElems << endl; // **************** Two collectives here ********************* #ifdef TIMING_OUTPUT Teuchos::Time ftime("setup time"); ftime.start(); #endif int prefixSum; G->Comm().ScanSum(&localElems, &prefixSum, 1); //cout << " prefixSum" << prefixSum << endl; // Start the index in prefixSum-localElems int *mySGID = new int[totalElems]; // vector of size Schur complement ! int *allSGID = new int[totalElems]; // vector of size Schur complement ! int i, j; for (i = 0, j = 0; i < totalElems ; i++) { if (i >= prefixSum - localElems && i < prefixSum) { mySGID[i] = rows[j]; j++; } else { mySGID[i] = 0; } allSGID[i] = 0; } C->Comm().SumAll(mySGID, allSGID, totalElems); #ifdef TIMING_OUTPUT ftime.stop(); cout << "Time to Compute RowIDS" << ftime.totalElapsedTime() << endl; ftime.reset(); #endif // Now everyone knows the GIDs in the Schur complement //cout << rMap << endl; j = 0; Teuchos::RCP<Epetra_CrsMatrix> Sbar = Teuchos::rcp(new Epetra_CrsMatrix( Copy, rMap, localElems)); int nentries; double *values = new double[localElems]; // Need to adjust this for more int *indices = new int[localElems]; // than one vector double *vecvalues; int dropped = 0; double *maxvalue = new double[nvectors]; #ifdef TIMING_OUTPUT ftime.start(); #endif #ifdef TIMING_OUTPUT Teuchos::Time app_time("Apply time"); #endif int findex = totalElems / nvectors ; for (i = 0 ; i < findex*nvectors ; i+=nvectors) { Epetra_MultiVector probevec(rMap, nvectors); Epetra_MultiVector Scol(rMap, nvectors); probevec.PutScalar(0.0); int cindex; for (int k = 0; k < nvectors; k++) { cindex = k+i; if (cindex >= prefixSum - localElems && cindex < prefixSum) { probevec.ReplaceGlobalValue(allSGID[cindex], k, 1.0); } } #ifdef TIMING_OUTPUT app_time.start(); #endif probeop.Apply(probevec, Scol); #ifdef TIMING_OUTPUT app_time.stop(); #endif Scol.MaxValue(maxvalue); for (int k = 0; k < nvectors; k++) //TODO:Need to switch these loops { cindex = k+i; vecvalues = Scol[k]; //cout << "MAX" << maxvalue << endl; for (j = 0 ; j < localElems ; j++) { nentries = 0; // inserting one entry in each row for now if (allSGID[cindex] == rows[j]) // diagonal entry { values[nentries] = vecvalues[j]; indices[nentries] = allSGID[cindex]; nentries++; Sbar->InsertGlobalValues(rows[j], nentries, values, indices); } else if (abs(vecvalues[j]/maxvalue[k]) > relative_thres) { values[nentries] = vecvalues[j]; indices[nentries] = allSGID[cindex]; nentries++; Sbar->InsertGlobalValues(rows[j], nentries, values, indices); } else { if (vecvalues[j] != 0.0) dropped++; } } } } probeop.ResetTempVectors(1); for ( ; i < totalElems ; i++) { Epetra_MultiVector probevec(rMap, 1); // TODO: Try doing more than one Epetra_MultiVector Scol(rMap, 1); // vector at a time probevec.PutScalar(0.0); if (i >= prefixSum - localElems && i < prefixSum) { probevec.ReplaceGlobalValue(allSGID[i], 0, 1.0); } #ifdef TIMING_OUTPUT app_time.start(); #endif probeop.Apply(probevec, Scol); #ifdef TIMING_OUTPUT app_time.stop(); #endif vecvalues = Scol[0]; Scol.MaxValue(maxvalue); //cout << "MAX" << maxvalue << endl; for (j = 0 ; j < localElems ; j++) { nentries = 0; // inserting one entry in each row for now if (allSGID[i] == rows[j]) // diagonal entry { values[nentries] = vecvalues[j]; indices[nentries] = allSGID[i]; nentries++; Sbar->InsertGlobalValues(rows[j], nentries, values, indices); } else if (abs(vecvalues[j]/maxvalue[0]) > relative_thres) { values[nentries] = vecvalues[j]; indices[nentries] = allSGID[i]; nentries++; Sbar->InsertGlobalValues(rows[j], nentries, values, indices); } else { if (vecvalues[j] != 0.0) dropped++; } } } #ifdef TIMING_OUTPUT ftime.stop(); cout << "Time in finding and dropping entries" << ftime.totalElapsedTime() << endl; ftime.reset(); #endif #ifdef TIMING_OUTPUT cout << "Time in Apply of probing" << app_time.totalElapsedTime() << endl; #endif Sbar->FillComplete(); cout << "#dropped entries" << dropped << endl; delete[] allSGID; delete[] mySGID; delete[] values; delete[] indices; delete[] maxvalue; return Sbar; }
//---------------------------------------------------------------------------// // Test templates //---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( SolverFactory, mcsa_two_by_two ) { typedef Epetra_Vector VectorType; typedef MCLS::VectorTraits<VectorType> VT; typedef Epetra_RowMatrix MatrixType; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); int comm_size = comm->getSize(); int comm_rank = comm->getRank(); // This is a 4 processor test. if ( comm_size == 4 ) { // Build the set-constant communicator. Teuchos::Array<int> ranks(2); if ( comm_rank < 2 ) { ranks[0] = 0; ranks[1] = 1; } else { ranks[0] = 2; ranks[1] = 3; } Teuchos::RCP<const Teuchos::Comm<int> > comm_set = comm->createSubcommunicator( ranks() ); int set_size = comm_set->getSize(); // Declare the linear problem in the global scope. Teuchos::RCP<MCLS::LinearProblem<VectorType,MatrixType> > linear_problem; // Build the linear system on set 0. if ( comm_rank < 2 ) { int local_num_rows = 10; int global_num_rows = local_num_rows*set_size; Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm_set ); Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); // Build the linear system. This operator is symmetric with a spectral // radius less than 1. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 3 ); Teuchos::Array<double> values( 3 ); global_columns[0] = 0; global_columns[1] = 1; global_columns[2] = 2; values[0] = 1.0; values[1] = 0.05; values[2] = 0.05; A->InsertGlobalValues( 0, global_columns.size(), &values[0], &global_columns[0] ); for ( int i = 1; i < global_num_rows-1; ++i ) { global_columns[0] = i-1; global_columns[1] = i; global_columns[2] = i+1; values[0] = 0.05; values[1] = 1.0; values[2] = 0.05; A->InsertGlobalValues( i, global_columns.size(), &values[0], &global_columns[0] ); } global_columns[0] = global_num_rows-3; global_columns[1] = global_num_rows-2; global_columns[2] = global_num_rows-1; values[0] = 0.05; values[1] = 0.05; values[2] = 1.0; A->InsertGlobalValues( global_num_rows-1, global_columns.size(), &values[0], &global_columns[0] ); A->FillComplete(); Teuchos::RCP<MatrixType> B = A; // Build the LHS. Put a large positive number here to be sure we are // clear the vector before solving. Teuchos::RCP<VectorType> x = MT::cloneVectorFromMatrixRows( *B ); VT::putScalar( *x, 0.0 ); // Build the RHS with negative numbers. this gives us a negative // solution. Teuchos::RCP<VectorType> b = MT::cloneVectorFromMatrixRows( *B ); VT::putScalar( *b, -1.0 ); // Create the linear problem. linear_problem = Teuchos::rcp( new MCLS::LinearProblem<VectorType,MatrixType>(B, x, b) ); } comm->barrier(); // Solver parameters. Teuchos::RCP<Teuchos::ParameterList> plist = Teuchos::rcp( new Teuchos::ParameterList() ); double cutoff = 1.0e-4; plist->set<std::string>("MC Type", "Adjoint"); plist->set<double>("Convergence Tolerance", 1.0e-8); plist->set<int>("Maximum Iterations", 10); plist->set<double>("Weight Cutoff", cutoff); plist->set<int>("Iteration Print Frequency", 1); plist->set<int>("MC Check Frequency", 50); plist->set<bool>("Reproducible MC Mode",true); plist->set<int>("Overlap Size", 2); plist->set<int>("Number of Sets", 2); plist->set<double>("Sample Ratio", 10.0); plist->set<std::string>("Transport Type", "Global" ); // Create the solver. MCLS::SolverFactory<VectorType,MatrixType> factory; Teuchos::RCP<MCLS::SolverManager<VectorType,MatrixType> > solver_manager = factory.create( "MCSA", comm, plist ); solver_manager->setProblem( linear_problem ); // Solve the problem. bool converged_status = solver_manager->solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager->getConvergedStatus() ); TEST_ASSERT( solver_manager->getNumIters() < 10 ); if ( comm_rank < 2 ) { TEST_ASSERT( solver_manager->achievedTol() > 0.0 ); } else { TEST_ASSERT( solver_manager->achievedTol() == 0.0 ); } if ( comm_rank < 2 ) { // Check that we got a negative solution. Teuchos::ArrayRCP<const double> x_view = VT::view( *linear_problem->getLHS() ); Teuchos::ArrayRCP<const double>::const_iterator x_view_it; for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it < Teuchos::ScalarTraits<double>::zero() ); } } comm->barrier(); // Now solve the problem with a positive source. if ( comm_rank < 2 ) { Teuchos::RCP<VectorType> b = MT::cloneVectorFromMatrixRows( *linear_problem->getOperator() ); VT::putScalar( *b, 2.0 ); linear_problem->setRHS( b ); VT::putScalar( *linear_problem->getLHS(), 0.0 ); } comm->barrier(); converged_status = solver_manager->solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager->getConvergedStatus() ); TEST_ASSERT( solver_manager->getNumIters() < 10 ); if ( comm_rank < 2 ) { TEST_ASSERT( solver_manager->achievedTol() > 0.0 ); } else { TEST_ASSERT( solver_manager->achievedTol() == 0.0 ); } if ( comm_rank < 2 ) { Teuchos::ArrayRCP<const double> x_view = VT::view( *linear_problem->getLHS() ); Teuchos::ArrayRCP<const double>::const_iterator x_view_it; for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it > Teuchos::ScalarTraits<double>::zero() ); } } comm->barrier(); // Reset the domain and solve again with a positive source. if ( comm_rank < 2 ) { VT::putScalar( *linear_problem->getLHS(), 0.0 ); } comm->barrier(); solver_manager->setProblem( linear_problem ); converged_status = solver_manager->solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager->getConvergedStatus() ); TEST_ASSERT( solver_manager->getNumIters() < 10 ); if ( comm_rank < 2 ) { TEST_ASSERT( solver_manager->achievedTol() > 0.0 ); } else { TEST_ASSERT( solver_manager->achievedTol() == 0.0 ); } if ( comm_rank < 2 ) { Teuchos::ArrayRCP<const double> x_view = VT::view( *linear_problem->getLHS() ); Teuchos::ArrayRCP<const double>::const_iterator x_view_it; for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it > Teuchos::ScalarTraits<double>::zero() ); } } comm->barrier(); // Reset both and solve with a negative source. if ( comm_rank < 2 ) { Teuchos::RCP<VectorType> b = MT::cloneVectorFromMatrixRows( *linear_problem->getOperator() ); VT::putScalar( *b, -2.0 ); linear_problem->setRHS( b ); VT::putScalar( *linear_problem->getLHS(), 0.0 ); } comm->barrier(); converged_status = solver_manager->solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager->getConvergedStatus() ); TEST_ASSERT( solver_manager->getNumIters() < 10 ); if ( comm_rank < 2 ) { TEST_ASSERT( solver_manager->achievedTol() > 0.0 ); } else { TEST_ASSERT( solver_manager->achievedTol() == 0.0 ); } if ( comm_rank < 2 ) { Teuchos::ArrayRCP<const double> x_view = VT::view( *linear_problem->getLHS() ); Teuchos::ArrayRCP<const double>::const_iterator x_view_it; for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it < Teuchos::ScalarTraits<double>::zero() ); } } comm->barrier(); } }
//---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( SourceTransporter, transport ) { typedef Epetra_Vector VectorType; typedef MCLS::VectorTraits<VectorType> VT; typedef Epetra_RowMatrix MatrixType; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; typedef MCLS::AdjointHistory<int> HistoryType; typedef std::mt19937 rng_type; typedef MCLS::AdjointDomain<VectorType,MatrixType,rng_type> DomainType; typedef MCLS::UniformAdjointSource<DomainType> SourceType; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm ); int comm_size = comm->getSize(); int local_num_rows = 10; int global_num_rows = local_num_rows*comm_size; Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); // Build the linear system. This operator is symmetric with a spectral // radius less than 1. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 3 ); Teuchos::Array<double> values( 3 ); global_columns[0] = 0; global_columns[1] = 1; global_columns[2] = 2; values[0] = 1.0/comm_size; values[1] = 0.12/comm_size; values[2] = 0.0/comm_size; A->InsertGlobalValues( 0, global_columns.size(), &values[0], &global_columns[0] ); for ( int i = 1; i < global_num_rows-1; ++i ) { global_columns[0] = i-1; global_columns[1] = i; global_columns[2] = i+1; values[0] = 0.12/comm_size; values[1] = 1.0/comm_size; values[2] = 0.12/comm_size; A->InsertGlobalValues( i, global_columns.size(), &values[0], &global_columns[0] ); } global_columns[0] = global_num_rows-3; global_columns[1] = global_num_rows-2; global_columns[2] = global_num_rows-1; values[0] = 0.0/comm_size; values[1] = 0.12/comm_size; values[2] = 1.0/comm_size; A->InsertGlobalValues( global_num_rows-1, global_columns.size(), &values[0], &global_columns[0] ); A->FillComplete(); Teuchos::RCP<MatrixType> B = MT::copyTranspose(*A); Teuchos::RCP<VectorType> x = MT::cloneVectorFromMatrixRows( *B ); VT::putScalar( *x, 0.0 ); Teuchos::RCP<VectorType> b = MT::cloneVectorFromMatrixRows( *B ); VT::putScalar( *b, -1.0 ); // Build the adjoint domain. Teuchos::ParameterList plist; plist.set<int>( "Overlap Size", 2 ); Teuchos::RCP<DomainType> domain = Teuchos::rcp( new DomainType( B, x, plist ) ); Teuchos::RCP<MCLS::PRNG<rng_type> > rng = Teuchos::rcp( new MCLS::PRNG<rng_type>( comm->getRank() ) ); domain->setRNG( rng ); // History setup. HistoryType::setByteSize(); // Create the adjoint source with a set number of histories. int mult = 100; double cutoff = 1.0e-6; plist.set<double>("Sample Ratio", mult); plist.set<double>("Weight Cutoff", cutoff); Teuchos::RCP<SourceType> source = Teuchos::rcp( new SourceType( b, domain, comm, comm->getSize(), comm->getRank(), plist ) ); source->setRNG( rng ); source->buildSource(); // Create the source transporter. plist.set<int>("MC Check Frequency", 10); double relative_cutoff = source->sourceWeight()*cutoff; MCLS::SourceTransporter<SourceType> source_transporter( comm, domain, plist ); source_transporter.assignSource( source, relative_cutoff ); // Do transport. source_transporter.transport(); domain->domainTally()->combineSetTallies( comm ); // Check that we got a negative solution. Teuchos::ArrayRCP<const double> x_view = VT::view( *x ); Teuchos::ArrayRCP<const double>::const_iterator x_view_it; for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it < 0.0 ); } }
int main(int argc, char *argv[]) { using std::cout; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif bool boolret; int MyPID = Comm.MyPID(); bool verbose = true; bool debug = false; bool dynXtraNev = false; std::string which("SM"); int nx = 10; // Discretization points in any one direction. int nev = 10; int blockSize = 3; int numBlocks = 10; double tol = 1e-5; Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","nodebug",&debug,"Print debugging information."); cmdp.setOption("sort",&which,"Targetted eigenvalues (SM,LM,SR,LR,SI,or LI)."); cmdp.setOption("nx",&nx,"Number of discretization points in each direction; n=nx*nx."); cmdp.setOption("nev",&nev,"Number of eigenvalues to compute."); cmdp.setOption("blocksize",&blockSize,"Block Size."); cmdp.setOption("tol",&tol,"Solver Tolerance."); cmdp.setOption("numblocks",&numBlocks,"Number of blocks for the Krylov-Schur form."); cmdp.setOption("dynrestart","nodynrestart",&dynXtraNev,"Use dynamic restart boundary to accelerate convergence."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } typedef double ScalarType; typedef Teuchos::ScalarTraits<ScalarType> SCT; typedef SCT::magnitudeType MagnitudeType; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<ScalarType,MV> MVT; typedef Anasazi::OperatorTraits<ScalarType,MV,OP> OPT; // Dimension of the matrix int NumGlobalElements = nx*nx; // Size of matrix nx*nx // Construct a Map that puts approximately the same number of // equations on each processor. Epetra_Map Map(NumGlobalElements, 0, Comm); // Get update list and number of local equations from newly created Map. int NumMyElements = Map.NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map.MyGlobalElements(&MyGlobalElements[0]); // Create an integer vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of OFF-DIAGONAL term for the ith global equation // on this processor std::vector<int> NumNz(NumMyElements); /* We are building a matrix of block structure: | T -I | |-I T -I | | -I T | | ... -I| | -I T| where each block is dimension nx by nx and the matrix is on the order of nx*nx. The block T is a tridiagonal matrix. */ for (int i=0; i<NumMyElements; i++) { if (MyGlobalElements[i] == 0 || MyGlobalElements[i] == NumGlobalElements-1 || MyGlobalElements[i] == nx-1 || MyGlobalElements[i] == nx*(nx-1) ) { NumNz[i] = 3; } else if (MyGlobalElements[i] < nx || MyGlobalElements[i] > nx*(nx-1) || MyGlobalElements[i]%nx == 0 || (MyGlobalElements[i]+1)%nx == 0) { NumNz[i] = 4; } else { NumNz[i] = 5; } } // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, Map, &NumNz[0]) ); // Compute coefficients for discrete convection-diffution operator const double one = 1.0; std::vector<double> Values(4); std::vector<int> Indices(4); double h = one /(nx+1); double h2 = h*h; Values[0] = -one/h2; Values[1] = -one/h2; Values[2] = -one/h2; Values[3]= -one/h2; double diag = 4.0 / h2; int NumEntries, info; for (int i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0) { Indices[0] = 1; Indices[1] = nx; NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == nx*(nx-1)) { Indices[0] = nx*(nx-1)+1; Indices[1] = nx*(nx-2); NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == nx-1) { Indices[0] = nx-2; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); Indices[0] = 2*nx-1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == NumGlobalElements-1) { Indices[0] = NumGlobalElements-2; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); Indices[0] = nx*(nx-1)-1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] < nx) { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]+nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] > nx*(nx-1)) { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]-nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i]%nx == 0) { Indices[0] = MyGlobalElements[i]+1; Indices[1] = MyGlobalElements[i]-nx; Indices[2] = MyGlobalElements[i]+nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if ((MyGlobalElements[i]+1)%nx == 0) { Indices[0] = MyGlobalElements[i]-nx; Indices[1] = MyGlobalElements[i]+nx; NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); Indices[0] = MyGlobalElements[i]-1; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]-nx; Indices[3] = MyGlobalElements[i]+nx; NumEntries = 4; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } // Put in the diagonal entry info = A->InsertGlobalValues(MyGlobalElements[i], 1, &diag, &MyGlobalElements[i]); assert( info==0 ); } // Finish up info = A->FillComplete(); assert( info==0 ); A->SetTracebackMode(1); // Shutdown Epetra Warning tracebacks //************************************ // Start the block Arnoldi iteration //*********************************** // // Variables used for the Block Krylov Schur Method // int maxRestarts = 500; // Create a sort manager to pass into the block Krylov-Schur solver manager // --> Make sure the reference-counted pointer is of type Anasazi::SortManager<> // --> The block Krylov-Schur solver manager uses Anasazi::BasicSort<> by default, // so you can also pass in the parameter "Which", instead of a sort manager. Teuchos::RCP<Anasazi::SortManager<MagnitudeType> > MySort = Teuchos::rcp( new Anasazi::BasicSort<MagnitudeType>( which ) ); // Set verbosity level int verbosity = Anasazi::Errors + Anasazi::Warnings; if (verbose) { verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails; } if (debug) { verbosity += Anasazi::Debug; } // // Create parameter list to pass into solver manager // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Sort Manager", MySort ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Num Blocks", numBlocks ); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); MyPL.set("Dynamic Extra NEV",dynXtraNev); // Create an Epetra_MultiVector for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(Map, blockSize) ); ivec->Random(); // Create the eigenproblem. Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(A, ivec) ); // Inform the eigenproblem that the operator A is symmetric MyProblem->setHermitian(true); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finishing passing it information boolret = MyProblem->setProblem(); if (boolret != true) { if (verbose && MyPID == 0) { std::cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << std::endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::BlockKrylovSchurSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length bool testFailed = false; Anasazi::ReturnType returnCode = MySolverMgr.solve(); if (returnCode != Anasazi::Converged) { testFailed = true; if (MyPID==0 && verbose) std::cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << std::endl; } // Get the Ritz values from the eigensolver std::vector<Anasazi::Value<double> > ritzValues = MySolverMgr.getRitzValues(); // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { int numritz = (int)ritzValues.size(); std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<std::endl<< "Computed Ritz Values"<< std::endl; std::cout<< std::setw(16) << "Real Part" << std::endl; std::cout<<"-----------------------------------------------------------"<<std::endl; for (int i=0; i<numritz; i++) { std::cout<< std::setw(16) << ritzValues[i].realpart << std::endl; } std::cout<<"-----------------------------------------------------------"<<std::endl; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<ScalarType,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<ScalarType> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; std::vector<int> index = sol.index; int numev = sol.numVecs; if (numev > 0) { // Compute residuals. std::vector<double> normA(numev); // Get storage Epetra_MultiVector Aevecs(Map,numev); Teuchos::SerialDenseMatrix<int,double> B(numev,numev); B.putScalar(0.0); for (int i=0; i<numev; i++) {B(i,i) = evals[i].realpart;} // Compute A*evecs OPT::Apply( *A, *evecs, Aevecs ); // Compute A*evecs - lambda*evecs and its norm MVT::MvTimesMatAddMv( -1.0, *evecs, B, 1.0, Aevecs ); MVT::MvNorm( Aevecs, normA ); // Scale the norms by the eigenvalue for (int i=0; i<numev; i++) { normA[i] /= Teuchos::ScalarTraits<double>::magnitude( evals[i].realpart ); if ( normA[i] > tol ) { testFailed = true; } } // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<std::endl<< "Actual Residuals"<<std::endl; std::cout<< std::setw(16) << "Real Part" << std::setw(20) << "Direct Residual"<< std::endl; std::cout<<"-----------------------------------------------------------"<<std::endl; for (int i=0; i<numev; i++) { std::cout<< std::setw(16) << evals[i].realpart << std::setw(20) << normA[i] << std::endl; } std::cout<<"-----------------------------------------------------------"<<std::endl; } } #ifdef EPETRA_MPI MPI_Finalize(); #endif if (testFailed) { if (verbose && MyPID==0) { std::cout << "End Result: TEST FAILED" << std::endl; } return -1; } // // Default return value // if (verbose && MyPID==0) { std::cout << "End Result: TEST PASSED" << std::endl; } return 0; }
TEUCHOS_UNIT_TEST( MCSA, MCSA_test) { int problem_size = 16; Epetra_SerialComm comm; Epetra_Map map( problem_size, 0, comm ); std::vector<double> x_vector( problem_size ); Epetra_Vector x( View, map, &x_vector[0] ); std::vector<double> x_aztec_vector( problem_size ); Epetra_Vector x_aztec( View, map, &x_aztec_vector[0] ); std::vector<double> b_vector( problem_size, 0.4 ); Epetra_Vector b( View, map, &b_vector[0] ); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, map, problem_size ) ); double lower_diag = -0.1; double diag = 2.4; double upper_diag = -0.1; int global_row = 0; int lower_row = 0; int upper_row = 0; for ( int i = 0; i < problem_size; ++i ) { global_row = A->GRID(i); lower_row = i-1; upper_row = i+1; if ( lower_row > -1 ) { A->InsertGlobalValues( global_row, 1, &lower_diag, &lower_row ); } A->InsertGlobalValues( global_row, 1, &diag, &global_row ); if ( upper_row < problem_size ) { A->InsertGlobalValues( global_row, 1, &upper_diag, &upper_row ); } } A->FillComplete(); double spec_rad_A = HMCSA::OperatorTools::spectralRadius( A ); std::cout << std::endl << "Operator spectral radius: " << spec_rad_A << std::endl; Teuchos::RCP<Epetra_LinearProblem> linear_problem = Teuchos::rcp( new Epetra_LinearProblem( A.getRawPtr(), &x, &b ) ); HMCSA::JacobiPreconditioner preconditioner( linear_problem ); preconditioner.precondition(); HMCSA::MCSA mcsa_solver( linear_problem ); mcsa_solver.iterate( 100, 1.0e-8, 100, 1.0e-8 ); std::cout << "MCSA ITERS: " << mcsa_solver.getNumIters() << std::endl; Epetra_LinearProblem aztec_linear_problem( A.getRawPtr(), &x_aztec, &b ); AztecOO aztec_solver( aztec_linear_problem ); aztec_solver.SetAztecOption( AZ_solver, AZ_gmres ); aztec_solver.Iterate( 100, 1.0e-8 ); std::vector<double> error_vector( problem_size ); Epetra_Vector error( View, map, &error_vector[0] ); for (int i = 0; i < problem_size; ++i) { error[i] = x[i] - x_aztec[i]; } double error_norm; error.Norm2( &error_norm ); std::cout << std::endl << "Aztec GMRES vs. MCSA absolute error L2 norm: " << error_norm << std::endl; }
/* Computes the approximate Schur complement for the wide separator */ Teuchos::RCP<Epetra_CrsMatrix> computeApproxWideSchur(shylu_config *config, shylu_symbolic *ssym, // symbolic structure Epetra_CrsMatrix *G, Epetra_CrsMatrix *R, Epetra_LinearProblem *LP, Amesos_BaseSolver *solver, Ifpack_Preconditioner *ifSolver, Epetra_CrsMatrix *C, Epetra_Map *localDRowMap) { int i; double relative_thres = config->relative_threshold; // Need to create local G (block diagonal portion) , R, C // Get row map of G //Epetra_Map CrMap = C->RowMap(); //int *c_rows = CrMap.MyGlobalElements(); //int *c_cols = (C->ColMap()).MyGlobalElements(); //int c_totalElems = CrMap.NumGlobalElements(); //int c_localElems = CrMap.NumMyElements(); //int c_localcolElems = (C->ColMap()).NumMyElements(); Epetra_Map GrMap = G->RowMap(); int *g_rows = GrMap.MyGlobalElements(); //int g_totalElems = GrMap.NumGlobalElements(); int g_localElems = GrMap.NumMyElements(); //Epetra_Map RrMap = R->RowMap(); //int *r_rows = RrMap.MyGlobalElements(); //int *r_cols = (R->ColMap()).MyGlobalElements(); //int r_totalElems = RrMap.NumGlobalElements(); //int r_localElems = RrMap.NumMyElements(); //int r_localcolElems = (R->ColMap()).NumMyElements(); Epetra_SerialComm LComm; Epetra_Map G_localRMap (-1, g_localElems, g_rows, 0, LComm); int nentries1, gid; // maxentries is the maximum of all three possible matrices as the arrays // are reused between the three int maxentries = max(C->MaxNumEntries(), R->MaxNumEntries()); maxentries = max(maxentries, G->MaxNumEntries()); double *values1 = new double[maxentries]; double *values2 = new double[maxentries]; double *values3 = new double[maxentries]; int *indices1 = new int[maxentries]; int *indices2 = new int[maxentries]; int *indices3 = new int[maxentries]; // Sbar - Approximate Schur complement Teuchos::RCP<Epetra_CrsMatrix> Sbar = Teuchos::rcp(new Epetra_CrsMatrix( Copy, GrMap, g_localElems)); // Include only the block diagonal elements of G in localG Epetra_CrsMatrix localG(Copy, G_localRMap, G->MaxNumEntries(), false); int cnt, scnt; for (i = 0; i < g_localElems ; i++) { gid = g_rows[i]; G->ExtractGlobalRowCopy(gid, maxentries, nentries1, values1, indices1); cnt = 0; scnt = 0; for (int j = 0 ; j < nentries1 ; j++) { if (G->LRID(indices1[j]) != -1) { values2[cnt] = values1[j]; indices2[cnt++] = indices1[j]; } else { // Add it to Sbar immediately values3[scnt] = values1[j]; indices3[scnt++] = indices1[j]; } } localG.InsertGlobalValues(gid, cnt, values2, indices2); Sbar->InsertGlobalValues(gid, scnt, values3, indices3); } localG.FillComplete(); //cout << "Created local G matrix" << endl; int nvectors = 16; /*ShyLU_Probing_Operator probeop(&localG, &localR, LP, solver, &localC, localDRowMap, nvectors);*/ ShyLU_Local_Schur_Operator probeop(config, ssym, &localG, R, LP, solver, ifSolver, C, localDRowMap, nvectors); #ifdef DUMP_MATRICES //ostringstream fnamestr; //fnamestr << "localC" << C->Comm().MyPID() << ".mat"; //string Cfname = fnamestr.str(); //EpetraExt::RowMatrixToMatlabFile(Cfname.c_str(), localC); //Epetra_Map defMapg(-1, g_localElems, 0, localG.Comm()); //EpetraExt::ViewTransform<Epetra_CrsMatrix> * ReIdx_MatTransg = //new EpetraExt::CrsMatrix_Reindex( defMapg ); //Epetra_CrsMatrix t2G = (*ReIdx_MatTransg)( localG ); //ReIdx_MatTransg->fwd(); //EpetraExt::RowMatrixToMatlabFile("localG.mat", t2G); #endif //cout << " totalElems in Schur Complement" << totalElems << endl; //cout << myPID << " localElems" << localElems << endl; // **************** Two collectives here ********************* #ifdef TIMING_OUTPUT Teuchos::Time ftime("setup time"); ftime.start(); #endif #ifdef TIMING_OUTPUT Teuchos::Time app_time("setup time"); #endif int nentries; // size > maxentries as there could be fill // TODO: Currently the size of the two arrays can be one, Even if we switch // the loop below the size of the array required is nvectors. Fix it double *values = new double[nvectors]; int *indices = new int[nvectors]; double *vecvalues; #ifdef SHYLU_DEBUG // mfh 25 May 2015: Don't declare this variable if it's not used. // It's only used if SHYLU_DEBUG is defined. int dropped = 0; #endif // SHYLU_DEBUG double *maxvalue = new double[nvectors]; #ifdef TIMING_OUTPUT ftime.start(); #endif int findex = g_localElems / nvectors ; int cindex; // int mypid = C->Comm().MyPID(); // unused Epetra_MultiVector probevec (G_localRMap, nvectors); Epetra_MultiVector Scol (G_localRMap, nvectors); probevec.PutScalar(0.0); for (i = 0 ; i < findex*nvectors ; i+=nvectors) { // Set the probevec to find block columns of S. for (int k = 0; k < nvectors; k++) { cindex = k+i; // TODO: Can do better than this, just need to go to the column map // of C, there might be null columns in C probevec.ReplaceGlobalValue(g_rows[cindex], k, 1.0); //if (mypid == 0) //cout << "Changing row to 1.0 " << g_rows[cindex] << endl; } #ifdef TIMING_OUTPUT app_time.start(); #endif probeop.Apply(probevec, Scol); #ifdef TIMING_OUTPUT app_time.stop(); #endif // Reset the probevec to all zeros. for (int k = 0; k < nvectors; k++) { cindex = k+i; probevec.ReplaceGlobalValue(g_rows[cindex], k, 0.0); } Scol.MaxValue(maxvalue); nentries = 0; for (int j = 0 ; j < g_localElems ; j++) { for (int k = 0; k < nvectors; k++) { cindex = k+i; vecvalues = Scol[k]; if ((g_rows[cindex] == g_rows[j]) || (abs(vecvalues[j]/maxvalue[k]) > relative_thres)) // diagonal entry or large entry. { values[nentries] = vecvalues[j]; indices[nentries++] = g_rows[cindex]; } #ifdef SHYLU_DEBUG else if (vecvalues[j] != 0.0) { dropped++; } #endif // SHYLU_DEBUG } Sbar->InsertGlobalValues(g_rows[j], nentries, values, indices); nentries = 0; } } if (i < g_localElems) { nvectors = g_localElems - i; probeop.ResetTempVectors(nvectors); Epetra_MultiVector probevec1 (G_localRMap, nvectors); Epetra_MultiVector Scol1 (G_localRMap, nvectors); probevec1.PutScalar(0.0); for (int k = 0; k < nvectors; k++) { cindex = k+i; // TODO: Can do better than this, just need to go to the column map // of C, there might be null columns in C probevec1.ReplaceGlobalValue(g_rows[cindex], k, 1.0); } #ifdef TIMING_OUTPUT app_time.start(); #endif probeop.Apply(probevec1, Scol1); #ifdef TIMING_OUTPUT app_time.stop(); #endif Scol1.MaxValue(maxvalue); nentries = 0; for (int j = 0 ; j < g_localElems ; j++) { //cout << "MAX" << maxvalue << endl; for (int k = 0; k < nvectors; k++) { cindex = k+i; vecvalues = Scol1[k]; //nentries = 0; // inserting one entry in each row for now if ((g_rows[cindex] == g_rows[j]) || (abs(vecvalues[j]/maxvalue[k]) > relative_thres)) // diagonal entry or large entry. { values[nentries] = vecvalues[j]; indices[nentries++] = g_rows[cindex]; } #ifdef SHYLU_DEBUG else if (vecvalues[j] != 0.0) { dropped++; } #endif // SHYLU_DEBUG } Sbar->InsertGlobalValues(g_rows[j], nentries, values, indices); nentries = 0; } } #ifdef TIMING_OUTPUT ftime.stop(); cout << "Time in finding and dropping entries" << ftime.totalElapsedTime() << endl; ftime.reset(); cout << "Time in Apply of probing" << app_time.totalElapsedTime() << endl; probeop.PrintTimingInfo(); #endif Sbar->FillComplete(); #ifdef DUMP_MATRICES Epetra_Map defMap2(-1, g_localElems, 0, C->Comm()); EpetraExt::ViewTransform<Epetra_CrsMatrix> * ReIdx_MatTrans2 = new EpetraExt::CrsMatrix_Reindex( defMap2 ); Epetra_CrsMatrix t2S = (*ReIdx_MatTrans2)( *Sbar ); ReIdx_MatTrans2->fwd(); EpetraExt::RowMatrixToMatlabFile("Schur.mat", t2S); #endif #ifdef SHYLU_DEBUG cout << "#dropped entries" << dropped << endl; #endif delete[] values; delete[] indices; delete[] values1; delete[] indices1; delete[] values2; delete[] indices2; delete[] values3; delete[] indices3; delete[] maxvalue; return Sbar; }
//---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( DomainTransporter, Cutoff2 ) { typedef Epetra_Vector VectorType; typedef MCLS::VectorTraits<VectorType> VT; typedef Epetra_RowMatrix MatrixType; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; typedef MCLS::AdjointHistory<int> HistoryType; typedef std::mt19937 rng_type; typedef MCLS::AdjointDomain<VectorType,MatrixType,rng_type> DomainType; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm ); int comm_size = comm->getSize(); int comm_rank = comm->getRank(); int local_num_rows = 10; int global_num_rows = local_num_rows*comm_size; Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); // Build the linear operator and solution vector. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 1 ); Teuchos::Array<double> values( 1 ); for ( int i = 1; i < global_num_rows; ++i ) { global_columns[0] = i-1; values[0] = -0.5; A->InsertGlobalValues( i, global_columns().size(), &values[0], &global_columns[0] ); } global_columns[0] = global_num_rows-1; values[0] = -0.5; A->InsertGlobalValues( global_num_rows-1, global_columns.size(), &values[0], &global_columns[0] ); A->FillComplete(); Teuchos::RCP<MatrixType> B = MT::copyTranspose(*A); Teuchos::RCP<VectorType> x = MT::cloneVectorFromMatrixRows( *A ); // Build the adjoint domain. Teuchos::ParameterList plist; plist.set<int>( "Overlap Size", 2 ); Teuchos::RCP<DomainType> domain = Teuchos::rcp( new DomainType( B, x, plist ) ); Teuchos::RCP<MCLS::PRNG<rng_type> > rng = Teuchos::rcp( new MCLS::PRNG<rng_type>( comm->getRank() ) ); domain->setRNG( rng ); // Build the domain transporter. double weight = 3.0; double relative_cutoff = weight / 4 + 0.01; MCLS::DomainTransporter<DomainType> transporter( domain, plist ); domain->setCutoff( relative_cutoff ); // Transport histories through the domain. for ( int i = 0; i < global_num_rows-2; ++i ) { if ( comm_rank == comm_size - 1 ) { if ( i >= local_num_rows*comm_rank && i < local_num_rows*(comm_rank+1) ) { HistoryType history( i, i, weight ); history.live(); transporter.transport( history ); TEST_EQUALITY( history.globalState(), i+2 ); TEST_EQUALITY( history.weight(), weight / 4 ); TEST_EQUALITY( history.event(), MCLS::Event::CUTOFF ); TEST_ASSERT( !history.alive() ); } } else { if ( i >= local_num_rows*comm_rank && i < 1+local_num_rows*(comm_rank+1) ) { HistoryType history( i, i, weight ); history.live(); transporter.transport( history ); TEST_EQUALITY( history.globalState(), i+2 ); TEST_EQUALITY( history.weight(), weight / 4 ); TEST_EQUALITY( history.event(), MCLS::Event::CUTOFF ); TEST_ASSERT( !history.alive() ); } } } // Check the tally. domain->domainTally()->combineSetTallies( comm ); Teuchos::ArrayRCP<const double> x_view = VT::view( *x ); double x_val = weight; for ( int i = 0; i < local_num_rows; ++i ) { if ( comm_rank == comm_size-1 && i == local_num_rows-1 ) { TEST_EQUALITY( x_view[i], 0.0 ); } else if ( comm_rank == comm_size-1 && i == local_num_rows-2 ) { TEST_EQUALITY( x_view[i], 3.0/2.0 ); } else if ( comm_rank == 0 && i == 0 ) { TEST_EQUALITY( x_view[i], x_val ); } else if ( comm_rank == 0 || i > 2 ) { TEST_EQUALITY( x_view[i], 3.0*x_val/2.0 ); } else { TEST_EQUALITY( x_view[i], 3.0*x_val ); } } }
/* Computes the approximate Schur complement for the wide separator using guided probing*/ Teuchos::RCP<Epetra_CrsMatrix> computeSchur_GuidedProbing ( shylu_config *config, shylu_symbolic *ssym, // symbolic structure shylu_data *data, // numeric structure Epetra_Map *localDRowMap ) { int i; double relative_thres = config->relative_threshold; Epetra_CrsMatrix *G = ssym->G.getRawPtr(); Epetra_CrsMatrix *R = ssym->R.getRawPtr(); Epetra_LinearProblem *LP = ssym->LP.getRawPtr(); Amesos_BaseSolver *solver = ssym->Solver.getRawPtr(); Ifpack_Preconditioner *ifSolver = ssym->ifSolver.getRawPtr(); Epetra_CrsMatrix *C = ssym->C.getRawPtr(); // Need to create local G (block diagonal portion) , R, C // Get row map of G Epetra_Map CrMap = C->RowMap(); int *c_rows = CrMap.MyGlobalElements(); int *c_cols = (C->ColMap()).MyGlobalElements(); //int c_totalElems = CrMap.NumGlobalElements(); int c_localElems = CrMap.NumMyElements(); int c_localcolElems = (C->ColMap()).NumMyElements(); Epetra_Map GrMap = G->RowMap(); int *g_rows = GrMap.MyGlobalElements(); //int g_totalElems = GrMap.NumGlobalElements(); int g_localElems = GrMap.NumMyElements(); Epetra_Map RrMap = R->RowMap(); int *r_rows = RrMap.MyGlobalElements(); int *r_cols = (R->ColMap()).MyGlobalElements(); //int r_totalElems = RrMap.NumGlobalElements(); int r_localElems = RrMap.NumMyElements(); int r_localcolElems = (R->ColMap()).NumMyElements(); Epetra_SerialComm LComm; Epetra_Map C_localRMap (-1, c_localElems, c_rows, 0, LComm); Epetra_Map C_localCMap (-1, c_localcolElems, c_cols, 0, LComm); Epetra_Map G_localRMap (-1, g_localElems, g_rows, 0, LComm); Epetra_Map R_localRMap (-1, r_localElems, r_rows, 0, LComm); Epetra_Map R_localCMap (-1, r_localcolElems, r_cols, 0, LComm); //cout << "#local rows" << g_localElems << "#non zero local cols" << c_localcolElems << endl; #ifdef DEBUG cout << "DEBUG MODE" << endl; int nrows = C->RowMap().NumMyElements(); assert(nrows == localDRowMap->NumGlobalElements()); int gids[nrows], gids1[nrows]; C_localRMap.MyGlobalElements(gids); localDRowMap->MyGlobalElements(gids1); cout << "Comparing R's domain map with D's row map" << endl; for (int i = 0; i < nrows; i++) { assert(gids[i] == gids1[i]); } #endif int nentries1, gid; // maxentries is the maximum of all three possible matrices as the arrays // are reused between the three int maxentries = max(C->MaxNumEntries(), R->MaxNumEntries()); maxentries = max(maxentries, G->MaxNumEntries()); double *values1 = new double[maxentries]; double *values2 = new double[maxentries]; double *values3 = new double[maxentries]; int *indices1 = new int[maxentries]; int *indices2 = new int[maxentries]; int *indices3 = new int[maxentries]; //cout << "Creating local matrices" << endl; int err; Epetra_CrsMatrix localC(Copy, C_localRMap, C->MaxNumEntries(), false); for (i = 0; i < c_localElems ; i++) { gid = c_rows[i]; err = C->ExtractGlobalRowCopy(gid, maxentries, nentries1, values1, indices1); assert (err == 0); //if (nentries1 > 0) // TODO: Later //{ err = localC.InsertGlobalValues(gid, nentries1, values1, indices1); assert (err == 0); //} } localC.FillComplete(G_localRMap, C_localRMap); //cout << "Created local C matrix" << endl; Epetra_CrsMatrix localR(Copy, R_localRMap, R->MaxNumEntries(), false); for (i = 0; i < r_localElems ; i++) { gid = r_rows[i]; R->ExtractGlobalRowCopy(gid, maxentries, nentries1, values1, indices1); localR.InsertGlobalValues(gid, nentries1, values1, indices1); } localR.FillComplete(*localDRowMap, R_localRMap); //cout << "Created local R matrix" << endl; // Sbar - Approximate Schur complement Teuchos::RCP<Epetra_CrsMatrix> Sbar = Teuchos::rcp(new Epetra_CrsMatrix( Copy, GrMap, g_localElems)); // Include only the block diagonal elements of G in localG Epetra_CrsMatrix localG(Copy, G_localRMap, G->MaxNumEntries(), false); int cnt, scnt; for (i = 0; i < g_localElems ; i++) { gid = g_rows[i]; G->ExtractGlobalRowCopy(gid, maxentries, nentries1, values1, indices1); cnt = 0; scnt = 0; for (int j = 0 ; j < nentries1 ; j++) { if (G->LRID(indices1[j]) != -1) { values2[cnt] = values1[j]; indices2[cnt++] = indices1[j]; } else { // Add it to Sbar immediately values3[scnt] = values1[j]; indices3[scnt++] = indices1[j]; } } localG.InsertGlobalValues(gid, cnt, values2, indices2); Sbar->InsertGlobalValues(gid, scnt, values3, indices3); } localG.FillComplete(); cout << "Created local G matrix" << endl; int nvectors = 16; ShyLU_Probing_Operator probeop(config, ssym, &localG, &localR, LP, solver, ifSolver, &localC, localDRowMap, nvectors); #ifdef DUMP_MATRICES //ostringstream fnamestr; //fnamestr << "localC" << C->Comm().MyPID() << ".mat"; //string Cfname = fnamestr.str(); //EpetraExt::RowMatrixToMatlabFile(Cfname.c_str(), localC); //Epetra_Map defMapg(-1, g_localElems, 0, localG.Comm()); //EpetraExt::ViewTransform<Epetra_CrsMatrix> * ReIdx_MatTransg = //new EpetraExt::CrsMatrix_Reindex( defMapg ); //Epetra_CrsMatrix t2G = (*ReIdx_MatTransg)( localG ); //ReIdx_MatTransg->fwd(); //EpetraExt::RowMatrixToMatlabFile("localG.mat", t2G); #endif //cout << " totalElems in Schur Complement" << totalElems << endl; //cout << myPID << " localElems" << localElems << endl; // **************** Two collectives here ********************* #ifdef TIMING_OUTPUT Teuchos::Time ftime("setup time"); #endif #ifdef TIMING_OUTPUT Teuchos::Time app_time("setup time"); #endif Teuchos::RCP<Epetra_CrsGraph> lSGraph = Teuchos::RCP<Epetra_CrsGraph> ( new Epetra_CrsGraph(Copy, G_localRMap, maxentries)); if (data->num_compute % config->reset_iter == 0) { int nentries; // size > maxentries as there could be fill // TODO: Currently the size of the two arrays can be one, Even if we switch // the loop below the size of the array required is nvectors. Fix it double *values = new double[g_localElems]; int *indices = new int[g_localElems]; double *vecvalues; int dropped = 0; double *maxvalue = new double[nvectors]; #ifdef TIMING_OUTPUT ftime.start(); #endif int findex = g_localElems / nvectors ; int cindex; // int mypid = C->Comm().MyPID(); // unused Epetra_MultiVector probevec(G_localRMap, nvectors); Epetra_MultiVector Scol(G_localRMap, nvectors); for (i = 0 ; i < findex*nvectors ; i+=nvectors) { probevec.PutScalar(0.0); // TODO: Move it out for (int k = 0; k < nvectors; k++) { cindex = k+i; // TODO: Can do better than this, just need to go to the column map // of C, there might be null columns in C // Not much of use for Shasta 2x2 .. Later. probevec.ReplaceGlobalValue(g_rows[cindex], k, 1.0); //if (mypid == 0) //cout << "Changing row to 1.0 " << g_rows[cindex] << endl; } #ifdef TIMING_OUTPUT app_time.start(); #endif probeop.Apply(probevec, Scol); #ifdef TIMING_OUTPUT app_time.stop(); #endif Scol.MaxValue(maxvalue); for (int k = 0; k < nvectors; k++) //TODO:Need to switch these loops { cindex = k+i; vecvalues = Scol[k]; //cout << "MAX" << maxvalue << endl; for (int j = 0 ; j < g_localElems ; j++) { nentries = 0; // inserting one entry in each row for now if (g_rows[cindex] == g_rows[j]) // diagonal entry { values[nentries] = vecvalues[j]; indices[nentries] = g_rows[cindex]; nentries++; err = Sbar->InsertGlobalValues(g_rows[j], nentries, values, indices); assert(err >= 0); err = lSGraph->InsertGlobalIndices(g_rows[j], nentries, indices); assert(err >= 0); } else if (abs(vecvalues[j]/maxvalue[k]) > relative_thres) { values[nentries] = vecvalues[j]; indices[nentries] = g_rows[cindex]; nentries++; err = Sbar->InsertGlobalValues(g_rows[j], nentries, values, indices); assert(err >= 0); err = lSGraph->InsertGlobalIndices(g_rows[j], nentries, indices); assert(err >= 0); } else { if (vecvalues[j] != 0.0) { dropped++; //cout << "vecvalues[j]" << vecvalues[j] << // " max" << maxvalue[k] << endl; } } } } } probeop.ResetTempVectors(1); for ( ; i < g_localElems ; i++) { // TODO: Can move the next two decalarations outside the loop Epetra_MultiVector probevec(G_localRMap, 1); Epetra_MultiVector Scol(G_localRMap, 1); probevec.PutScalar(0.0); // TODO: Can do better than this, just need to go to the column map // of C, there might be null columns in C probevec.ReplaceGlobalValue(g_rows[i], 0, 1.0); #ifdef TIMING_OUTPUT app_time.start(); #endif probeop.Apply(probevec, Scol); #ifdef TIMING_OUTPUT app_time.stop(); #endif vecvalues = Scol[0]; Scol.MaxValue(maxvalue); //cout << "MAX" << maxvalue << endl; for (int j = 0 ; j < g_localElems ; j++) { nentries = 0; // inserting one entry in each row for now if (g_rows[i] == g_rows[j]) // diagonal entry { values[nentries] = vecvalues[j]; indices[nentries] = g_rows[i]; nentries++; err = Sbar->InsertGlobalValues(g_rows[j], nentries, values, indices); assert(err >= 0); err = lSGraph->InsertGlobalIndices(g_rows[j], nentries, indices); assert(err >= 0); } else if (abs(vecvalues[j]/maxvalue[0]) > relative_thres) { values[nentries] = vecvalues[j]; indices[nentries] = g_rows[i]; nentries++; err = Sbar->InsertGlobalValues(g_rows[j], nentries, values, indices); assert(err >= 0); err = lSGraph->InsertGlobalIndices(g_rows[j], nentries, indices); assert(err >= 0); } else { if (vecvalues[j] != 0.0) dropped++; } } } #ifdef TIMING_OUTPUT ftime.stop(); cout << "Time in finding and dropping entries" << ftime.totalElapsedTime() << endl; ftime.reset(); #endif #ifdef TIMING_OUTPUT cout << "Time in Apply of probing" << app_time.totalElapsedTime() << endl; #endif probeop.PrintTimingInfo(); Sbar->FillComplete(); lSGraph->FillComplete(); data->localSbargraph = lSGraph; #ifdef DUMP_MATRICES Epetra_Map defMap2(-1, g_localElems, 0, C->Comm()); EpetraExt::ViewTransform<Epetra_CrsMatrix> * ReIdx_MatTrans2 = new EpetraExt::CrsMatrix_Reindex( defMap2 ); Epetra_CrsMatrix t2S = (*ReIdx_MatTrans2)( *Sbar ); ReIdx_MatTrans2->fwd(); EpetraExt::RowMatrixToMatlabFile("Schur.mat", t2S); #endif cout << "#dropped entries" << dropped << endl; delete[] values; delete[] indices; delete[] maxvalue; } else { if (((data->num_compute-1) % config->reset_iter) == 0) { // We recomputed the Schur complement with dropping for the last // compute. Reset the prober with the new orthogonal vectors for // the Sbar from the previous iteration. Teuchos::ParameterList pList; Teuchos::RCP<Isorropia::Epetra::Prober> gprober = Teuchos::RCP<Isorropia::Epetra::Prober> (new Isorropia::Epetra::Prober( data->localSbargraph.getRawPtr(), pList, false)); gprober->color(); data->guided_prober = gprober; } // Use the prober to probe the probeop for the sparsity pattern // add that to Sbar and call Fill complete int nvectors = data->guided_prober->getNumOrthogonalVectors(); cout << "Number of Orthogonal Vectors for guided probing" << nvectors << endl; probeop.ResetTempVectors(nvectors); Teuchos::RCP<Epetra_CrsMatrix> blockdiag_Sbar = data->guided_prober->probe(probeop); int maxentries = blockdiag_Sbar->GlobalMaxNumEntries(); int *indices = new int[maxentries]; double *values = new double[maxentries]; int numentries; for (int i = 0; i < blockdiag_Sbar->NumGlobalRows() ; i++) { int gid = blockdiag_Sbar->GRID(i); blockdiag_Sbar->ExtractGlobalRowCopy(gid, maxentries, numentries, values, indices); Sbar->InsertGlobalValues(gid, numentries, values, indices); } Sbar->FillComplete(); delete[] indices; delete[] values; } delete[] values1; delete[] indices1; delete[] values2; delete[] indices2; delete[] values3; delete[] indices3; return Sbar; }
// helper routines bool SplitMatrix2x2(Teuchos::RCP<const Epetra_CrsMatrix> A, const Epetra_Map& A11rowmap, const Epetra_Map& A22rowmap, Teuchos::RCP<Epetra_CrsMatrix>& A11, Teuchos::RCP<Epetra_CrsMatrix>& A12, Teuchos::RCP<Epetra_CrsMatrix>& A21, Teuchos::RCP<Epetra_CrsMatrix>& A22) { if (A==Teuchos::null) { std::cout << "ERROR: SplitMatrix2x2: A==null on entry" << std::endl; return false; } const Epetra_Comm& Comm = A->Comm(); const Epetra_Map& A22map = A22rowmap; const Epetra_Map& A11map = A11rowmap; //----------------------------- create a parallel redundant map of A22map std::map<int,int> a22gmap; { std::vector<int> a22global(A22map.NumGlobalElements()); int count=0; for (int proc=0; proc<Comm.NumProc(); ++proc) { int length = 0; if (proc==Comm.MyPID()) { for (int i=0; i<A22map.NumMyElements(); ++i) { a22global[count+length] = A22map.GID(i); ++length; } } Comm.Broadcast(&length,1,proc); Comm.Broadcast(&a22global[count],length,proc); count += length; } if (count != A22map.NumGlobalElements()) { std::cout << "ERROR SplitMatrix2x2: mismatch in dimensions" << std::endl; return false; } // create the map for (int i=0; i<count; ++i) a22gmap[a22global[i]] = 1; a22global.clear(); } //--------------------------------------------------- create matrix A22 A22 = Teuchos::rcp(new Epetra_CrsMatrix(Copy,A22map,100)); { std::vector<int> a22gcindices(100); std::vector<double> a22values(100); for (int i=0; i<A->NumMyRows(); ++i) { const int grid = A->GRID(i); if (A22map.MyGID(grid)==false) continue; int numentries; double* values; int* cindices; int err = A->ExtractMyRowView(i,numentries,values,cindices); if (err) { std::cout << "ERROR: SplitMatrix2x2: A->ExtractMyRowView returned " << err << std::endl; return false; } if (numentries>(int)a22gcindices.size()) { a22gcindices.resize(numentries); a22values.resize(numentries); } int count=0; for (int j=0; j<numentries; ++j) { const int gcid = A->ColMap().GID(cindices[j]); // see whether we have gcid in a22gmap std::map<int,int>::iterator curr = a22gmap.find(gcid); if (curr==a22gmap.end()) continue; //std::cout << gcid << " "; a22gcindices[count] = gcid; a22values[count] = values[j]; ++count; } //std::cout << std::endl; fflush(stdout); // add this filtered row to A22 err = A22->InsertGlobalValues(grid,count,&a22values[0],&a22gcindices[0]); if (err<0) { std::cout << "ERROR: SplitMatrix2x2: A->InsertGlobalValues returned " << err << std::endl; return false; } } //for (int i=0; i<A->NumMyRows(); ++i) a22gcindices.clear(); a22values.clear(); } A22->FillComplete(); A22->OptimizeStorage(); //----------------------------------------------------- create matrix A11 A11 = Teuchos::rcp(new Epetra_CrsMatrix(Copy,A11map,100)); { std::vector<int> a11gcindices(100); std::vector<double> a11values(100); for (int i=0; i<A->NumMyRows(); ++i) { const int grid = A->GRID(i); if (A11map.MyGID(grid)==false) continue; int numentries; double* values; int* cindices; int err = A->ExtractMyRowView(i,numentries,values,cindices); if (err) { std::cout << "ERROR: SplitMatrix2x2: A->ExtractMyRowView returned " << err << std::endl; return false; } if (numentries>(int)a11gcindices.size()) { a11gcindices.resize(numentries); a11values.resize(numentries); } int count=0; for (int j=0; j<numentries; ++j) { const int gcid = A->ColMap().GID(cindices[j]); // see whether we have gcid as part of a22gmap std::map<int,int>::iterator curr = a22gmap.find(gcid); if (curr!=a22gmap.end()) continue; a11gcindices[count] = gcid; a11values[count] = values[j]; ++count; } err = A11->InsertGlobalValues(grid,count,&a11values[0],&a11gcindices[0]); if (err<0) { std::cout << "ERROR: SplitMatrix2x2: A->InsertGlobalValues returned " << err << std::endl; return false; } } // for (int i=0; i<A->NumMyRows(); ++i) a11gcindices.clear(); a11values.clear(); } A11->FillComplete(); A11->OptimizeStorage(); //---------------------------------------------------- create matrix A12 A12 = Teuchos::rcp(new Epetra_CrsMatrix(Copy,A11map,100)); { std::vector<int> a12gcindices(100); std::vector<double> a12values(100); for (int i=0; i<A->NumMyRows(); ++i) { const int grid = A->GRID(i); if (A11map.MyGID(grid)==false) continue; int numentries; double* values; int* cindices; int err = A->ExtractMyRowView(i,numentries,values,cindices); if (err) { std::cout << "ERROR: SplitMatrix2x2: A->ExtractMyRowView returned " << err << std::endl; return false; } if (numentries>(int)a12gcindices.size()) { a12gcindices.resize(numentries); a12values.resize(numentries); } int count=0; for (int j=0; j<numentries; ++j) { const int gcid = A->ColMap().GID(cindices[j]); // see whether we have gcid as part of a22gmap std::map<int,int>::iterator curr = a22gmap.find(gcid); if (curr==a22gmap.end()) continue; a12gcindices[count] = gcid; a12values[count] = values[j]; ++count; } err = A12->InsertGlobalValues(grid,count,&a12values[0],&a12gcindices[0]); if (err<0) { std::cout << "ERROR: SplitMatrix2x2: A->InsertGlobalValues returned " << err << std::endl; return false; } } // for (int i=0; i<A->NumMyRows(); ++i) a12values.clear(); a12gcindices.clear(); } A12->FillComplete(A22map,A11map); A12->OptimizeStorage(); //----------------------------------------------------------- create A21 A21 = Teuchos::rcp(new Epetra_CrsMatrix(Copy,A22map,100)); { std::vector<int> a21gcindices(100); std::vector<double> a21values(100); for (int i=0; i<A->NumMyRows(); ++i) { const int grid = A->GRID(i); if (A22map.MyGID(grid)==false) continue; int numentries; double* values; int* cindices; int err = A->ExtractMyRowView(i,numentries,values,cindices); if (err) { std::cout << "ERROR: SplitMatrix2x2: A->ExtractMyRowView returned " << err << std::endl; return false; } if (numentries>(int)a21gcindices.size()) { a21gcindices.resize(numentries); a21values.resize(numentries); } int count=0; for (int j=0; j<numentries; ++j) { const int gcid = A->ColMap().GID(cindices[j]); // see whether we have gcid as part of a22gmap std::map<int,int>::iterator curr = a22gmap.find(gcid); if (curr!=a22gmap.end()) continue; a21gcindices[count] = gcid; a21values[count] = values[j]; ++count; } err = A21->InsertGlobalValues(grid,count,&a21values[0],&a21gcindices[0]); if (err<0) { std::cout << "ERROR: SplitMatrix2x2: A->InsertGlobalValues returned " << err << std::endl; return false; } } // for (int i=0; i<A->NumMyRows(); ++i) a21values.clear(); a21gcindices.clear(); } A21->FillComplete(A11map,A22map); A21->OptimizeStorage(); //-------------------------------------------------------------- tidy up a22gmap.clear(); return true; }
//---------------------------------------------------------------------------// // Test templates //---------------------------------------------------------------------------// TEUCHOS_UNIT_TEST( FixedPointSolverManager, one_by_one ) { typedef Epetra_Vector VectorType; typedef MCLS::VectorTraits<VectorType> VT; typedef Epetra_RowMatrix MatrixType; typedef MCLS::MatrixTraits<VectorType,MatrixType> MT; Teuchos::RCP<const Teuchos::Comm<int> > comm = Teuchos::DefaultComm<int>::getComm(); Teuchos::RCP<Epetra_Comm> epetra_comm = getEpetraComm( comm ); int comm_size = comm->getSize(); int local_num_rows = 10; int global_num_rows = local_num_rows*comm_size; Teuchos::RCP<Epetra_Map> map = Teuchos::rcp( new Epetra_Map( global_num_rows, 0, *epetra_comm ) ); // Build the linear system. Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, *map, 0 ) ); Teuchos::Array<int> global_columns( 3 ); Teuchos::Array<double> values( 3 ); global_columns[0] = 0; global_columns[1] = 1; global_columns[2] = 2; values[0] = 0.14; values[1] = 0.14; values[2] = 1.0; A->InsertGlobalValues( 0, global_columns.size(), &values[0], &global_columns[0] ); for ( int i = 1; i < global_num_rows-1; ++i ) { global_columns[0] = i-1; global_columns[1] = i; global_columns[2] = i+1; values[0] = 0.14; values[1] = 1.0; values[2] = 0.14; A->InsertGlobalValues( i, global_columns.size(), &values[0], &global_columns[0] ); } global_columns[0] = global_num_rows-3; global_columns[1] = global_num_rows-2; global_columns[2] = global_num_rows-1; values[0] = 0.14; values[1] = 0.14; values[2] = 1.0; A->InsertGlobalValues( global_num_rows-1, global_columns.size(), &values[0], &global_columns[0] ); A->FillComplete(); Teuchos::RCP<MatrixType> B = A; // Build the LHS. Put a large positive number here to be sure we are // clear the vector before solving. Teuchos::RCP<VectorType> x = MT::cloneVectorFromMatrixRows( *B ); VT::putScalar( *x, 0.0 ); // Build the RHS with negative numbers. this gives us a negative // solution. Teuchos::RCP<VectorType> b = MT::cloneVectorFromMatrixRows( *B ); VT::putScalar( *b, -1.0 ); // Solver parameters. Teuchos::RCP<Teuchos::ParameterList> plist = Teuchos::rcp( new Teuchos::ParameterList() ); plist->set<int>("Iteration Print Frequency", 1); plist->set<double>("Convergence Tolerance", 1.0e-8); plist->set<int>("Maximum Iterations", 100); plist->set<double>("Richardson Relaxation", 1.0); // Create the linear problem. Teuchos::RCP<MCLS::LinearProblem<VectorType,MatrixType> > linear_problem = Teuchos::rcp( new MCLS::LinearProblem<VectorType,MatrixType>( B, x, b ) ); // Create the solver. MCLS::FixedPointSolverManager<VectorType,MatrixType> solver_manager( linear_problem, comm, plist ); // Solve the problem. bool converged_status = solver_manager.solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager.getConvergedStatus() ); TEST_EQUALITY( solver_manager.getNumIters(), 15 ); TEST_ASSERT( solver_manager.achievedTol() > 0.0 ); // Check that we got a negative solution. Teuchos::ArrayRCP<const double> x_view = VT::view(*x); Teuchos::ArrayRCP<const double>::const_iterator x_view_it; for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it < Teuchos::ScalarTraits<double>::zero() ); } // Now solve the problem with a positive source. VT::putScalar( *b, 2.0 ); VT::putScalar( *x, 0.0 ); linear_problem->setLHS(x); converged_status = solver_manager.solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager.getConvergedStatus() ); TEST_EQUALITY( solver_manager.getNumIters(), 15 ); TEST_ASSERT( solver_manager.achievedTol() > 0.0 ); for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it > Teuchos::ScalarTraits<double>::zero() ); } // Reset the domain and solve again with a positive source. VT::putScalar( *x, 0.0 ); solver_manager.setProblem( linear_problem ); linear_problem->setLHS(x); converged_status = solver_manager.solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager.getConvergedStatus() ); TEST_EQUALITY( solver_manager.getNumIters(), 15 ); TEST_ASSERT( solver_manager.achievedTol() > 0.0 ); for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it > Teuchos::ScalarTraits<double>::zero() ); } // Reset both and solve with a negative source. VT::putScalar( *b, -2.0 ); VT::putScalar( *x, 0.0 ); linear_problem->setLHS(x); converged_status = solver_manager.solve(); TEST_ASSERT( converged_status ); TEST_ASSERT( solver_manager.getConvergedStatus() ); TEST_EQUALITY( solver_manager.getNumIters(), 15 ); TEST_ASSERT( solver_manager.achievedTol() > 0.0 ); for ( x_view_it = x_view.begin(); x_view_it != x_view.end(); ++x_view_it ) { TEST_ASSERT( *x_view_it < Teuchos::ScalarTraits<double>::zero() ); } }
int main(int argc, char *argv[]) { using Teuchos::CommandLineProcessor; using Teuchos::ParameterList; using Teuchos::RCP; using Teuchos::rcp; using std::cout; using std::endl; typedef double ST; typedef Teuchos::ScalarTraits<ST> SCT; typedef SCT::magnitudeType MT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Belos::MultiVecTraits<ST,MV> MVT; typedef Belos::OperatorTraits<ST,MV,OP> OPT; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); const int MyPID = Comm.MyPID(); #else // No EPETRA_MPI Epetra_SerialComm Comm; const int MyPID = 0; #endif // EPETRA_MPI bool verbose = false, debug = false; int frequency = -1; // frequency of status test output. int numrhs = 1; // number of right-hand sides to solve for int maxiters = -1; // maximum number of iterations allowed per linear system MT tol = 1.0e-8; // relative residual tolerance // Define command-line arguments CommandLineProcessor cmdp(false,true); cmdp.setOption ("verbose", "quiet", &verbose, "Print messages and results."); cmdp.setOption ("debug", "nodebug", &debug, "Print debugging information from the solver."); cmdp.setOption ("frequency", &frequency, "Solver's frequency for printing residuals (#iters)."); cmdp.setOption ("tol", &tol, "Relative residual tolerance used by MINRES solver."); cmdp.setOption ("num-rhs", &numrhs, "Number of right-hand sides for which to solve (> 0)."); cmdp.setOption ("max-iters", &maxiters, "Maximum number of iterations per linear system. -1 means " "we choose, based on problem size."); // Parse command-line arguments and fetch values if (cmdp.parse(argc,argv) != CommandLineProcessor::PARSE_SUCCESSFUL) { std::cout << "Failed to parse command-line arguments!" << std::endl; std::cout << "End Result: TEST FAILED" << std::endl; return -1; } // ********************************************************************** // ******************Set up the problem to be solved********************* // construct diagonal matrix const int NumGlobalElements = 1e2; const int m = 4; // number of negative eigenvalues // Create diagonal matrix with n-m positive and m negative eigenvalues. Epetra_Map epetraMap( NumGlobalElements, 0, Comm ); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, epetraMap, 1 ) ); for ( int k=0; k<epetraMap.NumMyElements(); k++ ) { int GIDk = epetraMap.GID(k); double val = 2*(GIDk-m) + 1; TEUCHOS_ASSERT_EQUALITY( 0, A->InsertGlobalValues( GIDk, 1, &val, &GIDk ) ); } TEUCHOS_ASSERT_EQUALITY( 0, A->FillComplete() ); TEUCHOS_ASSERT_EQUALITY( 0, A->OptimizeStorage() ); // // Make some (multi)vectors, for use in testing: an exact solution, // its corresponding right-hand side, and an initial guess. // // Make a random exact solution. Teuchos::RCP<Epetra_MultiVector> X_exact (new Epetra_MultiVector (epetraMap, numrhs)); X_exact->Seed(); MVT::MvRandom (*X_exact); // Compute the right-hand side as B = A*X. Teuchos::RCP<Epetra_MultiVector> B = MVT::Clone (*X_exact, numrhs); OPT::Apply (*A, *X_exact, *B); // Choose an initial guess of all zeros. Teuchos::RCP<Epetra_MultiVector> X = MVT::Clone (*X_exact, numrhs); MVT::MvInit (*X, ST(0.0)); // ********************************************************************** // // Set parameters that the user asked us to pick intelligently. // // Maximum number of iterations: set according to problem size. // maxiters=numGlobalElements-1 may not always converge, so we // set to numGlobalElements+1 for good measure. if (maxiters == -1) maxiters = NumGlobalElements + 1; // In a nonverbose test, the frequency should be set to -1, which // Belos interprets as "no intermediate status output." Override // whatever the user may have specified. if (! verbose) frequency = -1; // Silently fix a bad frequency value. else if (frequency < 0 && frequency != -1) frequency = -1; // Validate command-line arguments TEUCHOS_TEST_FOR_EXCEPTION( tol < 0, std::invalid_argument, "Relative residual tolerance must be nonnegative, but " "you supplied tol = " << tol << "." ); TEUCHOS_TEST_FOR_EXCEPTION( numrhs < 1, std::invalid_argument, "MINRES test requires at least one right-hand side, but " "you set the number of right-hand sides to " << numrhs << "." ); TEUCHOS_TEST_FOR_EXCEPTION( maxiters < 1, std::invalid_argument, "MINRES test requires at least one iteration, but you " "set the maximum number of iterations to " << maxiters << "." ); const bool proc_verbose = verbose && (MyPID==0); /* Only print on the zero processor */ // // ********Other information used by block solver*********** // *****************(can be user specified)****************** // // ParameterList belosList; belosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested int verbosity = Belos::Errors + Belos::Warnings; if (verbose) { verbosity += Belos::TimingDetails + Belos::StatusTestDetails; if (frequency > 0) belosList.set( "Output Frequency", frequency ); } if (debug) { verbosity += Belos::Debug; } belosList.set( "Verbosity", (int) verbosity ); // // Construct an unpreconditioned linear problem instance. // Belos::LinearProblem< ST, MV, OP > problem (A, X, B); { const bool set = problem.setProblem(); TEUCHOS_TEST_FOR_EXCEPTION( set == false, std::logic_error, "Belos::LinearProblem failed to set up correctly (setP" "roblem() returned false)! This probably means we imp" "lemented our test incorrectly." ); } // // ******************************************************************* // ****************Start the MINRES iteration************************* // ******************************************************************* // // Create an iterative solver manager. RCP< Belos::SolverManager<ST,MV,OP> > newSolver = rcp( new Belos::MinresSolMgr<ST,MV,OP>(rcp(&problem,false), rcp(&belosList,false))); // // **********Print out information about problem******************* // if (proc_verbose) { cout << endl << endl; cout << "Dimension of matrix: " << NumGlobalElements << endl; cout << "Number of right-hand sides: " << numrhs << endl; cout << "Relative residual tolerance: " << tol << endl; cout << endl; } // // Perform solve // Belos::ReturnType ret = Belos::Unconverged; try { ret = newSolver->solve(); } catch (std::exception& e) { if (MyPID == 0) cout << "MINRES solver threw an exception: " << e.what() << endl; throw e; } // // Compute actual residuals. // bool badRes = false; std::vector<double> actual_resids( numrhs ); std::vector<double> rhs_norm( numrhs ); Epetra_MultiVector resid(A->Map(), numrhs); OPT::Apply( *A, *X, resid ); MVT::MvAddMv( -1.0, resid, 1.0, *B, resid ); MVT::MvNorm( resid, actual_resids ); MVT::MvNorm( *B, rhs_norm ); if (proc_verbose) { std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl; for ( int i=0; i<numrhs; i++) { double actRes = actual_resids[i]/rhs_norm[i]; std::cout<<"Problem "<<i<<" : \t"<< actRes <<std::endl; if (actRes > tol) badRes = true; } } if (ret!=Belos::Converged || badRes) { if (proc_verbose) std::cout << std::endl << "End Result: TEST FAILED" << std::endl; } // // Default return value // if (proc_verbose) std::cout << std::endl << "End Result: TEST PASSED" << std::endl; #ifdef EPETRA_MPI MPI_Finalize(); #endif if (ret!=Belos::Converged || badRes) return -1; else return 0; }
int main(int argc, char *argv[]) { int i; bool ierr, gerr; gerr = true; #ifdef HAVE_MPI // Initialize MPI and setup an Epetra communicator MPI_Init(&argc,&argv); Teuchos::RCP<Epetra_MpiComm> Comm = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_WORLD) ); #else // If we aren't using MPI, then setup a serial communicator. Teuchos::RCP<Epetra_SerialComm> Comm = Teuchos::rcp( new Epetra_SerialComm() ); #endif // number of global elements int dim = 100; int blockSize = 5; bool verbose = false; if (argc>1) { if (argv[1][0]=='-' && argv[1][1]=='v') { verbose = true; } } // Construct a Map that puts approximately the same number of // equations on each processor. Teuchos::RCP<Epetra_Map> Map = Teuchos::rcp( new Epetra_Map(dim, 0, *Comm) ); // Get update list and number of local equations from newly created Map. int NumMyElements = Map->NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map->MyGlobalElements(&MyGlobalElements[0]); // Create an integer std::vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of OFF-DIAGONAL term for the ith global equation // on this processor std::vector<int> NumNz(NumMyElements); // We are building a tridiagonal matrix where each row has (-1 2 -1) // So we need 2 off-diagonal terms (except for the first and last equation) for (i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0 || MyGlobalElements[i] == dim-1) { NumNz[i] = 2; } else { NumNz[i] = 3; } } // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, *Map, &NumNz[0]) ); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 std::vector<double> Values(2); Values[0] = -1.0; Values[1] = -1.0; std::vector<int> Indices(2); double two = 2.0; int NumEntries; for (i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (MyGlobalElements[i] == dim-1) { Indices[0] = dim-2; NumEntries = 1; } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; NumEntries = 2; } ierr = A->InsertGlobalValues(MyGlobalElements[i],NumEntries,&Values[0],&Indices[0]); assert(ierr==0); // Put in the diagonal entry ierr = A->InsertGlobalValues(MyGlobalElements[i],1,&two,&MyGlobalElements[i]); assert(ierr==0); } // Finish building the epetra matrix A ierr = A->FillComplete(); assert(ierr==0); // Issue several useful typedefs; typedef Belos::MultiVec<double> EMV; typedef Belos::Operator<double> EOP; // Create an Epetra_MultiVector for an initial std::vector to start the solver. // Note that this needs to have the same number of columns as the blocksize. Teuchos::RCP<Belos::EpetraMultiVec> ivec = Teuchos::rcp( new Belos::EpetraMultiVec(*Map, blockSize) ); ivec->Random(); // Create an output manager to handle the I/O from the solver Teuchos::RCP<Belos::OutputManager<double> > MyOM = Teuchos::rcp( new Belos::OutputManager<double>() ); if (verbose) { MyOM->setVerbosity( Belos::Warnings ); } // test the Epetra adapter multivector ierr = Belos::TestMultiVecTraits<double,EMV>(MyOM,ivec); gerr &= ierr; if (ierr) { MyOM->print(Belos::Warnings,"*** EpetraAdapter PASSED TestMultiVecTraits()\n"); } else { MyOM->print(Belos::Warnings,"*** EpetraAdapter FAILED TestMultiVecTraits() ***\n\n"); } #ifdef HAVE_MPI MPI_Finalize(); #endif if (gerr == false) { MyOM->print(Belos::Warnings,"End Result: TEST FAILED\n"); return -1; } // // Default return value // MyOM->print(Belos::Warnings,"End Result: TEST PASSED\n"); return 0; }
// ====================================================================== void GetPtent(const Epetra_RowMatrix& A, Teuchos::ParameterList& List, double* thisns, Teuchos::RCP<Epetra_CrsMatrix>& Ptent, Teuchos::RCP<Epetra_MultiVector>& NextNS, const int domainoffset) { const int nsdim = List.get<int>("null space: dimension",-1); if (nsdim<=0) ML_THROW("null space dimension not given",-1); const Epetra_Map& rowmap = A.RowMatrixRowMap(); const int mylength = rowmap.NumMyElements(); // wrap nullspace into something more handy Epetra_MultiVector ns(View,rowmap,thisns,mylength,nsdim); // vector to hold aggregation information Epetra_IntVector aggs(rowmap,false); // aggregation with global aggregate numbering int naggregates = GetGlobalAggregates(const_cast<Epetra_RowMatrix&>(A),List,thisns,aggs); // build a domain map for Ptent // find first aggregate on proc int firstagg = -1; int offset = -1; for (int i=0; i<mylength; ++i) if (aggs[i]>=0) { offset = firstagg = aggs[i]; break; } offset *= nsdim; if (offset<0) ML_THROW("could not find any aggregate on proc",-2); std::vector<int> coarsegids(naggregates*nsdim); for (int i=0; i<naggregates; ++i) for (int j=0; j<nsdim; ++j) { coarsegids[i*nsdim+j] = offset + domainoffset; ++offset; } Epetra_Map pdomainmap(-1,naggregates*nsdim,&coarsegids[0],0,A.Comm()); // loop aggregates and build ids for dofs std::map<int,std::vector<int> > aggdofs; std::map<int,std::vector<int> >::iterator fool; for (int i=0; i<naggregates; ++i) { std::vector<int> gids(0); aggdofs.insert(std::pair<int,std::vector<int> >(firstagg+i,gids)); } for (int i=0; i<mylength; ++i) { if (aggs[i]<0) continue; std::vector<int>& gids = aggdofs[aggs[i]]; gids.push_back(aggs.Map().GID(i)); } #if 0 // debugging output for (int proc=0; proc<A.Comm().NumProc(); ++proc) { if (proc==A.Comm().MyPID()) { for (fool=aggdofs.begin(); fool!=aggdofs.end(); ++fool) { std::cout << "Proc " << proc << " Aggregate " << fool->first << " Dofs "; std::vector<int>& gids = fool->second; for (int i=0; i<(int)gids.size(); ++i) std::cout << gids[i] << " "; std::cout << std::endl; } } fflush(stdout); A.Comm().Barrier(); } #endif // coarse level nullspace to be filled NextNS = Teuchos::rcp(new Epetra_MultiVector(pdomainmap,nsdim,true)); Epetra_MultiVector& nextns = *NextNS; // matrix Ptent Ptent = Teuchos::rcp(new Epetra_CrsMatrix(Copy,rowmap,nsdim)); // loop aggregates and extract the appropriate slices of the nullspace. // do QR and assemble Q and R to Ptent and NextNS for (fool=aggdofs.begin(); fool!=aggdofs.end(); ++fool) { // extract aggregate-local junk of nullspace const int aggsize = (int)fool->second.size(); Epetra_SerialDenseMatrix Bagg(aggsize,nsdim); for (int i=0; i<aggsize; ++i) for (int j=0; j<nsdim; ++j) Bagg(i,j) = (*ns(j))[ns.Map().LID(fool->second[i])]; // Bagg = Q*R int m = Bagg.M(); int n = Bagg.N(); int lwork = n*10; int info = 0; int k = std::min(m,n); if (k!=n) ML_THROW("Aggregate too small, fatal!",-1); std::vector<double> work(lwork); std::vector<double> tau(k); Epetra_LAPACK lapack; lapack.GEQRF(m,n,Bagg.A(),m,&tau[0],&work[0],lwork,&info); if (info) ML_THROW("Lapack dgeqrf returned nonzero",info); if (work[0]>lwork) { lwork = (int)work[0]; work.resize(lwork); } // get R (stored on Bagg) and assemble it into nextns int agg_cgid = fool->first*nsdim; if (!nextns.Map().MyGID(agg_cgid+domainoffset)) ML_THROW("Missing coarse column id on this proc",-1); for (int i=0; i<n; ++i) for (int j=i; j<n; ++j) (*nextns(j))[nextns.Map().LID(domainoffset+agg_cgid+i)] = Bagg(i,j); // get Q and assemble it into Ptent lapack.ORGQR(m,n,k,Bagg.A(),m,&tau[0],&work[0],lwork,&info); if (info) ML_THROW("Lapack dorgqr returned nonzero",info); for (int i=0; i<aggsize; ++i) { const int actgrow = fool->second[i]; for (int j=0; j<nsdim; ++j) { int actgcol = fool->first*nsdim+j+domainoffset; int errone = Ptent->SumIntoGlobalValues(actgrow,1,&Bagg(i,j),&actgcol); if (errone>0) { int errtwo = Ptent->InsertGlobalValues(actgrow,1,&Bagg(i,j),&actgcol); if (errtwo<0) ML_THROW("Epetra_CrsMatrix::InsertGlobalValues returned negative nonzero",errtwo); } else if (errone) ML_THROW("Epetra_CrsMatrix::SumIntoGlobalValues returned negative nonzero",errone); } } // for (int i=0; i<aggsize; ++i) } // for (fool=aggdofs.begin(); fool!=aggdofs.end(); ++fool) int err = Ptent->FillComplete(pdomainmap,rowmap); if (err) ML_THROW("Epetra_CrsMatrix::FillComplete returned nonzero",err); err = Ptent->OptimizeStorage(); if (err) ML_THROW("Epetra_CrsMatrix::OptimizeStorage returned nonzero",err); return; }
int main(int argc, char *argv[]) { // int MyPID = 0; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); MyPID = Comm.MyPID(); #else Epetra_SerialComm Comm; #endif // typedef double ST; typedef Teuchos::ScalarTraits<ST> SCT; typedef SCT::magnitudeType MT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Belos::MultiVecTraits<ST,MV> MVT; typedef Belos::OperatorTraits<ST,MV,OP> OPT; using Teuchos::ParameterList; using Teuchos::RCP; using Teuchos::rcp; bool success = false; bool verbose = false; try { bool debug = false, proc_verbose = false; int frequency = -1; // frequency of status test output. int numrhs = 1; // number of right-hand sides to solve for int maxiters = -1; // maximum number of iterations allowed per linear system MT tol = 1.0e-10; // relative residual tolerance Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","nodebug",&debug,"Print debugging information from the solver."); cmdp.setOption("frequency",&frequency,"Solvers frequency for printing residuals (#iters)."); cmdp.setOption("tol",&tol,"Relative residual tolerance used by GMRES solver."); cmdp.setOption("num-rhs",&numrhs,"Number of right-hand sides to be solved for."); cmdp.setOption("max-iters",&maxiters,"Maximum number of iterations per linear system (-1 = adapted to problem/block size)."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { return -1; } if (!verbose) frequency = -1; // reset frequency if test is not verbose // ********************************************************************** // ******************Set up the problem to be solved********************* // construct diagonal matrix const int NumGlobalElements = 100; const int m = 4; // number of negative eigenvalues // Create diagonal matrix with n-m positive and m negative eigenvalues. Epetra_Map epetraMap( NumGlobalElements, 0, Comm ); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix( Copy, epetraMap, 1 ) ); for ( int k=0; k<epetraMap.NumMyElements(); k++ ) { int GIDk = epetraMap.GID(k); double val = 2*(GIDk-m) + 1; TEUCHOS_ASSERT_EQUALITY( 0, A->InsertGlobalValues( GIDk, 1, &val, &GIDk ) ); } TEUCHOS_ASSERT_EQUALITY( 0, A->FillComplete() ); TEUCHOS_ASSERT_EQUALITY( 0, A->OptimizeStorage() ); // create initial guess and right-hand side Teuchos::RCP<Epetra_MultiVector> vecX = Teuchos::rcp( new Epetra_MultiVector( epetraMap, numrhs ) ); Teuchos::RCP<Epetra_MultiVector> vecB = Teuchos::rcp( new Epetra_MultiVector( epetraMap, numrhs ) ); // ********************************************************************** proc_verbose = verbose && (MyPID==0); /* Only print on the zero processor */ Teuchos::RCP<Epetra_MultiVector> X; Teuchos::RCP<Epetra_MultiVector> B; // Check to see if the number of right-hand sides is the same as requested. if (numrhs>1) { X = rcp( new Epetra_MultiVector( epetraMap, numrhs ) ); B = rcp( new Epetra_MultiVector( epetraMap, numrhs ) ); X->Random(); OPT::Apply( *A, *X, *B ); X->PutScalar( 0.0 ); } else { X = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecX); B = Teuchos::rcp_implicit_cast<Epetra_MultiVector>(vecB); B->PutScalar( 1.0 ); } // // ********Other information used by block solver*********** // *****************(can be user specified)****************** // if (maxiters == -1) maxiters = NumGlobalElements - 1; // maximum number of iterations to run // ParameterList belosList; belosList.set( "Maximum Iterations", maxiters ); // Maximum number of iterations allowed belosList.set( "Convergence Tolerance", tol ); // Relative convergence tolerance requested belosList.set( "Assert Positive Definiteness", false ); // Explicitly don't enforce positive definiteness int verbosity = Belos::Errors + Belos::Warnings; if (verbose) { verbosity += Belos::TimingDetails + Belos::StatusTestDetails; if (frequency > 0) belosList.set( "Output Frequency", frequency ); } if (debug) { verbosity += Belos::Debug; } belosList.set( "Verbosity", verbosity ); // // Construct an unpreconditioned linear problem instance. // Belos::LinearProblem<double,MV,OP> problem( A, X, B ); bool set = problem.setProblem(); if (set == false) { if (proc_verbose) std::cout << std::endl << "ERROR: Belos::LinearProblem failed to set up correctly!" << std::endl; return -1; } // // ******************************************************************* // ****************Start the CG iteration************************* // ******************************************************************* // // Create an iterative solver manager. RCP<Belos::SolverManager<double,MV,OP> > newSolver = rcp( new Belos::PseudoBlockCGSolMgr<double,MV,OP>(rcp(&problem,false), rcp(&belosList,false))); // // **********Print out information about problem******************* // if (proc_verbose) { std::cout << std::endl << std::endl; std::cout << "Dimension of matrix: " << NumGlobalElements << std::endl; std::cout << "Number of right-hand sides: " << numrhs << std::endl; std::cout << "Relative residual tolerance: " << tol << std::endl; std::cout << std::endl; } // // Perform solve // Belos::ReturnType ret = newSolver->solve(); // // Get the number of iterations for this solve. // int numIters = newSolver->getNumIters(); if (proc_verbose) std::cout << "Number of iterations performed for this solve: " << numIters << std::endl; // // Compute actual residuals. // bool badRes = false; std::vector<double> actual_resids( numrhs ); std::vector<double> rhs_norm( numrhs ); Epetra_MultiVector resid(epetraMap, numrhs); OPT::Apply( *A, *X, resid ); MVT::MvAddMv( -1.0, resid, 1.0, *B, resid ); MVT::MvNorm( resid, actual_resids ); MVT::MvNorm( *B, rhs_norm ); if (proc_verbose) { std::cout<< "---------- Actual Residuals (normalized) ----------"<<std::endl<<std::endl; for ( int i=0; i<numrhs; i++) { double actRes = actual_resids[i]/rhs_norm[i]; std::cout<<"Problem "<<i<<" : \t"<< actRes <<std::endl; if (actRes > tol) badRes = true; } } success = ret==Belos::Converged && !badRes; if (success) { if (proc_verbose) std::cout << "End Result: TEST PASSED" << std::endl; } else { if (proc_verbose) std::cout << "End Result: TEST FAILED" << std::endl; } } TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success); #ifdef EPETRA_MPI MPI_Finalize(); #endif return ( success ? EXIT_SUCCESS : EXIT_FAILURE ); }
int main(int argc, char *argv[]) { int i; bool ierr, gerr; gerr = true; #ifdef HAVE_MPI // Initialize MPI and setup an Epetra communicator MPI_Init(&argc,&argv); Teuchos::RCP<Epetra_MpiComm> Comm = Teuchos::rcp( new Epetra_MpiComm(MPI_COMM_WORLD) ); #else // If we aren't using MPI, then setup a serial communicator. Teuchos::RCP<Epetra_SerialComm> Comm = Teuchos::rcp( new Epetra_SerialComm() ); #endif // number of global elements const int dim = 100; const int blockSize = 5; bool verbose = false; if (argc>1) { if (argv[1][0]=='-' && argv[1][1]=='v') { verbose = true; } } // Create an output manager to handle the I/O from the solver Teuchos::RCP<Anasazi::OutputManager<double> > MyOM = Teuchos::rcp( new Anasazi::BasicOutputManager<double>() ); if (verbose) { MyOM->setVerbosity( Anasazi::Warnings ); } #ifndef HAVE_EPETRA_THYRA MyOM->stream(Anasazi::Warnings) << "Please configure Anasazi with:" << std::endl << "--enable-epetra-thyra" << std::endl << "--enable-anasazi-thyra" << std::endl; #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; #endif // Construct a Map that puts approximately the same number of // equations on each processor. Teuchos::RCP<Epetra_Map> Map = Teuchos::rcp( new Epetra_Map(dim, 0, *Comm) ); // Get update list and number of local equations from newly created Map. int NumMyElements = Map->NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map->MyGlobalElements(&MyGlobalElements[0]); // Create an integer vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of OFF-DIAGONAL term for the ith global equation // on this processor std::vector<int> NumNz(NumMyElements); // We are building a tridiagonal matrix where each row has (-1 2 -1) // So we need 2 off-diagonal terms (except for the first and last equation) for (i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0 || MyGlobalElements[i] == dim-1) { NumNz[i] = 2; } else { NumNz[i] = 3; } } // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, *Map, &NumNz[0]) ); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 std::vector<double> Values(2); Values[0] = -1.0; Values[1] = -1.0; std::vector<int> Indices(2); double two = 2.0; int NumEntries; for (i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (MyGlobalElements[i] == dim-1) { Indices[0] = dim-2; NumEntries = 1; } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; NumEntries = 2; } ierr = A->InsertGlobalValues(MyGlobalElements[i],NumEntries,&Values[0],&Indices[0]); assert(ierr==0); // Put in the diagonal entry ierr = A->InsertGlobalValues(MyGlobalElements[i],1,&two,&MyGlobalElements[i]); assert(ierr==0); } // Finish building the epetra matrix A ierr = A->FillComplete(); assert(ierr==0); #ifdef HAVE_EPETRA_THYRA typedef Thyra::MultiVectorBase<double> TMVB; typedef Thyra::LinearOpBase<double> TLOB; // first, create a Thyra::VectorSpaceBase from an Epetra_Map using the Epetra-Thyra wrappers Teuchos::RCP<const Thyra::VectorSpaceBase<double> > space = Thyra::create_VectorSpace(Map); // then, create a Thyra::MultiVectorBase from the Thyra::VectorSpaceBase using Thyra creational functions Teuchos::RCP<Thyra::MultiVectorBase<double> > thyra_ivec = Thyra::createMembers(space,blockSize); // then, create a Thyra::LinearOpBase from the Epetra_CrsMatrix using the Epetra-Thyra wrappers Teuchos::RCP<const Thyra::LinearOpBase<double> > thyra_op = Thyra::epetraLinearOp(A); // test the Thyra multivector adapter ierr = Anasazi::TestMultiVecTraits<double,TMVB>(MyOM,thyra_ivec); gerr |= ierr; if (ierr) { MyOM->stream(Anasazi::Warnings) << "*** ThyraAdapter PASSED TestMultiVecTraits()" << std::endl; } else { MyOM->stream(Anasazi::Warnings) << "*** ThyraAdapter FAILED TestMultiVecTraits() ***" << std::endl << std::endl; } // test the Thyra operator adapter ierr = Anasazi::TestOperatorTraits<double,TMVB,TLOB>(MyOM,thyra_ivec,thyra_op); gerr |= ierr; if (ierr) { MyOM->stream(Anasazi::Warnings) << "*** ThyraAdapter PASSED TestOperatorTraits()" << std::endl; } else { MyOM->stream(Anasazi::Warnings) << "*** ThyraAdapter FAILED TestOperatorTraits() ***" << std::endl << std::endl; } #endif #ifdef HAVE_MPI MPI_Finalize(); #endif if (gerr == false) { MyOM->print(Anasazi::Warnings,"End Result: TEST FAILED\n"); return -1; } // // Default return value // MyOM->print(Anasazi::Warnings,"End Result: TEST PASSED\n"); return 0; }