Source code for moldflow.boundary_conditions

# SPDX-FileCopyrightText: 2025 Autodesk, Inc.
# SPDX-License-Identifier: Apache-2.0

"""
Usage:
    BoundaryConditions Class API Wrapper
"""

from .helper import coerce_optional_dispatch
from .common import LogMessage, AnalysisType, ConstraintType
from .helper import check_type, get_enum_value
from .com_proxy import safe_com
from .logger import process_log
from .ent_list import EntList
from .vector import Vector
from .prop import Property


[docs] class BoundaryConditions: """ Wrapper for BoundaryConditions class of Moldflow Synergy. """ def __init__(self, _boundary_conditions): """ Initialize the BoundaryConditions with a BoundaryConditions instance from COM. Args: _boundary_conditions: The BoundaryConditions instance. """ process_log(__name__, LogMessage.CLASS_INIT, locals(), name="BoundaryConditions") self.boundary_conditions = safe_com(_boundary_conditions) def _check_vector(self, vector: Vector | None) -> Vector: """ Check if the vector is valid. Args: vector (Vector | None): The vector to check. Returns: bool: True if the vector is valid, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="check_vector") if vector is None: return None if vector.x == int(vector.x): vector.x = get_enum_value(int(vector.x), ConstraintType) if vector.y == int(vector.y): vector.y = get_enum_value(int(vector.y), ConstraintType) if vector.z == int(vector.z): vector.z = get_enum_value(int(vector.z), ConstraintType) return vector
[docs] def create_entity_list(self) -> EntList: """ Creates a new entity list. Returns: EntList: The created entity list.""" process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_entity_list") result = self.boundary_conditions.CreateEntityList if result is None: return None return EntList(result)
[docs] def create_fixed_constraints(self, nodes: EntList | None, analysis: AnalysisType | int) -> int: """ Creates fixed constraints at given nodes for the specified analysis type. Args: nodes (EntList | None): The nodes to apply the fixed constraints to. analysis (AnalysisType | int): The analysis type (e.g., CORE_SHIFT). Returns: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_fixed_constraints") if nodes is not None: check_type(nodes, EntList) analysis = get_enum_value(analysis, AnalysisType) return self.boundary_conditions.CreateFixedConstraints( coerce_optional_dispatch(nodes, "ent_list"), analysis )
[docs] def create_core_shift_fixed_constraints( self, nodes: EntList | None, retract_time: float = 0 ) -> int: """ Creates core shift fixed constraints at given nodes with specified retract time. Args: nodes (EntList | None): The nodes to apply the fixed constraints to. retract_time (float): float that specified retract time. Returns: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_fixed_constraints") if nodes is not None: check_type(nodes, EntList) check_type(retract_time, (float, int)) return self.boundary_conditions.CreateFixedConstraints2( coerce_optional_dispatch(nodes, "ent_list"), retract_time )
[docs] def create_pin_constraints(self, nodes: EntList | None, analysis: AnalysisType | int) -> int: """ Creates pin constraints at given nodes for the specified analysis type. Args: nodes (EntList | None): The nodes to apply the pin constraints to. analysis (AnalysisType | int): The analysis type (e.g., WARP). Returns: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_pin_constraints") if nodes is not None: check_type(nodes, EntList) analysis = get_enum_value(analysis, AnalysisType) return self.boundary_conditions.CreatePinConstraints( coerce_optional_dispatch(nodes, "ent_list"), analysis )
[docs] def create_core_shift_pin_constraints( self, nodes: EntList | None, retract_time: float = 0 ) -> int: """ Creates core shift pin constraints at given nodes with specified retract time. Args: nodes (EntList | None): The nodes to apply the pin constraints to. retract_time (float): Optional retract time for CORE_SHIFT analysis. Returns: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_pin_constraints") if nodes is not None: check_type(nodes, EntList) check_type(retract_time, (float, int)) return self.boundary_conditions.CreatePinConstraints2( coerce_optional_dispatch(nodes, "ent_list"), retract_time )
# pylint: disable-next=R0913,R0917
[docs] def create_spring_constraints( self, nodes: EntList | None, analysis: AnalysisType | int, trans: Vector | None, rotation: Vector | None, ) -> int: """ Creates spring constraints at given nodes for the specified analysis type. Args: nodes (EntList | None): The nodes to apply the spring constraints to. analysis (AnalysisType | int): The analysis type (e.g., WARP). trans (Vector | None): Vector object that specifies translation stiffnesses rotation (Vector | None): Vector object that specifies rotation stiffnesses Returns: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_spring_constraints") if nodes is not None: check_type(nodes, EntList) analysis = get_enum_value(analysis, AnalysisType) if trans is not None: check_type(trans, Vector) if rotation is not None: check_type(rotation, Vector) return self.boundary_conditions.CreateSpringConstraints( coerce_optional_dispatch(nodes, "ent_list"), analysis, coerce_optional_dispatch(trans, "vector"), coerce_optional_dispatch(rotation, "vector"), )
# pylint: disable-next=R0913,R0917
[docs] def create_core_shift_spring_constraints( self, nodes: EntList | None, trans: Vector | None, rotation: Vector | None, retract_time: float = 0, ) -> int: """ Creates core shift spring constraints at given nodes with specified retract time. Args: nodes (EntList | None): The nodes to apply the spring constraints to. trans (Vector | None): Vector object that specifies translation stiffnesses rotation (Vector | None): Vector object that specifies rotation stiffnesses retract_time (float): float that specifies retract time Returns: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_spring_constraints") if nodes is not None: check_type(nodes, EntList) if trans is not None: check_type(trans, Vector) if rotation is not None: check_type(rotation, Vector) check_type(retract_time, (float, int)) return self.boundary_conditions.CreateSpringConstraints2( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(trans, "vector"), coerce_optional_dispatch(rotation, "vector"), retract_time, )
# pylint: disable-next=R0913,R0917
[docs] def create_general_constraints( self, nodes: EntList | None, analysis: AnalysisType | int, trans: Vector | None, rotation: Vector | None, trans_types: Vector | None, rotation_types: Vector | None, ) -> int: """ Creates general constraints at given nodes for the specified analysis type. Args: nodes (EntList | None): EntList object containing nodes to be constrained analysis (AnalysisType | int): AnalysisType or int specifying the analysis type trans (Vector | None): Vector object specifying translation constraints rotation (Vector | None): Vector object specifying rotation constraints trans_types (Vector | None): Vector object specifying translation constraint types rotation_types (Vector | None): Vector object specifying rotation constraint types Return: int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_general_constraints") if nodes is not None: check_type(nodes, EntList) if trans is not None: check_type(trans, Vector) if rotation is not None: check_type(rotation, Vector) if trans_types is not None: check_type(trans_types, Vector) if rotation_types is not None: check_type(rotation_types, Vector) analysis = get_enum_value(analysis, AnalysisType) trans_types = self._check_vector(trans_types) rotation_types = self._check_vector(rotation_types) return self.boundary_conditions.CreateGeneralConstraints2( coerce_optional_dispatch(nodes, "ent_list"), analysis, coerce_optional_dispatch(trans, "vector"), coerce_optional_dispatch(rotation, "vector"), coerce_optional_dispatch(trans_types, "vector"), coerce_optional_dispatch(rotation_types, "vector"), )
# pylint: disable-next=R0913,R0917
[docs] def create_core_shift_general_constraints( self, nodes: EntList | None, trans: Vector | None, rotation: Vector | None, trans_types: Vector | None, rotation_types: Vector | None, retract_time: float = 0, ) -> int: """ Creates core shift general constraints at given nodes with specified retract time. Args: nodes (EntList | None): EntList object containing nodes to be constrained trans (Vector | None): Vector object specifying translation constraints rotation (Vector | None): Vector object specifying rotation constraints trans_types (Vector | None): Vector object specifying translation constraint types rotation_types (Vector | None): Vector object specifying rotation constraint types retract_time (float): float specifying the retract time Return: int: Number of constraints created """ process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="create_core_shift_general_constraints", ) if nodes is not None: check_type(nodes, EntList) if trans is not None: check_type(trans, Vector) if rotation is not None: check_type(rotation, Vector) if trans_types is not None: check_type(trans_types, Vector) if rotation_types is not None: check_type(rotation_types, Vector) check_type(retract_time, (int, float)) trans_types = self._check_vector(trans_types) rotation_types = self._check_vector(rotation_types) return self.boundary_conditions.CreateGeneralConstraints3( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(trans, "vector"), coerce_optional_dispatch(rotation, "vector"), coerce_optional_dispatch(trans_types, "vector"), coerce_optional_dispatch(rotation_types, "vector"), retract_time, )
[docs] def create_nodal_loads( self, nodes: EntList | None, force: Vector | None, moment: Vector | None ) -> int: """ Creates nodal loads at selected nodes Args: nodes (EntList | None): The nodes to apply the nodal loads to. force (Vector | None): The force vector. moment (Vector | None): The moment vector. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_nodal_loads") if nodes is not None: check_type(nodes, EntList) if force is not None: check_type(force, Vector) if moment is not None: check_type(moment, Vector) return self.boundary_conditions.CreateNodalLoads( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(force, "vector"), coerce_optional_dispatch(moment, "vector"), )
[docs] def create_edge_loads(self, nodes: EntList | None, force: Vector | None) -> int: """ Creates edge loads at selected nodes Args: nodes (EntList | None): The nodes to apply the edge loads to. force (Vector | None): The force vector. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_edge_loads") if nodes is not None: check_type(nodes, EntList) if force is not None: check_type(force, Vector) return self.boundary_conditions.CreateEdgeLoads( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(force, "vector") )
[docs] def create_elemental_loads(self, tri: EntList | None, force: Vector | None) -> int: """ Creates elemental loads at selected elements Args: tri (EntList | None): The elements containing triangles to be loaded. force (Vector | None): The force vector. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_elemental_loads") if tri is not None: check_type(tri, EntList) if force is not None: check_type(force, Vector) return self.boundary_conditions.CreateElementalLoads( coerce_optional_dispatch(tri, "ent_list"), coerce_optional_dispatch(force, "vector") )
[docs] def create_pressure_loads(self, tri: EntList | None, pressure: float) -> int: """ Creates pressure loads at selected elements Args: tri (EntList | None): The elements containing triangles to be loaded. pressure (float): The pressure value. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_pressure_loads") if tri is not None: check_type(tri, EntList) check_type(pressure, (float, int)) return self.boundary_conditions.CreatePressureLoads( coerce_optional_dispatch(tri, "ent_list"), pressure )
[docs] def create_temperature_loads(self, tri: EntList | None, top: float, bottom: float) -> int: """ Creates temperature loads at selected elements Args: tri (EntList | None): The elements containing triangles to be loaded. top (float): Temperature at the top of the element. bottom (float): Temperature at the bottom of the element. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_temperature_loads") if tri is not None: check_type(tri, EntList) check_type(top, (float, int)) check_type(bottom, (float, int)) return self.boundary_conditions.CreateTemperatureLoads( coerce_optional_dispatch(tri, "ent_list"), top, bottom )
[docs] def create_volume_loads(self, tri: EntList | None, force: Vector | None) -> int: """ Creates volume loads at selected elements Args: tri (EntList | None): The elements containing triangles to be loaded. force (Vector | None): The force vector. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_volume_loads") if tri is not None: check_type(tri, EntList) if force is not None: check_type(force, Vector) return self.boundary_conditions.CreateVolumeLoads( coerce_optional_dispatch(tri, "ent_list"), coerce_optional_dispatch(force, "vector") )
[docs] def create_critical_dimension( self, node1: EntList | None, node2: EntList | None, upper: float, lower: float ) -> int: """ Creates a critical dimension between two nodes Args: node1 (EntList | None): The first node. node2 (EntList | None): The second node. upper (float): Upper Dimensional tolerance. lower (float): Lower Dimensional tolerance. Returns: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_critical_dimension") if node1 is not None: check_type(node1, EntList) if node2 is not None: check_type(node2, EntList) check_type(upper, (float, int)) check_type(lower, (float, int)) return self.boundary_conditions.CreateCriticalDimension( coerce_optional_dispatch(node1, "ent_list"), coerce_optional_dispatch(node2, "ent_list"), upper, lower, )
[docs] def create_doe_critical_dimension( self, node1: EntList | None, node2: EntList | None, name: str ) -> int: """ Creates a DOE critical dimension between two nodes Args: node1 (EntList | None): The first node. node2 (EntList | None): The second node. name (str): Name of the DOE critical dimension. Returns: int: Number of loads created """ process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="create_doe_critical_dimension" ) if node1 is not None: check_type(node1, EntList) if node2 is not None: check_type(node2, EntList) check_type(name, str) return self.boundary_conditions.CreateDoeCriticalDimension( coerce_optional_dispatch(node1, "ent_list"), coerce_optional_dispatch(node2, "ent_list"), name, )
[docs] def create_ndbc( self, nodes: EntList | None, normal: Vector | None, prop_type: int, prop: Property | None ) -> EntList: """ Creates a "generic" boundary condition such as: injection entrance, coolant entrance, gas entrance, etc. Args: nodes (EntList | None): The nodes to apply the boundary condition to. normal (Vector | None): The normal vector of the boundary condition. prop_type (int): Specifies the property type of the boundary condition prop (Property | None): Property that needs to be attached to the boundary condition. Specify Nothing to automatically create or select one for the given property type Returns: EntList: The list of NDBC that were created. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_ndbc") if nodes is not None: check_type(nodes, EntList) if normal is not None: check_type(normal, Vector) check_type(prop_type, int) if prop is not None: check_type(prop, Property) prop_disp = coerce_optional_dispatch(prop, "prop") result = self.boundary_conditions.CreateNDBC( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(normal, "vector"), prop_type, prop_disp, ) if result is None: return None return EntList(result)
[docs] def create_ndbc_at_xyz( self, coord: Vector | None, normal: Vector | None, prop_type: int, prop: Property | None ) -> EntList: """ Creates a "generic" boundary condition such as: injection entrance, coolant entrance, gas entrance, etc. Args: coord (Vector | None): The coordinates of the boundary condition. normal (Vector | None): The normal vector of the boundary condition. prop_type (int): Specifies the property type of the boundary condition prop (Property | None): Property that needs to be attached to the boundary condition. Specify Nothing to automatically create or select one for the given property type Returns: EntList: The list of NDBC that were created. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_ndbc_at_xyz") if coord is not None: check_type(coord, Vector) if normal is not None: check_type(normal, Vector) check_type(prop_type, int) if prop is not None: check_type(prop, Property) prop_disp = coerce_optional_dispatch(prop, "prop") result = self.boundary_conditions.CreateNDBCAtXYZ( coerce_optional_dispatch(coord, "vector"), coerce_optional_dispatch(normal, "vector"), prop_type, prop_disp, ) if result is None: return None return EntList(result)
[docs] def move_ndbc(self, ndbc: EntList | None, nodes: EntList | None, normal: Vector | None) -> bool: """ Moves the NDBC to the specified nodes and normal vector. Args: ndbc (EntList | None): The NDBC to move. nodes (EntList | None): The nodes to move the NDBC to. normal (Vector | None): The normal vector of the NDBC. Returns: bool: True if the NDBC was moved successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_ndbc") if ndbc is not None: check_type(ndbc, EntList) if nodes is not None: check_type(nodes, EntList) if normal is not None: check_type(normal, Vector) return self.boundary_conditions.MoveNDBC( coerce_optional_dispatch(ndbc, "ent_list"), coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(normal, "vector"), )
[docs] def move_ndbc_to_xyz( self, ndbc: EntList | None, coord: Vector | None, normal: Vector | None ) -> bool: """ Moves a boundary condition to a different position Args: ndbc (EntList | None): The NDBC to move. coord (Vector | None): The coordinates to move the NDBC to. normal (Vector | None): The normal vector of the NDBC. Returns: bool: True if successful; False if not """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_ndbc_to_xyz") if ndbc is not None: check_type(ndbc, EntList) if coord is not None: check_type(coord, Vector) if normal is not None: check_type(normal, Vector) return self.boundary_conditions.MoveNDBCToXYZ( coerce_optional_dispatch(ndbc, "ent_list"), coerce_optional_dispatch(coord, "vector"), coerce_optional_dispatch(normal, "vector"), )
[docs] def find_property(self, prop_type: int, prop_id: int) -> Property: """ Finds a property by its type and ID. Args: prop_type (int): The type of the property. prop_id (int): The ID of the property. Returns: Property: The found property. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="find_property") check_type(prop_type, int) check_type(prop_id, int) result = self.boundary_conditions.FindProperty(prop_type, prop_id) if result is None: return None return Property(result)
[docs] def set_prohibited_gate_nodes(self, nodes: EntList | None, analysis: AnalysisType | int) -> int: """ Sets the nodes as prohibited gate nodes for the specified analysis type. Args: nodes (EntList | None): The nodes to set as prohibited gate nodes. analysis (AnalysisType | int): The analysis type (e.g., WARP). Returns: int : Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_prohibited_gate_nodes") if nodes is not None: check_type(nodes, EntList) analysis = get_enum_value(analysis, AnalysisType) return self.boundary_conditions.SetProhibitedGateNodes( coerce_optional_dispatch(nodes, "ent_list"), analysis )
# pylint: disable-next=R0913,R0917
[docs] def create_one_sided_constraints( self, nodes: EntList | None, positive_trans: Vector | None, negative_trans: Vector | None, positive_trans_types: Vector | None, negative_trans_types: Vector | None, retract_time: float = 0, ) -> int: """ Creates one-sided constraints at given nodes for the specified analysis type. Args: nodes (EntList | None): The nodes to apply the one-sided constraints to. positive_trans (Vector | None): The positive translation vector. negative_trans (Vector | None): The negative translation vector. positive_trans_types (Vector | None): The positive translation types vector. negative_trans_types (Vector | None): The negative translation types vector. retract_time (float): The retract time. Returns: int: Number of constraints created """ process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="create_one_sided_constraints" ) if nodes is not None: check_type(nodes, EntList) if positive_trans is not None: check_type(positive_trans, Vector) if negative_trans is not None: check_type(negative_trans, Vector) if positive_trans_types is not None: check_type(positive_trans_types, Vector) if negative_trans_types is not None: check_type(negative_trans_types, Vector) if retract_time != 0: check_type(retract_time, (float, int)) positive_trans_types = self._check_vector(positive_trans_types) negative_trans_types = self._check_vector(negative_trans_types) return self.boundary_conditions.CreateOneSidedConstraints2( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(positive_trans, "vector"), coerce_optional_dispatch(negative_trans, "vector"), coerce_optional_dispatch(positive_trans_types, "vector"), coerce_optional_dispatch(negative_trans_types, "vector"), retract_time, ) positive_trans_types = self._check_vector(positive_trans_types) negative_trans_types = self._check_vector(negative_trans_types) return self.boundary_conditions.CreateOneSidedConstraints( coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(positive_trans, "vector"), coerce_optional_dispatch(negative_trans, "vector"), coerce_optional_dispatch(positive_trans_types, "vector"), coerce_optional_dispatch(negative_trans_types, "vector"), )