itm.grid.base - Handling general grids

The module itm.grid.base contains the core classes for working with grids stored in the general grid description.

Three classes are really important:

  • itm.grid.base.Grid for the grid itself
  • itm.grid.base.Object for individual grid objects
  • itm.grid.base.SubGrid for the individual subgrids

The other classes in the module are not typically used directly by users. Their documentation is deferred to a separate page.

The basic philosophy of these classes is to wrap sub-datastructures of a CPO (e.g. the complexgrid data structure) and add functionality to them.

itm.grid.base.Grid - accessing grid information and components

Obtaining a Grid

A grid is typically obtained from a Cpo object:

import itm.grid.cpo_tools as ct
cpo = ct.Cpo(9003, 0, 'edge', 0.0, 'klingshi', 'test', '4.09a')
grid = cpo.grid

When working with objects related to a grid (e.g. SubGrid or Object instances), these typically offer a ‘grid’ property to obtain their parent grid.

Getting basic grid information

The dimension of the space discretized by this grid:

In [4]: grid.ndim
Out[4]: 3

The label indices of the coordinate axes:

In [7]: grid.coord_types
Out[7]: [1, 2, 5]

Probably more useful, in real words:

In [9]: grid.coord_ids
Out[9]: ['x', 'y', 'Height Z']

In [10]: grid.coord_units
Out[10]: ['m', 'm', 'm']

Dimensions of the spaces in this grid:

In [5]: grid.space_dims
Out[5]: [1, 1, 1]

The object classes in this grid are all tuples that can be formed by varying the space dimension indices within thir ranges. The highest-dimensional objects are therefore the (1,1,1) objects:

In [6]: grid.class_exists( (1,1,1) )
Out[6]: True

Getting grid objects

When knowing the class and index tuples,

In [15]: obj = grid.get_obj( (1,1,1), (3,2,4) )
In [16]: str(obj)
Out[16]: '( ( 1 1 1 ) ( 3 2 4 ) )'

Alternatively, object can be adressed using their global index:

In [17]: obj.global_ind
Out[17]: 68

In [18]: str( grid.get_obj_by_global_index( obj.cls, obj.global_ind ) )
Out[18]: '( ( 1 1 1 ) ( 3 2 4 ) )'

Getting node coordinates

Getting the number of nodes:

In [20]: grid.nobj( (0,0,0) )
Out[20]: 300

For an individual node:

In [22]: grid.node_coord( (3,4,5) )
Out[22]: array([ 2. ,  1.5,  0.4])

Or, via a detour trough the global index of the node:

In [36]: grid.node_coord( grid.get_obj_by_global_index( (0,0,0), grid.node_index( (3,4,5) ) ) )
Out[36]: array([ 2. ,  1.5,  0.4])

If ones has a list of nodes, say, a subgrid of nodes:

In [29]: grid.nodes_coord( grid.subgrid_for_id("3d_structured_nodes") )
Out[29]:
array([[ 0. ,  0. ,  0. ],
       [ 1. ,  0. ,  0. ],
       [ 2. ,  0. ,  0. ],
       ............
       [ 4. ,  2. ,  0.9],
       [ 5. ,  2. ,  0.9]])

We can also just get a list of all nodes on the fly:

