#include <EpetraExt_MatlabEngine.h>
Collaboration diagram for EpetraExt::EpetraExt_MatlabEngine:
Public Member Functions  
Constructors/destructors.  
EpetraExt_MatlabEngine (const Epetra_Comm &Comm)  
EpetraExt_MatlabEngine constructor which creates a MatlabEngine object with a connection to an instance of the application Matlab by starting a new Matlab process.  
~EpetraExt_MatlabEngine ()  
EpetraExt_MatlabEngine destructor which closes the connection to Matlab which causes the Matlab process to also exit.  
General Epetra to Matlab Access Methods  
int  EvalString (char *command, char *outputBuffer=NULL, int outputBufferSize=1) 
Sends a command to Matlab.  
Epetra to Matlab Data Transfer Methods  
int  PutMultiVector (const Epetra_MultiVector &A, const char *variableName) 
Puts a copy of the serial or distributed MultiVector into the Matlab workspace.  
int  PutRowMatrix (const Epetra_RowMatrix &A, const char *variableName, bool transA) 
Puts a copy of the serial or distributed RowMatrix into the Matlab workspace.  
int  PutCrsGraph (const Epetra_CrsGraph &A, const char *variableName, bool transA) 
not implemented yet  
int  PutSerialDenseMatrix (const Epetra_SerialDenseMatrix &A, const char *variableName, int proc=0) 
Puts a copy of the SerialDenseMatrix into the Matlab workspace.  
int  PutIntSerialDenseMatrix (const Epetra_IntSerialDenseMatrix &A, const char *variableName, int proc=0) 
Puts a copy of the IntSerialDenseMatrix into the Matlab workspace.  
int  PutBlockMap (const Epetra_BlockMap &blockMap, const char *variableName, bool transA) 
Puts a copy of the BlockMap or Map into the Matlab workspace.  
int  PutIntoMatlab (const char *variableName, mxArray *matlabA) 
Puts a mxArray into Matlab.  
Matlab to Epetra Data Transfer Methods  
int  GetMultiVector (const char *variableName, Epetra_MultiVector &A) 
Puts a Matlab variable into a MultiVector.  
int  GetSerialDenseMatrix (const char *variableName, Epetra_SerialDenseMatrix &A, int proc=0) 
Puts a Matlab variable into a SerialDenseMatrix on the specified PE.  
int  GetIntSerialDenseMatrix (const char *variableName, Epetra_IntSerialDenseMatrix &A, int proc=0) 
Puts a Matlab variable into a IntSerialDenseMatrix on the specified PE.  
int  GetCrsMatrix (const char *variableName, Epetra_CrsMatrix &A, bool getTrans) 
Puts a Matlab variable into a CrsMatrix.  
General Matlab to Epetra Access Methods  
int  GetmxArrayDimensions (mxArray *matlabA, bool &isSparse, int &numRows, int &numCols, int &numNonZeros) 
Get general information about the mxArray. For internal use but can be used by an advanced user.  
int  GetmxArray (const char *variableName, mxArray **matlabA) 
Get a mxArray from Matlab. For internal use but can be used by an advanced user. 
The EpetraExt_MatlabEngine class allows Epetra data objects to be exported to Matlab and then operated on within Matlab using Matlab commands.
When an EpetraExt_MatlabEngine object is constructed a new instance of the application Matlab is started for EpetraExt_MatlabEngine to communicate with. All communication between EpetraExt_MatlabEngine and Matlab occurs on the root node (0) only. For parallel environments all objects are collected onto the root node before being put into Matlab. Object data is put into a mxArray which is then sent to the Matlab process. All objects passed to Matlab are copied into the Matlab memory space. So at the point when Matlab receives its copy of the data there is two copies of the mxArray in memory, one in the Epetra application and one in Matlab. Since Matlab has its own memory space the mxArray in the Epetra application should be deleted in order to free up memory space. All methods in EpetraExt_MatlabEngine that put Epetra objects into Matlab delete the temporary mxArray as soon as it is put into Matlab. If a user desires to create his/her own mxArray's and then send them to Matlab the method PutIntoMatlab can be used. It is important to note that PutIntoMatlab does NOT delete the mxArray it is passed. When the EpetraExt_MatlabEngine deconstructor is called the instance of Matlab that was started during construction of the EpetraExt_MatlabEngine object exits.
Error Codes
Build Instructions
These instructions can be found in the file Trilinos/packages/epetraext/doc/matlab.README.
This document contains build instructions for the files located in epetraext/src/matlab See the normal Trilinos doxygen documentation for usage instructions and references For an example program see epetraext/example/matlab For questions/problems/comments contact Jason Cross at jcross@software.sandia.gov NOTES: MATLAB will refer to the root directory of a Matlab installation. These instructions assume you are familiar with building Trilinos with epetraext and only need instructions on how to enable building EpetrEext with Matlab support. 1. UNIXlike systems (Solaris, Linux, etc.  NOT CYGWIN) 1.a. Add the library path of the Matlab libraries using withlibdirs="LMATLAB/LIBLOCATIONS/ARCH". For Matlab version 7 (release 14) the location of the libraries is MATLAB/bin/ARCH where ARCH is your system architecture (sol2 for Solaris, etc). For Matlab versions below 7 the location of the libraries is MATLAB/extern/lib/ARCH. 1.b. Now add the Matlab headers path using withincdirs="I/MATLAB/extern/include" If you've done the previous steps properly you are now ready to build epetraext with src/matlab. To do so do a normal Trilinos build process but add the necessary withincdirs and withinclibs described in the previous steps. You will also need to specify enableepetraextmatlab. The configure script in epetraext will make sure that all necessary header files and libraries can be found by the compiler and linker. 1.c. You probably will have to add the Matlab libraries directory to your environmental variable LD_LIBRARY_PATH so that the Matlab shared libraries can be found at runtime. For bash you would do export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/MATLAB/LIBLOCATIONS/ARCH" and for tcsh setenv LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:/MATLAB/LIBLOCATIONS/ARCH" 2. CYGWIN (with gcc in MS Windows) 2.a. First you will need to generate lib*.a files from the Matlab dlls. On the cygwin command line move into MATLAB/extern/include 2.b. Run the following commands: dlltool def libeng.def dllname libeng.dll outputlib libeng.a dlltool def libmx.def dllname libmx.dll outputlib libmx.a Note that you must have write access to the MATLAB/extern/include directory for the above commands to work verbatim. If you do not have write access change the outputlib lib*.a to outputlib SOMEPATH/lib*.a where SOMEPATH is a directory where you have write access to. 2.c. Now move libeng.a and libmx.a to some directory which we will call MATLABLIBDIR and then add that directory path to the ./configure parameter withlibdirs="L/the/path/to/MATLABLIBDIR" Note that you only need to generate these lib*.a libraries whenever you install a new version of Matlab. 2.d. Now libeng.dll and libmx.dll must be in the Windows PATH environmental variable. This can either be specified using normal Windows environmental command tools or by using you cygwin shell such as bash to modify the PATH variable. The dlls are located in MATLAB/bin/win32 2.e. Now you must add the MATLAB include files directory to your ./configure parameters with the parameter withincdirs="I/MATLAB/extern/include" 2.f. If you've done the previous steps properly you are now ready to build epetraext with src/matlab. To do so do a normal Trilinos build process but add the necessary withincdirs and withinclibs described in the previous steps. You will also need to specify enableepetraextmatlab. The configure script in epetraext will make sure that all necessary header files and libraries can be found by the compiler and linker. 2.g. If your MATLABLIBDIR is a nonstandard library directory (not /lib, /usr/lib, etc) then you will need to add that directory's path to the environmental variable LD_LIBRARY_PATH so that the Matlab shared libraries can be found at runtime. See 1.c. for more specific shell examples.
Example Code
The following example code generates simple Epetra objects and then puts them into Matlab.
The point of this example is to illustrate the flow of calls when using EpetraExt_MatlabEngine. This example program can be found in the file Trilinos/packages/epetraext/example/matlab/cxx_main.cpp.
/*@HEADER // *********************************************************************** // // EpetraExt: Epetra Extended  Linear Algebra Services Package // Copyright (2001) Sandia Corporation // // Under terms of Contract DEAC0494AL85000, there is a nonexclusive // license for use of this work by or on behalf of the U.S. Government. // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 021111307 // USA // Questions? Contact Michael A. Heroux (maherou@sandia.gov) // // *********************************************************************** //@HEADER */ #include "Epetra_ConfigDefs.h" #ifdef EPETRA_MPI #include "mpi.h" #include "Epetra_MpiComm.h" #else #include "Epetra_SerialComm.h" #endif #include "Epetra_Comm.h" #include "Epetra_Map.h" #include "Epetra_BlockMap.h" #include "Epetra_MultiVector.h" #include "Epetra_Vector.h" #include "Epetra_SerialDenseMatrix.h" #include "Epetra_SerialDenseVector.h" #include "Epetra_IntSerialDenseMatrix.h" #include "Epetra_IntSerialDenseVector.h" #include "Epetra_DataAccess.h" #include "Epetra_CrsMatrix.h" #include "EpetraExt_MatlabEngine.h" // contains the EpetraExt_MatlabEngine class int main(int argc, char *argv[]) { // standard Epetra MPI/Serial Comm startup #ifdef EPETRA_MPI MPI_Init(&argc,&argv); Epetra_MpiComm comm (MPI_COMM_WORLD); #else Epetra_SerialComm comm; #endif int MyPID = comm.MyPID(); int ierr = 0; bool verbose = (0 == MyPID); bool reportErrors = (0 == MyPID); // setup MatlabEngine if (verbose) cout << "going to startup a matlab process...\n"; EpetraExt::EpetraExt_MatlabEngine engine (comm); if (verbose) cout << "matlab started\n"; // setup an array of doubles to be used for the examples int M = 20; int numGlobalElements = M * comm.NumProc(); int N = 3; int numMyEntries = M * N; double* A = new double[numMyEntries]; double* Aptr = A; int startValue = numMyEntries * MyPID; for(int col=0; col < N; col++) { for(int row=0; row < M; row++) { *Aptr++ = startValue++; } } // setup an array of ints to be used for the examples int* intA = new int[numMyEntries]; int* intAptr = intA; int intStartValue = numMyEntries * MyPID; for(int i=0; i < M*N; i++) { *intAptr++ = intStartValue++; } // construct a map to be used by distributed objects Epetra_Map map (numGlobalElements, 0, comm); // CrsMatrix example // constructs a globally distributed CrsMatrix and then puts it into Matlab if (verbose) cout << " constructing CrsMatrix...\n"; Epetra_CrsMatrix crsMatrix (Copy, map, N); int* indices = new int[N]; for (int col=0; col < N; col++) { indices[col] = col; } double value = startValue; double* values = new double[numMyEntries]; int minMyGID = map.MinMyGID(); for (int row=0; row < M; row++) { for (int col=0; col < N; col++) { values[col] = value++; } crsMatrix.InsertGlobalValues(minMyGID + row, N, values, indices); } crsMatrix.FillComplete(); if (verbose) cout << " CrsMatrix constructed\n"; if (verbose) cout << " putting CrsMatrix into Matlab as CRSM\n"; ierr = engine.PutRowMatrix(crsMatrix, "CRSM", false); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutRowMatrix(crsMatrix, \"CRSM\", false): " << ierr << endl; } // BlockMap example // puts a map into Matlab if (verbose) cout << " putting Map into Matlab as MAP\n"; ierr = engine.PutBlockMap(map, "MAP", false); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutBlockMap(map, \"MAP\", false);: " << ierr << endl; } // MultiVector example // constructs a globally distributed MultiVector and then puts it into Matlab if (verbose) cout << " constructing MultiVector...\n"; Epetra_MultiVector multiVector (Copy, map, A, M, N); if (verbose) cout << " MultiVector constructed\n"; if (verbose) cout << " putting MultiVector into Matlab as MV\n"; ierr = engine.PutMultiVector(multiVector, "MV"); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutMultiVector(multiVector, \"MV\"): " << ierr << endl; } // SerialDenseMatrix example // constructs a SerialDenseMatrix on every PE if (verbose) cout << " constructing a SerialDenseMatrix...\n"; Epetra_SerialDenseMatrix sdMatrix (Copy, A, M, M, N); if (verbose) cout << " SerialDenseMatrix constructed\n"; if (verbose) cout << " putting SerialDenseMatrix from PE0 into Matlab as SDM_PE0\n"; // since the third parameter is left out, the SerialDenseMatrix from PE0 is used by default ierr = engine.PutSerialDenseMatrix(sdMatrix, "SDM_PE0"); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdMatrix, \"SDM_PE0\"): " << ierr << endl; } if (comm.NumProc() > 1) { if (verbose) cout << " putting SerialDenseMatrix from PE1 into Matlab as SDM_PE1\n"; // specifying 1 as the third parameter will put the SerialDenseMatrix from PE1 into Matlab ierr = engine.PutSerialDenseMatrix(sdMatrix, "SDM_PE1", 1); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdMatrix, \"SDM_PE1\", 1): " << ierr << endl; } } // SerialDenseVector example // constructs a SerialDenseVector on every PE if (verbose) cout << " constructing a SerialDenseVector...\n"; Epetra_SerialDenseVector sdVector (Copy, A, M); if (verbose) cout << " SerialDenseVector constructed\n"; // since the third parameter is left out, the SerialDenseMatrix from PE0 is used by default if (verbose) cout << " putting SerialDenseVector from PE0 into Matlab as SDV_PE0\n"; ierr = engine.PutSerialDenseMatrix(sdVector, "SDV_PE0"); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdVector, \"SDV_PE0\"): " << ierr << endl; } if (comm.NumProc() > 1) { if (verbose) cout << " putting SerialDenseVector from PE1 into Matlab as SDV_PE1\n"; // specifying 1 as the third parameter will put the SerialDenseVector from PE1 into Matlab ierr = engine.PutSerialDenseMatrix(sdVector, "SDV_PE1", 1); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(sdMatrix, \"SDV_PE1\", 1): " << ierr << endl; } } // IntSerialDenseMatrix example // constructs a IntSerialDenseMatrix on every PE if (verbose) cout << " constructing a IntSerialDenseMatrix...\n"; Epetra_IntSerialDenseMatrix isdMatrix (Copy, intA, M, M, N); if (verbose) cout << " IntSerialDenseMatrix constructed\n"; // since the third parameter is left out, the IntSerialDenseMatrix from PE0 is used by default if (verbose) cout << " putting IntSerialDenseMatrix from PE0 into Matlab as ISDM_PE0\n"; ierr = engine.PutIntSerialDenseMatrix(isdMatrix, "ISDM_PE0"); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutIntSerialDenseMatrix(isdMatrix, \"ISDM_PE0\"): " << ierr << endl; } if (comm.NumProc() > 1) { if (verbose) cout << " putting IntSerialDenseMatrix from PE1 into Matlab as ISDM_PE1\n"; // specifying 1 as the third parameter will put the IntSerialDenseMatrix from PE1 into Matlab ierr = engine.PutIntSerialDenseMatrix(isdMatrix, "ISDM_PE1", 1); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(isdMatrix, \"ISDM_PE1\", 1): " << ierr << endl; } } // IntSerialDenseVector example // constructs a IntSerialDenseVector on every PE if (verbose) cout << " constructing a IntSerialDenseVector...\n"; Epetra_IntSerialDenseVector isdVector (Copy, intA, M); if (verbose) cout << " IntSerialDenseVector constructed\n"; // since the third parameter is left out, the IntSerialDenseVector from PE0 is used by default if (verbose) cout << " putting IntSerialDenseVector from PE0 into Matlab as ISDV_PE0\n"; ierr = engine.PutIntSerialDenseMatrix(isdVector, "ISDV_PE0"); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutIntSerialDenseMatrix(isdVector, \"ISDV_PE0\"): " << ierr << endl; } if (comm.NumProc() > 1) { if (verbose) cout << " putting IntSerialDenseVector from PE1 into Matlab as ISDV_PE1\n"; // specifying 1 as the third parameter will put the IntSerialDenseVector from PE1 into Matlab ierr = engine.PutIntSerialDenseMatrix(isdVector, "ISDV_PE1", 1); if (ierr) { if (reportErrors) cout << "There was an error in engine.PutSerialDenseMatrix(isdVector, \"ISDV_PE1\", 1): " << ierr << endl; } } // entering a while loop on PE0 will keep the Matlab workspace alive /* if (MyPID == 0) while(1) { // do nothing } */ const int bufSize = 200; char s [bufSize]; const int matlabBufferSize = 1024 * 16; char matlabBuffer [matlabBufferSize]; // send some commands to Matlab and output the result to stdout engine.EvalString("whos", matlabBuffer, matlabBufferSize); if (verbose) cout << matlabBuffer << endl; engine.EvalString("SDV_PE0", matlabBuffer, matlabBufferSize); if (verbose) cout << matlabBuffer << endl; if (comm.NumProc() > 1) { engine.EvalString("SDV_PE1", matlabBuffer, matlabBufferSize); if (verbose) cout << matlabBuffer << endl; } // the following allows user interaction with Matlab if (MyPID == 0) while(1) { // Prompt the user and get a string printf(">> "); if (fgets(s, bufSize, stdin) == NULL) { printf("Bye\n"); break ; } printf ("command :%s:\n", s) ; // send the command to MATLAB // output goes to stdout ierr = engine.EvalString(s, matlabBuffer, matlabBufferSize); if (ierr != 0) { printf("there was an error: %d", ierr); ierr = 0; } else { printf("Matlab Output:\n%s", matlabBuffer); } } if (verbose) cout << endl << " all done\n"; // standard finalizer for Epetra MPI Comms #ifdef EPETRA_MPI MPI_Finalize(); #endif // we need to delete engine because the MatlabEngine finalizer shuts down the Matlab process associated with this example // if we don't delete the Matlab engine, then this example application will not shut down properly delete &engine; return(0); }

