Exemplo n.º 1
0
    def StoreGeometry(self):
        """ Stores the geometry from the result file """

        # read in the geometry from the result file
        with open(self.filename, 'rb') as f:
            f.seek((self.resultheader['ptrGEO'] + 2) * 4)
            geotable = np.fromfile(f, self.resultheader['endian'] + 'i', 80)
            geotable.tolist()

            ptrLOC = geotable[26]

            # Node information
            nnod = self.resultheader['nnod']
            nnum = np.empty(nnod, np.int32)
            nloc = np.empty((nnod, 6), np.float)
            _rstHelper.LoadNodes(self.filename, ptrLOC, nnod, nloc, nnum)

            # Element Information
            nelm = geotable[4]
            ptrEID = geotable[28]
            maxety = geotable[1]

            # pointer to the element type index table
            ptrETYP = geotable[20]
            f.seek((ptrETYP + 2) * 4)
            e_type_table = np.fromfile(
                f, self.resultheader['endian'] + 'i', maxety)

            # store information for each element type
            # make these arrays large so you can reference a value via element
            # type numbering

            # number of nodes for this element type
            nodelm = np.empty(10000, np.int32)

            # number of nodes per element having nodal forces
            nodfor = np.empty(10000, np.int32)

            # number of nodes per element having nodal stresses
            nodstr = np.empty(10000, np.int32)
            etype_ID = np.empty(maxety, np.int32)
            ekey = []
            for i in range(maxety):
                f.seek((ptrETYP + e_type_table[i] + 2) * 4)
                einfo = np.fromfile(f, self.resultheader['endian'] + 'i', 2)
                etype_ref = einfo[0]
                etype_ID[i] = einfo[1]
                ekey.append(einfo)

                f.seek((ptrETYP + e_type_table[i] + 2 + 60) * 4)
                nodelm[etype_ref] = np.fromfile(
                    f, self.resultheader['endian'] + 'i', 1)

                f.seek((ptrETYP + e_type_table[i] + 2 + 62) * 4)
                nodfor[etype_ref] = np.fromfile(
                    f, self.resultheader['endian'] + 'i', 1)

                f.seek((ptrETYP + e_type_table[i] + 2 + 93) * 4)
                nodstr[etype_ref] = np.fromfile(
                    f, self.resultheader['endian'] + 'i', 1)

            # store element table data
            self.element_table = {'nodelm': nodelm,
                                  'nodfor': nodfor,
                                  'nodstr': nodstr}

            # get the element description table
            f.seek((ptrEID + 2) * 4)
            e_disp_table = np.empty(nelm, np.int32)
            e_disp_table[:] = np.fromfile(
                f, self.resultheader['endian'] + 'i8', nelm)

            # get pointer to start of element table and adjust element pointers
            ptr = ptrEID + e_disp_table[0]
            e_disp_table -= e_disp_table[0]

        # The following is stored for each element
        # mat     - material reference number
        # type    - element type number
        # real    - real constant reference number
        # secnum  - section number
        # esys    - element coordinate system
        # death   - death flat (1 live, 0 dead)
        # solidm  - solid model reference
        # shape   - coded shape key
        # elnum   - element number
        # baseeid - base element number
        # NODES   - node numbers defining the element

        # allocate memory for this (a maximum of 21 points per element)
        etype = np.empty(nelm, np.int32)

        elem = np.empty((nelm, 20), np.int32)
        elem[:] = -1

        # load elements
        _rstHelper.LoadElements(self.filename, ptr, nelm, e_disp_table, elem,
                                etype)
        enum = self.resultheader['eeqv']

        # store geometry dictionary
        self.geometry = {'nnum': nnum,
                         'nodes': nloc,
                         'etype': etype,
                         'elem': elem,
                         'enum': enum,
                         'ekey': np.asarray(ekey, ctypes.c_long),
                         'e_rcon': np.ones_like(enum)}

        # store the reference array
        cell_type = ['45', '95', '185', '186', '92', '187', '154']
        result = _parser.Parse(self.geometry, True, cell_type)  # force_linear
        cells, offset, cell_type, self.numref, _, _, _ = result

        # Create vtk object if vtk installed
        if vtkloaded:
            nodes = nloc[:, :3]
            self.grid = vtkInterface.UnstructuredGrid(offset, cells,
                                                      cell_type, nodes)

        # get edge nodes
        nedge = nodstr[etype].sum()
        self.edge_idx = np.empty(nedge, np.int32)
        _rstHelper.AssembleEdges(
            nelm, etype, elem, self.numref.astype(
                np.int32), self.edge_idx, nodstr)

        # store edge node numbers and indices to the node array
        self.edge_node_num_idx = np.unique(self.edge_idx)
