Actual source code: matlab.c

petsc-3.11.4 2019-09-28
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;

 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) machine = "\0";
 53:   PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
 54:   if (!flg) {
 55:     PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
 56:   }
 57:   PetscStrlcat(buffer," -nojvm ",sizeof(buffer));
 58:   PetscInfo2(0,"Starting MATLAB engine on %s with command %s\n",machine,buffer);
 59:   e->ep = engOpen(buffer);
 60:   if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine on %s",machine);
 61:   engOutputBuffer(e->ep,e->buffer,1024);

 63:   MPI_Comm_rank(comm,&rank);
 64:   MPI_Comm_size(comm,&size);
 65:   sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
 66:   engEvalString(e->ep, buffer);
 67:   PetscInfo1(0,"Started MATLAB engine on %s\n",machine);

 69:   *mengine = e;
 70:   return(0);
 71: }

 73: /*@
 74:    PetscMatlabEngineDestroy - Destroys a vector.

 76:    Collective on PetscMatlabEngine

 78:    Input Parameters:
 79: .  e  - the engine

 81:    Level: advanced

 83: .seealso: PetscMatlabEnginCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
 84:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
 85:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
 86: @*/
 87: PetscErrorCode  PetscMatlabEngineDestroy(PetscMatlabEngine *v)
 88: {

 92:   if (!*v) return(0);
 94:   if (--((PetscObject)(*v))->refct > 0) return(0);
 95:   PetscHeaderDestroy(v);
 96:   return(0);
 97: }

 99: /*@C
100:     PetscMatlabEngineEvaluate - Evaluates a string in MATLAB

102:     Not Collective

104:     Input Parameters:
105: +   mengine - the MATLAB engine
106: -   string - format as in a printf()

108:    Level: advanced

110: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
111:           PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
112:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
113: @*/
114: PetscErrorCode  PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
115: {
116:   va_list        Argp;
117:   char           buffer[1024];
119:   size_t         fullLength;

122:   va_start(Argp,string);
123:   PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);
124:   va_end(Argp);

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

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

134:   PetscInfo1(0,"Done evaluating Matlab string: %s\n",buffer);
135:   return(0);
136: }

138: /*@C
139:     PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
140:           printed

142:     Not Collective

144:     Input Parameter:
145: .   mengine - the MATLAB engine

147:     Output Parameter:
148: .   string - buffer where MATLAB output is printed

150:    Level: advanced

152: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
153:           PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
154:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
155: @*/
156: PetscErrorCode  PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
157: {
159:   *string = mengine->buffer;
160:   return(0);
161: }

163: /*@C
164:     PetscMatlabEnginePrintOutput - prints the output from MATLAB

166:     Collective on PetscMatlabEngine

168:     Input Parameters:
169: .    mengine - the Matlab engine

171:    Level: advanced

173: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
174:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
175:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
176: @*/
177: PetscErrorCode  PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
178: {
180:   PetscMPIInt    rank;

183:   MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);
184:   PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);
185:   PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);
186:   return(0);
187: }

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

193:     Collective on PetscObject

195:     Input Parameters:
196: +    mengine - the MATLAB engine
197: -    object - the PETSc object, for example Vec

199:    Level: advanced

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

204: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
205:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
206:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
207: @*/
208: PetscErrorCode  PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
209: {
210:   PetscErrorCode ierr,(*put)(PetscObject,void*);

213:   PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);
214:   if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
215:   PetscInfo(0,"Putting MATLAB object\n");
216:   (*put)(obj,mengine->ep);
217:   PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);
218:   return(0);
219: }

221: /*@
222:     PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.

224:     Collective on PetscObject

226:     Input Parameters:
227: +    mengine - the MATLAB engine
228: -    object - the PETSc object, for example Vec

230:    Level: advanced

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

235: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
236:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
237:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
238: @*/
239: PetscErrorCode  PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
240: {
241:   PetscErrorCode ierr,(*get)(PetscObject,void*);

244:   if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
245:   PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);
246:   if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
247:   PetscInfo(0,"Getting MATLAB object\n");
248:   (*get)(obj,mengine->ep);
249:   PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);
250:   return(0);
251: }

253: /*
254:     The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
255:   is attached to a communicator, in this case the attribute is a PetscMatlabEngine
256: */
257: static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;


260: /*@C
261:    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
262:                     in a communicator.

264:    Not Collective

266:    Input Parameter:
267: .  comm - the MPI communicator to share the engine

269:    Level: developer

271:    Notes:
272:    Unlike almost all other PETSc routines, this does not return
273:    an error code. Usually used in the form
274: $      PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));

276: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
277:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
278:           PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
279:           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF

281: @*/
282: PetscMatlabEngine  PETSC_MATLAB_ENGINE_(MPI_Comm comm)
283: {
284:   PetscErrorCode    ierr;
285:   PetscBool         flg;
286:   PetscMatlabEngine mengine;

289:   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
290:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
291:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
292:   }
293:   MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
294:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
295:   if (!flg) { /* viewer not yet created */
296:     char *machinename = 0,machine[64];

298:     PetscOptionsGetString(NULL,NULL,"-matlab_engine_machine",machine,64,&flg);
299:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
300:     if (flg) machinename = machine;
301:     PetscMatlabEngineCreate(comm,machinename,&mengine);
302:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
303:     PetscObjectRegisterDestroy((PetscObject)mengine);
304:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
305:     MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine);
306:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
307:   }
308:   PetscFunctionReturn(mengine);
309: }

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

315:     Collective on PetscObject

317:     Input Parameters:
318: +    mengine - the MATLAB engine
319: .    m,n - the dimensions of the array
320: .    array - the array (represented in one dimension)
321: -    name - the name of the array

323:    Level: advanced

325: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
326:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
327:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), MatlabEngineGetArray(), PetscMatlabEngine
328: @*/
329: PetscErrorCode  PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
330: {
332:   mxArray        *mat;

335:   PetscInfo1(0,"Putting MATLAB array %s\n",name);
336: #if !defined(PETSC_USE_COMPLEX)
337:   mat = mxCreateDoubleMatrix(m,n,mxREAL);
338: #else
339:   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
340: #endif
341:   PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));
342:   engPutVariable(mengine->ep,name,mat);

344:   PetscInfo1(0,"Put MATLAB array %s\n",name);
345:   return(0);
346: }

348: /*@C
349:     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array

351:     Not Collective

353:     Input Parameters:
354: +    mengine - the Matlab engine
355: .    m,n - the dimensions of the array
356: .    array - the array (represented in one dimension)
357: -    name - the name of the array

359:    Level: advanced

361: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
362:           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
363:           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
364: @*/
365: PetscErrorCode  PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
366: {
368:   mxArray        *mat;

371:   PetscInfo1(0,"Getting MATLAB array %s\n",name);
372:   mat  = engGetVariable(mengine->ep,name);
373:   if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
374:   PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));
375:   PetscInfo1(0,"Got MATLAB array %s\n",name);
376:   return(0);
377: }