Physics Modules¶
Laser, toolpath, melt pool detection, species transport, adaptive mesh, mechanical residual stress, and cellular-automata grain microstructure.
mod_laser.f90 — laserinput¶
Laser beam management. Each timestep: interpolates toolpath to find beam position, computes scan velocity, distributes power as 2D Gaussian on top surface.
mod_toolpath.f90 — toolpath¶
read_toolpath()— reads.crsfile intotoolmatrix(1000, 5): time, x, y, z, laser_flagread_coordinates()— records beam state to rolling buffer each timestep
mod_dimen.f90 — dimensions¶
Melt pool detection from temperature field:
- Computes
alen(length),depth,widthvia linear interpolation at solidus isotherm - Sets momentum solver bounds (
istat:iend,jstat:jend,kstat) with padding
mod_adaptive_mesh.f90 — adaptive_mesh_mod¶
Movable adaptive structured mesh in X-Y that follows the laser/melt pool. Enabled by adaptive_flag=1.
amr_init()— initializes the refined region after grid generationamr_check_remesh(step_idx)— checks if remeshing is needed (everyremesh_intervalsteps)amr_regenerate_grid()— rebuilds X-Y grid with refined region centered on laseramr_interpolate_all_fields()— interpolates all fields from old grid to new gridamr_validate_grid()— sanity checks on new grid
mod_predict.f90 — prediction¶
Field prediction by integer-cell shifting in the scan direction. Shifts enthalpy, velocity, and pressure fields forward by the number of cells the laser traverses in one timestep. Called before the iteration loop on heating steps when predict_flag=1 and a melt pool exists. Reduces solver iterations by approximately 38% during heating.
predict_shift_integer(vx, vy, dt, ...)— computes integer cell shift from scan velocity, shifts all primary fields in extended melt pool regionishift_field(field, di, dj, ...)— generic integer-cell shift with direction-aware iteration order (no interpolation)
solver_species/mod_species.f90 — species¶
Dissimilar metal species transport. See Species Transport.
Secondary material properties and transport numerics live in solver_species/inputfile/input_param_species.txt and are loaded by read_species_params() at startup when species_flag=1.
Key functions: mix(prop1, prop2, C), read_species_params(), solve_species() (FVM + TDMA + block correction), species_bc() (zero-flux Neumann).
solver_mechanical/mod_mechanical.f90 — mechanical_solver¶
Element-by-Element (EBE) FEM solve of quasi-static mechanical equilibrium with J2 elastoplasticity, driven one-way by the thermal field. Phase-aware stiffness (E_solid for substrate, E_soft for powder/liquid) decided per cell from solidfield. Newton-Raphson outer + preconditioned Conjugate Gradient inner; coloured EBE assembly avoids global stiffness matrix. See Mechanical Solver.
Key entry points:
update_mech_grid()— builds the (optionally coarsened) FEM mesh from the thermal grid; runs at simulation start and after every AMR remesh.solve_mech_step(temp, solidfield)— one mechanical step: thermal-strain RHS → CG solve → return-map plastic update.solve_mech_cg(...)— Jacobi-preconditioned CG with the EBE matvecebe_matvec_mech. Enforces a roller (Z-only Dirichlet) BC on the bottom face —uz(:,:,1)=0, X/Y free — to avoid the bottom-corner stress singularity that a full clamp produces.
When mech_threads > 0 the solver runs in a separate cluster_main process (PHOENIX_RUN_MODE=mechanical) and consumes per-step binary snapshots from result/<case>/mechanical_results/mech_input_*.bin; otherwise it runs inline inside the thermal time loop.
solver_CA/ — cellular-automata microstructure¶
Voxel-based grain growth on a uniform sub-mesh of the build volume. Drives an octahedral-envelope capture/growth rule with the Kurz–Giovanola–Trivedi velocity v = a₁ + a₂ ΔT + a₃ ΔT², plus Thévoz–Rappaz Gaussian nucleation (surface + bulk). Runs as a separate Fortran/OpenMP process (PHOENIX_RUN_MODE=ca) that consumes the thermal field via the result/<case>/coupling/ca_input_*.bin frame queue produced by mod_ca_coupling_writer.f90. See the full CA Solver Overview.
Module map (code_base/solver_CA/):
| Module | Purpose |
|---|---|
ca_grid |
Uniform CA mesh + cell index helpers |
ca_state |
Per-cell state: cell_orient_id, cell_temp, has_been_melted, … |
ca_orient |
Append-only Bunge-Euler orientation list shared with the Voronoi initialiser |
ca_voronoi |
Initial-substrate Voronoi tessellation (OMP-parallel NN) |
ca_octahedron |
Octahedral envelope geometry + capture test (L1-norm in the crystal frame) |
ca_nucleation |
Surface + bulk Gaussian nucleation site populations |
ca_solve |
Main hot loop: rebuild active cells → checkup T → nucleate → grow → capture → optional VTI dump |
ca_coupling |
Reads ca_input_*.bin frames, trilinear in space + linear in time interpolation, exposes thermal_field_sample(x,y,z,t) |
ca_vtr |
XML-VTI output writer (zlib chunked compression, inline base64, persistent pthread for async write) |
ca_driver |
Top-level orchestration: parse input_param_ca.txt → init → solve → close |
Companion writer in the thermal-fluid solver:
solver_thermal_fluid/mod_ca_coupling_writer.f90 — ca_coupling_writer¶
Per-step exporter of the melt-pool sub-volume to result/<case>/coupling/ca_input_<NNNNNN>.bin. The bbox indices come straight from mod_dimen.f90 (imin..kmax); the writer adds halo padding, asserts uniform spacing along each axis inside the bbox, writes per-axis cell sizes (hx, hy, hz) into the header so non-uniform PHOENIX grids (typical: coarse substrate Z, fine powder Z) don't get silently stretched on the CA side, and flips an atomic .tmp → .bin rename so a slow CA reader never opens a half-written frame. On normal exit ca_export_end() touches ca_input_END so the CA reader's poll loop terminates.