001/* 002 * International System of Units (SI) 003 * Copyright (c) 2005-2019, 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 JSR-385, 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.4, September 12, 2019 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 action quantities (standard name <code>J.s</code>). 117 */ 118 public static final Unit<Action> JOULE_SECOND = addUnit(new ProductUnit<Action>(JOULE.multiply(SECOND)), 119 Action.class); 120 121 /** 122 * The SI unit for electric permittivity (standard name <code>ε</code>, 123 * <code>F/m </code> or <code>F·m−1</code>). In electromagnetism, absolute 124 * permittivity is the measure of resistance that is encountered when forming an 125 * electric field in a medium. 126 */ 127 public static final Unit<ElectricPermittivity> FARAD_PER_METRE = addUnit( 128 new AlternateUnit<ElectricPermittivity>(FARAD.divide(METRE), "ε"), ElectricPermittivity.class); 129 130 /** 131 * The SI unit for magnetic permeability quantities (standard name 132 * <code>N/A2</code>). 133 */ 134 public static final Unit<MagneticPermeability> NEWTON_PER_SQUARE_AMPERE = addUnit( 135 new ProductUnit<MagneticPermeability>(NEWTON.divide(AMPERE.pow(2))), MagneticPermeability.class); 136 137 /** 138 * The SI unit for wave number quantities (standard name <code>1/m</code>). 139 */ 140 public static final Unit<WaveNumber> RECIPROCAL_METRE = addUnit(new ProductUnit<WaveNumber>(METRE.pow(-1)), 141 WaveNumber.class); 142 143 /** 144 * The SI unit for dynamic viscosity quantities (standard name 145 * <code>Pa.s</code>). 146 */ 147 public static final Unit<DynamicViscosity> PASCAL_SECOND = addUnit( 148 new ProductUnit<DynamicViscosity>(PASCAL.multiply(SECOND)), DynamicViscosity.class); 149 150 /** 151 * Luminance is a photometric measure of the luminous intensity per unit area of 152 * light travelling in a given direction. It describes the amount of light that 153 * passes through, is emitted or reflected from a particular area, and falls 154 * within a given solid angle. The SI unit for luminance is candela per square 155 * metre (<code>cd/m2</code>). 156 * 157 * @see <a href="https://en.wikipedia.org/wiki/Luminance"> Wikipedia: 158 * Luminance</a> 159 */ 160 public static final Unit<Luminance> CANDELA_PER_SQUARE_METRE = addUnit( 161 new ProductUnit<Luminance>(CANDELA.divide(SQUARE_METRE)), Luminance.class); 162 163 /** 164 * The SI unit for kinematic viscosity quantities (standard name 165 * <code>m2/s"</code>). 166 */ 167 public static final Unit<KinematicViscosity> SQUARE_METRE_PER_SECOND = addUnit( 168 new ProductUnit<KinematicViscosity>(SQUARE_METRE.divide(SECOND)), KinematicViscosity.class); 169 170 /** 171 * The SI unit for magnetic field strength quantities (standard name 172 * <code>A/m"</code>). 173 */ 174 public static final Unit<MagneticFieldStrength> AMPERE_PER_METRE = addUnit( 175 new ProductUnit<MagneticFieldStrength>(AMPERE.divide(METRE)), MagneticFieldStrength.class); 176 177 /** 178 * The SI unit for ionizing radiation quantities (standard name 179 * <code>C/kg"</code>). 180 */ 181 public static final Unit<IonizingRadiation> COULOMB_PER_KILOGRAM = addUnit( 182 new ProductUnit<IonizingRadiation>(COULOMB.divide(KILOGRAM)), IonizingRadiation.class); 183 184 /** 185 * The SI unit for radiant intensity (standard name <code>W/sr</code>). 186 */ 187 public static final Unit<RadiantIntensity> WATT_PER_STERADIAN = addUnit( 188 WATT.divide(STERADIAN).asType(RadiantIntensity.class)); 189 190 /** 191 * The SI unit for radiance (standard name <code>W⋅sr−1⋅m−2</code>). 192 */ 193 public static final Unit<Radiance> WATT_PER_STERADIAN_PER_SQUARE_METRE = addUnit( 194 WATT_PER_STERADIAN.divide(SQUARE_METRE).asType(Radiance.class)); 195 196 /** 197 * The SI unit for intensity (standard name <code>W/m<sup>2</sup></code>). 198 */ 199 public static final Unit<Intensity> WATT_PER_SQUARE_METRE = addUnit( 200 WATT.divide(SQUARE_METRE).asType(Intensity.class)); 201 202 /** 203 * The SI unit of angular speed (standard name <code>rad/s</code>). 204 * 205 * @see AngularSpeed 206 */ 207 public static final Unit<AngularSpeed> RADIAN_PER_SECOND = addUnit( 208 new ProductUnit<AngularSpeed>(RADIAN.divide(SECOND)), "Radian per second", AngularSpeed.class); 209 210 /** 211 * The SI unit of angular acceleration (standard name <code>rad/s²</code>). 212 * 213 * @see AngularAcceleration 214 */ 215 public static final Unit<AngularAcceleration> RADIAN_PER_SQUARE_SECOND = addUnit( 216 new ProductUnit<AngularAcceleration>(RADIAN_PER_SECOND.divide(SECOND)), "Radian per square second", 217 AngularAcceleration.class); 218 219 /** 220 * An energy unit accepted for use with SI units (standard name 221 * <code>eV</code>). The electronvolt is the kinetic energy acquired by an 222 * electron passing through a potential difference of 1 V in vacuum. The value 223 * must be obtained by experiment, and is therefore not known exactly. 224 */ 225 public static final Unit<Energy> ELECTRON_VOLT = addUnit( 226 new TransformedUnit<Energy>(JOULE, MultiplyConverter.of(1.602176487E-19))); 227 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 228 229 /** 230 * A mass unit accepted for use with SI units (standard name <code>u</code>). 231 * The unified atomic mass unit is equal to 1/12 of the mass of an unbound atom 232 * of the nuclide 12C, at rest and in its ground state. The value must be 233 * obtained by experiment, and is therefore not known exactly. 234 */ 235 public static final Unit<Mass> UNIFIED_ATOMIC_MASS = addUnit( 236 new TransformedUnit<Mass>(KILOGRAM, MultiplyConverter.of(1.660538782E-27)), "Unified atomic mass", "u", 237 true); 238 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 239 240 /** 241 * A length unit accepted for use with SI units (standard name <code>UA</code>). 242 * The astronomical unit is a unit of length. 243 * Originally conceived as the average of Earth's aphelion and perihelion, 244 * since 2012 it has been defined as exactly 149,597,870,700 metres, 245 * or about 150 million kilometres (93 million miles). 246 * 247 * @see <a href="https://en.wikipedia.org/wiki/Astronomical_unit"> Wikipedia: Astronomical unit</a> 248 */ 249 public static final Unit<Length> ASTRONOMICAL_UNIT = addUnit( 250 new TransformedUnit<Length>(METRE, MultiplyConverter.of(149597870700d))); 251 252 /** 253 * An angle unit accepted for use with SI units (standard name 254 * <code>rev</code>). 255 */ 256 public static final Unit<Angle> REVOLUTION = addUnit(new TransformedUnit<Angle>(RADIAN, 257 MultiplyConverter.ofPiExponent(1).concatenate(MultiplyConverter.ofRational(2, 1)))); 258 259 /////////////////////////// 260 // Fundamental Constants // 261 /////////////////////////// 262 263 /** 264 * Holds the numeric value of the Avogadro constant. 265 */ 266 static final double AVOGADRO_CONSTANT_VALUE = 6.02214199E23; // (1/mol). 267 268 /** 269 * Holds the numeric value of the Boltzmann constant. 270 */ 271 static final double BOLTZMANN_CONSTANT_VALUE = 1.3806485279E-23; 272 273 /** 274 * Holds the electric charge value of one electron. 275 */ 276 static final double ELEMENTARY_CHARGE_VALUE = 1.602176462E-19; // (C). 277 278 /** 279 * Holds the numeric value of the Planck constant. 280 */ 281 static final double PLANCK_CONSTANT_VALUE = 6.62607015E-34; // (1/mol). 282 283 /** 284 * The Avogadro constant, named after scientist Amedeo Avogadro, is the number 285 * of constituent particles, usually molecules, atoms or ions that are contained 286 * in the amount of substance given by one mole. It is the proportionality 287 * factor that relates the molar mass of a substance to the mass of a sample, is 288 * designated with the symbol <code>N<sub>A<sub></code> or <code>L</code>, and has the 289 * value 6.022140857(74)×1023 mol−1 in the International System of Units (SI). 290 */ 291 public static final Unit<Dimensionless> AVOGADRO_CONSTANT = addUnit( 292 new AlternateUnit<Dimensionless>(ONE.divide(MOLE), "m-1").multiply(AVOGADRO_CONSTANT_VALUE), "NA", true); // (1/mol). 293 294 /** 295 * The Boltzmann constant (<code>k<sub>B<sub></code> or <code>k</code>) is a physical 296 * constant named after its discoverer, Ludwig Boltzmann, which relates the 297 * average relative kinetic energy of particles in a gas with the temperature of 298 * the gas and occurs in Planck's law of black-body radiation and in Boltzmann's 299 * entropy formula. 300 */ 301 public static final Unit<Dimensionless> BOLTZMANN_CONSTANT = addUnit( 302 new AlternateUnit<Dimensionless>(JOULE.divide(KELVIN), "J/K").multiply(BOLTZMANN_CONSTANT_VALUE), "kB", 303 true); 304 305 /** 306 * The elementary charge, usually denoted by <code>e</code> or sometimes 307 * <code>qe</code>, is the electric charge carried by a single proton or, 308 * equivalently, the magnitude of the electric charge carried by a single 309 * electron, which has charge −1 e. This elementary charge is a fundamental 310 * physical constant. To avoid confusion over its sign, e is sometimes called 311 * the elementary positive charge. 312 */ 313 public static final Unit<ElectricCharge> ELEMENTARY_CHARGE = addUnit(COULOMB.multiply(ELEMENTARY_CHARGE_VALUE), "e", 314 true); 315 316 /** 317 * The Planck constant (denoted <code>ℎ</code>, also called Planck's constant) 318 * is a physical constant that is the quantum of electromagnetic action, which 319 * relates the energy carried by a photon to its frequency. A photon's energy is 320 * equal to its frequency multiplied by the Planck constant. The Planck constant 321 * is of fundamental importance in quantum mechanics, and in metrology it is the 322 * basis for the definition of the kilogram. 323 */ 324 public static final Unit<Action> PLANCK_CONSTANT = addUnit(JOULE_SECOND.multiply(PLANCK_CONSTANT_VALUE), "\u210E", true); 325 326 ///////////////////// 327 // Collection View // 328 ///////////////////// 329 330 @Override 331 public String getName() { 332 return "SI"; 333 } 334 335 /** 336 * Adds a new unit not mapped to any specified quantity type. 337 * 338 * @param unit the unit being added. 339 * @return <code>unit</code>. 340 */ 341 private static <U extends Unit<?>> U addUnit(U unit) { 342 INSTANCE.units.add(unit); 343 return unit; 344 } 345 346 /** 347 * Adds a new unit not mapped to any specified quantity type and puts a text as 348 * symbol or label. 349 * 350 * @param unit the unit being added. 351 * @param name the string to use as name 352 * @param text the string to use as label or symbol 353 * @param isLabel if the string should be used as a label or not 354 * @return <code>unit</code>. 355 */ 356 private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) { 357 if (isLabel) { 358 SimpleUnitFormat.getInstance().label(unit, text); 359 } 360 if (name != null && unit instanceof AbstractUnit) { 361 return Helper.addUnit(INSTANCE.units, unit, name); 362 } else { 363 INSTANCE.units.add(unit); 364 } 365 return unit; 366 } 367 368 /** 369 * Adds a new unit not mapped to any specified quantity type and puts a text as 370 * symbol or label. 371 * 372 * @param unit the unit being added. 373 * @param text the string to use as label or symbol 374 * @param isLabel if the string should be used as a label or not 375 * @return <code>unit</code>. 376 */ 377 private static <U extends Unit<?>> U addUnit(U unit, String text, boolean isLabel) { 378 return addUnit(unit, null, text, isLabel); 379 } 380 381 /** 382 * Adds a new unit not mapped to any specified quantity type and puts a text as 383 * symbol or label. 384 * 385 * @param unit the unit being added. 386 * @param name the string to use as name 387 * @param label the string to use as label 388 * @return <code>unit</code>. 389 */ 390 private static <U extends Unit<?>> U addUnit(U unit, String name, String label) { 391 return addUnit(unit, name, label, true); 392 } 393 394 /** 395 * Adds a new unit with name and label and maps it to the specified quantity 396 * type. 397 * 398 * @param unit the unit being added. 399 * @param name the string to use as name 400 * @param label the string to use as label 401 * @param type the quantity type. 402 * @return <code>unit</code>. 403 */ 404 @SuppressWarnings("unused") 405 private static <U extends AbstractUnit<?>> U addUnit(U unit, String name, String label, 406 Class<? extends Quantity<?>> type) { 407 INSTANCE.quantityToUnit.put(type, unit); 408 return addUnit(unit, name, label); 409 } 410 411 /** 412 * Adds a new unit with a name and maps it to the specified quantity type. 413 * 414 * @param unit the unit being added. 415 * @param name the string to use as name 416 * @param type the quantity type. 417 * @return <code>unit</code>. 418 */ 419 private static <U extends AbstractUnit<?>> U addUnit(U unit, String name, Class<? extends Quantity<?>> type) { 420 INSTANCE.quantityToUnit.put(type, unit); 421 return addUnit(unit, name, null, false); 422 } 423 424 /** 425 * Adds a new unit and maps it to the specified quantity type. 426 * 427 * @param unit the unit being added. 428 * @param type the quantity type. 429 * @return <code>unit</code>. 430 */ 431 private static <U extends AbstractUnit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) { 432 INSTANCE.units.add(unit); 433 INSTANCE.quantityToUnit.put(type, unit); 434 return unit; 435 } 436}