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, STANDARD_GRAVITY,
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
77/// The unit whose square this unit is, which a square root carries.
78///
79/// Left unimplemented for units that are no square this library names, so that
80/// taking the root of such a quantity fails to compile.
81pub trait UnitRoot {
82    /// The unit of the square root.
83    type Output;
84}
85
86macro_rules! units {
87    ($($(#[$meta:meta])* $name:ident),+ $(,)?) => {
88        $(
89            $(#[$meta])*
90            #[derive(Clone, Copy, Debug, PartialEq, Eq)]
91            pub struct $name;
92            impl Unit for $name {}
93            impl UnitMul<Dimensionless> for $name {
94                type Output = $name;
95            }
96            impl UnitDiv<Dimensionless> for $name {
97                type Output = $name;
98            }
99            impl UnitHalves for $name {
100                type First = $name;
101                type Second = $name;
102            }
103            impl UnitSum for $name {
104                type Output = $name;
105            }
106        )+
107    };
108}
109
110units!(
111    /// A quantity carrying no unit.
112    Dimensionless,
113    /// A length.
114    Length,
115    /// A reciprocal length.
116    ReciprocalLength,
117    /// An area.
118    Area,
119    /// A reciprocal area.
120    ReciprocalArea,
121    /// A volume.
122    Volume,
123    /// A second moment of area, being an area squared.
124    SecondMomentOfArea,
125    /// A velocity, being a length per unit time.
126    Velocity,
127    /// An acceleration, being a velocity per unit time.
128    Acceleration,
129    /// A mass.
130    Mass,
131    /// A density, being a mass per unit volume.
132    Density,
133    /// A specific energy, being an energy per unit mass, and equally a squared velocity.
134    SpecificEnergy,
135    /// A force.
136    Force,
137    /// A force per unit length, as a stiffness is.
138    ForcePerLength,
139    /// A force per unit velocity, as a damping is.
140    ForcePerVelocity,
141    /// An energy.
142    Energy,
143    /// A power.
144    Power,
145    /// A stress per unit length, as a force per unit volume is.
146    StressPerLength,
147    /// A stress per unit area, as a stiffness per unit volume is.
148    StressPerArea,
149    /// A viscosity per unit length.
150    ViscosityPerLength,
151    /// A viscosity per unit area, as a damping per unit volume is.
152    ViscosityPerArea,
153    /// A stress, and equally a stiffness, being a stress per unit strain.
154    Stress,
155    /// A squared stress.
156    StressSquared,
157    /// A reciprocal stress, as a compliance is.
158    ReciprocalStress,
159    /// A time.
160    Time,
161    /// A rate, being a reciprocal time.
162    Rate,
163    /// A squared rate, being a squared reciprocal time.
164    RateSquared,
165    /// A viscosity, being a stress per unit rate.
166    Viscosity,
167    /// A fluidity, being the reciprocal of a viscosity.
168    ReciprocalViscosity,
169    /// A temperature.
170    Temperature,
171    /// A reciprocal temperature, as a coefficient of thermal expansion is.
172    ReciprocalTemperature,
173    /// A stress per unit temperature, as a thermal stress coefficient is.
174    StressPerTemperature,
175    /// A power per unit volume, as a dissipation is.
176    PowerDensity,
177    /// A temperature per unit length, as a temperature gradient is.
178    TemperaturePerLength,
179    /// A power per unit area, as a heat flux is.
180    PowerPerArea,
181    /// A power per unit length per unit temperature, as a thermal conductivity is.
182    PowerPerLengthTemperature,
183    /// A power per unit area per unit temperature, as a heat flux per unit temperature is.
184    PowerPerAreaTemperature,
185    /// A power per unit volume per unit temperature, as an entropy production rate per unit volume is.
186    PowerPerVolumeTemperature,
187    /// A power per unit temperature, as a thermal stiffness is.
188    PowerPerTemperature,
189    /// A power times a temperature, as the potential a heat flux derives from is.
190    PowerTemperature,
191    /// A power times a temperature per unit volume.
192    PowerTemperatureDensity,
193    /// An entropy, and equally the Boltzmann constant, being an energy per unit temperature.
194    Entropy,
195    /// An action, being an energy times a time, as the Planck constant is.
196    Action,
197    /// An amount of substance.
198    Amount,
199    /// A reciprocal amount of substance, as the Avogadro constant is.
200    ReciprocalAmount,
201    /// A molar entropy, as the gas constant is, being an entropy per unit amount.
202    MolarEntropy,
203    /// A molar energy, being an energy per unit amount.
204    MolarEnergy,
205    /// An electric charge, as the elementary charge is.
206    Charge,
207    /// A reciprocal stiffness, as a compliance conjugate to a force is.
208    ReciprocalForcePerLength,
209);
210
211macro_rules! unit_products {
212    ($($lhs:ident * $rhs:ident = $out:ident),+ $(,)?) => {
213        $(
214            impl UnitMul<$rhs> for $lhs {
215                type Output = $out;
216            }
217            impl UnitDiv<$rhs> for $out {
218                type Output = $lhs;
219            }
220        )+
221    };
222}
223
224impl UnitRoot for Dimensionless {
225    type Output = Dimensionless;
226}
227
228impl UnitRoot for RateSquared {
229    type Output = Rate;
230}
231
232impl UnitRoot for StressSquared {
233    type Output = Stress;
234}
235
236impl UnitRoot for SpecificEnergy {
237    type Output = Velocity;
238}
239
240unit_products!(
241    Dimensionless * Length = Length,
242    Dimensionless * ReciprocalLength = ReciprocalLength,
243    Dimensionless * Stress = Stress,
244    Dimensionless * Rate = Rate,
245    Dimensionless * Viscosity = Viscosity,
246    Dimensionless * Temperature = Temperature,
247    Viscosity * Rate = Stress,
248    Dimensionless * ReciprocalViscosity = ReciprocalViscosity,
249    Stress * ReciprocalViscosity = Rate,
250    ReciprocalViscosity * Stress = Rate,
251    Rate * Viscosity = Stress,
252    Length * ReciprocalLength = Dimensionless,
253    Dimensionless * ReciprocalStress = ReciprocalStress,
254    Stress * ReciprocalStress = Dimensionless,
255    ReciprocalStress * Stress = Dimensionless,
256    Dimensionless * ReciprocalTemperature = ReciprocalTemperature,
257    Temperature * ReciprocalTemperature = Dimensionless,
258    Dimensionless * StressPerTemperature = StressPerTemperature,
259    Stress * ReciprocalTemperature = StressPerTemperature,
260    StressPerTemperature * Temperature = Stress,
261    ReciprocalTemperature * Temperature = Dimensionless,
262    ReciprocalLength * Length = Dimensionless,
263    Dimensionless * Time = Time,
264    Rate * Time = Dimensionless,
265    Time * Rate = Dimensionless,
266    Dimensionless * RateSquared = RateSquared,
267    Rate * Rate = RateSquared,
268    Dimensionless * StressSquared = StressSquared,
269    Stress * Stress = StressSquared,
270    Stress * Time = Viscosity,
271    Dimensionless * PowerDensity = PowerDensity,
272    Stress * Rate = PowerDensity,
273    Rate * Stress = PowerDensity,
274    Dimensionless * Area = Area,
275    Dimensionless * ReciprocalArea = ReciprocalArea,
276    Dimensionless * Volume = Volume,
277    Dimensionless * SecondMomentOfArea = SecondMomentOfArea,
278    Dimensionless * Velocity = Velocity,
279    Dimensionless * Force = Force,
280    Dimensionless * ForcePerLength = ForcePerLength,
281    Dimensionless * ForcePerVelocity = ForcePerVelocity,
282    Dimensionless * Energy = Energy,
283    Dimensionless * Power = Power,
284    Dimensionless * StressPerLength = StressPerLength,
285    Dimensionless * StressPerArea = StressPerArea,
286    Dimensionless * ViscosityPerLength = ViscosityPerLength,
287    Dimensionless * ViscosityPerArea = ViscosityPerArea,
288    Length * Length = Area,
289    Length * Area = Volume,
290    Area * Length = Volume,
291    Area * Area = SecondMomentOfArea,
292    Length * Volume = SecondMomentOfArea,
293    Volume * Length = SecondMomentOfArea,
294    Area * ReciprocalArea = Dimensionless,
295    ReciprocalArea * Area = Dimensionless,
296    Length * ReciprocalArea = ReciprocalLength,
297    ReciprocalArea * Length = ReciprocalLength,
298    ReciprocalLength * ReciprocalLength = ReciprocalArea,
299    ReciprocalLength * Volume = Area,
300    ReciprocalLength * Area = Length,
301    Area * ReciprocalLength = Length,
302    Length * Rate = Velocity,
303    Rate * Length = Velocity,
304    Velocity * Time = Length,
305    Velocity * ReciprocalLength = Rate,
306    ReciprocalLength * Velocity = Rate,
307    Stress * Area = Force,
308    Area * Stress = Force,
309    Stress * Volume = Energy,
310    Force * Length = Energy,
311    Force * ReciprocalLength = ForcePerLength,
312    ForcePerLength * Length = Force,
313    Length * ForcePerLength = Force,
314    Velocity * ForcePerVelocity = Force,
315    Stress * ReciprocalLength = StressPerLength,
316    ReciprocalLength * Stress = StressPerLength,
317    StressPerLength * ReciprocalLength = StressPerArea,
318    StressPerLength * Length = Stress,
319    Length * StressPerLength = Stress,
320    StressPerLength * Area = ForcePerLength,
321    StressPerLength * Volume = Force,
322    StressPerArea * Volume = ForcePerLength,
323    Viscosity * ReciprocalLength = ViscosityPerLength,
324    ReciprocalLength * Viscosity = ViscosityPerLength,
325    ViscosityPerLength * ReciprocalLength = ViscosityPerArea,
326    ViscosityPerArea * Volume = ForcePerVelocity,
327    ForcePerVelocity * Velocity = Force,
328    Force * Velocity = Power,
329    PowerDensity * Volume = Power,
330    Energy * Rate = Power,
331    Power * Time = Energy,
332    Dimensionless * TemperaturePerLength = TemperaturePerLength,
333    Dimensionless * PowerPerArea = PowerPerArea,
334    Dimensionless * PowerPerLengthTemperature = PowerPerLengthTemperature,
335    Dimensionless * PowerPerAreaTemperature = PowerPerAreaTemperature,
336    Dimensionless * PowerPerVolumeTemperature = PowerPerVolumeTemperature,
337    Dimensionless * PowerPerTemperature = PowerPerTemperature,
338    Dimensionless * PowerTemperature = PowerTemperature,
339    Dimensionless * PowerTemperatureDensity = PowerTemperatureDensity,
340    Temperature * ReciprocalLength = TemperaturePerLength,
341    ReciprocalLength * Temperature = TemperaturePerLength,
342    TemperaturePerLength * PowerPerLengthTemperature = PowerPerArea,
343    PowerPerLengthTemperature * TemperaturePerLength = PowerPerArea,
344    PowerPerArea * ReciprocalLength = PowerDensity,
345    ReciprocalLength * PowerPerArea = PowerDensity,
346    PowerPerArea * TemperaturePerLength = PowerTemperatureDensity,
347    PowerTemperatureDensity * Volume = PowerTemperature,
348    PowerPerLengthTemperature * ReciprocalLength = PowerPerAreaTemperature,
349    ReciprocalLength * PowerPerLengthTemperature = PowerPerAreaTemperature,
350    PowerPerAreaTemperature * ReciprocalLength = PowerPerVolumeTemperature,
351    ReciprocalLength * PowerPerAreaTemperature = PowerPerVolumeTemperature,
352    PowerDensity * ReciprocalTemperature = EntropyDensityRate,
353    EntropyDensity * Rate = EntropyDensityRate,
354    PowerPerVolumeTemperature * Volume = PowerPerTemperature,
355    Power * Temperature = PowerTemperature,
356    PowerPerTemperature * Temperature = Power,
357    Temperature * PowerPerTemperature = Power,
358    Dimensionless * Entropy = Entropy,
359    Entropy * Temperature = Energy,
360    Temperature * Entropy = Energy,
361    Dimensionless * Action = Action,
362    Dimensionless * Amount = Amount,
363    Dimensionless * ReciprocalAmount = ReciprocalAmount,
364    Dimensionless * MolarEntropy = MolarEntropy,
365    Dimensionless * MolarEnergy = MolarEnergy,
366    Dimensionless * Charge = Charge,
367    Energy * Time = Action,
368    Time * Energy = Action,
369    Action * Rate = Energy,
370    Rate * Action = Energy,
371    Amount * ReciprocalAmount = Dimensionless,
372    ReciprocalAmount * Amount = Dimensionless,
373    Entropy * ReciprocalAmount = MolarEntropy,
374    ReciprocalAmount * Entropy = MolarEntropy,
375    MolarEntropy * Amount = Entropy,
376    MolarEntropy * Temperature = MolarEnergy,
377    Temperature * MolarEntropy = MolarEnergy,
378    Energy * ReciprocalAmount = MolarEnergy,
379    ReciprocalAmount * Energy = MolarEnergy,
380    MolarEnergy * Amount = Energy,
381    Dimensionless * ReciprocalForcePerLength = ReciprocalForcePerLength,
382    ReciprocalLength * Energy = Force,
383    Energy * ReciprocalLength = Force,
384    ReciprocalArea * Energy = ForcePerLength,
385    Energy * ReciprocalArea = ForcePerLength,
386    ForcePerLength * ReciprocalLength = Stress,
387    ReciprocalLength * ForcePerLength = Stress,
388    ForcePerLength * Area = Energy,
389    Area * ForcePerLength = Energy,
390    ReciprocalForcePerLength * Energy = Area,
391    Energy * ReciprocalForcePerLength = Area,
392    Length * Force = Energy,
393    ReciprocalForcePerLength * Force = Length,
394    Force * ReciprocalForcePerLength = Length,
395    Stress * Length = ForcePerLength,
396    Length * Stress = ForcePerLength,
397    Dimensionless * Acceleration = Acceleration,
398    Dimensionless * Mass = Mass,
399    Dimensionless * Density = Density,
400    Velocity * Rate = Acceleration,
401    Rate * Velocity = Acceleration,
402    Length * RateSquared = Acceleration,
403    RateSquared * Length = Acceleration,
404    Acceleration * Time = Velocity,
405    Time * Acceleration = Velocity,
406    Density * Volume = Mass,
407    Volume * Density = Mass,
408    Mass * Acceleration = Force,
409    Acceleration * Mass = Force,
410    Mass * RateSquared = ForcePerLength,
411    RateSquared * Mass = ForcePerLength,
412    Density * Acceleration = StressPerLength,
413    Acceleration * Density = StressPerLength,
414    Dimensionless * SpecificEnergy = SpecificEnergy,
415    Velocity * Velocity = SpecificEnergy,
416    Mass * SpecificEnergy = Energy,
417    SpecificEnergy * Mass = Energy,
418    Density * SpecificEnergy = Stress,
419    SpecificEnergy * Density = Stress,
420);
421
422impl<A, B, C, D> UnitMul<(C, D)> for (A, B)
423where
424    A: UnitMul<C>,
425    B: UnitMul<D>,
426{
427    type Output = (<A as UnitMul<C>>::Output, <B as UnitMul<D>>::Output);
428}
429
430impl<A, B, C, D> UnitDiv<(C, D)> for (A, B)
431where
432    A: UnitDiv<C>,
433    B: UnitDiv<D>,
434{
435    type Output = (<A as UnitDiv<C>>::Output, <B as UnitDiv<D>>::Output);
436}
437
438macro_rules! unit_inverses {
439    ($($unit:ident => $inverse:ident),+ $(,)?) => {
440        $(
441            impl UnitInv for $unit {
442                type Output = $inverse;
443            }
444        )+
445    };
446}
447
448unit_inverses!(
449    Dimensionless => Dimensionless,
450    Length => ReciprocalLength,
451    ReciprocalLength => Length,
452    Area => ReciprocalArea,
453    ReciprocalArea => Area,
454    Stress => ReciprocalStress,
455    ReciprocalStress => Stress,
456    Temperature => ReciprocalTemperature,
457    ReciprocalTemperature => Temperature,
458    Viscosity => ReciprocalViscosity,
459    ReciprocalViscosity => Viscosity,
460    Time => Rate,
461    Rate => Time,
462    Amount => ReciprocalAmount,
463    ReciprocalAmount => Amount,
464    ForcePerLength => ReciprocalForcePerLength,
465    ReciprocalForcePerLength => ForcePerLength,
466);
467
468/// A pressure.
469pub type Pressure = Stress;
470
471/// An energy per unit volume.
472pub type EnergyDensity = Stress;
473
474/// An elastic modulus.
475pub type Modulus = Stress;
476
477/// A compliance.
478pub type Compliance = ReciprocalStress;
479
480/// A fluidity.
481pub type Fluidity = ReciprocalViscosity;
482
483/// A coefficient of thermal expansion.
484pub type ThermalExpansion = ReciprocalTemperature;
485
486/// A frequency.
487pub type Frequency = Rate;
488
489/// A dissipation, being a power per unit volume.
490pub type Dissipation = PowerDensity;
491
492/// An entropy per unit volume.
493pub type EntropyDensity = StressPerTemperature;
494
495/// An entropy production rate per unit volume.
496pub type EntropyDensityRate = PowerPerVolumeTemperature;