Exemplo n.º 2
0
    def ParseVTK(self, force_linear=False, allowable_types=None,
                 null_unallowed=False):
        """
        Parses raw data from cdb file to VTK format.

        Parameters
        ----------
        force_linear : bool, optional
            This parser creates quadradic elements if available.  Set this to
            True to always create linear elements.  Defaults to False.

        allowable_types : list, optional
            Allowable element types.  Defaults to:
            ['45', '95', '185', '186', '92', '187']

            See help(pyansys.elements) for available element types.

        null_unallowed : bool, optional
            Elements types not matching element types will be stored as empty
            (null) elements.  Useful for debug or tracking element numbers.
            Default False.

        Returns
        -------
        uGrid : vtk.vtkUnstructuredGrid
            VTK unstructured grid from archive file.

        """

        if not vtk_loaded:
            raise Exception(
                'Unable to load VTK module.  Cannot parse raw cdb data')

        if self.CheckRaw():
            raise Exception(
                'Missing key data.  Cannot parse into unstructured grid')

        # Convert to vtk style arrays
        if allowable_types is None:
            allowable_types = ['45', '95', '185', '186', '92', '187']
        else:
            assert isinstance(allowable_types, list), \
                   'allowable_types must be a list'
            for eletype in allowable_types:
                if eletype not in valid_types:
                    raise Exception('Element type "%s" ' % eletype +
                                    'cannot be parsed in pyansys')

        result = _parser.Parse(self.raw, force_linear, allowable_types,
                               null_unallowed)
        cells, offset, cell_type, numref, enum, etype, rcon = result

        # catch bug
        cells[cells > numref.max()] = -1

        # Check for missing midside nodes
        if force_linear or np.all(cells != -1):
            nodes = self.raw['nodes'][:, :3].copy()
            nnum = self.raw['nnum']

        else:
            mask = cells == -1

            nextra = mask.sum()
            maxnum = numref.max() + 1
            cells[mask] = np.arange(maxnum, maxnum + nextra)

            nnodes = self.raw['nodes'].shape[0]
            nodes = np.zeros((nnodes + nextra, 3))
            nodes[:nnodes] = self.raw['nodes'][:, :3]

            # Set new midside nodes directly between their edge nodes
            temp_nodes = nodes.copy()
            _relaxmidside.ResetMidside(cells, temp_nodes)
            nodes[nnodes:] = temp_nodes[nnodes:]

            # merge nodes
            new_nodes = temp_nodes[nnodes:]
            unique_nodes, idxA, idxB = UniqueRows(new_nodes,
                                                  return_index=True,
                                                  return_inverse=True)

            # rewrite node numbers
            cells[mask] = idxB + maxnum
            nextra = idxA.shape[0]
            nodes = np.zeros((nnodes + nextra, 3))
            nodes[:nnodes] = self.raw['nodes'][:, :3]
            nodes[nnodes:] = unique_nodes

            # Add extra node numbers
            nnum = np.hstack((self.raw['nnum'],
                              np.ones(nextra, np.int32) * -1))

        # Create unstructured grid
        grid = vtkInterface.UnstructuredGrid(offset, cells, cell_type, nodes)

        # Store original ANSYS numbering
        grid.AddPointScalars(nnum, 'ANSYSnodenum')
        grid.AddCellScalars(enum, 'ANSYS_elem_num')
        grid.AddCellScalars(etype, 'ANSYS_elem_typenum')
        grid.AddCellScalars(rcon, 'ANSYS_real_constant')

        # Add element components to unstructured grid
        # ibool = np.empty(grid.GetNumberOfCells(), dtype=np.int8)
        for comp in self.raw['elem_comps']:
            mask = np.in1d(enum, self.raw['elem_comps'][comp], assume_unique=True)
            grid.AddCellScalars(mask, comp.strip())

        # Add node components to unstructured grid
        ibool = np.empty(grid.GetNumberOfPoints(), dtype=np.int8)
        for comp in self.raw['node_comps']:
            ibool[:] = 0  # reset component array

            # Convert to new node numbering
            nodenum = numref[self.raw['node_comps'][comp]]

            ibool[nodenum] = 1
            grid.AddPointScalars(ibool, comp.strip())

        grid.AddPointScalars(np.arange(grid.points.shape[0]), 'origid')

        # Add tracker for original node numbering
        npoints = grid.GetNumberOfPoints()
        grid.AddPointScalars(np.arange(npoints), 'VTKorigID')

        self.vtkuGrid = grid

        return grid
