Import redistributes from a uniquely owned (one-to-one) Map to a possibly not uniquely owned Map. Export redistributes from a possibly not uniquely owned to a uniquely owned Map. We distinguish between these cases both for historical reasons and for performance reasons.
In both cases, Import and Export let the user specify how to combine incoming new data with existing data that has the same global index. For example, one may replace old data with new data or sum them together.
This example shows how to migrate the data in Epetra objects (sparse matrices and vectors) between two different parallel distributions.
#include <Epetra_config.h>
#ifdef HAVE_MPI
# include <mpi.h>
# include <Epetra_MpiComm.h>
#else
# include <Epetra_SerialComm.h>
#endif // HAVE_MPI
#include <Epetra_CrsMatrix.h>
#include <Epetra_Export.h>
#include <Epetra_Map.h>
#include <Epetra_Vector.h>
#include <Epetra_Version.h>
#include <sstream>
#include <stdexcept>
#ifdef EPETRA_NO_32BIT_GLOBAL_INDICES
# define EXAMPLE_USES_64BIT_GLOBAL_INDICES 1
typedef long long global_ordinal_type;
#else
# ifdef EPETRA_NO_64BIT_GLOBAL_INDICES
typedef int global_ordinal_type;
# else
# define EXAMPLE_USES_64BIT_GLOBAL_INDICES 1
typedef long long global_ordinal_type;
# endif // EPETRA_NO_64BIT_GLOBAL_INDICES
#endif // EPETRA_NO_32BIT_GLOBAL_INDICES
{
const global_ordinal_type* myGblElts = NULL;
global_ordinal_type numGblElts = 0;
#ifdef EXAMPLE_USES_64BIT_GLOBAL_INDICES
myGblElts = map.MyGlobalElements64 ();
numGblElts = map.NumGlobalElements64 ();
#else
#endif // EXAMPLE_USES_64BIT_GLOBAL_INDICES
if (numMyElts > 0 && myGblElts == NULL) {
throw std::logic_error ("Failed to get the list of global indices");
}
int lclerr = 0;
double tempVals[3];
global_ordinal_type tempGblInds[3];
for (int i = 0; i < numMyElts; ++i) {
if (myGblElts[i] == 0) {
tempVals[0] = 2.0;
tempVals[1] = -1.0;
tempGblInds[0] = myGblElts[i];
tempGblInds[1] = myGblElts[i] + 1;
if (lclerr == 0) {
}
if (lclerr != 0) {
break;
}
}
else if (myGblElts[i] == numGblElts - 1) {
tempVals[0] = -1.0;
tempVals[1] = 2.0;
tempGblInds[0] = myGblElts[i] - 1;
tempGblInds[1] = myGblElts[i];
if (lclerr == 0) {
}
if (lclerr != 0) {
break;
}
}
else {
tempVals[0] = -1.0;
tempVals[1] = 2.0;
tempVals[2] = -1.0;
tempGblInds[0] = myGblElts[i] - 1;
tempGblInds[1] = myGblElts[i];
tempGblInds[2] = myGblElts[i] + 1;
if (lclerr == 0) {
}
if (lclerr != 0) {
break;
}
}
}
int gblerr = 0;
(void) comm.
MaxAll (&lclerr, &gblerr, 1);
if (gblerr != 0) {
if (A != NULL) {
delete A;
}
throw std::runtime_error ("Some process failed to insert an entry.");
}
if (gblerr != 0) {
if (A != NULL) {
delete A;
}
std::ostringstream os;
os << "A->FillComplete() failed with error code " << gblerr << ".";
throw std::runtime_error (os.str ());
}
return A;
}
void
{
const global_ordinal_type numGblElts = 10 * comm.
NumProc ();
const global_ordinal_type indexBase = 0;
int lclerr = 0;
const int procZeroMapNumLclElts = (comm.
MyPID () == 0) ?
numGblElts :
static_cast<global_ordinal_type> (0);
Epetra_Map procZeroMap (numGblElts, procZeroMapNumLclElts, indexBase, comm);
Epetra_Map globalMap (numGblElts, indexBase, comm);
if (A == NULL) {
lclerr = 1;
}
int gblerr = 0;
(void) comm.
MaxAll (&lclerr, &gblerr, 1);
if (gblerr != 0) {
throw std::runtime_error ("createCrsMatrix returned NULL on at least one "
"process.");
}
lclerr = B.Export (*A, exporter,
Insert);
gblerr = 0;
(void) comm.
MinAll (&lclerr, &gblerr, 1);
if (gblerr != 0) {
throw std::runtime_error ("Export() failed on at least one process.");
}
(void) comm.
MaxAll (&lclerr, &gblerr, 1);
if (gblerr != 0) {
throw std::runtime_error ("Export() failed on at least one process.");
}
lclerr = B.FillComplete ();
gblerr = 0;
(void) comm.
MinAll (&lclerr, &gblerr, 1);
if (gblerr != 0) {
throw std::runtime_error ("B.FillComplete() failed on at least one process.");
}
(void) comm.
MaxAll (&lclerr, &gblerr, 1);
if (gblerr != 0) {
throw std::runtime_error ("B.FillComplete() failed on at least one process.");
}
if (A != NULL) {
delete A;
}
}
int
main (int argc, char *argv[])
{
using std::cout;
using std::endl;
#ifdef HAVE_MPI
MPI_Init (&argc, &argv);
#else
#endif // HAVE_MPI
const int myRank = comm.
MyPID ();
const int numProcs = comm.
NumProc ();
if (myRank == 0) {
cout << Epetra_Version () << endl << endl
<< "Total number of processes: " << numProcs << endl;
}
example (comm);
if (myRank == 0) {
cout << "End Result: TEST PASSED" << endl;
}
#ifdef HAVE_MPI
(void) MPI_Finalize ();
#endif // HAVE_MPI
return 0;
}