Canvas-based modeller for ASCEND

From ASCEND

Jump to: navigation, search
The canvas-based model of fREEDA, an electrical circuit simulator. This canvas is based on Qt.
The canvas-based model of fREEDA, an electrical circuit simulator. This canvas is based on Qt.
Screenshot from Gaphor a UML tool. This canvas is pure Python on top of Cairo.
Screenshot from Gaphor a UML tool. This canvas is pure Python on top of Cairo.

Many other modelling environments provide a graphical flowsheet modeller, or 'canvas' onto which unit operations are arranged to create a process flow diagram (PFD). We would like to be able to do this in ASCEND too. The goals would be

  • create a new empty flowsheet
  • plop 'blocks' onto a canvas to represent various 'unit operations' such as tank, turbine, pump, column, resistor, capacity, actuator, motor, etc.
  • wire up the 'ports' on these blocks using 'connectors' that would correspond to 'streams' with multiple variables and parameters within them, such as a steam flow, or single variables such as a voltage signal.
  • view and edit parameters for the blocks in order to make adjustments to the system design.
  • solve the model
  • see graphically the parts of the model which have not converged or which are out-of-bounds.
  • view the values of variables within the blocks once it has solved
  • save the flowsheet in such a way that when reloaded, it can again be solved afresh.

Contents

[edit] Progress report

Screenshot of the prototype Gaphas-based canvas for ASCEND
Screenshot of the prototype Gaphas-based canvas for ASCEND
We have got a basically functional 'canvas' widget now based on Gaphas, with 'blocks', 'ports' and connector lines (see figure). This will clearly require more work on the connector lines and on the general usability, but it contains the necessary basic structure now to allow development to proceed in other areas.

What is required now is some work on the block 'palette' which will provide actual model components to the canvas. This requires some layers on top of the current 'Library' concept to allow a certain set of type descriptions to be loaded and parsed and checked for the necessary metadata to allow them to be utilised in a canvas-based model. The minimum metadata required is:

  • what variables are the 'inputs'
  • what variables are the 'outputs'
  • what variables are 'parameters' that must be specified via the GUI
  • something like a name for the block or its visual appearance

It is proposed that this metadata would be stored in the NOTES system, in order that canvas-based models can be loaded and solved with the current non-canvas GUI as well.

[edit] Two possible approachs to canvas-based models

We need to decide whether it is better that canvas-based models be parametric models or whether they should be non-parametric models. This would be the difference, for the case of a pipe segment, for example, between the two code snippets below. We imagine this as a 'block' that would have an inlet stream and an outlet stream, and a pressure drop 'dp' which could be set via the canvas-based GUI, for example by right-clicking the block and editing the value.

(* parametric model *)
MODEL pipesegment(
    inlet "in:" WILL_BE stream;
    output "out:" WILL_BE stream;
    dp WILL_BE delta_pressure;
);
    inlet.h = outlet.h;
    inlet.p + dp = outlet.p;
END pipesegment;

and

(* non-parametric model *)
MODEL pipesegment;
    inlet "in:" IS_A stream;
    output "out:" IS_A stream;
    dp "param:" IS_A delta_pressure;
    inlet.h = outlet.h;
    inlet.p + dp = outlet.p;
END pipesegment;

In the first case, the pipesegment model does not contain all the necessary variables, and it is not possible to create the pipesegment object without first creating the necessary parameter models 'inlet' and 'outlet'. On the other hand, this type of model is clearer in some ways because it effectively makes a distinction between 'private' (internal) variables and 'interface' variables (the ones that define its relationship with other models).

Note that we have used the 'inline notes' capability here to add metadata in both cases to allow ASCEND to determine how the block would need to appear: one inlet, one outlet, and one parameter. In the parametric model case, any parameter that is not designated 'in:' or 'out:' would be assumed to be a parameter (so the variable would need to be FIXed and a value specified by the user).

[edit] Loading, saving and solving canvas-based models

The above contains the minimal data required for the Library to be parsed and a 'palette' of available model 'blocks' presented to the user. The next question is: how should the resulting model be loaded, saved, and solved?

For the canvas-based model the essential data structures would contain

  • list of modules used in the canvas
  • list of blocks
    • type of each block
    • size and position of the block on the canvas
    • name of the block
    • block styling: colour, style?
  • list of connections
    • starting block and port (as blockname.portname)
    • ending block and port
    • line routing (a series of x,y points)
    • line styling: colour, width, etc?
  • list of other canvas objects
    • text labels, headings etc
    • possible 'output cells' that report current values of variables in the model
    • possible 'method buttons' that run methods on the model.
    • possible 'input cells' that allow variable values to be specified
  • list of parameter values
    • block to which the parameter blocks (maybe recursive).
    • value of the parameter.
    • units in which parameter has been specified.

