xref: /petsc/src/sys/classes/viewer/impls/matlab/vmatlab.c (revision 5c8f6a953e7ed1c81f507d64aebddb11080b60e9)
1 
2 #include <petsc-private/viewerimpl.h>
3 #include <mat.h>
4 
5 /*MC
6    PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB
7        with load('filename').
8 
9    Level: intermediate
10 
11        Note: Currently can only save PETSc vectors to .mat files, not matrices (use the PETSCVIEWERBINARY and
12              ${PETSC_DIR}/bin/matlab/PetscBinaryRead.m to read matrices into matlab).
13 
14              For parallel vectors obtained with DMCreateGlobalVector() or DMGetGlobalVector() the vectors are saved to
15              the .mat file in natural ordering. You can use DMView() to save the DMDA information to the .mat file
16              the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB
17              vector to the same multidimensional shape as it had in PETSc for plotting etc. For example,
18 
19 $             In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node)
20 $                PetscObjectSetName((PetscObject)x,"x");
21 $                VecView(x,PETSC_VIEWER_MATLAB_WORLD);
22 $                PetscObjectSetName((PetscObject)da,"da");
23 $                DMView(x,PETSC_VIEWER_MATLAB_WORLD);
24 $             Then from MATLAB
25 $                load('matlaboutput.mat')   % matlaboutput.mat is the default filename
26 $                xnew = zeros(da.n,da.m);
27 $                xnew(:) = x;    % reshape one dimensional vector back to two dimensions
28 
29               If you wish to put the same variable into the .mat file several times you need to give it a new
30               name before each call to view.
31 
32               Use PetscViewerMatlabPutArray() to just put an array of doubles into the .mat file
33 
34 .seealso:  PETSC_VIEWER_MATLAB_(),PETSC_VIEWER_MATLAB_SELF(), PETSC_VIEWER_MATLAB_WORLD(),PetscViewerCreate(),
35            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERBINARY,
36            PETSC_ASCII_VIEWER, PetscViewerFileSetName(), PetscViewerFileSetMode()
37 
38 M*/
39 
40 typedef struct {
41   MATFile       *ep;
42   PetscMPIInt   rank;
43   PetscFileMode btype;
44 } PetscViewer_Matlab;
45 
46 #undef __FUNCT__
47 #define __FUNCT__ "PetscViewerMatlabPutArray"
48 /*@C
49     PetscViewerMatlabPutArray - Puts an array into the MATLAB viewer.
50 
51       Not collective: only processor zero saves the array
52 
53     Input Parameters:
54 +    mfile - the viewer
55 .    m,n - the dimensions of the array
56 .    array - the array (represented in one dimension)
57 -    name - the name of the array
58 
59    Level: advanced
60 
61      Notes: Only writes array values on processor 0.
62 
63 @*/
64 PetscErrorCode  PetscViewerMatlabPutArray(PetscViewer mfile,int m,int n,const PetscScalar *array,const char *name)
65 {
66   PetscErrorCode     ierr;
67   PetscViewer_Matlab *ml = (PetscViewer_Matlab*)mfile->data;
68   mxArray            *mat;
69 
70   PetscFunctionBegin;
71   if (!ml->rank) {
72     ierr = PetscInfo1(mfile,"Putting MATLAB array %s\n",name);CHKERRQ(ierr);
73 #if !defined(PETSC_USE_COMPLEX)
74     mat  = mxCreateDoubleMatrix(m,n,mxREAL);
75 #else
76     mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
77 #endif
78     ierr = PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));CHKERRQ(ierr);
79     matPutVariable(ml->ep,name,mat);
80 
81     ierr = PetscInfo1(mfile,"Put MATLAB array %s\n",name);CHKERRQ(ierr);
82   }
83   PetscFunctionReturn(0);
84 }
85 
86 #undef __FUNCT__
87 #define __FUNCT__ "PetscViewerMatlabPutVariable"
88 PetscErrorCode  PetscViewerMatlabPutVariable(PetscViewer viewer,const char* name,void* mat)
89 {
90   PetscViewer_Matlab *ml = (PetscViewer_Matlab*)viewer->data; ;
91 
92   PetscFunctionBegin;
93   matPutVariable(ml->ep,name,(mxArray*)mat);
94   PetscFunctionReturn(0);
95 }
96 
97 #undef __FUNCT__
98 #define __FUNCT__ "PetscViewerMatlabGetArray"
99 /*@C
100     PetscViewerMatlabGetArray - Gets a variable from a MATLAB viewer into an array
101 
102     Not Collective; only processor zero reads in the array
103 
104     Input Parameters:
105 +    mfile - the MATLAB file viewer
106 .    m,n - the dimensions of the array
107 .    array - the array (represented in one dimension)
108 -    name - the name of the array
109 
110    Level: advanced
111 
112      Notes: Only reads in array values on processor 0.
113 
114 @*/
115 PetscErrorCode  PetscViewerMatlabGetArray(PetscViewer mfile,int m,int n,PetscScalar *array,const char *name)
116 {
117   PetscErrorCode     ierr;
118   PetscViewer_Matlab *ml = (PetscViewer_Matlab*)mfile->data;
119   mxArray            *mat;
120 
121   PetscFunctionBegin;
122   if (!ml->rank) {
123     ierr = PetscInfo1(mfile,"Getting MATLAB array %s\n",name);CHKERRQ(ierr);
124     mat  = matGetVariable(ml->ep,name);
125     if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
126     ierr = PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));CHKERRQ(ierr);
127     ierr = PetscInfo1(mfile,"Got MATLAB array %s\n",name);CHKERRQ(ierr);
128   }
129   PetscFunctionReturn(0);
130 }
131 
132 EXTERN_C_BEGIN
133 #undef __FUNCT__
134 #define __FUNCT__ "PetscViewerFileSetMode_Matlab"
135 PetscErrorCode  PetscViewerFileSetMode_Matlab(PetscViewer viewer,PetscFileMode type)
136 {
137   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;
138 
139   PetscFunctionBegin;
140   vmatlab->btype = type;
141   PetscFunctionReturn(0);
142 }
143 EXTERN_C_END
144 
145 /*
146         Actually opens the file
147 */
148 EXTERN_C_BEGIN
149 #undef __FUNCT__
150 #define __FUNCT__ "PetscViewerFileSetName_Matlab"
151 PetscErrorCode  PetscViewerFileSetName_Matlab(PetscViewer viewer,const char name[])
152 {
153   PetscViewer_Matlab  *vmatlab = (PetscViewer_Matlab*)viewer->data;
154   PetscFileMode       type = vmatlab->btype;
155 
156   PetscFunctionBegin;
157   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
158   if (vmatlab->ep) matClose(vmatlab->ep);
159 
160   /* only first processor opens file */
161   if (!vmatlab->rank) {
162     if (type == FILE_MODE_READ) {
163       vmatlab->ep = matOpen(name,"r");
164     } else if (type == FILE_MODE_WRITE || type == FILE_MODE_WRITE) {
165       vmatlab->ep = matOpen(name,"w");
166     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
167   }
168   PetscFunctionReturn(0);
169 }
170 EXTERN_C_END
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "PetscViewerDestroy_Matlab"
174 PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
175 {
176   PetscErrorCode     ierr;
177   PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data;
178 
179   PetscFunctionBegin;
180   if (vf->ep) matClose(vf->ep);
181   ierr = PetscFree(vf);CHKERRQ(ierr);
182   PetscFunctionReturn(0);
183 }
184 
185 EXTERN_C_BEGIN
186 #undef __FUNCT__
187 #define __FUNCT__ "PetscViewerCreate_Matlab"
188 PetscErrorCode  PetscViewerCreate_Matlab(PetscViewer viewer)
189 {
190   PetscErrorCode     ierr;
191   PetscViewer_Matlab *e;
192 
193   PetscFunctionBegin;
194   ierr         = PetscNewLog(viewer,PetscViewer_Matlab,&e);CHKERRQ(ierr);
195   ierr         = MPI_Comm_rank(((PetscObject)viewer)->comm,&e->rank);CHKERRQ(ierr);
196   e->btype     = (PetscFileMode)-1;
197   viewer->data = (void*) e;
198   ierr = PetscObjectComposeFunctionDynamic((PetscObject)viewer,"PetscViewerFileSetName_C","PetscViewerFileSetName_Matlab",
199                                      PetscViewerFileSetName_Matlab);CHKERRQ(ierr);
200   ierr = PetscObjectComposeFunctionDynamic((PetscObject)viewer,"PetscViewerFileSetMode_C","PetscViewerFileSetMode_Matlab",
201                                      PetscViewerFileSetMode_Matlab);CHKERRQ(ierr);
202   viewer->ops->destroy = PetscViewerDestroy_Matlab;
203   PetscFunctionReturn(0);
204 }
205 EXTERN_C_END
206 
207 #undef __FUNCT__
208 #define __FUNCT__ "PetscViewerMatlabOpen"
209 /*@C
210    PetscViewerMatlabOpen - Opens a Matlab .mat file for output
211 
212    Collective on MPI_Comm
213 
214    Input Parameters:
215 +  comm - MPI communicator
216 .  name - name of file
217 -  type - type of file
218 $    FILE_MODE_WRITE - create new file for MATLAB output
219 $    FILE_MODE_READ - open existing file for MATLAB input
220 $    FILE_MODE_WRITE - open existing file for MATLAB output
221 
222    Output Parameter:
223 .  binv - PetscViewer for MATLAB output to use with the specified file
224 
225    Level: beginner
226 
227    Note: This PetscViewer should be destroyed with PetscViewerDestroy().
228 
229     For writing files it only opens the file on processor 0 in the communicator.
230 
231      This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB
232      instead of this routine.
233 
234    Concepts: MATLAB .mat files
235    Concepts: PetscViewerMatlab^creating
236 
237 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(), PETSCVIEWERBINARY, PetscViewerBinaryOpen()
238           VecView(), MatView(), VecLoad(), MatLoad()
239 @*/
240 PetscErrorCode  PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
241 {
242   PetscErrorCode ierr;
243 
244   PetscFunctionBegin;
245   ierr = PetscViewerCreate(comm,binv);CHKERRQ(ierr);
246   ierr = PetscViewerSetType(*binv,PETSCVIEWERMATLAB);CHKERRQ(ierr);
247   ierr = PetscViewerFileSetMode(*binv,type);CHKERRQ(ierr);
248   ierr = PetscViewerFileSetName(*binv,name);CHKERRQ(ierr);
249   PetscFunctionReturn(0);
250 }
251 
252 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
253 
254 #undef __FUNCT__
255 #define __FUNCT__ "PETSC_VIEWER_MATLAB_"
256 /*@C
257      PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors
258                      in a communicator.
259 
260      Collective on MPI_Comm
261 
262      Input Parameter:
263 .    comm - the MPI communicator to share the Matlab PetscViewer
264 
265      Level: intermediate
266 
267    Options Database Keys:
268 $    -viewer_matlab_filename <name>
269 
270    Environmental variables:
271 -   PETSC_VIEWER_MATLAB_FILENAME
272 
273      Notes:
274      Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return
275      an error code.  The matlab PetscViewer is usually used in the form
276 $       XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm));
277 
278      Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session.
279 
280 .seealso: PETSC_VIEWER_MATLAB_WORLD, PETSC_VIEWER_MATLAB_SELF, PetscViewerMatlabOpen(), PetscViewerCreate(),
281           PetscViewerDestroy()
282 @*/
283 PetscViewer  PETSC_VIEWER_MATLAB_(MPI_Comm comm)
284 {
285   PetscErrorCode ierr;
286   PetscBool      flg;
287   PetscViewer    viewer;
288   char           fname[PETSC_MAX_PATH_LEN];
289   MPI_Comm       ncomm;
290 
291   PetscFunctionBegin;
292   ierr = PetscCommDuplicate(comm,&ncomm,PETSC_NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
293   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
294     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0);
295     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
296   }
297   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Matlab_keyval,(void **)&viewer,(int*)&flg);
298   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
299   if (!flg) { /* PetscViewer not yet created */
300     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
301     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
302     if (!flg) {
303       ierr = PetscStrcpy(fname,"matlaboutput.mat");
304       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
305     }
306     ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
307     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
308     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
309     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
310     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
311     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
312   }
313   ierr = PetscCommDestroy(&ncomm);
314   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
315   PetscFunctionReturn(viewer);
316 }
317 
318 
319 
320 
321 
322