Actual source code: vmatlab.c
2: #include <petsc/private/viewerimpl.h>
3: #include <mat.h>
5: typedef struct {
6: MATFile *ep;
7: PetscMPIInt rank;
8: PetscFileMode btype;
9: } PetscViewer_Matlab;
11: /*@C
12: PetscViewerMatlabPutArray - Puts an array into the `PETSCVIEWERMATLAB` viewer.
14: Not Collective: only processor zero saves `array`
16: Input Parameters:
17: + mfile - the viewer
18: . m - the first dimensions of `array`
19: . n - the second dimensions of `array`
20: . array - the array (represented in one dimension)
21: - name - the MATLAB name of `array`
23: Level: advanced
25: Note:
26: Only writes `array` values on processor 0.
28: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerMatlabGetArray()`
29: @*/
30: PetscErrorCode PetscViewerMatlabPutArray(PetscViewer mfile, int m, int n, const PetscScalar *array, const char *name)
31: {
32: PetscViewer_Matlab *ml;
33: mxArray *mat;
35: PetscFunctionBegin;
36: PetscCheck(mfile, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null argument: probably PETSC_VIEWER_MATLAB_() failed");
37: ml = (PetscViewer_Matlab *)mfile->data;
38: if (!ml->rank) {
39: PetscCall(PetscInfo(mfile, "Putting MATLAB array %s\n", name));
40: #if !defined(PETSC_USE_COMPLEX)
41: mat = mxCreateDoubleMatrix(m, n, mxREAL);
42: #else
43: mat = mxCreateDoubleMatrix(m, n, mxCOMPLEX);
44: #endif
45: PetscCall(PetscArraycpy(mxGetPr(mat), array, m * n));
46: matPutVariable(ml->ep, name, mat);
48: PetscCall(PetscInfo(mfile, "Put MATLAB array %s\n", name));
49: }
50: PetscFunctionReturn(PETSC_SUCCESS);
51: }
53: PetscErrorCode PetscViewerMatlabPutVariable(PetscViewer viewer, const char *name, void *mat)
54: {
55: PetscViewer_Matlab *ml = (PetscViewer_Matlab *)viewer->data;
57: PetscFunctionBegin;
58: matPutVariable(ml->ep, name, (mxArray *)mat);
59: PetscFunctionReturn(PETSC_SUCCESS);
60: }
62: /*@C
63: PetscViewerMatlabGetArray - Gets a variable from a `PETSCVIEWERMATLAB` viewer into an array
65: Not Collective; only processor zero reads in the array
67: Input Parameters:
68: + mfile - the MATLAB file viewer
69: . m - the first dimensions of `array`
70: . n - the second dimensions of `array`
71: . array - the array (represented in one dimension)
72: - name - the MATLAB name of `array`
74: Level: advanced
76: Note:
77: Only reads in `array` values on processor 0.
79: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerMatlabPutArray()`
80: @*/
81: PetscErrorCode PetscViewerMatlabGetArray(PetscViewer mfile, int m, int n, PetscScalar *array, const char *name)
82: {
83: PetscViewer_Matlab *ml;
84: mxArray *mat;
86: PetscFunctionBegin;
87: PetscCheck(mfile, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null argument: probably PETSC_VIEWER_MATLAB_() failed");
88: ml = (PetscViewer_Matlab *)mfile->data;
89: if (!ml->rank) {
90: PetscCall(PetscInfo(mfile, "Getting MATLAB array %s\n", name));
91: mat = matGetVariable(ml->ep, name);
92: PetscCheck(mat, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to get array %s from matlab", name);
93: PetscCall(PetscArraycpy(array, mxGetPr(mat), m * n));
94: PetscCall(PetscInfo(mfile, "Got MATLAB array %s\n", name));
95: }
96: PetscFunctionReturn(PETSC_SUCCESS);
97: }
99: PetscErrorCode PetscViewerFileSetMode_Matlab(PetscViewer viewer, PetscFileMode type)
100: {
101: PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab *)viewer->data;
103: PetscFunctionBegin;
104: vmatlab->btype = type;
105: PetscFunctionReturn(PETSC_SUCCESS);
106: }
108: /*
109: Actually opens the file
110: */
111: PetscErrorCode PetscViewerFileSetName_Matlab(PetscViewer viewer, const char name[])
112: {
113: PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab *)viewer->data;
114: PetscFileMode type = vmatlab->btype;
116: PetscFunctionBegin;
117: PetscCheck(type != (PetscFileMode)-1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
118: if (vmatlab->ep) matClose(vmatlab->ep);
120: /* only first processor opens file */
121: if (!vmatlab->rank) {
122: if (type == FILE_MODE_READ) vmatlab->ep = matOpen(name, "r");
123: else if (type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name, "w");
124: else {
125: PetscCheck(type != FILE_MODE_UNDEFINED, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
126: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[type]);
127: }
128: }
129: PetscFunctionReturn(PETSC_SUCCESS);
130: }
132: PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
133: {
134: PetscViewer_Matlab *vf = (PetscViewer_Matlab *)v->data;
136: PetscFunctionBegin;
137: if (vf->ep) matClose(vf->ep);
138: PetscCall(PetscFree(vf));
139: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL));
140: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL));
141: PetscFunctionReturn(PETSC_SUCCESS);
142: }
144: /*MC
145: PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB
146: with load('filename').
148: Level: intermediate
150: Notes:
151: Currently can only save PETSc vectors to .mat files, not matrices (use the `PETSCVIEWERBINARY` and
152: ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB).
154: For parallel vectors obtained with `DMCreateGlobalVector()` or `DMGetGlobalVector()` the vectors are saved to
155: the .mat file in natural ordering. You can use DMView() to save the `DMDA` information to the .mat file
156: the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB
157: vector to the same multidimensional shape as it had in PETSc for plotting etc. For example,
159: In your PETSc C/C++ code (assuming a two dimensional `DMDA` with one degree of freedom per node)
160: .vb
161: PetscObjectSetName((PetscObject)x,"x");
162: VecView(x,PETSC_VIEWER_MATLAB_WORLD);
163: PetscObjectSetName((PetscObject)da,"da");
164: DMView(x,PETSC_VIEWER_MATLAB_WORLD);
165: .ve
166: Then from MATLAB
167: .vb
168: load('matlaboutput.mat') % matlaboutput.mat is the default filename
169: xnew = zeros(da.n,da.m);
170: xnew(:) = x; % reshape one dimensional vector back to two dimensions
171: .ve
173: If you wish to put the same variable into the .mat file several times you need to give it a new
174: name before each call to view.
176: Use `PetscViewerMatlabPutArray()` to just put an array of doubles into the .mat file
178: .seealso: `PETSC_VIEWER_MATLAB_()`, `PETSC_VIEWER_MATLAB_SELF`, `PETSC_VIEWER_MATLAB_WORLD`, `PetscViewerCreate()`,
179: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERASCII`, `PETSCVIEWERDRAW`,
180: `PETSC_VIEWER_STDOUT_()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscMatlabEngine`
181: M*/
182: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer)
183: {
184: PetscViewer_Matlab *e;
186: PetscFunctionBegin;
187: PetscCall(PetscNew(&e));
188: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &e->rank));
189: e->btype = FILE_MODE_UNDEFINED;
190: viewer->data = (void *)e;
192: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_Matlab));
193: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Matlab));
195: viewer->ops->destroy = PetscViewerDestroy_Matlab;
196: PetscFunctionReturn(PETSC_SUCCESS);
197: }
199: /*@C
200: PetscViewerMatlabOpen - Opens a Matlab .mat file for output
202: Collective
204: Input Parameters:
205: + comm - MPI communicator
206: . name - name of file
207: - type - type of file
208: .vb
209: FILE_MODE_WRITE - create new file for MATLAB output
210: FILE_MODE_READ - open existing file for MATLAB input
211: FILE_MODE_WRITE - open existing file for MATLAB output
212: .ve
214: Output Parameter:
215: . binv - PetscViewer for MATLAB output to use with the specified file
217: Level: beginner
219: Notes:
220: This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.
222: For writing files it only opens the file on processor 0 in the communicator.
224: This only saves `Vec`s it cannot be used to save `Mat`s. We recommend using the `PETSCVIEWERBINARY` to save objects to be loaded into MATLAB
225: instead of this routine.
227: PETSc must be configured with the option `--with-matlab` for this functionality
229: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`
230: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`
231: @*/
232: PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *binv)
233: {
234: PetscFunctionBegin;
235: PetscCall(PetscViewerCreate(comm, binv));
236: PetscCall(PetscViewerSetType(*binv, PETSCVIEWERMATLAB));
237: PetscCall(PetscViewerFileSetMode(*binv, type));
238: PetscCall(PetscViewerFileSetName(*binv, name));
239: PetscFunctionReturn(PETSC_SUCCESS);
240: }
242: static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
244: /*@C
245: PETSC_VIEWER_MATLAB_ - Creates a `PETSCVIEWERMATLAB` `PetscViewer` shared by all processors
246: in a communicator.
248: Collective
250: Input Parameter:
251: . comm - the MPI communicator to share the Matlab `PetscViewer`
253: Options Database Key:
254: . -viewer_matlab_filename <name> - name of the Matlab file
256: Environmental variable:
257: . `PETSC_VIEWER_MATLAB_FILENAME` - name of the Matlab file
259: Level: intermediate
261: Note:
262: Unlike almost all other PETSc routines, `PETSC_VIEWER_MATLAB_()` does not return
263: an error code. The matlab PetscViewer is usually used in the form
264: $ XXXView(XXX object, PETSC_VIEWER_MATLAB_(comm));
266: Use `PETSC_VIEWER_SOCKET_()` or `PetscViewerSocketOpen()` to communicator with an interactive MATLAB session.
268: .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`,
269: `PetscViewerDestroy()`
270: @*/
271: PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm)
272: {
273: PetscErrorCode ierr;
274: PetscBool flg;
275: PetscViewer viewer;
276: char fname[PETSC_MAX_PATH_LEN];
277: MPI_Comm ncomm;
279: PetscFunctionBegin;
280: ierr = PetscCommDuplicate(comm, &ncomm, NULL);
281: if (ierr) {
282: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
283: PetscFunctionReturn(NULL);
284: }
285: if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
286: ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Matlab_keyval, 0);
287: if (ierr) {
288: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
289: PetscFunctionReturn(NULL);
290: }
291: }
292: ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void **)&viewer, (int *)&flg);
293: if (ierr) {
294: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
295: PetscFunctionReturn(NULL);
296: }
297: if (!flg) { /* PetscViewer not yet created */
298: ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_MATLAB_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
299: if (ierr) {
300: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
301: PetscFunctionReturn(NULL);
302: }
303: if (!flg) {
304: ierr = PetscStrncpy(fname, "matlaboutput.mat", sizeof(fname));
305: if (ierr) {
306: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
307: PetscFunctionReturn(NULL);
308: }
309: }
310: ierr = PetscViewerMatlabOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
311: if (ierr) {
312: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
313: PetscFunctionReturn(NULL);
314: }
315: ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
316: if (ierr) {
317: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
318: PetscFunctionReturn(NULL);
319: }
320: ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void *)viewer);
321: if (ierr) {
322: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
323: PetscFunctionReturn(NULL);
324: }
325: }
326: ierr = PetscCommDestroy(&ncomm);
327: if (ierr) {
328: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_MATLAB_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
329: PetscFunctionReturn(NULL);
330: }
331: PetscFunctionReturn(viewer);
332: }