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