001/* 002 * International System of Units (SI) 003 * Copyright (c) 2005-2021, Jean-Marie Dautelle, Werner Keil and others. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, 008 * are permitted provided that the following conditions are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright notice, 011 * this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 014 * and the following disclaimer in the documentation and/or other materials provided with the distribution. 015 * 016 * 3. Neither the name of SI System, Units of Measurement nor the names of their contributors may be used to 017 * endorse or promote products derived from this software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package si.uom; 031 032import static tech.units.indriya.AbstractUnit.ONE; 033 034import javax.measure.Quantity; 035import javax.measure.Unit; 036import javax.measure.quantity.Acceleration; 037import javax.measure.quantity.Angle; 038import javax.measure.quantity.Dimensionless; 039import javax.measure.quantity.ElectricCharge; 040import javax.measure.quantity.Energy; 041import javax.measure.quantity.Length; 042import javax.measure.quantity.Mass; 043 044import si.uom.quantity.*; 045import tech.units.indriya.AbstractUnit; 046import tech.units.indriya.format.SimpleUnitFormat; 047import tech.units.indriya.function.MultiplyConverter; 048import tech.units.indriya.unit.AlternateUnit; 049import tech.units.indriya.unit.ProductUnit; 050import tech.units.indriya.unit.TransformedUnit; 051import tech.units.indriya.unit.Units; 052 053/** 054 * <p> 055 * This class defines all SI (Système International d'Unités) base units and 056 * derived units as well as units that are accepted for use with the SI units. 057 * </p> 058 * 059 * @see <a href= 060 * "http://en.wikipedia.org/wiki/International_System_of_Units">Wikipedia: 061 * International System of Units</a> 062 * @see <a href="http://physics.nist.gov/cuu/Units/outside.html">Units outside 063 * the SI that are accepted for use with the SI</a> 064 * @see <a href="https://www.bipm.org/en/publications/si-brochure/">SI Brochure: 065 * The International System of Units (SI)</a> 066 * @see MetricPrefix 067 * 068 * @noextend This class is not intended to be extended by clients. 069 * 070 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 071 * @author <a href="mailto:werner@uom.si">Werner Keil</a> 072 * @version 2.8, May 20, 2021 073 */ 074public final class SI extends Units { 075 /** 076 * The singleton instance. 077 */ 078 private static final SI INSTANCE = new SI(); 079 080 /** 081 * Default constructor (prevents this class from being instantiated). 082 */ 083 private SI() { 084 } 085 086 /** 087 * Returns the singleton instance of this class. 088 * 089 * @return the metric system instance. 090 */ 091 public static SI getInstance() { 092 return INSTANCE; 093 } 094 095 //////////////////////////////// 096 // SI DERIVED ALTERNATE UNITS // 097 //////////////////////////////// 098 099 /** 100 * The SI unit for magnetomotive force (standard name <code>At</code>). 101 */ 102 public static final AlternateUnit<MagnetomotiveForce> AMPERE_TURN = addUnit( 103 new AlternateUnit<MagnetomotiveForce>(AMPERE, "At"), MagnetomotiveForce.class); 104 105 ////////////////////////////// 106 // SI DERIVED PRODUCT UNITS // 107 ////////////////////////////// 108 109 /** 110 * The SI unit for acceleration quantities (standard name <code>m/s2</code>). 111 */ 112 public static final Unit<Acceleration> METRE_PER_SQUARE_SECOND = addUnit( 113 new ProductUnit<Acceleration>(METRE_PER_SECOND.divide(SECOND)), Acceleration.class); 114 115 /** 116 * The SI unit for absement quantities (standard name <code>m.s</code>). 117 * @see <a href="https://en.wikipedia.org/wiki/Absement"> Wikipedia: 118 * Absement</a> 119 */ 120 public static final Unit<Absement> METRE_SECOND = addUnit( 121 new ProductUnit<Absement>(METRE.multiply(SECOND)), Absement.class); 122 123 /** 124 * The SI unit for action quantities (standard name <code>J.s</code>). 125 */ 126 public static final Unit<Action> JOULE_SECOND = addUnit(new ProductUnit<Action>(JOULE.multiply(SECOND)), 127 Action.class); 128 129 /** 130 * The SI unit for electric permittivity (standard name <code>ε</code>, 131 * <code>F/m </code> or <code>F·m−1</code>). In electromagnetism, absolute 132 * permittivity is the measure of resistance that is encountered when forming an 133 * electric field in a medium. 134 */ 135 public static final Unit<ElectricPermittivity> FARAD_PER_METRE = addUnit( 136 new ProductUnit<ElectricPermittivity>(FARAD.divide(METRE)), ElectricPermittivity.class); 137 138 /** 139 * The SI unit for electrical conductivity, <code>S/m</code>). 140 * @see <a href="https://en.wikipedia.org/wiki/Electrical_resistivity_and_conductivity">Wikipedia: Electrical resistivity and conductivity</a> 141 */ 142 public static final Unit<ElectricalConductivity> SIEMENS_PER_METRE = addUnit( 143 new ProductUnit<ElectricalConductivity>(SIEMENS.divide(METRE)), ElectricalConductivity.class); 144 145 /** 146 * The SI unit for electrical resistivity, <code>Ω⋅m</code>). 147 * @see <a href="https://en.wikipedia.org/wiki/Electrical_resistivity_and_conductivity">Wikipedia: Electrical resistivity and conductivity</a> 148 */ 149 public static final Unit<ElectricalResistivity> OHM_METRE = addUnit( 150 new ProductUnit<ElectricalResistivity>(OHM.multiply(METRE)), ElectricalResistivity.class); 151 152 /** 153 * The SI unit for magnetic permeability quantities (standard name 154 * <code>N/A2</code>). 155 */ 156 public static final Unit<MagneticPermeability> NEWTON_PER_SQUARE_AMPERE = addUnit( 157 new ProductUnit<MagneticPermeability>(NEWTON.divide(AMPERE.pow(2))), MagneticPermeability.class); 158 159 /** 160 * The SI unit for wave number quantities (standard name <code>1/m</code>). 161 */ 162 public static final Unit<WaveNumber> RECIPROCAL_METRE = addUnit(new ProductUnit<WaveNumber>(METRE.pow(-1)), 163 WaveNumber.class); 164 165 /** 166 * The SI unit for dynamic viscosity quantities (standard name 167 * <code>Pa.s</code>). 168 */ 169 public static final Unit<DynamicViscosity> PASCAL_SECOND = addUnit( 170 new ProductUnit<DynamicViscosity>(PASCAL.multiply(SECOND)), DynamicViscosity.class); 171 172 /** 173 * Luminance is a photometric measure of the luminous intensity per unit area of 174 * light travelling in a given direction. It describes the amount of light that 175 * passes through, is emitted or reflected from a particular area, and falls 176 * within a given solid angle. The SI unit for luminance is candela per square 177 * metre (<code>cd/m2</code>). 178 * 179 * @see <a href="https://en.wikipedia.org/wiki/Luminance"> Wikipedia: 180 * Luminance</a> 181 */ 182 public static final Unit<Luminance> CANDELA_PER_SQUARE_METRE = addUnit( 183 new ProductUnit<Luminance>(CANDELA.divide(SQUARE_METRE)), Luminance.class); 184 185 /** 186 * The SI unit for kinematic viscosity quantities (standard name 187 * <code>m2/s"</code>). 188 */ 189 public static final Unit<KinematicViscosity> SQUARE_METRE_PER_SECOND = addUnit( 190 new ProductUnit<KinematicViscosity>(SQUARE_METRE.divide(SECOND)), KinematicViscosity.class); 191 192 /** 193 * The SI unit for magnetic field strength quantities (standard name 194 * <code>A/m"</code>). 195 */ 196 public static final Unit<MagneticFieldStrength> AMPERE_PER_METRE = addUnit( 197 new ProductUnit<MagneticFieldStrength>(AMPERE.divide(METRE)), MagneticFieldStrength.class); 198 199 /** 200 * The SI unit for ionizing radiation quantities (standard name 201 * <code>C/kg"</code>). 202 */ 203 public static final Unit<IonizingRadiation> COULOMB_PER_KILOGRAM = addUnit( 204 new ProductUnit<IonizingRadiation>(COULOMB.divide(KILOGRAM)), IonizingRadiation.class); 205 206 /** 207 * The SI unit for radiant intensity (standard name <code>W/sr</code>). 208 */ 209 public static final Unit<RadiantIntensity> WATT_PER_STERADIAN = addUnit( 210 WATT.divide(STERADIAN).asType(RadiantIntensity.class)); 211 212 /** 213 * The SI unit for radiance (standard name <code>W⋅sr−1⋅m−2</code>). 214 */ 215 public static final Unit<Radiance> WATT_PER_STERADIAN_PER_SQUARE_METRE = addUnit( 216 WATT_PER_STERADIAN.divide(SQUARE_METRE).asType(Radiance.class)); 217 218 /** 219 * The SI unit for intensity (standard name <code>W/m<sup>2</sup></code>). 220 */ 221 public static final Unit<Intensity> WATT_PER_SQUARE_METRE = addUnit( 222 WATT.divide(SQUARE_METRE).asType(Intensity.class)); 223 224 /** 225 * The SI unit of angular speed (standard name <code>rad/s</code>). 226 * 227 * @see AngularSpeed 228 */ 229 public static final Unit<AngularSpeed> RADIAN_PER_SECOND = addUnit( 230 new ProductUnit<AngularSpeed>(RADIAN.divide(SECOND)), "Radian per second", AngularSpeed.class); 231 232 /** 233 * The SI unit of angular acceleration (standard name <code>rad/s²</code>). 234 * 235 * @see AngularAcceleration 236 */ 237 public static final Unit<AngularAcceleration> RADIAN_PER_SQUARE_SECOND = addUnit( 238 new ProductUnit<AngularAcceleration>(RADIAN_PER_SECOND.divide(SECOND)), "Radian per square second", 239 AngularAcceleration.class); 240 241 /** 242 * An energy unit accepted for use with SI units (standard name 243 * <code>eV</code>). The electronvolt is the kinetic energy acquired by an 244 * electron passing through a potential difference of 1 V in vacuum. The value 245 * must be obtained by experiment, and is therefore not known exactly. 246 */ 247 public static final Unit<Energy> ELECTRON_VOLT = addUnit( 248 new TransformedUnit<Energy>(JOULE, MultiplyConverter.of(1.602176487E-19)), "Electron Volt", "eV"); 249 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 250 251 /** 252 * A mass unit accepted for use with SI units (standard name <code>u</code>). 253 * The unified atomic mass unit is equal to 1/12 of the mass of an unbound atom 254 * of the nuclide 12C, at rest and in its ground state. The value must be 255 * obtained by experiment, and is therefore not known exactly. 256 */ 257 public static final Unit<Mass> UNIFIED_ATOMIC_MASS = addUnit( 258 new TransformedUnit<Mass>(KILOGRAM, MultiplyConverter.of(1.660538782E-27)), "Unified atomic mass", "u", 259 true); 260 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 261 262 /** 263 * A length unit accepted for use with SI units (standard name <code>UA</code>). 264 * The astronomical unit is a unit of length. 265 * Originally conceived as the average of Earth's aphelion and perihelion, 266 * since 2012 it has been defined as exactly 149,597,870,700 metres, 267 * or about 150 million kilometres (93 million miles). 268 * 269 * @see <a href="https://en.wikipedia.org/wiki/Astronomical_unit"> Wikipedia: Astronomical unit</a> 270 */ 271 public static final Unit<Length> ASTRONOMICAL_UNIT = addUnit( 272 new TransformedUnit<Length>(METRE, MultiplyConverter.of(149597870700d)), 273 "Astronomical Unit", "UA"); 274 275 /** 276 * An angle unit accepted for use with SI units (standard name 277 * <code>rev</code>). 278 */ 279 public static final Unit<Angle> REVOLUTION = addUnit(new TransformedUnit<Angle>(RADIAN, 280 MultiplyConverter.ofPiExponent(1).concatenate(MultiplyConverter.ofRational(2, 1))), 281 "Revolution", "rev"); 282 283 /** 284 * A kilogram per second (kg/s) is the derived SI unit of mass flow rate.<br> 285 * 286 * @see <a href="https://en.wikipedia.org/wiki/Mass_flow_rate"> Wikipedia: 287 * Mass flow rate</a> 288 */ 289 public static final Unit<MassFlowRate> KILOGRAM_PER_SECOND = addUnit( 290 new ProductUnit<MassFlowRate>(KILOGRAM.divide(SECOND)), MassFlowRate.class); 291 292 /** 293 * The newton-second (also newton second; symbol: N⋅s or N s)[1] is the derived SI unit of impulse.<br> 294 * It is dimensionally equivalent to the momentum unit kilogram-metre per second (kg⋅m/s).<br> 295 * One newton-second corresponds to a one-newton force applied for one second. 296 * 297 * @see <a href="https://en.wikipedia.org/wiki/Impulse_(physics)">Wikipedia: Impulse (physics)</a> 298 * @see #KILOGRAM_METRE_PER_SECOND 299 */ 300 public static final Unit<Impulse> NEWTON_SECOND = addUnit( 301 new ProductUnit<Impulse>(NEWTON.multiply(SECOND)), Impulse.class); 302 303 /** 304 * A kilogram-metre per second (kg⋅m/s) is the derived SI unit of momentum.<br> 305 * It is dimensionally equivalent to the newton-second.<br> 306 * One newton-second corresponds to a one-newton force applied for one second. 307 * 308 * @see #NEWTON_SECOND 309 * @see <a href="https://en.wikipedia.org/wiki/Momentum"> Wikipedia: 310 * Momentum</a> 311 */ 312 public static final Unit<Momentum> KILOGRAM_METRE_PER_SECOND = addUnit( 313 new ProductUnit<Momentum>(KILOGRAM.multiply(METRE_PER_SECOND)), Momentum.class); 314 315 /** 316 * A kilogram per second (kg/m2) is the derived SI unit of area density. 317 * 318 * @see <a href="https://en.wikipedia.org/wiki/Area_density"> Wikipedia: 319 * Area density</a> 320 */ 321 public static final Unit<AreaDensity> KILOGRAM_PER_SQUARE_METRE = addUnit( 322 new ProductUnit<AreaDensity>(KILOGRAM.divide(SQUARE_METRE)), AreaDensity.class); 323 324 /** 325 * A gray per second (kg⋅m/s) is the derived SI unit of radiation absorbed dose rate.<br> 326 * 327 * @see <a href="https://en.wikipedia.org/wiki/Absorbed_dose"> Wikipedia: 328 * Absorbed dose</a> 329 */ 330 public static final Unit<RadiationDoseAbsorbedRate> GRAY_PER_SECOND = addUnit( 331 new ProductUnit<RadiationDoseAbsorbedRate>(GRAY.divide(SECOND)), RadiationDoseAbsorbedRate.class); 332 333 334 /////////////////////////// 335 // Fundamental Constants // 336 /////////////////////////// 337 338 /** 339 * Holds the numeric value of the Avogadro constant. 340 */ 341 static final double AVOGADRO_CONSTANT_VALUE = 6.02214199E23; // (1/mol). 342 343 /** 344 * Holds the numeric value of the Boltzmann constant. 345 */ 346 static final double BOLTZMANN_CONSTANT_VALUE = 1.3806485279E-23; 347 348 /** 349 * Holds the electric charge value of one electron. 350 */ 351 static final double ELEMENTARY_CHARGE_VALUE = 1.602176462E-19; // (C). 352 353 /** 354 * Holds the numeric value of the Planck constant. 355 */ 356 static final double PLANCK_CONSTANT_VALUE = 6.62607015E-34; // (1/mol). 357 358 /** 359 * The Avogadro constant, named after scientist Amedeo Avogadro, is the number 360 * of constituent particles, usually molecules, atoms or ions that are contained 361 * in the amount of substance given by one mole. It is the proportionality 362 * factor that relates the molar mass of a substance to the mass of a sample, is 363 * designated with the symbol <code>N<sub>A<sub></code> or <code>L</code>, and has the 364 * value 6.022140857(74)×1023 mol−1 in the International System of Units (SI). 365 */ 366 public static final Unit<Dimensionless> AVOGADRO_CONSTANT = addUnit( 367 new AlternateUnit<Dimensionless>(ONE.divide(MOLE), "m-1").multiply(AVOGADRO_CONSTANT_VALUE), "NA", true); // (1/mol). 368 369 /** 370 * The Boltzmann constant (<code>k<sub>B</sub></code> or <code>k</code>) is a physical 371 * constant named after its discoverer, Ludwig Boltzmann, which relates the 372 * average relative kinetic energy of particles in a gas with the temperature of 373 * the gas and occurs in Planck's law of black-body radiation and in Boltzmann's 374 * entropy formula. 375 */ 376 public static final Unit<Dimensionless> BOLTZMANN_CONSTANT = addUnit( 377 new AlternateUnit<Dimensionless>(JOULE.divide(KELVIN), "J/K").multiply(BOLTZMANN_CONSTANT_VALUE), "kB", 378 true); 379 380 /** 381 * The elementary charge, usually denoted by <code>e</code> or sometimes 382 * <code>qe</code>, is the electric charge carried by a single proton or, 383 * equivalently, the magnitude of the electric charge carried by a single 384 * electron, which has charge −1 e. This elementary charge is a fundamental 385 * physical constant. To avoid confusion over its sign, e is sometimes called 386 * the elementary positive charge. 387 */ 388 public static final Unit<ElectricCharge> ELEMENTARY_CHARGE = addUnit(COULOMB.multiply(ELEMENTARY_CHARGE_VALUE), "e", 389 true); 390 391 /** 392 * The Planck constant (denoted <code>ℎ</code>, also called Planck's constant) 393 * is a physical constant that is the quantum of electromagnetic action, which 394 * relates the energy carried by a photon to its frequency. A photon's energy is 395 * equal to its frequency multiplied by the Planck constant. The Planck constant 396 * is of fundamental importance in quantum mechanics, and in metrology it is the 397 * basis for the definition of the kilogram. 398 */ 399 public static final Unit<Action> PLANCK_CONSTANT = addUnit(JOULE_SECOND.multiply(PLANCK_CONSTANT_VALUE), "\u210E", true); 400 401 ///////////////////// 402 // Collection View // 403 ///////////////////// 404 405 @Override 406 public String getName() { 407 return "SI"; 408 } 409 410 /** 411 * Adds a new unit not mapped to any specified quantity type. 412 * 413 * @param unit the unit being added. 414 * @return <code>unit</code>. 415 */ 416 private static <U extends Unit<?>> U addUnit(U unit) { 417 INSTANCE.units.add(unit); 418 return unit; 419 } 420 421 /** 422 * Adds a new unit not mapped to any specified quantity type and puts a text as 423 * symbol or label. 424 * 425 * @param unit the unit being added. 426 * @param name the string to use as name 427 * @param text the string to use as label or symbol 428 * @param isLabel if the string should be used as a label or not 429 * @return <code>unit</code>. 430 */ 431 private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) { 432 if (isLabel) { 433 SimpleUnitFormat.getInstance().label(unit, text); 434 } 435 if (name != null && unit instanceof AbstractUnit) { 436 return Helper.addUnit(INSTANCE.units, unit, name); 437 } else { 438 INSTANCE.units.add(unit); 439 } 440 return unit; 441 } 442 443 /** 444 * Adds a new unit not mapped to any specified quantity type and puts a text as 445 * symbol or label. 446 * 447 * @param unit the unit being added. 448 * @param text the string to use as label or symbol 449 * @param isLabel if the string should be used as a label or not 450 * @return <code>unit</code>. 451 */ 452 private static <U extends Unit<?>> U addUnit(U unit, String text, boolean isLabel) { 453 return addUnit(unit, null, text, isLabel); 454 } 455 456 /** 457 * Adds a new unit not mapped to any specified quantity type and puts a text as 458 * symbol or label. 459 * 460 * @param unit the unit being added. 461 * @param name the string to use as name 462 * @param label the string to use as label 463 * @return <code>unit</code>. 464 */ 465 private static <U extends Unit<?>> U addUnit(U unit, String name, String label) { 466 return addUnit(unit, name, label, true); 467 } 468 469 /** 470 * Adds a new unit with name and label and maps it to the specified quantity 471 * type. 472 * 473 * @param unit the unit being added. 474 * @param name the string to use as name 475 * @param label the string to use as label 476 * @param type the quantity type. 477 * @return <code>unit</code>. 478 */ 479 @SuppressWarnings("unused") 480 private static <U extends AbstractUnit<?>> U addUnit(U unit, String name, String label, 481 Class<? extends Quantity<?>> type) { 482 INSTANCE.quantityToUnit.put(type, unit); 483 return addUnit(unit, name, label); 484 } 485 486 /** 487 * Adds a new unit with a name and maps it to the specified quantity type. 488 * 489 * @param unit the unit being added. 490 * @param name the string to use as name 491 * @param type the quantity type. 492 * @return <code>unit</code>. 493 */ 494 private static <U extends AbstractUnit<?>> U addUnit(U unit, String name, Class<? extends Quantity<?>> type) { 495 INSTANCE.quantityToUnit.put(type, unit); 496 return addUnit(unit, name, null, false); 497 } 498 499 /** 500 * Adds a new unit and maps it to the specified quantity type. 501 * 502 * @param unit the unit being added. 503 * @param type the quantity type. 504 * @return <code>unit</code>. 505 */ 506 private static <U extends AbstractUnit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) { 507 INSTANCE.units.add(unit); 508 INSTANCE.quantityToUnit.put(type, unit); 509 return unit; 510 } 511}