Actual source code: mathematica.c

petsc-3.4.4 2014-03-13
  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>

  7: #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF)
  8: #define snprintf _snprintf
  9: #endif

 11: PetscViewer PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL;
 12: static void *mathematicaEnv                        = NULL;

 14: static PetscBool PetscViewerMathematicaPackageInitialized = PETSC_FALSE;
 17: /*@C
 18:   PetscViewerMathematicaFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
 19:   called from PetscFinalize().

 21:   Level: developer

 23: .keywords: Petsc, destroy, package, mathematica
 24: .seealso: PetscFinalize()
 25: @*/
 26: PetscErrorCode  PetscViewerMathematicaFinalizePackage(void)
 27: {
 29:   if (mathematicaEnv) MLDeinitialize((MLEnvironment) mathematicaEnv);
 30:   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
 31:   return(0);
 32: }

 36: /*@C
 37:   PetscViewerMathematicaInitializePackage - This function initializes everything in the Petsc interface to Mathematica. It is
 38:   called from PetscDLLibraryRegister() when using dynamic libraries, and on the call to PetscInitialize()
 39:   when using static libraries.

 41:   Level: developer

 43: .keywords: Petsc, initialize, package
 44: .seealso: PetscSysInitializePackage(), PetscInitialize()
 45: @*/
 46: PetscErrorCode  PetscViewerMathematicaInitializePackage(void)
 47: {
 48:   PetscError ierr;

 51:   if (PetscViewerMathematicaPackageInitialized) return(0);
 52:   PetscViewerMathematicaPackageInitialized = PETSC_TRUE;

 54:   mathematicaEnv = (void*) MLInitialize(0);

 56:   PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage);
 57:   return(0);
 58: }


 63: PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
 64: {

 68:   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) return(0);
 69:   PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE);
 70:   return(0);
 71: }

 75: static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
 76: {
 77:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
 78:   PetscErrorCode          ierr;

 81:   MLClose(vmath->link);
 82:   PetscFree(vmath->linkname);
 83:   PetscFree(vmath->linkhost);
 84:   PetscFree(vmath);
 85:   return(0);
 86: }

 90: PetscErrorCode PetscViewerDestroyMathematica_Private(void)
 91: {

 95:   if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) {
 96:     PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE);
 97:   }
 98:   return(0);
 99: }

103: PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
104: {
105:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
106: #if defined(MATHEMATICA_3_0)
107:   int                     argc = 6;
108:   char                    *argv[6];
109: #else
110:   int                     argc = 5;
111:   char                    *argv[5];
112: #endif
113:   char                    hostname[256];
114:   long                    lerr;
115:   PetscErrorCode          ierr;

118:   /* Link name */
119:   argv[0] = "-linkname";
120:   if (!vmath->linkname) argv[1] = "math -mathlink";
121:   else                  argv[1] = vmath->linkname;

123:   /* Link host */
124:   argv[2] = "-linkhost";
125:   if (!vmath->linkhost) {
126:     PetscGetHostName(hostname, 255);
127:     argv[3] = hostname;
128:   } else argv[3] = vmath->linkhost;

130:   /* Link mode */
131: #if defined(MATHEMATICA_3_0)
132:   argv[4] = "-linkmode";
133:   switch (vmath->linkmode) {
134:   case MATHEMATICA_LINK_CREATE:
135:     argv[5] = "Create";
136:     break;
137:   case MATHEMATICA_LINK_CONNECT:
138:     argv[5] = "Connect";
139:     break;
140:   case MATHEMATICA_LINK_LAUNCH:
141:     argv[5] = "Launch";
142:     break;
143:   }
144: #else
145:   switch (vmath->linkmode) {
146:   case MATHEMATICA_LINK_CREATE:
147:     argv[4] = "-linkcreate";
148:     break;
149:   case MATHEMATICA_LINK_CONNECT:
150:     argv[4] = "-linkconnect";
151:     break;
152:   case MATHEMATICA_LINK_LAUNCH:
153:     argv[4] = "-linklaunch";
154:     break;
155:   }
156: #endif
157:   vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
158: #endif
159:   return(0);
160: }

