Click here to Skip to main content
Click here to Skip to main content

Quantities, Units, and Values: An Object Oriented Implementation

, 25 Jun 2011
Rate this:
Please Sign up or sign in to vote.
A concrete implementation of the Quantities, Units, Dimensions, and Values abstract model through an object oriented implementation.

Introduction

Software for simulation or real time software typically manipulate physical quantities, and a solid foundation of quantities, units, and dimensions is a key issue. Common software languages do not provide native support for expressing units and quantities in order to avoid wrong assignments and comparisons or to do an automatic dimensional analysis. This causes of loss of time and trouble, and in a worst case, as the famous Mart Climate Orbiter, the failure of a mission due to a conversion error between systems of units.

Model Library for Quantities, Units, Dimensions and Values (QUDV) of sysML provides a solid model to express system physical properties. It provides an abstract syntax of the library expressed by a sequence of block diagrams.

In this article, we present a concrete implementation of the QUDV abstract model through an object oriented implementation. Our formulation is concentrate to provide the basis for defining basic units and other units via conversion or derivation. Also, it provides the definition of a system of units where it is possible to specify coherent derived units as a product of the base unit. In this version of the library, we miss the part for defining a declarative specification of dimensional analysis assigning an expression and its dependencies to each quantity kind. (It is an open issue.)

Analysis and Class Diagram

A system of units is generally a system of units of measurement composed of base units and derived units. A quantity is written as a number followed by a unit symbol.

In figure, 1 we have our class diagram with the main class that describes the implementation of a specific system of units. SimpleUnit provides the base class for defining other units via conversion: AffineConversionUnit, LinearConversionUnit, or the derivation DerivedUnit. SystemOfUnits provides the definition of all units and quantity kinds of our system.

Figure 1

A quantity is composed of a unique quantity kind, a numerical value, and a reference unit with other units defined by the conversion belonging to the same quantity kind.

Code System of Units

The system of units is implemented by hard coding the relations between the units and the quantity kinds in a unique class SystemOfUnits. For instance the quantity kind Temperature has a base unit of measurement Kelvin and other derived units as Centigrade, Fahrenheit, and Celsius. That relation is captured with a declarative specification, exploiting the model presented in figure 1.

Following the declaration of Kelvin, you find a description, a symbol K, and the reference to the quantity kind associated.

temperature = New QuantityKind("temperature", "T", "")
mKelvin = New SimpleUnit("kelvin", "K", temperature)

Another related unit of temperature is Centigrade that we define by a conversion from Kelvin.

'0c = 273.15k 'k=c+273.15
mCentigradi = New AffineConversionUnit("Centigrade", "C", temperature, mKelvin, 1, 273.15)

Following the structure of the temperature declaration, we define the quantity kinds useful in our projects as pressure, length, time, mass, density, and related units as Pascal, Meter, Second, Kilogram; for a complete list, see the code in the attachment.

Public Class SystemOfUnits
Private mName As String 
Private mCelsius As SimpleUnit
Private mKelvin As SimpleUnit
Private mFahrenheit As AffineConversionUnit
Private mCentigradi As AffineConversionUnit
Private mNewton As DerivedUnit
Private mPascal As DerivedUnit
Private mBar As LinearConversionUnit
Private mBarg As AffineConversionUnit
...
ReadOnly Property Pascal As DerivedUnit
    Get
        Return mPascal
    End Get
End Property
ReadOnly Property Bar As LinearConversionUnit
    Get
        Return mBar
    End Get
End Property
ReadOnly Property Barg As AffineConversionUnit
    Get
        Return mBarg
    End Get
End Property
...
Public Sub New()
    'Temperature Kelvin
    Dim temperature As QuantityKind
    temperature = New QuantityKind("temperature", "T", "")
    mKelvin = New SimpleUnit("kelvin", "K", temperature, "T", ""))
    '0c = 273.15k 'k=c+273.15
    mCentigradi = New AffineConversionUnit("Centigradi", "C", temperature, mKelvin, 1, 273.15)

    'pressure  Pascal
    Dim pressure As QuantityKind
    pressure = New QuantityKind("Pressure", "P", "")
    mPascal = New DerivedUnit("Pascal", "Pa", pressure)
    mPascal.addFactor(New UnitFactor(mMeter, -1))
    mPascal.addFactor(New UnitFactor(mKg, 1))
    mPascal.addFactor(New UnitFactor(mSecond, -2))
    '1bar= 100000 Pascal
    mBar = New LinearConversionUnit("Bar", "bar", pressure, mPascal, 101325)
    '1 barg = 100000 Pascal + 101325 
    mBarg = New AffineConversionUnit("Barg", "barg", pressure, mPascal, 101325, 101325)

    'length meter
    Dim length As QuantityKind
    length = New QuantityKind("Length", "l", "")
    '1m
    mMeter = New SimpleUnit("Meter", "m", length)
    '1km=1000m
    mKm = New LinearConversionUnit("kilometer", "km", length, mMeter, 1000)
    '1mm=0,0001m
    mMm = New LinearConversionUnit("mmillimeter", "mm", length, mMeter, 0.0001)
...
End Sub
End Class

In order to make the declarative specification of SystemOfUnits reusable in several projects, we build a library with all the defined classes.

Quantities

