NF mesh reconstruction#
Reconstruct a high-resolution 3D mesh from near-field (NF) HEDM .mic layers via voxel segmentation and CUBIT/SCULPT hex meshing, using NearFieldMeshBuilder. Use this to produce an Exodus mesh.e and per-element MRP orientations from NF data to drive CPFE, typically paired with an FF residual-strain initial condition.
Needs: CUBIT/SCULPT (via sculpt_config). The driver must run under an if __name__ == "__main__" guard: NF reconstruction uses multiprocess.Pool.
Tier B: needs CUBIT/SCULPT
This notebook needs CUBIT’s psculpt and epu, which is not available in CI or Google Colab, so it is not executed when these docs are built. It ships as an annotated code listing with no stored output — nothing on this page is a hand-written or fabricated result. Run it in a configured environment (see the installation guide) to produce the figures, and run it from the repository root so the mwe_data/ paths resolve.
Inputs#
A folder of per-layer .mic files (tab-delimited, %-prefixed headers). If the source is .ang files (8-column, no header), convert them to .mic first: graintrace has no ``.ang`` reader, so that conversion happens outside the package. The exp_file_token argument is the filename prefix used to find the layers. See concepts for the .mic format. For the synthetic path, SyntheticHEDMGenerator writes the NF folder (see
examples/demonstrate_cpfe_nfff.py).
Recipe#
[ ]:
from graintrace.construct_nf_mesh import NearFieldMeshBuilder
import numpy as np
def main():
builder_nf = NearFieldMeshBuilder(
input_folder="experiment_data/NF", save_dir="out/NF",
exp_file_token="layer", angle_convention="bunge", angle_type="radians",
symmetry="432", prefix="reconstructed", write_intermediate=True, write_vtk=True,
)
merged_grid = builder_nf.reconstruct(
dz=5.0, nx=200, ny=300,
segmentation={ # flat dict (radians) for NearFieldMeshBuilder
"misorientation_tol": 5.0 / 180 * np.pi, "connectivity": 6,
"batch_norm": 200_000, "grain_threshold": 1000, "stop_count": 500,
"grain_threshold_final": 10000,
},
)
mesh_path = builder_nf.mesh(sculpt_config=sculpt_config, sculpt_options=sculpt_options,
merged_grid=merged_grid)
# per-element MRP orientations -> builder_nf.mapped_orientations_path + ".csv"
if __name__ == "__main__":
main()
Key parameters#
dz: layer thickness in micrometers, must match the data;nx,nyset the in-plane grid resolution.segmentation: a flat dict (nomethod/paramsnesting) withmisorientation_tolin radians andconnectivityof 6 or 26.sculpt_config: required keyspsculpt,epu,nprocs, pluslauncherandenvironmentfor MPI.sculpt_optionsis a tuple of CLI flags, e.g.("--adapt", "-S", "2", "-CS", "4", "--void_mat", "0"). See configuration and meshing.
Outputs (in save_dir)#
merged_segmented_fixed_grid.npy: the segmented voxel grid, also a restart checkpoint.mesh.e: the Exodus mesh for CPFE.orientations.csv: per-element neml2 MRP orientations; use as the CPFEori_file.
Gotchas#
Restart: if segmentation already ran, load
merged_segmented_fixed_grid.npydirectly and pass it asmerged_gridtomesh(...)instead of re-runningreconstruct(...).Derive the NF bounding box from the saved grid coordinates for the CPFE boundary conditions; see pitfalls.
Full example#
Full script: examples/demonstrate_cpfe_nfff.py