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

 13: int 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: int PetscMatlabEngineCreate(MPI_Comm comm,const char machine[],PetscMatlabEngine *mengine)
 36: {
 37:   int               ierr,rank,size;
 38:   char              buffer[128];
 39:   PetscMatlabEngine e;

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

 48:   if (!machine) machine = "\0";
 49:   PetscLogInfo(0,"Starting Matlab engine on %s\n",machine);
 50:   e->ep = engOpen(machine);
 51:   if (!e->ep) SETERRQ1(1,"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,"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: int PetscMatlabEngineDestroy(PetscMatlabEngine v)
 81: {
 84:   if (--v->refct > 0) return(0);
 85:   PetscLogObjectDestroy(v);
 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: int PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
108: {
109:   va_list           Argp;
110:   char              buffer[1024];
111:   int               ierr,len,flops;

114:   PetscStrcpy(buffer,"flops(0);");
115:   va_start(Argp,string);
116: #if defined(PETSC_HAVE_VPRINTF_CHAR)
117:   vsprintf(buffer+9,string,(char *)Argp);
118: #else
119:   vsprintf(buffer+9,string,Argp);
120: #endif
121:   va_end(Argp);
122:   PetscStrcat(buffer,",flops");

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

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

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

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

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

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

163:     Not Collective

165:     Input Parameter:
166: .   mengine - the Matlab engine

168:     Output Parameter:
169: .   string - buffer where Matlab output is printed

171:    Level: advanced

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

186: /*@C
187:     PetscMatlabEnginePrintOutput - prints the output from Matlab

189:     Collective on PetscMatlabEngine

191:     Input Parameters:
192: .    mengine - the Matlab engine

194:    Level: advanced

196: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
197:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
198:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
199: @*/
200: int PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
201: {
202:   int  ierr,rank;

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

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

217:     Collective on PetscObject

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

223:    Level: advanced

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

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

249:     Collective on PetscObject

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

255:    Level: advanced

257: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
258:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
259:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
260: @*/
261: int PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
262: {
263:   int ierr,(*get)(PetscObject,void*);
264: 
266:   if (!obj->name) {
267:     SETERRQ(1,"Cannot get object that has no name");
268:   }
269:   PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",(void (**)(void))&get);
270:   if (!get) {
271:     SETERRQ1(1,"Object %s cannot be get into Matlab engine",obj->class_name);
272:   }
273:   PetscLogInfo(0,"Getting Matlab object\n");
274:   (*get)(obj,mengine->ep);
275:   PetscLogInfo(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 int Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;


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

292:    Not Collective

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

297:    Level: developer

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

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

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

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

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

345:     Collective on PetscObject

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

353:    Level: advanced

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

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

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

383:     Not Collective

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

391:    Level: advanced

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