示例#1
0
def aero2struct_force_mapping(aero_forces,
                              struct2aero_mapping,
                              zeta,
                              pos_def,
                              psi_def,
                              master,
                              master_elem,
                              cag=np.eye(3)):

    n_node, _ = pos_def.shape
    struct_forces = np.zeros((n_node, 6))

    for i_global_node in range(n_node):
        for mapping in struct2aero_mapping[i_global_node]:
            i_surf = mapping['i_surf']
            i_n = mapping['i_n']
            _, n_m, _ = aero_forces[i_surf].shape

            i_master_elem, master_elem_local_node = master[i_global_node, :]

            crv = psi_def[i_master_elem, master_elem_local_node, :]
            cab = algebra.crv2rot(crv)
            cbg = np.dot(cab.T, cag)

            for i_m in range(n_m):
                chi_g = zeta[i_surf][:, i_m, i_n] - np.dot(
                    cag.T, pos_def[i_global_node, :])
                struct_forces[i_global_node, 0:3] += np.dot(
                    cbg, aero_forces[i_surf][0:3, i_m, i_n])
                struct_forces[i_global_node, 3:6] += np.dot(
                    cbg, aero_forces[i_surf][3:6, i_m, i_n])
                struct_forces[i_global_node, 3:6] += np.dot(
                    cbg, np.cross(chi_g, aero_forces[i_surf][0:3, i_m, i_n]))
    return struct_forces
示例#2
0
    def calculate_forces(self, trajectory, input_trajectory, i_global_node,
                         i_trajectory_node):
        """
        This calculates the necessary response based on the current trajectory (trajectoy),
        the desired trayectory (input_trajectory) and the given node id.
        The output will be already converted to the material (b) FoR.
        """
        # for i in range(n_steps):
        #     state[i] = np.sum(feedback[:i])
        #     controller.set_point(set_point[i])
        #     feedback[i] = controller(state[i])
        force = np.zeros((3, ))
        for idim in range(3):
            # print('dim = ' + str(idim))
            self.controllers[i_trajectory_node][idim].set_point(
                input_trajectory[idim])
            force[idim] = self.controllers[i_trajectory_node][idim](
                trajectory[idim])

        master_elem, i_local_node_master_elem = self.data.structure.node_master_elem[
            i_global_node, :]
        cba = algebra.crv2rot(self.data.structure.timestep_info[
            self.data.ts].psi[master_elem, i_local_node_master_elem, :]).T
        cag = self.data.structure.timestep_info[self.data.ts].cag()

        force = np.dot(cba, np.dot(cag, force))
        return force
示例#3
0
    def nodal_b_for_2_a_for(self, nodal, tstep, filter=np.array([True]*6)):
        nodal_a = nodal.copy(order='F')
        for i_node in range(self.num_node):
            # get master elem and i_local_node
            i_master_elem, i_local_node = self.node_master_elem[i_node, :]
            crv = tstep.psi[i_master_elem, i_local_node, :]
            cab = algebra.crv2rot(crv)
            temp = np.zeros((6,))
            temp[0:3] = np.dot(cab, nodal[i_node, 0:3])
            temp[3:6] = np.dot(cab, nodal[i_node, 3:6])
            for i in range(6):
                if filter[i]:
                    nodal_a[i_node, i] = temp[i]

        return nodal_a
