xref: /petsc/src/sys/classes/viewer/impls/matlab/vmatlab.c (revision 8dbb0df66754dee4fb72dff2ad56e76db1e6b7c7)
1 
2 #include <petsc/private/viewerimpl.h>
3 #include <mat.h>
4 
5 typedef struct {
6   MATFile       *ep;
7   PetscMPIInt   rank;
8   PetscFileMode btype;
9 } PetscViewer_Matlab;
10 
11 /*@C
12     PetscViewerMatlabPutArray - Puts an array into the MATLAB viewer.
13 
14       Not collective: only processor zero saves the array
15 
16     Input Parameters:
17 +    mfile - the viewer
18 .    m,n - the dimensions of the array
19 .    array - the array (represented in one dimension)
20 -    name - the name of the array
21 
22    Level: advanced
23 
24      Notes:
25     Only writes array values on processor 0.
26 
27 @*/
28 PetscErrorCode  PetscViewerMatlabPutArray(PetscViewer mfile,int m,int n,const PetscScalar *array,const char *name)
29 {
30   PetscErrorCode     ierr;
31   PetscViewer_Matlab *ml;
32   mxArray            *mat;
33 
34   PetscFunctionBegin;
35   if (!mfile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed");
36   ml = (PetscViewer_Matlab*)mfile->data;
37   if (!ml->rank) {
38     ierr = PetscInfo1(mfile,"Putting MATLAB array %s\n",name);CHKERRQ(ierr);
39 #if !defined(PETSC_USE_COMPLEX)
40     mat  = mxCreateDoubleMatrix(m,n,mxREAL);
41 #else
42     mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
43 #endif
44     ierr = PetscArraycpy(mxGetPr(mat),array,m*n);CHKERRQ(ierr);
45     matPutVariable(ml->ep,name,mat);
46 
47     ierr = PetscInfo1(mfile,"Put MATLAB array %s\n",name);CHKERRQ(ierr);
48   }
49   PetscFunctionReturn(0);
50 }
51 
52 PetscErrorCode  PetscViewerMatlabPutVariable(PetscViewer viewer,const char *name,void *mat)
53 {
54   PetscViewer_Matlab *ml = (PetscViewer_Matlab*)viewer->data;
55 
56   PetscFunctionBegin;
57   matPutVariable(ml->ep,name,(mxArray*)mat);
58   PetscFunctionReturn(0);
59 }
60 
61 /*@C
62     PetscViewerMatlabGetArray - Gets a variable from a MATLAB viewer into an array
63 
64     Not Collective; only processor zero reads in the array
65 
66     Input Parameters:
67 +    mfile - the MATLAB file viewer
68 .    m,n - the dimensions of the array
69 .    array - the array (represented in one dimension)
70 -    name - the name of the array
71 
72    Level: advanced
73 
74      Notes:
75     Only reads in array values on processor 0.
76 
77 @*/
78 PetscErrorCode  PetscViewerMatlabGetArray(PetscViewer mfile,int m,int n,PetscScalar *array,const char *name)
79 {
80   PetscErrorCode     ierr;
81   PetscViewer_Matlab *ml;
82   mxArray            *mat;
83 
84   PetscFunctionBegin;
85   if (!mfile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null argument: probably PETSC_VIEWER_MATLAB_() failed");
86   ml = (PetscViewer_Matlab*)mfile->data;
87   if (!ml->rank) {
88     ierr = PetscInfo1(mfile,"Getting MATLAB array %s\n",name);CHKERRQ(ierr);
89     mat  = matGetVariable(ml->ep,name);
90     if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name);
91     ierr = PetscArraycpy(array,mxGetPr(mat),m*n);CHKERRQ(ierr);
92     ierr = PetscInfo1(mfile,"Got MATLAB array %s\n",name);CHKERRQ(ierr);
93   }
94   PetscFunctionReturn(0);
95 }
96 
97 PetscErrorCode  PetscViewerFileSetMode_Matlab(PetscViewer viewer,PetscFileMode type)
98 {
99   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;
100 
101   PetscFunctionBegin;
102   vmatlab->btype = type;
103   PetscFunctionReturn(0);
104 }
105 
106 /*
107         Actually opens the file
108 */
109 PetscErrorCode  PetscViewerFileSetName_Matlab(PetscViewer viewer,const char name[])
110 {
111   PetscViewer_Matlab *vmatlab = (PetscViewer_Matlab*)viewer->data;
112   PetscFileMode      type     = vmatlab->btype;
113 
114   PetscFunctionBegin;
115   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
116   if (vmatlab->ep) matClose(vmatlab->ep);
117 
118   /* only first processor opens file */
119   if (!vmatlab->rank) {
120     if (type == FILE_MODE_READ) vmatlab->ep = matOpen(name,"r");
121     else if (type == FILE_MODE_WRITE) vmatlab->ep = matOpen(name,"w");
122     else if (type == FILE_MODE_UNDEFINED) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
123     else SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[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);CHKERRMPI(ierr);
181   e->btype     = FILE_MODE_UNDEFINED;
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 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PETSCVIEWERBINARY, PetscViewerBinaryOpen()
217           VecView(), MatView(), VecLoad(), MatLoad()
218 @*/
219 PetscErrorCode  PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
220 {
221   PetscErrorCode ierr;
222 
223   PetscFunctionBegin;
224   ierr = PetscViewerCreate(comm,binv);CHKERRQ(ierr);
225   ierr = PetscViewerSetType(*binv,PETSCVIEWERMATLAB);CHKERRQ(ierr);
226   ierr = PetscViewerFileSetMode(*binv,type);CHKERRQ(ierr);
227   ierr = PetscViewerFileSetName(*binv,name);CHKERRQ(ierr);
228   PetscFunctionReturn(0);
229 }
230 
231 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
232 
233 /*@C
234      PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors
235                      in a communicator.
236 
237      Collective
238 
239      Input Parameter:
240 .    comm - the MPI communicator to share the Matlab PetscViewer
241 
242      Level: intermediate
243 
244    Options Database Keys:
245 .    -viewer_matlab_filename <name> - name of the Matlab file
246 
247    Environmental variables:
248 .   PETSC_VIEWER_MATLAB_FILENAME - name of the Matlab file
249 
250      Notes:
251      Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return
252      an error code.  The matlab PetscViewer is usually used in the form
253 $       XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm));
254 
255      Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session.
256 
257 .seealso: PETSC_VIEWER_MATLAB_WORLD, PETSC_VIEWER_MATLAB_SELF, PetscViewerMatlabOpen(), PetscViewerCreate(),
258           PetscViewerDestroy()
259 @*/
260 PetscViewer  PETSC_VIEWER_MATLAB_(MPI_Comm comm)
261 {
262   PetscErrorCode ierr;
263   PetscBool      flg;
264   PetscViewer    viewer;
265   char           fname[PETSC_MAX_PATH_LEN];
266   MPI_Comm       ncomm;
267 
268   PetscFunctionBegin;
269   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
270   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
271     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0);
272     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
273   }
274   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg);
275   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
276   if (!flg) { /* PetscViewer not yet created */
277     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
278     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
279     if (!flg) {
280       ierr = PetscStrcpy(fname,"matlaboutput.mat");
281       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
282     }
283     ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
284     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
285     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
286     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
287     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
288     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
289   }
290   ierr = PetscCommDestroy(&ncomm);
291   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
292   PetscFunctionReturn(viewer);
293 }
294 
295