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(PetscNewLog(v, &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 Level: intermediate 293 294 Notes: 295 Most users should employ the following commands to access the 296 Mathematica viewers 297 $ 298 $ PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer) 299 $ MatView(Mat matrix, PetscViewer viewer) 300 $ 301 $ or 302 $ 303 $ PetscViewerMathematicaOpen(MPI_Comm comm, int port, char *machine, char *mode, PetscViewer &viewer) 304 $ VecView(Vec vector, PetscViewer viewer) 305 306 Options Database Keys: 307 + -viewer_math_linkhost <machine> - The host machine for the kernel 308 . -viewer_math_linkname <name> - The full link name for the connection 309 . -viewer_math_linkport <port> - The port for the connection 310 . -viewer_math_mode <mode> - The mode, e.g. Launch, Connect 311 . -viewer_math_type <type> - The plot type, e.g. Triangulation, Vector 312 - -viewer_math_graphics <output> - The output type, e.g. Motif, PS, PSFile 313 314 .seealso: `MatView()`, `VecView()` 315 @*/ 316 PetscErrorCode PetscViewerMathematicaOpen(MPI_Comm comm, int port, const char machine[], const char mode[], PetscViewer *v) { 317 PetscFunctionBegin; 318 PetscCall(PetscViewerCreate(comm, v)); 319 #if 0 320 LinkMode linkmode; 321 PetscCall(PetscViewerMathematicaSetLinkPort(*v, port)); 322 PetscCall(PetscViewerMathematicaSetLinkHost(*v, machine)); 323 PetscCall(PetscViewerMathematicaParseLinkMode(mode, &linkmode)); 324 PetscCall(PetscViewerMathematicaSetLinkMode(*v, linkmode)); 325 #endif 326 PetscCall(PetscViewerSetType(*v, PETSC_VIEWER_MATHEMATICA)); 327 PetscFunctionReturn(0); 328 } 329 330 /*@C 331 PetscViewerMathematicaGetLink - Returns the link to Mathematica 332 333 Input Parameters: 334 + viewer - The Mathematica viewer 335 - link - The link to Mathematica 336 337 Level: intermediate 338 339 .keywords PetscViewer, Mathematica, link 340 .seealso `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 .keywords PetscViewer, Mathematica, packets 361 .seealso `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaGetVector()` 362 @*/ 363 PetscErrorCode PetscViewerMathematicaSkipPackets(PetscViewer viewer, int type) { 364 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 365 MLINK link = vmath->link; /* The link to Mathematica */ 366 int pkt; /* The packet type */ 367 368 PetscFunctionBegin; 369 while ((pkt = MLNextPacket(link)) && (pkt != type)) MLNewPacket(link); 370 if (!pkt) { 371 MLClearError(link); 372 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, (char *)MLErrorMessage(link)); 373 } 374 PetscFunctionReturn(0); 375 } 376 377 /*@C 378 PetscViewerMathematicaGetName - Retrieve the default name for objects communicated to Mathematica 379 380 Input Parameter: 381 . viewer - The Mathematica viewer 382 383 Output Parameter: 384 . name - The name for new objects created in Mathematica 385 386 Level: intermediate 387 388 .keywords PetscViewer, Mathematica, name 389 .seealso `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaClearName()` 390 @*/ 391 PetscErrorCode PetscViewerMathematicaGetName(PetscViewer viewer, const char **name) { 392 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 393 394 PetscFunctionBegin; 395 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 396 PetscValidPointer(name, 2); 397 *name = vmath->objName; 398 PetscFunctionReturn(0); 399 } 400 401 /*@C 402 PetscViewerMathematicaSetName - Override the default name for objects communicated to Mathematica 403 404 Input Parameters: 405 + viewer - The Mathematica viewer 406 - name - The name for new objects created in Mathematica 407 408 Level: intermediate 409 410 .keywords PetscViewer, Mathematica, name 411 .seealso `PetscViewerMathematicaSetName()`, `PetscViewerMathematicaClearName()` 412 @*/ 413 PetscErrorCode PetscViewerMathematicaSetName(PetscViewer viewer, const char name[]) { 414 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 418 PetscValidPointer(name, 2); 419 vmath->objName = name; 420 PetscFunctionReturn(0); 421 } 422 423 /*@C 424 PetscViewerMathematicaClearName - Use the default name for objects communicated to Mathematica 425 426 Input Parameter: 427 . viewer - The Mathematica viewer 428 429 Level: intermediate 430 431 .keywords PetscViewer, Mathematica, name 432 .seealso `PetscViewerMathematicaGetName()`, `PetscViewerMathematicaSetName()` 433 @*/ 434 PetscErrorCode PetscViewerMathematicaClearName(PetscViewer viewer) { 435 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 436 437 PetscFunctionBegin; 438 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 439 vmath->objName = NULL; 440 PetscFunctionReturn(0); 441 } 442 443 /*@C 444 PetscViewerMathematicaGetVector - Retrieve a vector from Mathematica 445 446 Input Parameter: 447 . viewer - The Mathematica viewer 448 449 Output Parameter: 450 . v - The vector 451 452 Level: intermediate 453 454 .keywords PetscViewer, Mathematica, vector 455 .seealso `VecView()`, `PetscViewerMathematicaPutVector()` 456 @*/ 457 PetscErrorCode PetscViewerMathematicaGetVector(PetscViewer viewer, Vec v) { 458 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 459 MLINK link; /* The link to Mathematica */ 460 char *name; 461 PetscScalar *mArray, *array; 462 long mSize; 463 int n; 464 465 PetscFunctionBegin; 466 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 467 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 468 469 /* Determine the object name */ 470 if (!vmath->objName) name = "vec"; 471 else name = (char *)vmath->objName; 472 473 link = vmath->link; 474 PetscCall(VecGetLocalSize(v, &n)); 475 PetscCall(VecGetArray(v, &array)); 476 MLPutFunction(link, "EvaluatePacket", 1); 477 MLPutSymbol(link, name); 478 MLEndPacket(link); 479 PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT)); 480 MLGetRealList(link, &mArray, &mSize); 481 PetscCheck(n == mSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Incompatible vector sizes %d %d", n, mSize); 482 PetscCall(PetscArraycpy(array, mArray, mSize)); 483 MLDisownRealList(link, mArray, mSize); 484 PetscCall(VecRestoreArray(v, &array)); 485 PetscFunctionReturn(0); 486 } 487 488 /*@C 489 PetscViewerMathematicaPutVector - Send a vector to Mathematica 490 491 Input Parameters: 492 + viewer - The Mathematica viewer 493 - v - The vector 494 495 Level: intermediate 496 497 .keywords PetscViewer, Mathematica, vector 498 .seealso `VecView()`, `PetscViewerMathematicaGetVector()` 499 @*/ 500 PetscErrorCode PetscViewerMathematicaPutVector(PetscViewer viewer, Vec v) { 501 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 502 MLINK link = vmath->link; /* The link to Mathematica */ 503 char *name; 504 PetscScalar *array; 505 int n; 506 507 PetscFunctionBegin; 508 /* Determine the object name */ 509 if (!vmath->objName) name = "vec"; 510 else name = (char *)vmath->objName; 511 512 PetscCall(VecGetLocalSize(v, &n)); 513 PetscCall(VecGetArray(v, &array)); 514 515 /* Send the Vector object */ 516 MLPutFunction(link, "EvaluatePacket", 1); 517 MLPutFunction(link, "Set", 2); 518 MLPutSymbol(link, name); 519 MLPutRealList(link, array, n); 520 MLEndPacket(link); 521 /* Skip packets until ReturnPacket */ 522 PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT)); 523 /* Skip ReturnPacket */ 524 MLNewPacket(link); 525 526 PetscCall(VecRestoreArray(v, &array)); 527 PetscFunctionReturn(0); 528 } 529 530 PetscErrorCode PetscViewerMathematicaPutMatrix(PetscViewer viewer, int m, int n, PetscReal *a) { 531 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 532 MLINK link = vmath->link; /* The link to Mathematica */ 533 char *name; 534 535 PetscFunctionBegin; 536 /* Determine the object name */ 537 if (!vmath->objName) name = "mat"; 538 else name = (char *)vmath->objName; 539 540 /* Send the dense matrix object */ 541 MLPutFunction(link, "EvaluatePacket", 1); 542 MLPutFunction(link, "Set", 2); 543 MLPutSymbol(link, name); 544 MLPutFunction(link, "Transpose", 1); 545 MLPutFunction(link, "Partition", 2); 546 MLPutRealList(link, a, m * n); 547 MLPutInteger(link, m); 548 MLEndPacket(link); 549 /* Skip packets until ReturnPacket */ 550 PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT)); 551 /* Skip ReturnPacket */ 552 MLNewPacket(link); 553 PetscFunctionReturn(0); 554 } 555 556 PetscErrorCode PetscViewerMathematicaPutCSRMatrix(PetscViewer viewer, int m, int n, int *i, int *j, PetscReal *a) { 557 PetscViewer_Mathematica *vmath = (PetscViewer_Mathematica *)viewer->data; 558 MLINK link = vmath->link; /* The link to Mathematica */ 559 const char *symbol; 560 char *name; 561 PetscBool match; 562 563 PetscFunctionBegin; 564 /* Determine the object name */ 565 if (!vmath->objName) name = "mat"; 566 else name = (char *)vmath->objName; 567 568 /* Make sure Mathematica recognizes sparse matrices */ 569 MLPutFunction(link, "EvaluatePacket", 1); 570 MLPutFunction(link, "Needs", 1); 571 MLPutString(link, "LinearAlgebra`CSRMatrix`"); 572 MLEndPacket(link); 573 /* Skip packets until ReturnPacket */ 574 PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT)); 575 /* Skip ReturnPacket */ 576 MLNewPacket(link); 577 578 /* Send the CSRMatrix object */ 579 MLPutFunction(link, "EvaluatePacket", 1); 580 MLPutFunction(link, "Set", 2); 581 MLPutSymbol(link, name); 582 MLPutFunction(link, "CSRMatrix", 5); 583 MLPutInteger(link, m); 584 MLPutInteger(link, n); 585 MLPutFunction(link, "Plus", 2); 586 MLPutIntegerList(link, i, m + 1); 587 MLPutInteger(link, 1); 588 MLPutFunction(link, "Plus", 2); 589 MLPutIntegerList(link, j, i[m]); 590 MLPutInteger(link, 1); 591 MLPutRealList(link, a, i[m]); 592 MLEndPacket(link); 593 /* Skip packets until ReturnPacket */ 594 PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT)); 595 /* Skip ReturnPacket */ 596 MLNewPacket(link); 597 598 /* Check that matrix is valid */ 599 MLPutFunction(link, "EvaluatePacket", 1); 600 MLPutFunction(link, "ValidQ", 1); 601 MLPutSymbol(link, name); 602 MLEndPacket(link); 603 PetscCall(PetscViewerMathematicaSkipPackets(viewer, RETURNPKT)); 604 MLGetSymbol(link, &symbol); 605 PetscCall(PetscStrcmp("True", (char *)symbol, &match)); 606 if (!match) { 607 MLDisownSymbol(link, symbol); 608 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid CSR matrix in Mathematica"); 609 } 610 MLDisownSymbol(link, symbol); 611 /* Skip ReturnPacket */ 612 MLNewPacket(link); 613 PetscFunctionReturn(0); 614 } 615