Actual source code: vmatlab.c
1: #include <petsc/private/viewerimpl.h>
2: #include <mat.h> /*I "petscmat.h" I*/
4: typedef struct {
5: MATFile *ep;
6: PetscMPIInt rank;
7: PetscFileMode btype;
8: } PetscViewer_Matlab;
10: /*@
11: PetscViewerMatlabPutArray - Puts an array into the `PETSCVIEWERMATLAB` viewer.
13: Not Collective, only processor zero saves `array`
15: Input Parameters:
16: + mfile - the viewer
17: . m - the first dimensions of `array`
18: . n - the second 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: /*@C
53: PetscViewerMatlabPutVariable - Write a raw MATLAB `mxArray` variable into a `PETSCVIEWERMATLAB` file under a chosen name.
55: Not Collective; only processor zero writes the variable
57: Input Parameters:
58: + viewer - the `PETSCVIEWERMATLAB` viewer
59: . name - the MATLAB variable name
60: - mat - the `mxArray *` variable to write (cast to `void *`)
62: Level: advanced
64: .seealso: `PetscViewer`, `PETSCVIEWERMATLAB`, `PetscViewerMatlabPutArray()`, `PetscViewerMatlabGetArray()`, `PetscViewerMatlabOpen()`
65: @*/
66: PetscErrorCode PetscViewerMatlabPutVariable(PetscViewer viewer, const char *name, void *mat)
67: {
68: PetscViewer_Matlab *ml = (PetscViewer_Matlab *)viewer->data;
70: PetscFunctionBegin;
71: matPutVariable(ml->ep, name, (mxArray *)mat);
72: PetscFunctionReturn(PETSC_SUCCESS);
73: }
75: /*@
76: PetscViewerMatlabGetArray - Gets a variable from a `PETSCVIEWERMATLAB` viewer into an array
78: Not Collective; only processor zero reads in the array
80: Input Parameters:
81: + mfile - the MATLAB file viewer
82: . m - the first dimensions of `array`
83: . n - the second dimensions of `array`
84: . array - the array (represented in one dimension), must of be length `m` * `n`
85: - name - the MATLAB name of `array`
87: Level: advanced
89: Note:
90: Only reads in `array` values on processor 0.
92: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerMatlabPutArray()`
93: @*/
94: PetscErrorCode PetscViewerMatlabGetArray(PetscViewer mfile, int m, int n, PetscScalar array[], const char *name)
95: {
96: PetscViewer_Matlab *ml;
97: mxArray *mat;
99: PetscFunctionBegin;
100: PetscCheck(mfile, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null argument: probably PETSC_VIEWER_MATLAB_() failed");
101: ml = (PetscViewer_Matlab *)mfile->data;
102: if (!ml->rank) {
103: PetscCall(PetscInfo(mfile, "Getting MATLAB array %s\n", name));
104: mat = matGetVariable(ml->ep, name);
105: PetscCheck(mat, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to get array %s from matlab", name);
106: PetscCall(PetscArraycpy(array, mxGetPr(mat), m * n));
107: PetscCall(PetscInfo(mfile, "Got MATLAB array %s\n", name));
108: }
109: PetscFunctionReturn(PETSC_SUCCESS);
110: }
112: static PetscErrorCode PetscViewerFileSetMode_Matlab(PetscViewer viewer, PetscFileMode type)
113: {
114: PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab *)viewer->data;
116: PetscFunctionBegin;
117: vmatlab->btype = type;
118: PetscFunctionReturn(PETSC_SUCCESS);
119: }
121: /*
122: Actually opens the file
123: */
124: static PetscErrorCode PetscViewerFileSetName_Matlab(PetscViewer viewer, const char name[])
125: {
126: PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab *)viewer->data;
127: PetscFileMode type = vmatlab->btype;
129: PetscFunctionBegin;
130: PetscCheck(type != (PetscFileMode)-1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
131: if (vmatlab->ep) matClose(vmatlab->ep);
133: /* only first processor opens file */
134: if (!vmatlab->rank) {
135: if (type == FILE_MODE_READ) vmatlab->ep = matOpen(name, "r");
136: else if (type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name, "w");
137: else {
138: PetscCheck(type != FILE_MODE_UNDEFINED, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
139: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[type]);
140: }
141: }
142: PetscFunctionReturn(PETSC_SUCCESS);
143: }
145: static PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
146: {
147: PetscViewer_Matlab *vf = (PetscViewer_Matlab *)v->data;
149: PetscFunctionBegin;
150: if (vf->ep) matClose(vf->ep);
151: PetscCall(PetscFree(vf));
152: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL));
153: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL));
154: PetscFunctionReturn(PETSC_SUCCESS);
155: }
157: /*MC
158: PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB
159: with load('filename').
161: Level: intermediate
163: Notes:
164: Currently can only save PETSc vectors to .mat files, not matrices (use the `PETSCVIEWERBINARY` and
165: ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB).
167: For parallel vectors obtained with `DMCreateGlobalVector()` or `DMGetGlobalVector()` the vectors are saved to
168: the .mat file in natural ordering. You can use DMView() to save the `DMDA` information to the .mat file
169: the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB
170: vector to the same multidimensional shape as it had in PETSc for plotting etc. For example,
172: In your PETSc C/C++ code (assuming a two dimensional `DMDA` with one degree of freedom per node)
173: .vb
174: PetscObjectSetName((PetscObject)x,"x");
175: VecView(x,PETSC_VIEWER_MATLAB_WORLD);
176: PetscObjectSetName((PetscObject)da,"da");
177: DMView(x,PETSC_VIEWER_MATLAB_WORLD);
178: .ve
179: Then from MATLAB
180: .vb
181: load('matlaboutput.mat') % matlaboutput.mat is the default filename
182: xnew = zeros(da.n,da.m);
183: xnew(:) = x; % reshape one dimensional vector back to two dimensions
184: .ve
186: If you wish to put the same variable into the .mat file several times you need to give it a new
187: name before each call to view.
189: Use `PetscViewerMatlabPutArray()` to just put an array of doubles into the .mat file
191: .seealso: `PETSC_VIEWER_MATLAB_()`, `PETSC_VIEWER_MATLAB_SELF`, `PETSC_VIEWER_MATLAB_WORLD`, `PetscViewerCreate()`,
192: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERASCII`, `PETSCVIEWERDRAW`,
193: `PETSC_VIEWER_STDOUT_()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscMatlabEngine`
194: M*/
195: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer)
196: {
197: PetscViewer_Matlab *e;
199: PetscFunctionBegin;
200: PetscCall(PetscNew(&e));
201: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &e->rank));
202: e->btype = FILE_MODE_UNDEFINED;
203: viewer->data = (void *)e;
205: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_Matlab));
206: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Matlab));
208: viewer->ops->destroy = PetscViewerDestroy_Matlab;
209: PetscFunctionReturn(PETSC_SUCCESS);
210: }
212: /*@
213: PetscViewerMatlabOpen - Opens a MATLAB .mat file for output
215: Collective
217: Input Parameters:
218: + comm - MPI communicator
219: . name - name of file
220: - type - type of file
221: .vb
222: FILE_MODE_WRITE - create new file for MATLAB output
223: FILE_MODE_READ - open existing file for MATLAB input
224: FILE_MODE_WRITE - open existing file for MATLAB output
225: .ve
227: Output Parameter:
228: . binv - PetscViewer for MATLAB output to use with the specified file
230: Level: beginner
232: Notes:
233: This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.
235: For writing files it only opens the file on processor 0 in the communicator.
237: 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
238: instead of this routine.
240: PETSc must be configured with the option `--with-matlab` for this functionality
242: .seealso: `PETSCVIEWERMATLAB`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`,
243: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`
244: @*/
245: PetscErrorCode PetscViewerMatlabOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *binv)
246: {
247: PetscFunctionBegin;
248: PetscCall(PetscViewerCreate(comm, binv));
249: PetscCall(PetscViewerSetType(*binv, PETSCVIEWERMATLAB));
250: PetscCall(PetscViewerFileSetMode(*binv, type));
251: PetscCall(PetscViewerFileSetName(*binv, name));
252: PetscFunctionReturn(PETSC_SUCCESS);
253: }
255: static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
257: /*@C
258: PETSC_VIEWER_MATLAB_ - Creates a `PETSCVIEWERMATLAB` `PetscViewer` shared by all processors
259: in a communicator.
261: Collective
263: Input Parameter:
264: . comm - the MPI communicator to share the MATLAB `PetscViewer`
266: Options Database Key:
267: . -viewer_matlab_filename name - name of the MATLAB file
269: Environmental variable:
270: . `PETSC_VIEWER_MATLAB_FILENAME` - name of the MATLAB file
272: Level: intermediate
274: Notes:
275: This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
277: Unlike almost all other PETSc routines, `PETSC_VIEWER_MATLAB_()` does not return
278: an error code. The MATLAB `PetscViewer` is usually used in the form `XXXView(XXX object, PETSC_VIEWER_MATLAB_(comm))`
280: Use `PETSC_VIEWER_SOCKET_()` or `PetscViewerSocketOpen()` to communicator with an interactive MATLAB session.
282: .seealso: `PETSC_VIEWER_MATLAB_WORLD`, `PETSC_VIEWER_MATLAB_SELF`, `PetscViewerMatlabOpen()`, `PetscViewerCreate()`,
283: `PetscViewerDestroy()`
284: @*/
285: PetscViewer PETSC_VIEWER_MATLAB_(MPI_Comm comm)
286: {
287: PetscBool flg;
288: PetscMPIInt iflg;
289: PetscViewer viewer;
290: char fname[PETSC_MAX_PATH_LEN];
291: MPI_Comm ncomm;
293: PetscFunctionBegin;
294: PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
295: if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) PetscCallMPINull(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Matlab_keyval, 0));
296: PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void **)&viewer, &iflg));
297: if (!iflg) { /* PetscViewer not yet created */
298: PetscCallNull(PetscOptionsGetenv(ncomm, "PETSC_VIEWER_MATLAB_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg));
299: if (!flg) PetscCallNull(PetscStrncpy(fname, "matlaboutput.mat", sizeof(fname)));
300: PetscCallNull(PetscViewerMatlabOpen(ncomm, fname, FILE_MODE_WRITE, &viewer));
301: PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
302: PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Matlab_keyval, (void *)viewer));
303: }
304: PetscCallNull(PetscCommDestroy(&ncomm));
305: PetscFunctionReturn(viewer);
306: }