Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Kitchen Sink Example using SI units

User-defined value types

(kitchen_sink.cpp)

This example provides a fairly extensive set of tests covering most of the quantity functionality. It uses the SI unit system defined in boost/units/systems/si.hpp.

If we define a few units and associated quantities,

/// scalar
const double    s1 = 2;

const long                  x1 = 2;
const static_rational<4,3>  x2;

/// define some units
force       u1 = newton;
energy      u2 = joule;

/// define some quantities
quantity<force>      q1(1.0*u1);
quantity<energy>     q2(2.0*u2);

the various algebraic operations between scalars, units, and quantities give

S1 :    2
X1 :    2
X2 :    (4/3)
U1 :    N
U2 :    J
Q1 :    1 N
Q2 :    2 J

Scalar/unit operations :

U1*S1 : 2 N
S1*U1 : 2 N
U1/S1 : 0.5 N
S1/U1 : 2 m^-1 kg^-1 s^2

Unit/unit operations and integral/rational powers of units :

U1+U1 : N
U1-U1 : N
U1*U1 : m^2 kg^2 s^-4
U1/U1 : dimensionless
U1*U2 : m^3 kg^2 s^-4
U1/U2 : m^-1
U1^X  : m^2 kg^2 s^-4
X1vU1 : m^(1/2) kg^(1/2) s^-1
U1^X2 : m^(4/3) kg^(4/3) s^(-8/3)
X2vU1 : m^(3/4) kg^(3/4) s^(-3/2)

Scalar/quantity operations :

Q1*S1 : 2 N
S1*Q1 : 2 N
Q1/S1 : 0.5 N
S1/Q1 : 2 m^-1 kg^-1 s^2

Unit/quantity operations :

U1*Q1 : 1 m^2 kg^2 s^-4
Q1*U1 : 1 m^2 kg^2 s^-4
U1/Q1 : 1 dimensionless
Q1/U1 : 1 dimensionless

Quantity/quantity operations and integral/rational powers of quantities :

+Q1   : 1 N
-Q1   : -1 N
Q1+Q1 : 2 N
Q1-Q1 : 0 N
Q1*Q1 : 1 m^2 kg^2 s^-4
Q1/Q1 : 1 dimensionless
Q1*Q2 : 2 m^3 kg^2 s^-4
Q1/Q2 : 0.5 m^-1
Q1^X1 : 1 m^2 kg^2 s^-4
X1vQ1 : 1 m^(1/2) kg^(1/2) s^-1
Q1^X2 : 1 m^(4/3) kg^(4/3) s^(-8/3)
X2vQ1 : 1 m^(3/4) kg^(3/4) s^(-3/2)

Logical comparison operators are also defined between quantities :

/// check comparison tests
quantity<length>    l1(1.0*meter),
                    l2(2.0*meters);

giving

l1 == l2    false
l1 != l2    true
l1 <= l2    true
l1 < l2     true
l1 >= l2    false
l1 > l2     false

Implicit conversion is allowed between dimensionless quantities and their corresponding value types :

/// check implicit unit conversion from dimensionless to value_type  
const double    dimless = (q1/q1);

A generic function for computing mechanical work can be defined that takes force and distance arguments in an arbitrary unit system and returns energy in the same system:

/// the physical definition of work - computed for an arbitrary unit system 
template<class System,class Y>
quantity<unit<energy_dimension,System>,Y>
work(quantity<unit<force_dimension,System>,Y> F,
     quantity<unit<length_dimension,System>,Y> dx)
{
    return F*dx;
}

/// test calcuation of work
quantity<force>       F(1.0*newton);
quantity<length>      dx(1.0*meter);
quantity<energy>      E(work(F,dx));

which functions as expected for SI quantities :

F  = 1 N
dx = 1 m
E  = 1 J

The ideal gas law can also be implemented in SI units :

/// the ideal gas law in si units
template<class Y>
quantity<si::amount,Y>
idealGasLaw(const quantity<si::pressure,Y>& P,
            const quantity<si::volume,Y>& V,
            const quantity<si::temperature,Y>& T)
{
    using namespace boost::units::si;

    using namespace constants::codata;
    return (P*V/(R*T));
}

/// test ideal gas law
quantity<temperature>   T = (273.+37.)*kelvin;
quantity<pressure>      P = 1.01325e5*pascals;
quantity<length>        r = 0.5e-6*meters;
quantity<volume>        V = (4.0/3.0)*3.141592*pow<3>(r);
quantity<amount>        n(idealGasLaw(P,V,T));

with the resulting output :

r = 5e-07 m
P = 101325 Pa
V = 5.23599e-19 m^3
T = 310 K
n = 2.05835e-17 mol
R = 8.314472 m^2 kg s^-2 K^-1 mol^-1 (rel. unc. = 1.8e-06)

Trigonometric and inverse trigonometric functions can be implemented for any unit system that provides an angular base dimension. For radians, these functions are found in boost/units/cmath.hpp These behave as one expects, with trigonometric functions taking an angular quantity and returning a dimensionless quantity, while the inverse trigonometric functions take a dimensionless quantity and return an angular quantity :

Defining a few angular quantities,

/// test trig stuff
quantity<plane_angle>           theta = 0.375*radians;
quantity<dimensionless>         sin_theta = sin(theta);
quantity<plane_angle>           thetap = asin(sin_theta);

yields

theta            = 0.375 rd
sin(theta)       = 0.366273 dimensionless
asin(sin(theta)) = 0.375 rd

Dealing with complex quantities is trivial. Here is the calculation of complex impedance :

quantity<electric_potential,complex_type> v = complex_type(12.5,0.0)*volts;
quantity<current,complex_type>            i = complex_type(3.0,4.0)*amperes;
quantity<resistance,complex_type>         z = complex_type(1.5,-2.0)*ohms;

giving

V   = (12.5,0) V
I   = (3,4) A
Z   = (1.5,-2) Ohm
I*Z = (12.5,0) V

User-defined value types that support the appropriate arithmetic operations are automatically supported as quantity value types. The operators that are supported by default for quantity value types are unary plus, unary minus, addition, subtraction, multiplication, division, equal-to, not-equal-to, less-than, less-or-equal-to, greater-than, and greater-or-equal-to. Support for rational powers and roots can be added by overloading the power_typeof_helper and root_typeof_helper classes. Here we implement a user-defined measurement class that models a numerical measurement with an associated measurement error and the appropriate algebra and demonstrates its use as a quantity value type; the full code is found in measurement.hpp.

Then, defining some measurement quantity variables

quantity<length,measurement<double> >
    u(measurement<double>(1.0,0.0)*meters),
    w(measurement<double>(4.52,0.02)*meters),
    x(measurement<double>(2.0,0.2)*meters),
    y(measurement<double>(3.0,0.6)*meters);

gives

x+y-w         = 0.48(+/-0.632772) m
w*x           = 9.04(+/-0.904885) m^2
x/y           = 0.666667(+/-0.149071) dimensionless

If we implement the overloaded helper classes for rational powers and roots then we can also compute rational powers of measurement quantities :

w*y^2/(u*x)^2 = 10.17(+/-3.52328) m^-1
w/(u*x)^(1/2) = 3.19612(+/-0.160431) dimensionless


PrevUpHomeNext