Exemplo n.º 3
0
    def parse_vtk(self,
                  force_linear=False,
                  allowable_types=None,
                  null_unallowed=False):
        """
        Parses raw data from cdb file to VTK format.

        Parameters
        ----------
        force_linear : bool, optional
            This parser creates quadradic elements if available.  Set this to
            True to always create linear elements.  Defaults to False.

        allowable_types : list, optional
            Allowable element types.  Defaults to:
            ['45', '95', '185', '186', '92', '187']

            See help(pyansys.elements) for available element types.

        null_unallowed : bool, optional
            Elements types not matching element types will be stored as empty
            (null) elements.  Useful for debug or tracking element numbers.
            Default False.

        Returns
        -------
        uGrid : vtk.vtkUnstructuredGrid
            VTK unstructured grid from archive file.

        """

        if self.check_raw():
            raise Exception(
                'Missing key data.  Cannot parse into unstructured grid')

        # Convert to vtk style arrays
        if allowable_types is None:
            allowable_types = ['45', '95', '185', '186', '92', '187']
        else:
            assert isinstance(allowable_types, list), \
                   'allowable_types must be a list'
            for eletype in allowable_types:
                if str(eletype) not in valid_types:
                    raise Exception('Element type "%s" ' % eletype +
                                    'cannot be parsed in pyansys')

        # parse raw output
        parsed = _parser.Parse(self.raw, force_linear, allowable_types,
                               null_unallowed)
        cells = parsed['cells']
        offset = parsed['offset']
        cell_type = parsed['cell_type']
        numref = parsed['numref']
        enum = parsed['enum']

        # catch bug
        # if np.any(cells > numref.max()):
        # import pdb; pdb.set_trace()
        # cells[cells > numref.max()] == 0

        # Check for missing midside nodes
        if force_linear or np.all(cells != -1):
            nodes = self.raw['nodes'][:, :3].copy()
            nnum = self.raw['nnum']
        else:
            mask = cells == -1

            nextra = mask.sum()
            maxnum = numref.max() + 1
            cells[mask] = np.arange(maxnum, maxnum + nextra)

            nnodes = self.raw['nodes'].shape[0]
            nodes = np.zeros((nnodes + nextra, 3))
            nodes[:nnodes] = self.raw['nodes'][:, :3]

            # Set new midside nodes directly between their edge nodes
            temp_nodes = nodes.copy()
            _relaxmidside.ResetMidside(cells, temp_nodes)
            nodes[nnodes:] = temp_nodes[nnodes:]

            # merge nodes
            new_nodes = temp_nodes[nnodes:]
            unique_nodes, idxA, idxB = unique_rows(new_nodes)

            # rewrite node numbers
            cells[mask] = idxB + maxnum
            nextra = idxA.shape[0]
            nodes = np.zeros((nnodes + nextra, 3))
            nodes[:nnodes] = self.raw['nodes'][:, :3]
            nodes[nnodes:] = unique_nodes

            # Add extra node numbers
            nnum = np.hstack(
                (self.raw['nnum'], np.ones(nextra, np.int32) * -1))

        # Create unstructured grid
        grid = vtki.UnstructuredGrid(offset, cells, cell_type, nodes)

        # Store original ANSYS element and cell information
        grid.point_arrays['ansys_node_num'] = nnum
        grid.cell_arrays['ansys_elem_num'] = enum
        grid.cell_arrays['ansys_elem_type_num'] = parsed['etype']
        grid.cell_arrays['ansys_real_constant'] = parsed['rcon']
        grid.cell_arrays['ansys_material_type'] = parsed['mtype']
        grid.cell_arrays['ansys_etype'] = parsed['ansys_etype']

        # Add element components to unstructured grid
        for comp in self.raw['elem_comps']:
            mask = np.in1d(enum,
                           self.raw['elem_comps'][comp],
                           assume_unique=True)
            grid.cell_arrays[comp.strip()] = mask

        # Add node components to unstructured grid
        for comp in self.raw['node_comps']:
            mask = np.in1d(nnum,
                           self.raw['node_comps'][comp],
                           assume_unique=True)
            grid.point_arrays[comp.strip()] = mask

        # Add tracker for original node numbering
        ind = np.arange(grid.number_of_points)
        grid.point_arrays['origid'] = ind
        grid.point_arrays['VTKorigID'] = ind

        self.vtkuGrid = grid
        return grid
