SimV2 reader

VisIt currently interfaces to simulations via libsim and the SimV1 reader. There are a number of features that the SimV1 reader was not designed to provide. To address the list of missing features and other complications, libsim must be enhanced and a SimV2 reader must be created.

Helping out

This effort has been completed. To get involved in the next round of development, see Additional in-situ work.

Missing features

This table lists some features that should appear in a SimV2 plugin as well as the status of work on each particular feature.

For now, SimV2 has been started as an exact copy of the SimV1 reader. New structures have been added and new fields have been added to the existing data interface structures. For now, the control interface is unchanged. The control functions may eventually change somewhat in order to accommodate new SimV2 features. The data interface may also change as development continues in order to hide structure members and replace that access with accessor functions.

Features Status
Species Done
CSG meshes Done
AMR meshes (see AMR movie) Done
vector data Done
tensor data Done
A way of saving a picture without bringing up the GUI. For example from running a simulation in batch mode. Done
Add a void* data argument to all simulation callbacks so the simulation can pass in a pointer to its data structures rather than having to rely on global variables Done
Support coordinates in single XY or XYZ array or maybe even strided array. Separating the coordinates out like we do not is not always convenient. Done
Delete all of the structures that are returned from sim callback functions so we don't leak memory. Done
Change how callbacks are registered so the host app does not to be linked with --export-dynamic Done
Add a new callback that permits collective communication Done
Simulations often run on compute nodes that can't access the outside world. Enable simulations to connect to outside world via SSH tunnelling mechanism already in VisIt. Done (supported in SimV1 for VisIt 1.12)

Additional issues fixed

  • VisItUpdatePlots now blocks until VisIt has updated its plots. The sim used to send VisIt an update message and then move on to N simulation cycles by the time VisIt had been asked to update its plots. The blocking mechanism sends a synchronization message to VisIt and then the sim reads VisIt commands, processing plot updates, until VisIt's viewer sends back the sync message.
  • Simple command buttons in the gui were not sending down their command string but instead a mangled, event-like version of the command. This has been fixed and the mangled stuff is sent down to the command as arguments so it's still accessible.
  • Unused arguments from the command callback interface were removed.
  • Simulation commands are now non-blocking in the engine proxy so the viewer can service other requests that come in. This was needed to prevent the viewer from freezing during a sim call that results in viewer synchronization (VisItUpdatePlots).

Additional features added

  • VisItDebug functions that let you printf into the VisIt debug logs from your simulation.
  • Libsim trace information can be written to log files that let you diagnose libsim problems. It might make sense to redirect the trace information now to the VisIt debug logs now what we can do that.
  • Added blockNames to the mesh metadata

Future work

  • Connecting to a simulation from Windows eventually causes the viewer->sim connection to die because sockets on Windows are set to non-blocking by default and our RPC's need to block. The combination of non-blocking and blocking behavior on the same socket causes many recv calls to fail with WSAEWOULDBLOCK or EAGAIN error that quickly triggers the lost connection logic. I've tried making the engine socket be blocking by using ioctlsocket() and that removes the socket errors from the logs but the connection seems to then get dropped on the Sim side... as near as I can tell. The best solution, is to make the sim's metadata come back to the viewer on yet another socket. This is easily doable by adding a separate xfer and a new socket in the engine and engine proxy.
  • The call to VisItSetupEnvironment should be deferred until VisIt tries to connect so we can get the version number from the connecting VisIt before we call "visit -env" to set up the libraries needed to import the sim runtime. For example, if you link with libsim from 1.11.2 (really it's versionless), libsim will load libraries from the most recent version of VisIt such as VisIt 1.12.0. If you ran "visit -v 1.11.0" to force VisIt to run VisIt 1.11.0, libsim will still load 1.12.0 libraries since that's the most current. This causes an incompatible version exception when the sim and VisIt try to connect.

Headaches in the SimV1 interface

  • Too much access to struct data. It might be prudent to provide a functional interface instead as we do for Fortran applications that want to use libsim.
    • A functional interface could in theory make it possible to add new items to opaque structures without breaking simulations and the SimV2 reader.
  • The whole command interface added by prevost
  • Finding visitCallbacks from the SimV1 reader is a problem since it requires the application to be linked in such a way that the visitCallbacks structure is globally visible. Some developers of larger packages hate that. In addition, it is not possible to do on Windows and likely on other platforms as well.
    • I changed the mac version of V1 to use dlopen/dlsym to find it. This could be propagated to other platforms easily. --Jeremy
  • Maybe the writer interface can be combined with the SimV2 reader. A separate writer was provided for SimV1 so as not to break existing simulations due to missing writer symbols.

Notes about some design changes

  • We need to have a set of shared functions that get loaded at runtime for allocating and accessing data. These can have a libsim veneer that points to dynamically loaded functions from the visitenginev2 library. The sim would use the veneer functions and the SimV2 reader would use the real functions from visitenginev2.
  • Create XML state object descriptions of the structures in the data interface library. We may be able to use the real AVT metadata object XML files for the metadata-related structures.
  • Create a new XML tool to generate an opaque structure and C set/get functions. This generated code would go into visitenginev2 to be dynamically loaded at runtime. The sim and the simv2 reader would use the access functions to get at the data. This would eliminate problems with changing struct sizes once and for all. The XML tool could probably automatically generate sensible fortran bindings too.
  • Move visitengine library from engine/main into sim/V2 so we can add the data interface code to it while keeping all the source within sim.
  • Add VisItRegisterXXXCallback functions to let the sim register the callback that will get called for various operations. Internally, we can store things into a structure in visitenginev2.
/* This code would live in visitenginev2 and would be meant to address the
 * problem of having a globally visible visitCallbacks structure. Heck, by 
 * stuffing the callback data into visitenginev2, I think we avoid the 
 * problems of having to have a globally visible struct. It's also good that
 * the structure is hidden so we can extend it without breaking compiled code.
typedef struct
    VisIt_MeshData *(*GetMesh)(void *, int dom, const char *var);
    void           *GetMeshData;
    /* and so on */ 
} VisIt_SimulationCallbacks;

static VisIt_SimulationCallbacks *visitCallbacks = NULL;

static VisIt_SimulationCallbacks *
    if(visitCallbacks == NULL)
        visitCallbacks = (VisIt_SimulationCallbacks *)malloc(sizeof(VisIt_SimulationCallbacks));
        memset(visitCallbacks, 0, sizeof(VisIt_SimulationCallbacks));
    return visitCallbacks;

/* This gets called from the sim, indirectly */
visit_set_getmesh(VisIt_MeshData *(*cb)(void *, int dom, const char *var), void *cbdata)
    VisIt_SimulationCallbacks *cbs = GetVisItCallbacks();
    cbs->GetMesh = cb;
    cbs->GetMeshData = cbdata;

/* This gets called from the SimV2 reader */
VisIt_GetMesh *
visit_call_getmesh(int dom, const char *var)
    VisIt_SimulationCallbacks *cbs = GetVisItCallbacks();
    if(cbs->GetMesh != NULL)
        return (*cbs->GetMesh)(cbs->GetMeshData, dom, var);
    return NULL;

/********* libsim ************/
VisItSetCallback_GetMesh(VisIt_MeshData *(*cb)(void *, int dom, const char *var), void *cbdata)
    void *sym = SAFE_DLSYM("visit_set_getmesh");
    if(sym != NULL)
        (*(FUNC *)sym)(cb, cbdata);