def extract_fiber_orientation(self, ply_index, use_elements): if use_elements: from abaqus import mdb if self.model_name in mdb.models.keys(): part = mdb.models[self.model_name].parts[self.part_name_shell] else: raise RuntimeError("Cannot obtain element locations, model for '{0}' is not loaded".format(self.model_name)) elements = part.elements coords = utils.vec_calc_elem_cg(elements) thetas = np.arctan2(coords[:, 1], coords[:, 0]) zs = coords[:, 2] else: thetas = np.linspace(-np.pi, np.pi, self.numel_r + 1) thetas = (thetas[:-1] + thetas[1:]) / 2 mean_circumf = np.pi*(self.rtop + self.rbot) # Estimate num elements in vertical direction numel_z = int(np.ceil(float(self.L) / mean_circumf * self.numel_r)) zs = np.linspace(0, self.H, numel_z + 1) zs = (zs[:-1] + zs[1:]) / 2 thetas, zs = np.meshgrid(thetas, zs) thetas = thetas.flatten() zs = zs.flatten() # Determine coords rs = self.fr(zs) xs = rs*np.cos(thetas) ys = rs*np.sin(thetas) coords = np.column_stack([xs, ys, zs]) out = np.array(self.impconf.ppi.fiber_orientation(ply_index, coords)) return _sort_field_data(thetas, zs, out, self.numel_r)
def _create_orientation_fields(self, mod, elements): """Create, for each ply, a discrete field containing the local orientation at each element. Parameters ---------- mod : Model Abaqus model to which the fields should be added elements : MeshElementArray Set of elements that should be represented in the discrete field Returns ------- fields : list List of DiscreteFields, one for each ply. .. note:: Must be called from Abaqus. """ from abaqusConstants import SCALAR cc = self.impconf.conecyl fields = [] coords = vec_calc_elem_cg(elements) el_ids = map(int, coords[:,3]) for i, angle in enumerate(cc.stack): field_name = 'ply_%02d_field' % (i+1) values = self.fiber_orientation(i, coords) if np.nan in values: raise ValueError('Invalid PPI parameters: not all points are covered by ply pieces') field = mod.DiscreteField( name=field_name, defaultValues=(angle, ), fieldType=SCALAR, data=[('', 1, el_ids, values)]) fields.append(field) return fields
def extract_fiber_orientation(self, ply_index, use_elements): if use_elements: from abaqus import mdb if self.model_name in mdb.models.keys(): part = mdb.models[self.model_name].parts[self.part_name_shell] else: raise RuntimeError( "Cannot obtain element locations, model for '{0}' is not loaded" .format(self.model_name)) elements = part.elements coords = utils.vec_calc_elem_cg(elements) thetas = np.arctan2(coords[:, 1], coords[:, 0]) zs = coords[:, 2] else: thetas = np.linspace(-np.pi, np.pi, self.numel_r + 1) thetas = (thetas[:-1] + thetas[1:]) / 2 mean_circumf = np.pi * (self.rtop + self.rbot) # Estimate num elements in vertical direction numel_z = int(np.ceil(float(self.L) / mean_circumf * self.numel_r)) zs = np.linspace(0, self.H, numel_z + 1) zs = (zs[:-1] + zs[1:]) / 2 thetas, zs = np.meshgrid(thetas, zs) thetas = thetas.flatten() zs = zs.flatten() # Determine coords rs = self.fr(zs) xs = rs * np.cos(thetas) ys = rs * np.sin(thetas) coords = np.column_stack([xs, ys, zs]) out = np.array(self.impconf.ppi.fiber_orientation(ply_index, coords)) return _sort_field_data(thetas, zs, out, self.numel_r)
def _nodal_field_S8_add_centroids(elements, node_labels, node_values): # For S8 elements and nodal fields, one may want to add values for the # centroids as well, to create a regular grid. This is done by # interpolation. # Values of interpolation functions at centroid: -0.25 for corner # nodes, 0.5 for side nodes INTERP = np.array([-0.25, -0.25, -0.25, -0.25, 0.5, 0.5, 0.5, 0.5]) el_coords = utils.vec_calc_elem_cg(elements) el_out = np.zeros((el_coords.shape[0], )) for i, el in enumerate(elements): # el.connectivity can't be used, as it uses node indices, not labels mask = np.in1d(node_labels, [n.label for n in el.getNodes()]) el_out[i] = np.dot(INTERP, node_values[mask]) # return coords, values for element centroids return el_coords[:, :3], el_out
def _nodal_field_S8_add_centroids(elements, node_labels, node_values): # For S8 elements and nodal fields, one may want to add values for the # centroids as well, to create a regular grid. This is done by # interpolation. # Values of interpolation functions at centroid: -0.25 for corner # nodes, 0.5 for side nodes INTERP = np.array([-0.25, -0.25, -0.25, -0.25, 0.5, 0.5, 0.5, 0.5]) el_coords = utils.vec_calc_elem_cg(elements) el_out = np.zeros((el_coords.shape[0], )) for i, el in enumerate(elements): # el.connectivity can't be used, as it uses node indices, not labels mask = np.in1d(node_labels, [n.label for n in el.getNodes()]) el_out[i] = np.dot(INTERP, node_values[mask]) # return coords, values for element centroids return el_coords[:,:3], el_out
def extract_thickness_data(self): from abaqus import mdb if self.model_name in mdb.models.keys(): part = mdb.models[self.model_name].parts[self.part_name_shell] else: raise RuntimeError("Cannot obtain element locations, model for '{0}' is not loaded".format(self.model_name)) elements = part.elements coords = utils.vec_calc_elem_cg(elements) thetas = np.arctan2(coords[:, 1], coords[:, 0]) zs = coords[:, 2] labels = coords[:, 3] thicks = np.zeros_like(zs) for layup in part.compositeLayups.values(): if not layup.suppressed: el_set = part.sets[layup.plies[0].region[0]] layup_els = np.array([e. label for e in el_set.elements]) layup_thickness = sum(p.thickness for p in layup.plies.values()) thicks[np.in1d(labels, layup_els)] = layup_thickness return _sort_field_data(thetas, zs, thicks, self.numel_r)
def extract_thickness_data(self): from abaqus import mdb if self.model_name in mdb.models.keys(): part = mdb.models[self.model_name].parts[self.part_name_shell] else: raise RuntimeError( "Cannot obtain element locations, model for '{0}' is not loaded". format(self.model_name)) elements = part.elements coords = utils.vec_calc_elem_cg(elements) thetas = np.arctan2(coords[:, 1], coords[:, 0]) zs = coords[:, 2] labels = coords[:, 3] thicks = np.zeros_like(zs) for layup in part.compositeLayups.values(): if not layup.suppressed: el_set = part.sets[layup.plies[0].region[0]] layup_els = np.array([e.label for e in el_set.elements]) layup_thickness = sum(p.thickness for p in layup.plies.values()) thicks[np.in1d(labels, layup_els)] = layup_thickness return _sort_field_data(thetas, zs, thicks, self.numel_r)
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 extract_field_output(self, ignore): from abaqus import mdb from abaqusConstants import NODAL import desicos.abaqus.abaqus_functions as abaqus_functions if self.model_name in mdb.models.keys(): part = mdb.models[self.model_name].parts[self.part_name_shell] else: text = 'The model corresponding to the active odb must be loaded' raise RuntimeError(text) elements = part.elements nodes = part.nodes sina = np.sin(self.alpharad) cosa = np.cos(self.alpharad) odb = abaqus_functions.get_current_odb() odbDisplay = abaqus_functions.get_current_odbdisplay() frame = abaqus_functions.get_current_frame() fieldOutputKey = odbDisplay.primaryVariable[0] sub_vector = odbDisplay.primaryVariable[5] frame_num = int(frame.frameValue) field = frame.fieldOutputs[fieldOutputKey] nodal_out = False if field.values[0].position == NODAL: nodal_out = True if nodal_out: odbSet = odb.rootAssembly.nodeSets['SHELL_FACES'] coords = np.array([n.coordinates for n in nodes]) labels = np.array([n.label for n in nodes]) if ignore: mask = np.in1d(labels, ignore) labels = labels[mask] coords = coords[mask] thetas = np.arctan2(coords[:, 1], coords[:, 0]) else: odbSet = odb.rootAssembly.elementSets['SHELL_FACES'] coords = utils.vec_calc_elem_cg(elements) thetas = np.arctan2(coords[:, 1], coords[:, 0]) field = field.getSubset(region=odbSet) attributes = { 'Magnitude': 'magnitude', 'Mises': 'mises', 'Min. In-Plane Principal': 'minInPlanePrincipal', 'Max. In-Plane Principal': 'maxInPlanePrincipal', 'Min. Principal': 'minPrincipal', 'Mid. Principal': 'midPrincipal', 'Max. Principal': 'maxPrincipal', 'Out-of-Plane Principal': 'outOfPlanePrincipal', 'Tresca': 'tresca', 'Third Invariant': 'inv3', } components = { 'S11': 0, 'S22': 1, 'S33': 2, 'S12': 3, 'SF1': 0, 'SF2': 1, 'SF3': 3, 'SM2': 0, 'SM1': 1, 'SM3': 2, } if sub_vector == '': out = np.array([val.data for val in field.values]) elif sub_vector in attributes.keys(): attr = attributes.get(sub_vector) out = np.array([getattr(v, attr) for v in field.values]) elif sub_vector in components.keys(): pos = components[sub_vector] out = np.array([v.data[pos] for v in field.values]) elif sub_vector in ('U1', 'UT1', 'U2', 'UT2', 'U3', 'UT3'): uvw_rec = np.array([val.data for val in field.values]) u1_rec = uvw_rec[:, 0] u2_rec = uvw_rec[:, 1] u3_rec = uvw_rec[:, 2] u3_cyl = u3_rec u2_cyl = u2_rec * np.cos(thetas) - u1_rec * np.sin(thetas) u1_cyl = u2_rec * np.sin(thetas) + u1_rec * np.cos(thetas) u1_cone = u1_cyl * cosa + u3_cyl * sina u2_cone = u2_cyl u3_cone = u3_cyl * cosa - u1_cyl * sina displ_vecs = { 'U1': u1_cone, 'U2': u2_cone, 'U3': u3_cone, 'UT1': u1_cone, 'UT2': u2_cone, 'UT3': u3_cone } out = displ_vecs[sub_vector] else: raise NotImplementedError('{0} cannot be used!'.format(sub_vector)) if not nodal_out: firstElement = None numIntPts = 0 for v in field.values: if firstElement is None: firstElement = v.elementLabel if v.elementLabel == firstElement: numIntPts += 1 else: break out = out.reshape(-1, numIntPts).mean(axis=1) if 'S8' in self.elem_type and nodal_out: el_coords, el_out = _nodal_field_S8_add_centroids( elements, labels, out) el_thetas = np.arctan2(el_coords[:, 1], el_coords[:, 0]) coords = np.vstack((coords, el_coords)) thetas = np.hstack((thetas, el_thetas)) out = np.hstack((out, el_out)) num_thetas = 2 * self.numel_r else: num_thetas = self.numel_r zs = coords[:, 2] return _sort_field_data(thetas, zs, out, num_thetas)
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 extract_field_output(self, ignore): from abaqus import mdb from abaqusConstants import NODAL import desicos.abaqus.abaqus_functions as abaqus_functions if self.model_name in mdb.models.keys(): part = mdb.models[self.model_name].parts[self.part_name_shell] else: text = 'The model corresponding to the active odb must be loaded' raise RuntimeError(text) elements = part.elements nodes = part.nodes sina = np.sin(self.alpharad) cosa = np.cos(self.alpharad) odb = abaqus_functions.get_current_odb() odbDisplay = abaqus_functions.get_current_odbdisplay() frame = abaqus_functions.get_current_frame() fieldOutputKey = odbDisplay.primaryVariable[0] sub_vector = odbDisplay.primaryVariable[5] frame_num = int(frame.frameValue) field = frame.fieldOutputs[fieldOutputKey] nodal_out = False if field.values[0].position == NODAL: nodal_out = True if nodal_out: odbSet = odb.rootAssembly.nodeSets['SHELL_FACES'] coords = np.array([n.coordinates for n in nodes]) labels = np.array([n.label for n in nodes]) if ignore: mask = np.in1d(labels, ignore) labels = labels[mask] coords = coords[mask] thetas = np.arctan2(coords[:, 1], coords[:, 0]) else: odbSet = odb.rootAssembly.elementSets['SHELL_FACES'] coords = utils.vec_calc_elem_cg(elements) thetas = np.arctan2(coords[:, 1], coords[:, 0]) field = field.getSubset(region=odbSet) attributes = { 'Magnitude': 'magnitude', 'Mises': 'mises', 'Min. In-Plane Principal': 'minInPlanePrincipal', 'Max. In-Plane Principal': 'maxInPlanePrincipal', 'Min. Principal': 'minPrincipal', 'Mid. Principal': 'midPrincipal', 'Max. Principal': 'maxPrincipal', 'Out-of-Plane Principal': 'outOfPlanePrincipal', 'Tresca': 'tresca', 'Third Invariant': 'inv3', } components = { 'S11': 0, 'S22': 1, 'S33': 2, 'S12': 3, 'SF1': 0, 'SF2': 1, 'SF3': 3, 'SM2': 0, 'SM1': 1, 'SM3': 2, } if sub_vector == '': out = np.array([val.data for val in field.values]) elif sub_vector in attributes.keys(): attr = attributes.get(sub_vector) out = np.array([getattr(v, attr) for v in field.values]) elif sub_vector in components.keys(): pos = components[sub_vector] out = np.array([v.data[pos] for v in field.values]) elif sub_vector in ('U1', 'UT1', 'U2', 'UT2', 'U3', 'UT3'): uvw_rec = np.array([val.data for val in field.values]) u1_rec = uvw_rec[:,0] u2_rec = uvw_rec[:,1] u3_rec = uvw_rec[:,2] u3_cyl = u3_rec u2_cyl = u2_rec*np.cos(thetas) - u1_rec*np.sin(thetas) u1_cyl = u2_rec*np.sin(thetas) + u1_rec*np.cos(thetas) u1_cone = u1_cyl*cosa + u3_cyl*sina u2_cone = u2_cyl u3_cone = u3_cyl*cosa - u1_cyl*sina displ_vecs = {'U1':u1_cone, 'U2':u2_cone, 'U3':u3_cone, 'UT1':u1_cone, 'UT2':u2_cone, 'UT3':u3_cone} out = displ_vecs[sub_vector] else: raise NotImplementedError('{0} cannot be used!'.format( sub_vector)) if not nodal_out: firstElement = None numIntPts = 0 for v in field.values: if firstElement is None: firstElement = v.elementLabel if v.elementLabel == firstElement: numIntPts += 1 else: break out = out.reshape(-1, numIntPts).mean(axis=1) if 'S8' in self.elem_type and nodal_out: el_coords, el_out = _nodal_field_S8_add_centroids(elements, labels, out) el_thetas = np.arctan2(el_coords[:, 1], el_coords[:, 0]) coords = np.vstack((coords, el_coords)) thetas = np.hstack((thetas, el_thetas)) out = np.hstack((out, el_out)) num_thetas = 2*self.numel_r else: num_thetas = self.numel_r zs = coords[:, 2] return _sort_field_data(thetas, zs, out, num_thetas)
import numpy as np from numpy.linalg import lstsq from numpy import sin, cos from regionToolset import Region from desicos.abaqus.utils import vec_calc_elem_cg elem_cgs = vec_calc_elem_cg( cc.part.elements ) ce = elem_cgs[ np.all( (elem_cgs[:,2] > 0.95*cc.h/2, elem_cgs[:,2] < 1.*cc.h/2),axis=0 ) ] ce = ce[ np.argsort(ce[:,3]) ] elem_ids = np.int_(ce[:,3]) odb = cc.attach_results() inst = odb.rootAssembly.instances['INSTANCECYLINDER'] odb_mesh_elem_array = inst.ElementSetFromElementLabels( name='ce', elementLabels=elem_ids ) frames = odb.steps[cc.step2Name].frames #def get_outputs(frame, key='SF'): def calc_sfs(frame): key = 'SF' fieldOutput = frame.fieldOutputs[key] output = fieldOutput.getSubset(region=odb_mesh_elem_array) sfs =np.array([[v.data[0], v.data[1], v.data[2], v.elementLabel] \ for v in output.values], dtype='float32') sfs = np.average(np.array([sfs[i:i+4] for i in range(0,len(elem_ids)*4,4)]), axis=1) return sfs vec_calc_sfs = np.vectorize(calc_sfs, otypes=[object])