//============================================================================== // Epetra_Export copy constructor Epetra_Export::Epetra_Export(const Epetra_Export & Exporter) : Epetra_Object(Exporter), TargetMap_(Exporter.TargetMap_), SourceMap_(Exporter.SourceMap_), NumSameIDs_(Exporter.NumSameIDs_), NumPermuteIDs_(Exporter.NumPermuteIDs_), PermuteToLIDs_(0), PermuteFromLIDs_(0), NumRemoteIDs_(Exporter.NumRemoteIDs_), RemoteLIDs_(0), NumExportIDs_(Exporter.NumExportIDs_), ExportLIDs_(0), ExportPIDs_(0), NumSend_(Exporter.NumSend_), NumRecv_(Exporter.NumRecv_), Distor_(0) { int i; if (NumPermuteIDs_>0) { PermuteToLIDs_ = new int[NumPermuteIDs_]; PermuteFromLIDs_ = new int[NumPermuteIDs_]; for (i=0; i< NumPermuteIDs_; i++) { PermuteToLIDs_[i] = Exporter.PermuteToLIDs_[i]; PermuteFromLIDs_[i] = Exporter.PermuteFromLIDs_[i]; } } if (NumRemoteIDs_>0) { RemoteLIDs_ = new int[NumRemoteIDs_]; for (i=0; i< NumRemoteIDs_; i++) RemoteLIDs_[i] = Exporter.RemoteLIDs_[i]; } TargetMap().Comm().Barrier(); if (NumExportIDs_>0) { ExportLIDs_ = new int[NumExportIDs_]; ExportPIDs_ = new int[NumExportIDs_]; for (i=0; i< NumExportIDs_; i++) { ExportLIDs_[i] = Exporter.ExportLIDs_[i]; ExportPIDs_[i] = Exporter.ExportPIDs_[i]; } } if (Exporter.Distor_!=0) Distor_ = Exporter.Distor_->Clone(); }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc, &argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif int NumGlobalElements = 4; // global dimension of the problem int NumMyElements; // local nodes Epetra_IntSerialDenseVector MyGlobalElements; if( Comm.MyPID() == 0 ) { NumMyElements = 3; MyGlobalElements.Size(NumMyElements); MyGlobalElements[0] = 0; MyGlobalElements[1] = 1; MyGlobalElements[2] = 2; } else { NumMyElements = 3; MyGlobalElements.Size(NumMyElements); MyGlobalElements[0] = 1; MyGlobalElements[1] = 2; MyGlobalElements[2] = 3; } // create a map Epetra_Map Map(-1,MyGlobalElements.Length(), MyGlobalElements.Values(),0, Comm); // create a vector based on map Epetra_Vector x(Map); for( int i=0 ; i<NumMyElements ; ++i ) x[i] = 10*( Comm.MyPID()+1 ); cout << x; // create a target map, in which all the elements are on proc 0 int NumMyElements_target; if( Comm.MyPID() == 0 ) NumMyElements_target = NumGlobalElements; else NumMyElements_target = 0; Epetra_Map TargetMap(-1,NumMyElements_target,0,Comm); Epetra_Export Exporter(Map,TargetMap); // work on vectors Epetra_Vector y(TargetMap); y.Export(x,Exporter,Add); cout << y; #ifdef HAVE_MPI MPI_Finalize(); #endif return(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int ierr = 0, i, j, forierr = 0; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif bool verbose = false; // Check if we should print results to standard out if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true; //char tmp; //if (Comm.MyPID()==0) cout << "Press any key to continue..."<< endl; //if (Comm.MyPID()==0) cin >> tmp; //Comm.Barrier(); Comm.SetTracebackMode(0); // This should shut down any error traceback reporting int MyPID = Comm.MyPID(); int NumProc = Comm.NumProc(); if (verbose && MyPID==0) cout << Epetra_Version() << endl << endl; if (verbose) cout << "Processor "<<MyPID<<" of "<< NumProc << " is alive."<<endl; // Redefine verbose to only print on PE 0 if (verbose && Comm.MyPID()!=0) verbose = false; int NumMyEquations = 20; long long NumGlobalEquations = NumMyEquations*NumProc+EPETRA_MIN(NumProc,3); if (MyPID < 3) NumMyEquations++; // Construct a Source Map that puts approximately the same Number of equations on each processor in // uniform global ordering Epetra_Map SourceMap(NumGlobalEquations, NumMyEquations, 0LL, Comm); // Get update list and number of local equations from newly created Map int NumMyElements = SourceMap.NumMyElements(); long long * SourceMyGlobalElements = new long long[NumMyElements]; SourceMap.MyGlobalElements(SourceMyGlobalElements); // Construct a Target Map that will contain: // some unchanged elements (relative to the soure map), // some permuted elements // some off-processor elements Epetra_Vector RandVec(SourceMap); RandVec.Random(); // This creates a vector of random numbers between negative one and one. long long *TargetMyGlobalElements = new long long[NumMyElements]; long long MinGID = SourceMap.MinMyGID64(); for (i=0; i< NumMyEquations/2; i++) TargetMyGlobalElements[i] = i + MinGID; // Half will be the same... for (i=NumMyEquations/2; i<NumMyEquations; i++) { int index = abs((int)(((double) (NumGlobalEquations-1) ) * RandVec[i])); TargetMyGlobalElements[i] = EPETRA_MIN(NumGlobalEquations-1,(long long) EPETRA_MAX(0,index)); } int NumSameIDs = 0; int NumPermutedIDs = 0; int NumRemoteIDs = 0; bool StillContiguous = true; for (i=0; i < NumMyEquations; i++) { if (SourceMyGlobalElements[i]==TargetMyGlobalElements[i] && StillContiguous) NumSameIDs++; else if (SourceMap.MyGID(TargetMyGlobalElements[i])) { StillContiguous = false; NumPermutedIDs++; } else { StillContiguous = false; NumRemoteIDs++; } } EPETRA_TEST_ERR(!(NumMyEquations==NumSameIDs+NumPermutedIDs+NumRemoteIDs),ierr); Epetra_Map TargetMap((long long) -1, NumMyElements, TargetMyGlobalElements, 0LL, Comm); // Create a multivector whose elements are GlobalID * (column number +1) int NumVectors = 3; Epetra_MultiVector SourceMultiVector(SourceMap, NumVectors); for (j=0; j < NumVectors; j++) for (i=0; i < NumMyElements; i++) SourceMultiVector[j][i] = (double) SourceMyGlobalElements[i]*(j+1); // Create a target multivector that we will fill using an Import Epetra_MultiVector TargetMultiVector(TargetMap, NumVectors); Epetra_Import Importer(TargetMap, SourceMap); EPETRA_TEST_ERR(!(TargetMultiVector.Import(SourceMultiVector, Importer, Insert)==0),ierr); // Test Target against expected values forierr = 0; for (j=0; j < NumVectors; j++) for (i=0; i < NumMyElements; i++) { if (TargetMultiVector[j][i]!= (double) TargetMyGlobalElements[i]*(j+1)) cout << "TargetMultiVector["<<i<<"]["<<j<<"] = " << TargetMultiVector[j][i] << " TargetMyGlobalElements[i]*(j+1) = " << TargetMyGlobalElements[i]*(j+1) << endl; forierr += !(TargetMultiVector[j][i]== (double) TargetMyGlobalElements[i]*(j+1)); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "MultiVector Import using Importer Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////// // Now use Importer to do an export Epetra_Vector TargetVector(SourceMap); Epetra_Vector ExpectedTarget(SourceMap); Epetra_Vector SourceVector(TargetMap); NumSameIDs = Importer.NumSameIDs(); int NumPermuteIDs = Importer.NumPermuteIDs(); int NumExportIDs = Importer.NumExportIDs(); int *PermuteFromLIDs = Importer.PermuteFromLIDs(); int *ExportLIDs = Importer.ExportLIDs(); int *ExportPIDs = Importer.ExportPIDs(); for (i=0; i < NumSameIDs; i++) ExpectedTarget[i] = (double) (MyPID+1); for (i=0; i < NumPermuteIDs; i++) ExpectedTarget[PermuteFromLIDs[i]] = (double) (MyPID+1); for (i=0; i < NumExportIDs; i++) ExpectedTarget[ExportLIDs[i]] += (double) (ExportPIDs[i]+1); for (i=0; i < NumMyElements; i++) SourceVector[i] = (double) (MyPID+1); EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, Importer, Add)==0),ierr); forierr = 0; for (i=0; i < NumMyElements; i++) { if (TargetVector[i]!= ExpectedTarget[i]) cout << " TargetVector["<<i<<"] = " << TargetVector[i] << " ExpectedTarget["<<i<<"] = " << ExpectedTarget[i] << " on PE " << MyPID << endl; forierr += !(TargetVector[i]== ExpectedTarget[i]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Vector Export using Importer Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////// // Now use Importer to create a reverse exporter TargetVector.PutScalar(0.0); Epetra_Export ReversedImport(Importer); EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, ReversedImport, Add)==0),ierr); forierr = 0; for (i=0; i < NumMyElements; i++) { if (TargetVector[i]!= ExpectedTarget[i]) cout << " TargetVector["<<i<<"] = " << TargetVector[i] << " ExpectedTarget["<<i<<"] = " << ExpectedTarget[i] << " on PE " << MyPID << endl; forierr += !(TargetVector[i]== ExpectedTarget[i]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Vector Export using Reversed Importer Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////// // Now use Exporter to create a reverse importer TargetVector.PutScalar(0.0); Epetra_Import ReversedExport(ReversedImport); EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, ReversedExport, Add)==0),ierr); forierr = 0; for (i=0; i < NumMyElements; i++) { if (TargetVector[i]!= ExpectedTarget[i]) cout << " TargetVector["<<i<<"] = " << TargetVector[i] << " ExpectedTarget["<<i<<"] = " << ExpectedTarget[i] << " on PE " << MyPID << endl; forierr += !(TargetVector[i]== ExpectedTarget[i]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Vector Export using Reversed Exporter Check OK" << endl << endl; ////////////////////////////////////////////////////////////////////////////////////////// // Build a tridiagonal system two ways: // 1) From "standard" matrix view where equations are uniquely owned. // 2) From 1D PDE view where nodes (equations) between processors are shared and partial contributions are done // in parallel, then merged together at the end of the construction process. // ////////////////////////////////////////////////////////////////////////////////////////// // Construct a Standard Map that puts approximately the same number of equations on each processor in // uniform global ordering Epetra_Map StandardMap(NumGlobalEquations, NumMyEquations, 0LL, Comm); // Get update list and number of local equations from newly created Map NumMyElements = StandardMap.NumMyElements(); long long * StandardMyGlobalElements = new long long[NumMyElements]; StandardMap.MyGlobalElements(StandardMyGlobalElements); // Create a standard Epetra_CrsGraph Epetra_CrsGraph StandardGraph(Copy, StandardMap, 3); EPETRA_TEST_ERR(StandardGraph.IndicesAreGlobal(),ierr); EPETRA_TEST_ERR(StandardGraph.IndicesAreLocal(),ierr); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 long long *Indices = new long long[2]; int NumEntries; forierr = 0; for (i=0; i<NumMyEquations; i++) { if (StandardMyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (StandardMyGlobalElements[i] == NumGlobalEquations-1) { Indices[0] = NumGlobalEquations-2; NumEntries = 1; } else { Indices[0] = StandardMyGlobalElements[i]-1; Indices[1] = StandardMyGlobalElements[i]+1; NumEntries = 2; } forierr += !(StandardGraph.InsertGlobalIndices(StandardMyGlobalElements[i], NumEntries, Indices)==0); forierr += !(StandardGraph.InsertGlobalIndices(StandardMyGlobalElements[i], 1, StandardMyGlobalElements+i)==0); // Put in the diagonal entry } EPETRA_TEST_ERR(forierr,ierr); // Finish up EPETRA_TEST_ERR(!(StandardGraph.IndicesAreGlobal()),ierr); EPETRA_TEST_ERR(!(StandardGraph.FillComplete()==0),ierr); EPETRA_TEST_ERR(!(StandardGraph.IndicesAreLocal()),ierr); EPETRA_TEST_ERR(StandardGraph.StorageOptimized(),ierr); StandardGraph.OptimizeStorage(); EPETRA_TEST_ERR(!(StandardGraph.StorageOptimized()),ierr); EPETRA_TEST_ERR(StandardGraph.UpperTriangular(),ierr); EPETRA_TEST_ERR(StandardGraph.LowerTriangular(),ierr); // Create Epetra_CrsMatrix using the just-built graph Epetra_CrsMatrix StandardMatrix(Copy, StandardGraph); EPETRA_TEST_ERR(StandardMatrix.IndicesAreGlobal(),ierr); EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr); // Add rows one-at-a-time // Need some vectors to help // Off diagonal Values will always be -1 double *Values = new double[2]; Values[0] = -1.0; Values[1] = -1.0; double two = 2.0; forierr = 0; for (i=0; i<NumMyEquations; i++) { if (StandardMyGlobalElements[i]==0) { Indices[0] = 1; NumEntries = 1; } else if (StandardMyGlobalElements[i] == NumGlobalEquations-1) { Indices[0] = NumGlobalEquations-2; NumEntries = 1; } else { Indices[0] = StandardMyGlobalElements[i]-1; Indices[1] = StandardMyGlobalElements[i]+1; NumEntries = 2; } forierr += !(StandardMatrix.ReplaceGlobalValues(StandardMyGlobalElements[i], NumEntries, Values, Indices)==0); // Put in the diagonal entry forierr += !(StandardMatrix.ReplaceGlobalValues(StandardMyGlobalElements[i], 1, &two, StandardMyGlobalElements+i)==0); } EPETRA_TEST_ERR(forierr,ierr); // Finish up EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr); EPETRA_TEST_ERR(!(StandardMatrix.FillComplete()==0),ierr); EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr); // EPETRA_TEST_ERR((StandardMatrix.StorageOptimized()),ierr); EPETRA_TEST_ERR((StandardMatrix.OptimizeStorage()),ierr); EPETRA_TEST_ERR(!(StandardMatrix.StorageOptimized()),ierr); EPETRA_TEST_ERR(StandardMatrix.UpperTriangular(),ierr); EPETRA_TEST_ERR(StandardMatrix.LowerTriangular(),ierr); // Construct an Overlapped Map of StandardMap that include the endpoints from two neighboring processors. int OverlapNumMyElements; long long OverlapMinMyGID; OverlapNumMyElements = NumMyElements + 1; if (MyPID==0) OverlapNumMyElements--; if (MyPID==0) OverlapMinMyGID = StandardMap.MinMyGID64(); else OverlapMinMyGID = StandardMap.MinMyGID64()-1; long long * OverlapMyGlobalElements = new long long[OverlapNumMyElements]; for (i=0; i< OverlapNumMyElements; i++) OverlapMyGlobalElements[i] = OverlapMinMyGID + i; Epetra_Map OverlapMap((long long) -1, OverlapNumMyElements, OverlapMyGlobalElements, 0LL, Comm); // Create the Overlap Epetra_Matrix Epetra_CrsMatrix OverlapMatrix(Copy, OverlapMap, 4); EPETRA_TEST_ERR(OverlapMatrix.IndicesAreGlobal(),ierr); EPETRA_TEST_ERR(OverlapMatrix.IndicesAreLocal(),ierr); // Add matrix element one cell at a time. // Each cell does an incoming and outgoing flux calculation double pos_one = 1.0; double neg_one = -1.0; forierr = 0; for (i=0; i<OverlapNumMyElements; i++) { long long node_left = OverlapMyGlobalElements[i]-1; long long node_center = node_left + 1; long long node_right = node_left + 2; if (i>0) { if (node_left>-1) forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &neg_one, &node_left)==0); forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0); } if (i<OverlapNumMyElements-1) { forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0); if (node_right<NumGlobalEquations) forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &neg_one, &node_right)==0); } } EPETRA_TEST_ERR(forierr,ierr); // Handle endpoints if (MyPID==0) { long long node_center = 0; EPETRA_TEST_ERR(!(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0),ierr); } if (MyPID==NumProc-1) { long long node_center = OverlapMyGlobalElements[OverlapNumMyElements-1]; EPETRA_TEST_ERR(!(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0),ierr); } EPETRA_TEST_ERR(!(OverlapMatrix.FillComplete()==0),ierr); // Make a gathered matrix from OverlapMatrix. It should be identical to StandardMatrix Epetra_CrsMatrix GatheredMatrix(Copy, StandardGraph); Epetra_Export Exporter(OverlapMap, StandardMap); EPETRA_TEST_ERR(!(GatheredMatrix.Export(OverlapMatrix, Exporter, Add)==0),ierr); EPETRA_TEST_ERR(!(GatheredMatrix.FillComplete()==0),ierr); // Check if entries of StandardMatrix and GatheredMatrix are identical int StandardNumEntries, GatheredNumEntries; int * StandardIndices, * GatheredIndices; double * StandardValues, * GatheredValues; int StandardNumMyNonzeros = StandardMatrix.NumMyNonzeros(); int GatheredNumMyNonzeros = GatheredMatrix.NumMyNonzeros(); EPETRA_TEST_ERR(!(StandardNumMyNonzeros==GatheredNumMyNonzeros),ierr); int StandardNumMyRows = StandardMatrix.NumMyRows(); int GatheredNumMyRows = GatheredMatrix.NumMyRows(); EPETRA_TEST_ERR(!(StandardNumMyRows==GatheredNumMyRows),ierr); forierr = 0; for (i=0; i< StandardNumMyRows; i++) { forierr += !(StandardMatrix.ExtractMyRowView(i, StandardNumEntries, StandardValues, StandardIndices)==0); forierr += !(GatheredMatrix.ExtractMyRowView(i, GatheredNumEntries, GatheredValues, GatheredIndices)==0); forierr += !(StandardNumEntries==GatheredNumEntries); for (j=0; j < StandardNumEntries; j++) { //if (StandardIndices[j]!=GatheredIndices[j]) // cout << "MyPID = " << MyPID << " i = " << i << " StandardIndices[" << j << "] = " << StandardIndices[j] // << " GatheredIndices[" << j << "] = " << GatheredIndices[j] << endl; //if (StandardValues[j]!=GatheredValues[j]) //cout << "MyPID = " << MyPID << " i = " << i << " StandardValues[" << j << "] = " << StandardValues[j] // << " GatheredValues[" << j << "] = " << GatheredValues[j] << endl; forierr += !(StandardIndices[j]==GatheredIndices[j]); forierr += !(StandardValues[j]==GatheredValues[j]); } } EPETRA_TEST_ERR(forierr,ierr); if (verbose) cout << "Matrix Export Check OK" << endl << endl; //Do Again with use of Epetra_OffsetIndex object for speed Epetra_OffsetIndex OffsetIndex( OverlapMatrix.Graph(), GatheredMatrix.Graph(), Exporter ); EPETRA_TEST_ERR(!(GatheredMatrix.Export(OverlapMatrix, Exporter, Add)==0),ierr); if (verbose) cout << "Optimized Matrix Export Check OK" << endl << endl; bool passed; Epetra_LongLongVector v1(StandardMap); v1.PutValue(2); Epetra_LongLongVector v2(StandardMap); v2.PutValue(3); Epetra_Export identExporter(StandardMap,StandardMap); // Identity exporter EPETRA_TEST_ERR(!(v2.Export(v1, identExporter, Insert)==0),ierr); passed = (v2.MinValue()==2); EPETRA_TEST_ERR(!passed,ierr); v1.PutValue(1); Epetra_Import identImporter(StandardMap,StandardMap); // Identity importer EPETRA_TEST_ERR(!(v2.Import(v1, identExporter, Insert)==0),ierr); passed = passed && (v2.MaxValue()==1); EPETRA_TEST_ERR(!passed,ierr); if (verbose) { if (passed) cout << "Identity Import/Export Check OK" << endl << endl; else cout << "Identity Import/Export Check Failed" << endl << endl; } int NumSubMapElements = StandardMap.NumMyElements()/2; int SubStart = Comm.MyPID(); NumSubMapElements = EPETRA_MIN(NumSubMapElements,StandardMap.NumMyElements()-SubStart); Epetra_Map SubMap((long long) -1, NumSubMapElements, StandardMyGlobalElements+SubStart, 0LL, Comm); Epetra_LongLongVector v3(View, SubMap, SubMap.MyGlobalElements64()); // Fill v3 with GID values for variety Epetra_Export subExporter(SubMap, StandardMap); // Export to a subset of indices of standard map EPETRA_TEST_ERR(!(v2.Export(v3,subExporter,Insert)==0),ierr); forierr = 0; for (i=0; i<SubMap.NumMyElements(); i++) { int i1 = StandardMap.LID(SubMap.GID64(i)); forierr += !(v3[i]==v2[i1]); } EPETRA_TEST_ERR(forierr,ierr); Epetra_Import subImporter(StandardMap, SubMap); // Import to a subset of indices of standard map EPETRA_TEST_ERR(!(v1.Import(v3,subImporter,Insert)==0),ierr); for (i=0; i<SubMap.NumMyElements(); i++) { int i1 = StandardMap.LID(SubMap.GID64(i)); forierr += !(v3[i]==v1[i1]); } EPETRA_TEST_ERR(forierr,ierr); if (verbose) { if (forierr==0) cout << "SubMap Import/Export Check OK" << endl << endl; else cout << "SubMap Import/Export Check Failed" << endl << endl; } #ifdef DOESNT_WORK_IN_PARALLEL forierr = special_submap_import_test(Comm); EPETRA_TEST_ERR(forierr, ierr); if (verbose) { if (forierr==0) cout << "Special SubMap Import Check OK" << endl << endl; else cout << "Special SubMap Import Check Failed" << endl << endl; } #endif forierr = alternate_import_constructor_test(Comm); EPETRA_TEST_ERR(forierr, ierr); if (verbose) { if (forierr==0) cout << "Alternative Import Constructor Check OK" << endl << endl; else cout << "Alternative Import Constructor Check Failed" << endl << endl; } // Release all objects delete [] SourceMyGlobalElements; delete [] TargetMyGlobalElements; delete [] OverlapMyGlobalElements; delete [] StandardMyGlobalElements; delete [] Values; delete [] Indices; #ifdef EPETRA_MPI MPI_Finalize() ; #endif /* end main */ return ierr ; }
// main driver int main(int argc, char *argv[]) { #ifdef HAVE_MPI MPI_Init(&argc, &argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif if (Comm.NumProc() != 2) { #ifdef HAVE_MPI MPI_Finalize(); #endif return(0); } int NumMyElements = 0; // NODES assigned to this processor int NumMyExternalElements = 0; // nodes used by this proc, but not hosted int NumMyTotalElements = 0; int FE_NumMyElements = 0; // TRIANGLES assigned to this processor int * MyGlobalElements = 0; // nodes assigned to this processor Epetra_IntSerialDenseMatrix T; // store the grid connectivity int MyPID=Comm.MyPID(); cout << MyPID << endl; switch( MyPID ) { case 0: NumMyElements = 3; NumMyExternalElements = 2; NumMyTotalElements = NumMyElements + NumMyExternalElements; FE_NumMyElements = 3; MyGlobalElements = new int[NumMyTotalElements]; MyGlobalElements[0] = 0; MyGlobalElements[1] = 4; MyGlobalElements[2] = 3; MyGlobalElements[3] = 1; MyGlobalElements[4] = 5; break; case 1: NumMyElements = 3; NumMyExternalElements = 2; NumMyTotalElements = NumMyElements + NumMyExternalElements; FE_NumMyElements = 3; MyGlobalElements = new int[NumMyTotalElements]; MyGlobalElements[0] = 1; MyGlobalElements[1] = 2; MyGlobalElements[2] = 5; MyGlobalElements[3] = 0; MyGlobalElements[4] = 4; break; } // build Map corresponding to update Epetra_Map Map(-1,NumMyElements,MyGlobalElements,0,Comm); // vector containing coordinates BEFORE exchanging external nodes Epetra_Vector CoordX_noExt(Map); Epetra_Vector CoordY_noExt(Map); switch( MyPID ) { case 0: T.Shape(3,FE_NumMyElements); // fill x-coordinates CoordX_noExt[0] = 0.0; CoordX_noExt[1] = 1.0; CoordX_noExt[2] = 0.0; // fill y-coordinates CoordY_noExt[0] = 0.0; CoordY_noExt[1] = 1.0; CoordY_noExt[2] = 1.0; // fill connectivity T(0,0) = 0; T(0,1) = 4; T(0,2) = 3; T(1,0) = 0; T(1,1) = 1; T(1,2) = 4; T(2,0) = 4; T(2,1) = 1; T(2,2) = 5; break; case 1: T.Shape(3,FE_NumMyElements); // fill x-coordinates CoordX_noExt[0] = 1.0; CoordX_noExt[1] = 2.0; CoordX_noExt[2] = 2.0; // fill y-coordinates CoordY_noExt[0] = 0.0; CoordY_noExt[1] = 0.0; CoordY_noExt[2] = 1.0; // fill connectivity T(0,0) = 0; T(0,1) = 1; T(0,2) = 4; T(1,0) = 1; T(1,1) = 5; T(1,2) = 4; T(2,0) = 1; T(2,1) = 2; T(2,2) = 5; break; } // - - - - - - - - - - - - - - - - - - - - // // E X T E R N A L N O D E S S E T U P // // - - - - - - - - - - - - - - - - - - - - // // build target map to exchange the valus of external nodes Epetra_Map TargetMap(-1,NumMyTotalElements, MyGlobalElements, 0, Comm); // !@# rename Map -> SourceMap ????? Epetra_Import Importer(TargetMap,Map); Epetra_Vector CoordX(TargetMap); Epetra_Vector CoordY(TargetMap); CoordX.Import(CoordX_noExt,Importer,Insert); CoordY.Import(CoordY_noExt,Importer,Insert); // now CoordX_noExt and CoordY_noExt are no longer required // NOTE: better to construct CoordX and CoordY as MultiVector // - - - - - - - - - - - - // // M A T R I X S E T U P // // - - - - - - - - - - - - // // build the CRS matrix corresponding to the grid // some vectors are allocated const int MaxNnzRow = 5; Epetra_CrsMatrix A(Copy,Map,MaxNnzRow); int Element, MyRow, GlobalRow, GlobalCol, i, j, k; Epetra_IntSerialDenseMatrix Struct; // temp to create the matrix connectivity Struct.Shape(NumMyElements,MaxNnzRow); for( i=0 ; i<NumMyElements ; ++i ) for( j=0 ; j<MaxNnzRow ; ++j ) Struct(i,j) = -1; // cycle over all the finite elements for( Element=0 ; Element<FE_NumMyElements ; ++Element ) { // cycle over each row for( i=0 ; i<3 ; ++i ) { // get the global and local number of this row GlobalRow = T(Element,i); MyRow = A.LRID(GlobalRow); if( MyRow != -1 ) { // only rows stored on this proc // cycle over the columns for( j=0 ; j<3 ; ++j ) { // get the global number only of this column GlobalCol = T(Element,j); // look if GlobalCol was already put in Struct for( k=0 ; k<MaxNnzRow ; ++k ) { if( Struct(MyRow,k) == GlobalCol || Struct(MyRow,k) == -1 ) break; } if( Struct(MyRow,k) == -1 ) { // new entry Struct(MyRow,k) = GlobalCol; } else if( Struct(MyRow,k) != GlobalCol ) { // maybe not enough space has beenn allocated cerr << "ERROR: not enough space for element " << GlobalRow << "," << GlobalCol << endl; return( 0 ); } } } } } int * Indices = new int [MaxNnzRow]; double * Values = new double [MaxNnzRow]; for( i=0 ; i<MaxNnzRow ; ++i ) Values[i] = 0.0; // now use Struct to fill build the matrix structure for( int Row=0 ; Row<NumMyElements ; ++Row ) { int Length = 0; for( int j=0 ; j<MaxNnzRow ; ++j ) { if( Struct(Row,j) == -1 ) break; Indices[Length] = Struct(Row,j); Length++; } GlobalRow = MyGlobalElements[Row]; A.InsertGlobalValues(GlobalRow, Length, Values, Indices); } // replace global numbering with local one in T for( int Element=0 ; Element<FE_NumMyElements ; ++Element ) { for( int i=0 ; i<3 ; ++i ) { int global = T(Element,i); int local = find(MyGlobalElements,NumMyTotalElements, global); if( global == -1 ) { cerr << "ERROR\n"; return( EXIT_FAILURE ); } T(Element,i) = local; } } // - - - - - - - - - - - - - - // // M A T R I X F I L L - I N // // - - - - - - - - - - - - - - // // room for the local matrix Epetra_SerialDenseMatrix Ke; Ke.Shape(3,3); // now fill the matrix for( int Element=0 ; Element<FE_NumMyElements ; ++Element ) { // variables used inside int GlobalRow; int MyRow; int GlobalCol; double x_triangle[3]; double y_triangle[3]; // get the spatial coordinate of each local node for( int i=0 ; i<3 ; ++i ) { MyRow = T(Element,i); y_triangle[i] = CoordX[MyRow]; x_triangle[i] = CoordY[MyRow]; } // compute the local matrix for Element compute_loc_matrix( x_triangle, y_triangle,Ke ); // insert it in the global one // cycle over each row for( int i=0 ; i<3 ; ++i ) { // get the global and local number of this row MyRow = T(Element,i); if( MyRow < NumMyElements ) { for( int j=0 ; j<3 ; ++j ) { // get global column number GlobalRow = MyGlobalElements[MyRow]; GlobalCol = MyGlobalElements[T(Element,j)]; A.SumIntoGlobalValues(GlobalRow,1,&(Ke(i,j)),&GlobalCol); } } } } A.FillComplete(); // - - - - - - - - - - - - - // // R H S & S O L U T I O N // // - - - - - - - - - - - - - // Epetra_Vector x(Map), b(Map); x.Random(); b.PutScalar(0.0); // Solution can be obtained using Aztecoo // free memory before leaving delete MyGlobalElements; delete Indices; delete Values; #ifdef HAVE_MPI MPI_Finalize(); #endif return( EXIT_SUCCESS ); } /* main */