xref: /petsc/src/sys/classes/matlabengine/matlab.c (revision ddcfb6fc814de002685263716f916f1eccaf9f7f)
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    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)
203 
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*);
211 
212   PetscFunctionBegin;
213   ierr = PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);CHKERRQ(ierr);
214   if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
215   ierr = PetscInfo(0,"Putting MATLAB object\n");CHKERRQ(ierr);
216   ierr = (*put)(obj,mengine->ep);CHKERRQ(ierr);
217   ierr = PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);CHKERRQ(ierr);
218   PetscFunctionReturn(0);
219 }
220 
221 /*@
222     PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.
223 
224     Collective on PetscObject
225 
226     Input Parameters:
227 +    mengine - the MATLAB engine
228 -    object - the PETSc object, for example Vec
229 
230    Level: advanced
231 
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)
234 
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*);
242 
243   PetscFunctionBegin;
244   if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
245   ierr = PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);CHKERRQ(ierr);
246   if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
247   ierr = PetscInfo(0,"Getting MATLAB object\n");CHKERRQ(ierr);
248   ierr = (*get)(obj,mengine->ep);CHKERRQ(ierr);
249   ierr = PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);CHKERRQ(ierr);
250   PetscFunctionReturn(0);
251 }
252 
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;
258 
259 
260 /*@C
261    PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
262                     in a communicator.
263 
264    Not Collective
265 
266    Input Parameter:
267 .  comm - the MPI communicator to share the engine
268 
269    Level: developer
270 
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));
275 
276 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
277           PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
278           PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
279           PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
280 
281 @*/
282 PetscMatlabEngine  PETSC_MATLAB_ENGINE_(MPI_Comm comm)
283 {
284   PetscErrorCode    ierr;
285   PetscBool         flg;
286   PetscMatlabEngine mengine;
287 
288   PetscFunctionBegin;
289   if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
290     ierr = 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   ierr = 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];
297 
298     ierr = 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     ierr = 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     ierr = PetscObjectRegisterDestroy((PetscObject)mengine);
304     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
305     ierr = 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 }
310 
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.
314 
315     Collective on PetscObject
316 
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
322 
323    Level: advanced
324 
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 {
331   PetscErrorCode ierr;
332   mxArray        *mat;
333 
334   PetscFunctionBegin;
335   ierr = PetscInfo1(0,"Putting MATLAB array %s\n",name);CHKERRQ(ierr);
336 #if !defined(PETSC_USE_COMPLEX)
337   mat = mxCreateDoubleMatrix(m,n,mxREAL);
338 #else
339   mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
340 #endif
341   ierr = PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));CHKERRQ(ierr);
342   engPutVariable(mengine->ep,name,mat);
343 
344   ierr = PetscInfo1(0,"Put MATLAB array %s\n",name);CHKERRQ(ierr);
345   PetscFunctionReturn(0);
346 }
347 
348 /*@C
349     PetscMatlabEngineGetArray - Gets a variable from Matlab into an array
350 
351     Not Collective
352 
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
358 
359    Level: advanced
360 
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 {
367   PetscErrorCode ierr;
368   mxArray        *mat;
369 
370   PetscFunctionBegin;
371   ierr = PetscInfo1(0,"Getting MATLAB array %s\n",name);CHKERRQ(ierr);
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   ierr = PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));CHKERRQ(ierr);
375   ierr = PetscInfo1(0,"Got MATLAB array %s\n",name);CHKERRQ(ierr);
376   PetscFunctionReturn(0);
377 }
378 
379 
380 
381 
382