With the above information it would be possible to save and reload a canvas-based model without loss of information, but note that the model would still have to be solved; it would not be saving the full state. It would have to be assumed that the model library upon which the canvas was based had not changed; certain debugging would be required to ensure that such a situation didn't result in a corrupted canvas-model. The above data might possibly be stored in a new file format '.a4g' specific to canvas-based modelling. (We could see the '.a4g' format as a sub-type of the '.a4c' format (in which case the above metadata might be embedded in NOTES, or similar?)

To solve a model with the above information, the approach would depend on whether the parametric or non-parametric modelling style is chosen.

For the parametric style, we would need to create definitions of the different streams before the blocks could be declared. This could lead to some ambiguity in the way that different streams are initialised, possible.

For the non-parametric style, we would only need to declare the blocks using IS_A, then declare the connections using ARE_THE_SAME. We would want to have some sort of hierarchical system of METHODS to ensure that the necessary variables were FIXed and initialised for each block in the model (similar to the proposed 'default_self' recursion that is currently a bit broken).

There need to be some protocols about how the model would be intialised, in any case.

It should be possible to re-solve the model after the user changes a value of a parameter. This would mean that canvas-gui would have exported the model to the solver, and would then know how its blocks corresponded to variables in the model, and would call var_fixed or similar routines via the 'libascend' API.

It appears that the right approach would be for the canvas-based GUI to generate a string or file-based representation of the model it has in member, using the above hierarchy of objects (modules, blocks, connectors, but not parameter values), then to instruct ASCEND to load that model, then to FIX and set the values of the parameters, then attempt to 'solve' the model. This might be done in cooperation with the existing PyGTK GUI, or might be done directly with calls to the libascend engine. the canvas-based GUI would have no awareness of the variables it contained other than that provided by the connector end-point names and the parameter names. Using those names it would be able to get/set values in the simulation.

It would be possible to avoid the need for the canvas GUI to be able to FIX or FREE variables in the model. When a 'source' block was required, it could be set up as a new 'block' and the necessary un-FIXed variables left as parameters to the model. Changing the source block to another type would allow other parameters to be fixed. When greater flexibility was required, the user could switch to the non-canvas GUI.

[edit] Design considerations

Do connections have properties and variables that need to be accessible, or is it always OK to access those variables/values via the connected blocks at either end?

What to do with the standard METHODS like specify, default_self, values?

How can we store the current state of the model? Should we try to do that?

How do we keep track of the fixed/free variables? Do we need to?

What about clashes between the values methods in different submodels setting values on their 'connection' members. Is this the corner-case that makes the parametric approach more desirable? Or does that not actually solve the problem?

How can the canvas modeller determine when a model is 'complete'?

Is it OK to leave dangling lines?

Is it OK to leave unconnected 'ports' on the sub-models?

Is it better to use '=' relationships instead of ARE_THE_SAME? It seems that in some cases this leads to models that solve more reliably.

Line routing is tricky and something that is not often done well. Could use some cool calligraphic code to make this work better

Could it be possible to highlight parts of the flowsheet corresponding to solved and un-solved portions of the model?

[edit] Software

Programs that implement these types of GUIs include

  • Gaphor (seems to use its own canvas widget, or pure Cairo?)
  • fREEDA (screenshot) (FOSS, Windows-based, uses a Qt canvas widget)
  • TRNSYS, Simulink, Visio, Dia, OOo Draw
  • COCO simulator (windows, closed-source freeward)
  • Conduit (uses goocanvas)
  • Dia (seems to use GnomeCanvas?)
  • GStreamer Editor (uses GnomeCanvas)
  • Dunnart (testbed for libavoid)
  • Inkscape (apparently includes support for libavoid, for automatic connector routing)

Software libraries that could be used for this functionality (most are discuss here):

  • Gaphas (API docs (uses only Cairo, via pure Python)
  • GooCanvas (uses Cairo inside)
  • GnomeCanvas (not sure if it's deprecated yet or not, uses libart inside)
  • libccc/CriaCanvas (uses Cairo inside)
  • Cairo (directly)
  • SoGTK (use the OpenInventor 3D scenegraph for 2D work here?)
  • Papyrus
  • libavoid (automatic connector-line routing including obstacle avoidance)

... it needs to be something that works within GTK and perhaps also PyGTK. ... we want to choose something that will be around for a while. The only canvas widgets from the above that is in Ubuntu and linked against are GooCanvas and GnomeCanvas, with GnomeCanvas being much more used than GooCanvas. libccc is available in Ubuntu but noone is linking against it yet (as of Hardy release)

Personal tools