Simple Induction Heating Application¶
All the files necessary to reproduce the results can be obtained via downloading this zip file.
Hint
If you are not familiar with coupled magnetic thermal problems, consider visiting our tutorial on Induction Heating
first.
Problem and setup description¶
The problem is really similar to the tutorial Induction Heating
but here we focus on applying openCFS in a "real world scenario" by parameterizing the mesh generation, simulation and material xml files and automating evaluations.
In general, the setup is depicted in the following figure:

It represents a 3D model of a single-turn coil wrapped around a cylindrical iron core and it is simulated as a quarter model, leveraging symmetry around the rotational axis. The surrounding air domain is chosen to be sufficiently large to prevent boundary conditions at its edges from influencing the simulation results.
The coil is excited by an alternating current, generating a time-varying magnetic field around it. This magnetic field penetrates the conductor inside the coil, in this case, the iron core, inducing eddy currents within the material. These eddy currents circulate through the core, producing heat due to Joule heating.
Before we start with the simulation and material xml definitions, let us have a look at the python script we use to automate the simulations cfsrun.py
, which depends on the class and methods defined in pyincludes.py
:
from pyincludes import OpenCFS
import matplotlib.pyplot as plt
# %%
################## INPUT BEGIN ##################
# please set the correct working directory for your system
CWD = 'provide correct working directory'
CFS = 'provide path to cfs'
TRELIS = 'provide path to coreform cubit'
# Simulation Parameter
SIM_PARAMETER = {'CURRENT': 100000,
'FREQUENCY': 10,
'HEAT_TRANSPORT_COEF': 15,
'INITIAL_TEMPERATURE': 293.15,
'BULK_TEMPERATURE': 293.15,
'HEAT_EMISSIVITY': 0.32,
'VELOCITY': 0.0,
'NUM_CORES': 2,
'TIME_STEPS': 5, # delta t
'NUM_STEPS': 10}
# Material Parameter
MAT_PARAMETER = {'HEAT_DENSITY_LINEAR': 7850,
'HEAT_DENSITY_NONLINEAR': 'heat_density.fnc',
'HEAT_CAPACITY_LINEAR': 10,
'HEAT_CAPACITY_NONLINEAR': 'heat_capacity.fnc',
'HEAT_CONDUCTIVITY_LINEAR': 37.69928,
'HEAT_CONDUCTIVITY_NONLINEAR': 'heat_conductivity.fnc',
'MAGNETIC_PERMEABILITY_LINEAR': 1.4e-3,
'ELECTRIC_CONDUCTIVITY_LINEAR': 4.5e6}
# Evaluation Parameter
EVAL_PARAMETER = {'START_POINT': [0, 0, 0],
'END_POINT': [0.0125, 0.1, 0],
'NUM_POINTS': 10}
# Input Files
INPUT_FILE = {'TRELIS_TEMPLATE': 'mcl_mesh_template',
'XML_TEMPLATE': 'harmMag_transT_template',
'MATERIAL_TEMPLATE': 'mat_template'}
OUTPUT_FILE = {'TRELIS': 'mcl_mesh',
'XML': 'harmMag_transT',
'MATERIAL': 'mat'}
cls_openCFS = OpenCFS(CWD, CFS, TRELIS, SIM_PARAMETER, MAT_PARAMETER, EVAL_PARAMETER, INPUT_FILE, OUTPUT_FILE)
global_data, local_data = cls_openCFS.toSimulation()
Most of the parameter settings in cfsrun.py
are self explaining. The basic idea is to replace strings like 'HEAT_CONDUCTIVITY_LINEAR' with the actual value in the corresponding template xml file (mat_template.xml
and harmMag_transT_template.xml
) and mesh file mcl_mesh_template.jou
.
A neat feature is this section
# Evaluation Parameter
EVAL_PARAMETER = {'START_POINT': [0, 0, 0],
'END_POINT': [0.0125, 0.1, 0],
'NUM_POINTS': 10}
Let us have a look at some parts of the <domain>
tag in harmMag_transT_template.xml
:
<domain geometryType="3d">
<variableList>
<var name="i_coil" value="CURRENT" />
<var name="f_coil" value="FREQUENCY" />
<var name="velocity" value="VELOCITY"/>
<var name="init_temp" value="INITIAL_TEMPERATURE"/>
<var name="bulk_temp" value="BULK_TEMPERATURE"/>
<var name="heatTransportCoef" value="HEAT_TRANSPORT_COEF"/>
<var name="wire_area" value="0.0006"/>
<var name="heat_emissivity" value="HEAT_EMISSIVITY"/>
</variableList>
...
Defining the problem in openCFS¶
The solution method we follow here is described in MagHeatPDE
as magnetics in frequency-domain - transient heat: linear magnetics - nonlinear heat \rho(T), c_{\textrm p}(T), \lambda(T), \epsilon(T), where \epsilon is the thermal emissivity (only relevant for really high temperatures).
This means we can only use constant (no saturation BH curve, no temperature dependency) magnetic permeability, otherwise we would need to switch to a transient magnetics - transient heat setup or use multiharmonic magnetics. So the temperature is just acting on nonlinear parameters in the heat PDE.
Let us now investigate the critical structures of the simulation xml file harmMag_transT_template.xml
:
...
<sequenceStep index="1">
<analysis>
<static></static>
</analysis>
<pdeList>
<heatConduction>
<regionList>
<region name="V_ROD"/>
</regionList>
<bcsAndLoads>
<temperature name="BC_MT_ROD" value="init_temp" />
<temperature name="BC_T_ROD" value="init_temp" />
</bcsAndLoads>
...
</heatConduction>
</pdeList>
</sequenceStep>
<sequenceStep index="2">
<analysis>
<harmonic>
<frequencyList>
<freq value="f_coil" />
</frequencyList>
</harmonic>
</analysis>
<pdeList>
<magneticEdge>
...
</magneticEdge>
</pdeList>
</sequenceStep>
<sequenceStep index="3">
<analysis>
<transient>
<numSteps>NUM_STEPS</numSteps>
<deltaT>TIME_STEPS</deltaT>
</transient>
</analysis>
<pdeList>
<heatConduction>
<regionList>
<region name="V_ROD" velocityId="vRod" nonLinIds="nonLin_heatCapacity nonLin_heatConductivity nonLin_density nonLin_thermalRadiation"/>
</regionList>
<nonLinList>
<heatCapacity id="nonLin_heatCapacity"/>
<heatConductivity id="nonLin_heatConductivity"/>
<density id="nonLin_density"/>
<thermalRadiation id="nonLin_thermalRadiation"/>
</nonLinList>
<velocityList>
<velocity name="vRod" coordSysId="cyl1">
<comp dof="z" value="velocity" />
</velocity>
</velocityList>
<initialValues>
<initialState>
<sequenceStep index="1" />
</initialState>
</initialValues>
<bcsAndLoads>
...
<heatSourceDensity volumeRegion="V_ROD" name="V_ROD">
<sequenceStep index="2">
<quantity name="magJouleLossPowerDensityOnNodes"
pdeName="magneticEdge" />
<timeFreqMapping>
<constant />
</timeFreqMapping>
</sequenceStep>
</heatSourceDensity>
</bcsAndLoads>
...
</heatConduction>
</pdeList>
</sequenceStep>
</cfsSimulation>
Visualization ParaView¶
If you are interested in the spatial distribution of Joule losses in the rod, you can open the resultfile harmMag_transT.cfs
and open AnalysisStep 2 (harmonic magnetic simulation).
You will also discover that the Joule losses result has complex and real part, which might be confusing after reading MagHeatPDE
but this is because of implementation reasons and in this case you can ignore the imaginary part and only visualize the real one:

Now these Joule losses are then used in the third sequence step as the right hand side of the heat PDE. If you are interested in the spatial distribution of the temperature, visualize Analysis Step 3 of the result file. But remember, further up, we mentioned a line-plotting feature. For this behalf, we run the last section of `cfsrun.py``
num_time_steps = SIM_PARAMETER['NUM_STEPS'] # e.g., 10
time_steps = list(range(1, num_time_steps + 1))
plt.figure(figsize=(10, 6))
for index, row in local_data.iterrows():
# Extract temperature values for each timestep
temperatures = [row[f'Temperature_TimeStep_{t}'] for t in time_steps]
plt.plot(time_steps, temperatures, marker='o', label=f'Point {index+1}')
plt.xlabel('Time Step')
plt.ylabel('Temperature')
plt.title('Local Data: Temperature Evolution Over Time Steps')
plt.legend(title='Local Points', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True)
plt.tight_layout()
plt.show()
