upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d module

abaqus_exporter_3d.py

Partitioned Abaqus .inp writer for the twinned simple 3D pipeline.

File layout (mirrors FM Steel convention)

model_master.inp

01_nodes.inp 02_elements.inp 03a_elsets_cells.inp per-grain cell ELSETs (material assignment, no overlap) 03b_elsets_roles.inp role grouping ELSETs (Option 2, deduplication allowed) 03c_elsets_families.inp family ELSETs (Option 3, user flag) 03d_elsets_variants.inp Sigma3 variant ELSETs (Option 5, user flag) 04_nsets_bc.inp boundary-condition node sets (faces of the domain) 05_materials.inp one *Material per grain (reference UMAT layout by default) 06_sections.inp *Solid Section linking 03a ELSETs to 05 materials 07_interactions.inp none (as in the reference); extend for cohesive zones etc. 08_steps_output.inp uniaxial static step, BCs and output requests (reference)

The materials and the step follow the reference model upxo_support/collab/T25C.inp, which runs in Abaqus with the target UMAT.

ELSET naming (03a — material assignment, no voxel overlap)

es_cell_nonpart_<gid> non-participating grains es_cell_host_<gid> host grains (remaining voxels after carving) es_cell_ptwin_<gid> primary twin lamellae es_cell_stwin_a_<gid> secondary twins carved from host (outward / 2a) es_cell_stwin_b_<gid> secondary twins carved from primary twin (inward / 2b)

Material naming: MAT_CELL_NONPART_<gid>, MAT_CELL_HOST_<gid>, etc. (underscores throughout – Abaqus keyword-file names do not permit periods)

2a vs 2b distinction

twin_parent_of[gid] is a HOST grain → secondary is 2a (outward) twin_parent_of[gid] is a PRIMARY TWIN → secondary is 2b (inward)

upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d.validate_step_controls(step_time, initial_inc, min_inc, max_inc, max_increments, output_interval, element_outputs, node_outputs)[source]

Raise ValueError for step controls Abaqus would reject or that cannot produce output. Returns the output lists as tuples.

upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d.required_bc_faces(load_axis)[source]

Face node sets the uniaxial step needs: the loaded face (max face of load_axis) and the min face of every axis.

upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d.write_reference_umat_material(f, name, euler_deg, grain_number, n_depvar=1, comment=None)[source]

One *Material in the reference layout: *Depvar then *User Material, constants=6 = phi1, Phi, phi2 (degrees, wrapped into [0, 360)), the grain number, then REFERENCE_UMAT_TAIL.

upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d.write_uniaxial_static_step(f, nset_names, load_axis, displacement, step_time=80.0, initial_inc=0.01, min_inc=1e-08, max_inc=1.0, max_increments=10000, output_interval=0.5, element_outputs=('LE', 'NE', 'S', 'SDV'), node_outputs=('U',))[source]

The reference load step: static, nlgeom, the max face of load_axis displaced by displacement along that axis, the min face of every axis held in its own direction, and the output requests. The defaults are the reference model’s (REFERENCE_STEP).

Field output is written every output_interval of step time, so the output database gets step_time / output_interval + 1 frames, and Abaqus shortens increments to land on those times.

nset_names maps ‘XMIN’..’ZMAX’ to the node-set names in the model.

class upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d.GrainElementIndex(lgi, nx, ny, nz, role_map, grain_elems)[source]

Bases: object

Pre-built grain-to-element index for AbaqusExporter3D.

Depends only on (lgi, twin_role, twin_parent_of) – NOT on any export setting – so build it once via AbaqusExporter3D.build_index() and pass the result to AbaqusExporter3D(index=..., ...) for every subsequent export of the same structure, regardless of what settings change between exports.

