conspire/domain/boundary/
mod.rs1mod condition;
4
5pub use condition::{BoundaryCondition, BoundaryConditions, Enforcement};
6
7use crate::{
8 math::{
9 Current, Quantity, Tensor, TensorRank1, TensorTuple, TensorVector, optimize::Prescription,
10 },
11 units::{
12 Concentration as ConcentrationUnit, ElectricPotential, Length,
13 Temperature as TemperatureUnit, Velocity as VelocityUnit,
14 },
15};
16use std::marker::PhantomData;
17
18pub trait Layout {
20 const STRIDE: usize;
21}
22
23pub trait NodalDof {
25 type Layout: Layout;
26}
27
28pub trait NodalState {
30 type Layout: Layout;
31}
32
33pub struct Solid<const D: usize>;
35
36pub struct SolidRate<const D: usize>;
38
39pub struct Field<U>(PhantomData<U>);
41
42pub struct Coupled<A, B>(PhantomData<(A, B)>);
44
45pub type SolidThermal<const D: usize> = Coupled<Solid<D>, Field<TemperatureUnit>>;
47
48impl<const D: usize> Layout for Solid<D> {
49 const STRIDE: usize = D;
50}
51
52impl<const D: usize> Layout for SolidRate<D> {
53 const STRIDE: usize = D;
54}
55
56impl<U> Layout for Field<U> {
57 const STRIDE: usize = 1;
58}
59
60impl<A, B> Layout for Coupled<A, B>
61where
62 A: Layout,
63 B: Layout,
64{
65 const STRIDE: usize = A::STRIDE + B::STRIDE;
66}
67
68impl<const D: usize> NodalDof for TensorRank1<D, Current, Length> {
69 type Layout = Solid<D>;
70}
71
72impl<const D: usize> NodalDof for TensorRank1<D, Current, VelocityUnit> {
73 type Layout = SolidRate<D>;
74}
75
76impl<U> NodalDof for Quantity<U> {
77 type Layout = Field<U>;
78}
79
80impl<A, B> NodalDof for TensorTuple<A, B>
81where
82 A: NodalDof + Tensor,
83 B: NodalDof + Tensor,
84{
85 type Layout = Coupled<A::Layout, B::Layout>;
86}
87
88impl<N> NodalState for TensorVector<N>
89where
90 N: NodalDof,
91{
92 type Layout = N::Layout;
93}
94
95pub struct Direct;
97
98pub struct Left<I>(PhantomData<I>);
100
101pub struct Right<I>(PhantomData<I>);
103
104pub trait Component<L, I>
108where
109 L: Layout,
110{
111 const OFFSET: usize;
112}
113
114impl<A, B, C, I> Component<Coupled<A, B>, Left<I>> for C
115where
116 A: Layout,
117 B: Layout,
118 C: Component<A, I>,
119{
120 const OFFSET: usize = C::OFFSET;
121}
122
123impl<A, B, C, I> Component<Coupled<A, B>, Right<I>> for C
124where
125 A: Layout,
126 B: Layout,
127 C: Component<B, I>,
128{
129 const OFFSET: usize = A::STRIDE + C::OFFSET;
130}
131
132pub trait Prescribable {
136 type Value;
137 fn prescription(value: Self::Value) -> Prescription;
138}
139
140#[derive(Clone, Copy)]
142pub struct Displacement<const AXIS: usize>;
143
144#[derive(Clone, Copy)]
146pub struct Velocity<const AXIS: usize>;
147
148#[derive(Clone, Copy)]
150pub struct Temperature;
151
152#[derive(Clone, Copy)]
154pub struct Potential;
155
156#[derive(Clone, Copy)]
158pub struct Concentration;
159
160impl<const D: usize, const AXIS: usize> Component<Solid<D>, Direct> for Displacement<AXIS> {
161 const OFFSET: usize = {
162 assert!(AXIS < D, "The axis is not one of the dimensions.");
163 AXIS
164 };
165}
166
167impl<const D: usize, const AXIS: usize> Component<SolidRate<D>, Direct> for Velocity<AXIS> {
168 const OFFSET: usize = {
169 assert!(AXIS < D, "The axis is not one of the dimensions.");
170 AXIS
171 };
172}
173
174impl Component<Field<TemperatureUnit>, Direct> for Temperature {
175 const OFFSET: usize = 0;
176}
177
178impl Component<Field<ElectricPotential>, Direct> for Potential {
179 const OFFSET: usize = 0;
180}
181
182impl Component<Field<ConcentrationUnit>, Direct> for Concentration {
183 const OFFSET: usize = 0;
184}
185
186impl<const AXIS: usize> Prescribable for Displacement<AXIS> {
187 type Value = Quantity<Length>;
188 fn prescription(value: Self::Value) -> Prescription {
189 Prescription::Offset(value.value())
190 }
191}
192
193impl<const AXIS: usize> Prescribable for Velocity<AXIS> {
194 type Value = Quantity<VelocityUnit>;
195 fn prescription(value: Self::Value) -> Prescription {
196 Prescription::Absolute(value.value())
197 }
198}
199
200impl Prescribable for Temperature {
201 type Value = Quantity<TemperatureUnit>;
202 fn prescription(value: Self::Value) -> Prescription {
203 Prescription::Absolute(value.value())
204 }
205}
206
207impl Prescribable for Potential {
208 type Value = Quantity<ElectricPotential>;
209 fn prescription(value: Self::Value) -> Prescription {
210 Prescription::Absolute(value.value())
211 }
212}
213
214impl Prescribable for Concentration {
215 type Value = Quantity<ConcentrationUnit>;
216 fn prescription(value: Self::Value) -> Prescription {
217 Prescription::Absolute(value.value())
218 }
219}