Actual source code: matlab.c

petsc-3.14.6 2021-03-30
Report Typos and Errors

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

 30:    Level: advanced

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

 45:   if (MATLABENGINE_CLASSID == -1) {
 46:     PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);
 47:   }
 48:   PetscOptionsGetBool(NULL,NULL,"-matlab_engine_graphics",&flg,NULL);

 50:   PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);

 52:   if (!machine) {
 53:     machine = "\0";
 54:     mgiven  = PETSC_FALSE;
 55:   }
 56:   PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
 57:   if (!flg) {
 58:     PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
 59:   }
 60:   PetscStrlcat(buffer," -nosplash ",sizeof(buffer));
 61:   if (mgiven) {
 62:     PetscInfo2(0,"Starting MATLAB engine on %s with command %s\n",machine,buffer);
 63:   } else {
 64:     PetscInfo1(0,"Starting MATLAB engine with command %s\n",buffer);
 65:   }
 66:   e->ep = engOpen(buffer);
 67:   if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine on %s",machine);
 68:   engOutputBuffer(e->ep,e->buffer,1024);

 70:   MPI_Comm_rank(comm,&rank);
 71:   MPI_Comm_size(comm,&size);
 72:   sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
 73:   engEvalString(e->ep, buffer);
 74:   if (mgiven) {
 75:     PetscInfo1(0,"Started MATLAB engine on %s\n",machine);
 76:   } else {
 77:     PetscInfo(0,"Started MATLAB engine\n");
 78:   }
 79:   *mengine = e;
 80:   return(0);
 81: }

 83: /*@
 84:    PetscMatlabEngineDestroy - Shuts down a Matlab engine.

 86:    Collective on PetscMatlabEngine

 88:    Input Parameters:
 89: .  e  - the engine

 91:    Level: advanced

 93: .seealso: PetscMatlabEngineCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
 94:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
 95:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
 96: @*/
 97: PetscErrorCode  PetscMatlabEngineDestroy(PetscMatlabEngine *v)
 98: {

102:   if (!*v) return(0);
104:   if (--((PetscObject)(*v))->refct > 0) return(0);
105:   PetscInfo(0,"Stopping MATLAB engine\n");
106:   engClose((*v)->ep);
107:   if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error closing Matlab engine");
108:   PetscInfo(0,"MATLAB engine stopped\n");
109:   PetscHeaderDestroy(v);
110:   return(0);
111: }

113: /*@C
114:     PetscMatlabEngineEvaluate - Evaluates a string in MATLAB

116:     Not Collective

118:     Input Parameters:
119: +   mengine - the MATLAB engine
120: -   string - format as in a printf()

122:    Level: advanced

124: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
125:           PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
126:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
127: @*/
128: PetscErrorCode  PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
129: {
130:   va_list        Argp;
131:   char           buffer[1024];
133:   size_t         fullLength;

136:   va_start(Argp,string);
137:   PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);
138:   va_end(Argp);

140:   PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);
141:   engEvalString(mengine->ep, buffer);

143:   /*
144:      Check for error in MATLAB: indicated by ? as first character in engine->buffer
145:   */
146:   if (mengine->buffer[4] == '?') SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in evaluating MATLAB command:%s\n%s",string,mengine->buffer);

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

152: /*@C
153:     PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
154:           printed

156:     Not Collective

158:     Input Parameter:
159: .   mengine - the MATLAB engine

161:     Output Parameter:
162: .   string - buffer where MATLAB output is printed

164:    Level: advanced

166: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
167:           PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
168:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
169: @*/
170: PetscErrorCode  PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
171: {
173:   *string = mengine->buffer;
174:   return(0);
175: }

177: /*@C
178:     PetscMatlabEnginePrintOutput - prints the output from MATLAB

180:     Collective on PetscMatlabEngine

182:     Input Parameters:
183: .    mengine - the Matlab engine

185:    Level: advanced

187: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
188:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
189:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
190: @*/
191: PetscErrorCode  PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
192: {
194:   PetscMPIInt    rank;

197:   MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);
198:   PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);
199:   PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);
200:   return(0);
201: }

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

207:     Collective on PetscObject

209:     Input Parameters:
210: +    mengine - the MATLAB engine
211: -    object - the PETSc object, for example Vec

213:    Level: advanced

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