lgi
nx
ny
nz
role_map
grain_elems
class upxo.pxtal.twinned_simple_3d.abaqus_exporter_3d.AbaqusExporter3D(lgi: numpy.ndarray | None = None, twin_role: Dict[int, str] | None = None, twin_parent_of: Dict[int, int] | None = None, all_quats: Dict[int, numpy.ndarray] | None = None, twinmake=None, voxel_size_um: float = 1.0, element_type: str = 'C3D8', material_format: str = 'reference_umat', n_depvar: int = 1, length_scale: float = 0.001, load_axis: str = 'z', applied_strain: float = 0.2, step_time: float = 80.0, write_step: bool = True, initial_inc: float = 0.01, min_inc: float = 1e-08, max_inc: float = 1.0, max_increments: int = 10000, output_interval: float = 0.5, element_outputs=('LE', 'NE', 'S', 'SDV'), node_outputs=('U',), write_role_elsets: bool = True, write_family_elsets: bool = True, write_variant_elsets: bool = True, role_enabled: Dict[str, bool] | None = None, role_prefix: Dict[str, str] | None = None, family_prefix: str = 'es_family_', variant_prefix: str = 'es_variant_ptwin_', nset_config: Dict[str, Dict[str, object]] | None = None, material_level: str = 'feature', index: GrainElementIndex | None = None)[source]

Bases: object

Writes a partitioned Abaqus input model for the twinned 3D structure.