示例#4
0
def generate_strip(node_info,
                   airfoil_db,
                   aligned_grid,
                   orientation_in=np.array([1, 0, 0])):
    """
    Returns a strip in "a" frame of reference, it has to be then rotated to
    simulate angles of attack, etc
    :param node_info:
    :param airfoil_db:
    :param aligned_grid:
    :param orientation_in:
    :return:
    """
    strip_coordinates_a_frame = np.zeros((3, node_info['M'] + 1),
                                         dtype=ct.c_double)
    strip_coordinates_b_frame = np.zeros((3, node_info['M'] + 1),
                                         dtype=ct.c_double)

    # airfoil coordinates
    # we are going to store everything in the x-z plane of the b
    # FoR, so that the transformation Cab rotates everything in place.
    if node_info['M_distribution'] == 'uniform':
        strip_coordinates_b_frame[1, :] = np.linspace(0.0, 1.0,
                                                      node_info['M'] + 1)
    elif node_info['M_distribution'] == '1-cos':
        domain = np.linspace(0, 1.0, node_info['M'] + 1)
        strip_coordinates_b_frame[1, :] = 0.5 * (1.0 - np.cos(domain * np.pi))
    else:
        raise NotImplemented('M_distribution is ' +
                             node_info['M_distribution'] +
                             ' and it is not yet supported')
    strip_coordinates_b_frame[2, :] = airfoil_db[node_info['airfoil']](
        strip_coordinates_b_frame[1, :])

    # elastic axis correction
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_b_frame[1, i_M] -= node_info['eaxis']

    # chord scaling
    strip_coordinates_b_frame *= node_info['chord']

    # twist transformation (rotation around x_b axis)
    if np.abs(node_info['twist']) > 1e-6:
        Ctwist = algebra.rotation3d_x(node_info['twist'])
    else:
        Ctwist = np.eye(3)

    # Cab transformation
    Cab = algebra.crv2rot(node_info['beam_psi'])

    # sweep angle correction
    # angle between orientation_in and chord line
    chord_line_b_frame = strip_coordinates_b_frame[:,
                                                   -1] - strip_coordinates_b_frame[:,
                                                                                   0]
    chord_line_a_frame = np.dot(Cab, chord_line_b_frame)
    sweep_angle = algebra.angle_between_vectors_sign(orientation_in,
                                                     chord_line_a_frame,
                                                     np.array([0, 0, 1]))
    # rotation matrix
    Csweep = algebra.rotation3d_z(-sweep_angle)

    # transformation from beam to aero
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_a_frame[:, i_M] = np.dot(
            Cab,
            np.dot(Csweep, np.dot(Ctwist, strip_coordinates_b_frame[:, i_M])))

    # add node coords
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_a_frame[:, i_M] += node_info['beam_coord']

    return strip_coordinates_a_frame
示例#5
0
文件: modal.py 项目: ljnpu/sharpy-1
def get_mode_zeta(data, eigvect):
    ''' 
    Retrieves the UVLM grid nodal displacements associated to the eigenvector 
    eigvect
    '''

    ### initialise
    aero = data.aero
    struct = data.structure
    tsaero = data.aero.timestep_info[data.ts]
    tsstr = data.structure.timestep_info[data.ts]

    num_dof = struct.num_dof.value
    eigvect = eigvect[:num_dof]

    zeta_mode = []
    for ss in range(aero.n_surf):
        zeta_mode.append(tsaero.zeta[ss].copy())

    jj = 0  # structural dofs index
    Cag0 = algebra.quat2rot(tsstr.quat)
    Cga0 = Cag0.T
    for node_glob in range(struct.num_node):

        ### detect bc at node (and no. of dofs)
        bc_here = struct.boundary_conditions[node_glob]
        if bc_here == 1:  # clamp
            dofs_here = 0
            continue
        elif bc_here == -1 or bc_here == 0:
            dofs_here = 6
            jj_tra = [jj, jj + 1, jj + 2]
            jj_rot = [jj + 3, jj + 4, jj + 5]
        jj += dofs_here

        # retrieve element and local index
        ee, node_loc = struct.node_master_elem[node_glob, :]

        # get original position and crv
        Ra0 = tsstr.pos[node_glob, :]
        psi0 = tsstr.psi[ee, node_loc, :]
        Rg0 = np.dot(Cga0, Ra0)
        Cab0 = algebra.crv2rot(psi0)
        Cbg0 = np.dot(Cab0.T, Cag0)

        # update position and crv of mode
        Ra = tsstr.pos[node_glob, :] + eigvect[jj_tra]
        psi = tsstr.psi[ee, node_loc, :] + eigvect[jj_rot]
        Rg = np.dot(Cga0, Ra)
        Cab = algebra.crv2rot(psi)
        Cbg = np.dot(Cab.T, Cag0)

        ### str -> aero mapping
        # some nodes may be linked to multiple surfaces...
        for str2aero_here in aero.struct2aero_mapping[node_glob]:

            # detect surface/span-wise coordinate (ss,nn)
            nn, ss = str2aero_here['i_n'], str2aero_here['i_surf']
            #print('%.2d,%.2d'%(nn,ss))

            # surface panelling
            M = aero.aero_dimensions[ss][0]
            N = aero.aero_dimensions[ss][1]

            for mm in range(M + 1):

                # get position of vertex in B FoR
                zetag0 = tsaero.zeta[ss][:, mm,
                                         nn]  # in G FoR, w.r.t. origin A-G
                Xb = np.dot(Cbg0, zetag0 - Rg0)  # in B FoR, w.r.t. origin B

                # update vertex position
                zeta_mode[ss][:, mm, nn] = Rg + np.dot(np.dot(Cga0, Cab), Xb)

    return zeta_mode
