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
*Materialin the reference layout:*Depvarthen*User Material, constants=6= phi1, Phi, phi2 (degrees, wrapped into [0, 360)), the grain number, thenREFERENCE_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_axisdisplaced bydisplacementalong 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_intervalof step time, so the output database gets step_time / output_interval + 1 frames, and Abaqus shortens increments to land on those times.nset_namesmaps ‘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:
objectPre-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 viaAbaqusExporter3D.build_index()and pass the result toAbaqusExporter3D(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:
objectWrites 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 – seeTwinnedSimple3DBase.plot_temporal_slice_3d’s P/R/C convention comment). Transposed internally to (nx, ny, nz) before any node/ element indexing, so callers should passcleaner.lgi_cleanexactly as produced – do not pre-transpose it yourself. May be omitted (None) ifindexis given instead (see below).twin_role (dict {gid: str}) –
twin_role_cleanfrom cleaner: one of ‘non_host’, ‘host’, ‘primary_twin’, ‘secondary_twin’.twin_parent_of (dict {child_gid: parent_gid}) –
twin_parent_of_cleanfrom cleaner.all_quats (dict {gid: ndarray(4,)}) – Per-grain unit quaternions [w, x, y, z].
twinmake (TwinGenerator3D or None) – Provides
twinmake.twin_halfwidths_voxand 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_axisis 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_PREFIXfor 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 atwrite()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 (lgiis 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 fromlgi/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 sameGrainElementIndexacross repeated exports that only change settings.
- 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.