Skip to content

Commit 31eaefd

Browse files
Merge Pull Request trilinos#12769 from cgcgcg/Trilinos/tpetraAddTest
Automatically Merged using Trilinos Pull Request AutoTester PR Title: b'Tpetra, Teko: SpAdd issues' PR Author: cgcgcg
2 parents 4db651d + d0a8322 commit 31eaefd

File tree

3 files changed

+152
-17
lines changed

3 files changed

+152
-17
lines changed

packages/teko/src/Teko_Utilities.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,34 +2195,43 @@ const ModifiableLinearOp explicitAdd(const LinearOp &opl_in, const LinearOp &opr
21952195
// Build output operator
21962196
RCP<Thyra::LinearOpBase<ST>> explicitOp;
21972197
RCP<Tpetra::CrsMatrix<ST, LO, GO, NT>> explicitCrsOp;
2198-
if (destOp != Teuchos::null) {
2198+
if (!destOp.is_null()) {
21992199
explicitOp = destOp;
2200-
try { // try to reuse matrix sparsity with Add. If it fails, build new operator with add
2201-
RCP<Thyra::TpetraLinearOp<ST, LO, GO, NT>> tOp =
2202-
rcp_dynamic_cast<Thyra::TpetraLinearOp<ST, LO, GO, NT>>(destOp);
2200+
RCP<Thyra::TpetraLinearOp<ST, LO, GO, NT>> tOp =
2201+
rcp_dynamic_cast<Thyra::TpetraLinearOp<ST, LO, GO, NT>>(destOp);
2202+
if (!tOp.is_null())
22032203
explicitCrsOp =
2204-
rcp_dynamic_cast<Tpetra::CrsMatrix<ST, LO, GO, NT>>(tOp->getTpetraOperator(), true);
2205-
Tpetra::MatrixMatrix::Add<ST, LO, GO, NT>(*tCrsOpl, transpl, scalarl, *tCrsOpr, transpr,
2206-
scalarr, explicitCrsOp);
2207-
} catch (std::logic_error &e) {
2208-
RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
2209-
*out << "*** THROWN EXCEPTION ***\n";
2210-
*out << e.what() << std::endl;
2211-
*out << "************************\n";
2212-
*out << "Teko: explicitAdd unable to reuse existing operator. Creating new operator.\n"
2213-
<< std::endl;
2204+
rcp_dynamic_cast<Tpetra::CrsMatrix<ST, LO, GO, NT>>(tOp->getTpetraOperator());
2205+
bool needNewTpetraMatrix =
2206+
(explicitCrsOp.is_null()) || (tCrsOpl == explicitCrsOp) || (tCrsOpr == explicitCrsOp);
2207+
if (!needNewTpetraMatrix) {
2208+
try {
2209+
// try to reuse matrix sparsity with Add. If it fails, build new operator with add
2210+
Tpetra::MatrixMatrix::Add<ST, LO, GO, NT>(*tCrsOpl, transpl, scalarl, *tCrsOpr, transpr,
2211+
scalarr, explicitCrsOp);
2212+
} catch (std::logic_error &e) {
2213+
RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
2214+
*out << "*** THROWN EXCEPTION ***\n";
2215+
*out << e.what() << std::endl;
2216+
*out << "************************\n";
2217+
*out << "Teko: explicitAdd unable to reuse existing operator. Creating new operator.\n"
2218+
<< std::endl;
2219+
needNewTpetraMatrix = true;
2220+
}
2221+
}
2222+
if (needNewTpetraMatrix)
2223+
// Do explicit matrix-matrix add
22142224
explicitCrsOp = Tpetra::MatrixMatrix::add<ST, LO, GO, NT>(scalarl, transpl, *tCrsOpl,
22152225
scalarr, transpr, *tCrsOpr);
2216-
}
22172226
} else {
2218-
explicitOp = rcp(new Thyra::TpetraLinearOp<ST, LO, GO, NT>());
2227+
explicitOp = rcp(new Thyra::TpetraLinearOp<ST, LO, GO, NT>());
2228+
// Do explicit matrix-matrix add
22192229
explicitCrsOp = Tpetra::MatrixMatrix::add<ST, LO, GO, NT>(scalarl, transpl, *tCrsOpl, scalarr,
22202230
transpr, *tCrsOpr);
22212231
}
22222232
RCP<Thyra::TpetraLinearOp<ST, LO, GO, NT>> tExplicitOp =
22232233
rcp_dynamic_cast<Thyra::TpetraLinearOp<ST, LO, GO, NT>>(explicitOp);
22242234

2225-
// Do explicit matrix-matrix add
22262235
tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST, LO, GO, NT>(explicitCrsOp->getRangeMap()),
22272236
Thyra::tpetraVectorSpace<ST, LO, GO, NT>(explicitCrsOp->getDomainMap()),
22282237
explicitCrsOp);

packages/teko/tests/src/tExplicitOps_tpetra.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,23 @@ bool tExplicitOps_tpetra::test_add_mod(int verbosity, std::ostream& os) {
463463
Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(expOp2, true);
464464
RCP<const Tpetra::Operator<ST, LO, GO, NT> > eop3 = tOp3->getConstTpetraOperator();
465465

466+
// Create a target linear operator, with a known sparsity pattern (diagonal) for a second time
467+
expOp2 = Teko::explicitAdd(H_, H_, expOp2);
468+
RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp3b =
469+
Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(expOp2, true);
470+
RCP<const Tpetra::Operator<ST, LO, GO, NT> > eop3b = tOp3b->getConstTpetraOperator();
471+
472+
// check that underlying pointers are the same
473+
{
474+
std::stringstream ss;
475+
Teuchos::FancyOStream fos(rcpFromRef(ss), " |||");
476+
TEST_ASSERT(eop3.getRawPtr() == eop3b.getRawPtr(),
477+
std::endl
478+
<< " tExplicitOps_tpetra::test_add_mod"
479+
<< ": Testing matrix addition returns new pointer");
480+
if (not(eop3.getRawPtr() == eop3b.getRawPtr()) || verbosity >= 10) os << ss.str();
481+
}
482+
466483
// Try to add matricies with sparsity patterns that differ from the target operator
467484
expOp2 = Teko::explicitAdd(Teko::scale(-4.0, F_), Teko::adjoint(G_), expOp2);
468485
RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp4 =
@@ -493,6 +510,52 @@ bool tExplicitOps_tpetra::test_add_mod(int verbosity, std::ostream& os) {
493510
if (not result || verbosity >= 10) os << ss.str();
494511
}
495512

513+
// Create a target linear operator, with a known sparsity pattern (diagonal) and aliased args
514+
expOp2 = Teko::explicitAdd(H_, H_, expOp2);
515+
tOp3 = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(expOp2, true);
516+
eop3 = tOp3->getConstTpetraOperator();
517+
auto expOp3 = Teko::explicitAdd(H_, expOp2, expOp2);
518+
RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp5 =
519+
Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(expOp3, true);
520+
RCP<const Tpetra::Operator<ST, LO, GO, NT> > eop5 = tOp5->getConstTpetraOperator();
521+
522+
// check that underlying pointers are different
523+
// since the sparsity pattern of expOp entering the explicitAdd
524+
// does not match the sparsity pattern returned by the explicitAdd
525+
// a new tpetra operator will be created
526+
{
527+
std::stringstream ss;
528+
Teuchos::FancyOStream fos(rcpFromRef(ss), " |||");
529+
TEST_ASSERT(eop3.getRawPtr() != eop5.getRawPtr(),
530+
std::endl
531+
<< " tExplicitOps_tpetra::test_add_mod2"
532+
<< ": Testing matrix addition returns new pointer");
533+
if (not(eop3.getRawPtr() == eop5.getRawPtr()) || verbosity >= 10) os << ss.str();
534+
}
535+
536+
// Create a target linear operator, with a known sparsity pattern (diagonal) and aliased args
537+
expOp2 = Teko::explicitAdd(H_, H_, expOp2);
538+
tOp3 = Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(expOp2, true);
539+
eop3 = tOp3->getConstTpetraOperator();
540+
auto expOp4 = Teko::explicitAdd(expOp2, H_, expOp2);
541+
RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp6 =
542+
Teuchos::rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(expOp4, true);
543+
RCP<const Tpetra::Operator<ST, LO, GO, NT> > eop6 = tOp6->getConstTpetraOperator();
544+
545+
// check that underlying pointers are different
546+
// since the sparsity pattern of expOp entering the explicitAdd
547+
// does not match the sparsity pattern returned by the explicitAdd
548+
// a new tpetra operator will be created
549+
{
550+
std::stringstream ss;
551+
Teuchos::FancyOStream fos(rcpFromRef(ss), " |||");
552+
TEST_ASSERT(eop3.getRawPtr() != eop6.getRawPtr(),
553+
std::endl
554+
<< " tExplicitOps_tpetra::test_add_mod3"
555+
<< ": Testing matrix addition returns new pointer");
556+
if (not(eop3.getRawPtr() == eop6.getRawPtr()) || verbosity >= 10) os << ss.str();
557+
}
558+
496559
return allPassed;
497560
}
498561

packages/tpetra/core/test/MatrixMatrix/MatrixMatrix_UnitTests.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <Teuchos_UnitTestHarness.hpp>
4545

4646
#include "TpetraExt_MatrixMatrix.hpp"
47+
#include "Teuchos_Assert.hpp"
4748
#include "TpetraExt_TripleMatrixMultiply.hpp"
4849
#include "Tpetra_MatrixIO.hpp"
4950
#include "Tpetra_Core.hpp"
@@ -436,6 +437,56 @@ add_test_results add_into_test(
436437
return toReturn;
437438
}
438439

440+
441+
template<class Matrix_t>
442+
add_test_results reuse_add_test(
443+
const std::string& name,
444+
RCP<Matrix_t > A,
445+
RCP<Matrix_t > B,
446+
bool AT,
447+
bool BT,
448+
RCP<Matrix_t > C,
449+
RCP<const Comm<int> > comm)
450+
{
451+
typedef typename Matrix_t::scalar_type SC;
452+
typedef typename Matrix_t::local_ordinal_type LO;
453+
typedef typename Matrix_t::global_ordinal_type GO;
454+
typedef typename Matrix_t::node_type NT;
455+
typedef Map<LO,GO,NT> Map_t;
456+
457+
add_test_results toReturn;
458+
toReturn.correctNorm = C->getFrobeniusNorm ();
459+
460+
RCP<const Map_t > rowmap = AT ? A->getDomainMap() : A->getRowMap();
461+
size_t estSize = A->getGlobalMaxNumRowEntries() + B->getGlobalMaxNumRowEntries();
462+
// estSize is upper bound for A, B; estimate only for AT, BT.
463+
RCP<Matrix_t> computedC = rcp( new Matrix_t(rowmap, estSize));
464+
465+
SC one = Teuchos::ScalarTraits<SC>::one();
466+
Tpetra::MatrixMatrix::Add(*A, AT, one, *B, BT, one, computedC);
467+
computedC->fillComplete(A->getDomainMap(), A->getRangeMap());
468+
469+
// Call Add a second time
470+
Tpetra::MatrixMatrix::Add(*A, AT, one, *B, BT, one, computedC);
471+
472+
TEUCHOS_ASSERT(A->getDomainMap()->isSameAs(*computedC->getDomainMap()));
473+
TEUCHOS_ASSERT(A->getRangeMap()->isSameAs(*computedC->getRangeMap()));
474+
475+
toReturn.computedNorm = computedC->getFrobeniusNorm ();
476+
toReturn.epsilon = fabs(toReturn.correctNorm - toReturn.computedNorm);
477+
478+
#if 0
479+
Tpetra::MatrixMarket::Writer<Matrix_t>::writeSparseFile(
480+
name+"_calculated.mtx", computedC);
481+
Tpetra::MatrixMarket::Writer<Matrix_t>::writeSparseFile(
482+
name+"_real.mtx", C);
483+
#endif
484+
485+
486+
return toReturn;
487+
}
488+
489+
439490
template<class Matrix_t>
440491
mult_test_results multiply_test_manualfc(
441492
const std::string& name,
@@ -1194,6 +1245,18 @@ TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL(Tpetra_MatMat, operations_test,SC,LO, GO, NT)
11941245
newOut << "\tComputed norm: " << results.computedNorm << endl;
11951246
newOut << "\tEpsilon: " << results.epsilon << endl;
11961247

1248+
if (verbose)
1249+
newOut << "Running 3-argument add reuse test (nonnull C on input) for "
1250+
<< currentSystem.name() << endl;
1251+
1252+
results = reuse_add_test(name+"_add",A, B, AT, BT, C, comm);
1253+
1254+
TEST_COMPARE(results.epsilon, <, epsilon);
1255+
newOut << "Reuse Add Test Results: " << endl;
1256+
newOut << "\tCorrect Norm: " << results.correctNorm << endl;
1257+
newOut << "\tComputed norm: " << results.computedNorm << endl;
1258+
newOut << "\tEpsilon: " << results.epsilon << endl;
1259+
11971260
// FIXME (mfh 09 May 2013) This test doesn't currently pass. I
11981261
// don't think anyone ever exercised the case where C is null on
11991262
// input before. I'm disabling this test for now until I have a

0 commit comments

Comments
 (0)