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 separate 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  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:   PetscInfo1(0,"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:   PetscInfo1(0,"Started Matlab engine on %s\n",machine);
 59: 
 60:   *mengine = e;
 61:   return(0);
 62: }

 66: /*@
 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  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  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:   PetscInfo1(0,"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:   PetscInfo1(0,"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  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  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: /*@
213:     PetscMatlabEnginePut - Puts a Petsc object into the Matlab space. For parallel objects,
214:       each processors part is put in a separate  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  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:   PetscInfo(0,"Putting Matlab object\n");
238:   (*put)(obj,mengine->ep);
239:   PetscInfo1(0,"Put Matlab object: %s\n",obj->name);
240:   return(0);
241: }

245: /*@
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  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:   PetscInfo(0,"Getting Matlab object\n");
273:   (*get)(obj,mengine->ep);
274:   PetscInfo1(0,"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_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 separate  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  PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
359: {
361:   mxArray *mat;
362: 
364:   PetscInfo1(0,"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:   PetscInfo1(0,"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  PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
397: {
399:   mxArray *mat;
400: 
402:   PetscInfo1(0,"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:   PetscInfo1(0,"Got Matlab array %s\n",name);
407:   return(0);
408: }