Skip to main content

conspire/domain/fem/block/thermal/conduction/
mod.rs

1#[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}