218: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
219:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
220:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
221: @*/
222: PetscErrorCode  PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
223: {
224:   PetscErrorCode ierr,(*put)(PetscObject,void*);

227:   PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);
228:   if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
229:   PetscInfo(0,"Putting MATLAB object\n");
230:   (*put)(obj,mengine->ep);
231:   PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);
232:   return(0);
233: }

235: /*@
236:     PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.

238:     Collective on PetscObject

240:     Input Parameters:
241: +    mengine - the MATLAB engine
242: -    object - the PETSc object, for example Vec

244:    Level: advanced

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

249: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
250:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
251:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
252: @*/
253: PetscErrorCode  PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
254: {
255:   PetscErrorCode ierr,(*get)(PetscObject,void*);

258:   if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
259:   PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);
260:   if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
261:   PetscInfo(0,"Getting MATLAB object\n");
262:   (*get)(obj,mengine->ep);
263:   PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);
264:   return(0);
265: }

267: /*
268:     The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
269:   is attached to a communicator, in this case the attribute is a PetscMatlabEngine
270: */
271: static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;


274: /*@C
275:    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
276:                     in a communicator.

278:    Not Collective

280:    Input Parameter:
281: .  comm - the MPI communicator to share the engine

283:    Level: developer

285:    Notes:
286:    Unlike almost all other PETSc routines, this does not return
287:    an error code. Usually used in the form
288: $      PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));

290: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
291:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
292:           PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
293:           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF

295: @*/
296: PetscMatlabEngine  PETSC_MATLAB_ENGINE_(MPI_Comm comm)
297: {
298:   PetscErrorCode    ierr;
299:   PetscBool         flg;
300:   PetscMatlabEngine mengine;

303:   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
304:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
305:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
306:   }
307:   MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
308:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
309:   if (!flg) { /* viewer not yet created */
310:     char *machinename = 0,machine[64];

312:     PetscOptionsGetString(NULL,NULL,"-matlab_engine_machine",machine,sizeof(machine),&flg);
313:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
314:     if (flg) machinename = machine;
315:     PetscMatlabEngineCreate(comm,machinename,&mengine);
316:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
317:     PetscObjectRegisterDestroy((PetscObject)mengine);
318:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
319:     MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine);
320:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
321:   }
322:   PetscFunctionReturn(mengine);
323: }

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

329:     Collective on PetscObject

331:     Input Parameters:
332: +    mengine - the MATLAB engine
333: .    m,n - the dimensions of the array
334: .    array - the array (represented in one dimension)
335: -    name - the name of the array

337:    Level: advanced

339: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
340:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
341:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), PetscMatlabEngineGetArray(), PetscMatlabEngine
342: @*/
343: PetscErrorCode  PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
344: {
346:   mxArray        *mat;

349:   PetscInfo1(0,"Putting MATLAB array %s\n",name);
350: #if !defined(PETSC_USE_COMPLEX)
351:   mat = mxCreateDoubleMatrix(m,n,mxREAL);
352: #else
353:   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
354: #endif
355:   PetscArraycpy(mxGetPr(mat),array,m*n);
356:   engPutVariable(mengine->ep,name,mat);

358:   PetscInfo1(0,"Put MATLAB array %s\n",name);
359:   return(0);
360: }

362: /*@C
363:     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array

365:     Not Collective

367:     Input Parameters:
368: +    mengine - the Matlab engine
369: .    m,n - the dimensions of the array
370: .    array - the array (represented in one dimension)
371: -    name - the name of the array

373:    Level: advanced

375: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
376:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
377:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
378: @*/
379: PetscErrorCode  PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
380: {
382:   mxArray        *mat;

385:   PetscInfo1(0,"Getting MATLAB array %s\n",name);
386:   mat  = engGetVariable(mengine->ep,name);
387:   if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
388:   if (mxGetM(mat) != (size_t) m) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"Array %s in matlab first dimension %d does not match requested size %d",name,(int)mxGetM(mat),m);
389:   if (mxGetN(mat) != (size_t) n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"Array %s in matlab second dimension %d does not match requested size %d",name,(int)mxGetN(mat),m);
390:   PetscArraycpy(array,mxGetPr(mat),m*n);
391:   PetscInfo1(0,"Got MATLAB array %s\n",name);
392:   return(0);
393: }