Beispiel #1
0
class MGridDomain(SDomain):
    """
    Get an array with element node coordinates
    """

    # Grid cell template - gets repeated according to the
    # within the grid geometry specification
    #
    grid_cell = Property(depends_on="grid_cell_spec")

    @cached_property
    def _get_grid_cell(self):
        return MGridCell(grid_cell_spec=self.grid_cell_spec)

    # Grid geometry specification
    #
    coord_min = Array(Float, value=[0.0, 0.0, 0.0])
    coord_max = Array(Float, value=[1.0, 1.0, 1.0])

    grid_cell_spec = Instance(MGridCellSpec)

    def _grid_cell_spec_default(self):
        return MGridCellSpec()

    # Remark[rch]:
    # beware - the Int type is not regarded as a normal int
    # within an array and must be first converted to int array
    #
    # Had we defined int as the dtype of an array, there would
    # be errors during editing
    #
    shape = Array(Int, value=[1, 1, 1])

    # Derived specifier for element grid shape
    # It converts the Int array to int so that it can be
    # used by general numpy operators
    #
    egrid_shape = Property(depends_on="shape")

    @cached_property
    def _get_egrid_shape(self):
        return self.shape.astype(int)

    # -------------------------------------------------------------------------
    # Shaping and slicing methods for construction and orientation
    # -------------------------------------------------------------------------
    def _get_grid_shape(self):
        """
        Get the grid shape for the full index and point grids 
        """
        cell_shape = self.grid_cell_spec.get_cell_shape().astype(int)
        egrid_shape = self.egrid_shape
        return multiply(cell_shape - 1, egrid_shape) + 1

    def _get_grid_size(self):
        """Get the size of the full index and point grids
        """
        shape = self._get_grid_shape()
        return reduce(lambda i, j: i * j, shape)

    def _get_igrid_slices(self):
        """Get slices defining the index grid
        """
        sub_cell_shape = self.grid_cell_spec.get_cell_shape() - 1
        elem_grid_shape = self.egrid_shape
        return tuple([slice(0, c * g + 1) for c, g in zip(sub_cell_shape, elem_grid_shape)])

    def _get_icell_slices(self):
        """Get slices extracting the first cell from the index grid
        """
        cell_shape = self.grid_cell_spec.get_cell_shape()
        return tuple([slice(0, c) for c in cell_shape])

    def _get_icell(self):
        """Get the node map within a cell of a 1-3 dimensional grid
        
        The enumeration of nodes within a single cell is managed by the
        self.grid_cell. This must be adapted to the global enumeration of the grid.
        
        The innermost index runs over the z-axis. Thus, the index of the points
        on the z axis is [0,1,...,shape[2]-1]. The following node at the y axis has 
        the number [shape[2], shape[2]+1, ..., shape[2]*2].

        """
        igrid = arange(self._get_grid_size()).reshape(self._get_grid_shape())
        # extract the first cell from the igrid
        icell_slices = self._get_icell_slices()
        icell = igrid[icell_slices]
        return icell

    # -------------------------------------------------------------------------
    # Generation methods for geometry and index maps
    # -------------------------------------------------------------------------

    def _get_pgrid_slices(self):
        """Get the slices to be used for the mgrid tool 
        to generate the point grid.
        """
        ndims = self.grid_cell_spec.get_n_dims()
        shape = self._get_grid_shape()
        return tuple(
            [slice(float(self.coord_min[i]), float(self.coord_max[i]), complex(0, shape[i])) for i in range(ndims)]
        )

    pgrid = Property(depends_on="grid_cell_spec.+,shape,coord_min,coord_max")

    @cached_property
    def _get_pgrid(self):
        """
        Construct the point grid underlying the mesh grid structure.
        """
        return mgrid[self._get_pgrid_slices()]

    def _get_pgrid_dims(self):
        return self._get_grid_shape()

    def _get_points(self):
        return c_[tuple([x.flatten() for x in self.pgrid])]

    def _get_tpoints(self):
        """Get the points in with deepest index along the x axes.
        """
        tp = self.pgrid.swapaxes(1, 3)
        return c_[tuple([x.flatten() for x in tp])]

    # Base node grid
    #
    def _get_base_node_array(self):
        """
        Construct the base node grid.
        """
        # get the cell shape - number of cell points without the next base point
        subcell_shape = self.grid_cell_spec.get_cell_shape().astype(int) - 1
        # get the element grid shape (number of elements in each dimension)
        egrid_shape = self.egrid_shape

        # get the index offset between two neighboring points on the x-axis
        z_offset = subcell_shape[2]
        # get the index offset between two neighboring points on the y-axis
        y_offset = (egrid_shape[2] * subcell_shape[2] + 1) * subcell_shape[1]
        # get the index offset between two neighboring points on the z-axis
        x_offset = (egrid_shape[2] * subcell_shape[2] + 1) * (egrid_shape[1] * subcell_shape[1] + 1) * subcell_shape[0]

        # grid shape (shape + 1)
        gshape = egrid_shape + 1

        # generate points along an axis respecting the above offsets
        xi_offsets = x_offset * arange(gshape[0])
        yi_offsets = y_offset * arange(gshape[1])
        zi_offsets = z_offset * arange(gshape[2])

        # expand the dimension of offsets and sum them up. using broadcasting
        # this generates the grid of the base nodes (the last node is cut away
        # as it does not hold any element
        igrid = xi_offsets[:-1, None, None] + yi_offsets[None, :-1, None] + zi_offsets[None, None, :-1]

        # return the indexes of the base nodes
        return sort(igrid.flatten())

    def _get_elnode_map(self):
        """
        Construct an array with 
        """
        icell = self._get_icell()
        node_map = icell.flatten()[self.grid_cell.node_map]
        base_nodes = self._get_base_node_array()

        # Use broadcasting to construct the node map for all elements
        #
        elnode_map = base_nodes[:, None] + node_map[None, :]
        return elnode_map

    def _get_expanded_elem_coords(self):
        iexp = index_exp[self._get_elnode_map()]
        return self._get_points()[iexp]

    def _get_elem_coords(self, elnum):
        iexp = index_exp[self._get_elnode_map()[elnum]]
        return self._get_points()[iexp]

    def _get_epoints(self):
        """Get element node numbers
        
        Extract the indices of all points that are connected to an element.
        """
        return self._get_points()[ix_(self._get_epoint_numbers())]

    def _get_epoint_numbers(self):
        # flatten and unique
        elnodes = self._get_elnode_map()
        return unique(elnodes.flatten())

    show_elem_array = Button

    def _show_elem_array_fired(self):
        elem_array = self._get_elnode_map()
        self.show_array = ElemArrayView(data=elem_array, rt_domain=self)
        self.show_array.configure_traits(kind="live")

    # -----------------------------------------------------------------
    # Visualization related methods
    # -----------------------------------------------------------------

    mvp_pgrid = Trait(MVStructuredGrid)

    def _mvp_pgrid_default(self):
        return MVStructuredGrid(name="Point grid", dims=self._get_pgrid_dims, points=self._get_tpoints)

    mvp_mgrid_ngeo_labels = Trait(MVPointLabels)

    def _mvp_mgrid_ngeo_labels_default(self):
        return MVPointLabels(name="Geo node numbers", points=self._get_epoints, scalars=self._get_epoint_numbers)

    refresh_button = Button("Draw")

    @on_trait_change("refresh_button")
    def redraw(self):
        """
        """
        self.mvp_pgrid.redraw()
        # self.mvp_mgrid_ngeo_labels.redraw( 'label_scalars' )

    # ------------------------------------------------------------------
    # UI - related methods
    # ------------------------------------------------------------------
    traits_view = View(
        Item("grid_cell_spec"),
        Item("shape@"),
        Item("coord_min"),
        Item("coord_max"),
        Item("refresh_button"),
        Item("show_elem_array"),
        resizable=True,
        scrollable=True,
        height=0.5,
        width=0.5,
    )
