Date: 2022-03-31T04:46:02+00:00

Actual source code: matlab.c

      2: #include <engine.h>   /* MATLAB include file */
      3: #include <petscsys.h>
      4: #include <petscmatlab.h>
      5: #include <petsc/private/petscimpl.h>

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

     13: PetscClassId MATLABENGINE_CLASSID = -1;

     15: /*@C
     16:     PetscMatlabEngineCreate - Creates a MATLAB engine object

     18:     Not Collective

     20:     Input Parameters:
     21: +   comm - a separate MATLAB engine is started for each process in the communicator
     22: -   host - name of machine where MATLAB engine is to be run (usually NULL)

     24:     Output Parameter:
     25: .   mengine - the resulting object

     27:    Options Database:
     28: +    -matlab_engine_graphics - allow the MATLAB engine to display graphics
     29: .    -matlab_engine_host - hostname, machine to run the MATLAB engine on
     30: -    -info - print out all requests to MATLAB and all if its responses (for debugging)

     32:    Level: advanced

     34: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
     35:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
     36:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
     37: @*/
     38: PetscErrorCode  PetscMatlabEngineCreate(MPI_Comm comm,const char host[],PetscMatlabEngine *mengine)
     39: {
     40:   PetscMPIInt       rank,size;
     41:   char              buffer[256];
     42:   PetscMatlabEngine e;
     43:   PetscBool         flg = PETSC_FALSE;

     45:   if (MATLABENGINE_CLASSID == -1) PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);
     46:   PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);

     48:   if (!host) {
     49:     char lhost[64];

     51:     PetscOptionsGetString(NULL,NULL,"-matlab_engine_host",lhost,sizeof(lhost),&flg);
     52:     if (flg) {host = lhost;}
     53:   }
     54:   flg = PETSC_FALSE;
     55:   PetscOptionsGetBool(NULL,NULL,"-matlab_engine_graphics",&flg,NULL);

     57:   if (host) {
     58:     PetscInfo(0,"Starting MATLAB engine on %s\n",host);
     59:   } else {

     61:   }
     62:   if (host) {
     63:     PetscStrcpy(buffer,"ssh ");
     64:     PetscStrcat(buffer,host);
     65:     PetscStrcat(buffer," \"");
     66:     PetscStrlcat(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
     67:     if (!flg) {
     68:       PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
     69:     }
     70:     PetscStrlcat(buffer," -nosplash ",sizeof(buffer));
     71:     PetscStrcat(buffer,"\"");
     72:   } else {
     73:     PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
     74:     if (!flg) {
     75:       PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
     76:     }
     77:     PetscStrlcat(buffer," -nosplash ",sizeof(buffer));
     78:   }
     79:   PetscInfo(0,"Starting MATLAB engine with command %s\n",buffer);
     80:   e->ep = engOpen(buffer);
     82:   engOutputBuffer(e->ep,e->buffer,sizeof(e->buffer));
     83:   if (host) {
     84:     PetscInfo(0,"Started MATLAB engine on %s\n",host);
     85:   } else {
     86:     PetscInfo(0,"Started MATLAB engine\n");
     87:   }

     89:   MPI_Comm_rank(comm,&rank);
     90:   MPI_Comm_size(comm,&size);
     91:   PetscMatlabEngineEvaluate(e,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
     92:   *mengine = e;
     93:   return 0;
     94: }

     96: /*@
     97:    PetscMatlabEngineDestroy - Shuts down a MATLAB engine.

     99:    Collective on PetscMatlabEngine

    101:    Input Parameters:
    102: .  e  - the engine

    104:    Level: advanced

    106: .seealso: PetscMatlabEngineCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    107:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    108:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    109: @*/
    110: PetscErrorCode  PetscMatlabEngineDestroy(PetscMatlabEngine *v)
    111: {

    114:   if (!*v) return 0;
    116:   if (--((PetscObject)(*v))->refct > 0) return 0;
    117:   PetscInfo(0,"Stopping MATLAB engine\n");
    118:   engClose((*v)->ep);
    120:   PetscInfo(0,"MATLAB engine stopped\n");
    121:   PetscHeaderDestroy(v);
    122:   return 0;
    123: }

    125: /*@C
    126:     PetscMatlabEngineEvaluate - Evaluates a string in MATLAB

    128:     Not Collective

    130:     Input Parameters:
    131: +   mengine - the MATLAB engine
    132: -   string - format as in a printf()

    134:    Notes:
    135:      Run the PETSc program with -info to always have printed back MATLAB's response to the string evaluation

    137:    Level: advanced

    139: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    140:           PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    141:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    142: @*/
    143: PetscErrorCode  PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
    144: {
    145:   va_list        Argp;
    146:   char           buffer[1024];
    147:   size_t         fullLength;

    149:   va_start(Argp,string);
    150:   PetscVSNPrintf(buffer,sizeof(buffer)-9-5,string,&fullLength,Argp);
    151:   va_end(Argp);

    153:   PetscInfo(0,"Evaluating MATLAB string: %s\n",buffer);
    154:   engEvalString(mengine->ep, buffer);
    155:   PetscInfo(0,"Done evaluating MATLAB string: %s\n",buffer);
    156:   PetscInfo(0,"  MATLAB output message: %s\n",mengine->buffer);

    158:   /*
    159:      Check for error in MATLAB: indicated by ? as first character in engine->buffer
    160:   */
    162:   return 0;
    163: }

    165: /*@C
    166:     PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
    167:           printed

    169:     Not Collective

    171:     Input Parameter:
    172: .   mengine - the MATLAB engine

    174:     Output Parameter:
    175: .   string - buffer where MATLAB output is printed

    177:    Level: advanced

    179: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    180:           PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
    181:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    182: @*/
    183: PetscErrorCode  PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
    184: {
    186:   *string = mengine->buffer;
    187:   return 0;
    188: }

    190: /*@C
    191:     PetscMatlabEnginePrintOutput - prints the output from MATLAB

    193:     Collective on PetscMatlabEngine

    195:     Input Parameters:
    196: .    mengine - the Matlab engine

    198:    Level: advanced

    200: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
    201:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
    202:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    203: @*/
    204: PetscErrorCode  PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
    205: {
    206:   PetscMPIInt    rank;

    209:   MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);
    210:   PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);
    211:   PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);
    212:   return 0;
    213: }

    215: /*@
    216:     PetscMatlabEnginePut - Puts a Petsc object into the MATLAB space. For parallel objects,
    217:       each processors part is put in a separate  MATLAB process.

    219:     Collective on PetscObject

    221:     Input Parameters:
    222: +    mengine - the MATLAB engine
    223: -    object - the PETSc object, for example Vec

    225:    Level: advanced

    227:    Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space
    228:          (this is because MATLAB uses compressed column format and PETSc uses compressed row format)

    230: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
    231:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    232:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    233: @*/
    234: PetscErrorCode  PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
    235: {
    236:   PetscErrorCode (*put)(PetscObject,void*);

    239:   PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);
    241:   PetscInfo(0,"Putting MATLAB object\n");
    242:   (*put)(obj,mengine->ep);
    243:   PetscInfo(0,"Put MATLAB object: %s\n",obj->name);
    244:   return 0;
    245: }

    247: /*@
    248:     PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.

    250:     Collective on PetscObject

    252:     Input Parameters:
    253: +    mengine - the MATLAB engine
    254: -    object - the PETSc object, for example Vec

    256:    Level: advanced

    258:    Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space
    259:          (this is because MATLAB uses compressed column format and PETSc uses compressed row format)

    261: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
    262:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    263:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    264: @*/
    265: PetscErrorCode  PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
    266: {
    267:   PetscErrorCode (*get)(PetscObject,void*);

    271:   PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);
    273:   PetscInfo(0,"Getting MATLAB object\n");
    274:   (*get)(obj,mengine->ep);
    275:   PetscInfo(0,"Got MATLAB object: %s\n",obj->name);
    276:   return 0;
    277: }

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

    285: /*@C
    286:    PETSC_MATLAB_ENGINE_ - Creates a MATLAB engine on each process in a communicator.

    288:    Not Collective

    290:    Input Parameter:
    291: .  comm - the MPI communicator to share the engine

    293:    Options Database:
    294: .  -matlab_engine_host - hostname

    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

    308: @*/
    309: PetscMatlabEngine  PETSC_MATLAB_ENGINE_(MPI_Comm comm)
    310: {
    311:   PetscErrorCode    ierr;
    312:   PetscBool         flg;
    313:   PetscMatlabEngine mengine;

    315:   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
    316:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
    317:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    318:   }
    319:   MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
    320:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    321:   if (!flg) { /* viewer not yet created */
    322:     PetscMatlabEngineCreate(comm,NULL,&mengine);
    323:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    324:     PetscObjectRegisterDestroy((PetscObject)mengine);
    325:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    326:     MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine);
    327:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    328:   }
    329:   return mengine;
    330: }

    332: /*@C
    333:     PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects,
    334:       each processors part is put in a separate  MATLAB process.

    336:     Collective on PetscObject

    338:     Input Parameters:
    339: +    mengine - the MATLAB engine
    340: .    m,n - the dimensions of the array
    341: .    array - the array (represented in one dimension)
    342: -    name - the name of the array

    344:    Level: advanced

    346: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
    347:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    348:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), PetscMatlabEngineGetArray(), PetscMatlabEngine
    349: @*/
    350: PetscErrorCode  PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
    351: {
    352:   mxArray *mat;

    355:   PetscInfo(0,"Putting MATLAB array %s\n",name);
    356: #if !defined(PETSC_USE_COMPLEX)
    357:   mat = mxCreateDoubleMatrix(m,n,mxREAL);
    358: #else
    359:   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
    360: #endif
    361:   PetscArraycpy(mxGetPr(mat),array,m*n);
    362:   engPutVariable(mengine->ep,name,mat);

    364:   PetscInfo(0,"Put MATLAB array %s\n",name);
    365:   return 0;
    366: }

    368: /*@C
    369:     PetscMatlabEngineGetArray - Gets a variable from MATLAB into an array

    371:     Not Collective

    373:     Input Parameters:
    374: +    mengine - the MATLAB engine
    375: .    m,n - the dimensions of the array
    376: .    array - the array (represented in one dimension)
    377: -    name - the name of the array

    379:    Level: advanced

    381: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
    382:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
    383:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
    384: @*/
    385: PetscErrorCode  PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
    386: {
    387:   mxArray        *mat;

    390:   PetscInfo(0,"Getting MATLAB array %s\n",name);
    391:   mat  = engGetVariable(mengine->ep,name);
    395:   PetscArraycpy(array,mxGetPr(mat),m*n);
    396:   PetscInfo(0,"Got MATLAB array %s\n",name);
    397:   return 0;
    398: }