|
Thyra Package Browser (Single Doxygen Collection) Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Thyra: Interfaces and Support for Abstract Numerical Algorithms 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 // @HEADER 00028 00029 #include "ExampleTridiagSerialLinearOp.hpp" 00030 #include "sillyCgSolve.hpp" 00031 #include "Thyra_DefaultScaledAdjointLinearOp.hpp" 00032 #include "Thyra_DefaultMultipliedLinearOp.hpp" 00033 #include "Thyra_VectorStdOps.hpp" 00034 #include "Thyra_TestingTools.hpp" 00035 #include "Thyra_LinearOpTester.hpp" 00036 #include "Teuchos_GlobalMPISession.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 // This example program is meant to show how easy it is to create 00045 // serial Thyra objects and use them with an ANA (CG in this case). 00046 // 00047 // This example uses a silly concrete tridiagonal matrix class called 00048 // ExampleSpmdTridiagLinearOp that demonstrates how to write and use such 00049 // subclasses. 00050 // 00051 template<class Scalar> 00052 bool runCgSolveExample( 00053 const int dim, 00054 const Scalar diagScale, 00055 const bool symOp, 00056 const bool showAllTests, 00057 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance, 00058 const int maxNumIters 00059 ) 00060 { 00061 00062 using Teuchos::as; 00063 using Teuchos::null; 00064 using Teuchos::RCP; 00065 using Teuchos::rcp; 00066 using Teuchos::OSTab; 00067 typedef Teuchos::ScalarTraits<Scalar> ST; 00068 using Thyra::multiply; 00069 using Thyra::scale; 00070 typedef typename ST::magnitudeType ScalarMag; 00071 bool success = true; 00072 bool result; 00073 Teuchos::RCP<Teuchos::FancyOStream> out = 00074 Teuchos::VerboseObjectBase::getDefaultOStream(); 00075 *out << "\n***\n*** Running silly CG solver using scalar type = \'" 00076 << ST::name() << "\' ...\n***\n"; 00077 Teuchos::Time timer(""); 00078 timer.start(true); 00079 00080 // 00081 // (A) Setup a simple linear system with tridiagonal operator: 00082 // 00083 // [ a*2 -1 ] 00084 // [ -r(1) a*2 -1 ] 00085 // A = [ . . . ] 00086 // [ -r(n-2) a*2 -1 ] 00087 // [ -r(n-1) a*2 ] 00088 // 00089 00090 // (A.1) Create the tridiagonal matrix operator 00091 *out << "\nConstructing tridiagonal matrix A of dimension = " << dim 00092 << " and diagonal multiplier = " << diagScale << " ...\n"; 00093 Teuchos::Array<Scalar> lower(dim-1), diag(dim), upper(dim-1); 00094 const Scalar 00095 up = -ST::one(), 00096 diagTerm = as<Scalar>(2.0) * diagScale * ST::one(), 00097 low = -(symOp ? ST::one() : ST::random()); 00098 int k = 0; 00099 // First row 00100 diag[k] = diagTerm; upper[k] = up; 00101 // Middle rows 00102 for( k = 1; k < dim - 1; ++k ) { 00103 lower[k-1] = low; diag[k] = diagTerm; upper[k] = up; 00104 } 00105 // Last row 00106 lower[k-1] = low; diag[k] = diagTerm; 00107 RCP<const Thyra::LinearOpBase<Scalar> > A = 00108 rcp(new ExampleTridiagSerialLinearOp<Scalar>(dim, lower, diag, upper)); 00109 00110 // (A.2) Testing the linear operator constructed linear operator 00111 *out << "\nTesting the constructed linear operator A ...\n"; 00112 Thyra::LinearOpTester<Scalar> linearOpTester; 00113 linearOpTester.enable_all_tests(false); 00114 linearOpTester.check_linear_properties(true); 00115 linearOpTester.set_all_error_tol(tolerance); 00116 linearOpTester.set_all_warning_tol(1e-2*tolerance); 00117 linearOpTester.show_all_tests(showAllTests); 00118 result = linearOpTester.check(*A, out.ptr()); 00119 if(!result) success = false; 00120 00121 // (A.3) Create RHS vector b and set to a random value 00122 RCP<Thyra::VectorBase<Scalar> > b = createMember(A->range()); 00123 Thyra::seed_randomize<Scalar>(0); 00124 Thyra::randomize( -ST::one(), +ST::one(), b.ptr() ); 00125 00126 // (A.4) Create LHS vector x and set to zero 00127 RCP<Thyra::VectorBase<Scalar> > x = createMember(A->domain()); 00128 Thyra::V_S( x.ptr(), ST::zero() ); 00129 00130 // (A.5) Create the final linear system 00131 if(!symOp) { 00132 *out << "\nSetting up normal equations for unsymmetric system A^H*(A*x-b) => new A*x = b ...\n"; 00133 // A^H*A 00134 RCP<const Thyra::LinearOpBase<Scalar> > AtA = multiply(adjoint(A), A); 00135 // A^H*b 00136 RCP<Thyra::VectorBase<Scalar> > nb = createMember(AtA->range()); 00137 Thyra::apply<Scalar>(*A, Thyra::CONJTRANS, *b, nb.ptr()); 00138 A = AtA; 00139 b = nb; 00140 } 00141 00142 // (A.6) Testing the linear operator used with the solve 00143 *out << "\nTesting the linear operator used with the solve ...\n"; 00144 linearOpTester.check_for_symmetry(true); 00145 result = linearOpTester.check(*A, out.ptr()); 00146 if(!result) success = false; 00147 00148 // 00149 // (B) Solve the linear system with the silly CG solver 00150 // 00151 *out << "\nSolving the linear system with sillyCgSolve(...) ...\n"; 00152 { 00153 OSTab tab2(out); 00154 result = sillyCgSolve(*A, *b, maxNumIters, tolerance, x.ptr(), *out); 00155 } 00156 if(!result) success = false; 00157 00158 // 00159 // (C) Check that the linear system was solved to the specified tolerance 00160 // 00161 RCP<Thyra::VectorBase<Scalar> > r = createMember(A->range()); 00162 // r = b 00163 Thyra::V_V(r.ptr(), *b); 00164 // r = -A*x + r 00165 Thyra::apply<Scalar>(*A, Thyra::NOTRANS, *x, r.ptr(), -ST::one(), ST::one()); 00166 const ScalarMag r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b); 00167 const ScalarMag rel_err = r_nrm/b_nrm, relaxTol = 10.0*tolerance; 00168 result = rel_err <= relaxTol; 00169 if(!result) success = false; 00170 *out << "\nChecking the residual ourselves ...\n"; 00171 { 00172 OSTab tab(out); 00173 *out 00174 << "\n||b-A*x||/||b|| = "<<r_nrm<<"/"<<b_nrm<<" = "<<rel_err<<(result?" <= ":" > ") 00175 <<"10.0*tolerance = "<<relaxTol<<": "<<(result?"passed":"failed")<<std::endl; 00176 } 00177 timer.stop(); 00178 *out << "\nTotal time = " << timer.totalElapsedTime() << " sec\n"; 00179 00180 return success; 00181 00182 } // end runCgSolveExample() 00183 00184 00185 // 00186 // Actual main driver program 00187 // 00188 int main(int argc, char *argv[]) 00189 { 00190 00191 using Teuchos::CommandLineProcessor; 00192 00193 bool success = true; 00194 bool result; 00195 00196 Teuchos::GlobalMPISession mpiSession(&argc,&argv); 00197 // Above is needed to run in an MPI build with some MPI implementations 00198 00199 Teuchos::RCP<Teuchos::FancyOStream> 00200 out = Teuchos::VerboseObjectBase::getDefaultOStream(); 00201 00202 try { 00203 00204 // 00205 // Read in command-line options 00206 // 00207 00208 00209 CommandLineProcessor clp; 00210 clp.throwExceptions(false); 00211 clp.addOutputSetupOptions(true); 00212 00213 int dim = 500; 00214 clp.setOption( "dim", &dim, 00215 "Dimension of the linear system." ); 00216 00217 double diagScale = 1.001; 00218 clp.setOption( "diag-scale", &diagScale, 00219 "Scaling of the diagonal to improve conditioning." ); 00220 00221 bool symOp = true; 00222 clp.setOption( "sym-op", "unsym-op", &symOp, 00223 "Determines if the operator is symmetric or not." ); 00224 00225 bool showAllTests = false; 00226 clp.setOption( "show-all-tests", "show-summary-only", &showAllTests, 00227 "Show all LinearOpTester tests or not" ); 00228 00229 double tolerance = 1e-4; 00230 clp.setOption( "tol", &tolerance, 00231 "Relative tolerance for linear system solve." ); 00232 00233 int maxNumIters = 300; 00234 clp.setOption( "max-num-iters", &maxNumIters, 00235 "Maximum of CG iterations." ); 00236 00237 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv); 00238 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return; 00239 00240 TEST_FOR_EXCEPTION( dim < 2, std::logic_error, "Error, dim=" << dim << " < 2 is not allowed!" ); 00241 00242 #if defined(HAVE_THYRA_FLOAT) 00243 result = runCgSolveExample<float>(dim, diagScale, symOp, showAllTests, 00244 tolerance, maxNumIters); 00245 if(!result) success = false; 00246 #endif 00247 00248 result = runCgSolveExample<double>(dim, diagScale, symOp, showAllTests, 00249 tolerance, maxNumIters); 00250 if(!result) success = false; 00251 00252 #ifdef HAVE_THYRA_COMPLEX 00253 00254 #if defined(HAVE_THYRA_FLOAT) 00255 result = runCgSolveExample<std::complex<float> >(dim, diagScale, symOp, showAllTests, 00256 tolerance, maxNumIters); 00257 if(!result) success = false; 00258 #endif 00259 00260 result = runCgSolveExample<std::complex<double> >(dim, diagScale, symOp, showAllTests, 00261 tolerance, maxNumIters); 00262 if(!result) success = false; 00263 00264 #endif // HAVE_THYRA_COMPLEX 00265 00266 #ifdef HAVE_TEUCHOS_GNU_MP 00267 00268 result = runCgSolveExample<mpf_class>(dim, diagScale, symOp, showAllTests, 00269 tolerance, maxNumIters); 00270 if(!result) success = false; 00271 00272 #ifdef HAVE_THYRA_COMPLEX 00273 00274 //result = runCgSolveExample<std::complex<mpf_class> >(dim, mpf_class(diagScale), symOp, 00275 showAllTests, mpf_class(tolerance), maxNumIters); 00276 //if(!result) success = false; 00277 //The above commented-out code throws a floating-point exception? 00278 00279 #endif // HAVE_THYRA_COMPLEX 00280 00281 #endif // HAVE_TEUCHOS_GNU_MP 00282 00283 } 00284 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success) 00285 00286 if(success) 00287 *out << "\nCongratulations! All of the tests checked out!\n"; 00288 else 00289 *out << "\nOh no! At least one of the tests failed!\n"; 00290 00291 return success ? 0 : 1; 00292 00293 } // end main()
1.7.4