Actual source code: matlab.c

      1: #define PETSC_DLL

      3: #include "engine.h"   /* Matlab include file */
      4: #include "petsc.h"
      5: #include <stdarg.h>

      7: struct  _p_PetscMatlabEngine {
      8:   PETSCHEADER(int);
      9:   Engine   *ep;
     10:   char     buffer[1024];
     11: };

     13: PetscCookie MATLABENGINE_COOKIE = -1;

     17: /*@C
     18:     PetscMatlabEngineCreate - Creates a Matlab engine object

     20:     Not Collective

     22:     Input Parameters:
     23: +   comm - a seperate Matlab engine is started for each process in the communicator
     24: -   machine - name of machine where Matlab engine is to be run (usually PETSC_NULL)

     26:     Output Parameter:
     27: .   mengine - the resulting object

     29:    Level: advanced

     31: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
     32:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
     33:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
     34: @*/
     35: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEngineCreate(MPI_Comm comm,const char machine[],PetscMatlabEngine *mengine)
     36: {
     37:   PetscErrorCode    ierr;
     38:   PetscMPIInt       rank,size;
     39:   char              buffer[256];
     40:   PetscMatlabEngine e;

     43:   if (MATLABENGINE_COOKIE == -1) {
     44:     PetscLogClassRegister(&MATLABENGINE_COOKIE,"Matlab Engine");
     45:   }
     46:   PetscHeaderCreate(e,_p_PetscMatlabEngine,int,MATLABENGINE_COOKIE,0,"MatlabEngine",comm,PetscMatlabEngineDestroy,0);

     48:   if (!machine) machine = "\0";
     49:   PetscLogInfo((0,"PetscMatlabEngineCreate:Starting Matlab engine on %s\n",machine));
     50:   e->ep = engOpen(machine);
     51:   if (!e->ep) SETERRQ1(PETSC_ERR_LIB,"Unable to start Matlab engine on %s\n",machine);
     52:   engOutputBuffer(e->ep,e->buffer,1024);

     54:   MPI_Comm_rank(comm,&rank);
     55:   MPI_Comm_size(comm,&size);
     56:   sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
     57:   engEvalString(e->ep, buffer);
     58:   PetscLogInfo((0,"PetscMatlabEngineCreate:Started Matlab engine on %s\n",machine));
     59:
     60:   *mengine = e;
     61:   return(0);
     62: }

     66: /*@C
     67:    PetscMatlabEngineDestroy - Destroys a vector.

     69:    Collective on PetscMatlabEngine

     71:    Input Parameters:
     72: .  e  - the engine

     74:    Level: advanced

     76: .seealso: PetscMatlabEnginCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
     77:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
     78:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
     79: @*/
     80: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEngineDestroy(PetscMatlabEngine v)
     81: {
     85:   if (--v->refct > 0) return(0);
     86:   PetscHeaderDestroy(v);
     87:   return(0);
     88: }

     92: /*@C
     93:     PetscMatlabEngineEvaluate - Evaluates a string in Matlab

     95:     Not Collective

     97:     Input Parameters:
     98: +   mengine - the Matlab engine
     99: -   string - format as in a printf()

    101:    Level: advanced

    103: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    104:           PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    105:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    106: @*/
    107: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
    108: {
    109:   va_list           Argp;
    110:   char              buffer[1024];
    112:   int               flops;
    113:   size_t            len;

    116:   PetscStrcpy(buffer,"flops(0);");
    117:   va_start(Argp,string);
    118:   PetscVSNPrintf(buffer+9,1024-9-5,string,Argp);
    119:   va_end(Argp);
    120:   PetscStrcat(buffer,",flops");

    122:   PetscLogInfo((0,"PetscMatlabEngineEvaluate:Evaluating Matlab string: %s\n",buffer));
    123:   engEvalString(mengine->ep, buffer);

    125:   /*
    126:      Check for error in Matlab: indicated by ? as first character in engine->buffer
    127:   */

    129:   if (mengine->buffer[4] == '?') {
    130:     SETERRQ2(PETSC_ERR_LIB,"Error in evaluating Matlab command:%s\n%s",string,mengine->buffer);
    131:   }

    133:   /*
    134:      Get flop number back from Matlab output
    135:   */
    136:   PetscStrlen(mengine->buffer,&len);
    137:   len -= 2;
    138:   while (len > 0) {
    139:     len--;
    140:     if (mengine->buffer[len] == ' ') break;
    141:     if (mengine->buffer[len] == '\n') break;
    142:     if (mengine->buffer[len] == '\t') break;
    143:   }
    144:   sscanf(mengine->buffer+len," %d\n",&flops);
    145:   PetscLogFlops(flops);
    146:   /* strip out of engine->buffer the end part about flops */
    147:   if (len < 14) SETERRQ1(PETSC_ERR_LIB,"Error from Matlab %s",mengine->buffer);
    148:   len -= 14;
    149:   mengine->buffer[len] = 0;

    151:   PetscLogInfo((0,"PetscMatlabEngineEvaluate:Done evaluating Matlab string: %s\n",buffer));
    152:   return(0);
    153: }

    157: /*@C
    158:     PetscMatlabEngineGetOutput - Gets a string buffer where the Matlab output is
    159:           printed

    161:     Not Collective

    163:     Input Parameter:
    164: .   mengine - the Matlab engine

    166:     Output Parameter:
    167: .   string - buffer where Matlab output is printed

    169:    Level: advanced

    171: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    172:           PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
    173:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    174: @*/
    175: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
    176: {
    178:   *string = mengine->buffer;
    179:   return(0);
    180: }

    184: /*@C
    185:     PetscMatlabEnginePrintOutput - prints the output from Matlab

    187:     Collective on PetscMatlabEngine

    189:     Input Parameters:
    190: .    mengine - the Matlab engine

    192:    Level: advanced

    194: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    195:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
    196:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    197: @*/
    198: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
    199: {
    201:   PetscMPIInt    rank;

    204:   MPI_Comm_rank(mengine->comm,&rank);
    205:   PetscSynchronizedFPrintf(mengine->comm,fd,"[%d]%s",rank,mengine->buffer);
    206:   PetscSynchronizedFlush(mengine->comm);
    207:   return(0);
    208: }

    212: /*@C
    213:     PetscMatlabEnginePut - Puts a Petsc object into the Matlab space. For parallel objects,
    214:       each processors part is put in a seperate  Matlab process.

    216:     Collective on PetscObject

    218:     Input Parameters:
    219: +    mengine - the Matlab engine
    220: -    object - the PETSc object, for example Vec

    222:    Level: advanced

    224: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
    225:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    226:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
    227: @*/
    228: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
    229: {
    230:   PetscErrorCode ierr,(*put)(PetscObject,void*);
    231:
    233:   PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",(void (**)(void))&put);
    234:   if (!put) {
    235:     SETERRQ1(PETSC_ERR_SUP,"Object %s cannot be put into Matlab engine",obj->class_name);
    236:   }
    237:   PetscLogInfo((0,"PetscMatlabEnginePut:Putting Matlab object\n"));
    238:   (*put)(obj,mengine->ep);
    239:   PetscLogInfo((0,"PetscMatlabEnginePut:Put Matlab object: %s\n",obj->name));
    240:   return(0);
    241: }

    245: /*@C
    246:     PetscMatlabEngineGet - Gets a variable from Matlab into a PETSc object.

    248:     Collective on PetscObject

    250:     Input Parameters:
    251: +    mengine - the Matlab engine
    252: -    object - the PETSc object, for example Vec

    254:    Level: advanced

    256: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
    257:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    258:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
    259: @*/
    260: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
    261: {
    262:   PetscErrorCode ierr,(*get)(PetscObject,void*);
    263:
    265:   if (!obj->name) {
    266:     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
    267:   }
    268:   PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",(void (**)(void))&get);
    269:   if (!get) {
    270:     SETERRQ1(PETSC_ERR_SUP,"Object %s cannot be gotten from Matlab engine",obj->class_name);
    271:   }
    272:   PetscLogInfo((0,"PetscMatlabEngineGet:Getting Matlab object\n"));
    273:   (*get)(obj,mengine->ep);
    274:   PetscLogInfo((0,"PetscMatlabEngineGet:Got Matlab object: %s\n",obj->name));
    275:   return(0);
    276: }

    278: /*
    279:     The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
    280:   is attached to a communicator, in this case the attribute is a PetscMatlabEngine
    281: */
    282: static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;

    287: /*@C
    288:    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
    289:                     in a communicator.

    291:    Not Collective

    293:    Input Parameter:
    294: .  comm - the MPI communicator to share the engine

    296:    Level: developer

    298:    Notes:
    299:    Unlike almost all other PETSc routines, this does not return
    300:    an error code. Usually used in the form
    301: $      PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));

    303: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    304:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    305:           PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
    306:           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
    307:
    308: @*/
    309: PetscMatlabEngine PETSC_DLLEXPORT PETSC_MATLAB_ENGINE_(MPI_Comm comm)
    310: {
    312:   PetscTruth        flg;
    313:   PetscMatlabEngine mengine;

    316:   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
    317:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
    318:     if (ierr) {PetscError(__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,1,1," "); mengine = 0;}
    319:   }
    320:   MPI_Attr_get(comm,Petsc_Matlab_Engine_keyval,(void **)&mengine,(int*)&flg);
    321:   if (ierr) {PetscError(__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,1,1," "); mengine = 0;}
    322:   if (!flg) { /* viewer not yet created */
    323:     char *machinename = 0,machine[64];

    325:     PetscOptionsGetString(PETSC_NULL,"-matlab_engine_machine",machine,64,&flg);
    326:     if (ierr) {PetscError(__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,1,1," "); mengine = 0;}
    327:     if (flg) machinename = machine;
    328:     PetscMatlabEngineCreate(comm,machinename,&mengine);
    329:     if (ierr) {PetscError(__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,1,1," "); mengine = 0;}
    330:     PetscObjectRegisterDestroy((PetscObject)mengine);
    331:     if (ierr) {PetscError(__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,1,1," "); mengine = 0;}
    332:     MPI_Attr_put(comm,Petsc_Matlab_Engine_keyval,mengine);
    333:     if (ierr) {PetscError(__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,1,1," "); mengine = 0;}
    334:   }
    335:   PetscFunctionReturn(mengine);
    336: }

    340: /*@C
    341:     PetscMatlabEnginePutArray - Puts a Petsc object into the Matlab space. For parallel objects,
    342:       each processors part is put in a seperate  Matlab process.

    344:     Collective on PetscObject

    346:     Input Parameters:
    347: +    mengine - the Matlab engine
    348: .    m,n - the dimensions of the array
    349: .    array - the array (represented in one dimension)
    350: -    name - the name of the array

    352:    Level: advanced

    354: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
    355:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    356:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), MatlabEngineGetArray(), PetscMatlabEngine
    357: @*/
    358: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
    359: {
    361:   mxArray *mat;
    362:
    364:   PetscLogInfo((0,"PetscMatlabEnginePutArray:Putting Matlab array %s\n",name));
    365: #if !defined(PETSC_USE_COMPLEX)
    366:   mat  = mxCreateDoubleMatrix(m,n,mxREAL);
    367: #else
    368:   mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
    369: #endif
    370:   PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));
    371:   engPutVariable(mengine->ep,name,mat);

    373:   PetscLogInfo((0,"PetscMatlabEnginePutArray:Put Matlab array %s\n",name));
    374:   return(0);
    375: }

    379: /*@C
    380:     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array

    382:     Not Collective

    384:     Input Parameters:
    385: +    mengine - the Matlab engine
    386: .    m,n - the dimensions of the array
    387: .    array - the array (represented in one dimension)
    388: -    name - the name of the array

    390:    Level: advanced

    392: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
    393:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    394:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
    395: @*/
    396: PetscErrorCode PETSC_DLLEXPORT PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
    397: {
    399:   mxArray *mat;
    400:
    402:   PetscLogInfo((0,"PetscMatlabEngineGetArray:Getting Matlab array %s\n",name));
    403:   mat  = engGetVariable(mengine->ep,name);
    404:   if (!mat) SETERRQ1(PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
    405:   PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));
    406:   PetscLogInfo((0,"PetscMatlabEngineGetArray:Got Matlab array %s\n",name));
    407:   return(0);
    408: }