Thyra Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
EpetraLinearOp_UnitTests.cpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 // 
00005 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
00006 //                 Copyright (2004) Sandia Corporation
00007 // 
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 // 
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 1//
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov) 
00039 // 
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 #include "Thyra_EpetraLinearOp.hpp"
00045 #include "Thyra_ScaledLinearOpBase.hpp"
00046 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
00047 #include "Thyra_RowStatLinearOpBase.hpp"
00048 #include "Thyra_LinearOpTester.hpp"
00049 #include "Thyra_DefaultBlockedLinearOp.hpp"
00050 #include "Thyra_VectorBase.hpp"
00051 #include "Thyra_VectorStdOps.hpp"
00052 #include "Thyra_MultiVectorBase.hpp"
00053 #include "Thyra_MultiVectorStdOps.hpp"
00054 #include "Thyra_DefaultProductVectorSpace.hpp"
00055 #include "Thyra_DefaultProductVector.hpp"
00056 #include "Thyra_DefaultDiagonalLinearOp.hpp"
00057 #include "Thyra_DefaultMultipliedLinearOp.hpp"
00058 #include "Thyra_DefaultZeroLinearOp.hpp"
00059 #include "Thyra_LinearOpTester.hpp"
00060 #include "Thyra_UnitTestHelpers.hpp"
00061 #include "Thyra_DefaultSpmdVectorSpace.hpp"
00062 
00063 #include "EpetraThyraAdaptersTestHelpers.hpp"
00064 
00065 #include "Thyra_DefaultBlockedLinearOp.hpp"
00066 
00067 #include "Teuchos_UnitTestHarness.hpp"
00068 #include "Teuchos_DefaultComm.hpp"
00069 
00070 namespace {
00071 
00072 
00073 
00074 } // namespace
00075 
00076 
00077 namespace Thyra {
00078 
00079 
00080 //
00081 // Unit Tests
00082 //
00083 
00084 
00085 TEUCHOS_UNIT_TEST( EpetraLinearOp, ScaledLinearOpBase )
00086 {
00087   using Teuchos::null;
00088   using Teuchos::inOutArg;
00089   using Teuchos::updateSuccess;
00090   using Teuchos::rcp_dynamic_cast;
00091   typedef ScalarTraits<double> ST;
00092 
00093   // Set up an EpetraLinearOp
00094 
00095   const RCP<const Epetra_Comm> comm = getEpetraComm();
00096   const int numLocalRows = g_localDim;
00097   const int numRows = numLocalRows * comm->NumProc();
00098   const int numCols = numLocalRows / 2;
00099   const RCP<Epetra_CrsMatrix> epetraCrsM = getEpetraMatrix(numRows, numCols);
00100   const RCP<LinearOpBase<double> > epetraOp = nonconstEpetraLinearOp(epetraCrsM);
00101 
00102   const RCP<ScaledLinearOpBase<double> > scaledOp =
00103     rcp_dynamic_cast<ScaledLinearOpBase<double> >(epetraOp, true);
00104 
00105   // Get the original mat-vec
00106 
00107   const double two = 2.0;
00108 
00109   const RCP<VectorBase<double> > rhs_vec =
00110     createMember<double>(epetraOp->domain());
00111   assign<double>(rhs_vec.ptr(), two);
00112 
00113   const RCP<VectorBase<double> > lhs_orig_vec =
00114     createMember<double>(epetraOp->range());
00115 
00116   apply<double>(*epetraOp, Thyra::NOTRANS, *rhs_vec, lhs_orig_vec.ptr());
00117 
00118   if (g_dumpAll) {
00119     out << "epetraOp = " << *epetraOp;
00120     out << "rhs_vec = " << *rhs_vec;
00121     out << "lhs_orig_vec = " << *lhs_orig_vec;
00122   }
00123 
00124   // Scale the op from the left (row scaling)
00125 
00126   const double three = 3.0;
00127 
00128   const RCP<VectorBase<double> > row_scaling =
00129     createMember<double>(epetraOp->range());
00130   assign<double>(row_scaling.ptr(), three);
00131 
00132   scaledOp->scaleLeft(*row_scaling);
00133 
00134   if (g_dumpAll) {
00135     out << "row_scaling = " << *row_scaling;
00136     out << "epetraOp left scaled = " << *epetraOp;
00137   }
00138 
00139   // Test that resulting left scaling
00140 
00141   const RCP<VectorBase<double> > lhs_left_scaled_vec =
00142     createMember<double>(epetraOp->range());
00143 
00144   apply<double>(*epetraOp, NOTRANS, *rhs_vec, lhs_left_scaled_vec.ptr());
00145 
00146   if (g_dumpAll) {
00147     out << "lhs_left_scaled_vec = " << *lhs_left_scaled_vec;
00148   }
00149 
00150   TEST_FLOATING_EQUALITY(
00151     three * sum<double>(*lhs_orig_vec),
00152     sum<double>(*lhs_left_scaled_vec),
00153     as<double>(10.0 * ST::eps())
00154     );
00155 
00156   // Left scale the matrix back
00157 
00158   const RCP<VectorBase<double> > inv_row_scaling =
00159     createMember<double>(epetraOp->range());
00160   reciprocal<double>(*row_scaling, inv_row_scaling.ptr());
00161 
00162   scaledOp->scaleLeft(*inv_row_scaling);
00163 
00164   if (g_dumpAll) {
00165     out << "inv_row_scaling = " << *row_scaling;
00166     out << "epetraOp left scaled back to orig = " << *epetraOp;
00167   }
00168 
00169   const RCP<VectorBase<double> > lhs_orig2_vec =
00170     createMember<double>(epetraOp->range());
00171 
00172   apply<double>(*epetraOp, NOTRANS, *rhs_vec, lhs_orig2_vec.ptr());
00173 
00174   if (g_dumpAll) {
00175     out << "lhs_orig2_vec = " << *lhs_orig2_vec;
00176   }
00177 
00178   TEST_FLOATING_EQUALITY(
00179     sum<double>(*lhs_orig_vec),
00180     sum<double>(*lhs_orig2_vec),
00181     as<double>(10.0 * ST::eps())
00182     );
00183   // NOTE: Above, it would ask for exact binary match except if one uses
00184   // threading it will not match exactly!
00185 
00186   // Scale the op from the right (col scaling)
00187 
00188   const double four = 4.0;
00189 
00190   const RCP<VectorBase<double> > col_scaling =
00191     createMember<double>(epetraOp->domain());
00192   assign<double>(col_scaling.ptr(), four);
00193 
00194   scaledOp->scaleRight(*col_scaling);
00195 
00196   if (g_dumpAll) {
00197     out << "col_scaling = " << *col_scaling;
00198     out << "epetraOp right scaled = " << *epetraOp;
00199   }
00200 
00201   // Test that resulting right scaling
00202 
00203   const RCP<VectorBase<double> > lhs_right_scaled_vec =
00204     createMember<double>(epetraOp->range());
00205 
00206   apply<double>(*epetraOp, NOTRANS, *rhs_vec, lhs_right_scaled_vec.ptr());
00207 
00208   if (g_dumpAll) {
00209     out << "lhs_right_scaled_vec = " << *lhs_right_scaled_vec;
00210   }
00211 
00212   TEST_FLOATING_EQUALITY(
00213     four * sum<double>(*lhs_orig_vec),
00214     sum<double>(*lhs_right_scaled_vec),
00215     as<double>(10.0 * ST::eps())
00216     );
00217 
00218   // Right scale the matrix back
00219 
00220   const RCP<VectorBase<double> > inv_col_scaling =
00221     createMember<double>(epetraOp->domain());
00222   reciprocal<double>(*col_scaling, inv_col_scaling.ptr());
00223 
00224   scaledOp->scaleRight(*inv_col_scaling);
00225 
00226   if (g_dumpAll) {
00227     out << "inv_col_scaling = " << *col_scaling;
00228     out << "epetraOp right scaled back to orig = " << *epetraOp;
00229   }
00230 
00231   const RCP<VectorBase<double> > lhs_orig3_vec =
00232     createMember<double>(epetraOp->range());
00233 
00234   apply<double>(*epetraOp, NOTRANS, *rhs_vec, lhs_orig3_vec.ptr());
00235 
00236   if (g_dumpAll) {
00237     out << "lhs_orig3_vec = " << *lhs_orig3_vec;
00238   }
00239 
00240   TEST_FLOATING_EQUALITY(
00241     sum<double>(*lhs_orig_vec),
00242     sum<double>(*lhs_orig3_vec),
00243     as<double>(10.0 * ST::eps())
00244     );
00245   // NOTE: Above, it would ask for exact binary match except if one uses
00246   // threading it will not match exactly!
00247   
00248 }
00249 
00250 
00251 TEUCHOS_UNIT_TEST( EpetraLinearOp, RowStatLinearOpBase )
00252 {
00253   using Teuchos::null;
00254   using Teuchos::inOutArg;
00255   using Teuchos::updateSuccess;
00256   using Teuchos::rcp_dynamic_cast;
00257   typedef ScalarTraits<double> ST;
00258 
00259   // Set up the EpetraLinearOp
00260 
00261   const RCP<const Epetra_Comm> comm = getEpetraComm();
00262   const int numLocalRows = g_localDim;
00263   const int numRows = numLocalRows * comm->NumProc();
00264   const int numCols = numLocalRows / 2;
00265   const RCP<Epetra_CrsMatrix> epetraCrsM = getEpetraMatrix(numRows, numCols);
00266   const double two = 2.0;
00267   epetraCrsM->PutScalar(-two); // put in negative two just to be extra "tricky"
00268   const RCP<LinearOpBase<double> > epetraOp = nonconstEpetraLinearOp(epetraCrsM);
00269 
00270   const RCP<RowStatLinearOpBase<double> > rowStatOp =
00271     rcp_dynamic_cast<RowStatLinearOpBase<double> >(epetraOp, true);
00272 
00273   if (g_dumpAll) {
00274     out << "epetraOp = " << *epetraOp;
00275   }
00276 
00277   // Get the inverse row sums
00278 
00279   const RCP<VectorBase<double> > inv_row_sums =
00280     createMember<double>(epetraOp->range());
00281   const RCP<VectorBase<double> > row_sums =
00282     createMember<double>(epetraOp->range());
00283 
00284   rowStatOp->getRowStat(RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM,
00285     inv_row_sums.ptr());
00286   rowStatOp->getRowStat(RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM,
00287     row_sums.ptr());
00288 
00289   if (g_dumpAll) {
00290     out << "inv_row_sums = " << *inv_row_sums;
00291     out << "row_sums = " << *row_sums;
00292   }
00293 
00294   TEST_FLOATING_EQUALITY(
00295     sum<double>(*inv_row_sums),
00296     as<double>((1.0 / (two * numCols)) * numRows),
00297     as<double>(10.0 * ST::eps())
00298     );
00299 
00300   TEST_FLOATING_EQUALITY(
00301     sum<double>(*row_sums),
00302     as<double>(two * numCols * numRows),
00303     as<double>(10.0 * ST::eps())
00304     );
00305 }
00306 
00307 RCP<Epetra_CrsMatrix> getMyEpetraMatrix(int numRows, int numCols, double shift=0.0) 
00308 {
00309   const RCP<const Epetra_Comm> comm = getEpetraComm();
00310 
00311   const Epetra_Map rowMap(numRows, 0, *comm);
00312   const Epetra_Map domainMap(numCols, numCols, 0, *comm);
00313  
00314   const RCP<Epetra_CrsMatrix> epetraCrsM =
00315     rcp(new Epetra_CrsMatrix(Copy, rowMap,domainMap,0));
00316 
00317   Array<double> rowEntries(numCols);
00318   Array<int> columnIndices(numCols);
00319   for (int j = 0; j < numCols; ++j)
00320     columnIndices[j] = j;
00321 
00322   const int numLocalRows = rowMap.NumMyElements();
00323   for (int i = 0; i < numLocalRows; ++i) {
00324     for (int j = 0; j < numCols; ++j) {
00325       rowEntries[j] = as<double>(i+1) + as<double>(j+1) / 10 + shift;
00326     }
00327 
00328     epetraCrsM->InsertMyValues( i, numCols, &rowEntries[0], &columnIndices[0] );
00329   }
00330 
00331   epetraCrsM->FillComplete(domainMap,rowMap);
00332   return epetraCrsM;
00333 }
00334 
00335 TEUCHOS_UNIT_TEST( EpetraLinearOp, Blocked_ScaledLinearOpBase)
00336 {
00337   using Teuchos::null;
00338   using Teuchos::inOutArg;
00339   using Teuchos::updateSuccess;
00340   using Teuchos::rcp_dynamic_cast;
00341   typedef ScalarTraits<double> ST;
00342 
00343   // Set up the EpetraLinearOp
00344 
00345   const RCP<const Epetra_Comm> comm = getEpetraComm();
00346   const int numLocalRows = g_localDim;
00347   const int numRows = numLocalRows * comm->NumProc();
00348   const int numCols = numLocalRows ;
00349  
00350   out << "numRows = " << numRows << ", numCols = " << numCols << std::endl;
00351 
00352   const RCP<Epetra_CrsMatrix> epetraCrsM00_base = getMyEpetraMatrix(numRows, numRows);
00353   const RCP<Epetra_CrsMatrix> epetraCrsM01_base = getMyEpetraMatrix(numRows, numCols);
00354   const RCP<Epetra_CrsMatrix> epetraCrsM10_base = getMyEpetraMatrix(numCols, numRows);
00355   const RCP<Epetra_CrsMatrix> epetraCrsM11_base = getMyEpetraMatrix(numCols, numCols);
00356   epetraCrsM00_base->PutScalar(2.0);
00357   epetraCrsM01_base->PutScalar(-8.0);
00358   epetraCrsM10_base->PutScalar(-9.0);
00359   epetraCrsM11_base->PutScalar(3.0);
00360   const RCP<Epetra_CrsMatrix> epetraCrsM00 = getMyEpetraMatrix(numRows, numRows);
00361   const RCP<Epetra_CrsMatrix> epetraCrsM01 = getMyEpetraMatrix(numRows, numCols);
00362   const RCP<Epetra_CrsMatrix> epetraCrsM10 = getMyEpetraMatrix(numCols, numRows);
00363   const RCP<Epetra_CrsMatrix> epetraCrsM11 = getMyEpetraMatrix(numCols, numCols);
00364   epetraCrsM00->PutScalar(2.0);
00365   epetraCrsM01->PutScalar(-8.0);
00366   epetraCrsM10->PutScalar(-9.0);
00367   epetraCrsM11->PutScalar(3.0);
00368 
00369   const RCP<const LinearOpBase<double> > op00_base = epetraLinearOp(epetraCrsM00_base);
00370   const RCP<const LinearOpBase<double> > op01_base = epetraLinearOp(epetraCrsM01_base);
00371   const RCP<const LinearOpBase<double> > op10_base = epetraLinearOp(epetraCrsM10_base);
00372   const RCP<const LinearOpBase<double> > op11_base = epetraLinearOp(epetraCrsM11_base);
00373 
00374   const RCP<LinearOpBase<double> > op00 = nonconstEpetraLinearOp(epetraCrsM00);
00375   const RCP<LinearOpBase<double> > op01 = nonconstEpetraLinearOp(epetraCrsM01);
00376   const RCP<LinearOpBase<double> > op10 = nonconstEpetraLinearOp(epetraCrsM10);
00377   const RCP<LinearOpBase<double> > op11 = nonconstEpetraLinearOp(epetraCrsM11);
00378 
00379   const RCP<const LinearOpBase<double> > blocked_base = block2x2(op00_base,op01_base,op10_base,op11_base);
00380   const RCP<LinearOpBase<double> > blocked = nonconstBlock2x2(op00,op01,op10,op11);
00381 
00382   const RCP<VectorBase<double> > left_scale  = createMember<double>(blocked_base->range());
00383   const RCP<VectorBase<double> > right_scale = createMember<double>(blocked_base->domain());
00384 
00385   put_scalar(7.0,left_scale.ptr());
00386   put_scalar(-4.0,right_scale.ptr());
00387 
00388   rcp_dynamic_cast<ScaledLinearOpBase<double> >(blocked)->scaleLeft(*left_scale);
00389 
00390   {
00391     LinearOpTester<double> tester;
00392     tester.set_all_error_tol(1e-10);
00393     tester.show_all_tests(true);
00394     tester.dump_all(true);
00395     tester.num_random_vectors(5);
00396     const RCP<const LinearOpBase<double> > left_op = Thyra::diagonal(left_scale);
00397     const RCP<const LinearOpBase<double> > ref_op = multiply(left_op,blocked_base);
00398 
00399     updateSuccess(tester.compare(*ref_op, *blocked, ptrFromRef(out)), success);
00400   }
00401 
00402   rcp_dynamic_cast<ScaledLinearOpBase<double> >(blocked)->scaleRight(*right_scale);
00403 
00404   {
00405     LinearOpTester<double> tester;
00406     tester.set_all_error_tol(1e-10);
00407     tester.show_all_tests(true);
00408     tester.dump_all(true);
00409     tester.num_random_vectors(5);
00410     const RCP<const LinearOpBase<double> > left_op = Thyra::diagonal(left_scale);
00411     const RCP<const LinearOpBase<double> > right_op = Thyra::diagonal(right_scale);
00412     const RCP<const LinearOpBase<double> > ref_op = multiply(left_op,blocked_base,right_op);
00413 
00414     updateSuccess(tester.compare(*ref_op, *blocked, ptrFromRef(out)), success);
00415   }
00416 }
00417 
00418 TEUCHOS_UNIT_TEST( EpetraLinearOp, Blocked_RowStatLinearOpBase )
00419 {
00420   using Teuchos::null;
00421   using Teuchos::inOutArg;
00422   using Teuchos::updateSuccess;
00423   using Teuchos::rcp_dynamic_cast;
00424   typedef ScalarTraits<double> ST;
00425 
00426   // Set up the EpetraLinearOp
00427 
00428   const RCP<const Epetra_Comm> comm = getEpetraComm();
00429   const int numLocalRows = g_localDim;
00430   const int numRows = numLocalRows * comm->NumProc();
00431   const int numCols = numLocalRows / 2;
00432  
00433   out << "numRows = " << numRows << ", numCols = " << numCols << std::endl;
00434 
00435   const RCP<Epetra_CrsMatrix> epetraCrsM00 = getEpetraMatrix(numRows, numRows);
00436   const RCP<Epetra_CrsMatrix> epetraCrsM01 = getEpetraMatrix(numRows, numCols);
00437   const RCP<Epetra_CrsMatrix> epetraCrsM10 = getEpetraMatrix(numCols, numRows);
00438   const RCP<Epetra_CrsMatrix> epetraCrsM11 = getEpetraMatrix(numCols, numCols);
00439   epetraCrsM00->PutScalar(2.0);
00440   epetraCrsM01->PutScalar(-8.0);
00441   epetraCrsM10->PutScalar(-9.0);
00442   epetraCrsM11->PutScalar(3.0);
00443 
00444   const RCP<const LinearOpBase<double> > op00 = epetraLinearOp(epetraCrsM00);
00445   const RCP<const LinearOpBase<double> > op01 = epetraLinearOp(epetraCrsM01);
00446   const RCP<const LinearOpBase<double> > op10 = epetraLinearOp(epetraCrsM10);
00447   const RCP<const LinearOpBase<double> > op11 = epetraLinearOp(epetraCrsM11);
00448 
00449   const RCP<const LinearOpBase<double> > blocked = block2x2(op00,op01,op10,op11);
00450 
00451   const RCP<const RowStatLinearOpBase<double> > rowStatOp =
00452     rcp_dynamic_cast<const RowStatLinearOpBase<double> >(blocked, true);
00453 
00454   if (g_dumpAll) {
00455     out << "epetraOp = " << *blocked;
00456   }
00457 
00458   // Get the inverse row sums
00459 
00460   const RCP<VectorBase<double> > inv_row_sums =
00461     createMember<double>(blocked->range());
00462   const RCP<VectorBase<double> > row_sums =
00463     createMember<double>(blocked->range());
00464 
00465   rowStatOp->getRowStat(RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM,
00466     inv_row_sums.ptr());
00467   rowStatOp->getRowStat(RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM,
00468     row_sums.ptr());
00469 
00470   if (g_dumpAll) {
00471     out << "inv_row_sums = " << *inv_row_sums;
00472     out << "row_sums = " << *row_sums;
00473   }
00474 
00475   TEST_FLOATING_EQUALITY(
00476     sum<double>(*inv_row_sums),
00477     as<double>((1.0/(numRows*2.0+numCols*8.0))*numRows + (1.0/(numRows*9.0+numCols*3.0))*numCols),
00478     as<double>(10.0 * ST::eps())
00479     );
00480   TEST_FLOATING_EQUALITY(
00481     sum<double>(*row_sums),
00482     as<double>((numRows*2.0+numCols*8.0)*numRows + (numRows*9.0+numCols*3.0)*numCols),
00483     as<double>(10.0 * ST::eps())
00484     );
00485 }
00486 
00487 TEUCHOS_UNIT_TEST( EpetraLinearOp, Blocked_ScalingWithMultiVectors)
00488 {
00489   using Teuchos::null;
00490   using Teuchos::inOutArg;
00491   using Teuchos::updateSuccess;
00492   using Teuchos::rcp_dynamic_cast;
00493   typedef ScalarTraits<double> ST;
00494 
00495   // Set up the EpetraLinearOp
00496 
00497   const RCP<const Epetra_Comm> comm = getEpetraComm();
00498   const RCP<const Teuchos::Comm<Ordinal> > tComm = 
00499       Teuchos::DefaultComm<Ordinal>::getComm();
00500   const int numLocalRows = 4;
00501   const int numRows = numLocalRows * comm->NumProc();
00502   const int numCols = numLocalRows / 2;
00503  
00504   out << "numRows = " << numRows << ", numCols = " << numCols << std::endl;
00505 
00506   const RCP<Epetra_CrsMatrix> epetraCrsM00 = getMyEpetraMatrix(numRows, numRows);
00507   const RCP<Epetra_CrsMatrix> epetraCrsM00_base = getMyEpetraMatrix(numRows, numRows);
00508   epetraCrsM00->PutScalar(2.0);
00509   epetraCrsM00_base->PutScalar(2.0);
00510 
00511   const RCP<LinearOpBase<double> > op00 = nonconstEpetraLinearOp(epetraCrsM00);
00512   const RCP<const LinearOpBase<double> > op00_base = epetraLinearOp(epetraCrsM00_base);
00513 
00514   RCP<const Thyra::VectorSpaceBase<double> > vs_0 = op00->range();
00515   RCP<const Thyra::VectorSpaceBase<double> > vs_1 = Thyra::locallyReplicatedDefaultSpmdVectorSpace<double>(tComm,numCols);
00516 
00517   RCP<Thyra::MultiVectorBase<double> > vec_01  = Thyra::createMembers(vs_0,numCols);
00518   RCP<Thyra::MultiVectorBase<double> > vec_10t = Thyra::createMembers(op00->domain(),numCols); // tranposed
00519   RCP<Thyra::MultiVectorBase<double> > vec_01_base  = Thyra::createMembers(vs_0,numCols);
00520   RCP<Thyra::MultiVectorBase<double> > vec_10t_base = Thyra::createMembers(op00->domain(),numCols); // tranposed
00521   const RCP<LinearOpBase<double> > op10t = vec_10t;
00522   const RCP<const LinearOpBase<double> > op10t_base = vec_10t_base;
00523   assign(vec_01.ptr(),-8.0);
00524   assign(vec_10t.ptr(),-9.0);
00525   assign(vec_01_base.ptr(),-8.0);
00526   assign(vec_10t_base.ptr(),-9.0);
00527 
00528   const RCP<LinearOpBase<double> > op01 = vec_01;
00529   const RCP<LinearOpBase<double> > op10 = nonconstAdjoint(op10t);
00530   const RCP<LinearOpBase<double> > op11 = nonconstZero(vec_01->domain(),vec_01->domain());
00531 
00532   const RCP<const LinearOpBase<double> > op01_base = vec_01_base;
00533   const RCP<const LinearOpBase<double> > op10_base = adjoint(op10t_base);
00534   const RCP<const LinearOpBase<double> > op11_base = zero(vec_01->domain(),vec_01->domain());
00535 
00536   out << "FIRST" << std::endl;
00537   const RCP<LinearOpBase<double> > blocked = nonconstBlock2x2(op00,op01,op10,op11);
00538   out << "SECOND" << Teuchos::describe(*blocked,Teuchos::VERB_EXTREME) << std::endl;
00539   const RCP<const LinearOpBase<double> > blocked_base = block2x2(op00_base,op01_base,op10_base,op11_base);
00540 
00541   const RCP<const RowStatLinearOpBase<double> > rowStatOp =
00542     rcp_dynamic_cast<const RowStatLinearOpBase<double> >(blocked, true);
00543 
00544   // Get the inverse row sums
00545 
00546   const RCP<VectorBase<double> > inv_row_sums =
00547     createMember<double>(blocked->range());
00548   const RCP<VectorBase<double> > row_sums =
00549     createMember<double>(blocked->range());
00550 
00551   rowStatOp->getRowStat(RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM,
00552     inv_row_sums.ptr());
00553   rowStatOp->getRowStat(RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM,
00554     row_sums.ptr());
00555 
00556   TEST_FLOATING_EQUALITY(
00557     sum<double>(*inv_row_sums),
00558     as<double>((1.0/(numRows*2.0+numCols*8.0))*numRows + (1.0/(numRows*9.0+numCols*0.0))*numCols),
00559     as<double>(10.0 * ST::eps())
00560     );
00561   TEST_FLOATING_EQUALITY(
00562     sum<double>(*row_sums),
00563     as<double>((numRows*2.0+numCols*8.0)*numRows + (numRows*9.0+numCols*0.0)*numCols),
00564     as<double>(10.0 * ST::eps())
00565     );
00566 
00567   {
00568     const RCP<VectorBase<double> > left_scale  = createMember<double>(blocked_base->range());
00569     const RCP<VectorBase<double> > right_scale = createMember<double>(blocked_base->domain());
00570   
00571     put_scalar(7.0,left_scale.ptr());
00572     put_scalar(-4.0,right_scale.ptr());
00573   
00574     rcp_dynamic_cast<ScaledLinearOpBase<double> >(blocked)->scaleLeft(*left_scale);
00575 
00576     {
00577       LinearOpTester<double> tester;
00578       tester.set_all_error_tol(1e-10);
00579       tester.show_all_tests(true);
00580       tester.dump_all(false);
00581       tester.num_random_vectors(2);
00582       const RCP<const LinearOpBase<double> > left_op = Thyra::diagonal(left_scale);
00583       const RCP<const LinearOpBase<double> > ref_op = multiply(left_op,blocked_base);
00584   
00585       updateSuccess(tester.compare(*ref_op, *blocked, ptrFromRef(out)), success);
00586     }
00587   
00588     rcp_dynamic_cast<ScaledLinearOpBase<double> >(blocked)->scaleRight(*right_scale);
00589   
00590     {
00591       LinearOpTester<double> tester;
00592       tester.set_all_error_tol(1e-10);
00593       tester.show_all_tests(true);
00594       tester.dump_all(false);
00595       tester.num_random_vectors(5);
00596       const RCP<const LinearOpBase<double> > left_op = Thyra::diagonal(left_scale);
00597       const RCP<const LinearOpBase<double> > right_op = Thyra::diagonal(right_scale);
00598       const RCP<const LinearOpBase<double> > ref_op = multiply(left_op,blocked_base,right_op);
00599   
00600       updateSuccess(tester.compare(*ref_op, *blocked, ptrFromRef(out)), success);
00601     }
00602   }
00603 }
00604 
00605 
00606 TEUCHOS_UNIT_TEST( EpetraLinearOp, rectangular )
00607 {
00608   using Teuchos::null;
00609   using Teuchos::inOutArg;
00610   using Teuchos::updateSuccess;
00611 
00612   const RCP<const Epetra_Comm> comm = getEpetraComm();
00613   const int numProcs = comm->NumProc();
00614 
00615   const int numLocalRows = g_localDim;
00616   const int numRows = numLocalRows * comm->NumProc();
00617   const int numCols = numLocalRows / 2;
00618 
00619   const RCP<Epetra_CrsMatrix> epetraCrsM = getEpetraMatrix(numRows, numCols);
00620 
00621   const RCP<const LinearOpBase<double> > epetraOp = epetraLinearOp(epetraCrsM);
00622 
00623   LinearOpTester<double> linearOpTester;
00624   linearOpTester.check_adjoint(numProcs == 1);
00625   linearOpTester.show_all_tests(g_show_all_tests);
00626   linearOpTester.dump_all(g_dumpAll);
00627   updateSuccess(linearOpTester.check(*epetraOp, inOutArg(out)), success);
00628 
00629   // NOTE: Above, it would seem the Epetra_CrsMatrix::Apply(...) does not work
00630   // when doing and adjoint where the RowMap has empty processes.
00631    
00632 }
00633 
00634 
00635 TEUCHOS_UNIT_TEST( EpetraLinearOp, blocked_op )
00636 {
00637 
00638   if (Teuchos::GlobalMPISession::getNProc() > 2) {
00639     out << "Skipping test if numProc > 2 since it fails for some reason\n";
00640     return;
00641   }
00642 
00643   using Teuchos::describe;
00644   
00645   // build sub operators
00646   RCP<const LinearOpBase<double> > A00 =
00647     epetraLinearOp(getEpetraMatrix(4,4,0));
00648   RCP<const LinearOpBase<double> > A01 =
00649     epetraLinearOp(getEpetraMatrix(4,3,1));
00650   RCP<const LinearOpBase<double> > A02 =
00651     epetraLinearOp(getEpetraMatrix(4,2,2));
00652   RCP<const LinearOpBase<double> > A10 =
00653     epetraLinearOp(getEpetraMatrix(3,4,3));
00654   RCP<const LinearOpBase<double> > A11 =
00655     epetraLinearOp(getEpetraMatrix(3,3,4));
00656   RCP<const LinearOpBase<double> > A12 =
00657     epetraLinearOp(getEpetraMatrix(3,2,5));
00658   RCP<const LinearOpBase<double> > A20 =
00659     epetraLinearOp(getEpetraMatrix(2,4,6));
00660   RCP<const LinearOpBase<double> > A21 =
00661     epetraLinearOp(getEpetraMatrix(2,3,8));
00662   RCP<const LinearOpBase<double> > A22 =
00663     epetraLinearOp(getEpetraMatrix(2,2,8));
00664 
00665   const Teuchos::EVerbosityLevel verbLevel =
00666     (g_dumpAll ? Teuchos::VERB_HIGH : Teuchos::VERB_MEDIUM);
00667   
00668   out << "Sub operators built" << std::endl;
00669 
00670   {
00671      // build composite operator
00672      RCP<const LinearOpBase<double> > A =
00673        block2x2<double>(
00674          block2x2<double>(A00, A01, A10, A11),   block2x1<double>(A02,A12),
00675          block1x2<double>(A20, A21),             A22
00676          );
00677    
00678      out << "First composite operator built" << std::endl;
00679      
00680      // build vectors for use in apply
00681      RCP<MultiVectorBase<double> > x = createMembers<double>(A->domain(), 3);
00682      RCP<MultiVectorBase<double> > y = createMembers<double>(A->range(), 3);
00683      
00684      randomize(-1.0, 1.0, x.ptr());
00685    
00686      out << "A = \n" << describe(*A, verbLevel) << std::endl;
00687      out << "x = \n" << describe(*x, verbLevel) << std::endl;
00688      out << "y = \n" << describe(*y, verbLevel) << std::endl;
00689      
00690      // perform a matrix vector multiply
00691      apply(*A, NOTRANS, *x, y.ptr());
00692 
00693      out << "First composite operator completed" << std::endl;
00694   }
00695 
00696   {
00697      RCP<const LinearOpBase<double> > A = block2x2<double>(
00698        A11,                          block1x2<double>(A10, A12),
00699        block2x1<double>(A01, A21),   block2x2<double>(A00, A02, A20, A22)
00700        );
00701      
00702      out << "Second composite operator built" << std::endl;
00703      
00704      // build vectors for use in apply
00705      RCP<MultiVectorBase<double> > x = createMembers<double>(A->domain(), 3);
00706      RCP<MultiVectorBase<double> > y = createMembers<double>(A->range(), 3);
00707      
00708      randomize(-1.0, 1.0, x.ptr());
00709    
00710      out << "A = \n" << describe(*A, verbLevel) << std::endl;
00711      out << "x = \n" << describe(*x, verbLevel) << std::endl;
00712      out << "y = \n" << describe(*y, verbLevel) << std::endl;
00713      
00714      // perform a matrix vector multiply
00715      apply(*A, NOTRANS, *x, y.ptr());
00716 
00717      out << "Second composite operator completed" << std::endl;
00718   }
00719 
00720   out << "Test complete" << std::endl;
00721 
00722 }
00723 
00724 
00725 } // namespace Thyra
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines