00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "ExampleTridiagSerialLinearOp.hpp"
00030 #include "sillyCgSolve.hpp"
00031 #include "sillierCgSolve.hpp"
00032 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00033 #include "Thyra_DefaultMultipliedLinearOp.hpp"
00034 #include "Thyra_VectorStdOps.hpp"
00035 #include "Thyra_TestingTools.hpp"
00036 #include "Thyra_LinearOpTester.hpp"
00037 #include "Teuchos_CommandLineProcessor.hpp"
00038 #include "Teuchos_VerboseObject.hpp"
00039 #include "Teuchos_Time.hpp"
00040 #include "Teuchos_StandardCatchMacros.hpp"
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 template<class Scalar>
00051 bool runCgSolveExample(
00052 const int dim
00053 ,const Scalar diagScale
00054 ,const bool symOp
00055 ,const bool showAllTests
00056 ,const bool verbose
00057 ,const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance
00058 ,const int maxNumIters
00059 ,const bool useSillierCg
00060 )
00061 {
00062 using Teuchos::RCP; using Teuchos::rcp; using Teuchos::null;
00063 using Teuchos::OSTab;
00064 typedef Teuchos::ScalarTraits<Scalar> ST;
00065 using Thyra::multiply; using Thyra::scale;
00066 typedef typename ST::magnitudeType ScalarMag;
00067 bool success = true;
00068 bool result;
00069 Teuchos::RCP<Teuchos::FancyOStream>
00070 out = (verbose ? Teuchos::VerboseObjectBase::getDefaultOStream() : Teuchos::null);
00071 if(verbose)
00072 *out << "\n***\n*** Running silly CG solver using scalar type = \'" << ST::name() << "\' ...\n***\n";
00073 Teuchos::Time timer("");
00074 timer.start(true);
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 if(verbose) *out << "\nConstructing tridiagonal matrix A of dimension = " << dim << " and diagonal multiplier = " << diagScale << " ...\n";
00086 std::vector<Scalar> lower(dim-1), diag(dim), upper(dim-1);
00087 const Scalar up = -ST::one(), diagTerm = Scalar(2)*diagScale*ST::one(), low = -(symOp?ST::one():ST::random());
00088 int k = 0;
00089 diag[k] = diagTerm; upper[k] = up;
00090 for( k = 1; k < dim - 1; ++k ) {
00091 lower[k-1] = low; diag[k] = diagTerm; upper[k] = up;
00092 }
00093 lower[k-1] = low; diag[k] = diagTerm;
00094 RCP<const Thyra::LinearOpBase<Scalar> >
00095 A = rcp(new ExampleTridiagSerialLinearOp<Scalar>(dim,&lower[0],&diag[0],&upper[0]));
00096
00097 if(verbose) *out << "\nTesting the constructed linear operator A ...\n";
00098 Thyra::LinearOpTester<Scalar> linearOpTester;
00099 linearOpTester.enable_all_tests(false);
00100 linearOpTester.check_linear_properties(true);
00101 linearOpTester.set_all_error_tol(tolerance);
00102 linearOpTester.set_all_warning_tol(ScalarMag(ScalarMag(1e-2)*tolerance));
00103 linearOpTester.show_all_tests(showAllTests);
00104 result = linearOpTester.check(*A,out.get());
00105 if(!result) success = false;
00106
00107 RCP<Thyra::VectorBase<Scalar> > b = createMember(A->range());
00108 Thyra::seed_randomize<Scalar>(0);
00109 Thyra::randomize( Scalar(-ST::one()), Scalar(+ST::one()), &*b );
00110
00111 RCP<Thyra::VectorBase<Scalar> > x = createMember(A->domain());
00112 Thyra::assign( &*x, ST::zero() );
00113
00114 if(!symOp) {
00115 if(verbose) *out << "\nSetting up normal equations for unsymmetric system A^H*(A*x-b) => new A*x = b ...\n";
00116 RCP<const Thyra::LinearOpBase<Scalar> > AtA = multiply(adjoint(A),A);
00117 RCP<Thyra::VectorBase<Scalar> > nb = createMember(AtA->range());
00118 Thyra::apply(*A,Thyra::CONJTRANS,*b,&*nb);
00119 A = AtA;
00120 b = nb;
00121 }
00122
00123 if(verbose) *out << "\nTesting the linear operator used with the solve ...\n";
00124 linearOpTester.check_for_symmetry(true);
00125 result = linearOpTester.check(*A,out.get());
00126 if(!result) success = false;
00127
00128
00129
00130 if(verbose) *out << "\nSolving the linear system with sillyCgSolve(...) ...\n";
00131 if(useSillierCg)
00132 result = sillierCgSolve(*A,*b,maxNumIters,tolerance,&*x,OSTab(out).get());
00133 else
00134 result = sillyCgSolve(*A,*b,maxNumIters,tolerance,&*x,OSTab(out).get());
00135 if(!result) success = false;
00136
00137
00138
00139 RCP<Thyra::VectorBase<Scalar> > r = createMember(A->range());
00140 Thyra::assign(&*r,*b);
00141 Thyra::apply(*A,Thyra::NOTRANS,*x,&*r,Scalar(-ST::one()),ST::one());
00142 const ScalarMag r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b);
00143 const ScalarMag rel_err = r_nrm/b_nrm, relaxTol = ScalarMag(10.0)*tolerance;
00144 result = rel_err <= relaxTol;
00145 if(!result) success = false;
00146 if(verbose) {
00147 *out << "\nChecking the residual ourselves ...\n";
00148 {
00149 OSTab tab(out);
00150 *out
00151 << "\n||b-A*x||/||b|| = "<<r_nrm<<"/"<<b_nrm<<" = "<<rel_err<<(result?" <= ":" > ")
00152 <<"10.0*tolerance = "<<relaxTol<<": "<<(result?"passed":"failed")<<std::endl;
00153 }
00154 }
00155 timer.stop();
00156 if(verbose) *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n";
00157
00158 return success;
00159 }
00160
00161
00162
00163
00164 int main(int argc, char *argv[])
00165 {
00166
00167 using Teuchos::CommandLineProcessor;
00168
00169 bool success = true;
00170 bool verbose = true;
00171 bool result;
00172
00173 Teuchos::RCP<Teuchos::FancyOStream>
00174 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00175
00176 try {
00177
00178
00179
00180
00181
00182 int dim = 500;
00183 double diagScale = 1.001;
00184 bool symOp = true;
00185 bool showAllTests = false;
00186 double tolerance = 1e-4;
00187 int maxNumIters = 300;
00188 bool useSillierCg = false;
00189
00190 CommandLineProcessor clp;
00191 clp.throwExceptions(false);
00192 clp.addOutputSetupOptions(true);
00193
00194 clp.setOption( "verbose", "quiet", &verbose, "Determines if any output is printed or not." );
00195 clp.setOption( "dim", &dim, "Dimension of the linear system." );
00196 clp.setOption( "diag-scale", &diagScale, "Scaling of the diagonal to improve conditioning." );
00197 clp.setOption( "sym-op", "unsym-op", &symOp, "Determines if the operator is symmetric or not." );
00198 clp.setOption( "show-all-tests", "show-summary-only", &showAllTests, "Show all LinearOpTester tests or not" );
00199 clp.setOption( "tol", &tolerance, "Relative tolerance for linear system solve." );
00200 clp.setOption( "max-num-iters", &maxNumIters, "Maximum of CG iterations." );
00201 clp.setOption( "use-sillier-cg", "use-silly-cg", &useSillierCg,
00202 "Use the handle-based sillerCgSolve() function or the nonhandle-based sillyCgSolve() function");
00203
00204 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00205 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00206
00207 TEST_FOR_EXCEPTION( dim < 2, std::logic_error, "Error, dim=" << dim << " < 2 is not allowed!" );
00208
00209
00210 result = runCgSolveExample<float>(dim,diagScale,symOp,showAllTests,verbose,tolerance,maxNumIters,useSillierCg);
00211 if(!result) success = false;
00212
00213
00214 result = runCgSolveExample<double>(dim,diagScale,symOp,showAllTests,verbose,tolerance,maxNumIters,useSillierCg);
00215 if(!result) success = false;
00216
00217 #if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX)
00218
00219
00220 result = runCgSolveExample<std::complex<float> >(dim,diagScale,symOp,showAllTests,verbose,tolerance,maxNumIters,useSillierCg);
00221 if(!result) success = false;
00222
00223
00224 result = runCgSolveExample<std::complex<double> >(dim,diagScale,symOp,showAllTests,verbose,tolerance,maxNumIters,useSillierCg);
00225 if(!result) success = false;
00226
00227 #endif
00228
00229 #ifdef HAVE_TEUCHOS_GNU_MP
00230
00231
00232 result = runCgSolveExample<mpf_class>(dim,diagScale,symOp,showAllTests,verbose,tolerance,maxNumIters,useSillierCg);
00233 if(!result) success = false;
00234
00235 #if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX)
00236
00237
00238
00239
00240
00241
00242 #endif
00243
00244 #endif
00245
00246 }
00247 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success)
00248
00249 if (verbose) {
00250 if(success) *out << "\nCongratulations! All of the tests checked out!\n";
00251 else *out << "\nOh no! At least one of the tests failed!\n";
00252 }
00253
00254 return success ? 0 : 1;
00255
00256 }