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