Parallel data redistribution of Epetra objects.
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
#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
#endif
{
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
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) {
lclerr = A->InsertGlobalValues (myGblElts[i], 2, tempVals, tempGblInds);
}
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) {
lclerr = A->InsertGlobalValues (myGblElts[i], 2, tempVals, tempGblInds);
}
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) {
lclerr = A->InsertGlobalValues (myGblElts[i], 3, tempVals, tempGblInds);
}
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.");
}
gblerr = A->FillComplete ();
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
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
return 0;
}
@ Insert
Definition Epetra_CombineMode.h:76
@ Copy
Definition Epetra_DataAccess.h:63
int MyGlobalElements(int *MyGlobalElementList) const
Puts list of global elements on this processor into the user-provided array.
int NumGlobalElements() const
Number of elements across all processors.
Definition Epetra_BlockMap.h:554
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
Definition Epetra_BlockMap.h:778
int NumMyElements() const
Number of elements on the calling processor.
Definition Epetra_BlockMap.h:563
Epetra_Comm: The Epetra Communication Abstract Base Class.
Definition Epetra_Comm.h:81
virtual int MaxAll(double *PartialMaxs, double *GlobalMaxs, int Count) const =0
Epetra_Comm Global Max function.
virtual int NumProc() const =0
Returns total number of processes.
virtual int MinAll(double *PartialMins, double *GlobalMins, int Count) const =0
Epetra_Comm Global Min function.
virtual int MyPID() const =0
Return my process ID.
Epetra_CrsMatrix: A class for constructing and using real-valued double-precision sparse compressed r...
Definition Epetra_CrsMatrix.h:181
Epetra_Export: This class builds an export object for efficient exporting of off-processor elements.
Definition Epetra_Export.h:70
Epetra_Map: A class for partitioning vectors and matrices.
Definition Epetra_Map.h:127
Epetra_MpiComm: The Epetra MPI Communication Class.
Definition Epetra_MpiComm.h:72
Epetra_SerialComm: The Epetra Serial Communication Class.
Definition Epetra_SerialComm.h:69
int MyPID() const
Return my process ID.
Definition Epetra_SerialComm.h:440
int NumProc() const
Returns total number of processes (always returns 1 for SerialComm).
Definition Epetra_SerialComm.h:443