def disturb_my_model(imperfection_file_name, nodes_file_name, output_file_name, H_model, H_measured, R_model, R_best_fit=None, semi_angle=0., stretch_H=False, z_offset_bot=None, rotatedeg=0., scaling_factor=1., r_TOL=1., num_closest_points=5, power_parameter=2, num_sec_z=25, sample_size=None): # reading nodes data log('Reading nodes data from {0} ...'.format(nodes_file_name)) nodes = get_nodes_from_txt_file(nodes_file_name) # calling translate_nodes function nodal_translations = calc_nodal_translations( imperfection_file_name, nodes = nodes, H_model = H_model, H_measured = H_measured, R_model = R_model, R_best_fit = R_best_fit, semi_angle = semi_angle, stretch_H = stretch_H, z_offset_bot = z_offset_bot, rotatedeg = rotatedeg, r_TOL = r_TOL, num_closest_points = num_closest_points, power_parameter = power_parameter, num_sec_z = num_sec_z, sample_size=sample_size) # writing output file log('Writing output file "{0}" ...'.format(output_file_name)) outfile = open(output_file_name, 'w') for i, node in enumerate(nodal_translations): original_coords = node[0:3] translations = nodal_translations[k] new_coords = original_coords + translations * scaling_factor outfile.write('{0:d} {1:f} {2:f} {3:f}\n'.format(k, coords[0], coords[1], coords[2])) outfile.close() return True
def disturb_my_model(imperfection_file_name, nodes_file_name, output_file_name, H_model, H_measured, R_model, R_best_fit=None, semi_angle=0., stretch_H=False, z_offset_bot=None, rotatedeg=0., scaling_factor=1., r_TOL=1., num_closest_points=5, power_parameter=2, num_sec_z=25, sample_size=None): # reading nodes data log('Reading nodes data from {0} ...'.format(nodes_file_name)) nodes = get_nodes_from_txt_file(nodes_file_name) # calling translate_nodes function nodal_translations = calc_nodal_translations( imperfection_file_name, nodes=nodes, H_model=H_model, H_measured=H_measured, R_model=R_model, R_best_fit=R_best_fit, semi_angle=semi_angle, stretch_H=stretch_H, z_offset_bot=z_offset_bot, rotatedeg=rotatedeg, r_TOL=r_TOL, num_closest_points=num_closest_points, power_parameter=power_parameter, num_sec_z=num_sec_z, sample_size=sample_size) # writing output file log('Writing output file "{0}" ...'.format(output_file_name)) outfile = open(output_file_name, 'w') for i, node in enumerate(nodal_translations): original_coords = node[0:3] translations = nodal_translations[k] new_coords = original_coords + translations * scaling_factor outfile.write('{0:d} {1:f} {2:f} {3:f}\n'.format( k, coords[0], coords[1], coords[2])) outfile.close() return True
def check_completed(self, wait=False, print_found=False): if not self.rebuilt: self.rebuild() tmp = os.path.join(self.output_dir, self.model_name + '.log') if wait == True: log('Waiting for job completion...') #TODO a general function to check the log file while True: if os.path.isfile(tmp): tmpfile = open(tmp, 'r') lines = tmpfile.readlines() tmpfile.close() if len(lines) == 0: continue if len(lines) < 2: continue if lines[-2].find('End Abaqus/Standard Analysis') > -1: if print_found: log('RUN COMPLETED for model {0}'.format( self.model_name)) return True elif lines[-1].find('Abaqus/Analysis exited with errors') > -1: if print_found: log('RUN COMPLETED WITH ERRORS for model {0}'.format( self.model_name)) return True else: if not wait: warn('RUN NOT COMPLETED for model {0}'.format( self.model_name)) return False else: if not wait: warn('RUN NOT STARTED for model {0}'.format( self.model_name)) return False if wait: import time time.sleep(5)
cc.created_model = False cc.create_model() part_nodes = mdb.models[cc.model_name].parts[cc.part_name_shell].nodes coords = np.array([n.coordinates for n in part_nodes]) sf = 100 path = r'C:\clones\desicos\desicos\conecylDB\files\dlr\degenhardt_2010_z20\degenhardt_2010_z20_msi_theta_z_imp.txt' H_measured = 510. H_model = 510. d, d, data = read_theta_z_imp(path=path, H_measured=H_measured, stretch_H=False, z_offset_bot=None) log('init sample') data = np.array(sample(data, 10000)) log('end sample') data = data[np.argsort(data[:, 0])] data = np.vstack((data[-3000:], data[:], data[:3000])) data[:, 0] /= data[:, 0].max() mesh = np.zeros((coords.shape[0], 2), dtype=FLOAT) mesh[:, 0] = arctan2(coords[:, 1], coords[:, 0]) mesh[:, 1] = coords[:, 2] mesh_norm = mesh.copy() mesh_norm[:, 0] /= mesh_norm[:, 0].max() mesh_norm[:, 1] /= mesh_norm[:, 1].max() import desicos.conecylDB.interpolate reload(desicos.conecylDB.interpolate)
def read_file(file_name, frequency=1, forced_average_radius=None, H_measured=None, R_best_fit=None, stretch_H=False, z_offset_bot=None, r_TOL=1.): log('Reading imperfection file: {0} ...'.format(file_name)) # user warnings if stretch_H: if z_offset_bot: warn('Because of the stretch_H option, ' + 'consider setting z_offset_bot to None') # reading the imperfection file ignore = False mps = np.loadtxt(file_name, dtype=FLOAT) r = np.sqrt(mps[:, 0]**2 + mps[:, 1]**2) # measuring model dimensions if R_best_fit is None: R_best_fit = np.average(r) warn('The cylinder average radius of the measured points ' + 'assumed to be {0:1.2f}'.format(R_best_fit)) z_min = mps[:, 2].min() z_max = mps[:, 2].max() z_center = (z_max + z_min) / 2. H_points = (z_max - z_min) log('R_best_fit : {0}'.format(R_best_fit)) # applying user inputs R = R_best_fit if forced_average_radius: R = forced_average_radius log('Forced measured radius: {0}'.format(forced_average_radius)) H_model = H_points if not H_measured: H_measured = H_points warn('The cylinder height of the measured points assumed ' + 'to be {0:1.2f}'.format(H_measured)) # calculating default z_offset_bot if not z_offset_bot: if stretch_H: z_offset_bot = 0. else: z_offset_bot = (H_measured - H_points) / 2. offset_z = z_offset_bot - z_min log('H_points : {0}'.format(H_points)) log('H_measured : {0}'.format(H_measured)) log('z_min : {0}'.format(z_min)) log('z_max : {0}'.format(z_max)) log('offset_z : {0}'.format(offset_z)) r_TOL_min = (R * (1 - r_TOL / 100.)) r_TOL_max = (R * (1 + r_TOL / 100.)) cond = np.all(np.array((r > r_TOL_max, r < r_TOL_min)), axis=0) skept = mps[cond] log('Skipping {0} points'.format(len(skept))) mps = mps[np.logical_not(cond)] offset_mps = mps.copy() offset_mps[:, 2] += offset_z norm_mps = offset_mps.copy() norm_mps[:, 0] /= R norm_mps[:, 1] /= R if stretch_H: norm_mps[:, 2] /= H_points else: norm_mps[:, 2] /= H_measured return mps, offset_mps, norm_mps
def calc_nodal_translations(imperfection_file_name, nodes, H_model, H_measured, R_model, R_best_fit, semi_angle, stretch_H, z_offset_bot, rotatedeg, r_TOL, num_closest_points, power_parameter, num_sec_z, sample_size): # reading imperfection file m, o, mps = read_file(file_name=imperfection_file_name, H_measured=H_measured, R_best_fit=R_best_fit, forced_average_radius=R_best_fit, stretch_H=stretch_H, z_offset_bot=z_offset_bot, r_TOL=r_TOL) log('Calculating nodal translations!') if sample_size: num = mps.shape[0] if sample_size < num: log('Using sample_size={0}'.format(sample_size), level=1) mps = mps[sample(range(num), int(sample_size)), :] num_nodes = nodes.shape[0] R_top = R_model - np.tan(np.deg2rad(semi_angle)) * H_model semi_angle = abs(semi_angle) def local_radius(z): return R_model + (R_top - R_model) * z / H_model mps[:, 2] *= H_model if semi_angle < 1.e-6: R_local = R_model else: R_local = local_radius(mps[:, 2]) thetarads = np.arctan2(mps[:, 1], mps[:, 0]) if rotatedeg: thetarads += np.deg2rad(rotatedeg) mps[:, 0] = R_local * np.cos(thetarads) mps[:, 1] = R_local * np.sin(thetarads) num_sec_z = int(num_sec_z) mem_limit = 1024 * 1024 * 1024 * 8 * 2 # 2 GB mem_entries = int(mem_limit / 64) # if float64 is used sec_size = int(num_nodes / num_sec_z) #TODO better memory control... if sec_size**2 * 10 > mem_entries: while True: num_sec_z += 1 sec_size = int(num_nodes / num_sec_z) if sec_size**2 * 10 <= mem_entries: warn('New sec_size {0}'.format(sec_size)) break ncp = num_closest_points nodes = nodes[np.argsort(nodes[:, 2])] mps = mps[np.argsort(mps[:, 2])] nodal_t = np.zeros(nodes.shape, dtype=nodes.dtype) limit = int(num_sec_z / 5) for i in xrange(num_sec_z + 1): i_inf = sec_size * i i_sup = sec_size * (i + 1) if i % limit == 0: log('processed {0:7d} out of {1:7d} entries'.format( min(i_sup, num_nodes), num_nodes), level=1) sub_nodes = nodes[i_inf:i_sup] if not np.any(sub_nodes): continue inf_z = sub_nodes[:, 2].min() sup_z = sub_nodes[:, 2].max() tol = 0.01 if i == 0 or i == num_sec_z: tol = 0.05 while True: cond1 = mps[:, 2] >= inf_z - tol * H_model cond2 = mps[:, 2] <= sup_z + tol * H_model cond = np.all(np.array((cond1, cond2)), axis=0) sub_mps = mps[cond] if not np.any(sub_mps): tol += 0.01 else: break dist = np.subtract.outer(sub_nodes[:, 0], sub_mps[:, 0])**2 dist += np.subtract.outer(sub_nodes[:, 1], sub_mps[:, 1])**2 dist += np.subtract.outer(sub_nodes[:, 2], sub_mps[:, 2])**2 asort = np.argsort(dist, axis=1) lenn = sub_nodes.shape[0] lenp = sub_mps.shape[0] asort_mesh = asort + np.meshgrid( np.arange(lenn) * lenp, np.arange(lenp))[0].transpose() # getting the z coordinate of the closest points sub_mps_z = np.take(sub_mps[:, 2], asort[:, :ncp]) # getting the distance of the closest points dist_ncp = np.take(dist, asort_mesh[:, :ncp]) # avoiding division by zero dist_ncp[(dist_ncp == 0)] == 1.e-12 # calculating the radius of the sub-group of measured points radius = np.sqrt(sub_mps[:, 0]**2 + sub_mps[:, 1]**2) # taking only the radius of the closest points radius_ncp = np.take(radius, asort[:, :ncp]) # weight calculation total_weight = np.sum(1. / (dist_ncp**power_parameter), axis=1) weight = 1. / (dist_ncp**power_parameter) # calculating the local radius for the closest points r_local_ncp = local_radius(sub_mps_z) # computing the new radius r_new = np.sum(radius_ncp * weight / r_local_ncp, axis=1) / total_weight r_new *= local_radius(sub_nodes[:, 2]) #NOTE modified after Regina, Mariano and Saullo decided to use # the imperfection amplitude constant along the whole cone # surface, which represents better the real manufacturing # conditions. In that case the amplitude will be re-scaled # using only the bottom radius # calculating the local radius for the nodes for the new assumption r_local_nodes = np.sqrt(sub_nodes[:, 0]**2 + sub_nodes[:, 1]**2) # calculating the scaling factor required for the new assumption sf = R_model / r_local_nodes theta = np.arctan2(sub_nodes[:, 1], sub_nodes[:, 0]) nodal_t[i_inf : i_sup][:, 0] = \ (r_new*np.cos(theta) - sub_nodes[:, 0])*sf nodal_t[i_inf : i_sup][:, 1] = \ (r_new*np.sin(theta) - sub_nodes[:, 1])*sf nodal_t[i_inf:i_sup][:, 3] = sub_nodes[:, 3] nodal_t = nodal_t[np.argsort(nodal_t[:, 3])] log('Nodal translations calculated!') return nodal_t
def translate_nodes_ABAQUS_c0(m0, n0, c0, funcnum, model_name, part_name, H_model, semi_angle=0., scaling_factor=1., fem_meridian_bot2top=True, ignore_bot_h=None, ignore_top_h=None, T=None): r"""Translates the nodes in Abaqus based on a Fourier series The Fourier Series can be a half-sine, half-cosine or a complete Fourier Series as detailed in :func:`desicos.conecylDB.fit_data.calc_c0`. Parameters ---------- m0 : int Number of terms along the `x` coordinate. n0 : int Number of terms along the `\theta` coordinate. c0 : numpy.ndarray The coefficients that will give the imperfection pattern. funcnum : int The function type, as detailed in :func:`desicos.conecylDB.fit_data.calc_c0`. model_name : str Must be a valid key in the dictionary ``mdb.models``, in the interactive Python inside Abaqus. part_name : str Must be a valid key in the dictionary ``mdb.models[model_name].parts``, in the interactive Python inside Abaqus. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. semi_angle : float, optional The cone semi-vertex angle (a null value indicates that a cylinder is beeing analyzed). scaling_factor : float, optional The scaling factor that will multiply ``c0`` when applying the imperfections. fem_meridian_bot2top : bool, optional A boolean indicating if the finite element has the `x` axis starting at the bottom or at the top. ignore_bot_h : None or float, optional Used to ignore nodes from the bottom resin ring. ignore_top_h : None or float, optional Used to ignore nodes from the top resin ring. T : None or np.ndarray, optional A transformation matrix (cf. :func:`.transf_matrix`) required when the mesh is not in the :ref:`default coordinate system <figure_conecyl>`. Returns ------- nodal_translations : numpy.ndarray A 2-D array containing the translations ``x, y, z`` for each column. Notes ----- Despite the nodal traslations are returned all the nodes belonging to this model will be already translated. """ from abaqus import mdb, session from desicos.conecylDB import fit_data log('Calculating imperfection amplitudes for model {0} ...\n\t'.format( model_name) + '(using a scaling factor of {0})'.format(scaling_factor)) c0 = c0 * scaling_factor mod = mdb.models[model_name] part = mod.parts[part_name] part_nodes = np.array(part.nodes) coords = np.array([n.coordinates for n in part_nodes]) if T is not None: tmp = np.vstack((coords.T, np.ones((1, coords.shape[0])))) coords = np.dot(T, tmp).T del tmp if ignore_bot_h is not None: if ignore_bot_h <= 0: ignore_bot_h = None else: log('Applying ignore_bot_h: ignoring nodes with z <= {0}'.format( ignore_bot_h)) mask = coords[:, 2] > ignore_bot_h coords = coords[mask] part_nodes = part_nodes[mask] if ignore_top_h is not None: if ignore_top_h <= 0: ignore_top_h = None else: log('Applying ignore_top_h: ignoring nodes with z >= {0}'.format( H_model - ignore_top_h)) mask = coords[:, 2] < (H_model - ignore_top_h) coords = coords[mask] part_nodes = part_nodes[mask] if ignore_bot_h is None: ignore_bot_h = 0 if ignore_top_h is None: ignore_top_h = 0 H_eff = H_model - (ignore_bot_h + ignore_top_h) if fem_meridian_bot2top: xs_norm = (coords[:, 2] - ignore_bot_h) / H_eff else: xs_norm = (H_eff - (coords[:, 2] - ignore_bot_h)) / H_eff thetas = arctan2(coords[:, 1], coords[:, 0]) alpharad = deg2rad(semi_angle) w0 = fit_data.fw0(m0, n0, c0, xs_norm, thetas, funcnum) nodal_translations = np.zeros_like(coords) nodal_translations[:, 0] = w0 * cos(alpharad) * cos(thetas) nodal_translations[:, 1] = w0 * cos(alpharad) * sin(thetas) nodal_translations[:, 2] = w0 * sin(alpharad) log('Calculation of imperfection amplitudes finished!') # applying translations viewport = session.viewports[session.currentViewportName] log('Applying new nodal positions in ABAQUS CAE to model {0} ...'.format( model_name)) log(' (using a scaling factor of {0})'.format(scaling_factor)) new_coords = coords + nodal_translations if T is not None: Tinv = np.zeros_like(T) Tinv[:3, :3] = T[:3, :3].T Tinv[:, 3] = -T[:, 3] tmp = np.vstack((new_coords.T, np.ones((1, new_coords.shape[0])))) new_coords = np.dot(Tinv, tmp).T del tmp meshNodeArray = part.nodes.sequenceFromLabels( [n.label for n in part_nodes]) new_coords = np.ascontiguousarray(new_coords) part.editNode(nodes=meshNodeArray, coordinates=new_coords) log('Application of new nodal positions finished!') ra = mod.rootAssembly viewport.setValues(displayedObject=ra) ra.regenerate() return nodal_translations
def read_file(file_name, frequency = 1, forced_average_radius = None, H_measured = None, R_best_fit = None, stretch_H = False, z_offset_bot = None, r_TOL = 1.): log('Reading imperfection file: {0} ...'.format(file_name)) # user warnings if stretch_H: if z_offset_bot: warn('Because of the stretch_H option, '+ 'consider setting z_offset_bot to None') # reading the imperfection file ignore = False mps = np.loadtxt(file_name, dtype=FLOAT) r = np.sqrt(mps[:, 0]**2 + mps[:, 1]**2) # measuring model dimensions if R_best_fit is None: R_best_fit = np.average(r) warn('The cylinder average radius of the measured points ' + 'assumed to be {0:1.2f}'.format(R_best_fit)) z_min = mps[:, 2].min() z_max = mps[:, 2].max() z_center = (z_max + z_min)/2. H_points = (z_max - z_min) log('R_best_fit : {0}'.format(R_best_fit)) # applying user inputs R = R_best_fit if forced_average_radius: R = forced_average_radius log('Forced measured radius: {0}'.format(forced_average_radius)) H_model = H_points if not H_measured: H_measured = H_points warn('The cylinder height of the measured points assumed ' + 'to be {0:1.2f}'.format(H_measured)) # calculating default z_offset_bot if not z_offset_bot: if stretch_H: z_offset_bot = 0. else: z_offset_bot = (H_measured - H_points) / 2. offset_z = z_offset_bot - z_min log('H_points : {0}'.format(H_points)) log('H_measured : {0}'.format(H_measured)) log('z_min : {0}'.format(z_min)) log('z_max : {0}'.format(z_max)) log('offset_z : {0}'.format(offset_z)) r_TOL_min = (R * (1-r_TOL/100.)) r_TOL_max = (R * (1+r_TOL/100.)) cond = np.all(np.array((r > r_TOL_max, r < r_TOL_min)), axis=0) skept = mps[cond] log('Skipping {0} points'.format(len(skept))) mps = mps[np.logical_not(cond)] offset_mps = mps.copy() offset_mps[:, 2] += offset_z norm_mps = offset_mps.copy() norm_mps[:, 0] /= R norm_mps[:, 1] /= R if stretch_H: norm_mps[:, 2] /= H_points else: norm_mps[:, 2] /= H_measured return mps, offset_mps, norm_mps
def calc_nodal_translations(imperfection_file_name, nodes, H_model, H_measured, R_model, R_best_fit, semi_angle, stretch_H, z_offset_bot, rotatedeg, r_TOL, num_closest_points, power_parameter, num_sec_z, sample_size): # reading imperfection file m, o, mps = read_file(file_name = imperfection_file_name, H_measured = H_measured, R_best_fit = R_best_fit, forced_average_radius = R_best_fit, stretch_H = stretch_H, z_offset_bot = z_offset_bot, r_TOL = r_TOL) log('Calculating nodal translations!') if sample_size: num = mps.shape[0] if sample_size < num: log('Using sample_size={0}'.format(sample_size), level=1) mps = mps[sample(range(num), int(sample_size)), :] num_nodes = nodes.shape[0] R_top = R_model - np.tan(np.deg2rad(semi_angle)) * H_model semi_angle = abs(semi_angle) def local_radius(z): return R_model + (R_top - R_model) * z / H_model mps[:, 2] *= H_model if semi_angle < 1.e-6: R_local = R_model else: R_local = local_radius(mps[:, 2]) thetarads = np.arctan2(mps[:, 1], mps[:, 0]) if rotatedeg: thetarads += np.deg2rad(rotatedeg) mps[:, 0] = R_local*np.cos(thetarads) mps[:, 1] = R_local*np.sin(thetarads) num_sec_z = int(num_sec_z) mem_limit = 1024*1024*1024*8*2 # 2 GB mem_entries = int(mem_limit / 64) # if float64 is used sec_size = int(num_nodes/num_sec_z) #TODO better memory control... if sec_size**2*10 > mem_entries: while True: num_sec_z +=1 sec_size = int(num_nodes/num_sec_z) if sec_size**2*10 <= mem_entries: warn('New sec_size {0}'.format(sec_size)) break ncp = num_closest_points nodes = nodes[np.argsort(nodes[:, 2])] mps = mps[np.argsort(mps[:, 2])] nodal_t = np.zeros(nodes.shape, dtype=nodes.dtype) limit = int(num_sec_z/5) for i in xrange(num_sec_z+1): i_inf = sec_size*i i_sup = sec_size*(i+1) if i % limit == 0: log('processed {0:7d} out of {1:7d} entries'.format( min(i_sup, num_nodes), num_nodes), level=1) sub_nodes = nodes[i_inf : i_sup] if not np.any(sub_nodes): continue inf_z = sub_nodes[:, 2].min() sup_z = sub_nodes[:, 2].max() tol = 0.01 if i == 0 or i == num_sec_z: tol = 0.05 while True: cond1 = mps[:, 2] >= inf_z - tol*H_model cond2 = mps[:, 2] <= sup_z + tol*H_model cond = np.all(np.array((cond1, cond2)), axis=0) sub_mps = mps[cond] if not np.any(sub_mps): tol += 0.01 else: break dist = np.subtract.outer(sub_nodes[:, 0], sub_mps[:, 0])**2 dist += np.subtract.outer(sub_nodes[:, 1], sub_mps[:, 1])**2 dist += np.subtract.outer(sub_nodes[:, 2], sub_mps[:, 2])**2 asort = np.argsort(dist, axis=1) lenn = sub_nodes.shape[0] lenp = sub_mps.shape[0] asort_mesh = asort + np.meshgrid(np.arange(lenn)*lenp, np.arange(lenp))[0].transpose() # getting the z coordinate of the closest points sub_mps_z = np.take(sub_mps[:, 2], asort[:, :ncp]) # getting the distance of the closest points dist_ncp = np.take(dist, asort_mesh[:, :ncp]) # avoiding division by zero dist_ncp[(dist_ncp==0)] == 1.e-12 # calculating the radius of the sub-group of measured points radius = np.sqrt(sub_mps[:, 0]**2 + sub_mps[:, 1]**2) # taking only the radius of the closest points radius_ncp = np.take(radius, asort[:, :ncp]) # weight calculation total_weight = np.sum(1./(dist_ncp**power_parameter), axis=1) weight = 1./(dist_ncp**power_parameter) # calculating the local radius for the closest points r_local_ncp = local_radius(sub_mps_z) # computing the new radius r_new = np.sum(radius_ncp*weight/r_local_ncp, axis=1)/total_weight r_new *= local_radius(sub_nodes[:, 2]) #NOTE modified after Regina, Mariano and Saullo decided to use # the imperfection amplitude constant along the whole cone # surface, which represents better the real manufacturing # conditions. In that case the amplitude will be re-scaled # using only the bottom radius # calculating the local radius for the nodes for the new assumption r_local_nodes = np.sqrt(sub_nodes[:,0]**2 + sub_nodes[:, 1]**2) # calculating the scaling factor required for the new assumption sf = R_model/r_local_nodes theta = np.arctan2(sub_nodes[:, 1], sub_nodes[:, 0]) nodal_t[i_inf : i_sup][:, 0] = \ (r_new*np.cos(theta) - sub_nodes[:, 0])*sf nodal_t[i_inf : i_sup][:, 1] = \ (r_new*np.sin(theta) - sub_nodes[:, 1])*sf nodal_t[i_inf : i_sup][:, 3] = sub_nodes[:, 3] nodal_t = nodal_t[np.argsort(nodal_t[:, 3])] log('Nodal translations calculated!') return nodal_t
def change_thickness_ABAQUS(imperfection_file_name, model_name, part_name, stack, t_model, t_measured, H_model, H_measured, R_model, R_best_fit = None, number_of_sets = None, semi_angle = 0., stretch_H = False, z_offset_bot = None, scaling_factor = 1., num_closest_points = 5, power_parameter = 2, num_sec_z = 100, elems_t = None, t_set = None, use_theta_z_format = False): r"""Applies a given thickness imperfection to the finite element model Assumes that a percentage variation of the laminate thickness can be represented by the same percentage veriation of each ply, i.e., each ply thickness is varied in order to reflect a given measured thickness imperfection field. Parameters ---------- imperfection_file_name : str Full path to the imperfection file. model_name : str Model name. part_name : str Part name. stack : list The stacking sequence of the current model with each angle given in degrees. t_model : float The nominal shell thickness of the current model. t_measured : float The nominal thickness of the measured specimen. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. H_measured : float The total height of the measured test specimen, including eventual resin rings at the edges. R_model : float Radius **at the bottom edge** of the model where the imperfections will be applied to. R_best_fit : float, optional Best fit radius obtained with functions :func:`.best_fit_cylinder` or :func:`.best_fit_cone`. number_of_sets : int, optional Defines in how many levels the thicknesses should be divided. If ``None`` it will be based on the input file, and if the threshold of ``100`` is exceeded, ``10`` sections are used. semi_angle : float, optional Cone semi-vertex angle in degrees, when applicable. stretch_H : bool, optional If the measured imperfection data should be stretched to the current model (which may happen when ``H_model!=H_measured``. z_offset_bot : float, optional It is common to have the measured data not covering the whole test specimen, and therefore it will be centralized, if a non-centralized position is desired this parameter can be used for the adjustment. scaling_factor : float, optional A scaling factor that can be used to study the imperfection sensitivity. num_closest_points : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. power_parameter : float, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. num_sec_z : int, optional Number of spatial sections used to classify the measured data in order to accelerate the searching algorithms elems_t : np.ndarray, optional Interpolated thickness for each element. Can be used to avoid the same interpolation to be performed twice. t_set : set, optional A ``set`` object containing the unique thicknesses that will be used to create the new properties. use_theta_z_format : bool, optional If the new format `\theta, Z, imp` should be used instead of the old `X, Y, Z`. """ from abaqus import mdb import desicos.abaqus.abaqus_functions as abaqus_functions mod = mdb.models[model_name] part = mod.parts[part_name] part_cyl_csys = part.features['part_cyl_csys'] part_cyl_csys = part.datums[part_cyl_csys.id] if use_theta_z_format: if elems_t is None or t_set is None: log('Reading coordinates for elements...') elements = vec_calc_elem_cg(part.elements) log('Coordinates for elements read!') d, d, data = read_theta_z_imp(path = imperfection_file_name, H_measured = H_measured, stretch_H = stretch_H, z_offset_bot = z_offset_bot) data3D = np.zeros((data.shape[0], 4), dtype=FLOAT) z = data[:, 1] z *= H_model alpharad = deg2rad(semi_angle) tana = tan(alpharad) def r_local(z): return R_model - z*tana data3D[:, 0] = r_local(z)*cos(data[:, 0]) data3D[:, 1] = r_local(z)*sin(data[:, 0]) data3D[:, 2] = z data3D[:, 3] = data[:, 2] ans = inv_weighted(data3D, elements[:, :3], num_sub = num_sec_z, col = 2, ncp = num_closest_points, power_parameter = power_parameter) t_set = set(ans) t_set.discard(0.) #TODO why inv_weighted returns an array with 0. elems_t = np.zeros((elements.shape[0], 2), dtype=FLOAT) elems_t[:, 0] = elements[:, 3] elems_t[:, 1] = ans else: log('Thickness differences already calculated!') else: if elems_t is None or t_set is None: # reading elements data log('Reading coordinates for elements...') elements = vec_calc_elem_cg(part.elements) log('Coordinates for elements read!') # calling translate_nodes function elems_t, t_set = calc_elems_t( imperfection_file_name, nodes = elements, t_model = t_model, t_measured = t_measured, H_model = H_model, H_measured = H_measured, R_model = R_model, R_best_fit = R_best_fit, semi_angle = semi_angle, stretch_H = stretch_H, z_offset_bot = z_offset_bot, num_closest_points = num_closest_points, power_parameter = power_parameter, num_sec_z = num_sec_z) else: log('Thickness differences already calculated!') # creating sets t_list = [] max_len_t_set = 100 if len(t_set) >= max_len_t_set and number_of_sets in (None, 0): number_of_sets = 10 log('More than {0:d} different thicknesses measured!'.format( max_len_t_set)) log('Forcing a number_of_sets = {0:d}'.format(number_of_sets)) if number_of_sets is None or number_of_sets == 0: number_of_sets = len(t_set) t_list = list(t_set) t_list.sort() else: t_min = min(t_set) t_max = max(t_set) t_list = list(np.linspace(t_min, t_max, number_of_sets+1)) # grouping elements sets_ids = [[] for i in range(len(t_list))] for entry in elems_t: elem_id, t = entry index = index_within_linspace(t_list, t) sets_ids[index].append(int(elem_id)) # putting elements in sets original_layup = part.compositeLayups['CompositePlate'] for i, set_ids in enumerate(sets_ids): if len(set_ids) == 0: # since t_set_norm * t_model <> t_set originally measured # there may be empty set_ids at the end continue elements = part.elements.sequenceFromLabels(labels=set_ids) suffix = 'measured_imp_t_{0:03d}'.format(i) set_name = 'Set_' + suffix log('Creating set ({0: 7d} elements): {1}'.format( len(set_ids), set_name)) part.Set(name = set_name, elements = elements) region = part.sets[set_name] layup_name = 'CLayup_' + suffix t_diff = (float(t_list[i]) - t_model) * scaling_factor t_scaling_factor = (t_model + t_diff)/t_model def modify_ply(index, kwargs): kwargs['thickness'] *= t_scaling_factor kwargs['region'] = region return kwargs layup = part.CompositeLayup(name=layup_name, objectToCopy=original_layup) layup.resume() abaqus_functions.modify_composite_layup(part=part, layup_name=layup_name, modify_func=modify_ply) # suppress needed to put the new properties to the input file original_layup.suppress() return elems_t, t_set
def translate_nodes_ABAQUS_c0(m0, n0, c0, funcnum, model_name, part_name, H_model, semi_angle=0., scaling_factor=1., fem_meridian_bot2top=True, ignore_bot_h=None, ignore_top_h=None, T=None): r"""Translates the nodes in Abaqus based on a Fourier series The Fourier Series can be a half-sine, half-cosine or a complete Fourier Series as detailed in :func:`desicos.conecylDB.fit_data.calc_c0`. Parameters ---------- m0 : int Number of terms along the `x` coordinate. n0 : int Number of terms along the `\theta` coordinate. c0 : numpy.ndarray The coefficients that will give the imperfection pattern. funcnum : int The function type, as detailed in :func:`desicos.conecylDB.fit_data.calc_c0`. model_name : str Must be a valid key in the dictionary ``mdb.models``, in the interactive Python inside Abaqus. part_name : str Must be a valid key in the dictionary ``mdb.models[model_name].parts``, in the interactive Python inside Abaqus. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. semi_angle : float, optional The cone semi-vertex angle (a null value indicates that a cylinder is beeing analyzed). scaling_factor : float, optional The scaling factor that will multiply ``c0`` when applying the imperfections. fem_meridian_bot2top : bool, optional A boolean indicating if the finite element has the `x` axis starting at the bottom or at the top. ignore_bot_h : None or float, optional Used to ignore nodes from the bottom resin ring. ignore_top_h : None or float, optional Used to ignore nodes from the top resin ring. T : None or np.ndarray, optional A transformation matrix (cf. :func:`.transf_matrix`) required when the mesh is not in the :ref:`default coordinate system <figure_conecyl>`. Returns ------- nodal_translations : numpy.ndarray A 2-D array containing the translations ``x, y, z`` for each column. Notes ----- Despite the nodal traslations are returned all the nodes belonging to this model will be already translated. """ from abaqus import mdb, session from desicos.conecylDB import fit_data log('Calculating imperfection amplitudes for model {0} ...\n\t'. format(model_name) + '(using a scaling factor of {0})'.format(scaling_factor)) c0 = c0*scaling_factor mod = mdb.models[model_name] part = mod.parts[part_name] part_nodes = np.array(part.nodes) coords = np.array([n.coordinates for n in part_nodes]) if T is not None: tmp = np.vstack((coords.T, np.ones((1, coords.shape[0])))) coords = np.dot(T, tmp).T del tmp if ignore_bot_h is not None: if ignore_bot_h <= 0: ignore_bot_h = None else: log('Applying ignore_bot_h: ignoring nodes with z <= {0}'.format( ignore_bot_h)) mask = coords[:, 2] > ignore_bot_h coords = coords[mask] part_nodes = part_nodes[mask] if ignore_top_h is not None: if ignore_top_h <= 0: ignore_top_h = None else: log('Applying ignore_top_h: ignoring nodes with z >= {0}'.format( H_model - ignore_top_h)) mask = coords[:, 2] < (H_model - ignore_top_h) coords = coords[mask] part_nodes = part_nodes[mask] if ignore_bot_h is None: ignore_bot_h = 0 if ignore_top_h is None: ignore_top_h = 0 H_eff = H_model - (ignore_bot_h + ignore_top_h) if fem_meridian_bot2top: xs_norm = (coords[:, 2]-ignore_bot_h)/H_eff else: xs_norm = (H_eff-(coords[:, 2]-ignore_bot_h))/H_eff thetas = arctan2(coords[:, 1], coords[:, 0]) alpharad = deg2rad(semi_angle) w0 = fit_data.fw0(m0, n0, c0, xs_norm, thetas, funcnum) nodal_translations = np.zeros_like(coords) nodal_translations[:, 0] = w0*cos(alpharad)*cos(thetas) nodal_translations[:, 1] = w0*cos(alpharad)*sin(thetas) nodal_translations[:, 2] = w0*sin(alpharad) log('Calculation of imperfection amplitudes finished!') # applying translations viewport = session.viewports[session.currentViewportName] log('Applying new nodal positions in ABAQUS CAE to model {0} ...'. format(model_name)) log(' (using a scaling factor of {0})'.format(scaling_factor)) new_coords = coords + nodal_translations if T is not None: Tinv = np.zeros_like(T) Tinv[:3, :3] = T[:3, :3].T Tinv[:, 3] = -T[:, 3] tmp = np.vstack((new_coords.T, np.ones((1, new_coords.shape[0])))) new_coords = np.dot(Tinv, tmp).T del tmp meshNodeArray = part.nodes.sequenceFromLabels( [n.label for n in part_nodes]) new_coords = np.ascontiguousarray(new_coords) part.editNode(nodes=meshNodeArray, coordinates=new_coords) log('Application of new nodal positions finished!') ra = mod.rootAssembly viewport.setValues(displayedObject=ra) ra.regenerate() return nodal_translations
def calc_translations_ABAQUS(imperfection_file_name, model_name, part_name, H_model, H_measured, R_model, R_best_fit=None, semi_angle=0., stretch_H=False, z_offset_bot=None, rotatedeg=0., scaling_factor=1., r_TOL=1., num_closest_points=5, power_parameter=2, num_sec_z=50, use_theta_z_format=True, ignore_bot_h=None, ignore_top_h=None, sample_size=None, T=None): r"""Reads an imperfection file and calculates the nodal translations Parameters ---------- imperfection_file_name : str Full path to the imperfection file. model_name : str Model name. part_name : str Part name. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. H_measured : float The total height of the measured test specimen, including eventual resin rings at the edges. R_model : float Radius **at the bottom edge** of the model where the imperfections will be applied to. R_best_fit : float, optional Best fit radius obtained with functions :func:`.best_fit_cylinder` or :func:`.best_fit_cone`. semi_angle : float, optional Cone semi-vertex angle in degrees, when applicable. stretch_H : bool, optional If the measured imperfection data should be stretched to the current model (which may happen when ``H_model!=H_measured``. z_offset_bot : float, optional It is common to have the measured data not covering the whole test specimen, and therefore it will be centralized, if a non-centralized position is desired this parameter can be used for the adjustment. rotatedeg : float, optional Rotation angle in degrees telling how much the imperfection pattern should be rotated about the `X_3` (or `Z`) axis. scaling_factor : float, optional A scaling factor that can be used to study the imperfection sensitivity. r_TOL : float, optional Percentage tolerance to ignore noisy data from the measurements. num_closest_points : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. power_parameter : float, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. num_sec_z : int, optional Number of spatial sections used to classify the measured data in order to accelerate the searching algorithms use_theta_z_format : bool, optional If the new format `\theta, Z, imp` should be used instead of the old `X, Y, Z`. ignore_bot_h : None or float, optional Used to ignore nodes from the bottom resin ring. ignore_top_h : None or float, optional Used to ignore nodes from the top resin ring. sample_size : int, optional If the input file containing the measured data is too large it may be required to limit the sample size in order to avoid memory errors. T : None or np.ndarray, optional A transformation matrix (cf. :func:`.transf_matrix`) required when the mesh is not in the :ref:`default coordinate system <figure_conecyl>`. """ import abaqus import desicos.abaqus.abaqus_functions as abaqus_functions mod = abaqus.mdb.models[model_name] part = mod.parts[part_name] part_nodes = np.array(part.nodes) coords = np.array([n.coordinates for n in part_nodes], dtype=FLOAT) if T is not None: tmp = np.vstack((coords.T, np.ones((1, coords.shape[0])))) coords = np.dot(T, tmp).T del tmp if ignore_bot_h is not None: if ignore_bot_h <= 0: ignore_bot_h = None else: mask = coords[:, 2] > ignore_bot_h coords = coords[mask] part_nodes = part_nodes[mask] if ignore_top_h is not None: if ignore_top_h <= 0: ignore_top_h = None else: mask = coords[:, 2] < (H_model - ignore_top_h) coords = coords[mask] part_nodes = part_nodes[mask] if use_theta_z_format: d, d, data = read_theta_z_imp(path=imperfection_file_name, H_measured=H_measured, stretch_H=stretch_H, z_offset_bot=z_offset_bot) if sample_size: num = data.shape[0] if sample_size < num: log('Using sample_size={0}'.format(sample_size), level=1) data = data[sample(range(num), int(sample_size)), :] if r_TOL: max_imp = R_model * r_TOL / 100. imp = data[:, 2] cond = np.any(np.array((imp > max_imp, imp < (-max_imp))), axis=0) log('Skipping {0} points'.format(len(imp[cond]))) data = data[np.logical_not(cond), :] data3D = np.zeros((data.shape[0], 4), dtype=FLOAT) if rotatedeg: data[:, 0] += deg2rad(rotatedeg) z = data[:, 1] z *= H_model alpharad = deg2rad(semi_angle) tana = tan(alpharad) def r_local(z): return R_model - z*tana data3D[:, 0] = r_local(z)*cos(data[:, 0]) data3D[:, 1] = r_local(z)*sin(data[:, 0]) data3D[:, 2] = z data3D[:, 3] = data[:, 2] w0 = inv_weighted(data3D, coords, num_sub = num_sec_z, col = 2, ncp = num_closest_points, power_parameter = power_parameter) thetas = arctan2(coords[:, 1], coords[:, 0]) trans = np.zeros_like(coords) trans[:, 0] = w0*cos(alpharad)*cos(thetas) trans[:, 1] = w0*cos(alpharad)*sin(thetas) trans[:, 2] = w0*sin(alpharad) else: #NOTE perhaps remove this in the future, when the imperfection files # are stored as theta, z, amplitude only nodes = np.array([[n.coordinates[0], n.coordinates[1], n.coordinates[2], n.label] for n in part_nodes], dtype=FLOAT) # calling translate_nodes function trans = calc_nodal_translations( imperfection_file_name, nodes = nodes, H_model = H_model, H_measured = H_measured, R_model = R_model, R_best_fit = R_best_fit, semi_angle = semi_angle, stretch_H = stretch_H, z_offset_bot = z_offset_bot, rotatedeg = rotatedeg, r_TOL = r_TOL, num_closest_points = num_closest_points, power_parameter = power_parameter, num_sec_z = num_sec_z, sample_size = sample_size) trans = trans[:, :3] return trans
def translate_nodes_ABAQUS(imperfection_file_name, model_name, part_name, H_model, H_measured, R_model, R_best_fit=None, semi_angle=0., stretch_H=False, z_offset_bot=None, rotatedeg=0., scaling_factor=1., r_TOL=1., num_closest_points=5, power_parameter=2, num_sec_z=50, nodal_translations=None, use_theta_z_format=False, ignore_bot_h=None, ignore_top_h=None, sample_size=None, T=None): r"""Translates the nodes in Abaqus based on imperfection data The imperfection amplitude for each node is calculated using an inversed weight function (see :func:`desicos.conecylDB.interpolate.inv_weighted`). Parameters ---------- imperfection_file_name : str The full path to the imperfection file, which must be a file with three columns containing the ``x, y, z`` coordinates when ``use_theta_z_format=False`` or containing ``x, theta, amplitude`` when ``use_theta_z_format=True``. model_name : str Must be a valid key in the dictionary ``mdb.models``, in the interactive Python inside Abaqus. part_name : str Must be a valid key in the dictionary ``mdb.models[model_name].parts``, in the interactive Python inside Abaqus. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. H_measured : float The total height of the measured test specimen, including eventual resin rings at the edges. R_model : float The radius of the current model. In case of cones this should be the bottom radius. R_best_fit : float, optional Best fit radius obtained with functions :func:`.best_fit_cylinder` or :func:`.best_fit_cone`. semi_angle : float, optional The cone semi-vertex angle (a null value indicates that a cylinder is beeing analyzed). stretch_H : float, optional A boolean indicating if the imperfection pattern should be stretched when applied to the model. The measurement systems usually cannot obtain data for the whole surface, making it an option to stretch the data to fit the whole surface. In case ``stretch_H=False`` the measured data of the extremities will be extruded up to the end of the domain. z_offset_bot : float, optional This parameter allows the analyst to adjust the height of the measured data about the model, when the measured data is not available for the whole domain. rotatedeg : float, optional Rotation angle in degrees telling how much the imperfection pattern should be rotated about the `X_3` (or `Z`) axis. scaling_factor : float, optional The scaling factor that will multiply the calculated imperfection amplitude. r_TOL : float, optional Parameter to ignore noisy data in the imperfection file, the points with a radius higher than `r=r_{model} \times (1 + r_{TOL})` will not be considered in the interpolation. num_closest_points : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. power_parameter : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. num_sec_z : int, optional Number of cross sections that will be used to classify the points spatially in the inverse-weighted algorithm. nodal_translations : None or numpy.ndarray, optional An array containing the interpolated traslations, which is passed to avoid repeated calls to the interpolation functions. use_theta_z_format : bool, optional A boolean to indicate whether the imperfection file contains ``x, y, z`` positions or ``theta, z, amplitude``. ignore_bot_h : None or float, optional Used to ignore nodes from the bottom resin ring. ignore_top_h : None or float, optional Used to ignore nodes from the top resin ring. sample_size : int, optional If the input file containing the measured data is too large it may be required to limit the sample size in order to avoid memory errors. T : None or np.ndarray, optional A transformation matrix (cf. :func:`.transf_matrix`) required when the mesh is not in the :ref:`default coordinate system <figure_conecyl>`. Returns ------- nodal_translations : numpy.ndarray A 2-D array containing the translations ``x, y, z`` for each column. Notes ----- Despite the nodal traslations are returned all the nodes belonging to this model will already be translated. """ from abaqus import mdb, session mod = mdb.models[model_name] part = mod.parts[part_name] part_nodes = np.array(part.nodes) coords = np.array([n.coordinates for n in part_nodes]) if T is not None: tmp = np.vstack((coords.T, np.ones((1, coords.shape[0])))) coords = np.dot(T, tmp).T del tmp if ignore_bot_h is not None: if ignore_bot_h <= 0: ignore_bot_h = None else: log('Applying ignore_bot_h: ignoring nodes with z <= {0}'.format( ignore_bot_h)) mask = coords[:, 2] > ignore_bot_h coords = coords[mask] part_nodes = part_nodes[mask] if ignore_top_h is not None: if ignore_top_h <= 0: ignore_top_h = None else: log('Applying ignore_top_h: ignoring nodes with z >= {0}'.format( H_model - ignore_top_h)) mask = coords[:, 2] < (H_model - ignore_top_h) coords = coords[mask] part_nodes = part_nodes[mask] if use_theta_z_format: if nodal_translations is None: trans = calc_translations_ABAQUS( imperfection_file_name = imperfection_file_name, model_name = model_name, part_name = part_name, H_model = H_model, H_measured = H_measured, R_model = R_model, R_best_fit = R_best_fit, semi_angle = semi_angle, stretch_H = stretch_H, z_offset_bot = z_offset_bot, rotatedeg = rotatedeg, scaling_factor = scaling_factor, r_TOL = r_TOL, num_closest_points = num_closest_points, power_parameter = power_parameter, num_sec_z = num_sec_z, use_theta_z_format = use_theta_z_format, ignore_bot_h = ignore_bot_h, ignore_top_h = ignore_top_h, sample_size = sample_size, T = T) else: trans = nodal_translations # applying translations viewport = session.viewports[session.currentViewportName] log('Applying new nodal positions in ABAQUS CAE to model {0} ...'. format(model_name)) log(' (using a scaling factor of {0})'.format(scaling_factor)) new_coords = coords + trans*scaling_factor if T is not None: Tinv = np.zeros_like(T) Tinv[:3, :3] = T[:3, :3].T Tinv[:, 3] = -T[:, 3] tmp = np.vstack((new_coords.T, np.ones((1, new_coords.shape[0])))) new_coords = np.dot(Tinv, tmp).T del tmp meshNodeArray = part.nodes.sequenceFromLabels( [n.label for n in part_nodes]) new_coords = np.ascontiguousarray(new_coords) part.editNode(nodes=part_nodes.tolist(), coordinates=new_coords) log('Application of new nodal positions finished!') ra = mod.rootAssembly viewport.setValues(displayedObject=ra) ra.regenerate() return trans else: nodes = np.array([[n.coordinates[0], n.coordinates[1], n.coordinates[2], n.label] for n in part_nodes], dtype=FLOAT) # calling translate_nodes function if nodal_translations is None: nodal_translations = calc_translations_ABAQUS( imperfection_file_name = imperfection_file_name, model_name = model_name, part_name = part_name, H_model = H_model, H_measured = H_measured, R_model = R_model, R_best_fit = R_best_fit, semi_angle = semi_angle, stretch_H = stretch_H, z_offset_bot = z_offset_bot, rotatedeg = rotatedeg, scaling_factor = scaling_factor, r_TOL = r_TOL, num_closest_points = num_closest_points, power_parameter = power_parameter, num_sec_z = num_sec_z, use_theta_z_format = use_theta_z_format, ignore_bot_h = ignore_bot_h, ignore_top_h = ignore_top_h, sample_size = sample_size, T = T) # applying translations viewport = session.viewports[session.currentViewportName] log('Applying new nodal positions in ABAQUS CAE for model {0} ...'. format(model_name)) log(' (using a scaling factor of {0})'.format(scaling_factor)) trans = nodal_translations new_coords = coords + trans*scaling_factor if T is not None: Tinv = np.zeros_like(T) Tinv[:3, :3] = T[:3, :3].T Tinv[:, 3] = -T[:, 3] tmp = np.vstack((new_coords.T, np.ones((1, new_coords.shape[0])))) new_coords = np.dot(Tinv, tmp).T del tmp meshNodeArray = part.nodes.sequenceFromLabels( [n.label for n in part_nodes]) new_coords = np.ascontiguousarray(new_coords) part.editNode(nodes=meshNodeArray, coordinates=new_coords) log('Application of new nodal positions finished!') # regenerating ra ra = mod.rootAssembly viewport.setValues(displayedObject=ra) ra.regenerate() return nodal_translations
cc.created_model = False cc.create_model() part_nodes = mdb.models[cc.model_name].parts[cc.part_name_shell].nodes coords = np.array([n.coordinates for n in part_nodes]) sf = 100 path = r'C:\clones\desicos\desicos\conecylDB\files\dlr\degenhardt_2010_z20\degenhardt_2010_z20_msi_theta_z_imp.txt' H_measured = 510. H_model = 510. d, d, data = read_theta_z_imp(path=path, H_measured=H_measured, stretch_H=False, z_offset_bot=None) log('init sample') data = np.array(sample(data, 10000)) log('end sample') data = data[np.argsort(data[:, 0])] data = np.vstack((data[-3000:], data[:], data[:3000])) data[:, 0] /= data[:, 0].max() mesh = np.zeros((coords.shape[0], 2), dtype=FLOAT) mesh[:, 0] = arctan2(coords[:, 1], coords[:, 0]) mesh[:, 1] = coords[:, 2] mesh_norm = mesh.copy() mesh_norm[:, 0] /= mesh_norm[:, 0].max() mesh_norm[:, 1] /= mesh_norm[:, 1].max() import desicos.conecylDB.interpolate
def translate_nodes_ABAQUS(imperfection_file_name, model_name, part_name, H_model, H_measured, R_model, R_best_fit=None, semi_angle=0., stretch_H=False, z_offset_bot=None, rotatedeg=0., scaling_factor=1., r_TOL=1., num_closest_points=5, power_parameter=2, nodal_translations=None, use_theta_z_format=False, ignore_bot_h=None, ignore_top_h=None, sample_size=None, T=None): r"""Translates the nodes in Abaqus based on imperfection data The imperfection amplitude for each node is calculated using an inversed weight function (see :func:`desicos.conecylDB.interpolate.inv_weighted`). Parameters ---------- imperfection_file_name : str The full path to the imperfection file, which must be a file with three columns containing the ``x, y, z`` coordinates when ``use_theta_z_format=False`` or containing ``x, theta, amplitude`` when ``use_theta_z_format=True``. model_name : str Must be a valid key in the dictionary ``mdb.models``, in the interactive Python inside Abaqus. part_name : str Must be a valid key in the dictionary ``mdb.models[model_name].parts``, in the interactive Python inside Abaqus. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. H_measured : float The total height of the measured test specimen, including eventual resin rings at the edges. R_model : float The radius of the current model. In case of cones this should be the bottom radius. R_best_fit : float, optional Best fit radius obtained with functions :func:`.best_fit_cylinder` or :func:`.best_fit_cone`. semi_angle : float, optional The cone semi-vertex angle (a null value indicates that a cylinder is beeing analyzed). stretch_H : float, optional A boolean indicating if the imperfection pattern should be stretched when applied to the model. The measurement systems usually cannot obtain data for the whole surface, making it an option to stretch the data to fit the whole surface. In case ``stretch_H=False`` the measured data of the extremities will be extruded up to the end of the domain. z_offset_bot : float, optional This parameter allows the analyst to adjust the height of the measured data about the model, when the measured data is not available for the whole domain. rotatedeg : float, optional Rotation angle in degrees telling how much the imperfection pattern should be rotated about the `X_3` (or `Z`) axis. scaling_factor : float, optional The scaling factor that will multiply the calculated imperfection amplitude. r_TOL : float, optional Parameter to ignore noisy data in the imperfection file, the points with a radius higher than `r=r_{model} \times (1 + r_{TOL})` will not be considered in the interpolation. num_closest_points : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. power_parameter : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. nodal_translations : None or numpy.ndarray, optional An array containing the interpolated traslations, which is passed to avoid repeated calls to the interpolation functions. use_theta_z_format : bool, optional A boolean to indicate whether the imperfection file contains ``x, y, z`` positions or ``theta, z, amplitude``. ignore_bot_h : None or float, optional Used to ignore nodes from the bottom resin ring. ignore_top_h : None or float, optional Used to ignore nodes from the top resin ring. sample_size : int, optional If the input file containing the measured data is too large it may be required to limit the sample size in order to avoid memory errors. T : None or np.ndarray, optional A transformation matrix (cf. :func:`.transf_matrix`) required when the mesh is not in the :ref:`default coordinate system <figure_conecyl>`. Returns ------- nodal_translations : numpy.ndarray A 2-D array containing the translations ``x, y, z`` for each column. Notes ----- Despite the nodal traslations are returned all the nodes belonging to this model will already be translated. """ from abaqus import mdb, session mod = mdb.models[model_name] part = mod.parts[part_name] part_nodes = np.array(part.nodes) coords = np.array([n.coordinates for n in part_nodes]) if T is not None: tmp = np.vstack((coords.T, np.ones((1, coords.shape[0])))) coords = np.dot(T, tmp).T del tmp if ignore_bot_h is not None: if ignore_bot_h <= 0: ignore_bot_h = None else: log('Applying ignore_bot_h: ignoring nodes with z <= {0}'.format( ignore_bot_h)) mask = coords[:, 2] > ignore_bot_h coords = coords[mask] part_nodes = part_nodes[mask] if ignore_top_h is not None: if ignore_top_h <= 0: ignore_top_h = None else: log('Applying ignore_top_h: ignoring nodes with z >= {0}'.format( H_model - ignore_top_h)) mask = coords[:, 2] < (H_model - ignore_top_h) coords = coords[mask] part_nodes = part_nodes[mask] if use_theta_z_format: if nodal_translations is None: trans = calc_translations_ABAQUS( imperfection_file_name=imperfection_file_name, model_name=model_name, part_name=part_name, H_model=H_model, H_measured=H_measured, R_model=R_model, R_best_fit=R_best_fit, semi_angle=semi_angle, stretch_H=stretch_H, z_offset_bot=z_offset_bot, rotatedeg=rotatedeg, scaling_factor=scaling_factor, r_TOL=r_TOL, num_closest_points=num_closest_points, power_parameter=power_parameter, use_theta_z_format=use_theta_z_format, ignore_bot_h=ignore_bot_h, ignore_top_h=ignore_top_h, sample_size=sample_size, T=T) else: trans = nodal_translations # applying translations viewport = session.viewports[session.currentViewportName] log('Applying new nodal positions in ABAQUS CAE to model {0} ...'. format(model_name)) log(' (using a scaling factor of {0})'.format(scaling_factor)) new_coords = coords + trans * scaling_factor if T is not None: Tinv = np.zeros_like(T) Tinv[:3, :3] = T[:3, :3].T Tinv[:, 3] = -T[:, 3] tmp = np.vstack((new_coords.T, np.ones((1, new_coords.shape[0])))) new_coords = np.dot(Tinv, tmp).T del tmp meshNodeArray = part.nodes.sequenceFromLabels( [n.label for n in part_nodes]) new_coords = np.ascontiguousarray(new_coords) part.editNode(nodes=part_nodes.tolist(), coordinates=new_coords) log('Application of new nodal positions finished!') ra = mod.rootAssembly viewport.setValues(displayedObject=ra) ra.regenerate() return trans else: nodes = np.array( [[n.coordinates[0], n.coordinates[1], n.coordinates[2], n.label] for n in part_nodes], dtype=FLOAT) # calling translate_nodes function if nodal_translations is None: nodal_translations = calc_translations_ABAQUS( imperfection_file_name=imperfection_file_name, model_name=model_name, part_name=part_name, H_model=H_model, H_measured=H_measured, R_model=R_model, R_best_fit=R_best_fit, semi_angle=semi_angle, stretch_H=stretch_H, z_offset_bot=z_offset_bot, rotatedeg=rotatedeg, scaling_factor=scaling_factor, r_TOL=r_TOL, num_closest_points=num_closest_points, power_parameter=power_parameter, use_theta_z_format=use_theta_z_format, ignore_bot_h=ignore_bot_h, ignore_top_h=ignore_top_h, sample_size=sample_size, T=T) # applying translations viewport = session.viewports[session.currentViewportName] log('Applying new nodal positions in ABAQUS CAE for model {0} ...'. format(model_name)) log(' (using a scaling factor of {0})'.format(scaling_factor)) trans = nodal_translations new_coords = coords + trans * scaling_factor if T is not None: Tinv = np.zeros_like(T) Tinv[:3, :3] = T[:3, :3].T Tinv[:, 3] = -T[:, 3] tmp = np.vstack((new_coords.T, np.ones((1, new_coords.shape[0])))) new_coords = np.dot(Tinv, tmp).T del tmp meshNodeArray = part.nodes.sequenceFromLabels( [n.label for n in part_nodes]) new_coords = np.ascontiguousarray(new_coords) part.editNode(nodes=meshNodeArray, coordinates=new_coords) log('Application of new nodal positions finished!') # regenerating ra ra = mod.rootAssembly viewport.setValues(displayedObject=ra) ra.regenerate() return nodal_translations
def calc_translations_ABAQUS(imperfection_file_name, model_name, part_name, H_model, H_measured, R_model, R_best_fit=None, semi_angle=0., stretch_H=False, z_offset_bot=None, rotatedeg=0., scaling_factor=1., r_TOL=1., num_closest_points=5, power_parameter=2, use_theta_z_format=True, ignore_bot_h=None, ignore_top_h=None, sample_size=None, T=None): r"""Reads an imperfection file and calculates the nodal translations Parameters ---------- imperfection_file_name : str Full path to the imperfection file. model_name : str Model name. part_name : str Part name. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. H_measured : float The total height of the measured test specimen, including eventual resin rings at the edges. R_model : float Radius **at the bottom edge** of the model where the imperfections will be applied to. R_best_fit : float, optional Best fit radius obtained with functions :func:`.best_fit_cylinder` or :func:`.best_fit_cone`. semi_angle : float, optional Cone semi-vertex angle in degrees, when applicable. stretch_H : bool, optional If the measured imperfection data should be stretched to the current model (which may happen when ``H_model!=H_measured``. z_offset_bot : float, optional It is common to have the measured data not covering the whole test specimen, and therefore it will be centralized, if a non-centralized position is desired this parameter can be used for the adjustment. rotatedeg : float, optional Rotation angle in degrees telling how much the imperfection pattern should be rotated about the `X_3` (or `Z`) axis. scaling_factor : float, optional A scaling factor that can be used to study the imperfection sensitivity. r_TOL : float, optional Percentage tolerance to ignore noisy data from the measurements. num_closest_points : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. power_parameter : float, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. use_theta_z_format : bool, optional If the new format `\theta, Z, imp` should be used instead of the old `X, Y, Z`. ignore_bot_h : None or float, optional Used to ignore nodes from the bottom resin ring. ignore_top_h : None or float, optional Used to ignore nodes from the top resin ring. sample_size : int, optional If the input file containing the measured data is too large it may be required to limit the sample size in order to avoid memory errors. T : None or np.ndarray, optional A transformation matrix (cf. :func:`.transf_matrix`) required when the mesh is not in the :ref:`default coordinate system <figure_conecyl>`. """ import abaqus import desicos.abaqus.abaqus_functions as abaqus_functions mod = abaqus.mdb.models[model_name] part = mod.parts[part_name] part_nodes = np.array(part.nodes) coords = np.array([n.coordinates for n in part_nodes], dtype=FLOAT) if T is not None: tmp = np.vstack((coords.T, np.ones((1, coords.shape[0])))) coords = np.dot(T, tmp).T del tmp if ignore_bot_h is not None: if ignore_bot_h <= 0: ignore_bot_h = None else: mask = coords[:, 2] > ignore_bot_h coords = coords[mask] part_nodes = part_nodes[mask] if ignore_top_h is not None: if ignore_top_h <= 0: ignore_top_h = None else: mask = coords[:, 2] < (H_model - ignore_top_h) coords = coords[mask] part_nodes = part_nodes[mask] if use_theta_z_format: d, d, data = read_theta_z_imp(path=imperfection_file_name, H_measured=H_measured, stretch_H=stretch_H, z_offset_bot=z_offset_bot) if sample_size: num = data.shape[0] if sample_size < num: log('Using sample_size={0}'.format(sample_size), level=1) data = data[sample(range(num), int(sample_size)), :] if r_TOL: max_imp = R_model * r_TOL / 100. imp = data[:, 2] cond = np.any(np.array((imp > max_imp, imp < (-max_imp))), axis=0) log('Skipping {0} points'.format(len(imp[cond]))) data = data[np.logical_not(cond), :] data3D = np.zeros((data.shape[0], 4), dtype=FLOAT) if rotatedeg: data[:, 0] += deg2rad(rotatedeg) z = data[:, 1] z *= H_model alpharad = deg2rad(semi_angle) tana = tan(alpharad) def r_local(z): return R_model - z * tana data3D[:, 0] = r_local(z) * cos(data[:, 0]) data3D[:, 1] = r_local(z) * sin(data[:, 0]) data3D[:, 2] = z data3D[:, 3] = data[:, 2] dist, w0 = inv_weighted(data3D, coords, ncp=num_closest_points, power_parameter=power_parameter) thetas = arctan2(coords[:, 1], coords[:, 0]) trans = np.zeros_like(coords) trans[:, 0] = w0 * cos(alpharad) * cos(thetas) trans[:, 1] = w0 * cos(alpharad) * sin(thetas) trans[:, 2] = w0 * sin(alpharad) else: #NOTE perhaps remove this in the future, when the imperfection files # are stored as theta, z, amplitude only nodes = np.array( [[n.coordinates[0], n.coordinates[1], n.coordinates[2], n.label] for n in part_nodes], dtype=FLOAT) # calling translate_nodes function trans = calc_nodal_translations(imperfection_file_name, nodes=nodes, H_model=H_model, H_measured=H_measured, R_model=R_model, R_best_fit=R_best_fit, semi_angle=semi_angle, stretch_H=stretch_H, z_offset_bot=z_offset_bot, rotatedeg=rotatedeg, r_TOL=r_TOL, num_closest_points=num_closest_points, power_parameter=power_parameter, sample_size=sample_size) trans = trans[:, :3] return trans
def plot_field_data(self, x, y, field, create_npz_only, ax, figsize, save_png, aspect, clean, outpath, pngname, npzname, pyname, num_levels, show_colorbar, lines): npzname = npzname.split('.npz')[0] + '.npz' pyname = pyname.split('.py')[0] + '.py' pngname = pngname.split('.png')[0] + '.png' npzname = os.path.join(outpath, npzname) pyname = os.path.join(outpath, pyname) pngname = os.path.join(outpath, pngname) if lines: # not empty or None # Concatenate all lines into a single matrix, separated by 'sep' sep = np.array([[float('NaN')], [float('NaN')]]) all_lines = (2 * len(lines) - 1) * [sep] all_lines[::2] = [np.array(l, copy=False) for l in lines] line = np.hstack(all_lines) else: line = np.empty((2, 0)) if not create_npz_only: try: import matplotlib.pyplot as plt import matplotlib except: create_npz_only = True if not create_npz_only: levels = np.linspace(field.min(), field.max(), num_levels) if ax is None: fig = plt.figure(figsize=figsize) ax = fig.add_subplot(111) else: if isinstance(ax, matplotlib.axes.Axes): ax = ax fig = ax.figure save_png = False else: raise ValueError('"ax" must be an Axes object') contours = ax.contourf(x, y, field, levels=levels) if show_colorbar: plt.colorbar(contours, ax=ax, shrink=0.5, format='%.4g', use_gridspec=True) ax.plot(line[0, :], line[1, :], 'k-', linewidth=0.5) ax.grid(False) ax.set_aspect(aspect) #ax.set_title( #r'$PL=20 N$, $F_{{C}}=50 kN$, $w_{{PL}}=\beta$, $mm$') if clean: ax.xaxis.set_ticks_position('none') ax.yaxis.set_ticks_position('none') ax.xaxis.set_ticklabels([]) ax.yaxis.set_ticklabels([]) ax.set_frame_on(False) else: ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks([-self.rbot * np.pi, 0, self.rbot * np.pi]) ax.xaxis.set_ticklabels([r'$-\pi$', '$0$', r'$+\pi$']) if save_png: log('') log('Plot saved at: {0}'.format(pngname)) plt.tight_layout() plt.savefig(pngname, transparent=True, bbox_inches='tight', pad_inches=0.05, dpi=400) else: log('Matplotlib cannot be imported from Abaqus') np.savez(npzname, x=x, y=y, field=field, line=line) with open(pyname, 'w') as f: f.write("import os\n") f.write("\n") f.write("import numpy as np\n") f.write("import matplotlib\n") f.write("matplotlib.use('TkAgg')\n") f.write("from matplotlib import cm\n") f.write("import matplotlib.pyplot as plt\n") f.write("from mpl_toolkits.axes_grid1 import make_axes_locatable\n") f.write("\n") f.write("add_title = False\n") f.write("tmp = np.load(r'{0}')\n".format(basename(npzname))) f.write("pngname = r'{0}'\n".format(basename(pngname))) f.write("x = tmp['x']\n") f.write("y = tmp['y']\n") f.write("field = tmp['field']\n") f.write("line = tmp['line']\n") f.write("clean = {0}\n".format(clean)) f.write("show_colorbar = {0}\n".format(show_colorbar)) f.write("plt.figure(figsize={0})\n".format(figsize)) f.write("ax = plt.gca()\n") f.write("levels = np.linspace(field.min(), field.max(), {0})\n".format( num_levels)) f.write( "contours = ax.contourf(x, y, field, levels=levels, cmap=cm.jet)\n" ) f.write("if show_colorbar:\n") f.write(" divider = make_axes_locatable(ax)\n") f.write( " cax = divider.append_axes('right', size='5%', pad=0.05)\n") f.write( " cbar = plt.colorbar(contours, cax=cax, format='%.2f', use_gridspec=True,\n" ) f.write(" ticks=[field.min(), field.max()])\n") f.write(" cbar.outline.remove()\n") f.write( " cbar.ax.tick_params(labelsize=14, pad=0., tick2On=False)\n") f.write("ax.plot(line[0,:], line[1,:], 'k-', linewidth=0.5)\n") f.write("ax.grid(False)\n") f.write("ax.set_aspect('{0}')\n".format(aspect)) f.write("if add_title:\n") f.write( " ax.set_title(r'Abaqus, $PL=20 N$, $F_{{C}}=50 kN$, $w_{{PL}}=\\beta$, $mm$')\n" ) f.write("if clean:\n") f.write(" ax.xaxis.set_ticks_position('none')\n") f.write(" ax.yaxis.set_ticks_position('none')\n") f.write(" ax.xaxis.set_ticklabels([])\n") f.write(" ax.yaxis.set_ticklabels([])\n") f.write(" ax.set_frame_on(False)\n") f.write("else:\n") f.write(" ax.xaxis.set_ticks_position('bottom')\n") f.write(" ax.yaxis.set_ticks_position('left')\n") f.write(" ax.xaxis.set_ticks([{0}, 0, {1}])\n".format( -self.rbot * np.pi, self.rbot * np.pi)) f.write( " ax.xaxis.set_ticklabels([r'$-\\pi$', '$0$', r'$+\\pi$'])\n") f.write("plt.savefig(pngname, transparent=True,\n") f.write(" bbox_inches='tight', pad_inches=0.05, dpi=400)\n") f.write("plt.show()\n") log('') log('Output exported to "{0}"'.format(npzname)) log('Please run the file "{0}" to plot the output'.format(pyname)) log('')
def change_thickness_ABAQUS(imperfection_file_name, model_name, part_name, stack, t_model, t_measured, H_model, H_measured, R_model, R_best_fit=None, number_of_sets=None, semi_angle=0., stretch_H=False, z_offset_bot=None, scaling_factor=1., num_closest_points=5, power_parameter=2, elems_t=None, t_set=None, use_theta_z_format=False): r"""Applies a given thickness imperfection to the finite element model Assumes that a percentage variation of the laminate thickness can be represented by the same percentage veriation of each ply, i.e., each ply thickness is varied in order to reflect a given measured thickness imperfection field. Parameters ---------- imperfection_file_name : str Full path to the imperfection file. model_name : str Model name. part_name : str Part name. stack : list The stacking sequence of the current model with each angle given in degrees. t_model : float The nominal shell thickness of the current model. t_measured : float The nominal thickness of the measured specimen. H_model : float Total height of the model where the imperfections will be applied to, considering also eventual resin rings. H_measured : float The total height of the measured test specimen, including eventual resin rings at the edges. R_model : float Radius **at the bottom edge** of the model where the imperfections will be applied to. R_best_fit : float, optional Best fit radius obtained with functions :func:`.best_fit_cylinder` or :func:`.best_fit_cone`. number_of_sets : int, optional Defines in how many levels the thicknesses should be divided. If ``None`` it will be based on the input file, and if the threshold of ``100`` is exceeded, ``10`` sections are used. semi_angle : float, optional Cone semi-vertex angle in degrees, when applicable. stretch_H : bool, optional If the measured imperfection data should be stretched to the current model (which may happen when ``H_model!=H_measured``. z_offset_bot : float, optional It is common to have the measured data not covering the whole test specimen, and therefore it will be centralized, if a non-centralized position is desired this parameter can be used for the adjustment. scaling_factor : float, optional A scaling factor that can be used to study the imperfection sensitivity. num_closest_points : int, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. power_parameter : float, optional See :func:`the inverse-weighted interpolation algorithm <.inv_weighted>`. elems_t : np.ndarray, optional Interpolated thickness for each element. Can be used to avoid the same interpolation to be performed twice. t_set : set, optional A ``set`` object containing the unique thicknesses that will be used to create the new properties. use_theta_z_format : bool, optional If the new format `\theta, Z, imp` should be used instead of the old `X, Y, Z`. """ from abaqus import mdb import desicos.abaqus.abaqus_functions as abaqus_functions mod = mdb.models[model_name] part = mod.parts[part_name] part_cyl_csys = part.features['part_cyl_csys'] part_cyl_csys = part.datums[part_cyl_csys.id] if use_theta_z_format: if elems_t is None or t_set is None: log('Reading coordinates for elements...') elements = vec_calc_elem_cg(part.elements) log('Coordinates for elements read!') d, d, data = read_theta_z_imp(path=imperfection_file_name, H_measured=H_measured, stretch_H=stretch_H, z_offset_bot=z_offset_bot) data3D = np.zeros((data.shape[0], 4), dtype=FLOAT) z = data[:, 1] z *= H_model alpharad = deg2rad(semi_angle) tana = tan(alpharad) def r_local(z): return R_model - z * tana data3D[:, 0] = r_local(z) * cos(data[:, 0]) data3D[:, 1] = r_local(z) * sin(data[:, 0]) data3D[:, 2] = z data3D[:, 3] = data[:, 2] dist, ans = inv_weighted(data3D, elements[:, :3], ncp=num_closest_points, power_parameter=power_parameter) t_set = set(ans) t_set.discard(0.) #TODO why inv_weighted returns an array with 0. elems_t = np.zeros((elements.shape[0], 2), dtype=FLOAT) elems_t[:, 0] = elements[:, 3] elems_t[:, 1] = ans else: log('Thickness differences already calculated!') else: if elems_t is None or t_set is None: # reading elements data log('Reading coordinates for elements...') elements = vec_calc_elem_cg(part.elements) log('Coordinates for elements read!') # calling translate_nodes function elems_t, t_set = calc_elems_t( imperfection_file_name, nodes=elements, t_model=t_model, t_measured=t_measured, H_model=H_model, H_measured=H_measured, R_model=R_model, R_best_fit=R_best_fit, semi_angle=semi_angle, stretch_H=stretch_H, z_offset_bot=z_offset_bot, num_closest_points=num_closest_points, power_parameter=power_parameter) else: log('Thickness differences already calculated!') # creating sets t_list = [] max_len_t_set = 100 if len(t_set) >= max_len_t_set and number_of_sets in (None, 0): number_of_sets = 10 log('More than {0:d} different thicknesses measured!'.format( max_len_t_set)) log('Forcing a number_of_sets = {0:d}'.format(number_of_sets)) if number_of_sets is None or number_of_sets == 0: number_of_sets = len(t_set) t_list = list(t_set) t_list.sort() else: t_min = min(t_set) t_max = max(t_set) t_list = list(np.linspace(t_min, t_max, number_of_sets + 1)) # grouping elements sets_ids = [[] for i in range(len(t_list))] for entry in elems_t: elem_id, t = entry index = index_within_linspace(t_list, t) sets_ids[index].append(int(elem_id)) # putting elements in sets original_layup = part.compositeLayups['CompositePlate'] for i, set_ids in enumerate(sets_ids): if len(set_ids) == 0: # since t_set_norm * t_model <> t_set originally measured # there may be empty set_ids at the end continue elements = part.elements.sequenceFromLabels(labels=set_ids) suffix = 'measured_imp_t_{0:03d}'.format(i) set_name = 'Set_' + suffix log('Creating set ({0: 7d} elements): {1}'.format( len(set_ids), set_name)) part.Set(name=set_name, elements=elements) region = part.sets[set_name] layup_name = 'CLayup_' + suffix t_diff = (float(t_list[i]) - t_model) * scaling_factor t_scaling_factor = (t_model + t_diff) / t_model def modify_ply(index, kwargs): kwargs['thickness'] *= t_scaling_factor kwargs['region'] = region return kwargs layup = part.CompositeLayup(name=layup_name, objectToCopy=original_layup) layup.resume() abaqus_functions.modify_composite_layup(part=part, layup_name=layup_name, modify_func=modify_ply) # suppress needed to put the new properties to the input file original_layup.suppress() return elems_t, t_set
def plot_field_data(self, x, y, field, create_npz_only, ax, figsize, save_png, aspect, clean, outpath, pngname, npzname, pyname, num_levels, show_colorbar, lines): npzname = npzname.split('.npz')[0] + '.npz' pyname = pyname.split('.py')[0] + '.py' pngname = pngname.split('.png')[0] + '.png' npzname = os.path.join(outpath, npzname) pyname = os.path.join(outpath, pyname) pngname = os.path.join(outpath, pngname) if lines: # not empty or None # Concatenate all lines into a single matrix, separated by 'sep' sep = np.array([[float('NaN')], [float('NaN')]]) all_lines = (2*len(lines) - 1)*[sep] all_lines[::2] = [np.array(l, copy=False) for l in lines] line = np.hstack(all_lines) else: line = np.empty((2, 0)) if not create_npz_only: try: import matplotlib.pyplot as plt import matplotlib except: create_npz_only = True if not create_npz_only: levels = np.linspace(field.min(), field.max(), num_levels) if ax is None: fig = plt.figure(figsize=figsize) ax = fig.add_subplot(111) else: if isinstance(ax, matplotlib.axes.Axes): ax = ax fig = ax.figure save_png = False else: raise ValueError('"ax" must be an Axes object') contours = ax.contourf(x, y, field, levels=levels) if show_colorbar: plt.colorbar(contours, ax=ax, shrink=0.5, format='%.4g', use_gridspec=True) ax.plot(line[0,:], line[1,:], 'k-', linewidth=0.5) ax.grid(False) ax.set_aspect(aspect) #ax.set_title( #r'$PL=20 N$, $F_{{C}}=50 kN$, $w_{{PL}}=\beta$, $mm$') if clean: ax.xaxis.set_ticks_position('none') ax.yaxis.set_ticks_position('none') ax.xaxis.set_ticklabels([]) ax.yaxis.set_ticklabels([]) ax.set_frame_on(False) else: ax.xaxis.set_ticks_position('bottom') ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks([-self.rbot*np.pi, 0, self.rbot*np.pi]) ax.xaxis.set_ticklabels([r'$-\pi$', '$0$', r'$+\pi$']) if save_png: log('') log('Plot saved at: {0}'.format(pngname)) plt.tight_layout() plt.savefig(pngname, transparent=True, bbox_inches='tight', pad_inches=0.05, dpi=400) else: log('Matplotlib cannot be imported from Abaqus') np.savez(npzname, x=x, y=y, field=field, line=line) with open(pyname, 'w') as f: f.write("import os\n") f.write("\n") f.write("import numpy as np\n") f.write("import matplotlib.pyplot as plt\n") f.write("from mpl_toolkits.axes_grid1 import make_axes_locatable\n") f.write("\n") f.write("add_title = False\n") f.write("tmp = np.load(r'{0}')\n".format(basename(npzname))) f.write("pngname = r'{0}'\n".format(basename(pngname))) f.write("x = tmp['x']\n") f.write("y = tmp['y']\n") f.write("field = tmp['field']\n") f.write("line = tmp['line']\n") f.write("clean = {0}\n".format(clean)) f.write("show_colorbar = {0}\n".format(show_colorbar)) f.write("plt.figure(figsize={0})\n".format(figsize)) f.write("ax = plt.gca()\n") f.write("levels = np.linspace(field.min(), field.max(), {0})\n".format( num_levels)) f.write("contours = ax.contourf(x, y, field, levels=levels)\n") f.write("if show_colorbar:\n") f.write(" divider = make_axes_locatable(ax)\n") f.write(" cax = divider.append_axes('right', size='5%', pad=0.05)\n") f.write(" cbar = plt.colorbar(contours, cax=cax, format='%.2f', use_gridspec=True,\n") f.write(" ticks=[field.min(), field.max()])\n") f.write(" cbar.outline.remove()\n") f.write(" cbar.ax.tick_params(labelsize=14, pad=0., tick2On=False)\n") f.write("ax.plot(line[0,:], line[1,:], 'k-', linewidth=0.5)\n") f.write("ax.grid(False)\n") f.write("ax.set_aspect('{0}')\n".format(aspect)) f.write("if add_title:\n") f.write(" ax.set_title(r'Abaqus, $PL=20 N$, $F_{{C}}=50 kN$, $w_{{PL}}=\\beta$, $mm$')\n") f.write("if clean:\n") f.write(" ax.xaxis.set_ticks_position('none')\n") f.write(" ax.yaxis.set_ticks_position('none')\n") f.write(" ax.xaxis.set_ticklabels([])\n") f.write(" ax.yaxis.set_ticklabels([])\n") f.write(" ax.set_frame_on(False)\n") f.write("else:\n") f.write(" ax.xaxis.set_ticks_position('bottom')\n") f.write(" ax.yaxis.set_ticks_position('left')\n") f.write(" ax.xaxis.set_ticks([{0}, 0, {1}])\n".format( -self.rbot*np.pi, self.rbot*np.pi)) f.write(" ax.xaxis.set_ticklabels([r'$-\\pi$', '$0$', r'$+\\pi$'])\n") f.write("plt.savefig(pngname, transparent=True,\n") f.write(" bbox_inches='tight', pad_inches=0.05, dpi=400)\n") f.write("plt.show()\n") log('') log('Output exported to "{0}"'.format(npzname)) log('Please run the file "{0}" to plot the output'.format( pyname)) log('')