Temperature Module (USE_TEMP)
ExaGOOP includes an optional coupled heat-transfer module that solves a Lagrangian energy equation alongside the momentum equation. When enabled, each material point carries thermal state (temperature, specific heat, thermal conductivity, heat flux, and internal heat source), and the nodal grid carries five additional fields that are deposited and interpolated every time step.
The module is compiled in or out at build time through the USE_TEMP
preprocessor flag. It is enabled by default in both the CMake and
GNUmake build systems.
Enabling the module at build time
CMake
cmake -DEXAGOOP_USE_TEMP=ON .. # ON → compiles temperature module (default)
cmake -DEXAGOOP_USE_TEMP=OFF .. # OFF → omits temperature module
The option defaults to ON. When ON, the preprocessor symbol
USE_TEMP=1 is injected; when OFF, USE_TEMP=0 is injected.
GNUmake
In the relevant GNUmakefile (e.g., Build_Gnumake/GNUmakefile or a
test-specific makefile), set the flag before including Make.defs:
USE_TEMP = TRUE # enables temperature module (default in build system)
USE_TEMP = FALSE # disables temperature module
The macro -DUSE_TEMP=$(USE_TEMP) is passed to the compiler automatically
by Build_Gnumake/GNUmakefile.
Note
TRUE and FALSE are defined by the build system as 1 and 0
respectively, so #if USE_TEMP guards in the source work correctly for
both build paths.
Autogeneration parameters
When mpm.use_autogen = 1 and the temperature module is compiled in,
four additional material properties must be supplied for the autogenerated
particle block. All four are optional and fall back to the defaults listed
below.
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Initial temperature \(T_p^0\) of all autogenerated particles. |
|
|
|
Specific heat capacity \(c_p\) (energy per unit mass per degree). |
|
|
|
Thermal conductivity \(\kappa\) (treated as a scalar; units consistent with the rest of the input). |
|
|
|
Volumetric internal heat source \(\dot{q}\). |
When particles are loaded from an external file (mpm.particle_file),
each particle line must include the four thermal fields in the order:
temperature, specific_heat, thermal_conductivity,
heat_source. The heat-flux vector components are initialised to zero
by the reader regardless of what the file contains.
Temperature boundary conditions
Temperature BCs follow the same per-face naming convention as the momentum
BCs. Each domain face is identified by an axis prefix (x, y, z)
and a side suffix (lo, hi), giving keys of the form
mpm.bc_xlo_temp, mpm.bc_xhi_temp, mpm.bc_ylo_temp, etc.
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
BC type for the named face (see keyword table below). |
|
|
|
Wall temperature \(T_w\) for |
|
|
|
Prescribed temperature gradient \(\partial T / \partial n\) for
|
|
|
|
Heat transfer coefficient \(h\) for |
|
|
|
Ambient temperature \(T_\infty\) for |
The five recognised BC type keywords are:
Keyword |
Meaning |
|---|---|
|
Periodic face. Automatically set for directions where
|
|
Fixed-temperature wall. The nodal temperature is overwritten each
step with |
|
Zero heat-flux (insulated) wall. The boundary node temperature is set equal to the first interior neighbour, enforcing \(\partial T / \partial n = 0\). No sub-parameters needed. |
|
Prescribed heat-flux wall. The boundary node temperature is set using a ghost-point formula: \(T_b = T_\text{int} + \texttt{flux} \cdot \Delta x\), where \(T_\text{int}\) is the first interior neighbour and \(\Delta x\) is the cell width in the face-normal direction. |
|
Convective (Robin) wall. The boundary temperature is set via a Biot-number weighting: \(T_b = (T_\text{int} + \text{Bi} \cdot T_\infty) / (1 + \text{Bi})\), where \(\text{Bi} = h \cdot \Delta x\). |
Nodal fields added by the temperature module
When USE_TEMP=1, the nodal MultiFab grows from 20 to 25 components
(NUM_STATES = 25). The five additional components, their integer
indices, and their physical meaning are:
Index |
Name ( |
Physical quantity |
|---|---|---|
20 |
|
\(\sum_p m_p c_p N_I(\mathbf{x}_p)\) — thermal mass at node \(I\), used as the denominator when normalising the nodal temperature. |
21 |
|
\(\sum_p m_p c_p T_p N_I(\mathbf{x}_p)\) — mass-weighted
temperature sum; divided by |
22 |
|
Nodal temperature \(T_I\) after normalisation and boundary condition enforcement. |
23 |
|
Net nodal heat source \(S_I = \sum_p (-\nabla N_I \cdot \mathbf{q}_p + \dot{q}_p N_I) V_p\), accumulated during the particle-to-grid pass. |
24 |
|
\(\Delta T_I = T_I^{t+\Delta t} - T_I^t\), computed after the
nodal temperature advance and used during the grid-to-particle
interpolation step (analogous to |
These field names are visible in ParaView when loading grid output files.
Per-particle thermal fields
The following real-data slots are appended to the particle struct when
USE_TEMP=1 (indices continue from the non-thermal fields; they are
not contiguous with the non-thermal fields in memory — see
realData enum in mpm_specs.H for absolute indices):
Field ( |
Description |
|---|---|
|
Current particle temperature \(T_p\). |
|
Specific heat \(c_p\); constant per particle throughout the simulation. |
|
Scalar thermal conductivity \(\kappa\); constant per particle. |
|
Heat-flux vector \(\mathbf{q}_p\) ( |
|
Volumetric internal heat source \(\dot{q}_p\); constant per particle. |
Time-step sequence for the thermal solve
Each time step, the thermal module executes the following operations inside the main integration loop (after the momentum update):
Particle-to-grid (P2G) — mass and source deposition
deposit_onto_grid_temperature()scattersMASS_SPHEAT,MASS_SPHEAT_TEMP, andSOURCE_TEMP_INDEXfrom particles to grid nodes.Nodal temperature normalisation For nodes where
MASS_SPHEAT ≥ mass_tolerance, the nodal temperature is computed as:\[T_I = \frac{\sum_p m_p c_p T_p N_I(\mathbf{x}_p)} {\sum_p m_p c_p N_I(\mathbf{x}_p)}\]Backup nodal temperature —
backup_current_temperature()copiesTEMPERATUREintoDELTA_TEMPERATUREfor use in step 6.Boundary condition enforcement —
nodal_bcs_temperature()applies Dirichlet values frombc_lower_tempval/bc_upper_tempvalat the domain boundary nodes.Nodal temperature advance —
advance_nodal_temperature()updates each node:\[T_I^{t+\Delta t} = T_I^t + \frac{S_I}{\sum_p m_p c_p N_I} \, \Delta t\]Store \(\Delta T\) —
store_delta_temperature()computesDELTA_TEMPERATURE = T_I^{new} − T_I^{old}.Grid-to-particle (G2P) — temperature and heat-flux interpolation
interpolate_from_grid_temperature()interpolatesDELTA_TEMPERATUREback to each particle to update \(T_p\), and computes the new particle heat-flux vector \(\mathbf{q}_p = -\kappa_p \nabla T(\mathbf{x}_p)\) by interpolating the gradient ofTEMPERATURE.
Minimal input file snippet
The block below shows the additional lines required on top of the standard input file to activate a uniform-temperature elastic-solid simulation with fixed temperatures at the lower and upper \(y\)-faces:
# -------------------------------------------------------------------
# Autogeneration: thermal properties
# (only needed when mpm.use_autogen = 1)
# -------------------------------------------------------------------
mpm.T_autogen = 300.0 # initial temperature (K)
mpm.cp_autogen = 500.0 # specific heat (J / kg K)
mpm.thermcond_autogen = 50.0 # thermal conductivity (W / m K)
mpm.heatsrc_autogen = 0.0 # volumetric heat source (W / m^3)
# -------------------------------------------------------------------
# Temperature boundary conditions
# -------------------------------------------------------------------
mpm.bc_ylo_temp = dirichlet
mpm.bc_ylo_temp.T_wall = 400.0
mpm.bc_yhi_temp = dirichlet
mpm.bc_yhi_temp.T_wall = 300.0
In this example the \(x\)- and \(z\)-faces are left at their
defaults (dirichlet with T_wall = 0.0 for non-periodic directions),
while the lower \(y\)-face is held at 400 K and the upper
\(y\)-face at 300 K, imposing a temperature gradient in the
\(y\)-direction.
Warning
The default values for bc_lower_tempval and bc_upper_tempval
are 0.0 in all directions. Any face for which these are not
explicitly set in the input file will have its boundary nodes forced to
\(T = 0\) each step. Always specify all six values (three lower,
three upper) when running with USE_TEMP=1.
Verification test cases
The following two test cases verify the heatflux and convective
temperature boundary conditions against analytical solutions. Both are
located under Tests/ and follow the standard ExaGOOP layout: a
PreProcess/ directory containing config.json and
Generate_MPs_Inputfile_Generic.py, a top-level input file
(Inputs_*.inp), a particle file (mpm_particles.dat), and a
PostProcess/ directory containing validate.py.
The thermal diffusivity for both cases is \(\alpha = k / (\rho c_p) = 1 / (1 \times 1) = 1\), which gives unit-diffusivity heat conduction — a clean choice that makes the analytical series converge quickly.
1D heat conduction with prescribed heat flux
Physical problem
A stationary elastic slab occupies \(x \in [0, L]\) with \(L = 1\). The left face is held at a fixed temperature, and the right face has a prescribed outward heat flux. The problem is effectively one-dimensional: the \(y\)-faces are periodic and the domain is thin (\(L_y = 0.1\)) so there is no variation in \(y\).
Governing equation:
Boundary and initial conditions:
Material properties
Property |
Value |
Notes |
|---|---|---|
Density \(\rho\) |
1.0 |
uniform |
Specific heat \(c_p\) |
1.0 |
uniform |
Thermal conductivity \(k\) |
1.0 |
uniform, giving \(\alpha = 1\) |
Internal heat source \(\dot{q}\) |
0.0 |
no volumetric source |
Initial temperature \(T_0\) |
0.0 |
uniform |
Domain and discretisation
The computational domain is \([0,1] \times [0,0.1]\) with \(40 \times 4\) background grid cells. Two material points per cell in each direction gives \(80 \times 8 = 640\) material points in total. The time step is fixed at \(\Delta t = 10^{-5}\) and the simulation is advanced to \(t_\text{final} = 2.0\).
Analytical solution
Decomposing \(T = T_s(x) + v(x,t)\) where \(T_s = (q/k)\,x\) is the steady state, the transient part satisfies the heat equation with a Dirichlet condition at \(x = 0\) and a zero-flux condition at \(x = L\). The eigenvalues of this Sturm-Liouville problem are \(\lambda_n = (2n-1)\pi / (2L),\; n = 1,2,\ldots\), giving:
At long times the solution approaches the linear steady state \(T_s(x) = x\).
Setting up the test case
The particle file and input file are generated from the configuration
in PreProcess/config.json. The key editable fields are:
{
"grid": { "nx": 40, "ny": 4 },
"ppc": [2, 2],
"bodies": [{
"temperature": {
"T": 0.0,
"spheat": 1.0,
"thermcond": 1.0,
"heatsrc": 0.0
}
}]
}
To regenerate the particle and input files, run from the test directory:
cd Tests/1D_Heat_Conduction_HeatFlux/
bash Generate_MPs_and_InputFiles.sh
This writes mpm_particles.dat and
Inputs_1DHeatConduction_HeatFlux.inp. The boundary conditions in the generated input file are:
mpm.bc_xlo_temp = dirichlet
mpm.bc_xlo_temp.T_wall = 0.0
mpm.bc_xhi_temp = heatflux
mpm.bc_xhi_temp.flux = 1.0
To change the imposed flux, set mpm.bc_xhi_temp.flux to the desired
value of \(q\). If the material thermal conductivity is also
changed (via thermcond in config.json), the flux entry in the
input file should be updated to \(q / k\) accordingly.
Running
Build the binary with the temperature module enabled:
cd Tests/1D_Heat_Conduction_HeatFlux
# copy make file here.
make USE_TEMP=TRUE -j4
Then run:
./ExaGOOP2d.<suffix>.ex Inputs_1DHeatConduction_HeatFlux.inp
Output particle snapshots are written to the subdirectory specified by
mpm.prefix_asciifilename inside the test directory.
Post-processing and validation
The validation script compares the numerical temperature profile against the analytical Fourier-series solution at \(t = 0.5\):
cd Tests/1D_Heat_Conduction_HeatFlux/PostProcess
python validate.py
A passing run prints the RMS error and PASS. The acceptance
criterion is RMS \(< 10^{-2}\).
Sample result
At \(t = 0.5\) the transient has partially decayed. The profile rises from \(T(0) = 0\) and curves upward, approaching the linear steady state \(T = x\). The first-mode relaxation time is \(1/\lambda_1^2 = 4/\pi^2 \approx 0.41\), so at \(t = 0.5\) roughly \(e^{-1.23} \approx 29\%\) of the leading-mode amplitude remains. Representative exact values are:
\(x\) |
\(T_\text{exact}(x,\,0.5)\) |
Steady state \(x\) |
|---|---|---|
0.00 |
0.000 |
0.000 |
0.25 |
0.160 |
0.250 |
0.50 |
0.333 |
0.500 |
0.75 |
0.532 |
0.750 |
1.00 |
0.764 |
1.000 |
The numerical solution produced by ExaGOOP matches these values to within RMS \(\approx 3 \times 10^{-3}\).
1D heat conduction with convective boundary condition
Physical problem
The same slab geometry and material as the heat-flux case, but with different boundary conditions: the left face has a fixed temperature and the right face is subject to Newton cooling (a Robin condition).
Boundary and initial conditions:
This models a slab heated from one end by a fixed wall and cooled from the other by a convective fluid. The Biot number is \(\text{Bi} = h L / k = 2\), placing this case firmly in the mixed-convection regime (neither thermally thin nor thick limit).
Material properties
Identical to the heat-flux case: \(\rho = c_p = k = 1\), \(\dot{q} = 0\), \(T_0 = 0\).
Analytical solution
The steady state satisfying both boundary conditions is:
Decomposing \(T = T_s + w\), the transient part \(w\) satisfies homogeneous boundary conditions of the same type (Dirichlet at \(x = 0\), Robin at \(x = L\)). The eigenfunctions are \(\sin(\lambda_n x)\) where the eigenvalues satisfy the transcendental equation:
For \(h/k = 2\) the first few roots are approximately \(\lambda_1 \approx 1.077\), \(\lambda_2 \approx 3.644\), \(\lambda_3 \approx 6.578\), … . The full solution is:
Setting up the test case
The config.json structure is identical to the heat-flux case. The
key boundary condition lines in the generated input file are:
mpm.bc_xlo_temp = dirichlet
mpm.bc_xlo_temp.T_wall = 1.0
mpm.bc_xhi_temp = convective
mpm.bc_xhi_temp.h = 2.0
mpm.bc_xhi_temp.T_inf = 0.0
To change the heat transfer coefficient, edit mpm.bc_xhi_temp.h.
To change the far-field temperature, edit mpm.bc_xhi_temp.T_inf.
Regenerate input and particle files after editing config.json:
cd Tests/1D_Heat_Conduction_Convective/PreProcess
python Generate_MPs_Inputfile_Generic.py
Running
cd Tests/1D_Heat_Conduction_Convective
make USE_TEMP=TRUE -j4
./ExaGOOP2d.gnu.MPI.ex Inputs_1DHeatConduction_Convective.inp
Post-processing and validation
cd Tests/1D_Heat_Conduction_Convective/PostProcess
python validate.py
The script finds eigenvalues numerically (scipy.optimize.brentq),
evaluates the Fourier series at \(t = 0.5\), and reports the RMS
error. Acceptance criterion: RMS \(< 10^{-2}\).
Sample result
The steady state \(T_s(x) = 1 - 2x/3\) drops from 1 at the heated wall to \(1/3 \approx 0.333\) at the convective boundary. The first eigenvalue \(\lambda_1 \approx 2.289\) gives a relaxation time of \(1/\lambda_1^2 \approx 0.19\), so by \(t = 0.5\) the profile is close to steady state. Representative exact values:
\(x\) |
\(T_\text{exact}(x,\,0.5)\) |
Steady state \(T_s(x)\) |
|---|---|---|
0.00 |
1.000 |
1.000 |
0.25 |
0.805 |
0.833 |
0.50 |
0.619 |
0.667 |
0.75 |
0.448 |
0.500 |
1.00 |
0.294 |
0.333 |
The numerical solution produced by ExaGOOP matches these values to within RMS \(\approx 2 \times 10^{-3}\).