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