def calculate_forces(self): for self.ts in range(self.ts_max): rot = algebra.quat2rot( self.data.structure.timestep_info[self.ts].quat).transpose() force = self.data.aero.timestep_info[self.ts].forces unsteady_force = self.data.aero.timestep_info[ self.ts].dynamic_forces n_surf = len(force) for i_surf in range(n_surf): total_steady_force = np.zeros((3, )) total_unsteady_force = np.zeros((3, )) _, n_rows, n_cols = force[i_surf].shape for i_m in range(n_rows): for i_n in range(n_cols): total_steady_force += force[i_surf][0:3, i_m, i_n] total_unsteady_force += unsteady_force[i_surf][0:3, i_m, i_n] self.data.aero.timestep_info[self.ts].inertial_steady_forces[ i_surf, 0:3] = total_steady_force self.data.aero.timestep_info[self.ts].inertial_unsteady_forces[ i_surf, 0:3] = total_unsteady_force self.data.aero.timestep_info[self.ts].body_steady_forces[ i_surf, 0:3] = np.dot(rot.T, total_steady_force) self.data.aero.timestep_info[self.ts].body_unsteady_forces[ i_surf, 0:3] = np.dot(rot.T, total_unsteady_force)
def glob_pos(self, include_rbm=True): coords = self.pos.copy() c = algebra.quat2rot(self.quat).transpose() for i_node in range(self.num_node): coords[i_node, :] = np.dot(c, coords[i_node, :]) if include_rbm: coords[i_node, :] += self.for_pos[0:3] return coords
def update_orientation(self, quat): """ :param quat: Corresponding to the Cga matrix :return: """ self.quat = quat.copy() # rotate gravity_vector_inertial to body # in fact the gravity vector is the vertical vector rot = algebra.quat2rot(self.quat) self.gravity_vector_body = np.dot(rot.T, self.gravity_vector_inertial)
def run(self): cout.cout_wrap('Running static coupled solver...', 1) for i_step in range(self.settings['n_load_steps'].value): # load step coefficient if not self.settings['n_load_steps'].value == 0: load_step_multiplier = ( i_step + 1.0) / self.settings['n_load_steps'].value else: load_step_multiplier = 1.0 # new storage every load step if i_step > 0: self.increase_ts() for i_iter in range(self.settings['max_iter'].value): cout.cout_wrap('i_step: %u, i_iter: %u' % (i_step, i_iter)) # run aero self.data = self.aero_solver.run() print('Beam last node: ') print( self.data.structure.timestep_info[self.data.ts].pos[20, :]) # map force struct_forces = mapping.aero2struct_force_mapping( self.data.aero.timestep_info[self.data.ts].forces, self.data.aero.struct2aero_mapping, self.data.aero.timestep_info[self.data.ts].zeta, self.data.structure.timestep_info[self.data.ts].pos, self.data.structure.timestep_info[self.data.ts].psi, self.data.structure.node_master_elem, self.data.structure.master, algebra.quat2rot(self.data.structure.timestep_info[ self.data.ts].quat).T) if not self.settings['relaxation_factor'].value == 0.: if i_iter == 0: self.previous_force = struct_forces.copy() temp = struct_forces.copy() struct_forces = ( (1.0 - self.settings['relaxation_factor'].value) * struct_forces + self.settings['relaxation_factor'].value * self.previous_force) self.previous_force = temp # copy force in beam temp1 = load_step_multiplier * struct_forces self.data.structure.timestep_info[ self.data.ts].steady_applied_forces = temp1.astype( dtype=ct.c_double, order='F') # update gravity direction # TODO # run beam self.data = self.structural_solver.run() # update grid self.aero_solver.update_step() # convergence if self.convergence(i_iter, i_step): break # for i_step in range(self.settings['n_load_steps']): # coeff = ct.c_double((i_step + 1.0)/(self.settings['n_load_steps'])) # for i_iter in range(self.settings['max_iter']): # cout.cout_wrap('Iter: %u, step: %u' % (i_iter, i_step), 2) # # self.aero_solver.initialise(self.data, update_flightcon=False, quiet=True) # self.data = self.aero_solver.run() # # struct_forces = mapping.aero2struct_force_mapping( # self.data.grid.timestep_info[self.ts].forces, # self.data.grid.struct2aero_mapping, # self.data.grid.timestep_info[self.ts].zeta, # self.data.beam.timestep_info[self.ts].pos_def, # self.data.beam.timestep_info[self.ts].psi_def, # self.data.beam.node_master_elem, # self.data.beam.master, # self.data.grid.inertial2aero) # # if self.relaxation_factor > 0.0: # struct_forces = ((1.0 - self.relaxation_factor)*struct_forces + # self.relaxation_factor*self.previous_forces) # # self.previous_forces = struct_forces # self.data.beam.update_forces(struct_forces) # self.structural_solver.initialise(self.data) # self.data = self.structural_solver.run(coeff) # # if self.convergence(i_iter): # self.data.flightconditions['FlightCon']['u_inf'] = self.original_u_inf # self.aero_solver.initialise(self.data, quiet=True) # self.data = self.aero_solver.run() # if i_step == self.settings['n_load_steps'] - 1: # cout.cout_wrap('Converged in %u iterations' % (i_iter + 1), 2) # break cout.cout_wrap('...Finished', 1) return self.data
def xbeam_solv_couplednlndyn(beam, settings): n_elem = ct.c_int(beam.num_elem) n_nodes = ct.c_int(beam.num_node) n_mass = ct.c_int(beam.n_mass) n_stiff = ct.c_int(beam.n_stiff) dt = settings['dt'].value n_tsteps = settings['num_steps'].value time = np.zeros((n_tsteps,), dtype=ct.c_double, order='F') for i in range(n_tsteps): time[i] = i*dt # deformation history matrices for_vel = np.zeros((n_tsteps + 1, 6), order='F') for_acc = np.zeros((n_tsteps + 1, 6), order='F') quat_history = np.zeros((n_tsteps, 4), order='F') dt = ct.c_double(dt) n_tsteps = ct.c_int(n_tsteps) xbopts = Xbopts() xbopts.PrintInfo = ct.c_bool(settings['print_info']) xbopts.Solution = ct.c_int(910) xbopts.OutInaframe = ct.c_bool(False) xbopts.MaxIterations = settings['max_iterations'] xbopts.NumLoadSteps = settings['num_load_steps'] # xbopts.NumGauss = ct.c_int(0) xbopts.DeltaCurved = settings['delta_curved'] xbopts.MinDelta = settings['min_delta'] xbopts.NewmarkDamp = settings['newmark_damp'] xbopts.gravity_on = settings['gravity_on'] xbopts.gravity = settings['gravity'] xbopts.gravity_dir_x = ct.c_double(settings['gravity_dir'][0]) xbopts.gravity_dir_y = ct.c_double(settings['gravity_dir'][1]) xbopts.gravity_dir_z = ct.c_double(settings['gravity_dir'][2]) pos_def_history = np.zeros((n_tsteps.value, beam.num_node, 3), order='F', dtype=ct.c_double) pos_dot_def_history = np.zeros((n_tsteps.value, beam.num_node, 3), order='F', dtype=ct.c_double) psi_def_history = np.zeros((n_tsteps.value, beam.num_elem, 3, 3), order='F', dtype=ct.c_double) psi_dot_def_history = np.zeros((n_tsteps.value, beam.num_elem, 3, 3), order='F', dtype=ct.c_double) dynamic_force = np.zeros((n_nodes.value, 6, n_tsteps.value), dtype=ct.c_double, order='F') for it in range(n_tsteps.value): dynamic_force[:, :, it] = beam.dynamic_input[it]['dynamic_forces'] # status flag success = ct.c_bool(True) # here we only need to set the flags at True, all the forces are follower xbopts.FollowerForce = ct.c_bool(True) xbopts.FollowerForceRig = ct.c_bool(True) import time as ti start_time = ti.time() f_xbeam_solv_couplednlndyn(ct.byref(n_elem), ct.byref(n_nodes), ct.byref(n_tsteps), time.ctypes.data_as(doubleP), beam.fortran['num_nodes'].ctypes.data_as(intP), beam.fortran['num_mem'].ctypes.data_as(intP), beam.fortran['connectivities'].ctypes.data_as(intP), beam.fortran['master'].ctypes.data_as(intP), ct.byref(n_mass), beam.fortran['mass'].ctypes.data_as(doubleP), beam.fortran['mass_indices'].ctypes.data_as(intP), ct.byref(n_stiff), beam.fortran['stiffness'].ctypes.data_as(doubleP), beam.fortran['inv_stiffness'].ctypes.data_as(doubleP), beam.fortran['stiffness_indices'].ctypes.data_as(intP), beam.fortran['frame_of_reference_delta'].ctypes.data_as(doubleP), beam.fortran['rbmass'].ctypes.data_as(doubleP), beam.fortran['node_master_elem'].ctypes.data_as(intP), beam.fortran['vdof'].ctypes.data_as(intP), beam.fortran['fdof'].ctypes.data_as(intP), ct.byref(xbopts), beam.ini_info.pos.ctypes.data_as(doubleP), beam.ini_info.psi.ctypes.data_as(doubleP), beam.timestep_info[0].steady_applied_forces.ctypes.data_as(doubleP), dynamic_force.ctypes.data_as(doubleP), for_vel.ctypes.data_as(doubleP), for_acc.ctypes.data_as(doubleP), pos_def_history.ctypes.data_as(doubleP), psi_def_history.ctypes.data_as(doubleP), pos_dot_def_history.ctypes.data_as(doubleP), psi_dot_def_history.ctypes.data_as(doubleP), quat_history.ctypes.data_as(doubleP), ct.byref(success)) cout.cout_wrap("\n--- %s seconds ---" % (ti.time() - start_time), 1) if not success: raise Exception('couplednlndyn did not converge') for_pos = np.zeros_like(for_vel) for_pos[:, 0] = sc.integrate.cumtrapz(for_vel[:, 0], dx=dt.value, initial=0) for_pos[:, 1] = sc.integrate.cumtrapz(for_vel[:, 1], dx=dt.value, initial=0) for_pos[:, 2] = sc.integrate.cumtrapz(for_vel[:, 2], dx=dt.value, initial=0) glob_pos_def = np.zeros_like(pos_def_history) for it in range(n_tsteps.value): rot = algebra.quat2rot(quat_history[it, :]).transpose() for inode in range(beam.num_node): glob_pos_def[it, inode, :] = np.dot(rot.T, pos_def_history[it, inode, :]) for i in range(n_tsteps.value - 1): beam.timestep_info[i + 1].pos[:] = pos_def_history[i+1, :] beam.timestep_info[i + 1].psi[:] = psi_def_history[i+1, :] beam.timestep_info[i + 1].pos_dot[:] = pos_dot_def_history[i+1, :] beam.timestep_info[i + 1].psi_dot[:] = psi_dot_def_history[i+1, :] beam.timestep_info[i + 1].quat[:] = quat_history[i+1, :] beam.timestep_info[i + 1].for_pos[:] = for_pos[i+1, :] beam.timestep_info[i + 1].for_vel[:] = for_vel[i+1, :]
def update_orientation(self, quat, ts=-1): rot = algebra.quat2rot(quat) self.timestep_info[ts].update_orientation(rot)
def cag(self): return algebra.quat2rot(self.quat)
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
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)
def plot_body(self): for i_surf in range(self.data.aero.timestep_info[self.ts].n_surf): filename = (self.body_filename + '_' + '%02u_' % i_surf + '%06u' % self.ts) dims = self.data.aero.timestep_info[self.ts].dimensions[i_surf, :] # dims_star = self.data.aero.timestep_info[self.ts].dimensions_star[i_surf, :] point_data_dim = (dims[0] + 1) * ( dims[1] + 1) # + (dims_star[0]+1)*(dims_star[1]+1) panel_data_dim = (dims[0]) * (dims[1] ) # + (dims_star[0])*(dims_star[1]) coords = np.zeros((point_data_dim, 3)) conn = [] panel_id = np.zeros((panel_data_dim, ), dtype=int) panel_surf_id = np.zeros((panel_data_dim, ), dtype=int) panel_gamma = np.zeros((panel_data_dim, )) normal = np.zeros((panel_data_dim, 3)) point_struct_id = np.zeros((point_data_dim, ), dtype=int) point_cf = np.zeros((point_data_dim, 3)) point_unsteady_cf = np.zeros((point_data_dim, 3)) counter = -1 rotation_mat = algebra.quat2rot( self.data.structure.timestep_info[self.ts].quat).transpose() # coordinates of corners for i_n in range(dims[1] + 1): for i_m in range(dims[0] + 1): counter += 1 coords[counter, :] = self.data.aero.timestep_info[ self.ts].zeta[i_surf][:, i_m, i_n] if self.settings['include_rbm']: coords[counter, :] = np.dot( rotation_mat, self.data.aero.timestep_info[ self.ts].zeta[i_surf][:, i_m, i_n]) coords[ counter, :] += self.data.structure.timestep_info[ self.ts].for_pos[0:3] counter = -1 node_counter = -1 for i_n in range(dims[1] + 1): global_counter = self.data.aero.aero2struct_mapping[i_surf][ i_n] for i_m in range(dims[0] + 1): node_counter += 1 # point data point_struct_id[node_counter] = global_counter point_cf[node_counter, :] = self.data.aero.timestep_info[ self.ts].forces[i_surf][0:3, i_m, i_n] try: point_unsteady_cf[ node_counter, :] = self.data.aero.timestep_info[ self.ts].dynamic_forces[i_surf][0:3, i_m, i_n] except AttributeError: pass if i_n < dims[1] and i_m < dims[0]: counter += 1 else: continue conn.append([ node_counter + 0, node_counter + 1, node_counter + dims[0] + 2, node_counter + dims[0] + 1 ]) # cell data normal[counter, :] = self.data.aero.timestep_info[ self.ts].normals[i_surf][:, i_m, i_n] panel_id[counter] = counter panel_surf_id[counter] = i_surf panel_gamma[counter] = self.data.aero.timestep_info[ self.ts].gamma[i_surf][i_m, i_n] ug = tvtk.UnstructuredGrid(points=coords) ug.set_cells(tvtk.Quad().cell_type, conn) ug.cell_data.scalars = panel_id ug.cell_data.scalars.name = 'panel_n_id' ug.cell_data.add_array(panel_surf_id) ug.cell_data.get_array(1).name = 'panel_surface_id' ug.cell_data.add_array(panel_gamma) ug.cell_data.get_array(2).name = 'panel_gamma' ug.cell_data.vectors = normal ug.cell_data.vectors.name = 'panel_normal' ug.point_data.scalars = np.arange(0, coords.shape[0]) ug.point_data.scalars.name = 'n_id' ug.point_data.add_array(point_struct_id) ug.point_data.get_array(1).name = 'point_struct_id' ug.point_data.add_array(point_cf) ug.point_data.get_array(2).name = 'point_steady_force' ug.point_data.add_array(point_unsteady_cf) ug.point_data.get_array(3).name = 'point_unsteady_force' write_data(ug, filename)
def plot_wake(self): for i_surf in range(self.data.aero.timestep_info[self.ts].n_surf): filename = (self.wake_filename + '_' + '%02u_' % i_surf + '%06u' % self.ts) dims_star = self.data.aero.timestep_info[self.ts].dimensions_star[ i_surf, :] dims_star[0] -= self.settings['minus_m_star'] point_data_dim = (dims_star[0] + 1) * (dims_star[1] + 1) panel_data_dim = (dims_star[0]) * (dims_star[1]) coords = np.zeros((point_data_dim, 3)) conn = [] panel_id = np.zeros((panel_data_dim, ), dtype=int) panel_surf_id = np.zeros((panel_data_dim, ), dtype=int) panel_gamma = np.zeros((panel_data_dim, )) counter = -1 rotation_mat = algebra.quat2rot( self.data.structure.timestep_info[self.ts].quat).transpose() # coordinates of corners for i_n in range(dims_star[1] + 1): for i_m in range(dims_star[0] + 1): counter += 1 coords[counter, :] = self.data.aero.timestep_info[ self.ts].zeta_star[i_surf][:, i_m, i_n] if self.settings['include_rbm']: coords[counter, :] = np.dot(rotation_mat, coords[counter, :]) coords[ counter, :] += self.data.structure.timestep_info[ self.ts].for_pos[0:3] counter = -1 node_counter = -1 # wake for i_n in range(dims_star[1] + 1): for i_m in range(dims_star[0] + 1): node_counter += 1 # cell data if i_n < dims_star[1] and i_m < dims_star[0]: counter += 1 else: continue conn.append([ node_counter + 0, node_counter + 1, node_counter + dims_star[0] + 2, node_counter + dims_star[0] + 1 ]) panel_id[counter] = counter panel_surf_id[counter] = i_surf panel_gamma[counter] = self.data.aero.timestep_info[ self.ts].gamma_star[i_surf][i_m, i_n] ug = tvtk.UnstructuredGrid(points=coords) ug.set_cells(tvtk.Quad().cell_type, conn) ug.cell_data.scalars = panel_id ug.cell_data.scalars.name = 'panel_n_id' ug.cell_data.add_array(panel_surf_id) ug.cell_data.get_array(1).name = 'panel_surface_id' ug.cell_data.add_array(panel_gamma) ug.cell_data.get_array(2).name = 'panel_gamma' ug.point_data.scalars = np.arange(0, coords.shape[0]) ug.point_data.scalars.name = 'n_id' write_data(ug, filename)