164: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
165: {
166:   PetscViewer_Mathematica *vmath;
167:   PetscErrorCode          ierr;

170: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
171:   PetscViewerMathematicaInitializePackage();
172: #endif

174:   PetscNewLog(v,PetscViewer_Mathematica, &vmath);
175:   v->data         = (void*) vmath;
176:   v->ops->destroy = PetscViewerDestroy_Mathematica;
177:   v->ops->flush   = 0;
178:   PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name);

180:   vmath->linkname     = NULL;
181:   vmath->linkhost     = NULL;
182:   vmath->linkmode     = MATHEMATICA_LINK_CONNECT;
183:   vmath->graphicsType = GRAPHICS_MOTIF;
184:   vmath->plotType     = MATHEMATICA_TRIANGULATION_PLOT;
185:   vmath->objName      = NULL;

187:   PetscViewerMathematicaSetFromOptions(v);
188:   PetscViewerMathematicaSetupConnection_Private(v);
189:   return(0);
190: }

194: PetscErrorCode PetscViewerMathematicaParseLinkMode_Private(char *modename, LinkMode *mode)
195: {
196:   PetscBool      isCreate, isConnect, isLaunch;

200:   PetscStrcasecmp(modename, "Create",  &isCreate);
201:   PetscStrcasecmp(modename, "Connect", &isConnect);
202:   PetscStrcasecmp(modename, "Launch",  &isLaunch);
203:   if (isCreate)       *mode = MATHEMATICA_LINK_CREATE;
204:   else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
205:   else if (isLaunch)  *mode = MATHEMATICA_LINK_LAUNCH;
206:   else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
207:   return(0);
208: }

212: PetscErrorCode  PetscViewerMathematicaSetFromOptions(PetscViewer v)
213: {
214:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
215:   char                    linkname[256];
216:   char                    modename[256];
217:   char                    hostname[256];
218:   char                    type[256];
219:   PetscInt                numPorts;
220:   PetscInt                *ports;
221:   PetscInt                numHosts;
222:   int                     h;
223:   char                    **hosts;
224:   PetscMPIInt             size, rank;
225:   PetscBool               opt;
226:   PetscErrorCode          ierr;

229:   MPI_Comm_size(PetscObjectComm((PetscObject)v), &size);
230:   MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank);

232:   /* Get link name */
233:   PetscOptionsGetString("viewer_", "-math_linkname", linkname, 256, &opt);
234:   if (opt) {
235:     PetscViewerMathematicaSetLinkName(v, linkname);
236:   }
237:   /* Get link port */
238:   numPorts = size;
239:   PetscMalloc(size*sizeof(int), &ports);
240:   PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt);
241:   if (opt) {
242:     if (numPorts > rank) snprintf(linkname, 255, "%6d", ports[rank]);
243:     else                 snprintf(linkname, 255, "%6d", ports[0]);
244:     PetscViewerMathematicaSetLinkName(v, linkname);
245:   }
246:   PetscFree(ports);
247:   /* Get link host */
248:   numHosts = size;
249:   PetscMalloc(size*sizeof(char*), &hosts);
250:   PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt);
251:   if (opt) {
252:     if (numHosts > rank) {
253:       PetscStrncpy(hostname, hosts[rank], 255);
254:     } else {
255:       PetscStrncpy(hostname, hosts[0], 255);
256:     }
257:     PetscViewerMathematicaSetLinkHost(v, hostname);
258:   }
259:   for (h = 0; h < numHosts; h++) {
260:     PetscFree(hosts[h]);
261:   }
262:   PetscFree(hosts);
263:   /* Get link mode */
264:   PetscOptionsGetString("viewer_", "-math_linkmode", modename, 256, &opt);
265:   if (opt) {
266:     LinkMode mode;

268:     PetscViewerMathematicaParseLinkMode_Private(modename, &mode);
269:     PetscViewerMathematicaSetLinkMode(v, mode);
270:   }
271:   /* Get graphics type */
272:   PetscOptionsGetString("viewer_", "-math_graphics", type, 256, &opt);
273:   if (opt) {
274:     PetscBool isMotif, isPS, isPSFile;

276:     PetscStrcasecmp(type, "Motif",  &isMotif);
277:     PetscStrcasecmp(type, "PS",     &isPS);
278:     PetscStrcasecmp(type, "PSFile", &isPSFile);
279:     if (isMotif)       vmath->graphicsType = GRAPHICS_MOTIF;
280:     else if (isPS)     vmath->graphicsType = GRAPHICS_PS_STDOUT;
281:     else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
282:   }
283:   /* Get plot type */
284:   PetscOptionsGetString("viewer_", "-math_type", type, 256, &opt);
285:   if (opt) {
286:     PetscBool isTri, isVecTri, isVec, isSurface;

288:     PetscStrcasecmp(type, "Triangulation",       &isTri);
289:     PetscStrcasecmp(type, "VectorTriangulation", &isVecTri);
290:     PetscStrcasecmp(type, "Vector",              &isVec);
291:     PetscStrcasecmp(type, "Surface",             &isSurface);
292:     if (isTri)          vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
293:     else if (isVecTri)  vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
294:     else if (isVec)     vmath->plotType = MATHEMATICA_VECTOR_PLOT;
295:     else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
296:   }
297:   return(0);
298: }