The association between the numerical value and the corresponding unit is made with the class Quantity. For instance, the value of pressure is represented by the class Pressure that inherits from the more general class Quantity. It contains all the related units of the quantity pressure and a numerical value to represent the measure from which to start all conversions.

Public Class Pressure
    Inherits Quantity
    Private mpascal As DerivedUnit
    Private mBar As LinearConversionUnit
    Private mBarg As AffineConversionUnit

    Public Sub New(ByVal si As SystemOfUnits)
        mQuantityKind = si.Pascal.QuantityKind
        mpascal = si.Pascal
        mBar = si.Bar
        mBarg = si.Barg
    End Sub
    ReadOnly Property unitPascal As Units
        Get
            Return mpascal
        End Get
    End Property
    ReadOnly Property unitBar As Units
        Get
            Return mBar
        End Get
    End Property
    ReadOnly Property unitBarg As Units
        Get
            Return mBarg
        End Get
    End Property
    Property Pascal As Double
        Get
            Return mValore
        End Get
        Set(ByVal value As Double)
            mValore = value
            check()
        End Set
    End Property
    Property dBar As Double
        Get
            Return (mValore / mBar.factor)
        End Get
        Set(ByVal value As Double)
            Dim avalue As Double = (value * mBar.factor)
            mValore = avalue
            check()
        End Set
    End Property
    Property dBarg As Double
        Get
            Return ((mValore - mBarg.Offset) / mBarg.Factor)
        End Get
        Set(ByVal value As Double)
            Dim avalue As Double = ((value * mBarg.Factor) + mBarg.Offset)
            mValore = avalue
            check()
        End Set
    End Property
 ... 

In the Quantity class, we introduce a convention: adding a property for each unit represented inside the class called with its symbol and a letter "d" to indicate if is a derived unit. This list of properties is to avoid assignment error when writing code, in particular when writing physical formula. We make explicit the meaning of the variable by its name, with the unit symbol previously designed and implemented in the library.

All other implementations of the Quantity class as Time, LinearPosition, Flow are provided in the code in the attachment.

Operator Overload

An interesting feature to automatically avoid errors in comparisons and adding incompatible physical quantities is obtained by adding to the class Quantity the overloads of operators +, -, >, <.

Public Shared Operator <(ByVal lp As Pressure, ByVal rp As Pressure) As Boolean
    If lp.Pascal < rp.Pascal Then
        Return True
    Else
        Return False
    End If
End Operator
Public Shared Operator >(ByVal lp As Pressure, ByVal rp As Pressure) As Boolean
    If lp.Pascal > rp.Pascal Then
        Return True
    Else
        Return False
    End If
End Operator
Public Shared Operator +(ByVal lp As Pressure, ByVal rp As Pressure) As Pressure
    Dim result As New Pressure(New SystemOfUnits)
    result.Pascal = lp.Pascal + rp.Pascal
    Return result
End Operator

Example of use

In the example, we will see how to instantiate the quantity Pressure, how to assign a numerical value, and how to compare and sum in safety mode.

In the example, the first assignment is from Pascal, the second from Barg. The library permits a correct comparison between the two values of pressure assigned from different units, as follows:

Dim pressure1 As New Pressure(si)
Dim pressure2 As New Pressure(si)
pressure1.Pascal = 100000
pressure2.dBarg = 5
If pressure2 > pressure1 Then
    MsgBox(pressure2.Pascal & " is greater then " & pressure1.Pascal)
End If

At first look, 5 is less than 100000, but it is exactly the contrary! Thanks QUDV library! We can add the two values avoiding conversion errors, exploiting the overload of the sum operator.

Dim result As Pressure
result = pressure1 + pressure2
MsgBox("The sum is " & result.Pascal)

You can use the test project in the attachment to see and build other examples.

Conclusions

In our experience, the use of physical quantities inside programs for simulation can be made more flexible by exploiting the class SystemOfUnits and the specialized classes of Quantity. This approach reduces the risk in adding and comparing values of different units (implementing the comparable interface completely eliminates the risk). The classes encapsulate the conversion factors and the structure of unit dimensions making it possible to do dimensional analysis. The creation of specialized quantities is useful to describe properties more close to the system behavior.

Other solutions exist as showed in [2] below where we formulate dimensions and units as classes in a nominally typed object-oriented language through the use of statically typed meta-classes. The new and promising F# language [3] provides native support to manage units of measure. It permits to annotate numeric types with a symbol that indicates the quantity kind and also helps to infer the derived type of an assignment.

References

  1. Quantities, Units, Dimensions, Values (QUDV), http://www.omgwiki.org/OMGSysML/doku.php?id=sysml-qudv:quantities_units_dimensions_values_qudv
  2. Eric Allen, David Chase, Victor Luchangco, Jan-Willem Maessen, and Guy L. Steele, Jr.. 2004. Object-oriented units of measurement. In Proceedings of the 19th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '04). ACM, New York, NY, USA, 384-403. DOI=10.1145/1028976.1029008 http://doi.acm.org/10.1145/1028976.1029008.
  3. Units of Measure (F#) http://msdn.microsoft.com/en-us/library/dd233243.aspx

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

EnricoOliva
Software Developer S.E.I.C srl
Italy Italy
PhD in Computer Science, software engineer and developer of real-time leak detection system. Visit my home page

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web02 | 2.8.140814.1 | Last Updated 25 Jun 2011
Article Copyright 2011 by EnricoOliva
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid