#include <Tpetra_MultiVector.hpp>
#include <Tpetra_Operator.hpp>
#include <Tpetra_Vector.hpp>
#include <Teuchos_TimeMonitor.hpp>
#include <cstdlib>
#include <iostream>
public:
MV;
private:
node_type>
import_type;
public:
MyOp(const global_ordinal_type n,
const Teuchos::RCP<const Teuchos::Comm<int> > comm) {
using std::cout;
using std::endl;
using Teuchos::RCP;
using Teuchos::rcp;
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_->getLocalNumElements();
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 std::cout;
using std::endl;
using Teuchos::RCP;
using Teuchos::rcp;
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 std::cout;
using std::endl;
using Teuchos::RCP;
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;
}