"""
Authors: Reza Najian Asl, https://github.com/RezaNajian
Date: June, 2024
License: FOL/LICENSE
"""
from .fe_loss import FiniteElementLoss
import jax
import jax.numpy as jnp
from functools import partial
from fol.tools.decoration_functions import *
from fol.tools.fem_utilities import *
from fol.mesh_input_output.mesh import Mesh
from fol.tools.usefull_functions import *
[docs]class ThermalLoss(FiniteElementLoss):
"""
Thermal loss functional for steady heat conduction finite element problems.
This class defines a scalar loss functional for heat conduction problems
solved with finite elements. The total loss value represents a
domain-integrated measure of thermal equilibrium and is assembled by
summing element-level contributions over all finite elements in the mesh.
For each element, the scalar contribution to the total loss is defined as
the inner product of the element residual vector with the corresponding
element temperature degrees of freedom. The global loss is obtained by
accumulating these scalar contributions across the computational domain,
resulting in a weighted residual formulation.
Element-level stiffness matrices and source vectors are evaluated using
Gaussian quadrature. The element conductivity can be nonlinear in the
temperature field according to the parameters ``beta`` and ``c`` in the
loss settings, using a conductivity of the form:
``k(T) = d(x) * (1 + beta * T^c)``
where ``d(x)`` is the element parameter field interpolated from ``de`` at
Gauss points.
Args:
name (str):
Name identifier for the loss instance.
loss_settings (dict):
Dictionary containing problem settings and optional nonlinear
conductivity parameters. Supported keys include ``"beta"`` and
``"c"`` for the temperature-dependent conductivity factor. The
element discretization settings (dimension, element type, and
ordered DOFs) are typically provided by the specialized subclasses.
fe_mesh (Mesh):
Finite element mesh over which the loss is defined.
Attributes:
thermal_loss_settings (dict):
Dictionary containing nonlinear conductivity parameters with keys
``"beta"`` and ``"c"``.
"""
[docs] @print_with_timestamp_and_execution_time
def Initialize(self,reinitialize=False) -> None:
if self.initialized and not reinitialize:
return
super().Initialize()
self.thermal_loss_settings = {"beta":0,"c":1}
if "beta" in self.loss_settings.keys():
self.thermal_loss_settings["beta"] = self.loss_settings["beta"]
if "c" in self.loss_settings.keys():
self.thermal_loss_settings["c"] = self.loss_settings["c"]
[docs] def ComputeElement(self,xyze,de,te,body_force=0):
"""
Compute element-level contributions to the thermal loss.
This method evaluates the element stiffness matrix and source vector
using Gaussian quadrature. The element residual is defined as
``Se @ te - Fe``. The scalar element contribution represents this
element's contribution to the total scalar loss value of the problem.
The total loss for the thermal problem is obtained by summing the
scalar contributions of all elements over the computational domain.
Each element contribution is computed as the inner product of the
element residual vector with the element temperature degrees of
freedom, resulting in a weighted residual formulation.
Args:
xyze:
Element nodal coordinates.
de:
Element parameter field values at nodes used to construct the
conductivity field (interpolated to Gauss points).
te:
Element temperature DOFs arranged consistently with the
element type and ordered DOFs.
body_force:
Element volumetric heat source term. This value is treated as a
constant over the element and integrated against the shape
functions. Default is 0.
Returns:
Tuple[float, jax.numpy.ndarray, jax.numpy.ndarray]:
- Scalar element loss contribution defined as
``te.T @ (Se @ te - Fe)``.
- Element residual vector ``Se @ te - Fe``.
- Element stiffness matrix ``Se``.
"""
def compute_at_gauss_point(gp_point,gp_weight,te):
te = jax.lax.stop_gradient(te)
N = self.fe_element.ShapeFunctionsValues(gp_point)
conductivity_at_gauss = jnp.dot(N, de.squeeze()) * (1 +
self.thermal_loss_settings["beta"]*(jnp.dot(N,te.squeeze()))**self.thermal_loss_settings["c"])
DN_DX = self.fe_element.ShapeFunctionsGlobalGradients(xyze,gp_point)
J = self.fe_element.Jacobian(xyze,gp_point)
detJ = jnp.linalg.det(J)
gp_stiffness = conductivity_at_gauss * (DN_DX @ DN_DX.T) * detJ * gp_weight
gp_f = gp_weight * detJ * body_force * N.reshape(-1,1)
return gp_stiffness,gp_f
gp_points,gp_weights = self.fe_element.GetIntegrationData()
k_gps,f_gps = jax.vmap(compute_at_gauss_point,in_axes=(0,0,None))(gp_points,gp_weights,te)
Se = jnp.sum(k_gps, axis=0)
Fe = jnp.sum(f_gps, axis=0)
def compute_elem_res(Se,te ,Fe):
te = jax.lax.stop_gradient(te)
return (Se @ te - Fe)
element_residuals = compute_elem_res(Se,te ,Fe)
return ((te.T @ element_residuals)[0,0]), (Se @ te - Fe), Se
[docs]class ThermalLoss3DTetra(ThermalLoss):
"""
Thermal loss for 3D tetrahedral finite elements.
This class configures :class:`ThermalLoss` for three-dimensional problems
discretized with tetrahedral elements. The temperature field has a single
DOF per node (``T``), and the thermal loss is assembled using the weighted
residual formulation defined in the base class.
Args:
name (str):
Name identifier for the loss instance.
loss_settings (dict):
Dictionary containing thermal settings and optional nonlinear
conductivity parameters (e.g., ``"beta"`` and ``"c"``).
fe_mesh (Mesh):
Finite element mesh associated with the loss.
"""
@print_with_timestamp_and_execution_time
def __init__(self, name: str, loss_settings: dict, fe_mesh: Mesh):
super().__init__(name,{**loss_settings,"compute_dims":3,
"ordered_dofs": ["T"],
"element_type":"tetra"},fe_mesh)
[docs]class ThermalLoss3DHexa(ThermalLoss):
"""
Thermal loss for 3D hexahedral finite elements.
This class configures :class:`ThermalLoss` for three-dimensional problems
discretized with hexahedral elements. The temperature field has a single
DOF per node (``T``), and the thermal loss is assembled using the weighted
residual formulation defined in the base class.
If the number of Gauss points is not specified in the loss settings, a
default value of ``num_gp = 2`` is used.
Args:
name (str):
Name identifier for the loss instance.
loss_settings (dict):
Dictionary containing thermal settings, optional nonlinear
conductivity parameters, and optional integration settings.
fe_mesh (Mesh):
Finite element mesh associated with the loss.
"""
@print_with_timestamp_and_execution_time
def __init__(self, name: str, loss_settings: dict, fe_mesh: Mesh):
if not "num_gp" in loss_settings.keys():
loss_settings["num_gp"] = 2
super().__init__(name,{**loss_settings,"compute_dims":3,
"ordered_dofs": ["T"],
"element_type":"hexahedron"},fe_mesh)
[docs]class ThermalLoss2DQuad(ThermalLoss):
"""
Thermal loss for 2D quadrilateral finite elements.
This class configures :class:`ThermalLoss` for two-dimensional problems
discretized with quadrilateral elements. The temperature field has a single
DOF per node (``T``), and the thermal loss is assembled using the weighted
residual formulation defined in the base class.
If the number of Gauss points is not specified in the loss settings, a
default value of ``num_gp = 2`` is used.
Args:
name (str):
Name identifier for the loss instance.
loss_settings (dict):
Dictionary containing thermal settings, optional nonlinear
conductivity parameters, and optional integration settings.
fe_mesh (Mesh):
Finite element mesh associated with the loss.
"""
def __init__(self, name: str, loss_settings: dict, fe_mesh: Mesh):
if not "num_gp" in loss_settings.keys():
loss_settings["num_gp"] = 2
super().__init__(name,{**loss_settings,"compute_dims":2,
"ordered_dofs": ["T"],
"element_type":"quad"},fe_mesh)
[docs]class ThermalLoss2DTri(ThermalLoss):
"""
Thermal loss for 2D triangular finite elements.
This class configures :class:`ThermalLoss` for two-dimensional problems
discretized with triangular elements. The temperature field has a single
DOF per node (``T``), and the thermal loss is assembled using the weighted
residual formulation defined in the base class.
Args:
name (str):
Name identifier for the loss instance.
loss_settings (dict):
Dictionary containing thermal settings and optional nonlinear
conductivity parameters (e.g., ``"beta"`` and ``"c"``).
fe_mesh (Mesh):
Finite element mesh associated with the loss.
"""
def __init__(self, name: str, loss_settings: dict, fe_mesh: Mesh):
super().__init__(name,{**loss_settings,"compute_dims":2,
"ordered_dofs": ["T"],
"element_type":"triangle"},fe_mesh)