EpetraExt_MatlabEngine constructor which creates a MatlabEngine object with a connection to an instance of the application Matlab by starting a new Matlab process.


Sends a command to Matlab. Any command that can normally be typed in at the Matlab command line can be passed in to EvalString(char* command). Commands such as 'help desk', 'edit', and 'plot(MATRIX)' will pop up an interactive window.


Puts a Matlab variable into a CrsMatrix. The values from the Matlab variable are exported to the CrsMatrix using an export object. Therefore the CrsMatrix must be prepared by the user just like any CrsMatrix would be before calling an export.


Puts a Matlab variable into a IntSerialDenseMatrix on the specified PE. The IntSerialDenseMatrix must be constructed by the user and have the proper amount of space to hold the values that will be copied from the given Matlab variable.


Puts a Matlab variable into a MultiVector. The values from the Matlab variable are exported to the MultiVector using an export object. Therefore the MultiVector must be prepared by the user just like any MultiVector would be before calling an export.


Get a mxArray from Matlab. For internal use but can be used by an advanced user. Calls the Matlab provided engGetVariable function which copies the specified variable from the Matlab workspace into a mxArray. Hence any changes to mxArray will not show up in Matlab, and any changes to the Matlab variable in Matlab will not show up in the mxArray. When finished with the mxArray mxDestroyArray should be called on the mxArray. Matlab appears to perform a copy to a new mxArray each time engGetVariable is called.


