using namespace gismo;
template<typename Solver>
void configureSolver(Solver & solver, const std::string & config);
int main(
int argc,
char**argv)
{
bool verbose = false;
bool status = false;
bool timing = false;
std::string solver = "Aztec:Gmres";
std::string preconditioner = "ML:DD";
std::string amesos_options = "";
std::string aztec_options = "";
std::string belos_options = "";
std::string ml_options = "";
gsCmdLine cmd(
"This file tests the Trilinos integration");
cmd.addSwitch("verbose", "Verbose output", verbose);
cmd.addSwitch("status", "Status output", status);
cmd.addSwitch("timing", "Timing output", timing);
cmd.addString("p", "preconditioner", "Type of external preconditioner", preconditioner);
cmd.addString("s", "solver", "Type of solver", solver);
cmd.addString("A", "amesos", "Additional options for Amesos solver", amesos_options);
cmd.addString("B", "belos", "Additional options for Belos solver", belos_options);
cmd.addString("M", "ml", "Additional options for ML solver", ml_options);
cmd.addString("Z", "aztec", "Additional options for Aztec solver", aztec_options);
try { cmd.getValues(argc,argv); } catch (int rv) { return rv; }
gsMpiComm comm = gsMpi::init(argc,argv).worldComm();
int n = 0;
if (0==_rank)
{
gsInfo <<
"Running on "<< comm.
size() <<
" processes.\n";
poissonDiscretization(A,b,n);
if ( n < 15 )
{
gsInfo << "Matrix:\n" << A.toDense() << "\n";
gsInfo << "det M = " << A.toDense().determinant() << "\n";
gsInfo << "rhs = "<< b.transpose() << "\n";
}
else
gsInfo << "Matrix: "<< A.rows() << " x " << A.cols() << "\n";
gsSparseSolver<>::SimplicialLDLT LDTL(A);
x = LDTL.solve(b);
if ( n < 100 )
gsInfo << "x = "<< x.transpose() <<"\n\n";
}
#ifdef gsTrilinos_ENABLED
trilinos::SparseMatrix t_A(A);
trilinos::Vector t_b(b, t_A);
gsInfo << "Processor "<<_rank <<" has "<< t_b.mySize()
<<" out of "<<t_b.size()<<" equations.\n";
bool OK_ALL = true;
if (solver.substr(0,6) == "Amesos")
{
solver.substr(7) == "Lapack" ?
solver.substr(7) == "KLU" ?
solver.substr(7) == "Umfpack" ?
solver.substr(7) == "Pardiso" ?
solver.substr(7) == "Taucs" ?
solver.substr(7) == "SuperLU" ?
solver.substr(7) == "SuperLUDist" ?
solver.substr(7) == "Mumps" ?
solver.substr(7) == "Dscpack" ?
0);
configureSolver(t_solver, amesos_options);
if (verbose) gsInfo << t_solver.currentParams();
t_solver.solve(t_b);
if (status) gsInfo << t_solver.status();
if (timing) gsInfo << t_solver.timing();
bool OK = false;
t_solver.getSolution(t_x);
if (0==_rank)
{
const real_t err = (x-t_x).norm();
gsInfo << "norm check: "<< err <<"\n";
OK = ( err < 10e-8 );
if ( n < 100 )
gsInfo << "t_x = "<< t_x.transpose() <<"\n";
}
OK_ALL = OK_ALL && OK;
gsInfo << "Trilinos Amesos solver: " << (OK ? "succeeded\n" : "failed\n");
}
else if (solver.substr(0,5) == "Aztec" &&
(preconditioner == "" ||
(preconditioner.length() >= 5 && preconditioner.substr(0,5) == "Aztec")))
{
configureSolver(t_solver, aztec_options);
if (solver.length() > 5) {
t_solver.set("AZ_solver", solver.substr(6));
}
if (preconditioner.length() > 5) {
t_solver.set("AZ_precond", preconditioner.substr(6));
}
if (verbose) gsInfo << t_solver.currentParams();
t_solver.solve(t_b);
if (status) gsInfo << t_solver.status();
if (timing) gsInfo << t_solver.timing();
bool OK = false;
t_solver.getSolution(t_x);
if (0==_rank)
{
const real_t err = (x-t_x).norm();
gsInfo << "norm check: "<< err <<"\n";
OK = ( err < 10e-8 );
if ( n < 100 )
gsInfo << "t_x = "<< t_x.transpose() <<"\n";
}
OK_ALL = OK_ALL && OK;
gsInfo << "Trilinos Aztec solver: " << (OK ? "succeeded\n" : "failed\n");
}
else if (solver.substr(0,5) == "Aztec" &&
preconditioner.substr(0,2) == "ML")
{
configureSolver(t_solver, aztec_options);
if (solver.length() > 5) {
t_solver.set("AZ_solver", solver.substr(6));
}
if (verbose) gsInfo << t_solver.currentParams();
preconditioner.substr(3) == "SA" ?
trilinos::solver::MLSolvers::SA :
preconditioner.substr(3) == "NSSA" ?
trilinos::solver::MLSolvers::NSSA :
preconditioner.substr(3) == "DD" ?
trilinos::solver::MLSolvers::DD :
preconditioner.substr(3) == "DDLU" ?
trilinos::solver::MLSolvers::DDLU :
preconditioner.substr(3) == "DDML" ?
trilinos::solver::MLSolvers::DDML :
preconditioner.substr(3) == "DDMLLU" ?
trilinos::solver::MLSolvers::DDMLLU :
0);
configureSolver(t_precond, ml_options);
if (verbose) gsInfo << t_precond.currentParams();
t_solver.setPreconditioner(t_precond);
t_solver.solve(t_b);
if (status) gsInfo << t_solver.status();
if (timing) gsInfo << t_solver.timing();
if (status) gsInfo << t_precond.status();
if (timing) gsInfo << t_precond.timing();
bool OK = false;
t_solver.getSolution(t_x);
if (0==_rank)
{
const real_t err = (x-t_x).norm();
gsInfo << "norm check: "<< err <<"\n";
OK = ( err < 10e-8 );
if ( n < 100 )
gsInfo << "t_x = "<< t_x.transpose() <<"\n";
}
OK_ALL = OK_ALL && OK;
gsInfo << "Trilinos Aztec solver with ML preconditioner: " << (OK ? "succeeded\n" : "failed\n");
}
else if (solver.substr(0,5) == "Belos")
{
solver.substr(6) == "BiCGStab" ?
solver.substr(6) == "BlockCG" ?
# ifdef Belos_ENABLE_Experimental
solver.substr(6) == "BlockGCRODR" ?
trilinos::solver::BelosSolvers::BlockGCRODR :
# endif
solver.substr(6) == "BlockGmres" ?
solver.substr(6) == "FixedPoint" ?
solver.substr(6) == "GCRODR" ?
solver.substr(6) == "GmresPoly" ?
solver.substr(6) == "LSQR" ?
solver.substr(6) == "Minres" ?
solver.substr(6) == "PCPG" ?
solver.substr(6) == "PseudoBlockCG" ?
solver.substr(6) == "PseudoBlockGmres" ?
solver.substr(6) == "PseudoBlockStochasticCG" ?
solver.substr(6) == "PseudoBlockTFQMR" ?
solver.substr(6) == "RCG" ?
solver.substr(6) == "TFQMR" ?
0);
configureSolver(t_solver, belos_options);
if (verbose) gsInfo << t_solver.currentParams();
t_solver.solve(t_b);
if (status) gsInfo << t_solver.status();
if (timing) gsInfo << t_solver.timing();
bool OK = false;
t_solver.getSolution(t_x);
if (0==_rank)
{
const real_t err = (x-t_x).norm();
gsInfo << "norm check: "<< err <<"\n";
OK = ( err < 10e-8 );
if ( n < 100 )
gsInfo << "t_x = "<< t_x.transpose() <<"\n";
}
OK_ALL = OK_ALL && OK;
gsInfo << "Trilinos Belos solver: " << (OK ? "succeeded\n" : "failed\n");
}
else
{
gsWarn <<
"Invalid choice of solver. Exiting.\n";
gsWarn <<
"\nValid choices for the solver are:\n";
gsWarn <<
"-s \"Amesos:Dscpack\"\n";
gsWarn <<
"-s \"Amesos:KLU\"\n";
gsWarn <<
"-s \"Amesos:Lapack\"\n";
gsWarn <<
"-s \"Amesos:Mumps\"\n";
gsWarn <<
"-s \"Amesos:Pardiso\"\n";
gsWarn <<
"-s \"Amesos:SuperLUDist\"\n";
gsWarn <<
"-s \"Amesos:SuperLU\"\n";
gsWarn <<
"-s \"Amesos:Taucs\"\n";
gsWarn <<
"-s \"Aztec:Analyze\"\n";
gsWarn <<
"-s \"Aztec:BiCGStab\"\n";
gsWarn <<
"-s \"Aztec:CGS\"\n";
gsWarn <<
"-s \"Aztec:CG\"\n";
gsWarn <<
"-s \"Aztec:CG_Condnum\"\n";
gsWarn <<
"-s \"Aztec:Fixed_Pt\"\n";
gsWarn <<
"-s \"Aztec:GmresR\"\n";
gsWarn <<
"-s \"Aztec:Gmres\"\n";
gsWarn <<
"-s \"Aztec:Gmres_Condnum\"\n";
gsWarn <<
"-s \"Aztec:LU\"\n";
gsWarn <<
"-s \"Aztec:SLU\"\n";
gsWarn <<
"-s \"Aztec:SymmLQ\"\n";
gsWarn <<
"-s \"Aztec:TFQMR\"\n";
gsWarn <<
"-s \"Belos:BiCGStab\"\n";
gsWarn <<
"-s \"Belos:BlockCG\"\n";
# ifdef Belos_ENABLE_Experimental
gsWarn <<
"-s \"Belos:BlockGCRODR\"\n";
# endif
gsWarn <<
"-s \"Belos:BlockGmres\"\n";
gsWarn <<
"-s \"Belos:FixedPoint\"\n";
gsWarn <<
"-s \"Belos:GCRODR\"\n";
gsWarn <<
"-s \"Belos:GmresPoly\"\n";
gsWarn <<
"-s \"Belos:LSQR\"\n";
gsWarn <<
"-s \"Belos:Minres\"\n";
gsWarn <<
"-s \"Belos:PCPG\"\n";
gsWarn <<
"-s \"Belos:PseudoBlockCG\"\n";
gsWarn <<
"-s \"Belos:PseudoBlockStochasticCG\"\n";
gsWarn <<
"-s \"Belos:PseudoBlockTFQMR\"\n";
gsWarn <<
"-s \"Belos:RCG\"\n";
gsWarn <<
"-s \"Belos:TFQMR\"\n";
gsWarn <<
"\nValid choices for the preconditioner are:\n";
gsWarn <<
"-p \"Aztec:Dom_Decomp\"\n";
gsWarn <<
"-p \"Aztec:Jacobi\"\n";
gsWarn <<
"-p \"Aztec:LS\"\n";
gsWarn <<
"-p \"Aztec:Neumann\"\n";
gsWarn <<
"-p \"Aztec:Sym_GS\"\n";
gsWarn <<
"-p \"ML:DDMLLU\"\n";
return 1;
}
return OK_ALL ? EXIT_SUCCESS : EXIT_FAILURE;
#else
return 0;
#endif
}
{
rhs.setZero(N);
mat.resize(N,N);
mat.reservePerColumn(3);
mat(0,0) = 2;
mat(0,1) = -1;
mat(N-1, N-1) = 2;
mat(N-1, N-2) = -1;
{
mat(k,k ) = 2;
mat(k,k-1) = -1;
mat(k,k+1) = -1;
}
const real_t meshSize = (real_t)1/(N+1);
const real_t pi2 = EIGEN_PI*EIGEN_PI;
rhs(k) = pi2*meshSize*meshSize*math::cos(meshSize*(1+k)*EIGEN_PI);
mat.makeCompressed();
}
template<typename Solver>
void configureSolver(Solver & solver, const std::string & str)
{
size_t npos=0, nlen=0;
while (nlen < str.length())
{
nlen = str.substr(npos).find(";");
std::string token = str.substr(npos,nlen);
npos+=nlen+1;
size_t mlen = token.find_last_of(":");
std::string name = token.substr(0,mlen);
size_t mpos = mlen+1;
mlen = token.substr(mpos).find_last_of("=");
std::string type = token.substr(mpos,mlen);
mpos+= mlen+1;
std::string value = token.substr(mpos);
if (type == "BOOL")
solver.set(name, value != "0");
else if (type == "INT")
else if (type == "DOUBLE")
else if (type == "STRING")
solver.set(name, value);
else
GISMO_ERROR(
"Error : Invalid parameter in solver configuration.");
}
}