00001
00002
00003 #include "Thyra_OperatorVectorClientSupport.hpp"
00004
00005
00006 #include "Thyra_DefaultSpmdVectorSpace.hpp"
00007
00008
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
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
00101
00102
00103
00104
00105 const RCP<const VectorSpaceBase<Scalar> >
00106 space0 = defaultSpmdVectorSpace<Scalar>(n0),
00107 space1 = defaultSpmdVectorSpace<Scalar>(n1),
00108 space2 = defaultSpmdVectorSpace<Scalar>(n2);
00109
00110
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
00125 const RCP<VectorBase<Scalar> > d = createMember(space2);
00126
00127
00128 const Scalar
00129 one = 1.0,
00130 beta = 2.0,
00131 gamma = 3.0,
00132 eta = 4.0;
00133
00134
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
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
00176
00177
00178
00179 const RCP<const LinearOpBase<Scalar> > I = identity(space1, "I");
00180
00181
00182 const RCP<const LinearOpBase<Scalar> > D = diagonal(d, "D");
00183
00184
00185
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
00198
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
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
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
00225
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
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
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
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
00298 result = exampleImplicitlyComposedLinearOperators<float>(
00299 n0, n1, n2, *out, verbLevel, 1e-5, true );
00300 if (!result) success = false;
00301 #endif
00302
00303
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
00312 result = exampleImplicitlyComposedLinearOperators<std::complex<float> >(
00313 n0, n1, n2, *out, verbLevel, 1e-5, false );
00314 if (!result) success = false;
00315
00316
00317
00318
00319
00320 #endif // defined(HAVE_THYRA_FLOAT)
00321
00322
00323
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
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 }