示例#6
0
def generate_strip(node_info, airfoil_db, aligned_grid, orientation_in=np.array([1, 0, 0]), calculate_zeta_dot = False):
    """
    Returns a strip in "a" frame of reference, it has to be then rotated to
    simulate angles of attack, etc
    :param node_info:
    :param airfoil_db:
    :param aligned_grid:
    :param orientation_in:
    :return:
    """
    strip_coordinates_a_frame = np.zeros((3, node_info['M'] + 1), dtype=ct.c_double)
    strip_coordinates_b_frame = np.zeros((3, node_info['M'] + 1), dtype=ct.c_double)

    # airfoil coordinates
    # we are going to store everything in the x-z plane of the b
    # FoR, so that the transformation Cab rotates everything in place.
    if node_info['M_distribution'] == 'uniform':
        strip_coordinates_b_frame[1, :] = np.linspace(0.0, 1.0, node_info['M'] + 1)
    elif node_info['M_distribution'] == '1-cos':
        domain = np.linspace(0, 1.0, node_info['M'] + 1)
        strip_coordinates_b_frame[1, :] = 0.5*(1.0 - np.cos(domain*np.pi))
    else:
        raise NotImplemented('M_distribution is ' + node_info['M_distribution'] +
                             ' and it is not yet supported')
    strip_coordinates_b_frame[2, :] = airfoil_db[node_info['airfoil']](
                                            strip_coordinates_b_frame[1, :])

    # elastic axis correction
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_b_frame[1, i_M] -= node_info['eaxis']

    chord_line_b_frame = strip_coordinates_b_frame[:, -1] - strip_coordinates_b_frame[:, 0]

    # control surface deflection
    if node_info['control_surface'] is not None:
        b_frame_hinge_coords = strip_coordinates_b_frame[:, node_info['M'] - node_info['control_surface']['chord']]
        # support for different hinge location for fully articulated control surfaces
        if node_info['control_surface']['hinge_coords'] is not None:
            # make sure the hinge coordinates are only applied when M == cs_chord
            if not node_info['M'] - node_info['control_surface']['chord'] == 0:
                cout.cout_wrap('The hinge coordinates parameter is only supported when M == cs_chord')
                node_info['control_surface']['hinge_coords'] = None
            else:
                b_frame_hinge_coords =  node_info['control_surface']['hinge_coords']

        for i_M in range(node_info['M'] - node_info['control_surface']['chord'], node_info['M'] + 1):
            relative_coords = strip_coordinates_b_frame[:, i_M] - b_frame_hinge_coords
            # rotate the control surface
            relative_coords = np.dot(algebra.rotation3d_x(-node_info['control_surface']['deflection']),
                                     relative_coords)
            # restore coordinates
            relative_coords += b_frame_hinge_coords

            # substitute with new coordinates
            strip_coordinates_b_frame[:, i_M] = relative_coords

    # chord scaling
    strip_coordinates_b_frame *= node_info['chord']

    # twist transformation (rotation around x_b axis)
    if np.abs(node_info['twist']) > 1e-6:
        Ctwist = algebra.rotation3d_x(node_info['twist'])
    else:
        Ctwist = np.eye(3)

    # Cab transformation
    Cab = algebra.crv2rot(node_info['beam_psi'])

    rot_angle = algebra.angle_between_vectors_sign(orientation_in, Cab[:, 1], Cab[:, 2])
    Crot = algebra.rotation3d_z(-rot_angle)

    c_sweep = np.eye(3)
    if np.abs(node_info['sweep']) > 1e-6:
        c_sweep = algebra.rotation3d_z(node_info['sweep'])

    # transformation from beam to beam prime (with sweep and twist)
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_b_frame[:, i_M] = np.dot(c_sweep, np.dot(Crot,
                                                   np.dot(Ctwist, strip_coordinates_b_frame[:, i_M])))
        strip_coordinates_a_frame[:, i_M] = np.dot(Cab, strip_coordinates_b_frame[:, i_M])

    # zeta_dot
    if calculate_zeta_dot:
        zeta_dot_a_frame = np.zeros((3, node_info['M'] + 1), dtype=ct.c_double)

        # velocity due to pos_dot
        for i_M in range(node_info['M'] + 1):
            zeta_dot_a_frame[:, i_M] += node_info['pos_dot']

        # velocity due to psi_dot
        Omega_b = algebra.crv_dot2Omega(node_info['beam_psi'], node_info['psi_dot'])
        for i_M in range(node_info['M'] + 1):
            zeta_dot_a_frame[:, i_M] += (
                np.dot(algebra.skew(Omega_b), strip_coordinates_a_frame[:, i_M]))

    else:
        zeta_dot_a_frame = np.zeros((3, node_info['M'] + 1), dtype=ct.c_double)

    # add node coords
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_a_frame[:, i_M] += node_info['beam_coord']

    # rotation from a to g
    for i_M in range(node_info['M'] + 1):
        strip_coordinates_a_frame[:, i_M] = np.dot(node_info['cga'],
                                                   strip_coordinates_a_frame[:, i_M])
        zeta_dot_a_frame[:, i_M] = np.dot(node_info['cga'],
                                          zeta_dot_a_frame[:, i_M])

    return strip_coordinates_a_frame, zeta_dot_a_frame
