Example #1
0
    def grid(self):
        """ Returns a vtkInterface unstructured grid """
        if 'vtkInterface' not in sys.modules:
            raise Exception('Cannot create grid without vtkInterface.\n' +
                            'Please run:\npip install vtkInterface')
        elif not hasattr(self, 'node'):
            raise Exception('Run Tetrahedralize first')

        if hasattr(self, '_grid') and not self._updated:
            return self._grid

        buf = np.empty((self.elem.shape[0], 1), np.int64)
        cell_type = np.empty(self.elem.shape[0], dtype='uint8')
        if self.elem.shape[1] == 4:  # linear
            buf[:] = 4
            cell_type[:] = 10
        elif self.elem.shape[1] == 10:  # quadradic
            buf[:] = 10
            cell_type[:] = 24
        else:
            raise Exception('Invalid element array shape %s' %
                            str(self.elem.shape))

        offset = np.cumsum(buf + 1) - (buf[0] + 1)
        cells = np.hstack((buf, self.elem))
        self._grid = vtki.UnstructuredGrid(offset, cells, cell_type, self.node)
        self._updated = False
        return self._grid
Example #2
0
    def AddCyclicProperties(self):
        """ Adds cyclic properties to result object """
        # ansys's duplicate sector contains nodes from the second half of the node
        # numbering
        #
        # ansys node numbering for the duplicate sector is
        # nnum.min() + nnum.max()
        # where nnum is the node numbering for the master sector

#        if not vtkloaded:
#            raise Exception('Unable to add ')

        # master sector max node number
        num_master_max = self.nnum[int(self.nnum.size / 2) - 1]

        # identify master and duplicate cyclic sectors
        cells = np.arange(self.enum.size)
        dup_cells = np.where(
            np.any(
                self.geometry['elem'] > num_master_max,
                1))[0]
        mas_cells = np.setdiff1d(cells, dup_cells)
        self.sector = self.grid.ExtractSelectionCells(mas_cells)
        dup_sector = self.grid.ExtractSelectionCells(dup_cells)

        # Store the indices of the master and duplicate nodes
        self.mas_ind = self.sector.GetPointScalars('vtkOriginalPointIds')
        self.dup_ind = dup_sector.GetPointScalars('vtkOriginalPointIds')

        # store cyclic node numbers
        self.cyc_nnum = self.nnum[self.mas_ind]

        # create full rotor
        nSector = self.resultheader['nSector']

        # Copy and translate mesh
        vtkappend = vtk.vtkAppendFilter()
        rang = 360.0 / nSector
        for i in range(nSector):

            # Transform mesh
            sector = self.sector.Copy()
            sector.RotateZ(rang * i)

            vtkappend.AddInputData(sector)

        # Combine meshes and add VTK_Utilities functions
        # vtkappend.MergePointsOn()
        vtkappend.Update()
        self.rotor = vtkInterface.UnstructuredGrid(vtkappend.GetOutput())
    def read_cell_data(self, fn_start):
        """Read cell data from ``vtk``

        Args:
            fn_start (:obj:`int`): the index of starting letter in
                ``ls -lrth`` corresponding to vtk filename
        """

        # We list all the files in ``vtk_folder``, then we extract the
        # vtk filename without the affix and append with list.
        # Then we sort it from small to large, since we need the vtk data
        # to be sequential in time. Finally we put the vectorized data as
        # `UV_concate_cell_array`.

        vtk_file_list = []
        file_list = os.listdir(self.vtk_folder)
        for names in file_list:
            if names.endswith(".vtk"):
                vtk_file_list.append(names[fn_start:-4])

        vtk_file_array = np.array(vtk_file_list, dtype=int)
        vtk_file_array.sort()

        uv_concate_cell_list = []
        for vtk_file in vtk_file_array:
            print 'current working on ', vtk_file

            # Note: grid is the central object in VTK where every field is added on to grid
            grid = vtki.UnstructuredGrid(self.vtk_folder + self.case_name + '_' + str(vtk_file) + \
                                         '.vtk')

            vel_cell = grid.cell_arrays['U']  # get the vector velocity

            u_cell = vel_cell[:, 0]  # get Ux
            v_cell = vel_cell[:, 1]  # get Uy

            uv_concate_cell = np.hstack(
                (u_cell, v_cell))  # concate U,V together

            uv_concate_cell_list.append(
                uv_concate_cell)  # we append the snapshots of stacked state
            # vector

        self.UV_concate_cell_array = np.array(
            uv_concate_cell_list)  # we transform it into
