upxo.pxtal.fm_steel_3d.phases_3d module

phases_3d.py

Phase identifiers for FM (ferritic-martensitic) steel microstructures.

This is deliberately a small, standalone module: phase identity is a core pipeline concept (which PAG transformed to martensite vs. which one stayed untransformed retained austenite), not something invented at mesh-export time – so it needs to be importable by the PAG/orientation/block classes themselves, not just by mesh_exporter_3d.py.

Scope

Two phases are currently modelled, matching what generate_pags()’s retained-austenite mechanism actually produces:

PHASE_MARTENSITE (2)

Transformed PAGs: full PAG -> packet -> block (-> sub-block) hierarchy, BCC, KS-derived orientation from the PAG’s own FCC orientation.

PHASE_RETAINED_AUSTENITE (1)

Untransformed PAGs: whole-PAG granularity only (no packets/blocks/ sub-blocks), FCC, orientation = the PAG’s own orientation (the same one assigned to every PAG uniformly by assign_pag_orientations, before retained-austenite PAGs are singled out).

Other phases are physically plausible in ferritic-martensitic steel voxel models (delta-ferrite: BCC, whole-grain, independent orientation with no KS relationship to any parent PAG; bainite: BCC, partial/reduced sub-structure) but are out of scope until a real use case needs them – adding one means giving it its own id here plus its own geometry-selection and orientation-assignment path elsewhere in the pipeline.

upxo.pxtal.fm_steel_3d.phases_3d.retained_austenite_voxels_and_orientations(fm_state)[source]

Grain-level {grain_id: voxels} + {grain_id: euler_angles} for every retained-austenite grain in fm_state (PAG-covered or leftover isolated).

Shared by FMSteel3DWithOrientations/FMSteel3DWithSubBlocks (duck-typed: any object exposing grain_locs, clusters_dict, pag_orientations, retained_austenite_pag_ids, isolated_grains, get_isolated_grain_orientation works). Retained austenite has no packet/block/sub-block subdivision (see module docstring), so this is always grain granularity regardless of how far the rest of the structure has progressed through the pipeline.

Calls ensure_isolated_grain_orientations() first (if available) so the non-negotiable “every non-void feature has an orientation” guarantee holds here too, rather than silently dropping grains with no orientation.