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::{Quantity, QuantitySparseVec2D, QuantityVector},
16    units::{Power, PowerPerTemperature, PowerTemperature},
17};
18
19pub type NodalForcesThermal = QuantityVector<Power>;
20pub type NodalStiffnessesThermal = QuantitySparseVec2D<PowerPerTemperature>;
21
22impl<C, F, const G: usize, const M: usize, const N: usize, const P: usize> ThermalConductionElements
23    for Block<C, F, G, M, N, P>
24where
25    C: ThermalConduction,
26    F: ThermalConductionFiniteElement<C, G, M, N, P>,
27{
28    fn potential(
29        &self,
30        nodal_temperatures: &NodalTemperatures,
31    ) -> Result<Quantity<PowerTemperature>, ElementModelError> {
32        self.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::<Result<Quantity<PowerTemperature>, FiniteElementError>>()
42            .map_err(|error| ElementModelError::upstream(error, self))
43    }
44    fn nodal_forces_into(
45        &self,
46        nodal_temperatures: &NodalTemperatures,
47        nodal_forces: &mut NodalForcesThermal,
48    ) -> Result<(), ElementModelError> {
49        self.elements()
50            .iter()
51            .zip(self.connectivity())
52            .try_for_each(|(element, element_connectivity)| {
53                element
54                    .nodal_forces(
55                        self.constitutive_model(),
56                        &self.nodal_temperatures_element(element_connectivity, nodal_temperatures),
57                    )?
58                    .into_iter()
59                    .zip(element_connectivity)
60                    .for_each(|(nodal_force, &node)| nodal_forces[node] += nodal_force);
61                Ok::<(), FiniteElementError>(())
62            })
63            .map_err(|error| ElementModelError::upstream(error, self))
64    }
65    fn nodal_stiffnesses_into(
66        &self,
67        nodal_temperatures: &NodalTemperatures,
68        nodal_stiffnesses: &mut NodalStiffnessesThermal,
69    ) -> Result<(), ElementModelError> {
70        self.elements()
71            .iter()
72            .zip(self.connectivity())
73            .try_for_each(|(element, element_connectivity)| {
74                element
75                    .nodal_stiffnesses(
76                        self.constitutive_model(),
77                        &self.nodal_temperatures_element(element_connectivity, nodal_temperatures),
78                    )?
79                    .into_iter()
80                    .zip(element_connectivity)
81                    .for_each(|(object, &node_a)| {
82                        object.into_iter().zip(element_connectivity).for_each(
83                            |(nodal_stiffness, &node_b)| {
84                                nodal_stiffnesses[node_a][node_b] += nodal_stiffness
85                            },
86                        )
87                    });
88                Ok::<(), FiniteElementError>(())
89            })
90            .map_err(|error| ElementModelError::upstream(error, self))
91    }
92}