Actual source code: mathematica.c
1: #include <petsc/private/viewerimpl.h>
2: #include <mathematica.h>
4: #if defined(PETSC_HAVE__SNPRINTF) && !defined(PETSC_HAVE_SNPRINTF)
5: #define snprintf _snprintf
6: #endif
8: PetscViewer PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE = NULL;
9: static void *mathematicaEnv = NULL;
11: static PetscBool PetscViewerMathematicaPackageInitialized = PETSC_FALSE;
12: /*@C
13: PetscViewerMathematicaFinalizePackage - This function destroys everything in the PETSc interface to Mathematica. It is
14: called from PetscFinalize().
16: Level: developer
18: .seealso: `PetscFinalize()`
19: @*/
20: PetscErrorCode PetscViewerMathematicaFinalizePackage(void)
21: {
22: PetscFunctionBegin;
23: if (mathematicaEnv) MLDeinitialize((MLEnvironment)mathematicaEnv);
24: PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
25: PetscFunctionReturn(PETSC_SUCCESS);
26: }
28: /*@C
29: PetscViewerMathematicaInitializePackage - This function initializes everything in the PETSc interface to Mathematica. It is
30: called from `PetscViewerInitializePackage()`.
32: Level: developer
34: .seealso: `PetscSysInitializePackage()`, `PetscInitialize()`
35: @*/
36: PetscErrorCode PetscViewerMathematicaInitializePackage(void)
37: {
38: PetscError ierr;
40: PetscFunctionBegin;
41: if (PetscViewerMathematicaPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
42: PetscViewerMathematicaPackageInitialized = PETSC_TRUE;
44: mathematicaEnv = (void *)MLInitialize(0);
46: PetscCall(PetscRegisterFinalize(PetscViewerMathematicaFinalizePackage));
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: static PetscErrorCode PetscViewerInitializeMathematicaWorld_Private()
51: {
52: PetscFunctionBegin;
53: if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscFunctionReturn(PETSC_SUCCESS);
54: PetscCall(PetscViewerMathematicaOpen(PETSC_COMM_WORLD, PETSC_DECIDE, NULL, NULL, &PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
55: PetscFunctionReturn(PETSC_SUCCESS);
56: }
58: static PetscErrorCode PetscViewerDestroy_Mathematica(PetscViewer viewer)
59: {
60: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
62: PetscFunctionBegin;
63: MLClose(vmath->link);
64: PetscCall(PetscFree(vmath->linkname));
65: PetscCall(PetscFree(vmath->linkhost));
66: PetscCall(PetscFree(vmath));
67: PetscFunctionReturn(PETSC_SUCCESS);
68: }
70: static PetscErrorCode PetscViewerDestroyMathematica_Private(void)
71: {
72: PetscFunctionBegin;
73: if (PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE) PetscCall(PetscViewerDestroy(PETSC_VIEWER_MATHEMATICA_WORLD_PRIVATE));
74: PetscFunctionReturn(PETSC_SUCCESS);
75: }
77: static PetscErrorCode PetscViewerMathematicaSetupConnection_Private(PetscViewer v)
78: {
79: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
80: #if defined(MATHEMATICA_3_0)
81: int argc = 6;
82: char *argv[6];
83: #else
84: int argc = 5;
85: char *argv[5];
86: #endif
87: char hostname[256];
88: long lerr;
90: PetscFunctionBegin;
91: /* Link name */
92: argv[0] = "-linkname";
93: if (!vmath->linkname) argv[1] = "math -mathlink";
94: else argv[1] = vmath->linkname;
96: /* Link host */
97: argv[2] = "-linkhost";
98: if (!vmath->linkhost) {
99: PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
100: argv[3] = hostname;
101: } else argv[3] = vmath->linkhost;
103: /* Link mode */
104: #if defined(MATHEMATICA_3_0)
105: argv[4] = "-linkmode";
106: switch (vmath->linkmode) {
107: case MATHEMATICA_LINK_CREATE:
108: argv[5] = "Create";
109: break;
110: case MATHEMATICA_LINK_CONNECT:
111: argv[5] = "Connect";
112: break;
113: case MATHEMATICA_LINK_LAUNCH:
114: argv[5] = "Launch";
115: break;
116: }
117: #else
118: switch (vmath->linkmode) {
119: case MATHEMATICA_LINK_CREATE:
120: argv[4] = "-linkcreate";
121: break;
122: case MATHEMATICA_LINK_CONNECT:
123: argv[4] = "-linkconnect";
124: break;
125: case MATHEMATICA_LINK_LAUNCH:
126: argv[4] = "-linklaunch";
127: break;
128: }
129: #endif
130: vmath->link = MLOpenInEnv(mathematicaEnv, argc, argv, &lerr);
131: #endif
132: PetscFunctionReturn(PETSC_SUCCESS);
133: }
135: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Mathematica(PetscViewer v)
136: {
137: PetscViewer_Mathematica *vmath;
139: PetscFunctionBegin;
140: PetscCall(PetscViewerMathematicaInitializePackage());
142: PetscCall(PetscNew(&vmath));
143: v->data = (void *)vmath;
144: v->ops->destroy = PetscViewerDestroy_Mathematica;
145: v->ops->flush = 0;
146: PetscCall(PetscStrallocpy(PETSC_VIEWER_MATHEMATICA, &((PetscObject)v)->type_name));
148: vmath->linkname = NULL;
149: vmath->linkhost = NULL;
150: vmath->linkmode = MATHEMATICA_LINK_CONNECT;
151: vmath->graphicsType = GRAPHICS_MOTIF;
152: vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
153: vmath->objName = NULL;
155: PetscCall(PetscViewerMathematicaSetFromOptions(v));
156: PetscCall(PetscViewerMathematicaSetupConnection_Private(v));
157: PetscFunctionReturn(PETSC_SUCCESS);
158: }
160: static PetscErrorCode PetscViewerMathematicaParseLinkMode(char *modename, LinkMode *mode)
161: {
162: PetscBool isCreate, isConnect, isLaunch;
164: PetscFunctionBegin;
165: PetscCall(PetscStrcasecmp(modename, "Create", &isCreate));
166: PetscCall(PetscStrcasecmp(modename, "Connect", &isConnect));
167: PetscCall(PetscStrcasecmp(modename, "Launch", &isLaunch));
168: if (isCreate) *mode = MATHEMATICA_LINK_CREATE;
169: else if (isConnect) *mode = MATHEMATICA_LINK_CONNECT;
170: else if (isLaunch) *mode = MATHEMATICA_LINK_LAUNCH;
171: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid Mathematica link mode: %s", modename);
172: PetscFunctionReturn(PETSC_SUCCESS);
173: }
175: PetscErrorCode PetscViewerMathematicaSetFromOptions(PetscViewer v)
176: {
177: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
178: char linkname[256];
179: char modename[256];
180: char hostname[256];
181: char type[256];
182: PetscInt numPorts;
183: PetscInt *ports;
184: PetscInt numHosts;
185: int h;
186: char **hosts;
187: PetscMPIInt size, rank;
188: PetscBool opt;
190: PetscFunctionBegin;
191: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
192: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));
194: /* Get link name */
195: PetscCall(PetscOptionsGetString("viewer_", "-math_linkname", linkname, sizeof(linkname), &opt));
196: if (opt) PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
197: /* Get link port */
198: numPorts = size;
199: PetscCall(PetscMalloc1(size, &ports));
200: PetscCall(PetscOptionsGetIntArray("viewer_", "-math_linkport", ports, &numPorts, &opt));
201: if (opt) {
202: if (numPorts > rank) snprintf(linkname, sizeof(linkname), "%6d", ports[rank]);
203: else snprintf(linkname, sizeof(linkname), "%6d", ports[0]);
204: PetscCall(PetscViewerMathematicaSetLinkName(v, linkname));
205: }
206: PetscCall(PetscFree(ports));
207: /* Get link host */
208: numHosts = size;
209: PetscCall(PetscMalloc1(size, &hosts));
210: PetscCall(PetscOptionsGetStringArray("viewer_", "-math_linkhost", hosts, &numHosts, &opt));
211: if (opt) {
212: if (numHosts > rank) {
213: PetscCall(PetscStrncpy(hostname, hosts[rank], sizeof(hostname)));
214: } else {
215: PetscCall(PetscStrncpy(hostname, hosts[0], sizeof(hostname)));
216: }
217: PetscCall(PetscViewerMathematicaSetLinkHost(v, hostname));
218: }
219: for (h = 0; h < numHosts; h++) PetscCall(PetscFree(hosts[h]));
220: PetscCall(PetscFree(hosts));
221: /* Get link mode */
222: PetscCall(PetscOptionsGetString("viewer_", "-math_linkmode", modename, sizeof(modename), &opt));
223: if (opt) {
224: LinkMode mode;
226: PetscCall(PetscViewerMathematicaParseLinkMode(modename, &mode));
227: PetscCall(PetscViewerMathematicaSetLinkMode(v, mode));
228: }
229: /* Get graphics type */
230: PetscCall(PetscOptionsGetString("viewer_", "-math_graphics", type, sizeof(type), &opt));
231: if (opt) {
232: PetscBool isMotif, isPS, isPSFile;
234: PetscCall(PetscStrcasecmp(type, "Motif", &isMotif));
235: PetscCall(PetscStrcasecmp(type, "PS", &isPS));
236: PetscCall(PetscStrcasecmp(type, "PSFile", &isPSFile));
237: if (isMotif) vmath->graphicsType = GRAPHICS_MOTIF;
238: else if (isPS) vmath->graphicsType = GRAPHICS_PS_STDOUT;
239: else if (isPSFile) vmath->graphicsType = GRAPHICS_PS_FILE;
240: }
241: /* Get plot type */
242: PetscCall(PetscOptionsGetString("viewer_", "-math_type", type, sizeof(type), &opt));
243: if (opt) {
244: PetscBool isTri, isVecTri, isVec, isSurface;
246: PetscCall(PetscStrcasecmp(type, "Triangulation", &isTri));
247: PetscCall(PetscStrcasecmp(type, "VectorTriangulation", &isVecTri));
248: PetscCall(PetscStrcasecmp(type, "Vector", &isVec));
249: PetscCall(PetscStrcasecmp(type, "Surface", &isSurface));
250: if (isTri) vmath->plotType = MATHEMATICA_TRIANGULATION_PLOT;
251: else if (isVecTri) vmath->plotType = MATHEMATICA_VECTOR_TRIANGULATION_PLOT;
252: else if (isVec) vmath->plotType = MATHEMATICA_VECTOR_PLOT;
253: else if (isSurface) vmath->plotType = MATHEMATICA_SURFACE_PLOT;
254: }
255: PetscFunctionReturn(PETSC_SUCCESS);
256: }
258: PetscErrorCode PetscViewerMathematicaSetLinkName(PetscViewer v, const char *name)
259: {
260: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
262: PetscFunctionBegin;
264: PetscAssertPointer(name, 2);
265: PetscCall(PetscStrallocpy(name, &vmath->linkname));
266: PetscFunctionReturn(PETSC_SUCCESS);
267: }
269: PetscErrorCode PetscViewerMathematicaSetLinkPort(PetscViewer v, int port)
270: {
271: char name[16];
273: PetscFunctionBegin;
274: snprintf(name, 16, "%6d", port);
275: PetscCall(PetscViewerMathematicaSetLinkName(v, name));
276: PetscFunctionReturn(PETSC_SUCCESS);
277: }
279: PetscErrorCode PetscViewerMathematicaSetLinkHost(PetscViewer v, const char *host)
280: {
281: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
283: PetscFunctionBegin;
285: PetscAssertPointer(host, 2);
286: PetscCall(PetscStrallocpy(host, &vmath->linkhost));
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: PetscErrorCode PetscViewerMathematicaSetLinkMode(PetscViewer v, LinkMode mode)
291: {
292: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)v->data;
294: PetscFunctionBegin;
295: vmath->linkmode = mode;
296: PetscFunctionReturn(PETSC_SUCCESS);
297: }
299: /*@
300: PetscViewerMathematicaOpen - Communicates with Mathemtica using MathLink.
302: Collective
304: Input Parameters:
305: + comm - The MPI communicator
306: . port - [optional] The port to connect on, or PETSC_DECIDE
307: . machine - [optional] The machine to run Mathematica on, or NULL
308: - mode - [optional] The connection mode, or NULL
310: Output Parameter:
311: . v - The Mathematica viewer
313: Options Database Keys:
314: + -viewer_math_linkhost <machine> - The host machine for the kernel
315: . -viewer_math_linkname <name> - The full link name for the connection
316: . -viewer_math_linkport <port> - The port for the connection
317: . -viewer_math_mode <mode> - The mode, e.g. Launch, Connect
318: . -viewer_math_type <type> - The plot type, e.g. Triangulation, Vector
319: - -viewer_math_graphics <output> - The output type, e.g. Motif, PS, PSFile
321: Level: intermediate
323: Note:
324: Most users should employ the following commands to access the
325: Mathematica viewers
326: .vb
327: PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
328: MatView(Mat matrix, PetscViewer viewer)
330: or
332: PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer)
333: VecView(Vec vector, PetscViewer viewer)
334: .ve
336: .seealso: `PETSCVIEWERMATHEMATICA`, `MatView()`, `VecView()`
337: @*/
338: PetscErrorCode PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v)
339: {
340: PetscFunctionBegin;
341: PetscCall(PetscViewerCreate(comm, v));
342: #if 0
343: LinkMode linkmode;
344: PetscCall(PetscViewerMathematicaSetLinkPort(*v, port));
345: PetscCall(PetscViewerMathematicaSetLinkHost(*v, machine));
346: PetscCall(PetscViewerMathematicaParseLinkMode(mode, &linkmode));
347: PetscCall(PetscViewerMathematicaSetLinkMode(*v, linkmode));
348: #endif
349: PetscCall(PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA));
350: PetscFunctionReturn(PETSC_SUCCESS);
351: }
353: /*
354: PetscViewerMathematicaGetLink - Returns the link to Mathematica from a `PETSCVIEWERMATHEMATICA`
356: Input Parameters:
357: + viewer - The Mathematica viewer
358: - link - The link to Mathematica
360: Level: intermediate
362: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaOpen()`
363: */
364: static PetscErrorCode PetscViewerMathematicaGetLink(PetscViewer viewer, MLINK *link)
365: {
366: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
368: PetscFunctionBegin;
370: *link = vmath->link;
371: PetscFunctionReturn(PETSC_SUCCESS);
372: }
374: /*@C
375: PetscViewerMathematicaSkipPackets - Discard packets sent by Mathematica until a certain packet type is received
377: Input Parameters:
378: + viewer - The Mathematica viewer
379: - type - The packet type to search for, e.g RETURNPKT
381: Level: advanced
383: .seealso: `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaGetVector()`
384: @*/
385: PetscErrorCode PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type)
386: {
387: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
388: MLINK link = vmath->link; /* The link to Mathematica */
389: int pkt; /* The packet type */
391: PetscFunctionBegin;
392: while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link);
393: if (!pkt) {
394: MLClearError(link);
395: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, (char *)MLErrorMessage(link));
396: }
397: PetscFunctionReturn(PETSC_SUCCESS);
398: }
400: /*@C
401: PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA`
403: Input Parameter:
404: . viewer - The Mathematica viewer
406: Output Parameter:
407: . name - The name for new objects created in Mathematica
409: Level: intermediate
411: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaClearName()`
412: @*/
413: PetscErrorCode PetscViewerMathematicaGetName(PetscViewer viewer, const char **name)
414: {
415: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
417: PetscFunctionBegin;
419: PetscAssertPointer(name, 2);
420: *name = vmath->objName;
421: PetscFunctionReturn(PETSC_SUCCESS);
422: }
424: /*@C
425: PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica via `PETSCVIEWERMATHEMATICA`
427: Input Parameters:
428: + viewer - The Mathematica viewer
429: - name - The name for new objects created in Mathematica
431: Level: intermediate
433: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaClearName()`
434: @*/
435: PetscErrorCode PetscViewerMathematicaSetName(PetscViewer viewer, const char name[])
436: {
437: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
439: PetscFunctionBegin;
441: PetscAssertPointer(name, 2);
442: vmath->objName = name;
443: PetscFunctionReturn(PETSC_SUCCESS);
444: }
446: /*@
447: PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica
449: Input Parameter:
450: . viewer - The Mathematica viewer
452: Level: intermediate
454: .seealso: `PETSCVIEWERMATHEMATICA`, `PetscViewerMathematicaGetName()`, `PetscViewerMathematicaSetName()`
455: @*/
456: PetscErrorCode PetscViewerMathematicaClearName(PetscViewer viewer)
457: {
458: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
460: PetscFunctionBegin;
462: vmath->objName = NULL;
463: PetscFunctionReturn(PETSC_SUCCESS);
464: }
466: PetscErrorCode PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a)
467: {
468: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
469: MLINK link = vmath->link; /* The link to Mathematica */
470: char *name;
472: PetscFunctionBegin;
473: /* Determine the object name */
474: if (!vmath->objName) name = "mat";
475: else name = (char *)vmath->objName;
477: /* Send the dense matrix object */
478: MLPutFunction(link, "EvaluatePacket", 1);
479: MLPutFunction(link, "Set", 2);
480: MLPutSymbol(link, name);
481: MLPutFunction(link, "Transpose", 1);
482: MLPutFunction(link, "Partition", 2);
483: MLPutRealList(link, a, m * n);
484: MLPutInteger(link, m);
485: MLEndPacket(link);
486: /* Skip packets until ReturnPacket */
487: PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
488: /* Skip ReturnPacket */
489: MLNewPacket(link);
490: PetscFunctionReturn(PETSC_SUCCESS);
491: }
493: PetscErrorCode PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a)
494: {
495: PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data;
496: MLINK link = vmath->link; /* The link to Mathematica */
497: const char *symbol;
498: char *name;
499: PetscBool match;
501: PetscFunctionBegin;
502: /* Determine the object name */
503: if (!vmath->objName) name = "mat";
504: else name = (char *)vmath->objName;
506: /* Make sure Mathematica recognizes sparse matrices */
507: MLPutFunction(link, "EvaluatePacket", 1);
508: MLPutFunction(link, "Needs", 1);
509: MLPutString(link, "LinearAlgebra`CSRMatrix`");
510: MLEndPacket(link);
511: /* Skip packets until ReturnPacket */
512: PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
513: /* Skip ReturnPacket */
514: MLNewPacket(link);
516: /* Send the CSRMatrix object */
517: MLPutFunction(link, "EvaluatePacket", 1);
518: MLPutFunction(link, "Set", 2);
519: MLPutSymbol(link, name);
520: MLPutFunction(link, "CSRMatrix", 5);
521: MLPutInteger(link, m);
522: MLPutInteger(link, n);
523: MLPutFunction(link, "Plus", 2);
524: MLPutIntegerList(link, i, m + 1);
525: MLPutInteger(link, 1);
526: MLPutFunction(link, "Plus", 2);
527: MLPutIntegerList(link, j, i[m]);
528: MLPutInteger(link, 1);
529: MLPutRealList(link, a, i[m]);
530: MLEndPacket(link);
531: /* Skip packets until ReturnPacket */
532: PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
533: /* Skip ReturnPacket */
534: MLNewPacket(link);
536: /* Check that matrix is valid */
537: MLPutFunction(link, "EvaluatePacket", 1);
538: MLPutFunction(link, "ValidQ", 1);
539: MLPutSymbol(link, name);
540: MLEndPacket(link);
541: PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT));
542: MLGetSymbol(link, &symbol);
543: PetscCall(PetscStrcmp("True", (char *)symbol, &match));
544: if (!match) {
545: MLDisownSymbol(link, symbol);
546: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica");
547: }
548: MLDisownSymbol(link, symbol);
549: /* Skip ReturnPacket */
550: MLNewPacket(link);
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }