test/ImportExport/cxx_main.cpp

Go to the documentation of this file.
00001 //@HEADER
00002 // ************************************************************************
00003 // 
00004 //               Epetra: Linear Algebra Services Package 
00005 //                 Copyright (2001) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ************************************************************************
00027 //@HEADER
00028 
00029 #include "Epetra_Map.h"
00030 #include "Epetra_Time.h"
00031 #include "Epetra_CrsMatrix.h"
00032 #include "Epetra_Vector.h"
00033 #include "Epetra_IntVector.h"
00034 #include "Epetra_Import.h"
00035 #include "Epetra_Export.h"
00036 #include "Epetra_OffsetIndex.h"
00037 #ifdef EPETRA_MPI
00038 #include "Epetra_MpiComm.h"
00039 #include "mpi.h"
00040 #else
00041 #include "Epetra_SerialComm.h"
00042 #endif
00043 #ifndef __cplusplus
00044 #define __cplusplus
00045 #endif
00046 #include "../epetra_test_err.h"
00047 #include "Epetra_Version.h"
00048 
00049 int main(int argc, char *argv[])
00050 {
00051   int ierr = 0, i, j, forierr = 0;
00052 
00053 #ifdef EPETRA_MPI
00054   // Initialize MPI
00055   MPI_Init(&argc,&argv);
00056   Epetra_MpiComm Comm( MPI_COMM_WORLD );
00057 #else
00058   Epetra_SerialComm Comm;
00059 #endif
00060 
00061   bool verbose = false;
00062 
00063   // Check if we should print results to standard out
00064   if (argc>1) if (argv[1][0]=='-' && argv[1][1]=='v') verbose = true;
00065 
00066 
00067 
00068 
00069   //char tmp;
00070   //if (Comm.MyPID()==0) cout << "Press any key to continue..."<< endl;
00071   //if (Comm.MyPID()==0) cin >> tmp;
00072   //Comm.Barrier();
00073 
00074   Comm.SetTracebackMode(0); // This should shut down any error traceback reporting
00075   int MyPID = Comm.MyPID();
00076   int NumProc = Comm.NumProc();
00077 
00078   if (verbose && MyPID==0)
00079     cout << Epetra_Version() << endl << endl;
00080 
00081   if (verbose) cout << "Processor "<<MyPID<<" of "<< NumProc
00082               << " is alive."<<endl;
00083 
00084   // Redefine verbose to only print on PE 0
00085   if (verbose && Comm.MyPID()!=0) verbose = false;
00086 
00087   int NumMyEquations = 20;
00088   int NumGlobalEquations = NumMyEquations*NumProc+EPETRA_MIN(NumProc,3);
00089   if (MyPID < 3) NumMyEquations++;
00090   // Construct a Source Map that puts approximately the same Number of equations on each processor in 
00091   // uniform global ordering
00092 
00093   Epetra_Map SourceMap(NumGlobalEquations, NumMyEquations, 0, Comm);
00094   
00095   // Get update list and number of local equations from newly created Map
00096   int NumMyElements = SourceMap.NumMyElements();
00097   int * SourceMyGlobalElements = new int[NumMyElements];
00098   SourceMap.MyGlobalElements(SourceMyGlobalElements);
00099 
00100   // Construct a Target Map that will contain:
00101   //  some unchanged elements (relative to the soure map),
00102   //  some permuted elements
00103   //  some off-processor elements
00104   Epetra_Vector RandVec(SourceMap);
00105   RandVec.Random(); // This creates a vector of random numbers between negative one and one.
00106 
00107   int *TargetMyGlobalElements = new int[NumMyElements];
00108 
00109   int MinGID = SourceMap.MinMyGID();
00110   for (i=0; i< NumMyEquations/2; i++) TargetMyGlobalElements[i] = i + MinGID; // Half will be the same...
00111   for (i=NumMyEquations/2; i<NumMyEquations; i++) {
00112     int index = abs((int)(((double) (NumGlobalEquations-1) ) * RandVec[i]));
00113     TargetMyGlobalElements[i] = EPETRA_MIN(NumGlobalEquations-1,EPETRA_MAX(0,index));
00114   }
00115 
00116   int NumSameIDs = 0;
00117   int NumPermutedIDs = 0;
00118   int NumRemoteIDs = 0;
00119   bool StillContiguous = true;
00120   for (i=0; i < NumMyEquations; i++) {
00121     if (SourceMyGlobalElements[i]==TargetMyGlobalElements[i] && StillContiguous)
00122       NumSameIDs++;
00123     else if (SourceMap.MyGID(TargetMyGlobalElements[i])) {
00124       StillContiguous = false;
00125       NumPermutedIDs++;
00126     }
00127     else {
00128       StillContiguous = false;
00129       NumRemoteIDs++;
00130     }
00131   }
00132   EPETRA_TEST_ERR(!(NumMyEquations==NumSameIDs+NumPermutedIDs+NumRemoteIDs),ierr);
00133 
00134   Epetra_Map TargetMap(-1, NumMyElements, TargetMyGlobalElements, 0, Comm);
00135 
00136   // Create a multivector whose elements are GlobalID * (column number +1)
00137 
00138   int NumVectors = 3;
00139   Epetra_MultiVector SourceMultiVector(SourceMap, NumVectors);
00140   for (j=0; j < NumVectors; j++)
00141     for (i=0; i < NumMyElements; i++)
00142       SourceMultiVector[j][i] = (double) SourceMyGlobalElements[i]*(j+1);
00143 
00144   // Create a target multivector that we will fill using an Import
00145 
00146   Epetra_MultiVector TargetMultiVector(TargetMap, NumVectors);
00147 
00148   Epetra_Import Importer(TargetMap, SourceMap);
00149 
00150   EPETRA_TEST_ERR(!(TargetMultiVector.Import(SourceMultiVector, Importer, Insert)==0),ierr);
00151 
00152   // Test Target against expected values
00153   forierr = 0;
00154   for (j=0; j < NumVectors; j++)
00155     for (i=0; i < NumMyElements; i++) {
00156       if (TargetMultiVector[j][i]!= (double) TargetMyGlobalElements[i]*(j+1))
00157   cout << "TargetMultiVector["<<i<<"]["<<j<<"] = " << TargetMultiVector[j][i] 
00158        <<  "  TargetMyGlobalElements[i]*(j+1) = " <<  TargetMyGlobalElements[i]*(j+1) << endl;
00159       forierr += !(TargetMultiVector[j][i]== (double) TargetMyGlobalElements[i]*(j+1));
00160     }
00161   EPETRA_TEST_ERR(forierr,ierr);
00162 
00163   if (verbose) cout << "MultiVector Import using Importer Check OK" << endl << endl;
00164 
00165 
00167 
00168   // Now use Importer to do an export
00169 
00170   Epetra_Vector TargetVector(SourceMap);
00171   Epetra_Vector ExpectedTarget(SourceMap);
00172   Epetra_Vector SourceVector(TargetMap);
00173 
00174   NumSameIDs = Importer.NumSameIDs();
00175   int NumPermuteIDs = Importer.NumPermuteIDs();
00176   int NumExportIDs = Importer.NumExportIDs();
00177   int *PermuteFromLIDs = Importer.PermuteFromLIDs();
00178   int *ExportLIDs = Importer.ExportLIDs();
00179   int *ExportPIDs = Importer.ExportPIDs();
00180 
00181   for (i=0; i < NumSameIDs; i++) ExpectedTarget[i] = (double) (MyPID+1);
00182   for (i=0; i < NumPermuteIDs; i++) ExpectedTarget[PermuteFromLIDs[i]] = 
00183               (double) (MyPID+1);
00184   for (i=0; i < NumExportIDs; i++) ExpectedTarget[ExportLIDs[i]] += 
00185              (double) (ExportPIDs[i]+1);
00186 
00187   for (i=0; i < NumMyElements; i++) SourceVector[i] =  (double) (MyPID+1);
00188 
00189   EPETRA_TEST_ERR(!(TargetVector.Export(SourceVector, Importer, Add)==0),ierr);
00190 
00191   forierr = 0;
00192   for (i=0; i < NumMyElements; i++) {
00193     if (TargetVector[i]!= ExpectedTarget[i])
00194       cout <<  "     TargetVector["<<i<<"] = " << TargetVector[i] 
00195      <<  "   ExpectedTarget["<<i<<"] = " <<  ExpectedTarget[i] << " on PE " << MyPID << endl;
00196     forierr += !(TargetVector[i]== ExpectedTarget[i]);
00197   }
00198   EPETRA_TEST_ERR(forierr,ierr);
00199 
00200   if (verbose) cout << "Vector Export using Importer Check OK" << endl << endl;
00201 
00202 
00203 
00205   //  Build a tridiagonal system two ways:
00206   //  1) From "standard" matrix view where equations are uniquely owned.
00207   //  2) From 1D PDE view where nodes (equations) between processors are shared and partial contributions are done
00208   //     in parallel, then merged together at the end of the construction process.
00209   //
00211 
00212 
00213 
00214   // Construct a Standard Map that puts approximately the same number of equations on each processor in 
00215   // uniform global ordering
00216 
00217   Epetra_Map StandardMap(NumGlobalEquations, NumMyEquations, 0, Comm);
00218   
00219   // Get update list and number of local equations from newly created Map
00220   NumMyElements = StandardMap.NumMyElements();
00221   int * StandardMyGlobalElements = new int[NumMyElements];
00222   StandardMap.MyGlobalElements(StandardMyGlobalElements);
00223 
00224 
00225   // Create a standard Epetra_CrsGraph
00226 
00227   Epetra_CrsGraph StandardGraph(Copy, StandardMap, 3);
00228   EPETRA_TEST_ERR(StandardGraph.IndicesAreGlobal(),ierr);
00229   EPETRA_TEST_ERR(StandardGraph.IndicesAreLocal(),ierr);
00230   
00231   // Add  rows one-at-a-time
00232   // Need some vectors to help
00233   // Off diagonal Values will always be -1
00234 
00235 
00236   int *Indices = new int[2];
00237   int NumEntries;
00238   
00239   forierr = 0;
00240   for (i=0; i<NumMyEquations; i++)
00241     {
00242     if (StandardMyGlobalElements[i]==0)
00243       {
00244   Indices[0] = 1;
00245   NumEntries = 1;
00246       }
00247     else if (StandardMyGlobalElements[i] == NumGlobalEquations-1)
00248       {
00249   Indices[0] = NumGlobalEquations-2;
00250   NumEntries = 1;
00251       }
00252     else
00253       {
00254   Indices[0] = StandardMyGlobalElements[i]-1;
00255   Indices[1] = StandardMyGlobalElements[i]+1;
00256   NumEntries = 2;
00257       }
00258     forierr += !(StandardGraph.InsertGlobalIndices(StandardMyGlobalElements[i], NumEntries, Indices)==0);
00259     forierr += !(StandardGraph.InsertGlobalIndices(StandardMyGlobalElements[i], 1, StandardMyGlobalElements+i)==0); // Put in the diagonal entry
00260     }
00261   EPETRA_TEST_ERR(forierr,ierr);
00262 
00263   // Finish up
00264   EPETRA_TEST_ERR(!(StandardGraph.IndicesAreGlobal()),ierr);
00265   EPETRA_TEST_ERR(!(StandardGraph.FillComplete()==0),ierr);
00266   EPETRA_TEST_ERR(!(StandardGraph.IndicesAreLocal()),ierr);
00267   EPETRA_TEST_ERR(StandardGraph.StorageOptimized(),ierr);
00268   StandardGraph.OptimizeStorage();
00269   EPETRA_TEST_ERR(!(StandardGraph.StorageOptimized()),ierr);
00270   EPETRA_TEST_ERR(StandardGraph.UpperTriangular(),ierr);
00271   EPETRA_TEST_ERR(StandardGraph.LowerTriangular(),ierr);
00272 
00273   // Create Epetra_CrsMatrix using the just-built graph
00274 
00275   Epetra_CrsMatrix StandardMatrix(Copy, StandardGraph);
00276   EPETRA_TEST_ERR(StandardMatrix.IndicesAreGlobal(),ierr);
00277   EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr);
00278   
00279   // Add  rows one-at-a-time
00280   // Need some vectors to help
00281   // Off diagonal Values will always be -1
00282 
00283 
00284   double *Values = new double[2];
00285   Values[0] = -1.0; Values[1] = -1.0;
00286   double two = 2.0;
00287   
00288   forierr = 0;
00289   for (i=0; i<NumMyEquations; i++)
00290     {
00291     if (StandardMyGlobalElements[i]==0)
00292       {
00293   Indices[0] = 1;
00294   NumEntries = 1;
00295       }
00296     else if (StandardMyGlobalElements[i] == NumGlobalEquations-1)
00297       {
00298   Indices[0] = NumGlobalEquations-2;
00299   NumEntries = 1;
00300       }
00301     else
00302       {
00303   Indices[0] = StandardMyGlobalElements[i]-1;
00304   Indices[1] = StandardMyGlobalElements[i]+1;
00305   NumEntries = 2;
00306       }
00307     forierr += !(StandardMatrix.ReplaceGlobalValues(StandardMyGlobalElements[i], NumEntries, Values, Indices)==0);
00308     // Put in the diagonal entry
00309     forierr += !(StandardMatrix.ReplaceGlobalValues(StandardMyGlobalElements[i], 1, &two, StandardMyGlobalElements+i)==0); 
00310     }
00311   EPETRA_TEST_ERR(forierr,ierr);
00312 
00313   // Finish up
00314   EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr);
00315   EPETRA_TEST_ERR(!(StandardMatrix.FillComplete()==0),ierr);
00316   EPETRA_TEST_ERR(!(StandardMatrix.IndicesAreLocal()),ierr);
00317   EPETRA_TEST_ERR((StandardMatrix.StorageOptimized()),ierr);
00318   EPETRA_TEST_ERR((StandardMatrix.OptimizeStorage()),ierr);
00319   EPETRA_TEST_ERR(!(StandardMatrix.StorageOptimized()),ierr);
00320   EPETRA_TEST_ERR(StandardMatrix.UpperTriangular(),ierr);
00321   EPETRA_TEST_ERR(StandardMatrix.LowerTriangular(),ierr);
00322 
00323   // Construct an Overlapped Map of StandardMap that include the endpoints from two neighboring processors.
00324 
00325   int OverlapNumMyElements;
00326   int OverlapMinMyGID;
00327 
00328   OverlapNumMyElements = NumMyElements + 1;
00329   if (MyPID==0) OverlapNumMyElements--;
00330 
00331   if (MyPID==0) OverlapMinMyGID = StandardMap.MinMyGID();
00332   else OverlapMinMyGID = StandardMap.MinMyGID()-1;
00333 
00334   int * OverlapMyGlobalElements = new int[OverlapNumMyElements];
00335 
00336   for (i=0; i< OverlapNumMyElements; i++) OverlapMyGlobalElements[i] = OverlapMinMyGID + i;
00337 
00338   Epetra_Map OverlapMap(-1, OverlapNumMyElements, OverlapMyGlobalElements, 0, Comm);
00339 
00340   // Create the Overlap Epetra_Matrix
00341 
00342   Epetra_CrsMatrix OverlapMatrix(Copy, OverlapMap, 4);
00343   EPETRA_TEST_ERR(OverlapMatrix.IndicesAreGlobal(),ierr);
00344   EPETRA_TEST_ERR(OverlapMatrix.IndicesAreLocal(),ierr);
00345   
00346   // Add  matrix element one cell at a time.
00347   // Each cell does an incoming and outgoing flux calculation
00348 
00349 
00350   double pos_one = 1.0;
00351   double neg_one = -1.0;
00352 
00353   forierr = 0;
00354   for (i=0; i<OverlapNumMyElements; i++)
00355     {
00356       int node_left = OverlapMyGlobalElements[i]-1;
00357       int node_center = node_left + 1;
00358       int node_right = node_left + 2;
00359       if (i>0) {
00360   if (node_left>-1)
00361     forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &neg_one, &node_left)==0);
00362   forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0);
00363       }
00364       if (i<OverlapNumMyElements-1) {
00365   forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0);
00366   if (node_right<NumGlobalEquations) 
00367     forierr += !(OverlapMatrix.InsertGlobalValues(node_center, 1, &neg_one, &node_right)==0);
00368       }
00369     }
00370   EPETRA_TEST_ERR(forierr,ierr);
00371 
00372   // Handle endpoints
00373   if (MyPID==0) {
00374     int node_center = 0;
00375     EPETRA_TEST_ERR(!(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0),ierr);
00376   }
00377   if (MyPID==NumProc-1) {
00378     int node_center = OverlapMyGlobalElements[OverlapNumMyElements-1];
00379     EPETRA_TEST_ERR(!(OverlapMatrix.InsertGlobalValues(node_center, 1, &pos_one, &node_center)==0),ierr);
00380   }
00381     
00382   EPETRA_TEST_ERR(!(OverlapMatrix.FillComplete()==0),ierr);
00383 
00384   // Make a gathered matrix from OverlapMatrix.  It should be identical to StandardMatrix
00385 
00386   Epetra_CrsMatrix GatheredMatrix(Copy, StandardGraph);
00387   Epetra_Export Exporter(OverlapMap, StandardMap);
00388   EPETRA_TEST_ERR(!(GatheredMatrix.Export(OverlapMatrix, Exporter, Add)==0),ierr);
00389   EPETRA_TEST_ERR(!(GatheredMatrix.FillComplete()==0),ierr);
00390 
00391   // Check if entries of StandardMatrix and GatheredMatrix are identical
00392 
00393   int StandardNumEntries, GatheredNumEntries;
00394   int * StandardIndices, * GatheredIndices;
00395   double * StandardValues, * GatheredValues;
00396 
00397   int StandardNumMyNonzeros = StandardMatrix.NumMyNonzeros();
00398   int GatheredNumMyNonzeros = GatheredMatrix.NumMyNonzeros();
00399   EPETRA_TEST_ERR(!(StandardNumMyNonzeros==GatheredNumMyNonzeros),ierr);
00400 
00401   int StandardNumMyRows = StandardMatrix.NumMyRows();
00402   int GatheredNumMyRows = GatheredMatrix.NumMyRows();
00403   EPETRA_TEST_ERR(!(StandardNumMyRows==GatheredNumMyRows),ierr);
00404 
00405   forierr = 0;
00406   for (i=0; i< StandardNumMyRows; i++)
00407     {
00408       forierr += !(StandardMatrix.ExtractMyRowView(i, StandardNumEntries, StandardValues, StandardIndices)==0);
00409       forierr += !(GatheredMatrix.ExtractMyRowView(i, GatheredNumEntries, GatheredValues, GatheredIndices)==0);
00410       forierr += !(StandardNumEntries==GatheredNumEntries);
00411       for (j=0; j < StandardNumEntries; j++) {
00412   //if (StandardIndices[j]!=GatheredIndices[j])
00413   // cout << "MyPID = " << MyPID << " i = " << i << "   StandardIndices[" << j << "] = " << StandardIndices[j] 
00414   //      << "   GatheredIndices[" << j << "] = " << GatheredIndices[j] << endl;
00415   //if (StandardValues[j]!=GatheredValues[j])
00416   //cout << "MyPID = " << MyPID << " i = " << i << "    StandardValues[" << j << "] = " <<  StandardValues[j] 
00417   //     << "    GatheredValues[" << j << "] = " <<  GatheredValues[j] << endl;
00418   forierr += !(StandardIndices[j]==GatheredIndices[j]);
00419   forierr += !(StandardValues[j]==GatheredValues[j]);
00420       }
00421     }
00422   EPETRA_TEST_ERR(forierr,ierr);
00423 
00424   if (verbose) cout << "Matrix Export Check OK" << endl << endl;
00425 
00426   //Do Again with use of Epetra_OffsetIndex object for speed
00427   Epetra_OffsetIndex OffsetIndex( OverlapMatrix.Graph(), GatheredMatrix.Graph(), Exporter );
00428   EPETRA_TEST_ERR(!(GatheredMatrix.Export(OverlapMatrix, Exporter, Add)==0),ierr);
00429 
00430   if (verbose) cout << "Optimized Matrix Export Check OK" << endl << endl;
00431 
00432   bool passed;
00433   Epetra_IntVector v1(StandardMap); v1.PutValue(2);
00434   Epetra_IntVector v2(StandardMap); v2.PutValue(3);
00435 
00436   Epetra_Export identExporter(StandardMap,StandardMap); // Identity exporter
00437   EPETRA_TEST_ERR(!(v2.Export(v1, identExporter, Insert)==0),ierr);
00438   passed = (v2.MinValue()==2);
00439   EPETRA_TEST_ERR(!passed,ierr);
00440 
00441   v1.PutValue(1);
00442   Epetra_Import identImporter(StandardMap,StandardMap); // Identity importer
00443   EPETRA_TEST_ERR(!(v2.Import(v1, identExporter, Insert)==0),ierr);
00444   passed = passed && (v2.MaxValue()==1);
00445   EPETRA_TEST_ERR(!passed,ierr);
00446 
00447   if (verbose) {
00448     if (passed) cout << "Identity Import/Export Check OK" << endl << endl;
00449     else cout << "Identity Import/Export Check Failed" << endl << endl;
00450   }
00451 
00452   int NumSubMapElements = StandardMap.NumMyElements()/2;
00453   int SubStart = Comm.MyPID();
00454   NumSubMapElements = EPETRA_MIN(NumSubMapElements,StandardMap.NumMyElements()-SubStart);
00455   Epetra_Map SubMap(-1, NumSubMapElements, StandardMyGlobalElements+SubStart, 0, Comm);
00456 
00457   Epetra_IntVector v3(View, SubMap, SubMap.MyGlobalElements()); // Fill v3 with GID values for variety
00458   Epetra_Export subExporter(SubMap, StandardMap); // Export to a subset of indices of standard map
00459   EPETRA_TEST_ERR(!(v2.Export(v3,subExporter,Insert)==0),ierr);
00460 
00461   forierr = 0;
00462   for (i=0; i<SubMap.NumMyElements(); i++) {
00463     int i1 = StandardMap.LID(SubMap.GID(i));
00464     forierr += !(v3[i]==v2[i1]);
00465   }
00466   EPETRA_TEST_ERR(forierr,ierr);
00467 
00468   Epetra_Import subImporter(StandardMap, SubMap); // Import to a subset of indices of standard map
00469   EPETRA_TEST_ERR(!(v1.Import(v3,subImporter,Insert)==0),ierr);
00470 
00471   for (i=0; i<SubMap.NumMyElements(); i++) {
00472     int i1 = StandardMap.LID(SubMap.GID(i));
00473     forierr += !(v3[i]==v1[i1]);
00474   }
00475   EPETRA_TEST_ERR(forierr,ierr);
00476 
00477   if (verbose) {
00478     if (forierr==0) cout << "SubMap Import/Export Check OK" << endl << endl;
00479     else cout << "SubMap Import/Export Check Failed" << endl << endl;
00480   }
00481 
00482   // Release all objects
00483 
00484   delete [] SourceMyGlobalElements;
00485   delete [] TargetMyGlobalElements;
00486   delete [] OverlapMyGlobalElements;
00487   delete [] StandardMyGlobalElements;
00488 
00489   delete [] Values;
00490   delete [] Indices;
00491 
00492 #ifdef EPETRA_MPI
00493   MPI_Finalize() ;
00494 #endif
00495 
00496 /* end main
00497 */
00498 return ierr ;
00499 }

Generated on Thu Sep 18 12:37:56 2008 for Epetra Package Browser (Single Doxygen Collection) by doxygen 1.3.9.1