xref: /petsc/src/sys/classes/matlabengine/matlab.c (revision 82f516cc2a80c5c0e712e5bfc0bf40989ffef740)
1 
2 #include <engine.h>   /* Matlab include file */
3 #include <petscsys.h>
4 
5 struct  _p_PetscMatlabEngine {
6   PETSCHEADER(int);
7   Engine *ep;
8   char   buffer[1024];
9 };
10 
11 PetscClassId MATLABENGINE_CLASSID = -1;
12 
13 #undef __FUNCT__
14 #define __FUNCT__ "PetscMatlabEngineCreate"
15 /*@C
16     PetscMatlabEngineCreate - Creates a MATLAB engine object
17 
18     Not Collective
19 
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)
23 
24     Output Parameter:
25 .   mengine - the resulting object
26 
27    Options Database:
28 .    -matlab_engine_graphics - allow the MATLAB engine to display graphics
29 
30    Level: advanced
31 
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;
43 
44   PetscFunctionBegin;
45   if (MATLABENGINE_CLASSID == -1) {
46     ierr = PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);CHKERRQ(ierr);
47   }
48   ierr = PetscOptionsGetBool(NULL,"-matlab_engine_graphics",&flg,NULL);CHKERRQ(ierr);
49 
50   ierr = PetscHeaderCreate(e,_p_PetscMatlabEngine,int,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,0);CHKERRQ(ierr);
51 
52   if (!machine) machine = "\0";
53   ierr = PetscStrcpy(buffer,PETSC_MATLAB_COMMAND);CHKERRQ(ierr);
54   if (!flg) {
55     ierr = PetscStrcat(buffer," -nodisplay ");CHKERRQ(ierr);
56   }
57   ierr  = PetscStrcat(buffer," -nojvm ");CHKERRQ(ierr);
58   ierr  = PetscInfo2(0,"Starting MATLAB engine on %s with command %s\n",machine,buffer);CHKERRQ(ierr);
59   e->ep = engOpen(buffer);
60   if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine on %s\n",machine);
61   engOutputBuffer(e->ep,e->buffer,1024);
62 
63   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
64   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
65   sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
66   engEvalString(e->ep, buffer);
67   ierr = PetscInfo1(0,"Started MATLAB engine on %s\n",machine);CHKERRQ(ierr);
68 
69   *mengine = e;
70   PetscFunctionReturn(0);
71 }
72 
73 #undef __FUNCT__
74 #define __FUNCT__ "PetscMatlabEngineDestroy"
75 /*@
76    PetscMatlabEngineDestroy - Destroys a vector.
77 
78    Collective on PetscMatlabEngine
79 
80    Input Parameters:
81 .  e  - the engine
82 
83    Level: advanced
84 
85 .seealso: PetscMatlabEnginCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
86           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
87           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
88 @*/
89 PetscErrorCode  PetscMatlabEngineDestroy(PetscMatlabEngine *v)
90 {
91   PetscErrorCode ierr;
92 
93   PetscFunctionBegin;
94   if (!*v) PetscFunctionReturn(0);
95   PetscValidHeaderSpecific(*v,MATLABENGINE_CLASSID,1);
96   if (--((PetscObject)(*v))->refct > 0) PetscFunctionReturn(0);
97   ierr = PetscHeaderDestroy(v);CHKERRQ(ierr);
98   PetscFunctionReturn(0);
99 }
100 
101 #undef __FUNCT__
102 #define __FUNCT__ "PetscMatlabEngineEvaluate"
103 /*@C
104     PetscMatlabEngineEvaluate - Evaluates a string in MATLAB
105 
106     Not Collective
107 
108     Input Parameters:
109 +   mengine - the MATLAB engine
110 -   string - format as in a printf()
111 
112    Level: advanced
113 
114 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
115           PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
116           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
117 @*/
118 PetscErrorCode  PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
119 {
120   va_list        Argp;
121   char           buffer[1024];
122   PetscErrorCode ierr;
123   size_t         fullLength;
124 
125   PetscFunctionBegin;
126   va_start(Argp,string);
127   ierr = PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);CHKERRQ(ierr);
128   va_end(Argp);
129 
130   ierr = PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);CHKERRQ(ierr);
131   engEvalString(mengine->ep, buffer);
132 
133   /*
134      Check for error in MATLAB: indicated by ? as first character in engine->buffer
135   */
136   if (mengine->buffer[4] == '?') SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in evaluating MATLAB command:%s\n%s",string,mengine->buffer);
137 
138   ierr = PetscInfo1(0,"Done evaluating Matlab string: %s\n",buffer);CHKERRQ(ierr);
139   PetscFunctionReturn(0);
140 }
141 
142 #undef __FUNCT__
143 #define __FUNCT__ "PetscMatlabEngineGetOutput"
144 /*@C
145     PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
146           printed
147 
148     Not Collective
149 
150     Input Parameter:
151 .   mengine - the MATLAB engine
152 
153     Output Parameter:
154 .   string - buffer where MATLAB output is printed
155 
156    Level: advanced
157 
158 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
159           PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
160           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
161 @*/
162 PetscErrorCode  PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
163 {
164   PetscFunctionBegin;
165   *string = mengine->buffer;
166   PetscFunctionReturn(0);
167 }
168 
169 #undef __FUNCT__
170 #define __FUNCT__ "PetscMatlabEnginePrintOutput"
171 /*@C
172     PetscMatlabEnginePrintOutput - prints the output from MATLAB
173 
174     Collective on PetscMatlabEngine
175 
176     Input Parameters:
177 .    mengine - the Matlab engine
178 
179    Level: advanced
180 
181 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
182           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
183           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
184 @*/
185 PetscErrorCode  PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
186 {
187   PetscErrorCode ierr;
188   PetscMPIInt    rank;
189 
190   PetscFunctionBegin;
191   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);CHKERRQ(ierr);
192   ierr = PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);CHKERRQ(ierr);
193   ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine));CHKERRQ(ierr);
194   PetscFunctionReturn(0);
195 }
196 
197 #undef __FUNCT__
198 #define __FUNCT__ "PetscMatlabEnginePut"
199 /*@
200     PetscMatlabEnginePut - Puts a Petsc object into the MATLAB space. For parallel objects,
201       each processors part is put in a separate  MATLAB process.
202 
203     Collective on PetscObject
204 
205     Input Parameters:
206 +    mengine - the MATLAB engine
207 -    object - the PETSc object, for example Vec
208 
209    Level: advanced
210 
211 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
212           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
213           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
214 @*/
215 PetscErrorCode  PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
216 {
217   PetscErrorCode ierr,(*put)(PetscObject,void*);
218 
219   PetscFunctionBegin;
220   ierr = PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",(void (**)(void))&put);CHKERRQ(ierr);
221   if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
222   ierr = PetscInfo(0,"Putting MATLAB object\n");CHKERRQ(ierr);
223   ierr = (*put)(obj,mengine->ep);CHKERRQ(ierr);
224   ierr = PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);CHKERRQ(ierr);
225   PetscFunctionReturn(0);
226 }
227 
228 #undef __FUNCT__
229 #define __FUNCT__ "PetscMatlabEngineGet"
230 /*@
231     PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.
232 
233     Collective on PetscObject
234 
235     Input Parameters:
236 +    mengine - the MATLAB engine
237 -    object - the PETSc object, for example Vec
238 
239    Level: advanced
240 
241 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
242           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
243           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
244 @*/
245 PetscErrorCode  PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
246 {
247   PetscErrorCode ierr,(*get)(PetscObject,void*);
248 
249   PetscFunctionBegin;
250   if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
251   ierr = PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",(void (**)(void))&get);CHKERRQ(ierr);
252   if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
253   ierr = PetscInfo(0,"Getting MATLAB object\n");CHKERRQ(ierr);
254   ierr = (*get)(obj,mengine->ep);CHKERRQ(ierr);
255   ierr = PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);CHKERRQ(ierr);
256   PetscFunctionReturn(0);
257 }
258 
259 /*
260     The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
261   is attached to a communicator, in this case the attribute is a PetscMatlabEngine
262 */
263 static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;
264 
265 
266 #undef __FUNCT__
267 #define __FUNCT__ "PETSC_MATLAB_ENGINE_"
268 /*@C
269    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
270                     in a communicator.
271 
272    Not Collective
273 
274    Input Parameter:
275 .  comm - the MPI communicator to share the engine
276 
277    Level: developer
278 
279    Notes:
280    Unlike almost all other PETSc routines, this does not return
281    an error code. Usually used in the form
282 $      PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));
283 
284 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
285           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
286           PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
287           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
288 
289 @*/
290 PetscMatlabEngine  PETSC_MATLAB_ENGINE_(MPI_Comm comm)
291 {
292   PetscErrorCode    ierr;
293   PetscBool         flg;
294   PetscMatlabEngine mengine;
295 
296   PetscFunctionBegin;
297   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
298     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
299     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
300   }
301   ierr = MPI_Attr_get(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
302   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
303   if (!flg) { /* viewer not yet created */
304     char *machinename = 0,machine[64];
305 
306     ierr = PetscOptionsGetString(NULL,"-matlab_engine_machine",machine,64,&flg);
307     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
308     if (flg) machinename = machine;
309     ierr = PetscMatlabEngineCreate(comm,machinename,&mengine);
310     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
311     ierr = PetscObjectRegisterDestroy((PetscObject)mengine);
312     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
313     ierr = MPI_Attr_put(comm,Petsc_Matlab_Engine_keyval,mengine);
314     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
315   }
316   PetscFunctionReturn(mengine);
317 }
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "PetscMatlabEnginePutArray"
321 /*@C
322     PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects,
323       each processors part is put in a separate  MATLAB process.
324 
325     Collective on PetscObject
326 
327     Input Parameters:
328 +    mengine - the MATLAB engine
329 .    m,n - the dimensions of the array
330 .    array - the array (represented in one dimension)
331 -    name - the name of the array
332 
333    Level: advanced
334 
335 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
336           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
337           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), MatlabEngineGetArray(), PetscMatlabEngine
338 @*/
339 PetscErrorCode  PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
340 {
341   PetscErrorCode ierr;
342   mxArray        *mat;
343 
344   PetscFunctionBegin;
345   ierr = PetscInfo1(0,"Putting MATLAB array %s\n",name);CHKERRQ(ierr);
346 #if !defined(PETSC_USE_COMPLEX)
347   mat = mxCreateDoubleMatrix(m,n,mxREAL);
348 #else
349   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
350 #endif
351   ierr = PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));CHKERRQ(ierr);
352   engPutVariable(mengine->ep,name,mat);
353 
354   ierr = PetscInfo1(0,"Put MATLAB array %s\n",name);CHKERRQ(ierr);
355   PetscFunctionReturn(0);
356 }
357 
358 #undef __FUNCT__
359 #define __FUNCT__ "PetscMatlabEngineGetArray"
360 /*@C
361     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array
362 
363     Not Collective
364 
365     Input Parameters:
366 +    mengine - the Matlab engine
367 .    m,n - the dimensions of the array
368 .    array - the array (represented in one dimension)
369 -    name - the name of the array
370 
371    Level: advanced
372 
373 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
374           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
375           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
376 @*/
377 PetscErrorCode  PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
378 {
379   PetscErrorCode ierr;
380   mxArray        *mat;
381 
382   PetscFunctionBegin;
383   ierr = PetscInfo1(0,"Getting MATLAB array %s\n",name);CHKERRQ(ierr);
384   mat  = engGetVariable(mengine->ep,name);
385   if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
386   ierr = PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));CHKERRQ(ierr);
387   ierr = PetscInfo1(0,"Got MATLAB array %s\n",name);CHKERRQ(ierr);
388   PetscFunctionReturn(0);
389 }
390 
391 
392 
393 
394