How do I create nCode Weld definition file from Mechanical?

Options
Ayush Kumar
Ayush Kumar Member, Moderator, Employee Posts: 419
5 Likes First Anniversary Ansys Employee Solution Developer Community of Practice Member
edited August 2023 in Structures

Best Answer

  • Ayush Kumar
    Ayush Kumar Member, Moderator, Employee Posts: 419
    5 Likes First Anniversary Ansys Employee Solution Developer Community of Practice Member
    edited December 2022 Answer ✓
    Options

    The following code creates 3 points along the weldline, normals and toe vectors. The input has to be a surface named selection named “face” and an edge called “weldline”. It creates a local coordinate system at the points, with the X-Axis pointing in the normal / toe direction. If the vector directions are not as you need them, you just need to negate the vectors.

    vec_global = [1, 0, 0]  # Global X axis
    
    # Dot product of two vectors
    dot_product = lambda vec_1, vec_2: sum(map(lambda x, y: x * y, vec_1, vec_2))
    
    
    def cross_prod(a, b):
        result = [a[1]*b[2] - a[2]*b[1],
                  a[2]*b[0] - a[0]*b[2],
                  a[0]*b[1] - a[1]*b[0]]
        return result
    
    
    # Vector magnitude
    def magnitude(vec):
        res = (vec[0] ** 2 + vec[1] ** 2 + vec[2] ** 2) ** 0.5
        if res == 0.0:
            return 1.0
        return res
    
    
    def create_cs(vec_normal_in, point):
        # Euler axis - angle
        rot_rad = acos(dot_product(vec_global, vec_normal_in) / magnitude(vec_global) * magnitude(vec_normal_in))
        # Euler axis - Axis of rotation
        axis = cross_prod(vec_global, vec_normal_in)
        # Unit vector normal to Surface and Global X axis vector
        axis_unit_vec = [axis[0] / magnitude(axis), axis[1] / magnitude(axis), axis[2] / magnitude(axis)]
            
        def get_euler_angles_from_axis(euler_axis, rot_angle):
            # Euler axis–angle - quaternions
            q1 = euler_axis[0] * sin(rot_angle / 2)
            q2 = euler_axis[1] * sin(rot_angle / 2)
            q3 = euler_axis[2] * sin(rot_angle / 2)
            q4 = cos(rot_angle / 2)
        
            # Quaternion - Euler angles (z-y'-x'' intrinsic)
            roll = atan2((2 * q4 * q1 + 2 * q2 * q3), (1 - 2 * (q1 ** 2 + q2 ** 2)))
            pitch = asin(2 * (q4 * q2 - q1 * q3))
            yaw = atan2((2 * q4 * q3 + 2 * q1 * q2), (1 - 2 * (q2 ** 2 + q3 ** 2)))
        
            # Euler angles (degrees)
            roll_deg = roll * 180 / pi
            pitch_deg = pitch * 180 / pi
            yaw_deg = yaw * 180 / pi
        
            return yaw_deg, pitch_deg, roll_deg
            
        yaw_deg, pitch_deg, roll_deg = get_euler_angles_from_axis(axis_unit_vec, rot_rad)
        
        # New coordinate system creation and orientation change to match surface normal vector
        new_cs = ExtAPI.DataModel.Project.Model.CoordinateSystems.AddCoordinateSystem()
        new_cs.OriginX = Quantity(point[0], "m")
        new_cs.OriginY = Quantity(point[1], "m")
        new_cs.OriginZ = Quantity(point[2], "m")
        new_cs.RotateZ()
        new_cs.RotateY()
        new_cs.RotateX()
        new_cs.SetTransformationValue(1, yaw_deg)
        new_cs.SetTransformationValue(2, pitch_deg)
        new_cs.SetTransformationValue(3, roll_deg)
    
    # Create face and node named selections
    geom_id = ExtAPI.DataModel.GetObjectsByName("face")[0].Ids[0]
    weldline_id = ExtAPI.DataModel.GetObjectsByName("weldline")[0].Ids[0]
    weldline = ExtAPI.DataModel.AnalysisList[0].GeoData.GeoEntityById(weldline_id)
    
    mesh_data = DataModel.MeshDataByName(DataModel.MeshDataNames[0])
    my_face = DataModel.GeoData.GeoEntityById(geom_id)
    base_point = weldline.StartVertex.X, weldline.StartVertex.Y, weldline.StartVertex.Z
    end_point = weldline.EndVertex.X, weldline.EndVertex.Y, weldline.EndVertex.Z
    
    length = weldline.Length
    line_vector = ((end_point[0] - base_point[0]) / (length),
                   (end_point[1] - base_point[1]) / (length),
                   (end_point[2] - base_point[2]) / (length))
    
    # 3D line equation
    fx = lambda t: base_point[0] + line_vector[0] * t
    fy = lambda t: base_point[1] + line_vector[1] * t
    fz = lambda t: base_point[2] + line_vector[2] * t
    
    # Get equidistant points on the weldline
    n_points = 3
    delta = length / (n_points - 1)
    points = [
        [fx(t * delta), fy(t * delta), fz(t * delta)] for t in range(n_points)
    ]
    
    # Get normal vectors at all points
    vec_normal = lambda (u, v): my_face.NormalAtParam(u, v)  # Normal Vector to the face at given node
    normals = [vec_normal(my_face.ParamAtPoint(tuple(point))) for point in points]
    
    # Get Toe vector at the Vertex in plane of the face
    vec_tangent = lambda u: weldline.TangentAtParam(u)
    tangents =  [vec_tangent(weldline.ParamAtPoint(tuple(point))) for point in points]
    toe_vec = [cross_prod(tangents[index], normal) for index, normal in enumerate(normals)]
        
    for index, normal in enumerate(normals):
        create_cs(normal, points[index])
        create_cs(toe_vec[index], points[index])