001/* 002 * International System of Units (SI) 003 * Copyright (c) 2005-2018, 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 javax.measure.Quantity; 033import javax.measure.Unit; 034import javax.measure.quantity.Acceleration; 035import javax.measure.quantity.Angle; 036import javax.measure.quantity.Area; 037import javax.measure.quantity.Energy; 038import javax.measure.quantity.Length; 039import javax.measure.quantity.Mass; 040 041import si.uom.quantity.Action; 042import si.uom.quantity.AngularAcceleration; 043import si.uom.quantity.AngularSpeed; 044import si.uom.quantity.DynamicViscosity; 045import si.uom.quantity.ElectricPermittivity; 046import si.uom.quantity.Intensity; 047import si.uom.quantity.IonizingRadiation; 048import si.uom.quantity.KinematicViscosity; 049import si.uom.quantity.Luminance; 050import si.uom.quantity.MagneticFieldStrength; 051import si.uom.quantity.MagneticPermeability; 052import si.uom.quantity.MagnetomotiveForce; 053import si.uom.quantity.Radiance; 054import si.uom.quantity.RadiantIntensity; 055import si.uom.quantity.WaveNumber; 056import tec.uom.se.AbstractUnit; 057import tec.uom.se.format.SimpleUnitFormat; 058import tec.uom.se.function.MultiplyConverter; 059import tec.uom.se.function.PiMultiplierConverter; 060import tec.uom.se.function.RationalConverter; 061import tec.uom.se.unit.AlternateUnit; 062import tec.uom.se.unit.ProductUnit; 063import tec.uom.se.unit.TransformedUnit; 064import tec.uom.se.unit.Units; 065 066/** 067 * <p> 068 * This class defines all SI (Système International d'Unités) base units and 069 * derived units as well as units that are accepted for use with the SI units. 070 * </p> 071 * 072 * @see <a href= 073 * "http://en.wikipedia.org/wiki/International_System_of_Units">Wikipedia: 074 * International System of Units</a> 075 * @see <a href="http://physics.nist.gov/cuu/Units/outside.html">Units outside 076 * the SI that are accepted for use with the SI</a> 077 * @see <a href="http://www.bipm.org/utils/common/pdf/si_brochure_8.pdf">SI 2006 078 * - Official Specification</a> 079 * @see tec.uom.se.unit.MetricPrefix 080 * 081 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 082 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 083 * @version 1.2, May 20, 2018 084 */ 085public final class SI extends Units { 086 /** 087 * The singleton instance. 088 */ 089 private static final SI INSTANCE = new SI(); 090 091 //////////////////////////////// 092 // SI DERIVED ALTERNATE UNITS // 093 //////////////////////////////// 094 095 /** 096 * The SI unit for magnetomotive force (standard name <code>At</code>). 097 */ 098 public static final Unit<MagnetomotiveForce> AMPERE_TURN = addUnit( 099 new AlternateUnit<MagnetomotiveForce>(Units.AMPERE, "At"), MagnetomotiveForce.class); 100 101 ////////////////////////////// 102 // SI DERIVED PRODUCT UNITS // 103 ////////////////////////////// 104 105 /** 106 * The SI unit for acceleration quantities (standard name 107 * <code>m/s²</code>). 108 */ 109 public static final Unit<Acceleration> METRE_PER_SQUARE_SECOND = addUnit( 110 new ProductUnit<Acceleration>(METRE_PER_SECOND.divide(SECOND)), Acceleration.class); 111 /** 112 * Alias {@link #METRE_PER_SQUARE_SECOND} 113 * 114 * @deprecated use METRE_PER_SQUARE_SECOND 115 */ 116 public static final Unit<Acceleration> METRES_PER_SQUARE_SECOND = METRE_PER_SQUARE_SECOND; 117 118 /** 119 * The SI unit for action quantities (standard name <code>j.s</code>). 120 */ 121 public static final Unit<Action> JOULE_SECOND = addUnit(new ProductUnit<Action>(JOULE.multiply(SECOND)), 122 Action.class); 123 124 /** 125 * The SI unit for electric permittivity (standard name <code>ε</code>, 126 * <code>F/m </code> or <code>F·m−1</code>). In electromagnetism, absolute 127 * permittivity is the measure of resistance that is encountered when 128 * forming an electric field in a medium. 129 */ 130 public static final Unit<ElectricPermittivity> FARAD_PER_METRE = addUnit( 131 new AlternateUnit<ElectricPermittivity>(FARAD.divide(METRE), "ε"), ElectricPermittivity.class); 132 133 /** 134 * The SI unit for magnetic permeability quantities (standard name 135 * <code>N/A2</code>). 136 */ 137 public static final Unit<MagneticPermeability> NEWTON_PER_SQUARE_AMPERE = addUnit( 138 new ProductUnit<MagneticPermeability>(NEWTON.divide(AMPERE.pow(2))), MagneticPermeability.class); 139 140 /** 141 * The SI unit for wave number quantities (standard name <code>1/m</code>). 142 */ 143 public static final Unit<WaveNumber> RECIPROCAL_METRE = addUnit(new ProductUnit<WaveNumber>(METRE.pow(-1)), 144 WaveNumber.class); 145 146 /** 147 * The SI unit for dynamic viscosity quantities (standard name 148 * <code>Pa.s</code>). 149 */ 150 public static final Unit<DynamicViscosity> PASCAL_SECOND = addUnit( 151 new ProductUnit<DynamicViscosity>(PASCAL.multiply(SECOND)), DynamicViscosity.class); 152 153 /** 154 * Luminance is a photometric measure of the luminous intensity per unit 155 * area of light travelling in a given direction. It describes the amount of 156 * light that passes through, is emitted or reflected from a particular 157 * area, and falls within a given solid angle. The SI unit for luminance is 158 * candela per square metre (<code>cd/m2</code>). 159 * 160 * @see <a href="https://en.wikipedia.org/wiki/Luminance"> Wikipedia: 161 * Luminance</a> 162 */ 163 public static final Unit<Luminance> CANDELA_PER_SQUARE_METRE = addUnit( 164 new ProductUnit<Luminance>(CANDELA.divide(SQUARE_METRE)), Luminance.class); 165 166 /** 167 * The SI unit for kinematic viscosity quantities (standard name 168 * <code>m2/s"</code>). 169 */ 170 public static final Unit<KinematicViscosity> SQUARE_METRE_PER_SECOND = addUnit( 171 new ProductUnit<KinematicViscosity>(SQUARE_METRE.divide(SECOND)), KinematicViscosity.class); 172 173 /** 174 * Alias for {@link #SQUARE_METRE_PER_SECOND} 175 * 176 * @deprecated use SQUARE_METRE_PER_SECOND 177 */ 178 public static final Unit<KinematicViscosity> SQUARE_METRES_PER_SECOND = SQUARE_METRE_PER_SECOND; 179 180 /** 181 * A magnetic field is the magnetic effect of electric currents and magnetic 182 * materials. The magnetic field at any given point is specified by both a 183 * direction and a magnitude (or strength); as such it is a vector field. 184 * The H-field is measured in amperes per metre (<code>A/m</code>) in SI 185 * units. 186 * 187 * @see <a href="https://en.wikipedia.org/wiki/Magnetic_field#The_H-field"> 188 * Wikipedia: Magnetic Field - The H Field</a> 189 */ 190 public static final Unit<MagneticFieldStrength> AMPERE_PER_METRE = addUnit( 191 new ProductUnit<MagneticFieldStrength>(AMPERE.divide(METRE)), MagneticFieldStrength.class); 192 193 194 /** 195 * The SI unit for ionizing radiation quantities (standard name 196 * <code>C/kg"</code>). 197 */ 198 public static final Unit<IonizingRadiation> COULOMB_PER_KILOGRAM = addUnit( 199 new ProductUnit<IonizingRadiation>(COULOMB.divide(KILOGRAM)), IonizingRadiation.class); 200 201 /** 202 * The SI unit for radiant intensity (standard name <code>W/sr</code>). 203 */ 204 public static final Unit<RadiantIntensity> WATT_PER_STERADIAN = addUnit( 205 WATT.divide(STERADIAN).asType(RadiantIntensity.class)); 206 207 /** 208 * The SI unit for radiance (standard name <code>W⋅sr−1⋅m−2</code>). 209 */ 210 public static final Unit<Radiance> WATT_PER_STERADIAN_PER_SQUARE_METRE = addUnit( 211 WATT_PER_STERADIAN.divide(SQUARE_METRE).asType(Radiance.class)); 212 213 /** 214 * The SI unit for intensity (standard name <code>W/m<sup>2</sup></code>). 215 */ 216 public static final Unit<Intensity> WATT_PER_SQUARE_METRE = addUnit( 217 WATT.divide(SQUARE_METRE).asType(Intensity.class)); 218 219 /** 220 * The SI unit of angular speed (standard name 221 * <code>rad/s</code>). 222 * @see AngularSpeed 223 */ 224 public static final Unit<AngularSpeed> RADIAN_PER_SECOND = addUnit( 225 new ProductUnit<AngularSpeed>(RADIAN.divide(SECOND)), "Radian per second", AngularSpeed.class); 226 227 /** 228 * The SI unit of angular acceleration (standard name 229 * <code>rad/s²</code>). 230 * @see AngularAcceleration 231 */ 232 public static final Unit<AngularAcceleration> RADIAN_PER_SQUARE_SECOND = addUnit( 233 new ProductUnit<AngularAcceleration>(RADIAN_PER_SECOND.divide(SECOND)), "Radian per square second", AngularAcceleration.class); 234 235 236 ///////////////////////////////////////////////////////////////// 237 // Units outside the SI that are accepted for use with the SI. // 238 ///////////////////////////////////////////////////////////////// 239 240 /** 241 * An energy unit accepted for use with SI units (standard name 242 * <code>eV</code>). The electronvolt is the kinetic energy acquired by an 243 * electron passing through a potential difference of 1 V in vacuum. The 244 * value must be obtained by experiment, and is therefore not known exactly. 245 */ 246 public static final Unit<Energy> ELECTRON_VOLT = new TransformedUnit<Energy>(JOULE, 247 new MultiplyConverter(1.602176487E-19)); 248 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 249 250 /** 251 * A mass unit accepted for use with SI units (standard name 252 * <code>u</code>). The unified atomic mass unit is equal to 1/12 of the 253 * mass of an unbound atom of the nuclide 12C, at rest and in its ground 254 * state. The value must be obtained by experiment, and is therefore not 255 * known exactly. 256 */ 257 public static final Unit<Mass> UNIFIED_ATOMIC_MASS = addUnit( 258 new TransformedUnit<Mass>(KILOGRAM, new MultiplyConverter(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 264 * <code>UA</code>). The astronomical unit is a unit of length. Its value is 265 * such that, when used to describe the motion of bodies in the solar 266 * system, the heliocentric gravitation constant is (0.017 202 098 95)2 267 * ua3·d-2. The value must be obtained by experiment, and is therefore not 268 * known exactly. 269 */ 270 public static final Unit<Length> ASTRONOMICAL_UNIT = addUnit( 271 new TransformedUnit<Length>(METRE, new MultiplyConverter(149597871000.0))); 272 // Best estimate source: http://maia.usno.navy.mil/NSFA/CBE.html 273 274 /** 275 * An angle unit accepted for use with SI units (standard name 276 * <code>rev</code>). 277 */ 278 public static final Unit<Angle> REVOLUTION = addUnit( 279 new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(2, 1)))); 280 281 /** 282 * An angle unit accepted for use with SI units (standard name 283 * <code>ha</code>). 284 */ 285 public static final Unit<Area> HECTARE = new TransformedUnit<Area>(SQUARE_METRE, new RationalConverter(10000, 1)); 286 287 ///////////////////// 288 // Collection View // 289 ///////////////////// 290 291 /** 292 * Default constructor (prevents this class from being instantiated). 293 */ 294 private SI() { // Singleton 295 } 296 297 @Override 298 public String getName() { 299 return SI.class.getSimpleName(); // for Java SE this works 300 } 301 302 /** 303 * Returns the singleton instance of this class. 304 * 305 * @return the metric system instance. 306 */ 307 public static SI getInstance() { 308 return INSTANCE; 309 } 310 311 /** 312 * Adds a new unit not mapped to any specified quantity type and puts a text 313 * as symbol or label. 314 * 315 * @param unit 316 * the unit being added. 317 * @param name 318 * the string to use as name 319 * @param text 320 * the string to use as label or symbol 321 * @param isLabel 322 * if the string should be used as a label or not 323 * @return <code>unit</code>. 324 */ 325 private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) { 326 if (isLabel) { 327 SimpleUnitFormat.getInstance().label(unit, text); 328 } 329 if (name != null && unit instanceof AbstractUnit) { 330 return Helper.addUnit(INSTANCE.units, unit, name); 331 } else { 332 INSTANCE.units.add(unit); 333 } 334 return unit; 335 } 336 337 /** 338 * Adds a new unit not mapped to any specified quantity type and puts a text 339 * as symbol or label. 340 * 341 * @param unit 342 * the unit being added. 343 * @param text 344 * the string to use as label or symbol 345 * @param isLabel 346 * if the string should be used as a label or not 347 * @return <code>unit</code>. 348 */ 349 @SuppressWarnings("unused") 350 private static <U extends Unit<?>> U addUnit(U unit, String text, boolean isLabel) { 351 return addUnit(unit, null, text, isLabel); 352 } 353 354 /** 355 * Adds a new unit not mapped to any specified quantity type. 356 * 357 * @param unit 358 * the unit being added. 359 * @return <code>unit</code>. 360 */ 361 private static <U extends Unit<?>> U addUnit(U unit) { 362 INSTANCE.units.add(unit); 363 return unit; 364 } 365 366 /** 367 * Adds a new unit with name and label and maps it to the specified quantity type. 368 * 369 * @param unit 370 * the unit being added. 371 * @param name 372 * the string to use as name 373 * @param label 374 * the string to use as label 375 * @param type 376 * the quantity type. 377 * @return <code>unit</code>. 378 */ 379// private static <U extends AbstractUnit<?>> U addUnit(U unit, String name, String label, Class<? extends Quantity<?>> type) { 380// INSTANCE.quantityToUnit.put(type, unit); 381// return addUnit(unit, name, label, true); 382// } 383 384 /** 385 * Adds a new unit with a name and maps it to the specified quantity type. 386 * 387 * @param unit 388 * the unit being added. 389 * @param name 390 * the string to use as name 391 * @param type 392 * the quantity type. 393 * @return <code>unit</code>. 394 */ 395 private static <U extends AbstractUnit<?>> U addUnit(U unit, String name, Class<? extends Quantity<?>> type) { 396 INSTANCE.quantityToUnit.put(type, unit); 397 return addUnit(unit, name, null, false); 398 } 399 400 /** 401 * Adds a new unit and maps it to the specified quantity type. 402 * 403 * @param unit 404 * the unit being added. 405 * @param type 406 * the quantity type. 407 * @return <code>unit</code>. 408 */ 409 private static <U extends AbstractUnit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) { 410 INSTANCE.units.add(unit); 411 INSTANCE.quantityToUnit.put(type, unit); 412 return unit; 413 } 414}