Source code for otaf.example_models.models_2_D._model_2D_16_dof

from __future__ import annotations

__author__ = "Kramer84"
__all__ = [
    "get_system_of_constraints_assembly_model",
    "get_distribution_params",
    "eval_scaled_credal_set_constraints",
    "get_scaled_credal_set_constraints_function",
    "dim",
    "sample_multiplier",
    "no_tol", 
]
import numpy as np
import sympy as sp

import otaf
from otaf.tolerances import sigma_delta_3D_plane


def get_assembly_data(
    hM: float = 10.0,
    hF: float = 10.2,
    L1: float = 30.0,
    L2: float = 70.0,
    L3: float = 30.0,
    lM: float = 10.0,
    lF: float = 10.2,
) -> dict[str, dict[str, Any]]:
    """Generate the system configuration data for the assembly.

    Parameters
    ----------
    hM : float, default 10.0
        Height parameter for the male component.
    hF : float, default 10.2
        Height parameter for the female component.
    L1 : float, default 30.0
        Length of the first section.
    L2 : float, default 70.0
        Length of the second section.
    L3 : float, default 30.0
        Length of the third section.
    lM : float, default 10.0
        Interface length for the male component.
    lF : float, default 10.2
        Interface length for the female component.

    Returns
    -------
    dict
        A configuration dictionary detailing components, frames,
        points, interactions, loops, and global constraints.
    """
    P1A0, P1A1, P1A2 = (
        np.array((L1 - lM / 2, hM / 2, 0.0)),
        np.array((L1 - lM / 2, 0, 0.0)),
        np.array((L1 - lM / 2, hM, 0.0)),
    )
    P1B0, P1B1, P1B2 = (
        np.array((L1 + lM / 2, hM / 2, 0.0)),
        np.array((L1 + lM / 2, 0, 0.0)),
        np.array((L1 + lM / 2, hM, 0.0)),
    )
    P1C0, P1C1, P1C2 = (
        np.array((L1 + L2 - lM / 2, hM / 2, 0.0)),
        np.array((L1 + L2 - lM / 2, 0, 0.0)),
        np.array((L1 + L2 - lM / 2, hM, 0.0)),
    )
    P1D0, P1D1, P1D2 = (
        np.array((L1 + L2 + lM / 2, hM / 2, 0.0)),
        np.array((L1 + L2 + lM / 2, 0, 0.0)),
        np.array((L1 + L2 + lM / 2, hM, 0.0)),
    )
    P1E0, P1E1 = (np.array((0.0, 0.0, 0.0)), np.array((L1 + L2 + L3, 0.0, 0.0)))
    P2A0, P2A1, P2A2 = (
        np.array((L1 - lF / 2, hF / 2, 0.0)),
        np.array((L1 - lF / 2, 0, 0.0)),
        np.array((L1 - lF / 2, hF, 0.0)),
    )
    P2B0, P2B1, P2B2 = (
        np.array((L1 + lF / 2, hF / 2, 0.0)),
        np.array((L1 + lF / 2, 0, 0.0)),
        np.array((L1 + lF / 2, hF, 0.0)),
    )
    P2C0, P2C1, P2C2 = (
        np.array((L1 + L2 - lF / 2, hF / 2, 0.0)),
        np.array((L1 + L2 - lF / 2, 0, 0.0)),
        np.array((L1 + L2 - lF / 2, hF, 0.0)),
    )
    P2D0, P2D1, P2D2 = (
        np.array((L1 + L2 + lF / 2, hF / 2, 0.0)),
        np.array((L1 + L2 + lF / 2, 0, 0.0)),
        np.array((L1 + L2 + lF / 2, hF, 0.0)),
    )
    P2E0, P2E1 = (np.array((0.0, 0.0, 0.0)), np.array((L1 + L2 + L3, 0.0, 0.0)))
    R0 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    x_, y_, z_ = (R0[0], R0[1], R0[2])
    RP1b = RP1d = R0
    RP1a = RP1c = np.array([-x_, -y_, z_]).T
    RP1e = np.array([y_, -x_, z_]).T
    RP2a = RP2c = R0
    RP2b = RP2d = np.array([-x_, -y_, z_]).T
    RP2e = np.array([-y_, x_, z_]).T
    TP1cC0, TP1cC1, TP1cC2 = (
        otaf.geometry.tfrt(RP1c, P1C0),
        otaf.geometry.tfrt(RP1c, P1C1),
        otaf.geometry.tfrt(RP1c, P1C2),
    )
    TP1aA0, TP1aA1, TP1aA2 = (
        otaf.geometry.tfrt(RP1a, P1A0),
        otaf.geometry.tfrt(RP1a, P1A1),
        otaf.geometry.tfrt(RP1a, P1A2),
    )
    TP1bB0, TP1bB1, TP1bB2 = (
        otaf.geometry.tfrt(RP1b, P1B0),
        otaf.geometry.tfrt(RP1b, P1B1),
        otaf.geometry.tfrt(RP1b, P1B2),
    )
    TP1dD0, TP1dD1, TP1dD2 = (
        otaf.geometry.tfrt(RP1d, P1D0),
        otaf.geometry.tfrt(RP1d, P1D1),
        otaf.geometry.tfrt(RP1d, P1D2),
    )
    TP1eE0, TP1eE1 = (otaf.geometry.tfrt(RP1e, P1E0), otaf.geometry.tfrt(RP1e, P1E1))
    TP2aA0, TP2aA1, TP2aA2 = (
        otaf.geometry.tfrt(RP2a, P2A0),
        otaf.geometry.tfrt(RP2a, P2A1),
        otaf.geometry.tfrt(RP2a, P2A2),
    )
    TP2cC0, TP2cC1, TP2cC2 = (
        otaf.geometry.tfrt(RP2c, P2C0),
        otaf.geometry.tfrt(RP2c, P2C1),
        otaf.geometry.tfrt(RP2c, P2C2),
    )
    TP2bB0, TP2bB1, TP2bB2 = (
        otaf.geometry.tfrt(RP2b, P2B0),
        otaf.geometry.tfrt(RP2b, P2B1),
        otaf.geometry.tfrt(RP2b, P2B2),
    )
    TP2dD0, TP2dD1, TP2dD2 = (
        otaf.geometry.tfrt(RP2d, P2D0),
        otaf.geometry.tfrt(RP2d, P2D1),
        otaf.geometry.tfrt(RP2d, P2D2),
    )
    TP2eE0, TP2eE1 = (otaf.geometry.tfrt(RP2e, P2E0), otaf.geometry.tfrt(RP2e, P2E1))
    system_data = {
        "PARTS": {
            "1": {
                "a": {
                    "FRAME": RP1a,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"A0": P1A0, "A1": P1A1, "A2": P1A2},
                    "INTERACTIONS": ["P2a"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "b": {
                    "FRAME": RP1b,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"B0": P1B0, "B1": P1B1, "B2": P1B2},
                    "INTERACTIONS": ["P2b"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "c": {
                    "FRAME": RP1c,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"C0": P1C0, "C1": P1C1, "C2": P1C2},
                    "INTERACTIONS": ["P2c"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "d": {
                    "FRAME": RP1d,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"D0": P1D0, "D1": P1D1, "D2": P1D2},
                    "INTERACTIONS": ["P2d"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "e": {
                    "FRAME": RP1e,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["PERFECT"],
                    "POINTS": {"E0": P1E0, "E1": P1E1},
                    "INTERACTIONS": ["P2e"],
                    "CONSTRAINTS_G": ["SLIDING"],
                },
            },
            "2": {
                "a": {
                    "FRAME": RP2a,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"A0": P2A0, "A1": P2A1, "A2": P2A2},
                    "INTERACTIONS": ["P1a"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "b": {
                    "FRAME": RP2b,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"B0": P2B0, "B1": P2B1, "B2": P2B2},
                    "INTERACTIONS": ["P1b"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "c": {
                    "FRAME": RP2c,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"C0": P2C0, "C1": P2C1, "C2": P2C2},
                    "INTERACTIONS": ["P1c"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "d": {
                    "FRAME": RP2d,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["NONE"],
                    "POINTS": {"D0": P2D0, "D1": P2D1, "D2": P2D2},
                    "INTERACTIONS": ["P1d"],
                    "CONSTRAINTS_G": ["FLOATING"],
                },
                "e": {
                    "FRAME": RP2e,
                    "TYPE": "plane",
                    "CONSTRAINTS_D": ["PERFECT"],
                    "POINTS": {"E0": P2E0, "E1": P2E1},
                    "INTERACTIONS": ["P1e"],
                    "CONSTRAINTS_G": ["SLIDING"],
                },
            },
        },
        "LOOPS": {
            "COMPATIBILITY": {
                "L0": "P1eE0 -> P2eE0 -> P2aA0 -> P1aA0",
                "L1": "P1eE0 -> P2eE0 -> P2dD0 -> P1dD0",
                "L2": "P1cC0 -> P2cC0 -> P2bB0 -> P1bB0",
                "L3": "P1bB0 -> P2bB0 -> P2aA0 -> P1aA0",
            }
        },
        "GLOBAL_CONSTRAINTS": "2D_NZ",
    }
    return system_data


def get_assembly_data_processor_object(
    system_data: dict[str, Any] | None = None,
) -> otaf.AssemblyDataProcessor:
    """Initialize and prepare an AssemblyDataProcessor instance.

    Parameters
    ----------
    system_data : dict, optional
        The configuration dictionary containing assembly definitions.
        If None, default assembly data is generated.

    Returns
    -------
    otaf.AssemblyDataProcessor
        The data processor with generated expanded loops.
    """
    SDA = otaf.AssemblyDataProcessor(system_data)
    SDA.generate_expanded_loops()
    return SDA


def get_compatibility_loop_handling_object(
    SDA: otaf.AssemblyDataProcessor | None = None,
) -> otaf.CompatibilityLoopHandling:
    """Create a CompatibilityLoopHandling instance for assembly loops.

    Parameters
    ----------
    SDA : otaf.AssemblyDataProcessor, optional
        The assembly data processor. If None, a default instance
        is instantiated.

    Returns
    -------
    otaf.CompatibilityLoopHandling
        The configured compatibility loop handler object.
    """
    SDA = (
        SDA if SDA is not None else get_assembly_data_processor_object(get_assembly_data())
    )
    CLH = otaf.CompatibilityLoopHandling(SDA)
    return CLH


def get_interface_loop_handling_object(
    SDA: otaf.AssemblyDataProcessor | None = None,
    CLH: otaf.CompatibilityLoopHandling | None = None,
) -> otaf.InterfaceLoopHandling:
    """Create an InterfaceLoopHandling instance with set resolution.

    Parameters
    ----------
    SDA : otaf.AssemblyDataProcessor, optional
        The assembly data processor. If None, a default hierarchy
        is created along with `CLH`.
    CLH : otaf.CompatibilityLoopHandling, optional
        The compatibility loop handler. If None, a default hierarchy
        is created along with `SDA`.

    Returns
    -------
    otaf.InterfaceLoopHandling
        The initialized interface loop handler object.
    """
    if not SDA or not CLH:
        SDA = get_assembly_data_processor_object(get_assembly_data())
        CLH = get_compatibility_loop_handling_object(SDA)
    ILH = otaf.InterfaceLoopHandling(SDA, CLH, circle_resolution=20)
    return ILH


[docs] def get_system_of_constraints_assembly_model( hM: float = 10.0, hF: float = 10.2, L1: float = 30.0, L2: float = 70.0, L3: float = 30.0, lM: float = 10.0, lF: float = 10.2, ) -> otaf.SystemOfConstraintsAssemblyModel: """Construct the complete system of constraints assembly model. Parameters ---------- hM : float, default 10.0 Height parameter for the male component. hF : float, default 10.2 Height parameter for the female component. L1 : float, default 30.0 Length of the first section. L2 : float, default 70.0 Length of the second section. L3 : float, default 30.0 Length of the third section. lM : float, default 10.0 Interface length for the male component. lF : float, default 10.2 Interface length for the female component. Returns ------- otaf.SystemOfConstraintsAssemblyModel The initialized assembly model with embedded optimization variables. """ SDA = get_assembly_data_processor_object(get_assembly_data(hM, hF, L1, L2, L3, lM, lF)) CLH = get_compatibility_loop_handling_object(SDA) ILH = get_interface_loop_handling_object(SDA, CLH) compatibility_expressions = CLH.get_compatibility_expressions() interface_constraints = ILH.get_interface_expressions() SOCAM = otaf.SystemOfConstraintsAssemblyModel( compatibility_expressions, interface_constraints ) SOCAM.embedOptimizationVariable() return SOCAM
[docs] def get_distribution_params( tol: float = 0.16, capa: float = 1.0, hM: float = 10.0, hF: float = 10.2, ) -> tuple[Any, list[sp.Symbol], np.ndarray, np.ndarray]: """Compute defect distribution parameters and variance vectors. Parameters ---------- tol : float, default 0.16 Tolerance limit value used to compute standard deviations. capa : float, default 1.0 Process capability index factor. hM : float, default 10.0 Height parameter for the male component. hF : float, default 10.2 Height parameter for the female component. Returns ------- RandDeviationVect : otaf.distribution.ComposedDistribution The joint normal defect distribution model. deviation_symbols : list of sympy.Symbol The symbolic tracking parameters for spatial deviations. max_std_vect : np.ndarray A 1D array of calculated maximum standard deviations. np.ndarray A 1D array of zero-initialized mean parameter offsets. """ deviation_symbols = list( sp.symbols( "u_d_2 gamma_d_2 u_d_3 gamma_d_3 u_d_4 gamma_d_4 u_d_5 gamma_d_5 u_d_6 gamma_d_6 u_d_7 gamma_d_7 u_d_8 gamma_d_8 u_d_9 gamma_d_9" ) ) sigma_e_pos = tol / (6 * capa) theta_max_m = tol / hM theta_max_f = tol / hF sigma_e_theta_m = 2 * theta_max_m / (6 * capa) sigma_e_theta_f = 2 * theta_max_f / (6 * capa) RandDeviationVect = otaf.distribution.get_composed_normal_defect_distribution( defect_names=deviation_symbols, sigma_dict={ "gamma_d_2": sigma_e_theta_f, "gamma_d_3": sigma_e_theta_m, "gamma_d_4": sigma_e_theta_f, "gamma_d_5": sigma_e_theta_m, "gamma_d_6": sigma_e_theta_m, "gamma_d_7": sigma_e_theta_f, "gamma_d_8": sigma_e_theta_f, "gamma_d_9": sigma_e_theta_m, "u": sigma_e_pos, }, ) max_std_vect = np.array( [ sigma_e_pos, sigma_e_theta_f, sigma_e_pos, sigma_e_theta_m, sigma_e_pos, sigma_e_theta_f, sigma_e_pos, sigma_e_theta_m, sigma_e_pos, sigma_e_theta_m, sigma_e_pos, sigma_e_theta_f, sigma_e_pos, sigma_e_theta_f, sigma_e_pos, sigma_e_theta_m, ] ) return (RandDeviationVect, deviation_symbols, max_std_vect, np.array([0.0] * 16))
dim = 16 sample_multiplier = np.eye(dim) no_tol = False
[docs] def eval_scaled_credal_set_constraints( x_scaled: np.ndarray, max_std_vect: np.ndarray, tracker: Any | None = None, experiment_key: Any | None = None, tol: float = 0.16, capa: float = 1.0, hM: float = 10.0, hF: float = 10.2, ) -> np.ndarray: """Map scaled deviations to real values and evaluate constraints. Parameters ---------- x_scaled : np.ndarray The scaled standard deviation vector inputs. max_std_vect : np.ndarray The upper-bound limits for standard deviation mapping. tracker : Any, optional Data logging tracker instance. Default is None. experiment_key : Any, optional Unique identifier key for tracking logs. Default is None. tol : float, default 0.16 The baseline design tolerance. capa : float, default 1.0 The process capability standard multiplier. hM : float, default 10.0 Height parameter for the male component. hF : float, default 10.2 Height parameter for the female component. Returns ------- np.ndarray The calculated constraint evaluation bounds array. """ target = tol / (6 * capa) constraint1 = ( sigma_delta_3D_plane(hF / 2, 0, x_std[0], 0, x_std[1]) - target ) / target constraint2 = ( sigma_delta_3D_plane(hM / 2, 0, x_std[2], 0, x_std[3]) - target ) / target constraint3 = ( sigma_delta_3D_plane(hF / 2, 0, x_std[4], 0, x_std[5]) - target ) / target constraint4 = ( sigma_delta_3D_plane(hM / 2, 0, x_std[6], 0, x_std[7]) - target ) / target constraint5 = ( sigma_delta_3D_plane(hM / 2, 0, x_std[8], 0, x_std[9]) - target ) / target constraint6 = ( sigma_delta_3D_plane(hF / 2, 0, x_std[10], 0, x_std[11]) - target ) / target constraint7 = ( sigma_delta_3D_plane(hF / 2, 0, x_std[12], 0, x_std[13]) - target ) / target constraint8 = ( sigma_delta_3D_plane(hM / 2, 0, x_std[14], 0, x_std[15]) - target ) / target return np.array( [ constraint1, constraint2, constraint3, constraint4, constraint5, constraint6, constraint7, constraint8, ] )
def get_scaled_credal_set_constraints_function( max_std_vect: np.ndarray, tracker: Any | None = None, experiment_key: Any | None = None, tol: float = 0.16, capa: float = 1.0, hM: float = 10.0, hF: float = 10.2, ) -> Callable[[np.ndarray], np.ndarray]: """Generate a wrapped lambda function for scaled constraints. Parameters ---------- max_std_vect : np.ndarray The upper-bound limits for standard deviation mapping. tracker : Any, optional Data logging tracker instance. Default is None. experiment_key : Any, optional Unique identifier key for tracking logs. Default is None. tol : float, default 0.16 The baseline design tolerance. capa : float, default 1.0 The process capability index multiplier. hM : float, default 10.0 Height parameter for the male component. hF : float, default 10.2 Height parameter for the female component. Returns ------- Callable[[np.ndarray], np.ndarray] A single-argument function mapping `x_scaled` to its evaluated constraint array. """ x_real = x_scaled * max_std_vect constraint_array = eval_credal_set_constraints( x_real, tol=tol, capa=capa, hM=hM, hF=hF ) if tracker: tracker.update_constraint_data( exp_key=experiment_key, x=x_scaled, constraints=constraint_array ) return constraint_array
[docs] def get_scaled_credal_set_constraints_function( max_std_vect, tracker=None, experiment_key=None, tol=0.16, capa=1.0, hM=10, hF=10.2 ): return lambda x_scaled: eval_scaled_credal_set_constraints( x_scaled, max_std_vect, tracker, experiment_key, tol=tol, capa=capa, hM=hM, hF=hF, )