Actual source code: matlab.c
2: #include <engine.h> /* MATLAB include file */
3: #include <petscsys.h>
4: #include <petscmatlab.h>
5: #include <petsc/private/petscimpl.h>
7: struct _p_PetscMatlabEngine {
8: PETSCHEADER(int);
9: Engine *ep;
10: char buffer[1024];
11: };
13: PetscClassId MATLABENGINE_CLASSID = -1;
15: /*@C
16: PetscMatlabEngineCreate - Creates a MATLAB engine object
18: Not Collective
20: Input Parameters:
21: + comm - a separate MATLAB engine is started for each process in the communicator
22: - host - name of machine where MATLAB engine is to be run (usually NULL)
24: Output Parameter:
25: . mengine - the resulting object
27: Options Database:
28: + -matlab_engine_graphics - allow the MATLAB engine to display graphics
29: . -matlab_engine_host - hostname, machine to run the MATLAB engine on
30: - -info - print out all requests to MATLAB and all if its responses (for debugging)
32: Level: advanced
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 host[],PetscMatlabEngine *mengine)
39: {
40: PetscErrorCode ierr;
41: PetscMPIInt rank,size;
42: char buffer[256];
43: PetscMatlabEngine e;
44: PetscBool flg = PETSC_FALSE;
47: if (MATLABENGINE_CLASSID == -1) {
48: PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);
49: }
50: PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);
52: if (!host) {
53: char lhost[64];
55: PetscOptionsGetString(NULL,NULL,"-matlab_engine_host",lhost,sizeof(lhost),&flg);
56: if (flg) {host = lhost;}
57: }
58: flg = PETSC_FALSE;
59: PetscOptionsGetBool(NULL,NULL,"-matlab_engine_graphics",&flg,NULL);
61: if (host) {
62: PetscInfo1(0,"Starting MATLAB engine on %s\n",host);
63: } else {
65: }
66: if (host) {
67: PetscStrcpy(buffer,"ssh ");
68: PetscStrcat(buffer,host);
69: PetscStrcat(buffer," \"");
70: PetscStrlcat(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
71: if (!flg) {
72: PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
73: }
74: PetscStrlcat(buffer," -nosplash ",sizeof(buffer));
75: PetscStrcat(buffer,"\"");
76: } else {
77: PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
78: if (!flg) {
79: PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
80: }
81: PetscStrlcat(buffer," -nosplash ",sizeof(buffer));
82: }
83: PetscInfo1(0,"Starting MATLAB engine with command %s\n",buffer);
84: e->ep = engOpen(buffer);
85: if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine with %s",buffer);
86: engOutputBuffer(e->ep,e->buffer,sizeof(e->buffer));
87: if (host) {
88: PetscInfo1(0,"Started MATLAB engine on %s\n",host);
89: } else {
90: PetscInfo(0,"Started MATLAB engine\n");
91: }
93: MPI_Comm_rank(comm,&rank);
94: MPI_Comm_size(comm,&size);
95: PetscMatlabEngineEvaluate(e,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
96: *mengine = e;
97: return(0);
98: }
100: /*@
101: PetscMatlabEngineDestroy - Shuts down a MATLAB engine.
103: Collective on PetscMatlabEngine
105: Input Parameters:
106: . e - the engine
108: Level: advanced
110: .seealso: PetscMatlabEngineCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
111: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
112: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
113: @*/
114: PetscErrorCode PetscMatlabEngineDestroy(PetscMatlabEngine *v)
115: {
119: if (!*v) return(0);
121: if (--((PetscObject)(*v))->refct > 0) return(0);
122: PetscInfo(0,"Stopping MATLAB engine\n");
123: engClose((*v)->ep);
124: if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error closing Matlab engine");
125: PetscInfo(0,"MATLAB engine stopped\n");
126: PetscHeaderDestroy(v);
127: return(0);
128: }
130: /*@C
131: PetscMatlabEngineEvaluate - Evaluates a string in MATLAB
133: Not Collective
135: Input Parameters:
136: + mengine - the MATLAB engine
137: - string - format as in a printf()
139: Notes:
140: Run the PETSc program with -info to always have printed back MATLAB's response to the string evaluation
142: Level: advanced
144: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
145: PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
146: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
147: @*/
148: PetscErrorCode PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
149: {
150: va_list Argp;
151: char buffer[1024];
153: size_t fullLength;
156: va_start(Argp,string);
157: PetscVSNPrintf(buffer,sizeof(buffer)-9-5,string,&fullLength,Argp);
158: va_end(Argp);
160: PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);
161: engEvalString(mengine->ep, buffer);
162: PetscInfo1(0,"Done evaluating MATLAB string: %s\n",buffer);
163: PetscInfo1(0," MATLAB output message: %s\n",mengine->buffer);
165: /*
166: Check for error in MATLAB: indicated by ? as first character in engine->buffer
167: */
168: if (mengine->buffer[4] == '?') SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in evaluating MATLAB command:%s\n%s",string,mengine->buffer);
169: return(0);
170: }
172: /*@C
173: PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
174: printed
176: Not Collective
178: Input Parameter:
179: . mengine - the MATLAB engine
181: Output Parameter:
182: . string - buffer where MATLAB output is printed
184: Level: advanced
186: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
187: PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
188: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
189: @*/
190: PetscErrorCode PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
191: {
193: if (!mengine) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_MATLAB_ENGINE_() failed");
194: *string = mengine->buffer;
195: return(0);
196: }
198: /*@C
199: PetscMatlabEnginePrintOutput - prints the output from MATLAB
201: Collective on PetscMatlabEngine
203: Input Parameters:
204: . mengine - the Matlab engine
206: Level: advanced
208: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
209: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
210: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
211: @*/
212: PetscErrorCode PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
213: {
215: PetscMPIInt rank;
218: if (!mengine) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_MATLAB_ENGINE_() failed");
219: MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);
220: PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);
221: PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);
222: return(0);
223: }
225: /*@
226: PetscMatlabEnginePut - Puts a Petsc object into the MATLAB space. For parallel objects,
227: each processors part is put in a separate MATLAB process.
229: Collective on PetscObject
231: Input Parameters:
232: + mengine - the MATLAB engine
233: - object - the PETSc object, for example Vec
235: Level: advanced
237: Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space
238: (this is because MATLAB uses compressed column format and PETSc uses compressed row format)
240: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
241: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
242: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
243: @*/
244: PetscErrorCode PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
245: {
246: PetscErrorCode ierr,(*put)(PetscObject,void*);
249: if (!mengine) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_MATLAB_ENGINE_() failed");
250: PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);
251: if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
252: PetscInfo(0,"Putting MATLAB object\n");
253: (*put)(obj,mengine->ep);
254: PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);
255: return(0);
256: }
258: /*@
259: PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.
261: Collective on PetscObject
263: Input Parameters:
264: + mengine - the MATLAB engine
265: - object - the PETSc object, for example Vec
267: Level: advanced
269: Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space
270: (this is because MATLAB uses compressed column format and PETSc uses compressed row format)
272: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
273: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
274: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
275: @*/
276: PetscErrorCode PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
277: {
278: PetscErrorCode ierr,(*get)(PetscObject,void*);
281: if (!mengine) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_MATLAB_ENGINE_() failed");
282: if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
283: PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);
284: if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
285: PetscInfo(0,"Getting MATLAB object\n");
286: (*get)(obj,mengine->ep);
287: PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);
288: return(0);
289: }
291: /*
292: The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
293: is attached to a communicator, in this case the attribute is a PetscMatlabEngine
294: */
295: static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;
298: /*@C
299: PETSC_MATLAB_ENGINE_ - Creates a MATLAB engine on each process in a communicator.
301: Not Collective
303: Input Parameter:
304: . comm - the MPI communicator to share the engine
306: Options Database:
307: . -matlab_engine_host - hostname
309: Level: developer
311: Notes:
312: Unlike almost all other PETSc routines, this does not return
313: an error code. Usually used in the form
314: $ PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));
316: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
317: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
318: PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
319: PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
321: @*/
322: PetscMatlabEngine PETSC_MATLAB_ENGINE_(MPI_Comm comm)
323: {
324: PetscErrorCode ierr;
325: PetscBool flg;
326: PetscMatlabEngine mengine;
329: if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
330: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
331: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
332: }
333: MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
334: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
335: if (!flg) { /* viewer not yet created */
336: PetscMatlabEngineCreate(comm,NULL,&mengine);
337: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
338: PetscObjectRegisterDestroy((PetscObject)mengine);
339: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
340: MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine);
341: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
342: }
343: PetscFunctionReturn(mengine);
344: }
346: /*@C
347: PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects,
348: each processors part is put in a separate MATLAB process.
350: Collective on PetscObject
352: Input Parameters:
353: + mengine - the MATLAB engine
354: . m,n - the dimensions of the array
355: . array - the array (represented in one dimension)
356: - name - the name of the array
358: Level: advanced
360: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
361: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
362: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), PetscMatlabEngineGetArray(), PetscMatlabEngine
363: @*/
364: PetscErrorCode PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
365: {
367: mxArray *mat;
370: if (!mengine) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_MATLAB_ENGINE_() failed");
371: PetscInfo1(0,"Putting MATLAB array %s\n",name);
372: #if !defined(PETSC_USE_COMPLEX)
373: mat = mxCreateDoubleMatrix(m,n,mxREAL);
374: #else
375: mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
376: #endif
377: PetscArraycpy(mxGetPr(mat),array,m*n);
378: engPutVariable(mengine->ep,name,mat);
380: PetscInfo1(0,"Put MATLAB array %s\n",name);
381: return(0);
382: }
384: /*@C
385: PetscMatlabEngineGetArray - Gets a variable from MATLAB into an array
387: Not Collective
389: Input Parameters:
390: + mengine - the MATLAB engine
391: . m,n - the dimensions of the array
392: . array - the array (represented in one dimension)
393: - name - the name of the array
395: Level: advanced
397: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
398: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
399: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine
400: @*/
401: PetscErrorCode PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[])
402: {
404: mxArray *mat;
407: if (!mengine) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_MATLAB_ENGINE_() failed");
408: PetscInfo1(0,"Getting MATLAB array %s\n",name);
409: mat = engGetVariable(mengine->ep,name);
410: if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
411: if (mxGetM(mat) != (size_t) m) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"Array %s in MATLAB first dimension %d does not match requested size %d",name,(int)mxGetM(mat),m);
412: if (mxGetN(mat) != (size_t) n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"Array %s in MATLAB second dimension %d does not match requested size %d",name,(int)mxGetN(mat),m);
413: PetscArraycpy(array,mxGetPr(mat),m*n);
414: PetscInfo1(0,"Got MATLAB array %s\n",name);
415: return(0);
416: }