Get general information about the mxArray. For internal use but can be used by an advanced user. Makes several Matlab function calls on the mxArray in order to determine the number of rows, columns, nonzeros, and whether or not the mxArray is sparse.


Puts a Matlab variable into a SerialDenseMatrix on the specified PE. The SerialDenseMatrix must be constructed by the user and have the proper amount of space to hold the values that will be copied from the given Matlab variable.


Puts a copy of the BlockMap or Map into the Matlab workspace.


Puts a mxArray into Matlab. The Matlab provided C library provides mxArray which is used to construct and fill a Matlab object before sending it to Matlab to be put into the Matlab workspace. The mxArray is copied into the Matlab memory space and is not needed after it has been passed to Matlab. mxArrays should be destroyed using mxDestoryArray(mxArray) when they are no longer needed by the C/C++ program using them. Objects in Matlab must be destroyed using EvalString(char* command) and the appropriate Matlab command to destroy the object. EpetraExt::MatlabEngine uses PutIntoMatlab to pass all mxArrays it generates into Matlab. However, a user can create, fill, and put his/her own mxArrays into Matlab using this method. To create a mxArray mex.h must be included. For more information on how to use mxArrays see Matlab's documentation (type helpdesk at the Matlab command prompt) and see the External API Reference section.


Puts a copy of the IntSerialDenseMatrix into the Matlab workspace.


Puts a copy of the serial or distributed MultiVector into the Matlab workspace.


Puts a copy of the serial or distributed RowMatrix into the Matlab workspace.


Puts a copy of the SerialDenseMatrix into the Matlab workspace.