302: PetscErrorCode  PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
303: {
304:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
305:   PetscErrorCode          ierr;

310:   PetscStrallocpy(name, &vmath->linkname);
311:   return(0);
312: }

316: PetscErrorCode  PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
317: {
318:   char           name[16];

322:   snprintf(name, 16, "%6d", port);
323:   PetscViewerMathematicaSetLinkName(v, name);
324:   return(0);
325: }

329: PetscErrorCode  PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
330: {
331:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;
332:   PetscErrorCode          ierr;

337:   PetscStrallocpy(host, &vmath->linkhost);
338:   return(0);
339: }

343: PetscErrorCode  PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
344: {
345:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) v->data;

348:   vmath->linkmode = mode;
349:   return(0);
350: }

352: /*----------------------------------------- Public Functions --------------------------------------------------------*/
355: /*@C
356:   PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.

358:   Collective on comm

360:   Input Parameters:
361: + comm    - The MPI communicator
362: . port    - [optional] The port to connect on, or PETSC_DECIDE
363: . machine - [optional] The machine to run Mathematica on, or NULL
364: - mode    - [optional] The connection mode, or NULL

366:   Output Parameter:
367: . viewer  - The Mathematica viewer

369:   Level: intermediate

371:   Notes:
372:   Most users should employ the following commands to access the
373:   Mathematica viewers
374: $
375: $    PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
376: $    MatView(Mat matrix, PetscViewer viewer)
377: $
378: $                or
379: $
380: $    PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
381: $    VecView(Vec vector, PetscViewer viewer)

383:    Options Database Keys:
384: $    -viewer_math_linkhost <machine> - The host machine for the kernel
385: $    -viewer_math_linkname <name>    - The full link name for the connection
386: $    -viewer_math_linkport <port>    - The port for the connection
387: $    -viewer_math_mode <mode>        - The mode, e.g. Launch, Connect
388: $    -viewer_math_type <type>        - The plot type, e.g. Triangulation, Vector
389: $    -viewer_math_graphics <output>  - The output type, e.g. Motif, PS, PSFile

391: .keywords: PetscViewer, Mathematica, open

393: .seealso: MatView(), VecView()
394: @*/
395: PetscErrorCode  PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
396: {

400:   PetscViewerCreate(comm, v);
401: #if 0
402:   LinkMode linkmode;
403:   PetscViewerMathematicaSetLinkPort(*v, port);
404:   PetscViewerMathematicaSetLinkHost(*v, machine);
405:   PetscViewerMathematicaParseLinkMode_Private(mode, &linkmode);
406:   PetscViewerMathematicaSetLinkMode(*v, linkmode);
407: #endif
408:   PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA);
409:   return(0);
410: }

414: /*@C
415:   PetscViewerMathematicaGetLink - Returns the link to Mathematica

417:   Input Parameters:
418: . viewer - The Mathematica viewer
419: . link   - The link to Mathematica

421:   Level: intermediate

423: .keywords PetscViewer, Mathematica, link
424: .seealso PetscViewerMathematicaOpen()
425: @*/
426: PetscErrorCode  PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
427: {
428:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

432:   *link = vmath->link;
433:   return(0);
434: }