示例#7
0
    def plot(self):
        for it in range(len(self.data.structure.timestep_info)):
            it_filename = (self.filename + '%06u' % it)
            num_nodes = self.data.structure.num_node
            num_elem = self.data.structure.num_elem

            coords = np.zeros((num_nodes, 3))
            conn = np.zeros((num_elem, 3), dtype=int)
            node_id = np.zeros((num_nodes, ), dtype=int)
            elem_id = np.zeros((num_elem, ), dtype=int)
            local_x = np.zeros((num_nodes, 3))
            local_y = np.zeros((num_nodes, 3))
            local_z = np.zeros((num_nodes, 3))
            # output_loads = True
            # try:
            #     self.data.beam.timestep_info[it].loads
            # except AttributeError:
            #     output_loads = False

            # if output_loads:
            #     gamma = np.zeros((num_elem, 3))
            #     kappa = np.zeros((num_elem, 3))

            # if self.settings['applied_forces']:

            # if self.settings['frame'] == 'inertial':
            #     try:
            #         self.aero2inertial = self.data.grid.inertial2aero.T
            #     except AttributeError:
            #         self.aero2inertial = np.eye(3)
            #         cout.cout_wrap('BeamPlot: No inertial2aero information, output will be in body FoR', 0)
            #
            # else:
            #     self.aero2inertial = np.eye(3)

            app_forces = np.zeros((num_nodes, 3))
            unsteady_app_forces = np.zeros((num_nodes, 3))

            # aero2inertial rotation
            aero2inertial = algebra.quat2rot(
                self.data.structure.timestep_info[it].quat).transpose()

            # coordinates of corners
            # for i_node in range(num_nodes):
            #     coords[i_node, :] = self.data.structure.timestep_info[it].pos[i_node, :]
            #     if self.settings['include_rbm']:
            #         coords[i_node, :] = np.dot(aero2inertial, coords[i_node, :])
            #         coords[i_node, :] += self.data.structure.timestep_info[it].for_pos[0:3]
            coords = self.data.structure.timestep_info[it].glob_pos(
                include_rbm=self.settings['include_rbm'])

            for i_node in range(num_nodes):
                i_elem = self.data.structure.node_master_elem[i_node, 0]
                i_local_node = self.data.structure.node_master_elem[i_node, 1]
                node_id[i_node] = i_node

                # v1, v2, v3 = self.data.structure.elements[i_elem].deformed_triad(
                #     self.data.structure.timestep_info[it].psi[i_elem, :, :]
                # )
                # local_x[i_node, :] = np.dot(aero2inertial, v1[i_local_node, :])
                # local_y[i_node, :] = np.dot(aero2inertial, v2[i_local_node, :])
                # local_z[i_node, :] = np.dot(aero2inertial, v3[i_local_node, :])
                v1 = np.array([1., 0, 0])
                v2 = np.array([0., 1, 0])
                v3 = np.array([0., 0, 1])
                cab = algebra.crv2rot(
                    self.data.structure.timestep_info[it].psi[i_elem,
                                                              i_local_node, :])
                local_x[i_node, :] = np.dot(aero2inertial, np.dot(cab, v1))
                local_y[i_node, :] = np.dot(aero2inertial, np.dot(cab, v2))
                local_z[i_node, :] = np.dot(aero2inertial, np.dot(cab, v3))

                # applied forces
                cab = algebra.crv2rot(
                    self.data.structure.timestep_info[it].psi[i_elem,
                                                              i_local_node, :])
                app_forces[i_node, :] = np.dot(
                    aero2inertial,
                    np.dot(
                        cab, self.data.structure.timestep_info[it].
                        steady_applied_forces[i_node, 0:3]))
                if not it == 0:
                    try:
                        unsteady_app_forces[i_node, :] = np.dot(
                            aero2inertial,
                            np.dot(
                                cab, self.data.structure.dynamic_input[it - 1]
                                ['dynamic_forces'][i_node, 0:3]))
                    except IndexError:
                        pass

            for i_elem in range(num_elem):
                conn[i_elem, :] = self.data.structure.elements[
                    i_elem].reordered_global_connectivities
                elem_id[i_elem] = i_elem
                # if output_loads:
                #     gamma[i_elem, :] = self.data.structure.timestep_info[it].loads[i_elem, 0:3]
                #     kappa[i_elem, :] = self.data.structure.timestep_info[it].loads[i_elem, 3:6]

            ug = tvtk.UnstructuredGrid(points=coords)
            ug.set_cells(tvtk.Line().cell_type, conn)
            ug.cell_data.scalars = elem_id
            ug.cell_data.scalars.name = 'elem_id'
            # if output_loads:
            #     ug.cell_data.add_array(gamma, 'vector')
            #     ug.cell_data.get_array(1).name = 'gamma'
            #     ug.cell_data.add_array(kappa, 'vector')
            #     ug.cell_data.get_array(2).name = 'kappa'
            ug.point_data.scalars = node_id
            ug.point_data.scalars.name = 'node_id'
            point_vector_counter = 1
            ug.point_data.add_array(local_x, 'vector')
            ug.point_data.get_array(point_vector_counter).name = 'local_x'
            point_vector_counter += 1
            ug.point_data.add_array(local_y, 'vector')
            ug.point_data.get_array(point_vector_counter).name = 'local_y'
            point_vector_counter += 1
            ug.point_data.add_array(local_z, 'vector')
            ug.point_data.get_array(point_vector_counter).name = 'local_z'
            if self.settings['include_applied_forces']:
                point_vector_counter += 1
                ug.point_data.add_array(app_forces, 'vector')
                ug.point_data.get_array(
                    point_vector_counter).name = 'app_forces'
            if self.settings['include_unsteady_applied_forces']:
                point_vector_counter += 1
                ug.point_data.add_array(unsteady_app_forces, 'vector')
                ug.point_data.get_array(
                    point_vector_counter).name = 'unsteady_app_forces'

            write_data(ug, it_filename)
