xref: /petsc/src/sys/classes/viewer/impls/matlab/vmatlab.c (revision 82f516cc2a80c5c0e712e5bfc0bf40989ffef740)
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) vmatlab->ep = matOpen(name,"r");
163     else if (type == FILE_MODE_WRITE || type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name,"w");
164     else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
165   }
166   PetscFunctionReturn(0);
167 }
168 EXTERN_C_END
169 
170 #undef __FUNCT__
171 #define __FUNCT__ "PetscViewerDestroy_Matlab"
172 PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
173 {
174   PetscErrorCode     ierr;
175   PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data;
176 
177   PetscFunctionBegin;
178   if (vf->ep) matClose(vf->ep);
179   ierr = PetscFree(vf);CHKERRQ(ierr);
180   PetscFunctionReturn(0);
181 }
182 
183 EXTERN_C_BEGIN
184 #undef __FUNCT__
185 #define __FUNCT__ "PetscViewerCreate_Matlab"
186 PetscErrorCode  PetscViewerCreate_Matlab(PetscViewer viewer)
187 {
188   PetscErrorCode     ierr;
189   PetscViewer_Matlab *e;
190 
191   PetscFunctionBegin;
192   ierr         = PetscNewLog(viewer,PetscViewer_Matlab,&e);CHKERRQ(ierr);
193   ierr         = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&e->rank);CHKERRQ(ierr);
194   e->btype     = (PetscFileMode)-1;
195   viewer->data = (void*) e;
196 
197   ierr = PetscObjectComposeFunctionDynamic((PetscObject)viewer,"PetscViewerFileSetName_C","PetscViewerFileSetName_Matlab",PetscViewerFileSetName_Matlab);CHKERRQ(ierr);
198   ierr = PetscObjectComposeFunctionDynamic((PetscObject)viewer,"PetscViewerFileSetMode_C","PetscViewerFileSetMode_Matlab",PetscViewerFileSetMode_Matlab);CHKERRQ(ierr);
199 
200   viewer->ops->destroy = PetscViewerDestroy_Matlab;
201   PetscFunctionReturn(0);
202 }
203 EXTERN_C_END
204 
205 #undef __FUNCT__
206 #define __FUNCT__ "PetscViewerMatlabOpen"
207 /*@C
208    PetscViewerMatlabOpen - Opens a Matlab .mat file for output
209 
210    Collective on MPI_Comm
211 
212    Input Parameters:
213 +  comm - MPI communicator
214 .  name - name of file
215 -  type - type of file
216 $    FILE_MODE_WRITE - create new file for MATLAB output
217 $    FILE_MODE_READ - open existing file for MATLAB input
218 $    FILE_MODE_WRITE - open existing file for MATLAB output
219 
220    Output Parameter:
221 .  binv - PetscViewer for MATLAB output to use with the specified file
222 
223    Level: beginner
224 
225    Note: This PetscViewer should be destroyed with PetscViewerDestroy().
226 
227     For writing files it only opens the file on processor 0 in the communicator.
228 
229      This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB
230      instead of this routine.
231 
232    Concepts: MATLAB .mat files
233    Concepts: PetscViewerMatlab^creating
234 
235 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(), PETSCVIEWERBINARY, PetscViewerBinaryOpen()
236           VecView(), MatView(), VecLoad(), MatLoad()
237 @*/
238 PetscErrorCode  PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
239 {
240   PetscErrorCode ierr;
241 
242   PetscFunctionBegin;
243   ierr = PetscViewerCreate(comm,binv);CHKERRQ(ierr);
244   ierr = PetscViewerSetType(*binv,PETSCVIEWERMATLAB);CHKERRQ(ierr);
245   ierr = PetscViewerFileSetMode(*binv,type);CHKERRQ(ierr);
246   ierr = PetscViewerFileSetName(*binv,name);CHKERRQ(ierr);
247   PetscFunctionReturn(0);
248 }
249 
250 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
251 
252 #undef __FUNCT__
253 #define __FUNCT__ "PETSC_VIEWER_MATLAB_"
254 /*@C
255      PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors
256                      in a communicator.
257 
258      Collective on MPI_Comm
259 
260      Input Parameter:
261 .    comm - the MPI communicator to share the Matlab PetscViewer
262 
263      Level: intermediate
264 
265    Options Database Keys:
266 $    -viewer_matlab_filename <name>
267 
268    Environmental variables:
269 -   PETSC_VIEWER_MATLAB_FILENAME
270 
271      Notes:
272      Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return
273      an error code.  The matlab PetscViewer is usually used in the form
274 $       XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm));
275 
276      Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session.
277 
278 .seealso: PETSC_VIEWER_MATLAB_WORLD, PETSC_VIEWER_MATLAB_SELF, PetscViewerMatlabOpen(), PetscViewerCreate(),
279           PetscViewerDestroy()
280 @*/
281 PetscViewer  PETSC_VIEWER_MATLAB_(MPI_Comm comm)
282 {
283   PetscErrorCode ierr;
284   PetscBool      flg;
285   PetscViewer    viewer;
286   char           fname[PETSC_MAX_PATH_LEN];
287   MPI_Comm       ncomm;
288 
289   PetscFunctionBegin;
290   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
291   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
292     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0);
293     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
294   }
295   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg);
296   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
297   if (!flg) { /* PetscViewer not yet created */
298     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
299     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
300     if (!flg) {
301       ierr = PetscStrcpy(fname,"matlaboutput.mat");
302       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
303     }
304     ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
305     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
306     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
307     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
308     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
309     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
310   }
311   ierr = PetscCommDestroy(&ncomm);
312   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
313   PetscFunctionReturn(viewer);
314 }
315 
316 
317 
318 
319 
320