Skip to content

Commit

Permalink
Tpetra: Add "compare Maps" utility executable to examples
Browse files Browse the repository at this point in the history
@trilinos/tpetra This is useful for #438 and #558, among others.

Build/Test Cases Summary
Enabled Packages: TpetraCore
Disabled Packages: FEI,PyTrilinos,Moertel,STK,SEACAS,ThreadPool,OptiPack,Rythmos,Intrepid,ROL
0) MPI_DEBUG => passed: passed=100,notpassed=0 (5.17 min)
1) SERIAL_RELEASE => passed: passed=74,notpassed=0 (2.29 min)
Other local commits for this build/test group: b945495
  • Loading branch information
Mark Hoemmen committed Aug 18, 2016
1 parent b945495 commit 566b0db
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/ifpack2/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
TRIBITS_ADD_TEST_DIRECTORIES(belos)
TRIBITS_ADD_TEST_DIRECTORIES(unit_tests)
TRIBITS_ADD_TEST_DIRECTORIES(vanka)

1 change: 1 addition & 0 deletions packages/tpetra/core/example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ ADD_SUBDIRECTORY(Lesson05-Redistribution)
ADD_SUBDIRECTORY(Lesson06-Custom-Operator)
ADD_SUBDIRECTORY(Lesson07-Kokkos-Fill)

ADD_SUBDIRECTORY(utilities)
ADD_SUBDIRECTORY(advanced)
3 changes: 3 additions & 0 deletions packages/tpetra/core/example/README
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ topic.
Other examples
==============

The utilities/ subdirectory builds executable utilities that Trilinos
developers may find useful.

The advanced/ subdirectory contains examples best suited for either
advanced Tpetra users or Tpetra developers.

Expand Down
6 changes: 6 additions & 0 deletions packages/tpetra/core/example/utilities/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TRIBITS_ADD_EXECUTABLE(
compareMaps
SOURCES compareMaps.cpp
COMM serial mpi
)

215 changes: 215 additions & 0 deletions packages/tpetra/core/example/utilities/compareMaps.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// @HEADER
// ***********************************************************************
//
// Tpetra: Templated Linear Algebra Services Package
// Copyright (2008) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact Michael A. Heroux ([email protected])
//
// ************************************************************************
// @HEADER

#include "MatrixMarket_Tpetra.hpp"
#include "Tpetra_Details_gathervPrint.hpp"
#include "Tpetra_DefaultPlatform.hpp"
#include "Tpetra_Map.hpp"
#include "Teuchos_CommandLineProcessor.hpp"
#include "Teuchos_CommHelpers.hpp"
#include "Teuchos_GlobalMPISession.hpp"
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <fstream>
#include <sstream>
#include <iostream>

