xref: /petsc/src/sys/classes/viewer/impls/matlab/vmatlab.c (revision 05552d4bd0342c207cc7c527d55aae516dc232d5)
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) vmatlab->ep = matOpen(name,"w");
123     else if (type == FILE_MODE_UNDEFINED) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
124     else SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[type]);
125   }
126   PetscFunctionReturn(0);
127 }
128 
129 PetscErrorCode PetscViewerDestroy_Matlab(PetscViewer v)
130 {
131   PetscErrorCode     ierr;
132   PetscViewer_Matlab *vf = (PetscViewer_Matlab*)v->data;
133 
134   PetscFunctionBegin;
135   if (vf->ep) matClose(vf->ep);
136   ierr = PetscFree(vf);CHKERRQ(ierr);
137   PetscFunctionReturn(0);
138 }
139 
140 /*MC
141    PETSCVIEWERMATLAB - A viewer that saves the variables into a MATLAB .mat file that may be read into MATLAB
142        with load('filename').
143 
144    Level: intermediate
145 
146        Note: Currently can only save PETSc vectors to .mat files, not matrices (use the PETSCVIEWERBINARY and
147              ${PETSC_DIR}/share/petsc/matlab/PetscBinaryRead.m to read matrices into MATLAB).
148 
149              For parallel vectors obtained with DMCreateGlobalVector() or DMGetGlobalVector() the vectors are saved to
150              the .mat file in natural ordering. You can use DMView() to save the DMDA information to the .mat file
151              the fields in the MATLAB loaded da variable give the array dimensions so you can reshape the MATLAB
152              vector to the same multidimensional shape as it had in PETSc for plotting etc. For example,
153 
154 $             In your PETSc C/C++ code (assuming a two dimensional DMDA with one degree of freedom per node)
155 $                PetscObjectSetName((PetscObject)x,"x");
156 $                VecView(x,PETSC_VIEWER_MATLAB_WORLD);
157 $                PetscObjectSetName((PetscObject)da,"da");
158 $                DMView(x,PETSC_VIEWER_MATLAB_WORLD);
159 $             Then from MATLAB
160 $                load('matlaboutput.mat')   % matlaboutput.mat is the default filename
161 $                xnew = zeros(da.n,da.m);
162 $                xnew(:) = x;    % reshape one dimensional vector back to two dimensions
163 
164               If you wish to put the same variable into the .mat file several times you need to give it a new
165               name before each call to view.
166 
167               Use PetscViewerMatlabPutArray() to just put an array of doubles into the .mat file
168 
169 .seealso:  PETSC_VIEWER_MATLAB_(),PETSC_VIEWER_MATLAB_SELF, PETSC_VIEWER_MATLAB_WORLD,PetscViewerCreate(),
170            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERBINARY, PETSCVIEWERASCII, PETSCVIEWERDRAW,
171            PETSC_VIEWER_STDOUT_(), PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat
172 
173 M*/
174 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Matlab(PetscViewer viewer)
175 {
176   PetscErrorCode     ierr;
177   PetscViewer_Matlab *e;
178 
179   PetscFunctionBegin;
180   ierr         = PetscNewLog(viewer,&e);CHKERRQ(ierr);
181   ierr         = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&e->rank);CHKERRMPI(ierr);
182   e->btype     = FILE_MODE_UNDEFINED;
183   viewer->data = (void*) e;
184 
185   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_Matlab);CHKERRQ(ierr);
186   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Matlab);CHKERRQ(ierr);
187 
188   viewer->ops->destroy = PetscViewerDestroy_Matlab;
189   PetscFunctionReturn(0);
190 }
191 
192 /*@C
193    PetscViewerMatlabOpen - Opens a Matlab .mat file for output
194 
195    Collective
196 
197    Input Parameters:
198 +  comm - MPI communicator
199 .  name - name of file
200 -  type - type of file
201 $    FILE_MODE_WRITE - create new file for MATLAB output
202 $    FILE_MODE_READ - open existing file for MATLAB input
203 $    FILE_MODE_WRITE - open existing file for MATLAB output
204 
205    Output Parameter:
206 .  binv - PetscViewer for MATLAB output to use with the specified file
207 
208    Level: beginner
209 
210    Note: This PetscViewer should be destroyed with PetscViewerDestroy().
211 
212     For writing files it only opens the file on processor 0 in the communicator.
213 
214      This only saves Vecs it cannot be used to save Mats. We recommend using the PETSCVIEWERBINARY to save objects to be loaded into MATLAB
215      instead of this routine.
216 
217 
218 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PETSCVIEWERBINARY, PetscViewerBinaryOpen()
219           VecView(), MatView(), VecLoad(), MatLoad()
220 @*/
221 PetscErrorCode  PetscViewerMatlabOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
222 {
223   PetscErrorCode ierr;
224 
225   PetscFunctionBegin;
226   ierr = PetscViewerCreate(comm,binv);CHKERRQ(ierr);
227   ierr = PetscViewerSetType(*binv,PETSCVIEWERMATLAB);CHKERRQ(ierr);
228   ierr = PetscViewerFileSetMode(*binv,type);CHKERRQ(ierr);
229   ierr = PetscViewerFileSetName(*binv,name);CHKERRQ(ierr);
230   PetscFunctionReturn(0);
231 }
232 
233 static PetscMPIInt Petsc_Viewer_Matlab_keyval = MPI_KEYVAL_INVALID;
234 
235 /*@C
236      PETSC_VIEWER_MATLAB_ - Creates a Matlab PetscViewer shared by all processors
237                      in a communicator.
238 
239      Collective
240 
241      Input Parameter:
242 .    comm - the MPI communicator to share the Matlab PetscViewer
243 
244      Level: intermediate
245 
246    Options Database Keys:
247 .    -viewer_matlab_filename <name>
248 
249    Environmental variables:
250 .   PETSC_VIEWER_MATLAB_FILENAME
251 
252      Notes:
253      Unlike almost all other PETSc routines, PETSC_VIEWER_MATLAB_ does not return
254      an error code.  The matlab PetscViewer is usually used in the form
255 $       XXXView(XXX object,PETSC_VIEWER_MATLAB_(comm));
256 
257      Use PETSC_VIEWER_SOCKET_() or PetscViewerSocketOpen() to communicator with an interactive MATLAB session.
258 
259 .seealso: PETSC_VIEWER_MATLAB_WORLD, PETSC_VIEWER_MATLAB_SELF, PetscViewerMatlabOpen(), PetscViewerCreate(),
260           PetscViewerDestroy()
261 @*/
262 PetscViewer  PETSC_VIEWER_MATLAB_(MPI_Comm comm)
263 {
264   PetscErrorCode ierr;
265   PetscBool      flg;
266   PetscViewer    viewer;
267   char           fname[PETSC_MAX_PATH_LEN];
268   MPI_Comm       ncomm;
269 
270   PetscFunctionBegin;
271   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
272   if (Petsc_Viewer_Matlab_keyval == MPI_KEYVAL_INVALID) {
273     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Matlab_keyval,0);
274     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
275   }
276   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void**)&viewer,(int*)&flg);
277   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
278   if (!flg) { /* PetscViewer not yet created */
279     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_MATLAB_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
280     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
281     if (!flg) {
282       ierr = PetscStrcpy(fname,"matlaboutput.mat");
283       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
284     }
285     ierr = PetscViewerMatlabOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
286     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
287     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
288     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
289     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Matlab_keyval,(void*)viewer);
290     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
291   }
292   ierr = PetscCommDestroy(&ncomm);
293   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_MATLAB_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
294   PetscFunctionReturn(viewer);
295 }
296 
297 
298 
299 
300 
301