1#[cfg(test)]
19mod test;
20
21use super::{
22 Acceleration, Action, Amount, Area, Charge, Density, Dimensionless, Energy, Entropy, Force,
23 ForcePerLength, Length, Mass, MolarEnergy, MolarEntropy, PowerPerLengthTemperature, Rate,
24 ReciprocalAmount, ReciprocalTemperature, SpecificEnergy, Stress, StressPerLength, Temperature,
25 Time, Velocity, Viscosity, Volume,
26};
27use crate::math::{Quantity, TensorRank0};
28
29const ZERO_CELSIUS: TensorRank0 = 273.15;
31
32pub type Scale<U> = fn(TensorRank0) -> Quantity<U>;
34
35pub fn length_scale(label: &str) -> Option<Scale<Length>> {
44 Some(match label.trim().to_lowercase().as_str() {
45 "m" | "meter" | "meters" | "metre" | "metres" => Length::meters,
46 "mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Length::millimeters,
47 "cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Length::centimeters,
48 "um" | "\u{b5}m" | "\u{3bc}m" | "micrometer" | "micrometers" | "micrometre"
49 | "micrometres" | "micron" | "microns" => Length::micrometers,
50 "nm" | "nanometer" | "nanometers" | "nanometre" | "nanometres" => Length::nanometers,
51 "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Length::kilometers,
52 "in" | "inch" | "inches" => Length::inches,
53 "ft" | "foot" | "feet" => Length::feet,
54 _ => return None,
55 })
56}
57
58macro_rules! scales {
64 ($($unit:ident { $($name:ident / $reader:ident = $factor:expr, $doc:expr),+ $(,)? })+) => {
65 $(
66 impl $unit {
67 $(
68 #[doc = concat!("A quantity of ", $doc, ".")]
69 pub const fn $name(value: TensorRank0) -> Quantity<$unit> {
70 Quantity::new(value * $factor)
71 }
72 )+
73 }
74 impl Quantity<$unit> {
75 $(
76 #[doc = concat!("How many ", $doc, " the quantity is.")]
77 pub const fn $reader(&self) -> TensorRank0 {
78 self.value() / $factor
79 }
80 )+
81 }
82 )+
83 };
84}
85
86scales!(
87 Length {
88 meters / in_meters = 1.0, "metres",
89 millimeters / in_millimeters = 1e-3, "millimetres",
90 micrometers / in_micrometers = 1e-6, "micrometres",
91 nanometers / in_nanometers = 1e-9, "nanometres",
92 centimeters / in_centimeters = 1e-2, "centimetres",
93 kilometers / in_kilometers = 1e3, "kilometres",
94 inches / in_inches = 2.54e-2, "inches",
95 feet / in_feet = 3.048e-1, "feet",
96 }
97 Area {
98 square_meters / in_square_meters = 1.0, "square metres",
99 square_millimeters / in_square_millimeters = 1e-6, "square millimetres",
100 square_centimeters / in_square_centimeters = 1e-4, "square centimetres",
101 }
102 Volume {
103 cubic_meters / in_cubic_meters = 1.0, "cubic metres",
104 cubic_millimeters / in_cubic_millimeters = 1e-9, "cubic millimetres",
105 cubic_centimeters / in_cubic_centimeters = 1e-6, "cubic centimetres",
106 liters / in_liters = 1e-3, "litres",
107 }
108 Time {
109 seconds / in_seconds = 1.0, "seconds",
110 milliseconds / in_milliseconds = 1e-3, "milliseconds",
111 microseconds / in_microseconds = 1e-6, "microseconds",
112 minutes / in_minutes = 6e1, "minutes",
113 hours / in_hours = 3.6e3, "hours",
114 }
115 Rate {
116 per_second / in_per_second = 1.0, "reciprocal seconds",
117 per_minute / in_per_minute = 1.0 / 6e1, "reciprocal minutes",
118 per_hour / in_per_hour = 1.0 / 3.6e3, "reciprocal hours",
119 hertz / in_hertz = 1.0, "hertz",
120 }
121 Stress {
122 pascals / in_pascals = 1.0, "pascals",
123 kilopascals / in_kilopascals = 1e3, "kilopascals",
124 megapascals / in_megapascals = 1e6, "megapascals",
125 gigapascals / in_gigapascals = 1e9, "gigapascals",
126 bars / in_bars = 1e5, "bars",
127 psi / in_psi = 6.894_757_293_168_361e3, "pounds per square inch",
128 ksi / in_ksi = 6.894_757_293_168_361e6, "kips per square inch",
129 }
130 Force {
131 newtons / in_newtons = 1.0, "newtons",
132 millinewtons / in_millinewtons = 1e-3, "millinewtons",
133 kilonewtons / in_kilonewtons = 1e3, "kilonewtons",
134 meganewtons / in_meganewtons = 1e6, "meganewtons",
135 pounds_force / in_pounds_force = 4.448_221_615_260_5, "pounds force",
136 }
137 Energy {
138 joules / in_joules = 1.0, "joules",
139 millijoules / in_millijoules = 1e-3, "millijoules",
140 kilojoules / in_kilojoules = 1e3, "kilojoules",
141 electronvolts / in_electronvolts = 1.602_176_634e-19, "electronvolts",
142 }
143 Entropy {
144 joules_per_kelvin / in_joules_per_kelvin = 1.0, "joules per kelvin",
145 }
146 Action {
147 joule_seconds / in_joule_seconds = 1.0, "joule seconds",
148 }
149 Amount {
150 moles / in_moles = 1.0, "moles",
151 millimoles / in_millimoles = 1e-3, "millimoles",
152 }
153 ReciprocalAmount {
154 per_mole / in_per_mole = 1.0, "reciprocal moles",
155 }
156 MolarEntropy {
157 joules_per_mole_kelvin / in_joules_per_mole_kelvin = 1.0, "joules per mole kelvin",
158 }
159 MolarEnergy {
160 joules_per_mole / in_joules_per_mole = 1.0, "joules per mole",
161 kilojoules_per_mole / in_kilojoules_per_mole = 1e3, "kilojoules per mole",
162 }
163 ForcePerLength {
164 newtons_per_meter / in_newtons_per_meter = 1.0, "newtons per metre",
165 piconewtons_per_nanometer / in_piconewtons_per_nanometer = 1e-3,
166 "piconewtons per nanometre",
167 }
168 Velocity {
169 meters_per_second / in_meters_per_second = 1.0, "metres per second",
170 millimeters_per_second / in_millimeters_per_second = 1e-3, "millimetres per second",
171 kilometers_per_hour / in_kilometers_per_hour = 1.0 / 3.6, "kilometres per hour",
172 }
173 Acceleration {
174 meters_per_second_squared / in_meters_per_second_squared = 1.0,
175 "metres per second squared",
176 standard_gravities / in_standard_gravities = 9.806_65, "standard gravities",
177 }
178 Mass {
179 kilograms / in_kilograms = 1.0, "kilograms",
180 grams / in_grams = 1e-3, "grams",
181 milligrams / in_milligrams = 1e-6, "milligrams",
182 tonnes / in_tonnes = 1e3, "tonnes",
183 pounds_mass / in_pounds_mass = 4.535_923_7e-1, "pounds mass",
184 }
185 Density {
186 kilograms_per_cubic_meter / in_kilograms_per_cubic_meter = 1.0,
187 "kilograms per cubic metre",
188 grams_per_cubic_centimeter / in_grams_per_cubic_centimeter = 1e3,
189 "grams per cubic centimetre",
190 tonnes_per_cubic_millimeter / in_tonnes_per_cubic_millimeter = 1e12,
191 "tonnes per cubic millimetre",
192 }
193 SpecificEnergy {
194 joules_per_kilogram / in_joules_per_kilogram = 1.0, "joules per kilogram",
195 }
196 Charge {
197 coulombs / in_coulombs = 1.0, "coulombs",
198 }
199 Viscosity {
200 pascal_seconds / in_pascal_seconds = 1.0, "pascal seconds",
201 poise / in_poise = 1e-1, "poise",
202 centipoise / in_centipoise = 1e-3, "centipoise",
203 }
204 Temperature {
205 kelvin / in_kelvin = 1.0, "kelvin",
206 }
207 ReciprocalTemperature {
208 per_kelvin / in_per_kelvin = 1.0, "reciprocal kelvin",
209 per_celsius / in_per_celsius = 1.0, "reciprocal degrees celsius",
210 }
211 StressPerLength {
212 pascals_per_meter / in_pascals_per_meter = 1.0, "pascals per metre",
213 megapascals_per_millimeter / in_megapascals_per_millimeter = 1e9,
214 "megapascals per millimetre",
215 }
216 PowerPerLengthTemperature {
217 watts_per_meter_kelvin / in_watts_per_meter_kelvin = 1.0, "watts per metre kelvin",
218 }
219 Dimensionless {
220 percent / in_percent = 1e-2, "percent",
221 }
222);
223
224impl Dimensionless {
225 pub const fn of(value: TensorRank0) -> Quantity<Dimensionless> {
231 Quantity::new(value)
232 }
233}
234
235impl Temperature {
236 pub const fn celsius(value: TensorRank0) -> Quantity<Temperature> {
242 Quantity::new(value + ZERO_CELSIUS)
243 }
244 pub const fn fahrenheit(value: TensorRank0) -> Quantity<Temperature> {
249 Quantity::new((value - 32.0) * 5.0 / 9.0 + ZERO_CELSIUS)
250 }
251}
252
253impl Quantity<Temperature> {
254 pub const fn in_celsius(&self) -> TensorRank0 {
256 self.value() - ZERO_CELSIUS
257 }
258 pub const fn in_fahrenheit(&self) -> TensorRank0 {
260 (self.value() - ZERO_CELSIUS) * 9.0 / 5.0 + 32.0
261 }
262}