示例#8
0
    def write_beam(self, it):
        it_filename = (self.filename +
                       '%06u' % it)
        num_nodes = self.data.structure.num_node
        num_elem = self.data.structure.num_elem

        coords = np.zeros((num_nodes, 3))
        conn = np.zeros((num_elem, 3), dtype=int)
        node_id = np.zeros((num_nodes,), dtype=int)
        elem_id = np.zeros((num_elem,), dtype=int)
        coords_a_cell = np.zeros((num_elem, 3), dtype=int)
        local_x = np.zeros((num_nodes, 3))
        local_y = np.zeros((num_nodes, 3))
        local_z = np.zeros((num_nodes, 3))
        coords_a = np.zeros((num_nodes, 3))

        app_forces = np.zeros((num_nodes, 3))
        app_moment = np.zeros((num_nodes, 3))

        # aero2inertial rotation
        aero2inertial = self.data.structure.timestep_info[it].cga()

        # coordinates of corners
        coords = self.data.structure.timestep_info[it].glob_pos(include_rbm=self.settings['include_rbm'])

        # check if I can output gravity forces
        with_gravity = False
        try:
            gravity_forces = self.data.structure.timestep_info[it].gravity_forces[:]
            with_gravity = True
        except AttributeError:
            pass

        # check if postproc dicts are present and count/prepare
        with_postproc_cell = False
        try:
            self.data.structure.timestep_info[it].postproc_cell
            with_postproc_cell = True
        except AttributeError:
            pass
        with_postproc_node = False
        try:
            self.data.structure.timestep_info[it].postproc_node
            with_postproc_node = True
        except AttributeError:
            pass

        # count number of arguments
        postproc_cell_keys = self.data.structure.timestep_info[it].postproc_cell.keys()
        postproc_cell_vals = self.data.structure.timestep_info[it].postproc_cell.values()
        postproc_cell_scalar = []
        postproc_cell_vector = []
        postproc_cell_6vector = []
        for k, v in self.data.structure.timestep_info[it].postproc_cell.items():
            _, cols = v.shape
            if cols == 1:
                raise NotImplementedError('scalar cell types not supported in beamplot (Easy to implement)')
                # postproc_cell_scalar.append(k)
            elif cols == 3:
                postproc_cell_vector.append(k)
            elif cols == 6:
                postproc_cell_6vector.append(k)
            else:
                raise AttributeError('Only scalar and 3-vector types supported in beamplot')
        # count number of arguments
        postproc_node_keys = self.data.structure.timestep_info[it].postproc_node.keys()
        postproc_node_vals = self.data.structure.timestep_info[it].postproc_node.values()
        postproc_node_scalar = []
        postproc_node_vector = []
        postproc_node_6vector = []
        for k, v in self.data.structure.timestep_info[it].postproc_node.items():
            _, cols = v.shape
            if cols == 1:
                raise NotImplementedError('scalar node types not supported in beamplot (Easy to implement)')
                # postproc_cell_scalar.append(k)
            elif cols == 3:
                postproc_node_vector.append(k)
            elif cols == 6:
                postproc_node_6vector.append(k)
            else:
                raise AttributeError('Only scalar and 3-vector types supported in beamplot')

        for i_node in range(num_nodes):
            i_elem = self.data.structure.node_master_elem[i_node, 0]
            i_local_node = self.data.structure.node_master_elem[i_node, 1]
            node_id[i_node] = i_node

            v1 = np.array([1., 0, 0])
            v2 = np.array([0., 1, 0])
            v3 = np.array([0., 0, 1])
            cab = algebra.crv2rot(
                self.data.structure.timestep_info[it].psi[i_elem, i_local_node, :])
            local_x[i_node, :] = np.dot(aero2inertial, np.dot(cab, v1))
            local_y[i_node, :] = np.dot(aero2inertial, np.dot(cab, v2))
            local_z[i_node, :] = np.dot(aero2inertial, np.dot(cab, v3))

            if i_local_node == 2:
                coords_a_cell[i_elem, :] = self.data.structure.timestep_info[it].pos[i_node, :]
            coords_a[i_node, :] = self.data.structure.timestep_info[it].pos[i_node, :]

            # applied forces
            cab = algebra.crv2rot(self.data.structure.timestep_info[it].psi[i_elem, i_local_node, :])
            app_forces[i_node, :] = np.dot(aero2inertial,
                                           np.dot(cab,
                                                  self.data.structure.timestep_info[it].steady_applied_forces[i_node, 0:3]+
                                                  self.data.structure.timestep_info[it].unsteady_applied_forces[i_node, 0:3]))
            app_moment[i_node, :] = np.dot(aero2inertial,
                                           np.dot(cab,
                                                  self.data.structure.timestep_info[it].steady_applied_forces[i_node, 3:6]+
                                                  self.data.structure.timestep_info[it].unsteady_applied_forces[i_node, 3:6]))

            if with_gravity:
                gravity_forces[i_node, 0:3] = np.dot(aero2inertial,
                                                     gravity_forces[i_node, 0:3])
                gravity_forces[i_node, 3:6] = np.dot(aero2inertial,
                                                     gravity_forces[i_node, 3:6])

        for i_elem in range(num_elem):
            conn[i_elem, :] = self.data.structure.elements[i_elem].reordered_global_connectivities
            elem_id[i_elem] = i_elem

        ug = tvtk.UnstructuredGrid(points=coords)
        ug.set_cells(tvtk.Line().cell_type, conn)
        ug.cell_data.scalars = elem_id
        ug.cell_data.scalars.name = 'elem_id'
        counter = 1
        if with_postproc_cell:
            for k in postproc_cell_vector:
                ug.cell_data.add_array(self.data.structure.timestep_info[it].postproc_cell[k])
                ug.cell_data.get_array(counter).name = k + '_cell'
                counter += 1
            for k in postproc_cell_6vector:
                for i in range(0, 2):
                    ug.cell_data.add_array(self.data.structure.timestep_info[it].postproc_cell[k][:, 3*i:3*(i+1)])
                    ug.cell_data.get_array(counter).name = k + '_' + str(i) + '_cell'
                    counter += 1
        ug.cell_data.add_array(coords_a_cell)
        ug.cell_data.get_array(counter).name = 'coords_a_elem'
        counter += 1

        ug.point_data.scalars = node_id
        ug.point_data.scalars.name = 'node_id'
        point_vector_counter = 1
        ug.point_data.add_array(local_x, 'vector')
        ug.point_data.get_array(point_vector_counter).name = 'local_x'
        point_vector_counter += 1
        ug.point_data.add_array(local_y, 'vector')
        ug.point_data.get_array(point_vector_counter).name = 'local_y'
        point_vector_counter += 1
        ug.point_data.add_array(local_z, 'vector')
        ug.point_data.get_array(point_vector_counter).name = 'local_z'
        point_vector_counter += 1
        ug.point_data.add_array(coords_a, 'vector')
        ug.point_data.get_array(point_vector_counter).name = 'coords_a'
        if self.settings['include_applied_forces']:
            point_vector_counter += 1
            ug.point_data.add_array(app_forces, 'vector')
            ug.point_data.get_array(point_vector_counter).name = 'app_forces'
            if with_gravity:
                point_vector_counter += 1
                ug.point_data.add_array(gravity_forces[:, 0:3], 'vector')
                ug.point_data.get_array(point_vector_counter).name = 'gravity_forces'

        if self.settings['include_applied_moments']:
            point_vector_counter += 1
            ug.point_data.add_array(app_moment, 'vector')
            ug.point_data.get_array(point_vector_counter).name = 'app_moments'
            if with_gravity:
                point_vector_counter += 1
                ug.point_data.add_array(gravity_forces[:, 3:6], 'vector')
                ug.point_data.get_array(point_vector_counter).name = 'gravity_moments'
        if with_postproc_node:
            for k in postproc_node_vector:
                point_vector_counter += 1
                ug.point_data.add_array(self.data.structure.timestep_info[it].postproc_node[k])
                ug.point_data.get_array(point_vector_counter).name = k + '_point'
            for k in postproc_node_6vector:
                for i in range(0, 2):
                    point_vector_counter += 1
                    ug.point_data.add_array(self.data.structure.timestep_info[it].postproc_node[k][:, 3*i:3*(i+1)])
                    ug.point_data.get_array(point_vector_counter).name = k + '_' + str(i) + '_point'

        write_data(ug, it_filename)