conspire/domain/fem/block/element/thermal/conduction/
mod.rs1#[cfg(test)]
2pub mod test;
3
4use crate::{
5 constitutive::{ConstitutiveError, thermal::conduction::ThermalConduction},
6 fem::block::element::{
7 Element, FiniteElement, FiniteElementError,
8 thermal::{ElementNodalTemperatures, ThermalFiniteElement},
9 },
10 math::{ContractWith, Quantity, Tensor, TensorList},
11 mechanics::{HeatFluxTangents, HeatFluxes},
12 units::{Power, PowerPerTemperature, PowerTemperature},
13};
14
15pub type ElementNodalForcesThermal<const D: usize> = TensorList<Quantity<Power>, D>;
16pub type ElementNodalStiffnessesThermal<const D: usize> =
17 TensorList<ElementNodalForcesThermalPerTemperature<D>, D>;
18pub type ElementNodalForcesThermalPerTemperature<const D: usize> =
19 TensorList<Quantity<PowerPerTemperature>, D>;
20
21pub trait ThermalConductionFiniteElement<
22 C,
23 const G: usize,
24 const M: usize,
25 const N: usize,
26 const P: usize,
27> where
28 C: ThermalConduction,
29 Self: ThermalFiniteElement<G, M, N, P>,
30{
31 fn potential(
32 &self,
33 constitutive_model: &C,
34 nodal_temperatures: &ElementNodalTemperatures<N>,
35 ) -> Result<Quantity<PowerTemperature>, FiniteElementError>;
36 fn nodal_forces(
37 &self,
38 constitutive_model: &C,
39 nodal_temperatures: &ElementNodalTemperatures<N>,
40 ) -> Result<ElementNodalForcesThermal<N>, FiniteElementError>;
41 fn nodal_stiffnesses(
42 &self,
43 constitutive_model: &C,
44 nodal_temperatures: &ElementNodalTemperatures<N>,
45 ) -> Result<ElementNodalStiffnessesThermal<N>, FiniteElementError>;
46}
47
48impl<C, const G: usize, const M: usize, const N: usize, const O: usize, const P: usize>
49 ThermalConductionFiniteElement<C, G, M, N, P> for Element<3, G, N, O>
50where
51 C: ThermalConduction,
52 Self: ThermalFiniteElement<G, M, N, P>,
53{
54 fn potential(
55 &self,
56 constitutive_model: &C,
57 nodal_temperatures: &ElementNodalTemperatures<N>,
58 ) -> Result<Quantity<PowerTemperature>, FiniteElementError> {
59 self.temperature_gradients(nodal_temperatures)
60 .iter()
61 .zip(self.integration_weights())
62 .map(|(temperature_gradient, integration_weight)| {
63 Ok::<_, ConstitutiveError>(
64 constitutive_model.potential(temperature_gradient)? * integration_weight,
65 )
66 })
67 .sum::<Result<_, ConstitutiveError>>()
68 .map_err(|error| FiniteElementError::upstream(error, self))
69 }
70 fn nodal_forces(
71 &self,
72 constitutive_model: &C,
73 nodal_temperatures: &ElementNodalTemperatures<N>,
74 ) -> Result<ElementNodalForcesThermal<N>, FiniteElementError> {
75 let heat_fluxes = self
76 .temperature_gradients(nodal_temperatures)
77 .iter()
78 .map(|temperature_gradient| constitutive_model.heat_flux(temperature_gradient))
79 .collect::<Result<HeatFluxes<G>, _>>()
80 .map_err(|error| FiniteElementError::upstream(error, self))?;
81 Ok(heat_fluxes
82 .iter()
83 .zip(
84 self.gradient_vectors()
85 .iter()
86 .zip(self.integration_weights()),
87 )
88 .map(|(heat_flux, (gradient_vectors, integration_weight))| {
89 gradient_vectors
90 .iter()
91 .map(|gradient_vector| {
92 -heat_flux.contract_with(gradient_vector) * integration_weight
93 })
94 .collect()
95 })
96 .sum())
97 }
98 fn nodal_stiffnesses(
99 &self,
100 constitutive_model: &C,
101 nodal_temperatures: &ElementNodalTemperatures<N>,
102 ) -> Result<ElementNodalStiffnessesThermal<N>, FiniteElementError> {
103 let heat_flux_tangents = self
104 .temperature_gradients(nodal_temperatures)
105 .iter()
106 .map(|temperature_gradient| constitutive_model.heat_flux_tangent(temperature_gradient))
107 .collect::<Result<HeatFluxTangents<G>, _>>()
108 .map_err(|error| FiniteElementError::upstream(error, self))?;
109 Ok(heat_flux_tangents
110 .iter()
111 .zip(
112 self.gradient_vectors()
113 .iter()
114 .zip(self.integration_weights()),
115 )
116 .map(
117 |(heat_flux_tangent, (gradient_vectors, integration_weight))| {
118 gradient_vectors
119 .iter()
120 .map(|gradient_vector_a| {
121 gradient_vectors
122 .iter()
123 .map(|gradient_vector_b| {
124 -gradient_vector_a
125 .contract_with(&(heat_flux_tangent * gradient_vector_b))
126 * integration_weight
127 })
128 .collect()
129 })
130 .collect()
131 },
132 )
133 .sum())
134 }
135}