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