Parameters:
  • lgi (ndarray (nz, ny, nx) or None) – Cleaned labelled grain image from StructureCleaner3D (cleaner.lgi_clean), in the twinned_simple_3d pipeline’s native axis order (axis0=Z, axis2=X – see TwinnedSimple3DBase.plot_temporal_slice_3d’s P/R/C convention comment). Transposed internally to (nx, ny, nz) before any node/ element indexing, so callers should pass cleaner.lgi_clean exactly as produced – do not pre-transpose it yourself. May be omitted (None) if index is given instead (see below).

  • twin_role (dict {gid: str}) – twin_role_clean from cleaner: one of ‘non_host’, ‘host’, ‘primary_twin’, ‘secondary_twin’.

  • twin_parent_of (dict {child_gid: parent_gid}) – twin_parent_of_clean from cleaner.

  • all_quats (dict {gid: ndarray(4,)}) – Per-grain unit quaternions [w, x, y, z].

  • twinmake (TwinGenerator3D or None) – Provides twinmake.twin_halfwidths_vox and optionally variant index when Option 5 (variant ELSETs) is requested.

  • voxel_size_um (float) – Physical voxel edge length in microns for node coordinate output.

  • element_type (str) – Abaqus element type, one of SUPPORTED_ELEMENT_TYPES: ‘C3D8’ (default; one linear hex brick per voxel) or ‘C3D4’ (six linear tetrahedra per voxel). Element sets list the elements of every voxel they contain, so they hold six times as many ids for C3D4.

  • material_format (str) – ‘reference_umat’ (default) → the layout of the reference model T25C: *Depvar, then *User Material with 6 constants: Bunge-Euler angles in degrees wrapped into [0, 360), a sequential grain number 1..N, then REFERENCE_UMAT_TAIL. ‘bunge_euler’ → *User Material with 3 Bunge-Euler constants. ‘orientation’ → *Elastic stub (for elastic studies).

  • n_depvar (int) – Number of UMAT state variables (*Depvar); default 1, as in the reference. Not used by ‘orientation’.

  • length_scale (float) – Multiplies every node coordinate. Coordinates are voxel index x voxel_size_um x length_scale; the default 1e-3 writes mm.

  • load_axis (str) – ‘x’, ‘y’ or ‘z’ (default): the axis of the uniaxial load in 08.

  • applied_strain (float) – Nominal strain of the load step (default 0.2): the max face of load_axis is displaced by applied_strain x the domain length along that axis, in the scaled units.

  • step_time (float) – Total time of the static step (default 80, as in the reference).

  • write_step (bool) – Write the step in 08 (default True). The face node sets the step needs are written even if disabled in nset_config.

  • initial_inc (float, float, float, int) – *Static increment controls and the *Step inc= limit (defaults 0.01, 1e-8, 1.0, 10000, as in the reference).

  • min_inc (float, float, float, int) – *Static increment controls and the *Step inc= limit (defaults 0.01, 1e-8, 1.0, 10000, as in the reference).

  • max_inc (float, float, float, int) – *Static increment controls and the *Step inc= limit (defaults 0.01, 1e-8, 1.0, 10000, as in the reference).

  • max_increments (float, float, float, int) – *Static increment controls and the *Step inc= limit (defaults 0.01, 1e-8, 1.0, 10000, as in the reference).

  • output_interval (float) – Field output every this much step time (default 0.5): the output database gets step_time / output_interval + 1 frames.

  • element_outputs (str or sequence of str) – Field output variables, e.g. ‘LE, NE, S, SDV’ and ‘U’ (the defaults). The output database grows with the number of variables and frames.

  • node_outputs (str or sequence of str) – Field output variables, e.g. ‘LE, NE, S, SDV’ and ‘U’ (the defaults). The output database grows with the number of variables and frames.

  • write_role_elsets (bool) – Write 03b_elsets_roles.inp (Option 2 grouping).

  • write_family_elsets (bool) – Write 03c_elsets_families.inp (Option 3 grouping).

  • write_variant_elsets (bool) – Write 03d_elsets_variants.inp (Option 5 grouping).

  • role_enabled (dict {role_key: bool} or None) – Per-role toggle for whether that role’s bucket ELSET is written in 03b (role_key is one of ‘non_host’/’host’/’primary_twin’/ ‘stwin_a’/’stwin_b’). Defaults to all-enabled. Has no effect on 03a (per-grain elsets are always written for every grain, regardless of role, since every element must belong to exactly one 03a ELSET for material/section assignment) – this only controls the optional 03b convenience groupings.

  • role_prefix (dict {role_key: str} or None) – Per-role ELSET name override for 03b (same keys as role_enabled). Falls back to _DEFAULT_ROLE_PREFIX for any role not given.

  • family_prefix (str) – ELSET name prefix for 03c (<family_prefix><host_gid> – include your own trailing separator, e.g. 'es_family_').

  • variant_prefix (str) – ELSET name prefix for 03d (<variant_prefix><v> – include your own trailing separator, e.g. 'es_variant_ptwin_').

  • nset_config (dict {face: {'enabled': bool, 'prefix': str}} or None) – Per-face ('XMIN'/'XMAX'/'YMIN'/'YMAX'/'ZMIN'/ 'ZMAX') toggle and name override for 04. Falls back to _DEFAULT_NSET_CONFIG (all enabled) for any face not given.

  • material_level (str) – One of 'feature' (default – one *Material per grain, today’s only implemented behaviour) or a role key. Non-'feature' values are accepted but NOT implemented: materials/sections are still written per-grain, and a warning is raised at write() time rather than silently honouring the request.

  • index (GrainElementIndex or None) – A pre-built index from build_index(). When given, the expensive grain-to-element indexing pass is skipped entirely (lgi is then optional and ignored if also given) – use this to re-export the same cleaned structure with different settings without re-indexing each time. When None (default), the index is built fresh from lgi/twin_role/twin_parent_of, exactly matching the previous (pre-split) behaviour.

static build_index(lgi: numpy.ndarray, twin_role: Dict[int, str], twin_parent_of: Dict[int, int], verbose: bool = True) → GrainElementIndex[source]

Build the grain-to-element index from a cleaned labelled structure – the expensive part of constructing an AbaqusExporter3D (transposing to native (nx,ny,nz), classifying secondary twins into 2a/2b, and indexing every grain’s element IDs). Depends only on (lgi, twin_role, twin_parent_of), NOT on any export setting, so build it once and reuse the same GrainElementIndex across repeated exports that only change settings.

property n_elements: int

Number of elements written (voxels x elements per voxel).

write(out_dir: str = '/home/runner/work/UPXO/UPXO/data/ABQInputFiles/ofhcCu') → None[source]

Write all Abaqus input files to out_dir.

Parameters:

out_dir (str, optional) – Destination directory. Defaults to DEFAULT_ABQ_OUT_DIR (upxo_library/data/ABQInputFiles/ofhcCu/ resolved relative to the package root). Pass any absolute or relative path to override.