EpetraExt Package Browser (Single Doxygen Collection) Development
example/matlab/cxx_main.cpp
Go to the documentation of this file.
00001 /*
00002 //@HEADER
00003 // ***********************************************************************
00004 //
00005 //     EpetraExt: Epetra Extended - Linear Algebra Services Package
00006 //                 Copyright (2011) Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 //@HEADER
00042 */
00043 
00044 #include "Epetra_ConfigDefs.h"
00045 
00046 #ifdef EPETRA_MPI
00047 #include "mpi.h"
00048 #include "Epetra_MpiComm.h"
00049 #else
00050 #include "Epetra_SerialComm.h"
00051 #endif
00052 
00053 #include "Epetra_Comm.h"
00054 #include "Epetra_Map.h"
00055 #include "Epetra_BlockMap.h"
00056 #include "Epetra_MultiVector.h"
00057 #include "Epetra_Vector.h"
00058 #include "Epetra_SerialDenseMatrix.h"
00059 #include "Epetra_SerialDenseVector.h"
00060 #include "Epetra_IntSerialDenseMatrix.h"
00061 #include "Epetra_IntSerialDenseVector.h"
00062 #include "Epetra_DataAccess.h"
00063 #include "Epetra_CrsMatrix.h"
00064 
00065 #include "EpetraExt_MatlabEngine.h" // contains the EpetraExt_MatlabEngine class
00066 
00067 int main(int argc, char *argv[]) {
00068 
00069 // standard Epetra MPI/Serial Comm startup  
00070 #ifdef EPETRA_MPI
00071   MPI_Init(&argc,&argv);
00072   Epetra_MpiComm comm (MPI_COMM_WORLD);
00073 #else
00074   Epetra_SerialComm comm;
00075 #endif
00076   
00077   int MyPID = comm.MyPID();
00078   int ierr = 0;
00079   bool verbose = (0 == MyPID);
00080   bool reportErrors = (0 == MyPID);
00081   // setup MatlabEngine
00082   if (verbose) cout << "going to startup a matlab process...\n";
00083   EpetraExt::EpetraExt_MatlabEngine engine (comm);
00084   if (verbose) cout << "matlab started\n";
00085   
00086   // setup an array of doubles to be used for the examples
00087   int M = 20;
00088   int numGlobalElements = M * comm.NumProc();
00089   int N = 3;
00090   int numMyEntries = M * N;
00091   double* A = new double[numMyEntries];
00092   double* Aptr = A;
00093   int startValue = numMyEntries * MyPID;
00094 
00095   for(int col=0; col < N; col++) {
00096   for(int row=0; row < M; row++) {
00097           *Aptr++ = startValue++;
00098       }
00099   }
00100 
00101   // setup an array of ints to be used for the examples
00102   int* intA = new int[numMyEntries];
00103   int* intAptr = intA;
00104   int intStartValue = numMyEntries * MyPID;
00105   for(int i=0; i < M*N; i++) {
00106       *intAptr++ = intStartValue++;
00107   }
00108   
00109   // construct a map to be used by distributed objects
00110   Epetra_Map map (numGlobalElements, 0, comm);
00111   
00112   // CrsMatrix example
00113   // constructs a globally distributed CrsMatrix and then puts it into Matlab
00114   if (verbose) cout << " constructing CrsMatrix...\n";
00115   Epetra_CrsMatrix crsMatrix (Copy, map, N);
00116   int* indices = new int[N];
00117   for (int col=0; col < N; col++) {
00118     indices[col] = col;   
00119   }
00120   
00121   double value = startValue;
00122   double* values = new double[numMyEntries];
00123   int minMyGID = map.MinMyGID();
00124   for (int row=0; row < M; row++) {
00125     for (int col=0; col < N; col++) {
00126       values[col] = value++;
00127     }
00128       
00129     crsMatrix.InsertGlobalValues(minMyGID + row, N, values, indices);
00130   }
00131   
00132   crsMatrix.FillComplete();
00133   if (verbose) cout << " CrsMatrix constructed\n";
00134   if (verbose) cout << " putting CrsMatrix into Matlab as CRSM\n";
00135   ierr = engine.PutRowMatrix(crsMatrix, "CRSM", false);
00136   if (ierr) {
00137     if (reportErrors) cout << "There was an error in engine.PutRowMatrix(crsMatrix, \"CRSM\", false): " << ierr << endl;
00138   }
00139   
00140   // BlockMap example
00141   // puts a map into Matlab
00142   if (verbose) cout << " putting Map into Matlab as MAP\n";
00143   ierr = engine.PutBlockMap(map, "MAP", false);
00144   if (ierr) {
00145     if (reportErrors) cout << "There was an error in engine.PutBlockMap(map, \"MAP\", false);: " << ierr << endl;
00146   }
00147   
00148   // MultiVector example
00149   // constructs a globally distributed MultiVector and then puts it into Matlab
00150   if (verbose) cout << " constructing MultiVector...\n";
00151   Epetra_MultiVector multiVector (Copy, map, A, M, N);
00152   if (verbose) cout << " MultiVector constructed\n";
00153   if (verbose) cout << " putting MultiVector into Matlab as MV\n";
00154   ierr = engine.PutMultiVector(multiVector, "MV");
00155   if (ierr) {
00156     if (reportErrors) cout << "There was an error in engine.PutMultiVector(multiVector, \"MV\"): " << ierr << endl;
00157   }
00158   
00159   // SerialDenseMatrix example
00160   // constructs a SerialDenseMatrix on every PE
00161   if (verbose) cout << " constructing a SerialDenseMatrix...\n";
00162   Epetra_SerialDenseMatrix sdMatrix (Copy, A, M, M, N);
00163   if (verbose) cout << " SerialDenseMatrix constructed\n";
00164   if (verbose) cout << " putting SerialDenseMatrix from PE0 into Matlab as SDM_PE0\n";
00165   // since the third parameter is left out, the SerialDenseMatrix from PE0 is used by default
00166   ierr = engine.PutSerialDenseMatrix(sdMatrix, "SDM_PE0");
00167   if (ierr) {
00168     if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdMatrix, \"SDM_PE0\"): " << ierr << endl;
00169   }
00170   if (comm.NumProc() > 1) {
00171     if (verbose) cout << " putting SerialDenseMatrix from PE1 into Matlab as SDM_PE1\n";
00172     // specifying 1 as the third parameter will put the SerialDenseMatrix from PE1 into Matlab
00173     ierr = engine.PutSerialDenseMatrix(sdMatrix, "SDM_PE1", 1);
00174     if (ierr) {
00175       if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdMatrix, \"SDM_PE1\", 1): " << ierr << endl;
00176     }
00177   }
00178   
00179 
00180   // SerialDenseVector example
00181   // constructs a SerialDenseVector on every PE
00182   if (verbose) cout << " constructing a SerialDenseVector...\n";
00183   Epetra_SerialDenseVector sdVector (Copy, A, M);
00184   if (verbose) cout << " SerialDenseVector constructed\n";
00185   // since the third parameter is left out, the SerialDenseMatrix from PE0 is used by default
00186   if (verbose) cout << " putting SerialDenseVector from PE0 into Matlab as SDV_PE0\n";
00187   ierr = engine.PutSerialDenseMatrix(sdVector, "SDV_PE0");
00188   if (ierr) {
00189     if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdVector, \"SDV_PE0\"): " << ierr << endl;
00190   }
00191   if (comm.NumProc() > 1) {
00192     if (verbose) cout << " putting SerialDenseVector from PE1 into Matlab as SDV_PE1\n";
00193     // specifying 1 as the third parameter will put the SerialDenseVector from PE1 into Matlab
00194     ierr = engine.PutSerialDenseMatrix(sdVector, "SDV_PE1", 1);
00195     if (ierr) {
00196       if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdMatrix, \"SDV_PE1\", 1): " << ierr << endl;
00197     }
00198   }
00199 
00200   // IntSerialDenseMatrix example
00201   // constructs a IntSerialDenseMatrix on every PE
00202   if (verbose) cout << " constructing a IntSerialDenseMatrix...\n";
00203   Epetra_IntSerialDenseMatrix isdMatrix (Copy, intA, M, M, N);
00204   if (verbose) cout << " IntSerialDenseMatrix constructed\n";
00205   // since the third parameter is left out, the IntSerialDenseMatrix from PE0 is used by default
00206   if (verbose) cout << " putting IntSerialDenseMatrix from PE0 into Matlab as ISDM_PE0\n";
00207   ierr = engine.PutIntSerialDenseMatrix(isdMatrix, "ISDM_PE0");
00208   if (ierr) {
00209     if (reportErrors) cout << "There was an error in engine.PutIntSerialDenseMatrix(isdMatrix, \"ISDM_PE0\"): " << ierr << endl;
00210   }
00211   if (comm.NumProc() > 1) {
00212     if (verbose) cout << " putting IntSerialDenseMatrix from PE1 into Matlab as ISDM_PE1\n";
00213     // specifying 1 as the third parameter will put the IntSerialDenseMatrix from PE1 into Matlab
00214     ierr = engine.PutIntSerialDenseMatrix(isdMatrix, "ISDM_PE1", 1);
00215     if (ierr) {
00216       if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(isdMatrix, \"ISDM_PE1\", 1): " << ierr << endl;
00217     }
00218   }
00219 
00220 
00221   // IntSerialDenseVector example
00222   // constructs a IntSerialDenseVector on every PE
00223   if (verbose) cout << " constructing a IntSerialDenseVector...\n";
00224   Epetra_IntSerialDenseVector isdVector (Copy, intA, M);
00225   if (verbose) cout << " IntSerialDenseVector constructed\n";
00226   // since the third parameter is left out, the IntSerialDenseVector from PE0 is used by default
00227   if (verbose) cout << " putting IntSerialDenseVector from PE0 into Matlab as ISDV_PE0\n";
00228   ierr = engine.PutIntSerialDenseMatrix(isdVector, "ISDV_PE0");
00229   if (ierr) {
00230     if (reportErrors) cout << "There was an error in engine.PutIntSerialDenseMatrix(isdVector, \"ISDV_PE0\"): " << ierr << endl;
00231   }
00232   if (comm.NumProc() > 1) {
00233     if (verbose) cout << " putting IntSerialDenseVector from PE1 into Matlab as ISDV_PE1\n";
00234     // specifying 1 as the third parameter will put the IntSerialDenseVector from PE1 into Matlab
00235     ierr = engine.PutIntSerialDenseMatrix(isdVector, "ISDV_PE1", 1);
00236     if (ierr) {
00237       if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(isdVector, \"ISDV_PE1\", 1): " << ierr << endl;
00238     }
00239   }
00240   
00241   // entering a while loop on PE0 will keep the Matlab workspace alive
00242   /*
00243   if (MyPID == 0)
00244   while(1) {
00245     // do nothing
00246   }
00247   */
00248 
00249   const int bufSize = 200;
00250   char s [bufSize];
00251   const int matlabBufferSize = 1024 * 16;
00252   char matlabBuffer [matlabBufferSize];
00253   
00254   // send some commands to Matlab and output the result to stdout
00255   engine.EvalString("whos", matlabBuffer, matlabBufferSize);
00256   if (verbose) cout << matlabBuffer << endl;
00257   engine.EvalString("SDV_PE0", matlabBuffer, matlabBufferSize);
00258   if (verbose) cout << matlabBuffer << endl;
00259   if (comm.NumProc() > 1) {
00260     engine.EvalString("SDV_PE1", matlabBuffer, matlabBufferSize);
00261     if (verbose) cout << matlabBuffer << endl;
00262   }
00263   
00264   // the following allows user interaction with Matlab
00265   if (MyPID == 0)
00266   while(1) {
00267       // Prompt the user and get a string
00268       printf(">> ");
00269       if (fgets(s, bufSize, stdin) == NULL) {
00270           printf("Bye\n");
00271           break ;
00272       }
00273       printf ("command :%s:\n", s) ;
00274       
00275       // send the command to MATLAB
00276       // output goes to stdout
00277       ierr = engine.EvalString(s, matlabBuffer, matlabBufferSize);
00278       if (ierr != 0) {
00279           printf("there was an error: %d", ierr);
00280       ierr = 0;
00281       }
00282       else {
00283           printf("Matlab Output:\n%s", matlabBuffer);
00284       }
00285   }
00286   
00287   if (verbose) cout << endl << " all done\n";
00288 
00289 // standard finalizer for Epetra MPI Comms
00290 #ifdef EPETRA_MPI
00291   MPI_Finalize();
00292 #endif
00293 
00294   // we need to delete engine because the MatlabEngine finalizer shuts down the Matlab process associated with this example
00295   // if we don't delete the Matlab engine, then this example application will not shut down properly
00296   delete &engine;
00297   return(0);
00298 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines