xref: /petsc/src/sys/classes/viewer/impls/mathematica/mathematica.c (revision 356ed81403a8ddb9cbcae868d64486ea275d004c)
1 
2 #include <petsc/private/viewerimpl.h>   /* "petscsys.h" */
3 #include <petsc/private/pcimpl.h>
4 #include <../src/mat/impls/aij/seq/aij.h>
5 #include <mathematica.h>
6 
7 #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF)
8 #define snprintf _snprintf
9 #endif
10 
11 PetscViewer PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL;
12 static void *mathematicaEnv                        = NULL;
13 
14 static PetscBool PetscViewerMathematicaPackageInitialized = PETSC_FALSE;
15 /*@C
16   PetscViewerMathematicaFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
17   called from PetscFinalize().
18 
19   Level: developer
20 
21 .seealso: PetscFinalize()
22 @*/
23 PetscErrorCode  PetscViewerMathematicaFinalizePackage(void)
24 {
25   PetscFunctionBegin;
26   if (mathematicaEnv) MLDeinitialize((MLEnvironment) mathematicaEnv);
27   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
28   PetscFunctionReturn(0);
29 }
30 
31 /*@C
32   PetscViewerMathematicaInitializePackage - This function initializes everything in the Petsc interface to Mathematica. It is
33   called from PetscViewerInitializePackage().
34 
35   Level: developer
36 
37 .seealso: PetscSysInitializePackage(), PetscInitialize()
38 @*/
39 PetscErrorCode  PetscViewerMathematicaInitializePackage(void)
40 {
41   PetscError ierr;
42 
43   PetscFunctionBegin;
44   if (PetscViewerMathematicaPackageInitialized) PetscFunctionReturn(0);
45   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
46 
47   mathematicaEnv = (void*) MLInitialize(0);
48 
49   PetscCall(PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage));
50   PetscFunctionReturn(0);
51 }
52 
53 PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
54 {
55   PetscFunctionBegin;
56   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscFunctionReturn(0);
57   PetscCall(PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
58   PetscFunctionReturn(0);
59 }
60 
61 static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
62 {
63   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
64 
65   PetscFunctionBegin;
66   MLClose(vmath->link);
67   PetscCall(PetscFree(vmath->linkname));
68   PetscCall(PetscFree(vmath->linkhost));
69   PetscCall(PetscFree(vmath));
70   PetscFunctionReturn(0);
71 }
72 
73 PetscErrorCode PetscViewerDestroyMathematica_Private(void)
74 {
75   PetscFunctionBegin;
76   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) {
77     PetscCall(PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
78   }
79   PetscFunctionReturn(0);
80 }
81 
82 PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
83 {
84   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
85 #if defined(MATHEMATICA_3_0)
86   int                     argc = 6;
87   char                    *argv[6];
88 #else
89   int                     argc = 5;
90   char                    *argv[5];
91 #endif
92   char                    hostname[256];
93   long                    lerr;
94 
95   PetscFunctionBegin;
96   /* Link name */
97   argv[0] = "-linkname";
98   if (!vmath->linkname) argv[1] = "math -mathlink";
99   else                  argv[1] = vmath->linkname;
100 
101   /* Link host */
102   argv[2] = "-linkhost";
103   if (!vmath->linkhost) {
104     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
105     argv[3] = hostname;
106   } else argv[3] = vmath->linkhost;
107 
108   /* Link mode */
109 #if defined(MATHEMATICA_3_0)
110   argv[4] = "-linkmode";
111   switch (vmath->linkmode) {
112   case MATHEMATICA_LINK_CREATE:
113     argv[5] = "Create";
114     break;
115   case MATHEMATICA_LINK_CONNECT:
116     argv[5] = "Connect";
117     break;
118   case MATHEMATICA_LINK_LAUNCH:
119     argv[5] = "Launch";
120     break;
121   }
122 #else
123   switch (vmath->linkmode) {
124   case MATHEMATICA_LINK_CREATE:
125     argv[4] = "-linkcreate";
126     break;
127   case MATHEMATICA_LINK_CONNECT:
128     argv[4] = "-linkconnect";
129     break;
130   case MATHEMATICA_LINK_LAUNCH:
131     argv[4] = "-linklaunch";
132     break;
133   }
134 #endif
135   vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
136 #endif
137   PetscFunctionReturn(0);
138 }
139 
140 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
141 {
142   PetscViewer_Mathematica *vmath;
143 
144   PetscFunctionBegin;
145   PetscCall(PetscViewerMathematicaInitializePackage());
146 
147   PetscCall(PetscNewLog(v,&vmath));
148   v->data         = (void*) vmath;
149   v->ops->destroy = PetscViewerDestroy_Mathematica;
150   v->ops->flush   = 0;
151   PetscCall(PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name));
152 
153   vmath->linkname     = NULL;
154   vmath->linkhost     = NULL;
155   vmath->linkmode     = MATHEMATICA_LINK_CONNECT;
156   vmath->graphicsType = GRAPHICS_MOTIF;
157   vmath->plotType     = MATHEMATICA_TRIANGULATION_PLOT;
158   vmath->objName      = NULL;
159 
160   PetscCall(PetscViewerMathematicaSetFromOptions(v));
161   PetscCall(PetscViewerMathematicaSetupConnection_Private(v));
162   PetscFunctionReturn(0);
163 }
164 
165 static PetscErrorCode PetscViewerMathematicaParseLinkMode(char *modename, LinkMode *mode)
166 {
167   PetscBool      isCreate, isConnect, isLaunch;
168 
169   PetscFunctionBegin;
170   PetscCall(PetscStrcasecmp(modename, "Create",  &isCreate));
171   PetscCall(PetscStrcasecmp(modename, "Connect", &isConnect));
172   PetscCall(PetscStrcasecmp(modename, "Launch",  &isLaunch));
173   if (isCreate)       *mode = MATHEMATICA_LINK_CREATE;
174   else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
175   else if (isLaunch)  *mode = MATHEMATICA_LINK_LAUNCH;
176   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
177   PetscFunctionReturn(0);
178 }
179 
180 PetscErrorCode  PetscViewerMathematicaSetFromOptions(PetscViewer v)
181 {
182   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
183   char                    linkname[256];
184   char                    modename[256];
185   char                    hostname[256];
186   char                    type[256];
187   PetscInt                numPorts;
188   PetscInt                *ports;
189   PetscInt                numHosts;
190   int                     h;
191   char                    **hosts;
192   PetscMPIInt             size, rank;
193   PetscBool               opt;
194 
195   PetscFunctionBegin;
196   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
197   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));
198 
199   /* Get link name */
200   PetscCall(PetscOptionsGetString("viewer_", "-math_linkname", linkname, sizeof(linkname), &opt));
201   if (opt) {
202     PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
203   }
204   /* Get link port */
205   numPorts = size;
206   PetscCall(PetscMalloc1(size, &ports));
207   PetscCall(PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt));
208   if (opt) {
209     if (numPorts > rank) snprintf(linkname, sizeof(linkname), "%6d", ports[rank]);
210     else                 snprintf(linkname, sizeof(linkname), "%6d", ports[0]);
211     PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
212   }
213   PetscCall(PetscFree(ports));
214   /* Get link host */
215   numHosts = size;
216   PetscCall(PetscMalloc1(size, &hosts));
217   PetscCall(PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt));
218   if (opt) {
219     if (numHosts > rank) {
220       PetscCall(PetscStrncpy(hostname, hosts[rank], sizeof(hostname)));
221     } else {
222       PetscCall(PetscStrncpy(hostname, hosts[0], sizeof(hostname)));
223     }
224     PetscCall(PetscViewerMathematicaSetLinkHost(v, hostname));
225   }
226   for (h = 0; h < numHosts; h++) {
227     PetscCall(PetscFree(hosts[h]));
228   }
229   PetscCall(PetscFree(hosts));
230   /* Get link mode */
231   PetscCall(PetscOptionsGetString("viewer_", "-math_linkmode", modename, sizeof(modename), &opt));
232   if (opt) {
233     LinkMode mode;
234 
235     PetscCall(PetscViewerMathematicaParseLinkMode(modename, &mode));
236     PetscCall(PetscViewerMathematicaSetLinkMode(v, mode));
237   }
238   /* Get graphics type */
239   PetscCall(PetscOptionsGetString("viewer_", "-math_graphics", type, sizeof(type), &opt));
240   if (opt) {
241     PetscBool isMotif, isPS, isPSFile;
242 
243     PetscCall(PetscStrcasecmp(type, "Motif",  &isMotif));
244     PetscCall(PetscStrcasecmp(type, "PS",     &isPS));
245     PetscCall(PetscStrcasecmp(type, "PSFile", &isPSFile));
246     if (isMotif)       vmath->graphicsType = GRAPHICS_MOTIF;
247     else if (isPS)     vmath->graphicsType = GRAPHICS_PS_STDOUT;
248     else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
249   }
250   /* Get plot type */
251   PetscCall(PetscOptionsGetString("viewer_", "-math_type", type, sizeof(type), &opt));
252   if (opt) {
253     PetscBool isTri, isVecTri, isVec, isSurface;
254 
255     PetscCall(PetscStrcasecmp(type, "Triangulation",       &isTri));
256     PetscCall(PetscStrcasecmp(type, "VectorTriangulation", &isVecTri));
257     PetscCall(PetscStrcasecmp(type, "Vector",              &isVec));
258     PetscCall(PetscStrcasecmp(type, "Surface",             &isSurface));
259     if (isTri)          vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
260     else if (isVecTri)  vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
261     else if (isVec)     vmath->plotType = MATHEMATICA_VECTOR_PLOT;
262     else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
263   }
264   PetscFunctionReturn(0);
265 }
266 
267 PetscErrorCode  PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
268 {
269   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
270 
271   PetscFunctionBegin;
272   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
273   PetscValidCharPointer(name,2);
274   PetscCall(PetscStrallocpy(name, &vmath->linkname));
275   PetscFunctionReturn(0);
276 }
277 
278 PetscErrorCode  PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
279 {
280   char           name[16];
281 
282   PetscFunctionBegin;
283   snprintf(name, 16, "%6d", port);
284   PetscCall(PetscViewerMathematicaSetLinkName(v, name));
285   PetscFunctionReturn(0);
286 }
287 
288 PetscErrorCode  PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
289 {
290   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
291 
292   PetscFunctionBegin;
293   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
294   PetscValidCharPointer(host,2);
295   PetscCall(PetscStrallocpy(host, &vmath->linkhost));
296   PetscFunctionReturn(0);
297 }
298 
299 PetscErrorCode  PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
300 {
301   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
302 
303   PetscFunctionBegin;
304   vmath->linkmode = mode;
305   PetscFunctionReturn(0);
306 }
307 
308 /*----------------------------------------- Public Functions --------------------------------------------------------*/
309 /*@C
310   PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.
311 
312   Collective
313 
314   Input Parameters:
315 + comm    - The MPI communicator
316 . port    - [optional] The port to connect on, or PETSC_DECIDE
317 . machine - [optional] The machine to run Mathematica on, or NULL
318 - mode    - [optional] The connection mode, or NULL
319 
320   Output Parameter:
321 . viewer  - The Mathematica viewer
322 
323   Level: intermediate
324 
325   Notes:
326   Most users should employ the following commands to access the
327   Mathematica viewers
328 $
329 $    PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
330 $    MatView(Mat matrix, PetscViewer viewer)
331 $
332 $                or
333 $
334 $    PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
335 $    VecView(Vec vector, PetscViewer viewer)
336 
337    Options Database Keys:
338 +    -viewer_math_linkhost <machine> - The host machine for the kernel
339 .    -viewer_math_linkname <name>    - The full link name for the connection
340 .    -viewer_math_linkport <port>    - The port for the connection
341 .    -viewer_math_mode <mode>        - The mode, e.g. Launch, Connect
342 .    -viewer_math_type <type>        - The plot type, e.g. Triangulation, Vector
343 -    -viewer_math_graphics <output>  - The output type, e.g. Motif, PS, PSFile
344 
345 .seealso: MatView(), VecView()
346 @*/
347 PetscErrorCode  PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
348 {
349   PetscFunctionBegin;
350   PetscCall(PetscViewerCreate(comm, v));
351 #if 0
352   LinkMode linkmode;
353   PetscCall(PetscViewerMathematicaSetLinkPort(*v, port));
354   PetscCall(PetscViewerMathematicaSetLinkHost(*v, machine));
355   PetscCall(PetscViewerMathematicaParseLinkMode(mode, &linkmode));
356   PetscCall(PetscViewerMathematicaSetLinkMode(*v, linkmode));
357 #endif
358   PetscCall(PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA));
359   PetscFunctionReturn(0);
360 }
361 
362 /*@C
363   PetscViewerMathematicaGetLink - Returns the link to Mathematica
364 
365   Input Parameters:
366 + viewer - The Mathematica viewer
367 - link   - The link to Mathematica
368 
369   Level: intermediate
370 
371 .keywords PetscViewer, Mathematica, link
372 .seealso PetscViewerMathematicaOpen()
373 @*/
374 PetscErrorCode  PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
375 {
376   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
377 
378   PetscFunctionBegin;
379   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID,1);
380   *link = vmath->link;
381   PetscFunctionReturn(0);
382 }
383 
384 /*@C
385   PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received
386 
387   Input Parameters:
388 + viewer - The Mathematica viewer
389 - type   - The packet type to search for, e.g RETURNPKT
390 
391   Level: advanced
392 
393 .keywords PetscViewer, Mathematica, packets
394 .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaGetVector()
395 @*/
396 PetscErrorCode  PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
397 {
398   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
399   MLINK                   link   = vmath->link; /* The link to Mathematica */
400   int                     pkt;                 /* The packet type */
401 
402   PetscFunctionBegin;
403   while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
404   if (!pkt) {
405     MLClearError(link);
406     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, (char*) MLErrorMessage(link));
407   }
408   PetscFunctionReturn(0);
409 }
410 
411 /*@C
412   PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica
413 
414   Input Parameter:
415 . viewer - The Mathematica viewer
416 
417   Output Parameter:
418 . name   - The name for new objects created in Mathematica
419 
420   Level: intermediate
421 
422 .keywords PetscViewer, Mathematica, name
423 .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
424 @*/
425 PetscErrorCode  PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
426 {
427   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
428 
429   PetscFunctionBegin;
430   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID,1);
431   PetscValidPointer(name,2);
432   *name = vmath->objName;
433   PetscFunctionReturn(0);
434 }
435 
436 /*@C
437   PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica
438 
439   Input Parameters:
440 + viewer - The Mathematica viewer
441 - name   - The name for new objects created in Mathematica
442 
443   Level: intermediate
444 
445 .keywords PetscViewer, Mathematica, name
446 .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
447 @*/
448 PetscErrorCode  PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
449 {
450   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
451 
452   PetscFunctionBegin;
453   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID,1);
454   PetscValidPointer(name,2);
455   vmath->objName = name;
456   PetscFunctionReturn(0);
457 }
458 
459 /*@C
460   PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica
461 
462   Input Parameter:
463 . viewer - The Mathematica viewer
464 
465   Level: intermediate
466 
467 .keywords PetscViewer, Mathematica, name
468 .seealso PetscViewerMathematicaGetName(), PetscViewerMathematicaSetName()
469 @*/
470 PetscErrorCode  PetscViewerMathematicaClearName(PetscViewer viewer)
471 {
472   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
473 
474   PetscFunctionBegin;
475   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID,1);
476   vmath->objName = NULL;
477   PetscFunctionReturn(0);
478 }
479 
480 /*@C
481   PetscViewerMathematicaGetVector - Retrieve a vector from Mathematica
482 
483   Input Parameter:
484 . viewer - The Mathematica viewer
485 
486   Output Parameter:
487 . v      - The vector
488 
489   Level: intermediate
490 
491 .keywords PetscViewer, Mathematica, vector
492 .seealso VecView(), PetscViewerMathematicaPutVector()
493 @*/
494 PetscErrorCode  PetscViewerMathematicaGetVector(PetscViewer viewer, Vec v)
495 {
496   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
497   MLINK                   link;   /* The link to Mathematica */
498   char                    *name;
499   PetscScalar             *mArray,*array;
500   long                    mSize;
501   int                     n;
502 
503   PetscFunctionBegin;
504   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID,1);
505   PetscValidHeaderSpecific(v,      VEC_CLASSID,2);
506 
507   /* Determine the object name */
508   if (!vmath->objName) name = "vec";
509   else                 name = (char*) vmath->objName;
510 
511   link = vmath->link;
512   PetscCall(VecGetLocalSize(v, &n));
513   PetscCall(VecGetArray(v, &array));
514   MLPutFunction(link, "EvaluatePacket", 1);
515   MLPutSymbol(link, name);
516   MLEndPacket(link);
517   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
518   MLGetRealList(link, &mArray, &mSize);
519   PetscCheckFalse(n != mSize,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Incompatible vector sizes %d %d",n,mSize);
520   PetscCall(PetscArraycpy(array, mArray, mSize));
521   MLDisownRealList(link, mArray, mSize);
522   PetscCall(VecRestoreArray(v, &array));
523   PetscFunctionReturn(0);
524 }
525 
526 /*@C
527   PetscViewerMathematicaPutVector - Send a vector to Mathematica
528 
529   Input Parameters:
530 + viewer - The Mathematica viewer
531 - v      - The vector
532 
533   Level: intermediate
534 
535 .keywords PetscViewer, Mathematica, vector
536 .seealso VecView(), PetscViewerMathematicaGetVector()
537 @*/
538 PetscErrorCode  PetscViewerMathematicaPutVector(PetscViewer viewer, Vec v)
539 {
540   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
541   MLINK                   link   = vmath->link; /* The link to Mathematica */
542   char                    *name;
543   PetscScalar             *array;
544   int                     n;
545 
546   PetscFunctionBegin;
547   /* Determine the object name */
548   if (!vmath->objName) name = "vec";
549   else                 name = (char*) vmath->objName;
550 
551   PetscCall(VecGetLocalSize(v, &n));
552   PetscCall(VecGetArray(v, &array));
553 
554   /* Send the Vector object */
555   MLPutFunction(link, "EvaluatePacket", 1);
556   MLPutFunction(link, "Set", 2);
557   MLPutSymbol(link, name);
558   MLPutRealList(link, array, n);
559   MLEndPacket(link);
560   /* Skip packets until ReturnPacket */
561   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
562   /* Skip ReturnPacket */
563   MLNewPacket(link);
564 
565   PetscCall(VecRestoreArray(v, &array));
566   PetscFunctionReturn(0);
567 }
568 
569 PetscErrorCode  PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
570 {
571   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
572   MLINK                   link   = vmath->link; /* The link to Mathematica */
573   char                    *name;
574 
575   PetscFunctionBegin;
576   /* Determine the object name */
577   if (!vmath->objName) name = "mat";
578   else                 name = (char*) vmath->objName;
579 
580   /* Send the dense matrix object */
581   MLPutFunction(link, "EvaluatePacket", 1);
582   MLPutFunction(link, "Set", 2);
583   MLPutSymbol(link, name);
584   MLPutFunction(link, "Transpose", 1);
585   MLPutFunction(link, "Partition", 2);
586   MLPutRealList(link, a, m*n);
587   MLPutInteger(link, m);
588   MLEndPacket(link);
589   /* Skip packets until ReturnPacket */
590   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
591   /* Skip ReturnPacket */
592   MLNewPacket(link);
593   PetscFunctionReturn(0);
594 }
595 
596 PetscErrorCode  PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
597 {
598   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
599   MLINK                   link   = vmath->link; /* The link to Mathematica */
600   const char              *symbol;
601   char                    *name;
602   PetscBool               match;
603 
604   PetscFunctionBegin;
605   /* Determine the object name */
606   if (!vmath->objName) name = "mat";
607   else                 name = (char*) vmath->objName;
608 
609   /* Make sure Mathematica recognizes sparse matrices */
610   MLPutFunction(link, "EvaluatePacket", 1);
611   MLPutFunction(link, "Needs", 1);
612   MLPutString(link, "LinearAlgebra`CSRMatrix`");
613   MLEndPacket(link);
614   /* Skip packets until ReturnPacket */
615   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
616   /* Skip ReturnPacket */
617   MLNewPacket(link);
618 
619   /* Send the CSRMatrix object */
620   MLPutFunction(link, "EvaluatePacket", 1);
621   MLPutFunction(link, "Set", 2);
622   MLPutSymbol(link, name);
623   MLPutFunction(link, "CSRMatrix", 5);
624   MLPutInteger(link, m);
625   MLPutInteger(link, n);
626   MLPutFunction(link, "Plus", 2);
627   MLPutIntegerList(link, i, m+1);
628   MLPutInteger(link, 1);
629   MLPutFunction(link, "Plus", 2);
630   MLPutIntegerList(link, j, i[m]);
631   MLPutInteger(link, 1);
632   MLPutRealList(link, a, i[m]);
633   MLEndPacket(link);
634   /* Skip packets until ReturnPacket */
635   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
636   /* Skip ReturnPacket */
637   MLNewPacket(link);
638 
639   /* Check that matrix is valid */
640   MLPutFunction(link, "EvaluatePacket", 1);
641   MLPutFunction(link, "ValidQ", 1);
642   MLPutSymbol(link, name);
643   MLEndPacket(link);
644   PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
645   MLGetSymbol(link, &symbol);
646   PetscCall(PetscStrcmp("True", (char*) symbol, &match));
647   if (!match) {
648     MLDisownSymbol(link, symbol);
649     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
650   }
651   MLDisownSymbol(link, symbol);
652   /* Skip ReturnPacket */
653   MLNewPacket(link);
654   PetscFunctionReturn(0);
655 }
656