Exemplo n.º 4
0
    def ParseVTK(self, force_linear=False, allowable_types=None):
        """
        Parses raw data from cdb file to VTK format.

        Parameters
        ----------
        force_linear : bool, optional
            This parser creates quadradic elements if available.  Set this to
            True to always create linear elements.  Defaults to False.

        allowable_types : list, optional
            Allowable element types.  Defaults to:
            ['45', '95', '185', '186', '92', '187']

            Can include:
            ['45', '95', '185', '186', '92', '187', '154']

        Returns
        -------
        uGrid : vtk.vtkUnstructuredGrid
            VTK unstructured grid from archive file.

        """

        if not vtk_loaded:
            raise Exception(
                'Unable to load VTK module.  Cannot parse raw cdb data')

        if self.CheckRaw():
            raise Exception(
                'Missing key data.  Cannot parse into unstructured grid')

        # Convert to vtk style arrays
        if allowable_types is None:
            allowable_types = ['45', '95', '185', '186', '92', '187']
        else:
            assert isinstance(allowable_types, list), \
                   'allowable_types must be a list'

        result = _parser.Parse(self.raw, force_linear, allowable_types)
        cells, offset, cell_type, numref, enum, etype, rcon = result

        # catch bug
        cells[cells > numref.max()] = -1

        # Check for missing midside nodes
        possible_merged = False
        if force_linear or np.all(cells != -1):
            nodes = self.raw['nodes'][:, :3].copy()
            nnum = self.raw['nnum']

        else:
            mask = cells == -1

            nextra = mask.sum()
            maxnum = numref.max() + 1
            cells[mask] = np.arange(maxnum, maxnum + nextra)

            nnodes = self.raw['nodes'].shape[0]
            nodes = np.zeros((nnodes + nextra, 3))
            nodes[:nnodes] = self.raw['nodes'][:, :3]

            # Add extra node numbers
            nnum = np.hstack((self.raw['nnum'],
                              np.ones(nextra, np.int32) * -1))

            # Set new midside nodes directly between their edge nodes
            temp_nodes = nodes.copy()
            _relaxmidside.ResetMidside(cells, temp_nodes)
            nodes[nnodes:] = temp_nodes[nnodes:]

            possible_merged = True

        # Create unstructured grid
        grid = vtkInterface.UnstructuredGrid(offset, cells, cell_type, nodes)

        # Store original ANSYS numbering
        grid.AddPointScalars(nnum, 'ANSYSnodenum')
        grid.AddCellScalars(enum, 'ANSYS_elem_num')
        grid.AddCellScalars(etype, 'ANSYS_elem_typenum')
        grid.AddCellScalars(rcon, 'ANSYS_real_constant')

        # Add node components to unstructured grid
        ibool = np.empty(grid.GetNumberOfPoints(), dtype=np.int8)
        for comp in self.raw['node_comps']:
            ibool[:] = 0  # reset component array

            # Convert to new node numbering
            nodenum = numref[self.raw['node_comps'][comp]]

            ibool[nodenum] = 1
            grid.AddPointScalars(ibool, comp.strip())

        # merge duplicate points
        if possible_merged:
            vtkappend = vtk.vtkAppendFilter()
            vtkappend.AddInputData(grid)
            vtkappend.MergePointsOn()
            vtkappend.Update()
            grid = vtkInterface.UnstructuredGrid(vtkappend.GetOutput())

        # Add tracker for original node numbering
        npoints = grid.GetNumberOfPoints()
        grid.AddPointScalars(np.arange(npoints), 'VTKorigID')

        self.vtkuGrid = grid

        return grid