spectral_galerkin_heat.physics.spectral_ops

Backend-agnostic spectral free functions (shared by CPU and GPU kernels).

These operate on a SpectralSolverState and are pure einsum / array-copy logic: they take the array module from SsState.xp, so both kernel modules import them from here.

Operations that differ between backends stay in the per-backend kernel modules: the FFT (DCT_II / IDCT_II), the scipy/cupyx ndimage shifts, and the @njit vs @cuda.jit source-term kernel.

Functions

project_box_to_modes(field_box, SsState)

Project fine box field to global spectral modes.

reconstruct_volume(a, SsState)

Reconstruct the full cell-centred temperature field over Ω from modes a.

project_volume(field, SsState)

Project a full cell-centred volume field onto the modal basis.

assemble_property_correction(SsState, a_trial, ...)

Assemble the temperature-dependent property correction modes C_mnp.

reconstruct_temperature_box(a, SsState)

Reconstructs temperature in the refined, laser-following sub-box of the domain.

initialize_latent_heat_if_needed(SsState)

Initialize fine-mesh T_prev from current trial modes on the first time step.

update_latent_heat_history(SsState)

Store the converged fine-mesh temperature as T_prev for the next step.

reconstruct_surface_temperature(a, SsState)

Reconstruct the 2D temperature field at the top surface (z = Lz).

reconstruct_bottom_temperature(a, SsState)

Reconstruct the 2D temperature field at the bottom surface (z = 0).

compute_latent_heat_source(Q_buffer, phys, num, SsState)

Compute volumetric latent heat source Q (W/m^3) on the fine mesh.

shift_latent_heat_history(SsState, laser_state, num)

Shift T_prev and Q_prev to align with the current laser position.

Module Contents

spectral_galerkin_heat.physics.spectral_ops.project_box_to_modes(field_box, SsState)

Project fine box field to global spectral modes.

The two branches give bit-identical results. einsum returns an F-contiguous view, which makes the * dV_fine scaling read uncoalesced on GPU, so the GPU path spells the same contraction out as tensordots to keep every intermediate C-contiguous. Strided access is cheap on CPU, where einsum is the faster of the two.

spectral_galerkin_heat.physics.spectral_ops.reconstruct_volume(a, SsState)

Reconstruct the full cell-centred temperature field over Ω from modes a.

Inverse of project_volume(): T = IDCT_II(a) / sqrt(dV). Returns a (nz, ny, nx) array on the same grid the modes live on.

spectral_galerkin_heat.physics.spectral_ops.project_volume(field, SsState)

Project a full cell-centred volume field onto the modal basis.

Forward of reconstruct_volume(): modes = sqrt(dV) * DCT_II(field). Scaled in place, for the reason given in reconstruct_volume().

spectral_galerkin_heat.physics.spectral_ops.assemble_property_correction(SsState, a_trial, T_prev_full, dt, model, k_bar, a_bar)

Assemble the temperature-dependent property correction modes C_mnp.

Forcing-assembly recipe: reconstruct T over Ω from the current trial modes, read the property fluctuations k'(T)=k(T)-k̄ and a'(T)=a(T)-ā from the tabulated model, form g = k' ∇T (finite-difference gradient) and s_a = -a' ∂_t T, then project. The projection returns only the volume modes; the boundary contribution of the conductivity correction is handled by the solver as a rescaling of the prescribed surface flux (see below and SpectralSolver.step).

Parameters:
  • a_trial (ndarray (nz, ny, nx)) – Current Picard trial modes.

  • T_prev_full (ndarray (nz, ny, nx)) – Previous converged full-volume temperature field (for ∂_t T).

  • dt (float) – Time step.

  • model (MaterialModel) – Temperature-dependent property model.

  • k_bar (float) – The ETD1 propagators’ reference constants (k̄, ā).

  • a_bar (float) – The ETD1 propagators’ reference constants (k̄, ā).

Returns:

C – Correction forcing modes, to be injected as a += KK · C.

Return type:

ndarray (nz, ny, nx)

spectral_galerkin_heat.physics.spectral_ops.reconstruct_temperature_box(a, SsState)

Reconstructs temperature in the refined, laser-following sub-box of the domain.

spectral_galerkin_heat.physics.spectral_ops.initialize_latent_heat_if_needed(SsState)

Initialize fine-mesh T_prev from current trial modes on the first time step.

Must be called after buffers.a_temp has been set to a reasonable estimate (e.g. the decayed modes).

spectral_galerkin_heat.physics.spectral_ops.update_latent_heat_history(SsState)

Store the converged fine-mesh temperature as T_prev for the next step.

Call once per time step, after the fixed-point iteration has converged and buffers.a_temp holds the final spectral modes.

spectral_galerkin_heat.physics.spectral_ops.reconstruct_surface_temperature(a, SsState)

Reconstruct the 2D temperature field at the top surface (z = Lz).

Sums the z-modes weighted by the top-surface Cp coefficients, then applies the inverse DCT (via the backend idct hook).

spectral_galerkin_heat.physics.spectral_ops.reconstruct_bottom_temperature(a, SsState)

Reconstruct the 2D temperature field at the bottom surface (z = 0).

At z=0, cos(p*pi*0/Lz) = 1 so the weighting is plain Cp (no sign alternation).

spectral_galerkin_heat.physics.spectral_ops.compute_latent_heat_source(Q_buffer, phys, num, SsState)

Compute volumetric latent heat source Q (W/m^3) on the fine mesh.

Uses the current trial modes (buffers.a_temp) and the stored T_prev. Does not update T_prev; call update_latent_heat_history() after the iteration has converged.

The latent source is Q = -rho(T) * L_f * (f_l(T) - f_l(T_prev)) / dt with f_l clamped to [0, 1]. For a temperature-dependent material the density is the blended rho(T) = (1-f_l)rho_s(T)+f_l rho_l(T) evaluated per cell.

spectral_galerkin_heat.physics.spectral_ops.shift_latent_heat_history(SsState, laser_state, num)

Shift T_prev and Q_prev to align with the current laser position.

Call once per time step, before the fixed-point iteration begins.