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