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: }