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