Working with submodels : Multiple-instance submodels : Special-purpose submodels

Special-purpose submodels

Generally, a Simile submodel has no built-in semantics besides what is described above for specifying its dimensions and how the number of instances is determined. However, certain uses of submodels are so common that we have decided to create special types of submodel to better support these uses, making models using them simpler and computationally faster. So, instead of the three radio buttons, Simile v6.1 includes a pulldown menu of six submodel types. When a selection is made, a message explaining the type is shown, together with entry fields for additional information  required for that type. Simple (dimensionless) submodels are now separate from those with array dimensions, and there are two predefined types:

Rectangular grid

The submodel has two dimensions and represents rectangular patches that cover a larger rectangular area. In addition to the usual features of array submodels, rectangular grid submodels can contain the following:

  • The functions row_id() and column_id() can be used to get the indices of each instance's row and column in the grid (these are equivalent to index(2) and index(1) respectively)
  • An influence's properties can be edited to enable the role "Include list of values from up to 8 grid squares...". When this role is enabled, the equation of the destination component can refer to the source component values in two ways: by the normal name, which just gives the value in the same submodel instance as normal, or by the name prefixed with "from_8_nbrs_", which gives a list of values from the instances representing the 8 grid squares adjoining the current one at sides or corners. There may be fewer than 8 values, e.g., if the current square is on the side or corner of the whole grid.

Hexagonal grid

The submodel has two dimensions and represents regular-hexagonal patches that cover a larger, roughly rectangular area in a honeycomb pattern. The patches have vertical sides, and odd-numbered rows are shifted half a width to the right so they tesselate with the even-numbered rows above and below. Hexagonal grid submodels can contain the following:

  • The functions row_id() and column_id(), as for rectangular grids
  • The functions hex_centre_x() and hex_centre_y() which give the x and y coordinates respectively of the centre of the hexagon relative to the bottom-left corner of the grid, in multiples of the length of one side of a hexagon
  • The functions hex_vertices_x() and hex_vertices_y() which give arrays of six values that are the x and y coordinates of the vertices of each hexagon, in the same terms as the centres above
  • An influence's properties can be edited to enable the role "Include list of values from up to 6 grid hexagons...". When this role is enabled, the equation of the destination component can refer to the source component values in two ways: by the normal name, which just gives the value in the same submodel instance as normal, or by the name prefixed with "from_6_nbrs_", which gives a list of values from the instances representing the 6 grid hexagons sharing an edge with the current one. There may be fewer than 6 values, e.g., if the current hexagon is on the side or corner of the whole grid.

More about values from neighbours

These special influence roles are intended to replace the requirement of having a separate self-association submodel representing the neighbour relationship between members of spatial grid arrays, and moving values between neighbours by taking them out to this association submodel by one role and back by the other. The lists of values they generate are variable-membership (due to different neighbour counts at sides/corners) so must be summed or applied to some other cumulative function before being assigned to the value of a local variable. However, all the usual operations can be applied to them before this. In fact the grid cell submodel itself can be made variable-membership, by adding a condition component to it just as is done for ordinary array submodels. This could be useful if we have an irregularly shaped area that we want to break down into grid cells -- in this case, set the dimensions of the grid so it covers the whole area, then add a condition that is true only for those cells that fall into the irregular area. Cells will then have fewer neighbours if they are at the edge of the selected area, and a single 'island' cell would have no neighbours, with the neighbour influence roles supplying empty lists.

Additionally, the lists have indices from special enumerated types representing the different directions in which the neighbour can lie. For the rectangular grid these are the points of the compass: nw, n, ne, etc. For the hexagonal grid these correspond to odd-numbered hours on a clock face, and so are written 1h, 3h ... 11h. These can be used like members of any other enumerated type, and to make a multi-instance submodel in which they are the indices, the dimension should be rect_nbr or hex_nbr. Now, because Simile v6.1 also introduces the ability to use the element() function to select sublists from lists, we can get other sets of neighbour data that might be useful, e.g.,

element({from_8_nbrs_size}, ["n","w","e","s"])

will produce a list of the values of 'size' in only the neighbouring rectangles that share a whole side with the current one.

element({from_6_nbrs_fire}, ["1h", "3h", "5h"])

will produce a list of the values of 'fire' in only the neighbouring hexagons further right than the current one. Note though that this could also be done by comparing the results of the hex_centre_x() function in the local and neighbouring hexagons, e.g., is 'fire' true in any neighbour hexagon to the right? use:

any({from_6_nbrs_fire} and {from_6_nbrs_xctr}>xctr)

...where xctr is another variable with equation hex_centre_x() and an influence to the current one with values from neighbours enabled.

In: Contents >> Working with submodels