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