438: /*@C
439:   PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received

441:   Input Parameters:
442: . viewer - The Mathematica viewer
443: . type   - The packet type to search for, e.g RETURNPKT

445:   Level: advanced

447: .keywords PetscViewer, Mathematica, packets
448: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaGetVector()
449: @*/
450: PetscErrorCode  PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
451: {
452:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
453:   MLINK                   link   = vmath->link; /* The link to Mathematica */
454:   int                     pkt;                 /* The packet type */

457:   while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
458:   if (!pkt) {
459:     MLClearError(link);
460:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, (char*) MLErrorMessage(link));
461:   }
462:   return(0);
463: }

467: /*@C
468:   PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica

470:   Input Parameter:
471: . viewer - The Mathematica viewer

473:   Output Parameter:
474: . name   - The name for new objects created in Mathematica

476:   Level: intermediate

478: .keywords PetscViewer, Mathematica, name
479: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
480: @*/
481: PetscErrorCode  PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
482: {
483:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

488:   *name = vmath->objName;
489:   return(0);
490: }

494: /*@C
495:   PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica

497:   Input Parameters:
498: . viewer - The Mathematica viewer
499: . name   - The name for new objects created in Mathematica

501:   Level: intermediate

503: .keywords PetscViewer, Mathematica, name
504: .seealso PetscViewerMathematicaSetName(), PetscViewerMathematicaClearName()
505: @*/
506: PetscErrorCode  PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
507: {
508:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

513:   vmath->objName = name;
514:   return(0);
515: }

519: /*@C
520:   PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica

522:   Input Parameter:
523: . viewer - The Mathematica viewer

525:   Level: intermediate

527: .keywords PetscViewer, Mathematica, name
528: .seealso PetscViewerMathematicaGetName(), PetscViewerMathematicaSetName()
529: @*/
530: PetscErrorCode  PetscViewerMathematicaClearName(PetscViewer viewer)
531: {
532:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;

536:   vmath->objName = NULL;
537:   return(0);
538: }

