def get_centroid_volume(self, element_id=None, xyz_cid0=None, total=False): """ Gets the centroid and volume for one or more elements. Parameters ---------- element_id : (nelements, ) int ndarray; default=None the elements to consider xyz_cid0 : (nnodes, 3) float ndarray; default=None -> calculate the GRIDs in CORD2R=0 total : bool; default=False should the volume be summed; centroid be averaged .. seealso:: CHEXA20.get_volume_by_element_id() and CHEXA20.get_centroid_by_element_id() for more information. """ nodes = self._get_node_locations_by_element_id(element_id, xyz_cid0) n1, n2, n3, n4, n5, n6, n7, n8 = nodes (A1, c1) = quad_area_centroid(n1, n2, n3, n4) (A2, c2) = quad_area_centroid(n5, n6, n7, n8) centroid = (c1 * A1 + c2 * A2) / (A1 + A2) volume = (A1 + A2) / 2. * norm(c1 - c2, axis=1) if total: centroid = centroid.mean() volume = abs(volume).sum() else: volume = abs(volume) assert volume.min() > 0.0, 'volume.min() = %f' % volume.min() return centroid, volume
def get_centroid_by_element_id(self, element_id=None, xyz_cid0=None, total=False): """ Gets the centroid for one or more elements. Parameters ---------- element_id : (nelements, ) int ndarray; default=None the elements to consider xyz_cid0 : (nnodes, 3) float ndarray; default=None -> calculate the GRIDs in CORD2R=0 total : bool; default=False should the centroid be averaged """ nodes = self._get_node_locations_by_element_id(element_id, xyz_cid0) n1, n2, n3, n4, n5, n6, n7, n8 = nodes (A1, c1) = quad_area_centroid(n1, n2, n3, n4) (A2, c2) = quad_area_centroid(n5, n6, n7, n8) centroid = (c1 * A1 + c2 * A2) / (A1 + A2) if total: centroid = centroid.mean(axis=0) return centroid
def get_mass_by_element_id(self, element_ids_orig=None, xyz_cid0=None, sort_output=True): if xyz_cid0 is None: xyz_cid0 = self.model.grid.get_position_by_node_index() element_ids, element_ids_orig = self._get_element_ids(element_ids_orig) if len(element_ids) == 0: nelements = len(element_ids_orig) mass = np.full(nelements, np.nan, 'float64') if sort_output: i = np.argsort(element_ids_orig) #print("i =", i, i.shape) #print("element_ids_orig =", element_ids_orig, element_ids_orig.shape) return element_ids_orig[i], mass else: return element_ids_orig, mass nelements_orig = len(element_ids_orig) #print('eids orig = %s' % element_ids_orig) type_map = { #'CELAS1' : self.elements_spring.celas1, 'CELAS2': self.elements_spring.celas2, 'CELAS3': self.elements_spring.celas3, 'CELAS4': self.elements_spring.celas4, 'CBAR': self.cbar, 'CBEAM': self.cbeam, 'CROD': self.crod, 'CONROD': self.conrod, 'CTUBE': self.ctube, 'CSHEAR': self.cshear, 'CQUAD4': self.elements_shell.cquad4, 'CTRIA3': self.elements_shell.ctria3, 'CTETRA4': self.elements_solid.ctetra4, 'CPENTA6': self.elements_solid.cpenta6, 'CHEXA8': self.elements_solid.chexa8, 'CTETRA10': self.elements_solid.ctetra10, 'CPENTA15': self.elements_solid.cpenta15, 'CHEXA20': self.elements_solid.chexa20, } exclude_types = [ 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4', 'CMASS1', 'CMASS2', 'CMASS3', 'CMASS4', 'CBUSH', 'CBUSH1D', 'CBUSH2D', ] pid_data = self.get_element_ids_by_property_type( element_ids, exclude_types=exclude_types) element_ids_to_analyze = pid_data[:, 0] data2 = self.group_elements_by_property_type_and_element_type( self, pid_data) #self.model.log.debug('**data2 = %s' % data2) nelements = len(element_ids) #self.model.log.debug('nelement_ids =', nelements) eids2 = np.zeros(nelements_orig, dtype='int32') #mass = full(nelements, nan, dtype='float64') mass = np.full(nelements_orig, np.nan, dtype='float64') #self.model.log.debug('mass.shape =', mass.shape) ni = 0 self.model.log.debug('data2 = %s' % data2) for (pid, etype), element_ids in data2.items(): #self.model.log.debug('pid=%s eType=%s element_ids=%s' % (pid, eType, element_ids)) elements = type_map[etype] i = np.searchsorted(elements.element_id, element_ids) n = len(i) eids2[ni:ni + n] = elements.element_id[i] if pid == 0: # CONROD pass else: self.model.log.debug('*cat pid = %s' % pid) props = self.get_properties([pid]) if len(props) == 0: # the property doesn't exist self.model.log.debug( 'Property %i does not exist and is needed by %s eid=%i' % (pid, etype, element_ids[0])) ni += n #print('props = %s' % props) continue # we only get one property at a time prop = props[0] #print(' prop = %s' % str(prop).rstrip()) elements = type_map[etype] i = np.searchsorted(elements.element_id, element_ids) n = len(i) #print('ielements = %s' % i) if etype in [ 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', ]: pass elif etype in ['CROD', 'CONROD', 'CBAR', 'CBEAM']: msg = ', which is required for %ss' % etype n1 = self.get_nodes(elements.node_ids[i, 0], xyz_cid0, msg=msg) n2 = self.get_nodes(elements.node_ids[i, 1], xyz_cid0, msg=msg) length = np.linalg.norm(n2 - n1, axis=1) #print('prop = %s' % prop) #print(' calling get_mass_per_area for pid=%s' % (pid)) if etype == 'CONROD': rho = self.model.materials.get_density_by_material_id( elements.material_id) mass[ni:ni + n] = length * elements.A[i] * rho[i] + elements.nsm[i] else: mpl = prop.get_mass_per_length_by_property_id() mass[ni:ni + n] = mpl * length del prop elif etype in ['CTRIA3', 'CQUAD4', 'CSHEAR']: if etype == 'CTRIA3': n1, n2, n3 = (elements.node_ids[i, 0], elements.node_ids[i, 1], elements.node_ids[i, 2]) n1 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n1), :] n2 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n2), :] n3 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n3), :] area = _ctria3_normal_A(n1, n2, n3, calculate_area=True, normalize=False)[1] elif etype in ['CQUAD4', 'CSHEAR']: n1, n2, n3, n4 = (elements.node_ids[i, 0], elements.node_ids[i, 1], elements.node_ids[i, 2], elements.node_ids[i, 3]) n1 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n1), :] n2 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n2), :] n3 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n3), :] n4 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n4), :] area = _cquad4_normal_A(n1, n2, n3, n4, calculate_area=True, normalize=False)[1] else: self.model.log.debug( "Element.get_mass doesn't support %s; try %s.get_mass" % (etype, etype)) ni += n continue #print('prop = %s' % prop) #print(' calling get_mass_per_area for pid=%s' % (pid)) mpa = prop.get_mass_per_area_by_property_id() mass[ni:ni + n] = mpa * area del prop elif etype in [ 'CTETRA4', 'CTETRA10', 'CPENTA6', 'CPENTA15', 'CHEXA8', 'CHEXA20' ]: rho = prop.get_density_by_property_id() del prop if etype in ['CTETRA4', 'CTETRA10']: n1, n2, n3, n4 = (elements.node_ids[i, 0], elements.node_ids[i, 1], elements.node_ids[i, 2], elements.node_ids[i, 3]) n1 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n1), :] n2 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n2), :] n3 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n3), :] n4 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n4), :] volumei = np.zeros(n, self.model.float_fmt) i = 0 for n1i, n2i, n3i, n4i in zip(n1, n2, n3, n4): volumei[i] = volume4(n1i, n2i, n3i, n4i) i += 1 elif etype in ['CPENTA6', 'CPENTA15']: n1, n2, n3, n4, n5, n6 = ( elements.node_ids[i, 0], elements.node_ids[i, 1], elements.node_ids[i, 2], elements.node_ids[i, 3], elements.node_ids[i, 4], elements.node_ids[i, 5], ) n1 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n1), :] n2 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n2), :] n3 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n3), :] n4 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n4), :] n5 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n5), :] n6 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n6), :] (area1, centroid1) = tri_area_centroid(n1, n2, n3) (area2, centroid2) = tri_area_centroid(n4, n5, n6) volumei = (area1 + area2) / 2. * np.linalg.norm( centroid1 - centroid2, axis=1) elif etype in ['CHEXA8', 'CHEXA20']: n1, n2, n3, n4, n5, n6, n7, n8 = ( elements.node_ids[i, 0], elements.node_ids[i, 1], elements.node_ids[i, 2], elements.node_ids[i, 3], elements.node_ids[i, 4], elements.node_ids[i, 5], elements.node_ids[i, 6], elements.node_ids[i, 7], ) n1 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n1), :] n2 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n2), :] n3 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n3), :] n4 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n4), :] n5 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n5), :] n6 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n6), :] n7 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n7), :] n8 = xyz_cid0[ self.model.grid.get_node_index_by_node_id(n8), :] (area1, centroid1) = quad_area_centroid(n1, n2, n3, n4) (area2, centroid2) = quad_area_centroid(n5, n6, n7, n8) volumei = (area1 + area2) / 2. * np.linalg.norm( centroid1 - centroid2, axis=1) else: msg = "Element.get_mass doesn't support %s; try %s.get_mass" % ( etype, etype) self.model.log.debug(msg) ni += n continue mass[ni:ni + n] = volumei * rho else: msg = " Element.get_mass doesn't support %s; try %s.get_mass" % ( etype, etype) self.model.log.debug(msg) msg = "Element.get_mass doesn't support %s; try %s.get_mass" % ( etype, etype) raise NotImplementedError(msg) #self.model.log.debug("") ni += n #self.model.log.debug('data2 = %s' % data2) diff = np.setdiff1d(element_ids_orig, element_ids_to_analyze) #print('A = %s' % element_ids_orig) #print('B = %s' % element_ids_to_analyze) #print('A-B = %s' % (diff)) #print('eids2 = %s' % eids2) #if len(diff): #print('****diff = %s' % list(diff)) #print('eids out = %s' % eids2) #print('len(eids2) =', len(eids2)) #print('len(diff) =', len(diff)) eids2[ni:] = diff if sort_output: i = np.argsort(eids2) eids2 = eids2[i] mass = mass[i] return eids2, mass