Actual source code: matlab.c
petsc-3.14.6 2021-03-30
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: - machine - 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
30: Level: advanced
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,mgiven = PETSC_TRUE;
45: if (MATLABENGINE_CLASSID == -1) {
46: PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);
47: }
48: PetscOptionsGetBool(NULL,NULL,"-matlab_engine_graphics",&flg,NULL);
50: PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);
52: if (!machine) {
53: machine = "\0";
54: mgiven = PETSC_FALSE;
55: }
56: PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));
57: if (!flg) {
58: PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));
59: }
60: PetscStrlcat(buffer," -nosplash ",sizeof(buffer));
61: if (mgiven) {
62: PetscInfo2(0,"Starting MATLAB engine on %s with command %s\n",machine,buffer);
63: } else {
64: PetscInfo1(0,"Starting MATLAB engine with command %s\n",buffer);
65: }
66: e->ep = engOpen(buffer);
67: if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine on %s",machine);
68: engOutputBuffer(e->ep,e->buffer,1024);
70: MPI_Comm_rank(comm,&rank);
71: MPI_Comm_size(comm,&size);
72: sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size);
73: engEvalString(e->ep, buffer);
74: if (mgiven) {
75: PetscInfo1(0,"Started MATLAB engine on %s\n",machine);
76: } else {
77: PetscInfo(0,"Started MATLAB engine\n");
78: }
79: *mengine = e;
80: return(0);
81: }
83: /*@
84: PetscMatlabEngineDestroy - Shuts down a Matlab engine.
86: Collective on PetscMatlabEngine
88: Input Parameters:
89: . e - the engine
91: Level: advanced
93: .seealso: PetscMatlabEngineCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
94: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
95: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
96: @*/
97: PetscErrorCode PetscMatlabEngineDestroy(PetscMatlabEngine *v)
98: {
102: if (!*v) return(0);
104: if (--((PetscObject)(*v))->refct > 0) return(0);
105: PetscInfo(0,"Stopping MATLAB engine\n");
106: engClose((*v)->ep);
107: if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error closing Matlab engine");
108: PetscInfo(0,"MATLAB engine stopped\n");
109: PetscHeaderDestroy(v);
110: return(0);
111: }
113: /*@C
114: PetscMatlabEngineEvaluate - Evaluates a string in MATLAB
116: Not Collective
118: Input Parameters:
119: + mengine - the MATLAB engine
120: - string - format as in a printf()
122: Level: advanced
124: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
125: PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
126: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
127: @*/
128: PetscErrorCode PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...)
129: {
130: va_list Argp;
131: char buffer[1024];
133: size_t fullLength;
136: va_start(Argp,string);
137: PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);
138: va_end(Argp);
140: PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);
141: engEvalString(mengine->ep, buffer);
143: /*
144: Check for error in MATLAB: indicated by ? as first character in engine->buffer
145: */
146: if (mengine->buffer[4] == '?') SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in evaluating MATLAB command:%s\n%s",string,mengine->buffer);
148: PetscInfo1(0,"Done evaluating Matlab string: %s\n",buffer);
149: return(0);
150: }
152: /*@C
153: PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is
154: printed
156: Not Collective
158: Input Parameter:
159: . mengine - the MATLAB engine
161: Output Parameter:
162: . string - buffer where MATLAB output is printed
164: Level: advanced
166: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
167: PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(),
168: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
169: @*/
170: PetscErrorCode PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string)
171: {
173: *string = mengine->buffer;
174: return(0);
175: }
177: /*@C
178: PetscMatlabEnginePrintOutput - prints the output from MATLAB
180: Collective on PetscMatlabEngine
182: Input Parameters:
183: . mengine - the Matlab engine
185: Level: advanced
187: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
188: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(),
189: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
190: @*/
191: PetscErrorCode PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd)
192: {
194: PetscMPIInt rank;
197: MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);
198: PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);
199: PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);
200: return(0);
201: }
203: /*@
204: PetscMatlabEnginePut - Puts a Petsc object into the MATLAB space. For parallel objects,
205: each processors part is put in a separate MATLAB process.
207: Collective on PetscObject
209: Input Parameters:
210: + mengine - the MATLAB engine
211: - object - the PETSc object, for example Vec
213: Level: advanced
215: Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space
216: (this is because MATLAB uses compressed column format and PETSc uses compressed row format)
218: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
219: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
220: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
221: @*/
222: PetscErrorCode PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj)
223: {
224: PetscErrorCode ierr,(*put)(PetscObject,void*);
227: PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);
228: if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name);
229: PetscInfo(0,"Putting MATLAB object\n");
230: (*put)(obj,mengine->ep);
231: PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);
232: return(0);
233: }
235: /*@
236: PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object.
238: Collective on PetscObject
240: Input Parameters:
241: + mengine - the MATLAB engine
242: - object - the PETSc object, for example Vec
244: Level: advanced
246: Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space
247: (this is because MATLAB uses compressed column format and PETSc uses compressed row format)
249: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(),
250: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
251: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine
252: @*/
253: PetscErrorCode PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj)
254: {
255: PetscErrorCode ierr,(*get)(PetscObject,void*);
258: if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name");
259: PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);
260: if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name);
261: PetscInfo(0,"Getting MATLAB object\n");
262: (*get)(obj,mengine->ep);
263: PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);
264: return(0);
265: }
267: /*
268: The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that
269: is attached to a communicator, in this case the attribute is a PetscMatlabEngine
270: */
271: static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID;
274: /*@C
275: PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors
276: in a communicator.
278: Not Collective
280: Input Parameter:
281: . comm - the MPI communicator to share the engine
283: Level: developer
285: Notes:
286: Unlike almost all other PETSc routines, this does not return
287: an error code. Usually used in the form
288: $ PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm));
290: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(),
291: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
292: PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine,
293: PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF
295: @*/
296: PetscMatlabEngine PETSC_MATLAB_ENGINE_(MPI_Comm comm)
297: {
298: PetscErrorCode ierr;
299: PetscBool flg;
300: PetscMatlabEngine mengine;
303: if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) {
304: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0);
305: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
306: }
307: MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg);
308: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
309: if (!flg) { /* viewer not yet created */
310: char *machinename = 0,machine[64];
312: PetscOptionsGetString(NULL,NULL,"-matlab_engine_machine",machine,sizeof(machine),&flg);
313: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
314: if (flg) machinename = machine;
315: PetscMatlabEngineCreate(comm,machinename,&mengine);
316: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
317: PetscObjectRegisterDestroy((PetscObject)mengine);
318: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
319: MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine);
320: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;}
321: }
322: PetscFunctionReturn(mengine);
323: }
325: /*@C
326: PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects,
327: each processors part is put in a separate MATLAB process.
329: Collective on PetscObject
331: Input Parameters:
332: + mengine - the MATLAB engine
333: . m,n - the dimensions of the array
334: . array - the array (represented in one dimension)
335: - name - the name of the array
337: Level: advanced
339: .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(),
340: PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(),
341: PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), PetscMatlabEngineGetArray(), PetscMatlabEngine
342: @*/
343: PetscErrorCode PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[])
344: {
346: mxArray *mat;
349: PetscInfo1(0,"Putting MATLAB array %s\n",name);
350: #if !defined(PETSC_USE_COMPLEX)
351: mat = mxCreateDoubleMatrix(m,n,mxREAL);
352: #else
353: mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
354: #endif
355: PetscArraycpy(mxGetPr(mat),array,m*n);
356: engPutVariable(mengine->ep,name,mat);
358: PetscInfo1(0,"Put MATLAB array %s\n",name);
359: return(0);
360: }
362: /*@C
363: PetscMatlabEngineGetArray - Gets a variable from Matlab into an array
365: Not Collective
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
373: Level: advanced
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: {
382: mxArray *mat;
385: PetscInfo1(0,"Getting MATLAB array %s\n",name);
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: 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);
389: 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);
390: PetscArraycpy(array,mxGetPr(mat),m*n);
391: PetscInfo1(0,"Got MATLAB array %s\n",name);
392: return(0);
393: }