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