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