In [40]: grid.nodes_coord( grid.get_objs( (0,0,0) ) )
Out[40]:
array([[ 0. ,  0. ,  0. ],
       ............

Or even simpler, omit the list of nodes, and get all nodes:

In [41]: grid.nodes_coord()
Out[41]:
array([[ 0. ,  0. ,  0. ],
       ............

If we have an object, we can get the nodes that are part of that object, and use them again to get their coordinates:

In [44]: grid.nodes_coord( grid.get_obj( (1,1,1), (3,2,4) ).nodes )
Out[44]:
array([[ 3. ,  0.5,  0.4],
       [ 2. ,  1. ,  0.3],
       [ 3. ,  0.5,  0.3],
       [ 2. ,  0.5,  0.3],
       [ 3. ,  1. ,  0.3],
       [ 2. ,  0.5,  0.4],
       [ 3. ,  1. ,  0.4],
       [ 2. ,  1. ,  0.4]])

itm.grid.base.Object - Grid objects

Creating grid objects

Grid objects can be created directly by the grid object (see Getting grid objects above)

Typically, grid objects are not handled individually but in groups. These can be subgrids:

In [46]: sg = grid.subgrid_for_id("3d_structured_faces")
In [47]: sg[10]
Out[47]: <itm.grid.base.Object instance at 0xd31dea8>
In [48]: str(sg[0])
Out[48]: '( ( 1 1 0 ) ( 1 3 1 ) )'

If you need a list of objects that are not pre-defined in the grid as a subgrid, you can create your own object lists:

In [15]: frontfaces = itm.grid.base.ImplicitObjectList( grid, (1,1,0), ( None, None, 1 ) )
In [16]: len(frontfaces)
Out[16]: 20

(Manually creating object lists is powerful, but you have to understand object descriptors. Have a look at the internal documentation FIXME:link).

Object connectivity

When working with discretizations, one often has to exploit relations and connectivity between grid objects. Fortunately, that’s simple. Lets pick a 3d cell as example:

In [5]: cell = grid.subgrid_for_id("3d_structured_volumes")[65]
In [6]: print cell
( ( 1 1 1 ) ( 1 2 4 ) )

This cell is bounded by 2d faces, the so-called composing objects:

In [14]: cell.composing_objs
Out[14]:
[<itm.grid.base.Object instance at 0x6762ea8>,
 <itm.grid.base.Object instance at 0x6743050>,
 <itm.grid.base.Object instance at 0x6743098>,
 <itm.grid.base.Object instance at 0x67430e0>,
 <itm.grid.base.Object instance at 0x6743128>,
 <itm.grid.base.Object instance at 0x6743170>]

In [15]: for face in cell.composing_objs:
   ....:     print face
   ....:
( ( 0 1 1 ) ( 1 2 4 ) )
( ( 0 1 1 ) ( 2 2 4 ) )
( ( 1 0 1 ) ( 1 2 4 ) )
( ( 1 0 1 ) ( 1 3 4 ) )
( ( 1 1 0 ) ( 1 2 4 ) )
( ( 1 1 0 ) ( 1 2 5 ) )

To get the neighbour cells of the cell:

In [16]: for neighbour_cell in cell.neighbours:
   ....:     print neighbour_cell
   ....:
( ( 1 1 1 ) ( 2 2 4 ) )
( ( 1 1 1 ) ( 1 1 4 ) )
( ( 1 1 1 ) ( 1 3 4 ) )
( ( 1 1 1 ) ( 1 2 3 ) )
( ( 1 1 1 ) ( 1 2 5 ) )

This cell is at the edge of the domain, so it only has five neighbours. To see this in more detail:

In [17]: for neighbour_list in cell.neighbour_lists:
   ....:     print neighbour_list
   ....:
[]
[<itm.grid.base.Object instance at 0x673e098>]
[<itm.grid.base.Object instance at 0x673e3f8>]
[<itm.grid.base.Object instance at 0x673e488>]
[<itm.grid.base.Object instance at 0x673e518>]
[<itm.grid.base.Object instance at 0x673e5a8>]

Object.neighbour_lists returns one list of neighbour for every composing object (here, for every face of the 3d cell). For the first face, this list is empty, so there is no neighbour on that side.

A special operation is to get all nodes for an object:

In [20]: for node in cell.nodes:
   ....:     print node
   ....:
( ( 0 0 0 ) ( 1 3 5 ) )
( ( 0 0 0 ) ( 1 2 4 ) )
( ( 0 0 0 ) ( 1 3 4 ) )
( ( 0 0 0 ) ( 2 3 4 ) )
( ( 0 0 0 ) ( 1 2 5 ) )
( ( 0 0 0 ) ( 2 3 5 ) )
( ( 0 0 0 ) ( 2 2 5 ) )
( ( 0 0 0 ) ( 2 2 4 ) )

If needed, one can directly get the node positions in space:

In [22]: cell.nodes_coord
Out[22]:
array([[ 0. ,  1. ,  0.4],
       [ 0. ,  0.5,  0.3],
       [ 0. ,  1. ,  0.3],
       [ 1. ,  1. ,  0.3],
       [ 0. ,  0.5,  0.4],
       [ 1. ,  1. ,  0.4],
       [ 1. ,  0.5,  0.4],
       [ 1. ,  0.5,  0.3]])