exampleImplicitlyComposedLinearOperators.cpp

00001 
00002 // Bring in all of the operator/vector ANA client support software
00003 #include "Thyra_OperatorVectorClientSupport.hpp"
00004 
00005 // Just use a default SPMD space for this example
00006 #include "Thyra_DefaultSpmdVectorSpace.hpp"
00007 
00008 // Some utilities from Teuchos
00009 #include "Teuchos_CommandLineProcessor.hpp"
00010 #include "Teuchos_VerboseObject.hpp"
00011 #include "Teuchos_VerbosityLevelCommandLineProcessorHelpers.hpp"
00012 #include "Teuchos_Time.hpp"
00013 #include "Teuchos_StandardCatchMacros.hpp"
00014 #include "Teuchos_as.hpp"
00015 
00058 template<class Scalar>
00059 int exampleImplicitlyComposedLinearOperators(
00060   const int n0,
00061   const int n1,
00062   const int n2,
00063   Teuchos::FancyOStream &out,
00064   const Teuchos::EVerbosityLevel verbLevel,
00065   typename Teuchos::ScalarTraits<Scalar>::magnitudeType errorTol,
00066   const bool testAdjoint
00067   )
00068 {
00069 
00070   // Using and other declarations
00071   typedef Teuchos::ScalarTraits<Scalar> ST;
00072   using Teuchos::as;
00073   using Teuchos::RCP;
00074   using Teuchos::OSTab;
00075   using Thyra::VectorSpaceBase;
00076   using Thyra::VectorBase;
00077   using Thyra::MultiVectorBase;
00078   using Thyra::LinearOpBase;
00079   using Thyra::defaultSpmdVectorSpace;
00080   using Thyra::randomize;
00081   using Thyra::identity;
00082   using Thyra::diagonal;
00083   using Thyra::multiply;
00084   using Thyra::add;
00085   using Thyra::subtract;
00086   using Thyra::scale;
00087   using Thyra::adjoint;
00088   using Thyra::block1x2;
00089   using Thyra::block2x2;
00090   using Thyra::block2x2;
00091 
00092   out << "\n***"
00093       << "\n*** Demonstrating building linear operators for scalar type "
00094       << ST::name()
00095       << "\n***\n";
00096 
00097   OSTab tab(out);
00098 
00099   //
00100   // A) Set up the basic objects and other inputs to build the implicitly
00101   // composed linear operators.
00102   //
00103   
00104   // Create serial vector spaces in this case
00105   const RCP<const VectorSpaceBase<Scalar> >
00106     space0 = defaultSpmdVectorSpace<Scalar>(n0),
00107     space1 = defaultSpmdVectorSpace<Scalar>(n1),
00108     space2 = defaultSpmdVectorSpace<Scalar>(n2);
00109 
00110   // Create the component linear operators first as multi-vectors
00111   const RCP<MultiVectorBase<Scalar> >
00112     mvA = createMembers(space2, n0, "A"),
00113     mvB = createMembers(space0, n2, "B"),
00114     mvC = createMembers(space0, n0, "C"),
00115     mvE = createMembers(space0, n1, "E"),
00116     mvF = createMembers(space0, n1, "F"),
00117     mvJ = createMembers(space2, n1, "J"),
00118     mvK = createMembers(space1, n2, "K"),
00119     mvL = createMembers(space2, n1, "L"),
00120     mvN = createMembers(space0, n1, "N"),
00121     mvP = createMembers(space2, n1, "P"),
00122     mvQ = createMembers(space0, n2, "Q");
00123 
00124   // Create the vector diagonal for D
00125   const RCP<VectorBase<Scalar> > d = createMember(space2);
00126 
00127   // Get the constants
00128   const Scalar
00129     one = 1.0,
00130     beta = 2.0,
00131     gamma = 3.0,
00132     eta = 4.0;
00133 
00134   // Randomize the values in the Multi-Vector
00135   randomize( -one, +one, &*mvA );
00136   randomize( -one, +one, &*mvB );
00137   randomize( -one, +one, &*mvC );
00138   randomize( -one, +one, &*d );
00139   randomize( -one, +one, &*mvE );
00140   randomize( -one, +one, &*mvF );
00141   randomize( -one, +one, &*mvJ );
00142   randomize( -one, +one, &*mvK );
00143   randomize( -one, +one, &*mvL );
00144   randomize( -one, +one, &*mvN );
00145   randomize( -one, +one, &*mvP );
00146   randomize( -one, +one, &*mvQ );
00147 
00148   // Get the linear operator forms of the basic component linear operators
00149   const RCP<const LinearOpBase<Scalar> >
00150     A = mvA,
00151     B = mvB,
00152     C = mvC,
00153     E = mvE,
00154     F = mvF,
00155     J = mvJ,
00156     K = mvK,
00157     L = mvL,
00158     N = mvN,
00159     P = mvP,
00160     Q = mvQ;
00161 
00162   out << describe(*A, verbLevel);
00163   out << describe(*B, verbLevel);
00164   out << describe(*C, verbLevel);
00165   out << describe(*E, verbLevel);
00166   out << describe(*F, verbLevel);
00167   out << describe(*J, verbLevel);
00168   out << describe(*K, verbLevel);
00169   out << describe(*L, verbLevel);
00170   out << describe(*N, verbLevel);
00171   out << describe(*P, verbLevel);
00172   out << describe(*Q, verbLevel);
00173 
00174   //
00175   // B) Create the composed linear operators
00176   //
00177 
00178   // I
00179   const RCP<const LinearOpBase<Scalar> > I = identity(space1, "I");
00180 
00181   // D = diag(d)
00182   const RCP<const LinearOpBase<Scalar> > D = diagonal(d, "D");
00183 
00184   // M00 = [ gama*B*A + C,  E + F ] ^H
00185   //       [ J^H * A,       I     ]
00186   const RCP<const LinearOpBase<Scalar> > M00 =
00187     adjoint(
00188       block2x2(
00189         add( scale(gamma,multiply(B,A)), C ),  add( E, F ),
00190         multiply(adjoint(J),A),                I
00191         ),
00192       "M00"
00193       );
00194 
00195   out << "\nM00 = " << describe(*M00, verbLevel);
00196 
00197   // M01 = beta * [ Q ]
00198   //              [ K ]
00199   const RCP<const LinearOpBase<Scalar> > M01 =
00200     scale(
00201       beta,
00202       block2x1( Q, K ),
00203       "M01"
00204       );
00205 
00206   out << "\nM01 = "  << describe(*M01, verbLevel);
00207             
00208   // M10 = [ L * N^H,  eta*P ]
00209   const RCP<const LinearOpBase<Scalar> > M10 =
00210     block1x2(
00211       multiply(L,adjoint(N)),  scale(eta,P),
00212       "M10"
00213       );
00214 
00215   out << "\nM10 = " << describe(*M10, verbLevel);
00216 
00217   // M11 = D - Q^H*Q
00218   const RCP<const LinearOpBase<Scalar> > M11 =
00219     subtract( D, multiply(adjoint(Q),Q), "M11" );
00220 
00221   out << "\nM11 = "  << describe(*M11, verbLevel);
00222   
00223 
00224   // M = [ M00, M01 ]
00225   //     [ M10, M11 ]
00226   const RCP<const LinearOpBase<Scalar> > M =
00227     block2x2(
00228       M00, M01,
00229       M10, M11,
00230       "M"
00231       );
00232 
00233   out << "\nM = " << describe(*M, verbLevel);
00234 
00235   
00236   //
00237   // C) Test the final composed operator
00238   //
00239 
00240   Thyra::LinearOpTester<Scalar> linearOpTester;
00241   linearOpTester.set_all_error_tol(errorTol);
00242   linearOpTester.check_adjoint(testAdjoint);
00243   if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_HIGH))
00244     linearOpTester.show_all_tests(true);
00245   if (as<int>(verbLevel) >= as<int>(Teuchos::VERB_EXTREME))
00246     linearOpTester.dump_all(true);
00247 
00248   const bool result = linearOpTester.check(*M,&out);
00249 
00250   return result;
00251 
00252 }
00253 
00254 
00255 //
00256 // Main driver program
00257 //
00258 int main( int argc, char *argv[] )
00259 {
00260   
00261   using Teuchos::CommandLineProcessor;
00262 
00263   bool success = true;
00264   bool result;
00265 
00266   Teuchos::RCP<Teuchos::FancyOStream>
00267     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00268 
00269   try {
00270 
00271     //
00272     // Read in command-line options
00273     //
00274 
00275     CommandLineProcessor  clp;
00276     clp.throwExceptions(false);
00277     clp.addOutputSetupOptions(true);
00278 
00279     int n0 = 2;
00280     clp.setOption( "n0", &n0 );
00281 
00282     int n1 = 3;
00283     clp.setOption( "n1", &n1 );
00284 
00285     int n2 = 4;
00286     clp.setOption( "n2", &n2 );
00287 
00288     Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_MEDIUM;
00289     setVerbosityLevelOption( "verb-level", &verbLevel,
00290       "Top-level verbosity level.  By default, this gets deincremented as you go deeper into numerical objects.",
00291       &clp );
00292 
00293     CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00294     if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00295 
00296 #if defined(HAVE_THYRA_FLOAT)
00297     // Run using float
00298     result = exampleImplicitlyComposedLinearOperators<float>(
00299       n0, n1, n2, *out, verbLevel, 1e-5, true );
00300     if (!result) success = false;
00301 #endif
00302 
00303     // Run using double
00304     result = exampleImplicitlyComposedLinearOperators<double>(
00305       n0, n1, n2, *out, verbLevel, 1e-12, true );
00306     if (!result) success = false;
00307 
00308 #ifdef HAVE_THYRA_COMPLEX
00309 
00310 #if defined(HAVE_THYRA_FLOAT)
00311     // Run using std::complex<float>
00312     result = exampleImplicitlyComposedLinearOperators<std::complex<float> >(
00313       n0, n1, n2, *out, verbLevel, 1e-5, false );
00314     if (!result) success = false;
00315     // 2007/11/02: rabartl: Above, I skip the test of the adjoint since it
00316     // fails but a lot.  On my machine, the relative error is:
00317     //    rel_err((-3.00939,-0.836347),(-0.275689,1.45244)) = 1.14148.
00318     // Since this works just fine for the next complex<double> case, I am
00319     // going to just skip this test.
00320 #endif // defined(HAVE_THYRA_FLOAT)
00321 
00322 
00323     // Run using std::complex<double>
00324     result = exampleImplicitlyComposedLinearOperators<std::complex<double> >(
00325       n0, n1, n2, *out, verbLevel, 1e-12, true );
00326     if (!result) success = false;
00327 
00328 #endif // HAVE_THYRA_COMPLEX
00329 
00330 #ifdef HAVE_TEUCHOS_GNU_MP
00331 
00332     // Run using mpf_class
00333     result = exampleImplicitlyComposedLinearOperators<mpf_class>(
00334       n0, n1, n2, *out, verbLevel, 1e-20, true );
00335     if (!result) success = false;
00336 
00337 #endif // HAVE_TEUCHOS_GNU_MP
00338 
00339   }
00340   TEUCHOS_STANDARD_CATCH_STATEMENTS(true,*out,success)
00341     
00342   if(success)
00343     *out << "\nCongratulations! All of the tests checked out!\n";
00344   else
00345     *out << "\nOh no! At least one of the tests failed!\n";
00346   
00347   return success ? 0 : 1;
00348 
00349 } // end main()

Generated on Wed May 12 21:26:53 2010 for Thyra Operator/Vector Support by  doxygen 1.4.7