conspire/domain/fem/block/thermal/conduction/
mod.rs1#[cfg(test)]
2pub mod test;
3
4use crate::{
5 constitutive::thermal::conduction::ThermalConduction,
6 fem::{
7 ElementModelError,
8 block::{
9 Block,
10 element::{FiniteElementError, thermal::conduction::ThermalConductionFiniteElement},
11 thermal::{NodalTemperatures, ThermalElements},
12 },
13 thermal::conduction::ThermalConductionElements,
14 },
15 math::{Scalar, SquareMatrix, Vector},
16};
17
18pub type NodalForcesThermal = Vector;
19pub type NodalStiffnessesThermal = SquareMatrix;
20
21impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize> ThermalConductionElements
22 for Block<C, F, G, M, N, P>
23where
24 C: ThermalConduction,
25 F: ThermalConductionFiniteElement<C, G, M, N, P>,
26{
27 fn potential(
28 &self,
29 nodal_temperatures: &NodalTemperatures,
30 ) -> Result<Scalar, ElementModelError> {
31 match self
32 .elements()
33 .iter()
34 .zip(self.connectivity())
35 .map(|(element, element_connectivity)| {
36 element.potential(
37 self.constitutive_model(),
38 &self.nodal_temperatures_element(element_connectivity, nodal_temperatures),
39 )
40 })
41 .sum()
42 {
43 Ok(potential) => Ok(potential),
44 Err(error) => Err(ElementModelError::Upstream(
45 format!("{error}"),
46 format!("{self:?}"),
47 )),
48 }
49 }
50 fn nodal_forces_into(
51 &self,
52 nodal_temperatures: &NodalTemperatures,
53 nodal_forces: &mut NodalForcesThermal,
54 ) -> Result<(), ElementModelError> {
55 match self
56 .elements()
57 .iter()
58 .zip(self.connectivity())
59 .try_for_each(|(element, element_connectivity)| {
60 element
61 .nodal_forces(
62 self.constitutive_model(),
63 &self.nodal_temperatures_element(element_connectivity, nodal_temperatures),
64 )?
65 .into_iter()
66 .zip(element_connectivity)
67 .for_each(|(nodal_force, &node)| nodal_forces[node] += nodal_force);
68 Ok::<(), FiniteElementError>(())
69 }) {
70 Ok(()) => Ok(()),
71 Err(error) => Err(ElementModelError::Upstream(
72 format!("{error}"),
73 format!("{self:?}"),
74 )),
75 }
76 }
77 fn nodal_stiffnesses_into(
78 &self,
79 nodal_temperatures: &NodalTemperatures,
80 nodal_stiffnesses: &mut NodalStiffnessesThermal,
81 ) -> Result<(), ElementModelError> {
82 match self
83 .elements()
84 .iter()
85 .zip(self.connectivity())
86 .try_for_each(|(element, element_connectivity)| {
87 element
88 .nodal_stiffnesses(
89 self.constitutive_model(),
90 &self.nodal_temperatures_element(element_connectivity, nodal_temperatures),
91 )?
92 .into_iter()
93 .zip(element_connectivity)
94 .for_each(|(object, &node_a)| {
95 object.into_iter().zip(element_connectivity).for_each(
96 |(nodal_stiffness, &node_b)| {
97 nodal_stiffnesses[node_a][node_b] += nodal_stiffness
98 },
99 )
100 });
101 Ok::<(), FiniteElementError>(())
102 }) {
103 Ok(()) => Ok(()),
104 Err(error) => Err(ElementModelError::Upstream(
105 format!("{error}"),
106 format!("{self:?}"),
107 )),
108 }
109 }
110}