graintrace.run_cpfe_simulation#
MOOSE/PUMA crystal-plasticity FE simulation runner (NEML2 v3 / AOTI).
- class graintrace.run_cpfe_simulation.CPFESimulation(mesh_file, save_simulation_folder, moose_run_file, element_order='SECOND', eeres_file=None, ori_file=None, use_ff_initial_field=False, dim=3)[source]#
Bases:
objectConfigure and run a MOOSE/PUMA crystal-plasticity FE simulation (NEML2 v3 / AOTI).
Given a mesh, per-grain MRP orientations, and optional initial elastic strain, this writes the MOOSE input decks, bakes the material parameters into the NEML2 model, AOTI-compiles it with
neml2-compile, and launchespuma-opt. Configure viaset_parameters(section, **kwargs)for thematerial,simulation_parameters,boundary, andgrid_propertiessections, then callrun(ncore=...). Seeexamples/demonstrate_cpfe.pyand the/cpfe-simulationskill.- DEFAULT_PARAMS = {'boundary': {'bc': {'x': {'negative': 'stress_free', 'positive': 'stress_free'}, 'y': {'negative': 'stress_free', 'positive': 'stress_free'}, 'z': {'negative': 0, 'positive': 0.001}}, 'bounding_box': [0.0, 1.0, 0.0, 1.0, 0.0, 1.0], 'bounding_box_buffer': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'fix_tolerance': 1e-08}, 'grid_properties': {'bounding_box': [0.0, 1.0, 0.0, 1.0, 0.0, 1.0], 'number_of_elements': [20, 20, 20]}, 'material': {'burger_scale': 2.22, 'elastic_E': 209016, 'elastic_G': 60355.0, 'elastic_nu': 0.307, 'power_slip_g0': 0.0001, 'power_slip_n': 20, 'slip_constant_strength': 130.0, 'voce_hardening_initial_slope': 1556.09, 'voce_hardening_saturation': 100.0}, 'simulation_parameters': {'base_folder': 'simulation_out', 'compile_devices': None, 'device': 'cpu', 'device_batch': 0, 'distributed_mesh': False, 'dt': 0.1, 'exodus_output': 'sync', 'extra_ld_library_paths': None, 'grid_transfer': 'final', 'initialize_time': 1.0, 'launcher': 'mpiexec', 'mesh_csv': 'sync', 'neml2_load_files': None, 'recompile': True, 'solver_route': 'timestep_optimized', 'strain_unit_conversion': 1.0, 'sync_times': '0.1 1.0 2.0 3.0 4.0 5.0', 'total_time': 5.0}}#
- SOLVER_ROUTE_DECKS = {'hpc_memory': 'executioner_hpc_memory.i', 'timestep_optimized': 'executioner_timestep_optimized.i'}#
- set_parameters(section, **kwargs)[source]#
Update one parameter section in place with keyword overrides.
Recognized sections and their common keys:
“material”: slip_constant_strength, voce_hardening_initial_slope, voce_hardening_saturation, power_slip_n, power_slip_g0, elastic_E, elastic_nu, elastic_G, burger_scale (MPa/micrometer conventions per the model).
“simulation_parameters”: dt, total_time, initialize_time (load ramps from initialize_time to total_time), device (“cpu”/”cuda:N”/space-separated list), device_batch (per-device NEML2 chunk size; 0 = whole batch), sync_times (space-separated string of MOOSE grid-output times), grid_transfer (“final”|”per_step”|”off”), exodus_output (“sync”|”per_step”), mesh_csv (“sync”|”per_step”|”off”), launcher (“mpiexec”|”srun”), distributed_mesh (bool; True pre-splits the mesh to ncore and runs –use-split, requires ncore>=2), solver_route (“timestep_optimized” (default) = direct LU/superlu_dist with preconditioner reuse, robust and iteration-cheap but memory-bound on large meshes; “hpc_memory” = iterative fgmres + GAMG algebraic multigrid, low/scalable memory for large HPC meshes and the recommended partner of distributed_mesh=True), recompile, compile_devices, neml2_load_files, extra_ld_library_paths, base_folder, strain_unit_conversion.
“boundary”: bounding_box ([xlo,xhi,ylo,yhi,zlo,zhi]), bc (per-axis dict of “negative”/”positive” values, each “stress_free” or a numeric displacement), fix_tolerance, bounding_box_buffer.
“grid_properties”: number_of_elements ([nx,ny,nz]) and bounding_box (the inset regular-grid box, typically the BC box shrunk by 0.0001 per face).
- Parameters:
section – One of “material”, “simulation_parameters”, “boundary”, “grid_properties”.
**kwargs – Keys to override within that section; unknown keys are added as-is.
- validate_geometry_and_bcs()[source]#
Validate bounding box and boundary conditions based on dimension.
- write_orientation_file()[source]#
Write mrps_orientation.csv from the orientation file; return grain count.
- run(ncore=8)[source]#
Prepare the input decks, AOTI-compile the NEML2 model, and launch puma-opt.
Copies the cpfe_base templates into save_simulation_folder, writes the run-specific boundary/orientation/postprocessor decks, bakes the material parameters into the NEML2 model and neml2-compiles it (unless a cached AOTI package exists and recompile is False), then starts puma-opt as a detached background process. Only dim=3 is supported.
When simulation_parameters[‘distributed_mesh’] is True, the mesh is first pre-split into ncore partitions (a one-time synchronous –split-mesh step) and the solve runs with –use-split so each rank reads only its partition (low per-rank memory for large meshes). This requires ncore >= 2 and a puma-opt build with the EqualValueBoundaryConstraint distributed-mesh fix.
- Parameters:
ncore – Number of MPI ranks to launch (passed as -n to the launcher). For multi-GPU runs set this to the number of GPUs in the device list. With distributed_mesh=True this must be >= 2. Default 8.