Skip to main content

conspire/units/
mod.rs

1//! Dimensional analysis.
2
3#[cfg(test)]
4mod test;
5
6mod constants;
7mod scale;
8
9pub use constants::{
10    AVOGADRO_CONSTANT, BOLTZMANN_CONSTANT, ELEMENTARY_CHARGE, GAS_CONSTANT, LIGHT_SPEED,
11    PLANCK_CONSTANT, ROOM_TEMPERATURE,
12};
13pub use scale::{Scale, length_scale};
14
15/// The physical unit a tensor carries.
16///
17/// Tensors may only be added when their units agree, and multiplying them
18/// combines their units through [`UnitMul`], all of which is checked when the
19/// operations are compiled rather than when they run.
20pub trait Unit {}
21
22/// The unit obtained by multiplying by `Rhs`.
23pub trait UnitMul<Rhs> {
24    /// The unit of the product.
25    type Output;
26}
27
28/// The unit obtained by dividing by `Rhs`.
29pub trait UnitDiv<Rhs> {
30    /// The unit of the quotient.
31    type Output;
32}
33
34/// The units the halves of a tuple take from a unit meant for the pair.
35///
36/// A tuple is scaled either by a step in one variable, which both halves take,
37/// or by a quantity whose unit is the pair the halves already carry. Naming both
38/// through one trait keeps a single scaling rule for tuples rather than two that
39/// would overlap.
40pub trait UnitHalves {
41    /// The unit the first half takes.
42    type First;
43    /// The unit the second half takes.
44    type Second;
45}
46
47impl<A, B> UnitHalves for (A, B) {
48    type First = A;
49    type Second = B;
50}
51
52/// The unit a sum of parts carries, which is the unit each part carries.
53///
54/// A merit adds the halves of a tuple's contraction together, so a pair whose
55/// halves agree is that unit once. Left unimplemented for a pair whose halves
56/// differ, since adding those names nothing. Implemented concretely rather than
57/// blanketly for the same reason [`UnitHalves`] is: a blanket identity would
58/// overlap the pair.
59pub trait UnitSum {
60    /// The unit of the sum.
61    type Output;
62}
63
64impl<A> UnitSum for (A, A) {
65    type Output = A;
66}
67
68/// The unit obtained by inverting.
69///
70/// Left unimplemented for units whose inverse names no quantity, so that
71/// inverting such a tensor fails to compile.
72pub trait UnitInv {
73    /// The unit of the inverse.
74    type Output;
75}
76
77macro_rules! units {
78    ($($(#[$meta:meta])* $name:ident),+ $(,)?) => {
79        $(
80            $(#[$meta])*
81            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
82            pub struct $name;
83            impl Unit for $name {}
84            impl UnitMul<Dimensionless> for $name {
85                type Output = $name;
86            }
87            impl UnitDiv<Dimensionless> for $name {
88                type Output = $name;
89            }
90            impl UnitHalves for $name {
91                type First = $name;
92                type Second = $name;
93            }
94            impl UnitSum for $name {
95                type Output = $name;
96            }
97        )+
98    };
99}
100
101units!(
102    /// A quantity carrying no unit.
103    Dimensionless,
104    /// A length.
105    Length,
106    /// A reciprocal length.
107    ReciprocalLength,
108    /// An area.
109    Area,
110    /// A reciprocal area.
111    ReciprocalArea,
112    /// A volume.
113    Volume,
114    /// A second moment of area, being an area squared.
115    SecondMomentOfArea,
116    /// A velocity, being a length per unit time.
117    Velocity,
118    /// A force.
119    Force,
120    /// A force per unit length, as a stiffness is.
121    ForcePerLength,
122    /// A force per unit velocity, as a damping is.
123    ForcePerVelocity,
124    /// An energy.
125    Energy,
126    /// A power.
127    Power,
128    /// A stress per unit length, as a force per unit volume is.
129    StressPerLength,
130    /// A stress per unit area, as a stiffness per unit volume is.
131    StressPerArea,
132    /// A viscosity per unit length.
133    ViscosityPerLength,
134    /// A viscosity per unit area, as a damping per unit volume is.
135    ViscosityPerArea,
136    /// A stress, and equally a stiffness, being a stress per unit strain.
137    Stress,
138    /// A reciprocal stress, as a compliance is.
139    ReciprocalStress,
140    /// A time.
141    Time,
142    /// A rate, being a reciprocal time.
143    Rate,
144    /// A viscosity, being a stress per unit rate.
145    Viscosity,
146    /// A fluidity, being the reciprocal of a viscosity.
147    ReciprocalViscosity,
148    /// A temperature.
149    Temperature,
150    /// A reciprocal temperature, as a coefficient of thermal expansion is.
151    ReciprocalTemperature,
152    /// A stress per unit temperature, as a thermal stress coefficient is.
153    StressPerTemperature,
154    /// A power per unit volume, as a dissipation is.
155    PowerDensity,
156    /// A temperature per unit length, as a temperature gradient is.
157    TemperaturePerLength,
158    /// A power per unit area, as a heat flux is.
159    PowerPerArea,
160    /// A power per unit length per unit temperature, as a thermal conductivity is.
161    PowerPerLengthTemperature,
162    /// A power per unit area per unit temperature, as a heat flux per unit temperature is.
163    PowerPerAreaTemperature,
164    /// A power per unit volume per unit temperature.
165    PowerPerVolumeTemperature,
166    /// A power per unit temperature, as a thermal stiffness is.
167    PowerPerTemperature,
168    /// A power times a temperature, as the potential a heat flux derives from is.
169    PowerTemperature,
170    /// A power times a temperature per unit volume.
171    PowerTemperatureDensity,
172    /// An entropy, and equally the Boltzmann constant, being an energy per unit temperature.
173    Entropy,
174    /// An action, being an energy times a time, as the Planck constant is.
175    Action,
176    /// An amount of substance.
177    Amount,
178    /// A reciprocal amount of substance, as the Avogadro constant is.
179    ReciprocalAmount,
180    /// A molar entropy, as the gas constant is, being an entropy per unit amount.
181    MolarEntropy,
182    /// A molar energy, being an energy per unit amount.
183    MolarEnergy,
184    /// An electric charge, as the elementary charge is.
185    Charge,
186    /// A reciprocal stiffness, as a compliance conjugate to a force is.
187    ReciprocalForcePerLength,
188);
189
190macro_rules! unit_products {
191    ($($lhs:ident * $rhs:ident = $out:ident),+ $(,)?) => {
192        $(
193            impl UnitMul<$rhs> for $lhs {
194                type Output = $out;
195            }
196            impl UnitDiv<$rhs> for $out {
197                type Output = $lhs;
198            }
199        )+
200    };
201}
202
203unit_products!(
204    Dimensionless * Length = Length,
205    Dimensionless * ReciprocalLength = ReciprocalLength,
206    Dimensionless * Stress = Stress,
207    Dimensionless * Rate = Rate,
208    Dimensionless * Viscosity = Viscosity,
209    Dimensionless * Temperature = Temperature,
210    Viscosity * Rate = Stress,
211    Dimensionless * ReciprocalViscosity = ReciprocalViscosity,
212    Stress * ReciprocalViscosity = Rate,
213    ReciprocalViscosity * Stress = Rate,
214    Rate * Viscosity = Stress,
215    Length * ReciprocalLength = Dimensionless,
216    Dimensionless * ReciprocalStress = ReciprocalStress,
217    Stress * ReciprocalStress = Dimensionless,
218    ReciprocalStress * Stress = Dimensionless,
219    Dimensionless * ReciprocalTemperature = ReciprocalTemperature,
220    Temperature * ReciprocalTemperature = Dimensionless,
221    Dimensionless * StressPerTemperature = StressPerTemperature,
222    Stress * ReciprocalTemperature = StressPerTemperature,
223    StressPerTemperature * Temperature = Stress,
224    ReciprocalTemperature * Temperature = Dimensionless,
225    ReciprocalLength * Length = Dimensionless,
226    Dimensionless * Time = Time,
227    Rate * Time = Dimensionless,
228    Time * Rate = Dimensionless,
229    Stress * Time = Viscosity,
230    Dimensionless * PowerDensity = PowerDensity,
231    Stress * Rate = PowerDensity,
232    Rate * Stress = PowerDensity,
233    Dimensionless * Area = Area,
234    Dimensionless * ReciprocalArea = ReciprocalArea,
235    Dimensionless * Volume = Volume,
236    Dimensionless * SecondMomentOfArea = SecondMomentOfArea,
237    Dimensionless * Velocity = Velocity,
238    Dimensionless * Force = Force,
239    Dimensionless * ForcePerLength = ForcePerLength,
240    Dimensionless * ForcePerVelocity = ForcePerVelocity,
241    Dimensionless * Energy = Energy,
242    Dimensionless * Power = Power,
243    Dimensionless * StressPerLength = StressPerLength,
244    Dimensionless * StressPerArea = StressPerArea,
245    Dimensionless * ViscosityPerLength = ViscosityPerLength,
246    Dimensionless * ViscosityPerArea = ViscosityPerArea,
247    Length * Length = Area,
248    Length * Area = Volume,
249    Area * Length = Volume,
250    Area * Area = SecondMomentOfArea,
251    Length * Volume = SecondMomentOfArea,
252    Volume * Length = SecondMomentOfArea,
253    Area * ReciprocalArea = Dimensionless,
254    ReciprocalArea * Area = Dimensionless,
255    Length * ReciprocalArea = ReciprocalLength,
256    ReciprocalArea * Length = ReciprocalLength,
257    ReciprocalLength * ReciprocalLength = ReciprocalArea,
258    ReciprocalLength * Volume = Area,
259    ReciprocalLength * Area = Length,
260    Area * ReciprocalLength = Length,
261    Length * Rate = Velocity,
262    Rate * Length = Velocity,
263    Velocity * Time = Length,
264    Velocity * ReciprocalLength = Rate,
265    ReciprocalLength * Velocity = Rate,
266    Stress * Area = Force,
267    Area * Stress = Force,
268    Stress * Volume = Energy,
269    Force * Length = Energy,
270    Force * ReciprocalLength = ForcePerLength,
271    ForcePerLength * Length = Force,
272    Length * ForcePerLength = Force,
273    Velocity * ForcePerVelocity = Force,
274    Stress * ReciprocalLength = StressPerLength,
275    ReciprocalLength * Stress = StressPerLength,
276    StressPerLength * ReciprocalLength = StressPerArea,
277    StressPerLength * Length = Stress,
278    Length * StressPerLength = Stress,
279    StressPerLength * Area = ForcePerLength,
280    StressPerLength * Volume = Force,
281    StressPerArea * Volume = ForcePerLength,
282    Viscosity * ReciprocalLength = ViscosityPerLength,
283    ReciprocalLength * Viscosity = ViscosityPerLength,
284    ViscosityPerLength * ReciprocalLength = ViscosityPerArea,
285    ViscosityPerArea * Volume = ForcePerVelocity,
286    ForcePerVelocity * Velocity = Force,
287    Force * Velocity = Power,
288    PowerDensity * Volume = Power,
289    Energy * Rate = Power,
290    Power * Time = Energy,
291    Dimensionless * TemperaturePerLength = TemperaturePerLength,
292    Dimensionless * PowerPerArea = PowerPerArea,
293    Dimensionless * PowerPerLengthTemperature = PowerPerLengthTemperature,
294    Dimensionless * PowerPerAreaTemperature = PowerPerAreaTemperature,
295    Dimensionless * PowerPerVolumeTemperature = PowerPerVolumeTemperature,
296    Dimensionless * PowerPerTemperature = PowerPerTemperature,
297    Dimensionless * PowerTemperature = PowerTemperature,
298    Dimensionless * PowerTemperatureDensity = PowerTemperatureDensity,
299    Temperature * ReciprocalLength = TemperaturePerLength,
300    ReciprocalLength * Temperature = TemperaturePerLength,
301    TemperaturePerLength * PowerPerLengthTemperature = PowerPerArea,
302    PowerPerLengthTemperature * TemperaturePerLength = PowerPerArea,
303    PowerPerArea * ReciprocalLength = PowerDensity,
304    ReciprocalLength * PowerPerArea = PowerDensity,
305    PowerPerArea * TemperaturePerLength = PowerTemperatureDensity,
306    PowerTemperatureDensity * Volume = PowerTemperature,
307    PowerPerLengthTemperature * ReciprocalLength = PowerPerAreaTemperature,
308    ReciprocalLength * PowerPerLengthTemperature = PowerPerAreaTemperature,
309    PowerPerAreaTemperature * ReciprocalLength = PowerPerVolumeTemperature,
310    ReciprocalLength * PowerPerAreaTemperature = PowerPerVolumeTemperature,
311    PowerPerVolumeTemperature * Volume = PowerPerTemperature,
312    Power * Temperature = PowerTemperature,
313    PowerPerTemperature * Temperature = Power,
314    Temperature * PowerPerTemperature = Power,
315    Dimensionless * Entropy = Entropy,
316    Entropy * Temperature = Energy,
317    Temperature * Entropy = Energy,
318    Dimensionless * Action = Action,
319    Dimensionless * Amount = Amount,
320    Dimensionless * ReciprocalAmount = ReciprocalAmount,
321    Dimensionless * MolarEntropy = MolarEntropy,
322    Dimensionless * MolarEnergy = MolarEnergy,
323    Dimensionless * Charge = Charge,
324    Energy * Time = Action,
325    Time * Energy = Action,
326    Action * Rate = Energy,
327    Rate * Action = Energy,
328    Amount * ReciprocalAmount = Dimensionless,
329    ReciprocalAmount * Amount = Dimensionless,
330    Entropy * ReciprocalAmount = MolarEntropy,
331    ReciprocalAmount * Entropy = MolarEntropy,
332    MolarEntropy * Amount = Entropy,
333    MolarEntropy * Temperature = MolarEnergy,
334    Temperature * MolarEntropy = MolarEnergy,
335    Energy * ReciprocalAmount = MolarEnergy,
336    ReciprocalAmount * Energy = MolarEnergy,
337    MolarEnergy * Amount = Energy,
338    Dimensionless * ReciprocalForcePerLength = ReciprocalForcePerLength,
339    ReciprocalLength * Energy = Force,
340    Energy * ReciprocalLength = Force,
341    ReciprocalArea * Energy = ForcePerLength,
342    Energy * ReciprocalArea = ForcePerLength,
343    ForcePerLength * ReciprocalLength = Stress,
344    ReciprocalLength * ForcePerLength = Stress,
345    ForcePerLength * Area = Energy,
346    Area * ForcePerLength = Energy,
347    ReciprocalForcePerLength * Energy = Area,
348    Energy * ReciprocalForcePerLength = Area,
349    Length * Force = Energy,
350    ReciprocalForcePerLength * Force = Length,
351    Force * ReciprocalForcePerLength = Length,
352    Stress * Length = ForcePerLength,
353    Length * Stress = ForcePerLength,
354);
355
356impl<A, B, C, D> UnitMul<(C, D)> for (A, B)
357where
358    A: UnitMul<C>,
359    B: UnitMul<D>,
360{
361    type Output = (<A as UnitMul<C>>::Output, <B as UnitMul<D>>::Output);
362}
363
364impl<A, B, C, D> UnitDiv<(C, D)> for (A, B)
365where
366    A: UnitDiv<C>,
367    B: UnitDiv<D>,
368{
369    type Output = (<A as UnitDiv<C>>::Output, <B as UnitDiv<D>>::Output);
370}
371
372macro_rules! unit_inverses {
373    ($($unit:ident => $inverse:ident),+ $(,)?) => {
374        $(
375            impl UnitInv for $unit {
376                type Output = $inverse;
377            }
378        )+
379    };
380}
381
382unit_inverses!(
383    Dimensionless => Dimensionless,
384    Length => ReciprocalLength,
385    ReciprocalLength => Length,
386    Area => ReciprocalArea,
387    ReciprocalArea => Area,
388    Stress => ReciprocalStress,
389    ReciprocalStress => Stress,
390    Temperature => ReciprocalTemperature,
391    ReciprocalTemperature => Temperature,
392    Viscosity => ReciprocalViscosity,
393    ReciprocalViscosity => Viscosity,
394    Time => Rate,
395    Rate => Time,
396    Amount => ReciprocalAmount,
397    ReciprocalAmount => Amount,
398    ForcePerLength => ReciprocalForcePerLength,
399    ReciprocalForcePerLength => ForcePerLength,
400);
401
402/// A pressure.
403pub type Pressure = Stress;
404
405/// An energy per unit volume.
406pub type EnergyDensity = Stress;
407
408/// An elastic modulus.
409pub type Modulus = Stress;
410
411/// A compliance.
412pub type Compliance = ReciprocalStress;
413
414/// A fluidity.
415pub type Fluidity = ReciprocalViscosity;
416
417/// A coefficient of thermal expansion.
418pub type ThermalExpansion = ReciprocalTemperature;
419
420/// A frequency.
421pub type Frequency = Rate;
422
423/// A dissipation, being a power per unit volume.
424pub type Dissipation = PowerDensity;