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