Skip to content

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 .crs file into toolmatrix(1000, 5): time, x, y, z, laser_flag
  • read_coordinates() — records beam state to rolling buffer each timestep

mod_dimen.f90 — dimensions

Melt pool detection from temperature field:

  • Computes alen (length), depth, width via 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 generation
  • amr_check_remesh(step_idx) — checks if remeshing is needed (every remesh_interval steps)
  • amr_regenerate_grid() — rebuilds X-Y grid with refined region centered on laser
  • amr_interpolate_all_fields() — interpolates all fields from old grid to new grid
  • amr_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 region
  • ishift_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 matvec ebe_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.