xref: /petsc/src/sys/classes/matlabengine/matlab.c (revision feff33ee0b5b037fa8f9f294dede656a2f85cc47)
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 /*@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,NULL,"-matlab_engine_graphics",&flg,NULL);CHKERRQ(ierr);
49 
50   ierr = PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);CHKERRQ(ierr);
51 
52   if (!machine) machine = "\0";
53   ierr = PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));CHKERRQ(ierr);
54   if (!flg) {
55     ierr = PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));CHKERRQ(ierr);
56   }
57   ierr  = PetscStrlcat(buffer," -nojvm ",sizeof(buffer));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",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 /*@
74    PetscMatlabEngineDestroy - Destroys a vector.
75 
76    Collective on PetscMatlabEngine
77 
78    Input Parameters:
79 .  e  - the engine
80 
81    Level: advanced
82 
83 .seealso: PetscMatlabEnginCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
84           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
85           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
86 @*/
87 PetscErrorCode  PetscMatlabEngineDestroy(PetscMatlabEngine *v)
88 {
89   PetscErrorCode ierr;
90 
91   PetscFunctionBegin;
92   if (!*v) PetscFunctionReturn(0);
93   PetscValidHeaderSpecific(*v,MATLABENGINE_CLASSID,1);
94   if (--((PetscObject)(*v))->refct > 0) PetscFunctionReturn(0);
95   ierr = PetscHeaderDestroy(v);CHKERRQ(ierr);
96   PetscFunctionReturn(0);
97 }
98 
99 /*@C
100     PetscMatlabEngineEvaluate - Evaluates a string in MATLAB
101 
102     Not Collective
103 
104     Input Parameters:
105 +   mengine - the MATLAB engine
106 -   string - format as in a printf()
107 
108    Level: advanced
109 
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];
118   PetscErrorCode ierr;
119   size_t         fullLength;
120 
121   PetscFunctionBegin;
122   va_start(Argp,string);
123   ierr = PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);CHKERRQ(ierr);
124   va_end(Argp);
125 
126   ierr = PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);CHKERRQ(ierr);
127   engEvalString(mengine->ep, buffer);
128 
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);
133 
134   ierr = PetscInfo1(0,"Done evaluating Matlab string: %s\n",buffer);CHKERRQ(ierr);
135   PetscFunctionReturn(0);
136 }
137 
138 /*@C
139     PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
140           printed
141 
142     Not Collective
143 
144     Input Parameter:
145 .   mengine - the MATLAB engine
146 
147     Output Parameter:
148 .   string - buffer where MATLAB output is printed
149 
150    Level: advanced
151 
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 {
158   PetscFunctionBegin;
159   *string = mengine->buffer;
160   PetscFunctionReturn(0);
161 }
162 
163 /*@C
164     PetscMatlabEnginePrintOutput - prints the output from MATLAB
165 
166     Collective on PetscMatlabEngine
167 
168     Input Parameters:
169 .    mengine - the Matlab engine
170 
171    Level: advanced
172 
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 {
179   PetscErrorCode ierr;
180   PetscMPIInt    rank;
181 
182   PetscFunctionBegin;
183   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);CHKERRQ(ierr);
184   ierr = PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);CHKERRQ(ierr);
185   ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);CHKERRQ(ierr);
186   PetscFunctionReturn(0);
187 }
188 
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.
192 
193     Collective on PetscObject
194 
195     Input Parameters:
196 +    mengine - the MATLAB engine
197 -    object - the PETSc object, for example Vec
198 
199    Level: advanced
200 
201 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
202           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
203           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
204 @*/
205 PetscErrorCode  PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
206 {
207   PetscErrorCode ierr,(*put)(PetscObject,void*);
208 
209   PetscFunctionBegin;
210   ierr = PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);CHKERRQ(ierr);
211   if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
212   ierr = PetscInfo(0,"Putting MATLAB object\n");CHKERRQ(ierr);
213   ierr = (*put)(obj,mengine->ep);CHKERRQ(ierr);
214   ierr = PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);CHKERRQ(ierr);
215   PetscFunctionReturn(0);
216 }
217 
218 /*@
219     PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.
220 
221     Collective on PetscObject
222 
223     Input Parameters:
224 +    mengine - the MATLAB engine
225 -    object - the PETSc object, for example Vec
226 
227    Level: advanced
228 
229 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
230           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
231           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine
232 @*/
233 PetscErrorCode  PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
234 {
235   PetscErrorCode ierr,(*get)(PetscObject,void*);
236 
237   PetscFunctionBegin;
238   if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
239   ierr = PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);CHKERRQ(ierr);
240   if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
241   ierr = PetscInfo(0,"Getting MATLAB object\n");CHKERRQ(ierr);
242   ierr = (*get)(obj,mengine->ep);CHKERRQ(ierr);
243   ierr = PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);CHKERRQ(ierr);
244   PetscFunctionReturn(0);
245 }
246 
247 /*
248     The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
249   is attached to a communicator, in this case the attribute is a PetscMatlabEngine
250 */
251 static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;
252 
253 
254 /*@C
255    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
256                     in a communicator.
257 
258    Not Collective
259 
260    Input Parameter:
261 .  comm - the MPI communicator to share the engine
262 
263    Level: developer
264 
265    Notes:
266    Unlike almost all other PETSc routines, this does not return
267    an error code. Usually used in the form
268 $      PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));
269 
270 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
271           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
272           PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
273           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
274 
275 @*/
276 PetscMatlabEngine  PETSC_MATLAB_ENGINE_(MPI_Comm comm)
277 {
278   PetscErrorCode    ierr;
279   PetscBool         flg;
280   PetscMatlabEngine mengine;
281 
282   PetscFunctionBegin;
283   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
284     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
285     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
286   }
287   ierr = MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
288   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
289   if (!flg) { /* viewer not yet created */
290     char *machinename = 0,machine[64];
291 
292     ierr = PetscOptionsGetString(NULL,NULL,"-matlab_engine_machine",machine,64,&flg);
293     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
294     if (flg) machinename = machine;
295     ierr = PetscMatlabEngineCreate(comm,machinename,&mengine);
296     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
297     ierr = PetscObjectRegisterDestroy((PetscObject)mengine);
298     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
299     ierr = MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine);
300     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
301   }
302   PetscFunctionReturn(mengine);
303 }
304 
305 /*@C
306     PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects,
307       each processors part is put in a separate  MATLAB process.
308 
309     Collective on PetscObject
310 
311     Input Parameters:
312 +    mengine - the MATLAB engine
313 .    m,n - the dimensions of the array
314 .    array - the array (represented in one dimension)
315 -    name - the name of the array
316 
317    Level: advanced
318 
319 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
320           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
321           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), MatlabEngineGetArray(), PetscMatlabEngine
322 @*/
323 PetscErrorCode  PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
324 {
325   PetscErrorCode ierr;
326   mxArray        *mat;
327 
328   PetscFunctionBegin;
329   ierr = PetscInfo1(0,"Putting MATLAB array %s\n",name);CHKERRQ(ierr);
330 #if !defined(PETSC_USE_COMPLEX)
331   mat = mxCreateDoubleMatrix(m,n,mxREAL);
332 #else
333   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
334 #endif
335   ierr = PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));CHKERRQ(ierr);
336   engPutVariable(mengine->ep,name,mat);
337 
338   ierr = PetscInfo1(0,"Put MATLAB array %s\n",name);CHKERRQ(ierr);
339   PetscFunctionReturn(0);
340 }
341 
342 /*@C
343     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array
344 
345     Not Collective
346 
347     Input Parameters:
348 +    mengine - the Matlab engine
349 .    m,n - the dimensions of the array
350 .    array - the array (represented in one dimension)
351 -    name - the name of the array
352 
353    Level: advanced
354 
355 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
356           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
357           PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
358 @*/
359 PetscErrorCode  PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
360 {
361   PetscErrorCode ierr;
362   mxArray        *mat;
363 
364   PetscFunctionBegin;
365   ierr = PetscInfo1(0,"Getting MATLAB array %s\n",name);CHKERRQ(ierr);
366   mat  = engGetVariable(mengine->ep,name);
367   if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
368   ierr = PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));CHKERRQ(ierr);
369   ierr = PetscInfo1(0,"Got MATLAB array %s\n",name);CHKERRQ(ierr);
370   PetscFunctionReturn(0);
371 }
372 
373 
374 
375 
376