Example #4
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)
Example #5
0
def test_merge():
    from vtkInterface import examples
    beamA = vtki.UnstructuredGrid(examples.hexbeamfile)
    beamB = beamA.Copy()
    beamB.points[:, 1] += 1
    beamA.Merge(beamB)
Example #6
0
def BeamExample():
    # Load module and example file

    hexfile = hexbeamfile

    # Load Grid
    grid = vtkInterface.UnstructuredGrid(hexfile)

    # Create fiticious displacements as a function of Z location
    pts = grid.GetNumpyPoints(deep=True)
    d = np.zeros_like(pts)
    d[:, 1] = pts[:, 2]**3/250

    # Displace original grid
    grid.SetNumpyPoints(pts + d)

    # Camera position
    cpos = [(11.915126303095157, 6.11392754955802, 3.6124956735471914),
            (0.0, 0.375, 2.0),
            (-0.42546442225230097, 0.9024244135964158, -0.06789847673314177)]

    try:
        import matplotlib
        colormap = 'bwr'
    except ImportError:
        colormap = None

    # plot this displaced beam
    plobj = vtkInterface.PlotClass()
    plobj.AddMesh(grid, scalars=d[:, 1], stitle='Y Displacement',
                  rng=[-d.max(), d.max()], colormap=colormap)
    plobj.SetCameraPosition(cpos)
    plobj.AddText('Static Beam Example')
    cpos = plobj.Plot(autoclose=False)  # store camera position
    # plobj.TakeScreenShot('beam.png')
    plobj.Close()

    # Animate plot
    plobj = vtkInterface.PlotClass()
    plobj.AddMesh(grid, scalars=d[:, 1], stitle='Y Displacement', showedges=True,
                  rng=[-d.max(), d.max()], interpolatebeforemap=True,
                  colormap=colormap)
    plobj.SetCameraPosition(cpos)
    plobj.AddText('Beam Animation Example')
    plobj.Plot(interactive=False, autoclose=False, window_size=[800, 600])

    #plobj.OpenMovie('beam.mp4')
#    plobj.OpenGif('beam.gif')
    for phase in np.linspace(0, 4*np.pi, 100):
        plobj.UpdateCoordinates(pts + d*np.cos(phase), render=False)
        plobj.UpdateScalars(d[:, 1]*np.cos(phase), render=False)
        plobj.Render()
#        plobj.WriteFrame()
        time.sleep(0.01)

    plobj.Close()

    # Animate plot as a wireframe
    plobj = vtkInterface.PlotClass()
    plobj.AddMesh(grid, scalars=d[:, 1], stitle='Y Displacement',
                  showedges=True, rng=[-d.max(), d.max()], colormap=colormap,
                  interpolatebeforemap=True, style='wireframe')
    plobj.SetCameraPosition(cpos)
    plobj.AddText('Beam Animation Example 2')
    plobj.Plot(interactive=False, autoclose=False, window_size=[800, 600])

    # plobj.OpenMovie('beam.mp4')
    # plobj.OpenGif('beam_wireframe.gif')
    for phase in np.linspace(0, 4*np.pi, 100):
        plobj.UpdateCoordinates(pts + d*np.cos(phase), render=False)
        plobj.UpdateScalars(d[:, 1]*np.cos(phase), render=False)
        plobj.Render()
#        plobj.WriteFrame()
        time.sleep(0.01)

    plobj.Close()