Beispiel #2
0
class MGridDomain(SDomain):
    '''
    Get an array with element node coordinates
    '''

    # Grid cell template - gets repeated according to the 
    # within the grid geometry specification
    #
    grid_cell = Property( depends_on = 'grid_cell_spec' )
    @cached_property
    def _get_grid_cell(self):
        return MGridCell( grid_cell_spec = self.grid_cell_spec )


    # Grid geometry specification
    #
    coord_min = Array( Float, value = [ 0., 0., 0.] )
    coord_max = Array( Float, value = [ 1., 1., 1.] )
    
    grid_cell_spec = Instance( MGridCellSpec )
    def _grid_cell_spec_default(self):
        return MGridCellSpec()
    
    # Remark[rch]: 
    # beware - the Int type is not regarded as a normal int
    # within an array and must be first converted to int array
    #
    # Had we defined int as the dtype of an array, there would
    # be errors during editing
    #
    shape   = Array( Int, value = [ 1, 1, 1 ] )
    
    # Derived specifier for element grid shape
    # It converts the Int array to int so that it can be
    # used by general numpy operators
    #
    egrid_shape = Property( depends_on = 'shape' )
    @cached_property
    def _get_egrid_shape(self):
        return self.shape.astype(int)

    #-------------------------------------------------------------------------
    # Shaping and slicing methods for construction and orientation
    #-------------------------------------------------------------------------
    def _get_grid_shape(self):
        '''
        Get the grid shape for the full index and point grids 
        '''
        cell_shape = self.grid_cell_spec.get_cell_shape().astype(int)
        egrid_shape = self.egrid_shape
        return multiply( cell_shape - 1, egrid_shape  ) + 1

    def _get_grid_size(self):
        '''Get the size of the full index and point grids
        '''
        shape = self._get_grid_shape()
        return reduce( lambda i,j: i*j, shape )
    
    def _get_igrid_slices(self):
        '''Get slices defining the index grid
        '''
        sub_cell_shape = self.grid_cell_spec.get_cell_shape() - 1
        elem_grid_shape = self.egrid_shape
        return tuple( [ slice( 0, c*g+1 ) 
                        for c,g in zip(sub_cell_shape,elem_grid_shape) ] )

    def _get_icell_slices(self):
        '''Get slices extracting the first cell from the index grid
        '''
        cell_shape = self.grid_cell_spec.get_cell_shape()
        return tuple( [ slice( 0,c )
                        for c in cell_shape ] )        

    def _get_icell(self):
        '''Get the node map within a cell of a 1-3 dimensional grid
        
        The enumeration of nodes within a single cell is managed by the
        self.grid_cell. This must be adapted to the global enumeration of the grid.
        
        The innermost index runs over the z-axis. Thus, the index of the points
        on the z axis is [0,1,...,shape[2]-1]. The following node at the y axis has 
        the number [shape[2], shape[2]+1, ..., shape[2]*2].

        '''
        igrid = arange( self._get_grid_size() ).reshape( self._get_grid_shape( ))
        # extract the first cell from the igrid
        icell_slices = self._get_icell_slices()
        icell = igrid[ icell_slices ]
        return icell

    #-------------------------------------------------------------------------
    # Generation methods for geometry and index maps
    #-------------------------------------------------------------------------

    def _get_pgrid_slices(self):
        '''Get the slices to be used for the mgrid tool 
        to generate the point grid.
        '''
        ndims = self.grid_cell_spec.get_n_dims()
        shape = self._get_grid_shape()
        return tuple( [ slice( float(self.coord_min[i]),
                               float(self.coord_max[i]),
                               complex(0,shape[i]) ) 
                        for i in range(ndims ) ] )

    pgrid = Property( depends_on = 'grid_cell_spec.+,shape,coord_min,coord_max' )
    @cached_property
    def _get_pgrid(self):
        '''
        Construct the point grid underlying the mesh grid structure.
        '''
        return mgrid[ self._get_pgrid_slices() ]

    def _get_pgrid_dims(self):
        return self._get_grid_shape()

    def _get_points(self):
        return c_[ tuple([ x.flatten() for x in self.pgrid ]) ]

    def _get_tpoints(self):
        '''Get the points in with deepest index along the x axes.
        '''
        tp = self.pgrid.swapaxes(1,3)
        return c_[ tuple([ x.flatten() for x in tp ]) ]
      
      
        
    # Base node grid
    #
    def _get_base_node_array(self):
        '''
        Construct the base node grid.
        '''
        # get the cell shape - number of cell points without the next base point
        subcell_shape = self.grid_cell_spec.get_cell_shape().astype(int) - 1
        # get the element grid shape (number of elements in each dimension)
        egrid_shape = self.egrid_shape

        # get the index offset between two neighboring points on the x-axis  
        z_offset = subcell_shape[2]
        # get the index offset between two neighboring points on the y-axis  
        y_offset = ( egrid_shape[2] * subcell_shape[2] + 1) * subcell_shape[1]
        # get the index offset between two neighboring points on the z-axis  
        x_offset = ( egrid_shape[2] * subcell_shape[2] + 1 ) * \
                   ( egrid_shape[1] * subcell_shape[1] + 1 ) * \
                     subcell_shape[0]

        # grid shape (shape + 1)
        gshape = egrid_shape + 1
        
        # generate points along an axis respecting the above offsets 
        xi_offsets = x_offset * arange( gshape[0] )
        yi_offsets = y_offset * arange( gshape[1] )
        zi_offsets = z_offset * arange( gshape[2] )

        # expand the dimension of offsets and sum them up. using broadcasting
        # this generates the grid of the base nodes (the last node is cut away 
        # as it does not hold any element
        igrid = xi_offsets[:-1,None,None] + \
                yi_offsets[None,:-1,None] + \
                zi_offsets[None,None,:-1]

        # return the indexes of the base nodes
        return sort( igrid.flatten() )

    def _get_elnode_map(self):
        '''
        Construct an array with 
        '''
        icell = self._get_icell()
        node_map   = icell.flatten()[ self.grid_cell.node_map ]
        base_nodes = self._get_base_node_array()

        # Use broadcasting to construct the node map for all elements
        #
        elnode_map = base_nodes[:,None] + node_map[None,:]
        return elnode_map

    def _get_expanded_elem_coords(self):
        iexp = index_exp[ self._get_elnode_map() ]
        return self._get_points()[iexp]

    def _get_elem_coords(self, elnum):
        iexp = index_exp[ self._get_elnode_map()[ elnum ] ]
        return self._get_points()[iexp]

    def _get_epoints(self):
        '''Get element node numbers
        
        Extract the indices of all points that are connected to an element.
        '''
        return self._get_points()[ ix_( self._get_epoint_numbers( ) ) ]
        
    def _get_epoint_numbers(self):
        # flatten and unique
        elnodes = self._get_elnode_map()
        return unique( elnodes.flatten() )

    show_elem_array = Button
    def _show_elem_array_fired(self):
        elem_array = self._get_elnode_map()
        self.show_array = ElemArrayView( data = elem_array, 
                                         rt_domain = self )
        self.show_array.configure_traits( kind = 'live' )
        
    #-----------------------------------------------------------------
    # Visualization related methods
    #-----------------------------------------------------------------

    mvp_pgrid = Trait( MVStructuredGrid )
    def _mvp_pgrid_default(self):
        return MVStructuredGrid( name = 'Point grid', 
                                  dims = self._get_pgrid_dims,
                                  points = self._get_tpoints )
    
    mvp_mgrid_ngeo_labels = Trait( MVPointLabels )
    def _mvp_mgrid_ngeo_labels_default(self):
        return MVPointLabels( name = 'Geo node numbers', 
                                  points = self._get_epoints,
                                  scalars = self._get_epoint_numbers)


    

    refresh_button = Button('Draw')
    @on_trait_change('refresh_button')
    def redraw(self):
        '''
        '''
        self.mvp_pgrid.redraw( )        
        #self.mvp_mgrid_ngeo_labels.redraw( 'label_scalars' )        

    #------------------------------------------------------------------
    # UI - related methods
    #------------------------------------------------------------------
    traits_view = View(Item('grid_cell_spec'),
                       Item('shape@'),
                       Item('coord_min'),
                       Item('coord_max'),
                       Item('refresh_button'),
                       Item('show_elem_array'),
                       resizable = True,
                       scrollable = True,
                       height = 0.5,
                       width = 0.5)        
Beispiel #3
0
 def _show_elem_array_fired(self):
     elem_array = self._get_elnode_map()
     self.show_array = ElemArrayView(data=elem_array, rt_domain=self)
     self.show_array.configure_traits(kind="live")
Beispiel #4
0
 def _show_elem_array_fired(self):
     elem_array = self._get_elnode_map()
     self.show_array = ElemArrayView( data = elem_array, 
                                      rt_domain = self )
     self.show_array.configure_traits( kind = 'live' )