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