CPFE (NF geometry + FF initial strain)#
Run a combined near-field + far-field CPFE simulation: the NF reconstruction supplies the high-resolution hex mesh and per-element orientations, while the FF reconstruction supplies the initial elastic-strain (residual-strain) field. Use this when you want to drive CPFE from an NF mesh with an FF residual-strain initial condition, optionally end to end from synthetic HEDM.
Needs: the native stack: NEPER (FF/synthetic), CUBIT/SCULPT (NF mesh), MOOSE puma-opt + neml2-compile.
Tier B: needs the full native stack
This notebook needs neper, CUBIT’s psculpt/epu, and puma-opt, 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#
An NF mesh and orientations, from NF reconstruction (
NearFieldMeshBuilder):mesh.eplus a per-element MRPorientations.csv.An FF per-grain elastic-strain file, from FF reconstruction (
VoronoiMeshBuilderwithgenerate_mesh=False):reconstruction_cpfe_ee.csv.
If the NF and FF data are not co-registered, shift the FF x, y, z into the NF frame first (see below). A synthetic HEDM generator can produce both stages when you do not have experimental data.
Pipeline#
(optional) Generate synthetic HEDM, writing an FF CSV and NF layers.
Build the NF mesh:
NearFieldMeshBuilder.reconstructthenNearFieldMeshBuilder.meshproducemesh.eandorientations.csv.Build the FF residual strain:
build_voronoi(generate_mesh=False, ...)producesreconstruction_cpfe_ee.csv.Run CPFE with the NF mesh, NF orientations, and the FF strain field.
Recipe#
Shift the FF elastic-strain file into the NF frame when the two are not co-registered:
[ ]:
import pandas as pd
ff_translation = (dx, dy, dz) # from experiment geometry
ee = pd.read_csv("out/ff_reconstruction/reconstruction_cpfe_ee.csv",
header=None, index_col=False)
ee.iloc[:, 0] += ff_translation[0]
ee.iloc[:, 1] += ff_translation[1]
ee.iloc[:, 2] += ff_translation[2]
ee.to_csv("out/ff_reconstruction/reconstruction_cpfe_ee_shifted.csv",
index=False, header=False)
Run the simulation:
[ ]:
from graintrace.run_cpfe_simulation import CPFESimulation
sim = CPFESimulation(
mesh_file="out/nf_reconstruction/mesh.e",
save_simulation_folder="out/simulation",
eeres_file="out/ff_reconstruction/reconstruction_cpfe_ee_shifted.csv",
ori_file="out/nf_reconstruction/orientations.csv",
dim=3, element_order="FIRST", # NF meshes are typically FIRST order
moose_run_file="external/puma/puma-opt", # your built puma-opt
use_ff_initial_field=False, # ee comes from a DIFFERENT mesh
)
sim.set_parameters("material", ...) # see the material-calibration tutorial
sim.set_parameters("simulation_parameters",
device="cuda:0", device_batch=1000,
dt=0.5, total_time=2.0, initialize_time=1.0, sync_times="2.0")
sim.set_parameters("boundary", bounding_box=nf_bbox, bc={...})
sim.set_parameters("grid_properties",
number_of_elements=[10, 10, 10], bounding_box=grid_bb)
sim.run(ncore=8)
Key parameters#
use_ff_initial_field:Falsewheneeres_filecomes from a different mesh than the geometry (FF strain on an NF mesh);Trueonly when mesh and strain file are co-registered FF.FF-to-NF shift: add
(dx, dy, dz)to the first three columns ofreconstruction_cpfe_ee.csvto align frames before passing it aseeres_file.nf_bbox: derive from the NFmerged_segmented_fixed_grid.npycoordinates (see configuration).sculpt_config: configures the NF hex mesh (see configuration).CPFE material, simulation, boundary, and grid parameters follow CPFE simulation.
Gotchas#
The same NEML2 v3 AOTI notes as CPFE simulation apply: material parameters are baked into the model and compiled on
run(); there are no runtime schedulers; a device list maps to MPI ranks.NF reconstruction uses multiprocessing, so the driver must sit under an
if __name__ == "__main__":guard.moose_run_filemust point at your built v3puma-opt.
Full example#
Full script: examples/demonstrate_cpfe_nfff.py