def __init__( self, pos: Tuple[float, float, float], size: Tuple[float, float, float], subdiv: Union[int, Tuple[int, int, int]], mass: float = 0, sphere_swept_thickness: Optional[float] = 0.2, ) -> None: # use the same subdivision on all axis if not isinstance(subdiv, tuple): subdiv = (subdiv, ) * 3 self._nodes = None # store nodes in a 3d list, indeces _nodes[x][y][z] self._elements = None self._sphere_swept_thickness = sphere_swept_thickness self._pos = pos self._size = size self._subdiv = subdiv self._mass = mass self._material = fea.ChContinuumElastic( ) # elastic: no permanet deformation self._contact_surface = None # fea.ChContactSurfaceMesh() self._contact_material = chrono.ChMaterialSurfaceSMC() self._mesh = fea.ChMesh()
bbmin, bbmax = chrono.ChVectorD(), chrono.ChVectorD() shape.GetTotalAABB(bbmin, bbmax) bbmin, bbmax = eval(str(bbmin)), eval(str(bbmax)) print(bbmin, bbmax) print(shape.GetPos()) bb_dx = bbmax[0] - bbmin[0] bb_dy = bbmax[1] - bbmin[1] bb_dz = bbmax[2] - bbmin[2] # Align shape to the center of axis system shape.SetPos( chrono.ChVectorD(-bb_dx / 2. - bbmin[0], -bb_dy / 2. - bbmin[1], -bb_dz / 2. - bbmin[2])) mysystem.Add(shape) # Inferred mesh inf_mesh_init = fea.ChMesh() inf_mesh = fea.ChMesh() inf_mesh_big = fea.ChMesh() # Chrono visualization viz_inf_mesh_init = fea.ChVisualizationFEAmesh(inf_mesh_init) viz_inf_mesh_init.SetWireframe(True) viz_inf_mesh_init.SetFEMglyphType( fea.ChVisualizationFEAmesh.E_GLYPH_NODE_DOT_POS) viz_inf_mesh_init.SetSymbolsThickness(1. * UNIT_FACTOR) inf_mesh_init.AddAsset(viz_inf_mesh_init) mysystem.AddMesh(inf_mesh_init) viz_inf_mesh = fea.ChVisualizationFEAmesh(inf_mesh) viz_inf_mesh.SetWireframe(True) viz_inf_mesh.SetFEMglyphType(fea.ChVisualizationFEAmesh.E_GLYPH_NODE_DOT_POS)
print("Example: FEA of the Jeffcott rotor passing through resonance.") # The path to the Chrono data directory containing various assets (meshes, textures, data files) # is automatically set, relative to the default location of this demo. # If running from a different directory, you must change the path to the data directory with: #chrono.SetChronoDataPath('path/to/data') # --------------------------------------------------------------------- # # Create the simulation system and add items # # Create a Chrono::Engine physical system my_system = chrono.ChSystemNSC() my_mesh = fea.ChMesh() my_system.Add(my_mesh) my_mesh.SetAutomaticGravity( True, 2 ) # for max precision in gravity of FE, at least 2 integration points per element when using cubic IGA my_system.Set_G_acc(chrono.ChVectorD(0, -9.81, 0)) beam_L = 6 beam_ro = 0.050 beam_ri = 0.045 CH_C_PI = 3.1456 # Create a section, i.e. thickness and material properties # for beams. This will be shared among some beams.
def __init__(self, sys, gravity, material, width, height, position_base, position_tip, damping, elements, torque=10, origin=True, stator_constraint=None): self.mesh = fea.ChMesh() self.mesh.SetAutomaticGravity(gravity) self.section = fea.ChBeamSectionAdvanced() self.section.SetAsRectangularSection(width, height) self.section.SetYoungModulus(material.modulus) self.section.SetGshearModulus(material.shear) self.section.SetDensity(material.density) self.section.SetBeamRaleyghDamping(damping) self.position_base = chrono.ChVectorD(*position_base) self.position_tip = chrono.ChVectorD(*position_tip) self.builder = fea.ChBuilderBeamEuler( ) #Use the beam builder assembly method to assembly each beam self.builder.BuildBeam( self.mesh, self.section, elements, self.position_base, self.position_tip, chrono.ChVectorD(0, 1, 0), ) self.stator = chrono.ChBodyEasyCylinder(0.01, 0.01, 1000) self.stator.SetPos(self.position_base) self.stator.SetBodyFixed(origin) self.frame = chrono.ChFrameD(self.stator) sys.Add(self.stator) if (origin == False) and ( stator_constraint is not None ): #If the beam is not located at the origin, it must need to be constrained to another beam self.constraint = chrono.ChLinkMateGeneric() self.constraint.Initialize(self.stator, stator_constraint, False, chrono.ChFrameD(self.stator), chrono.ChFrameD(stator_constraint)) self.constraint.SetConstrainedCoords(True, True, True, True, True, True) sys.Add(self.constraint) self.frame = chrono.ChFrameD(self.stator) self.rotor = chrono.ChBodyEasyCylinder(0.011, 0.011, 1000) self.rotor.SetPos(self.position_base) sys.Add(self.rotor) self.frame.SetRot( chrono.Q_from_AngAxis(chrono.CH_C_PI_2, chrono.VECT_X) ) #Rotate the direction of rotation to be planar (x-z plane) self.motor = chrono.ChLinkMotorRotationTorque() self.motor.Initialize(self.rotor, self.stator, self.frame) sys.Add(self.motor) self.motor.SetTorqueFunction(chrono.ChFunction_Const(torque)) self.arm_base = (self.builder.GetLastBeamNodes().front()) self.arm_tip = (self.builder.GetLastBeamNodes().back()) self.mate = chrono.ChLinkMateGeneric() self.mate.Initialize(self.builder.GetLastBeamNodes().front(), self.rotor, chrono.ChFrameD(self.builder.GetLastBeamNodes( ).front().GetPos())) #constrain beam to rotor self.mate.SetConstrainedCoords( True, True, True, True, True, True ) #constraints must be in format: (True,True,True,True,True,True) to constrain x,y,z,rotx,roty,rotz coordinates sys.Add(self.mate) self.visual = fea.ChVisualizationFEAmesh(self.mesh) self.visual.SetFEMdataType( fea.ChVisualizationFEAmesh.E_PLOT_ELEM_BEAM_MZ) self.visual.SetColorscaleMinMax(-1.4, 1.4) self.visual.SetSmoothFaces(True) self.visual.SetWireframe(False) self.mesh.AddAsset(self.visual) sys.Add(self.mesh)
mcontact.SetMaterialSurface(contact_material) # Fix the extremities of the sleeve to the disks sleeve.fix_extremities(left_cyl, right_cyl, mysystem) # Extend the sleeve. It will be released after some iterations. # TODO check for a generic way of computing the expanding force sleeve.expand(1 / (NNODES_ANGLE * NNODES_LENGTH) * 7000000. * UNIT_FACTOR * bb_dx) # --------------------------------------------------------------------- # OPTIMISATION SETUP # Prepare the visualization of the optimisation algorithm # Mesh computed by the physical simulation target_mesh = fea.ChMesh() # The mesh that will approximate the target mesh inf_mesh = fea.ChMesh() # # --------------------------------------------------------------------- # # VISUALIZATION mvisualizeClothcoll = fea.ChVisualizationFEAmesh(cloth_mesh) mvisualizeClothcoll.SetWireframe(True) mvisualizeClothcoll.SetFEMglyphType( fea.ChVisualizationFEAmesh.E_GLYPH_NODE_DOT_POS) mvisualizeClothcoll.SetSymbolsThickness(1. * UNIT_FACTOR) #cloth_mesh.AddAsset(mvisualizeClothcoll) viz_cloth = fea.ChVisualizationFEAmesh(inf_mesh) viz_cloth.SetWireframe(True) viz_cloth.SetFEMglyphType(fea.ChVisualizationFEAmesh.E_GLYPH_NODE_DOT_POS)
def __init__(self, length, radius, neighbours, na=MIN_NA, nl=MIN_NL, material=None, node_mass=10., sleeve_thickness=0.002, alphadamp=0.1, shift_x=0, shift_y=0, shift_z=0): """ Initialize a 3D cylinder mesh made of na x nl nodes. This forms the skeleton of the sleeve. :param length: the length of the sleeve :param radius: the radius of the sleeve :param neighbours: Number of neighbours :param na: number of nodes in the circumference :param nl: number of nodes in the length :param material: a fea.ChMaterialShellReissner material property of the mesh :param node_mass: mass of the node :param sleeve_thickness: Thickness of the sleeve :param alphadamp This is the Rayleigh "alpha" for the stiffness-proportional damping. This assumes damping forces as F=alpha*[Km]*v where [Km] is the stiffness matrix (material part, i.e.excluding geometric stiffness) and v is a vector of node speeds. Usually, alpha in the range 0.0 - 0.1 Note that the mass-proportional term of classical Rayleigh damping is not supported. :param shift_x: the sleeve displacement from the origin on x axis :param shift_y: the sleeve displacement from the origin on y axis :param shift_z: the sleeve displacement from the origin on z axis """ # Handle unrealistic values if na < 3: raise ValueError(f"Number of nodes in the circumference" f" must be >= {self.MIN_NA}.") if nl < 2: raise ValueError( f"Number of nodes in the length must be >= {self.MIN_NL}.") self.na = na self.nl = nl self.length = length self.radius = radius self.shift_x = shift_x self.shift_y = shift_y # Create the nodes and edges self.nodes, self.edges = gen_cylinder.gen_cylinder( radius, length, na, nl, neighbours, shift_x, shift_y, shift_z) # Create the mesh made of nodes and elements self.mesh = fea.ChMesh() # Create FEA nodes self.fea_nodes = [] for n in self.nodes: nodepos = tool.make_ChVectorD(n) noderot = chrono.ChQuaternionD(chrono.QUNIT) node = fea.ChNodeFEAxyzrot(chrono.ChFrameD(nodepos, noderot)) node.SetMass(node_mass) self.fea_nodes.append(node) self.mesh.AddNode(node) # Create FEA elements self.elements = [] for i in range(nl - 1): for j in range(na): # Make elements elem = fea.ChElementShellReissner4() if j == na - 1: # Connect last nodes to the first ones elem.SetNodes( self.fea_nodes[(i + 1) * na], # top right self.fea_nodes[i * na], # top left self.fea_nodes[j + i * na], # bottom left self.fea_nodes[j + (i + 1) * na] # bottom right ) else: elem.SetNodes( self.fea_nodes[j + 1 + (i + 1) * na], # top right self.fea_nodes[j + 1 + i * na], # top left self.fea_nodes[j + i * na], # bottom left self.fea_nodes[j + (i + 1) * na] # bottom right ) if material: elem.AddLayer(sleeve_thickness, 0 * chrono.CH_C_DEG_TO_RAD, material) elem.SetAlphaDamp(alphadamp) elem.SetAsNeutral() self.mesh.AddElement(elem) self.elements.append(elem)
mcube = chrono.ChBodyEasyBox(0.1, 0.1, 0.1, 2700, True, True, mysurfmaterial) mcube.SetPos(chrono.ChVectorD(0.6, 0.5, 0.6)) my_system.Add(mcube) msphere = chrono.ChBodyEasySphere(0.1, 2700, True, True, mysurfmaterial) msphere.SetPos(chrono.ChVectorD(0.8, 0.5, 0.6)) my_system.Add(msphere) # # Example 1: tetrahedrons, with collisions # # Create a mesh. We will use it for tetrahedrons. my_mesh = fea.ChMesh() # 1) a FEA tetrahedron(s): # Create a material, that must be assigned to each solid element in the mesh, # and set its parameters mmaterial = fea.ChContinuumElastic() mmaterial.Set_E(0.01e9) # rubber 0.01e9, steel 200e9 mmaterial.Set_v(0.3) mmaterial.Set_RayleighDampingK(0.003) mmaterial.Set_density(1000) for i in range(4): try: cdown = chrono.ChCoordsysD(chrono.ChVectorD(0, -0.4, 0)) crot = chrono.ChCoordsysD(