542: /*@C
543:   PetscViewerMathematicaGetVector - Retrieve a vector from Mathematica

545:   Input Parameter:
546: . viewer - The Mathematica viewer

548:   Output Parameter:
549: . v      - The vector

551:   Level: intermediate

553: .keywords PetscViewer, Mathematica, vector
554: .seealso VecView(), PetscViewerMathematicaPutVector()
555: @*/
556: PetscErrorCode  PetscViewerMathematicaGetVector(PetscViewer viewer, Vec v)
557: {
558:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
559:   MLINK                   link;   /* The link to Mathematica */
560:   char                    *name;
561:   PetscScalar             *mArray,*array;
562:   long                    mSize;
563:   int                     n;
564:   PetscErrorCode          ierr;


570:   /* Determine the object name */
571:   if (!vmath->objName) name = "vec";
572:   else                 name = (char*) vmath->objName;

574:   link = vmath->link;
575:   VecGetLocalSize(v, &n);
576:   VecGetArray(v, &array);
577:   MLPutFunction(link, "EvaluatePacket", 1);
578:   MLPutSymbol(link, name);
579:   MLEndPacket(link);
580:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
581:   MLGetRealList(link, &mArray, &mSize);
582:   if (n != mSize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Incompatible vector sizes %d %d",n,mSize);
583:   PetscMemcpy(array, mArray, mSize * sizeof(double));
584:   MLDisownRealList(link, mArray, mSize);
585:   VecRestoreArray(v, &array);
586:   return(0);
587: }

591: /*@C
592:   PetscViewerMathematicaPutVector - Send a vector to Mathematica

594:   Input Parameters:
595: + viewer - The Mathematica viewer
596: - v      - The vector

598:   Level: intermediate

600: .keywords PetscViewer, Mathematica, vector
601: .seealso VecView(), PetscViewerMathematicaGetVector()
602: @*/
603: PetscErrorCode  PetscViewerMathematicaPutVector(PetscViewer viewer, Vec v)
604: {
605:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
606:   MLINK                   link   = vmath->link; /* The link to Mathematica */
607:   char                    *name;
608:   PetscScalar             *array;
609:   int                     n;
610:   PetscErrorCode          ierr;

613:   /* Determine the object name */
614:   if (!vmath->objName) name = "vec";
615:   else                 name = (char*) vmath->objName;

617:   VecGetLocalSize(v, &n);
618:   VecGetArray(v, &array);

620:   /* Send the Vector object */
621:   MLPutFunction(link, "EvaluatePacket", 1);
622:   MLPutFunction(link, "Set", 2);
623:   MLPutSymbol(link, name);
624:   MLPutRealList(link, array, n);
625:   MLEndPacket(link);
626:   /* Skip packets until ReturnPacket */
627:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
628:   /* Skip ReturnPacket */
629:   MLNewPacket(link);

631:   VecRestoreArray(v, &array);
632:   return(0);
633: }

635: PetscErrorCode  PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
636: {
637:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
638:   MLINK                   link   = vmath->link; /* The link to Mathematica */
639:   char                    *name;
640:   PetscErrorCode          ierr;

643:   /* Determine the object name */
644:   if (!vmath->objName) name = "mat";
645:   else                 name = (char*) vmath->objName;

647:   /* Send the dense matrix object */
648:   MLPutFunction(link, "EvaluatePacket", 1);
649:   MLPutFunction(link, "Set", 2);
650:   MLPutSymbol(link, name);
651:   MLPutFunction(link, "Transpose", 1);
652:   MLPutFunction(link, "Partition", 2);
653:   MLPutRealList(link, a, m*n);
654:   MLPutInteger(link, m);
655:   MLEndPacket(link);
656:   /* Skip packets until ReturnPacket */
657:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
658:   /* Skip ReturnPacket */
659:   MLNewPacket(link);
660:   return(0);
661: }

663: PetscErrorCode  PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
664: {
665:   PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica*) viewer->data;
666:   MLINK                   link   = vmath->link; /* The link to Mathematica */
667:   const char              *symbol;
668:   char                    *name;
669:   PetscBool               match;
670:   PetscErrorCode          ierr;

673:   /* Determine the object name */
674:   if (!vmath->objName) name = "mat";
675:   else                 name = (char*) vmath->objName;

677:   /* Make sure Mathematica recognizes sparse matrices */
678:   MLPutFunction(link, "EvaluatePacket", 1);
679:   MLPutFunction(link, "Needs", 1);
680:   MLPutString(link, "LinearAlgebra`CSRMatrix`");
681:   MLEndPacket(link);
682:   /* Skip packets until ReturnPacket */
683:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
684:   /* Skip ReturnPacket */
685:   MLNewPacket(link);

687:   /* Send the CSRMatrix object */
688:   MLPutFunction(link, "EvaluatePacket", 1);
689:   MLPutFunction(link, "Set", 2);
690:   MLPutSymbol(link, name);
691:   MLPutFunction(link, "CSRMatrix", 5);
692:   MLPutInteger(link, m);
693:   MLPutInteger(link, n);
694:   MLPutFunction(link, "Plus", 2);
695:   MLPutIntegerList(link, i, m+1);
696:   MLPutInteger(link, 1);
697:   MLPutFunction(link, "Plus", 2);
698:   MLPutIntegerList(link, j, i[m]);
699:   MLPutInteger(link, 1);
700:   MLPutRealList(link, a, i[m]);
701:   MLEndPacket(link);
702:   /* Skip packets until ReturnPacket */
703:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
704:   /* Skip ReturnPacket */
705:   MLNewPacket(link);

707:   /* Check that matrix is valid */
708:   MLPutFunction(link, "EvaluatePacket", 1);
709:   MLPutFunction(link, "ValidQ", 1);
710:   MLPutSymbol(link, name);
711:   MLEndPacket(link);
712:   PetscViewerMathematicaSkipPackets(viewer, RETURNPKT);
713:   MLGetSymbol(link, &symbol);
714:   PetscStrcmp("True", (char*) symbol, &match);
715:   if (!match) {
716:     MLDisownSymbol(link, symbol);
717:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
718:   }
719:   MLDisownSymbol(link, symbol);
720:   /* Skip ReturnPacket */
721:   MLNewPacket(link);
722:   return(0);
723: }