|
Thyra Package Browser (Single Doxygen Collection)
Version of the Day
|
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
1.7.6.1