// This program reads two Maps from a file. The Maps must have the
// same process counts as the input communicator.
int
main (int argc, char* argv[])
{
using Teuchos::broadcast;
using Teuchos::outArg;
using Teuchos::RCP;
using Teuchos::REDUCE_MIN;
using Teuchos::reduceAll;
using std::cerr;
using std::cout;
using std::endl;
typedef Tpetra::Map<> map_type;
// Reader must be templated on a CrsMatrix specialization
typedef Tpetra::MatrixMarket::Reader<Tpetra::CrsMatrix<> > reader_type;

Teuchos::GlobalMPISession mpiSession (&argc, &argv);
const int myRank = mpiSession.getRank ();
const int rootRank = 0;
auto comm = Tpetra::DefaultPlatform::getDefaultPlatform ().getComm ();

std::string mapFile1, mapFile2;
bool tolerant = false;
bool debug = false;
{
const bool throwExceptions = false;
const bool recognizeAllOptions = true; // let Kokkos options through
Teuchos::CommandLineProcessor cmdLineProc (throwExceptions, recognizeAllOptions);
cmdLineProc.setOption ("mapFile1", &mapFile1, "Filename of first Map file, to read on Process 0");
cmdLineProc.setOption ("mapFile2", &mapFile2, "Filename of second Map file, to read on Process 0");
cmdLineProc.setOption ("tolerant", "strict", &tolerant, "Read Maps in tolerant mode");
cmdLineProc.setOption ("debug", "release", &debug, "Enable debug output");

auto result = cmdLineProc.parse (argc, argv);
if (result != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
if (result == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
return EXIT_SUCCESS; // printed help; now we're done
}
else if (result != Teuchos::CommandLineProcessor::PARSE_UNRECOGNIZED_OPTION) {
return EXIT_FAILURE; // some error that's not just an unrecognized option
}
}
}

// On Process 0, test whether the files exist.
int lclFileExists = 0;
int gblFileExists = 0;
if (myRank == rootRank) {
std::ifstream f1 (mapFile1);
lclFileExists = f1.good () ? 1 : 0;
gblFileExists = lclFileExists;
f1.close ();
}
broadcast<int, int> (*comm, rootRank, outArg (gblFileExists));
if (gblFileExists != 1) {
if (myRank == rootRank) {
cerr << "Cannot read the first Map file \"" << mapFile1 << "\"!" << endl;
}
return EXIT_FAILURE;
}

if (myRank == rootRank) {
std::ifstream f2 (mapFile2);
lclFileExists = f2.good ();
gblFileExists = lclFileExists;
f2.close ();
}
broadcast<int, int> (*comm, rootRank, outArg (gblFileExists));
if (gblFileExists != 1) {
if (myRank == rootRank) {
cerr << "Cannot read the second Map file \"" << mapFile2 << "\"!" << endl;
}
return EXIT_FAILURE;
}

if (debug && myRank == rootRank) {
cerr << "Both Map files are readable" << endl;
}

RCP<const map_type> map1;
RCP<const map_type> map2;

int lclSuccess = 0;
int gblSuccess = 0;
std::ostringstream errStrm;
try {
map1 = reader_type::readMapFile (mapFile1, comm, tolerant, debug);
lclSuccess = 1;
}
catch (std::exception& e) {
errStrm << "Process " << myRank << ": Caught exception while reading "
"first Map file: " << e.what () << endl;
}
catch (...) {
errStrm << "Process " << myRank << ": Caught exception not a subclass of "
"std::exception, while reading first Map file" << endl;
}
if (map1.is_null ()) {
errStrm << "Process " << myRank << ": Attempt to read first Map file "
"returned null" << endl;
lclSuccess = 0;
}

reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
if (gblSuccess != 1) {
Tpetra::Details::gathervPrint (std::cerr, errStrm.str (), *comm);
return EXIT_FAILURE;
}

if (debug && myRank == rootRank) {
cerr << "Read first Map file" << endl;
}

try {
map2 = reader_type::readMapFile (mapFile2, comm, tolerant, debug);
lclSuccess = 1;
}
catch (std::exception& e) {
errStrm << "Process " << myRank << ": Caught exception while reading "
"second Map file: " << e.what () << endl;
}
catch (...) {
errStrm << "Process " << myRank << ": Caught exception not a subclass of "
"std::exception, while reading second Map file" << endl;
}
if (map2.is_null ()) {
errStrm << "Process " << myRank << ": Attempt to read second Map file "
"returned null" << endl;
lclSuccess = 0;
}

reduceAll<int, int> (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
if (gblSuccess != 1) {
Tpetra::Details::gathervPrint (std::cerr, errStrm.str (), *comm);
return EXIT_FAILURE;
}

if (debug && myRank == rootRank) {
cerr << "Read second Map file" << endl;
}

// At this point, we have two valid Maps. Let's print stuff about them.
const bool compat = map1->isCompatible (*map2);
const bool same = map1->isSameAs (*map2);
// This is a local (per MPI process) property. Thus, we have to
// all-reduce to find out whether it's true on all processes (which
// is actually what we want to know).
const bool locallyFitted = Tpetra::Details::isLocallyFitted (*map1, *map2);
const int locallyFittedInt = locallyFitted ? 1 : 0;
int globallyFittedInt = 0; // output argument
reduceAll<int, int> (*comm, REDUCE_MIN, locallyFittedInt,
outArg (globallyFittedInt));
const bool globallyFitted = (globallyFittedInt == 1);

if (myRank == rootRank) {
cout << "Maps compatible? " << (compat ? "YES" : "NO") << endl
<< "Maps same? " << (same ? "YES" : "NO") << endl
<< "Maps fitted? " << (globallyFitted ? "YES" : "NO") << endl;
}
return EXIT_SUCCESS;
}

0 comments on commit 566b0db

Please sign in to comment.