conspire/domain/fem/solid/elastic_hyperviscous/
mod.rs1use crate::{
2 fem::{
3 Blocks, ElementModel, ElementModelError, Elements, Model, NodalCoordinates,
4 NodalCoordinatesHistory, NodalVelocities, NodalVelocitiesHistory,
5 block::{band_from_neighbors, finalize_node_neighbors},
6 solid::{NodalForcesSolid, NodalStiffnessesSolid, viscoelastic::ViscoelasticElements},
7 },
8 math::{
9 Scalar, Tensor,
10 integrate::{ImplicitDaeSecondOrderMinimize, IntegrationError},
11 optimize::{EqualityConstraint, SecondOrderOptimization},
12 },
13 mechanics::Times,
14};
15
16pub trait ElasticHyperviscousElements<const D: usize>
17where
18 Self: ViscoelasticElements<D>,
19{
20 fn viscous_dissipation(
21 &self,
22 nodal_coordinates: &NodalCoordinates<D>,
23 nodal_velocities: &NodalVelocities<D>,
24 ) -> Result<Scalar, ElementModelError>;
25 fn dissipation_potential(
26 &self,
27 nodal_coordinates: &NodalCoordinates<D>,
28 nodal_velocities: &NodalVelocities<D>,
29 ) -> Result<Scalar, ElementModelError>;
30}
31
32impl<B, const D: usize> ElasticHyperviscousElements<D> for Model<B, D>
33where
34 B: ElasticHyperviscousElements<D>,
35{
36 fn viscous_dissipation(
37 &self,
38 nodal_coordinates: &NodalCoordinates<D>,
39 nodal_velocities: &NodalVelocities<D>,
40 ) -> Result<Scalar, ElementModelError> {
41 self.blocks
42 .viscous_dissipation(nodal_coordinates, nodal_velocities)
43 }
44 fn dissipation_potential(
45 &self,
46 nodal_coordinates: &NodalCoordinates<D>,
47 nodal_velocities: &NodalVelocities<D>,
48 ) -> Result<Scalar, ElementModelError> {
49 self.blocks
50 .dissipation_potential(nodal_coordinates, nodal_velocities)
51 }
52}
53
54impl<B1, B2, const D: usize> ElasticHyperviscousElements<D> for Blocks<B1, B2>
55where
56 B1: ElasticHyperviscousElements<D>,
57 B2: ElasticHyperviscousElements<D>,
58{
59 fn viscous_dissipation(
60 &self,
61 nodal_coordinates: &NodalCoordinates<D>,
62 nodal_velocities: &NodalVelocities<D>,
63 ) -> Result<Scalar, ElementModelError> {
64 Ok(self
65 .0
66 .viscous_dissipation(nodal_coordinates, nodal_velocities)?
67 + self
68 .1
69 .viscous_dissipation(nodal_coordinates, nodal_velocities)?)
70 }
71 fn dissipation_potential(
72 &self,
73 nodal_coordinates: &NodalCoordinates<D>,
74 nodal_velocities: &NodalVelocities<D>,
75 ) -> Result<Scalar, ElementModelError> {
76 Ok(self
77 .0
78 .dissipation_potential(nodal_coordinates, nodal_velocities)?
79 + self
80 .1
81 .dissipation_potential(nodal_coordinates, nodal_velocities)?)
82 }
83}
84
85pub trait SecondOrderMinimize<const D: usize> {
86 fn minimize(
87 &self,
88 equality_constraint: EqualityConstraint,
89 integrator: impl ImplicitDaeSecondOrderMinimize<
90 Scalar,
91 NodalForcesSolid<D>,
92 NodalStiffnessesSolid<D>,
93 NodalVelocities<D>,
94 NodalVelocitiesHistory<D>,
95 >,
96 time: &[Scalar],
97 solver: impl SecondOrderOptimization<
98 Scalar,
99 NodalForcesSolid<D>,
100 NodalStiffnessesSolid<D>,
101 NodalCoordinates<D>,
102 >,
103 ) -> Result<(Times, NodalCoordinatesHistory<D>, NodalVelocitiesHistory<D>), IntegrationError>;
104}
105
106impl<B, const D: usize> SecondOrderMinimize<D> for Model<B, D>
107where
108 B: ElasticHyperviscousElements<D>,
109{
110 fn minimize(
111 &self,
112 equality_constraint: EqualityConstraint,
113 integrator: impl ImplicitDaeSecondOrderMinimize<
114 Scalar,
115 NodalForcesSolid<D>,
116 NodalStiffnessesSolid<D>,
117 NodalVelocities<D>,
118 NodalVelocitiesHistory<D>,
119 >,
120 time: &[Scalar],
121 solver: impl SecondOrderOptimization<
122 Scalar,
123 NodalForcesSolid<D>,
124 NodalStiffnessesSolid<D>,
125 NodalCoordinates<D>,
126 >,
127 ) -> Result<(Times, NodalCoordinatesHistory<D>, NodalVelocitiesHistory<D>), IntegrationError>
128 {
129 let mut neighbors = vec![Vec::new(); self.coordinates().len()];
130 self.node_neighbors(&mut neighbors);
131 finalize_node_neighbors(&mut neighbors);
132 let banded = band_from_neighbors(&neighbors, &equality_constraint, D);
133 integrator.integrate(
134 |_: Scalar,
135 nodal_coordinates: &NodalCoordinates<D>,
136 nodal_velocities: &NodalVelocities<D>| {
137 Ok(self.dissipation_potential(nodal_coordinates, nodal_velocities)?)
138 },
139 |_: Scalar,
140 nodal_coordinates: &NodalCoordinates<D>,
141 nodal_velocities: &NodalVelocities<D>| {
142 Ok(self.nodal_forces(nodal_coordinates, nodal_velocities)?)
143 },
144 |_: Scalar,
145 nodal_coordinates: &NodalCoordinates<D>,
146 nodal_velocities: &NodalVelocities<D>| {
147 Ok(self.nodal_stiffnesses(nodal_coordinates, nodal_velocities)?)
148 },
149 solver,
150 time,
151 self.coordinates().clone().into(),
152 |_: Scalar| equality_constraint.clone(),
153 Some(banded),
154 )
155 }
156}