Source code for pyvcad_attribute_resolver.modules.j750_modulus_toughness

"""J750 modulus+toughness to volume-fractions conversion registrations."""

import pyvcad as pv

from pyvcad_attribute_resolver.registry import register_conversion

from .data import (
    DEFAULT_LOOKUP_TABLE_PATH,
    validate_solution,
    generate_lookup_table_file,
    generate_reachable_region_plot,
    interpolate_lookup_table,
    load_lookup_table,
    solve_volume_fractions,
    compute_achieved_properties,
)


def _resolve_material_ids(material_defs, soft_material, rigid_material, liquid_material):
    return (
        material_defs.id(soft_material),
        material_defs.id(rigid_material),
        material_defs.id(liquid_material),
    )


def _build_lookup_entries(soft_id, rigid_id, liquid_id, lookup_table_path):
    lookup_table = load_lookup_table(lookup_table_path)
    modulus_axis_mpa = lookup_table["modulus_axis_mpa"]
    toughness_axis_mj_per_m3 = lookup_table["toughness_axis_mj_per_m3"]
    fraction_grid = lookup_table["fractions"]
    valid_grid = lookup_table["valid"]

    entries = []
    for toughness_index, toughness_mj_per_m3 in enumerate(toughness_axis_mj_per_m3):
        for modulus_index, modulus_mpa in enumerate(modulus_axis_mpa):
            fractions = {
                soft_id: float(fraction_grid[toughness_index, modulus_index, 0]),
                rigid_id: float(fraction_grid[toughness_index, modulus_index, 1]),
                liquid_id: float(fraction_grid[toughness_index, modulus_index, 2]),
            }
            entry = pv.LookupTableEntry(
                [float(modulus_mpa), float(toughness_mj_per_m3)],
                fractions,
            )
            entry.is_valid = bool(valid_grid[toughness_index, modulus_index])
            entries.append(entry)
    return entries


def _lut_factory(soft_id, rigid_id, liquid_id, lookup_table_path):
    entries = _build_lookup_entries(soft_id, rigid_id, liquid_id, lookup_table_path)

    def _factory():
        return pv.LookupTableConverter(
            [pv.DefaultAttributes.MODULUS, pv.DefaultAttributes.TOUGHNESS],
            [pv.DefaultAttributes.VOLUME_FRACTIONS],
            entries,
            pv.InterpolationMode.LINEAR,
        )

    return _factory


[docs] def register_j750_modulus_toughness_conversions( material_defs=None, rigid_material="VeroBlack", soft_material="Agilus30Clr", liquid_material="M.Cleanser", lookup_table_path=None, ): """Register the J750 modulus+toughness to volume-fractions conversion. The bundled lookup table assumes modulus values are provided in MPa and toughness values are provided in MJ/m^3. The shipped table is generated from the legacy C++ inverse model using the default 0.30 liquid cap. To use a different liquid cap or table resolution, generate a new table file with :func:`generate_j750_modulus_toughness_lookup_table` and pass its path via ``lookup_table_path``. """ if material_defs is None: material_defs = pv.j750_materials if lookup_table_path is None: lookup_table_path = DEFAULT_LOOKUP_TABLE_PATH soft_id, rigid_id, liquid_id = _resolve_material_ids( material_defs, soft_material, rigid_material, liquid_material, ) register_conversion( source="modulus", target="volume_fractions", converter_factory=_lut_factory( soft_id, rigid_id, liquid_id, lookup_table_path, ), name="j750_modulus_toughness_to_volume_fractions", priority=0, tags=["j750_modulus_toughness"], required_inputs=["modulus", "toughness"], )
[docs] def generate_j750_modulus_toughness_lookup_table( output_path=None, table_size=128, max_liquid_volume=0.30, fail_threshold=0.05, ): """Generate a J750 modulus+toughness lookup-table JSON file.""" return generate_lookup_table_file( output_path=output_path, table_size=table_size, max_liquid_volume=max_liquid_volume, fail_threshold=fail_threshold, )
[docs] def generate_j750_modulus_toughness_reachable_region_plot( output_path, lookup_table_path=None, table_size=128, max_liquid_volume=0.30, fail_threshold=0.05, fraction_steps=181, ): """Generate the reachable-region validation plot used in the docs.""" return generate_reachable_region_plot( output_path=output_path, lookup_table_path=lookup_table_path, table_size=table_size, max_liquid_volume=max_liquid_volume, fail_threshold=fail_threshold, fraction_steps=fraction_steps, )
__all__ = [ "register_j750_modulus_toughness_conversions", "generate_j750_modulus_toughness_lookup_table", "generate_j750_modulus_toughness_reachable_region_plot", "solve_volume_fractions", "compute_achieved_properties", "interpolate_lookup_table", "load_lookup_table", "validate_solution", ]