Actual source code: matlab.c

  1: /* $Id: matlab.c,v 1.17 2001/08/06 21:14:26 bsmith Exp $ #include "petsc.h" */

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

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

 18:     Not Collective

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

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

 27:    Level: advanced

 29: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
 30:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
 31:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutScalar(), PetscMatlabEngine
 32: @*/
 33: int PetscMatlabEngineCreate(MPI_Comm comm,char *machine,PetscMatlabEngine *mengine)
 34: {
 35:   int               ierr,rank,size;
 36:   char              buffer[128];
 37:   PetscMatlabEngine e;

 40:   PetscHeaderCreate(e,_p_PetscMatlabEngine,int,MATLABENGINE_COOKIE,0,"MatlabEngine",comm,PetscMatlabEngineDestroy,0);
 41:   PetscLogObjectCreate(e);

 43:   if (!machine) machine = "\0";
 44:   PetscLogInfo(0,"Starting Matlab engine on %s\n",machine);
 45:   e->ep = engOpen(machine);
 46:   if (!e->ep) SETERRQ1(1,"Unable to start Matlab engine on %s\n",machine);
 47:   engOutputBuffer(e->ep,e->buffer,1024);

 49:   MPI_Comm_rank(comm,&rank);
 50:   MPI_Comm_size(comm,&size);
 51:   sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
 52:   engEvalString(e->ep, buffer);
 53:   PetscLogInfo(0,"Started Matlab engine on %s\n",machine);
 54: 
 55:   *mengine = e;
 56:   return(0);
 57: }

 61: /*@C
 62:    PetscMatlabEngineDestroy - Destroys a vector.

 64:    Collective on PetscMatlabEngine

 66:    Input Parameters:
 67: .  e  - the engine

 69:    Level: advanced

 71: .seealso: PetscMatlabEnginCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
 72:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
 73:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutScalar(), PetscMatlabEngine
 74: @*/
 75: int PetscMatlabEngineDestroy(PetscMatlabEngine v)
 76: {
 79:   if (--v->refct > 0) return(0);
 80:   PetscLogObjectDestroy(v);
 81:   PetscHeaderDestroy(v);
 82:   return(0);
 83: }

 87: /*@C
 88:     PetscMatlabEngineEvaluate - Evaluates a string in Matlab

 90:     Not Collective

 92:     Input Parameters:
 93: +   mengine - the Matlab engine
 94: -   string - format as in a printf()

 96:    Level: advanced

 98: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
 99:           PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
100:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutScalar(), PetscMatlabEngine
101: @*/
102: int PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,char *string,...)
103: {
104:   va_list           Argp;
105:   char              buffer[1024];
106:   int               ierr,len,flops;

109:   PetscStrcpy(buffer,"flops(0);");
110:   va_start(Argp,string);
111: #if defined(PETSC_HAVE_VPRINTF_CHAR)
112:   vsprintf(buffer+9,string,(char *)Argp);
113: #else
114:   vsprintf(buffer+9,string,Argp);
115: #endif
116:   va_end(Argp);
117:   PetscStrcat(buffer,",flops");

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

122:   /* 
123:      Check for error in Matlab: indicated by ? as first character in engine->buffer
124:   */

126:   if (mengine->buffer[4] == '?') {
127:     SETERRQ2(1,"Error in evaluating Matlab command:%s\n%s",string,mengine->buffer);
128:   }

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

148:   PetscLogInfo(0,"Done evaluating Matlab string: %s\n",buffer);
149:   return(0);
150: }

154: /*@C
155:     PetscMatlabEngineGetOutput - Gets a string buffer where the Matlab output is 
156:           printed

158:     Not Collective

160:     Input Parameter:
161: .   mengine - the Matlab engine

163:     Output Parameter:
164: .   string - buffer where Matlab output is printed

166:    Level: advanced

168: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
169:           PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
170:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutScalar(), PetscMatlabEngine
171: @*/
172: int PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
173: {
175:   *string = mengine->buffer;
176:   return(0);
177: }

181: /*@C
182:     PetscMatlabEnginePrintOutput - prints the output from Matlab

184:     Collective on PetscMatlabEngine

186:     Input Parameters:
187: .    mengine - the Matlab engine

189:    Level: advanced

191: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
192:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
193:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutScalar(), PetscMatlabEngine
194: @*/
195: int PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
196: {
197:   int  ierr,rank;

200:   MPI_Comm_rank(mengine->comm,&rank);
201:   PetscSynchronizedFPrintf(mengine->comm,fd,"[%d]%s",rank,mengine->buffer);
202:   PetscSynchronizedFlush(mengine->comm);
203:   return(0);
204: }

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

212:     Collective on PetscObject

214:     Input Parameters:
215: +    mengine - the Matlab engine
216: -    object - the PETSc object, for example Vec

218:    Level: advanced

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

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

244:     Collective on PetscObject

246:     Input Parameters:
247: +    mengine - the Matlab engine
248: -    object - the PETSc object, for example Vec

250:    Level: advanced

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

274: /*
275:     The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
276:   is attached to a communicator, in this case the attribute is a PetscMatlabEngine
277: */
278: static int Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;


283: /*@C
284:    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors 
285:                     in a communicator.

287:    Not Collective

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

292:    Level: developer

294:    Notes: 
295:    Unlike almost all other PETSc routines, this does not return 
296:    an error code. Usually used in the form
297: $      PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));

299: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
300:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
301:           PetscMatlabEngineCreate(), PetscMatlabEnginePutScalar(), PetscMatlabEngine,
302:           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
303:  
304: @*/
305: PetscMatlabEngine PETSC_MATLAB_ENGINE_(MPI_Comm comm)
306: {
307:   int               ierr;
308:   PetscTruth        flg;
309:   PetscMatlabEngine mengine;

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

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

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

340:     Collective on PetscObject

342:     Input Parameters:
343: +    mengine - the Matlab engine
344: .    m,n - the dimensions of the array
345: .    array - the array (represented in one dimension)
346: -    name - the name of the array

348:    Level: advanced

350: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
351:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
352:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), MatlabEngineGetArray(), PetscMatlabEngine
353: @*/
354: int PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,char *name)
355: {
356:   int     ierr;
357:   mxArray *mat;
358: 
360:   PetscLogInfo(0,"Putting Matlab array %s\n",name);
361: #if !defined(PETSC_USE_COMPLEX)
362:   mat  = mxCreateDoubleMatrix(m,n,mxREAL);
363: #else
364:   mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
365: #endif
366:   PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));
367:   mxSetName(mat,name);
368:   engPutArray(mengine->ep,mat);

370:   PetscLogInfo(0,"Put Matlab array %s\n",name);
371:   return(0);
372: }

376: /*@C
377:     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array

379:     Not Collective

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

387:    Level: advanced

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