Example #7
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
Example #8
0
    def pps_paraview_cylinder(
        self,
        cylinder_folder="./50d_cylinder_flow_pod_case",
        pod_path="/media/shaowu/shaowu_main_hard/shaowu/OpenFOAM/shaowu-6/run/vortex_shedding/c6_re100_whole_POD.npz"
    ):
        """postprocessing for cylinder case with paraview.

        This is a very problem specific method. It will use the POD weights and it will use eval trajectory
        to get the full field projected and saved into vtk files. It is a good example for extending to other cases.

        Args:
            cylinder_folder (:obj:`str`): path to the full POD data.

        """

        # 1. read POD data from POD path
        pod_data = np.load(pod_path)
        vh = pod_data['vh']
        # s = pod_data['s']
        # u = pod_data['u']

        # 2. read eval file
        eval_file_name = 'save_trj_comparison_whole.npz'
        eval_file_data = np.load(self.eval_dir + '/' +
                                 self.params['model_name'] + '/' +
                                 eval_file_name)
        true_trajectory = eval_file_data['ttrj']
        pred_trajectory = eval_file_data['ptrj']

        # compute the mean and std
        print('')
        print('pred trajectory shape = ')
        print(pred_trajectory.shape)
        print('')

        pred_trajectory_mean = np.mean(pred_trajectory, axis=0)
        pred_trajectory_std = np.std(pred_trajectory, axis=0)
        print('pred_trajectory_std shape = ', pred_trajectory_std.shape)

        # 3. generate VTK files
        self.vtk_folder = self.pps_dir + '/VTK'

        # make directory for vtk
        mkdir(self.vtk_folder)

        # 3.1 generate true flowfield VTK
        true_data_UV_array = np.matmul(true_trajectory,
                                       vh[:true_trajectory.shape[1], :])
        true_data_U = true_data_UV_array[:, :int(true_data_UV_array.shape[1] /
                                                 2)]
        true_data_V = true_data_UV_array[:,
                                         int(true_data_UV_array.shape[1] / 2):]
        true_data_W = np.zeros(true_data_U.shape)

        # get 3d true velo
        true_data_vel = np.stack((true_data_U, true_data_V, true_data_W),
                                 axis=2)

        # 3.2 generate pred flowfield VTK -- mean
        pred_data_UV_array = np.matmul(pred_trajectory_mean,
                                       vh[:pred_trajectory_mean.shape[1], :])
        pred_data_U = pred_data_UV_array[:, :int(pred_data_UV_array.shape[1] /
                                                 2)]
        pred_data_V = pred_data_UV_array[:,
                                         int(pred_data_UV_array.shape[1] / 2):]
        pred_data_W = np.zeros(pred_data_U.shape)

        # get 3d pred velo
        pred_data_vel_mean = np.stack((pred_data_U, pred_data_V, pred_data_W),
                                      axis=2)

        # 3.2 -- std
        pred_data_UV_array_std = np.matmul(
            pred_trajectory_std, vh[:pred_trajectory_std.shape[1], :])
        pred_data_U_std = pred_data_UV_array_std[:, :int(pred_data_UV_array_std
                                                         .shape[1] / 2)]
        pred_data_V_std = pred_data_UV_array_std[:,
                                                 int(pred_data_UV_array_std.
                                                     shape[1] / 2):]
        pred_data_W_std = np.zeros(pred_data_U_std.shape)

        # get 3d pred velo -- std
        pred_data_vel_std = np.stack(
            (pred_data_U_std, pred_data_V_std, pred_data_W_std), axis=2)

        # 3.5 read blank VTK files for cylinder to write new things on: loop over time
        for time_step in range(true_data_U.shape[0]):

            true_data = vtki.UnstructuredGrid(cylinder_folder + '/base.vtk')
            pred_data = vtki.UnstructuredGrid(cylinder_folder + '/base.vtk')

            # 3.2 add fields in
            true_data.AddCellScalars(true_data_vel[time_step, :, :], 'U')

            pred_data.AddCellScalars(pred_data_vel_mean[time_step, :, :],
                                     'U_mean')
            pred_data.AddCellScalars(pred_data_vel_std[time_step, :, :],
                                     'U_std')

            # save
            true_data.Write(self.vtk_folder + '/true_flowfield_' +
                            str(time_step) + '.vtk')
            pred_data.Write(self.vtk_folder + '/pred_flowfield_' +
                            str(time_step) + '.vtk')

            del (true_data)
            del (pred_data)
Example #9
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