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