#include <Tpetra_MultiVector.hpp>
#include <Tpetra_Operator.hpp>
#include <Tpetra_Vector.hpp>
#include <Teuchos_TimeMonitor.hpp>
#include <cstdlib>
#include <iostream>
public:
private:
public:
MyOp (const global_ordinal_type n,
const Teuchos::RCP<const Teuchos::Comm<int> > comm)
{
using Teuchos::RCP;
using Teuchos::rcp;
using std::cout;
using std::endl;
TEUCHOS_TEST_FOR_EXCEPTION(
comm.is_null (), std::invalid_argument,
"MyOp constructor: The input Comm object must be nonnull.");
const int myRank = comm->getRank ();
const int numProcs = comm->getSize ();
if (myRank == 0) {
cout << "MyOp constructor" << endl;
}
const global_ordinal_type indexBase = 0;
opMap_ = rcp (new map_type (n, indexBase, comm));
local_ordinal_type nlocal = opMap_->getNodeNumElements ();
if (myRank > 0) {
++nlocal;
}
if (myRank < numProcs - 1) {
++nlocal;
}
std::vector<global_ordinal_type> indices;
indices.reserve (nlocal);
if (myRank > 0) {
indices.push_back (opMap_->getMinGlobalIndex () - 1);
}
for (global_ordinal_type i = opMap_->getMinGlobalIndex ();
i <= opMap_->getMaxGlobalIndex (); ++i) {
indices.push_back (i);
}
if (myRank < numProcs - 1) {
indices.push_back (opMap_->getMaxGlobalIndex () + 1);
}
Teuchos::ArrayView<const global_ordinal_type> elementList (indices);
const global_ordinal_type numGlobalElements = n + 2*(numProcs - 1);
redistMap_ = rcp (new map_type (numGlobalElements, elementList, indexBase, comm));
importer_= rcp (new import_type (opMap_, redistMap_));
};
virtual ~MyOp () {}
Teuchos::RCP<const map_type>
getDomainMap()
const {
return opMap_; }
Teuchos::RCP<const map_type>
getRangeMap()
const {
return opMap_; }
void
MV& Y,
Teuchos::ETransp mode = Teuchos::NO_TRANS,
scalar_type alpha = Teuchos::ScalarTraits<scalar_type>::one (),
scalar_type beta = Teuchos::ScalarTraits<scalar_type>::zero ()) const
{
using Teuchos::RCP;
using Teuchos::rcp;
using std::cout;
using std::endl;
typedef Teuchos::ScalarTraits<scalar_type> STS;
RCP<const Teuchos::Comm<int> > comm = opMap_->getComm ();
const int myRank = comm->getRank ();
const int numProcs = comm->getSize ();
if (myRank == 0) {
cout << "MyOp::apply" << endl;
}
TEUCHOS_TEST_FOR_EXCEPTION(
X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
"X and Y do not have the same numbers of vectors (columns).");
TEUCHOS_TEST_FOR_EXCEPTION(
alpha != STS::one() || beta != STS::zero(), std::logic_error,
"MyOp::apply was given alpha != 1 or beta != 0. "
"These cases are not implemented.");
const size_t numVecs = X.getNumVectors ();
RCP<MV> redistData = rcp (new MV (redistMap_, numVecs));
const local_ordinal_type nlocRows =
static_cast<local_ordinal_type> (X.getLocalLength ());
for (size_t c = 0; c < numVecs; ++c) {
Teuchos::ArrayRCP<scalar_type> colView = redistData->getDataNonConst (c);
local_ordinal_type offset;
if (myRank > 0) {
Y.replaceLocalValue (0, c, -colView[0] + 2*colView[1] - colView[2]);
offset = 0;
}
else {
Y.replaceLocalValue (0, c, 2*colView[0] - colView[1]);
offset = 1;
}
for (local_ordinal_type r = 1; r < nlocRows - 1; ++r) {
const scalar_type newVal =
-colView[r-offset] + 2*colView[r+1-offset] - colView[r+2-offset];
Y.replaceLocalValue (r, c, newVal);
}
if (myRank < numProcs - 1) {
const scalar_type newVal =
-colView[nlocRows-1-offset] + 2*colView[nlocRows-offset]
- colView[nlocRows+1-offset];
Y.replaceLocalValue (nlocRows-1, c, newVal);
}
else {
const scalar_type newVal =
-colView[nlocRows-1-offset] + 2*colView[nlocRows-offset];
Y.replaceLocalValue (nlocRows-1, c, newVal);
}
}
}
private:
Teuchos::RCP<const map_type> opMap_, redistMap_;
Teuchos::RCP<const import_type> importer_;
};
int
main (int argc, char *argv[])
{
using Teuchos::RCP;
using std::cout;
using std::endl;
bool success = true;
{
const int myRank = comm->getRank ();
MyOp::global_ordinal_type n = 100;
Teuchos::CommandLineProcessor cmdp (false, true);
cmdp.setOption ("n", &n, "Number of rows of our operator.");
if (cmdp.parse (argc, argv) !=
Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
return EXIT_FAILURE;
}
MyOp K (n, comm);
MyOp::local_ordinal_type,
MyOp::global_ordinal_type,
MyOp::node_type> vec_type;
vec_type x (K.getDomainMap ());
vec_type y (K.getRangeMap ());
K.apply (x, y);
using map_type = MyOp::map_type;
RCP<const map_type> rangeMap = K.getRangeMap ();
vec_type y_expected (rangeMap);
y_expected.putScalar (0.0);
if (rangeMap->isNodeGlobalElement (0)) {
y_expected.replaceGlobalValue (0, 1.0);
}
if (rangeMap->isNodeGlobalElement (n - 1)) {
y_expected.replaceGlobalValue (n - 1, 1.0);
}
y_expected.update (1.0, y, -1.0);
typedef vec_type::mag_type mag_type;
const mag_type diffMaxNorm = y_expected.normInf ();
if (myRank == 0) {
if (diffMaxNorm == 0.0) {
cout << "Yay! ||y - y_expected||_inf = 0." << endl
<< "End Result: TEST PASSED" << endl;
}
else {
success = false;
cout << "Oops! ||y - y_expected||_inf = " << diffMaxNorm
<< " != 0." << endl
<< "End Result: TEST FAILED" << endl;
}
}
}
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}