Units

In SAMSON, physical quantities are *strongly typed*. All physical quantities have associated units types, and the use of regular C++ types (*e.g.* `double`

, `float`

, etc.) is discouraged for the development of new SAMSON Elements (although it is natural when integrating existing source code).

In order to use units types, the `SBQuantity.hpp`

header should be included:

#include "SBQuantity.hpp"

but this file is often indirectly included *via* other files (*e.g.* `"SBAtom.hpp"`

, etc.).

Thanks to *metaprogramming techniques*, conversions and checks are performed at compile time, and have no runtime impact on performance.

The following definitions are used in SAMSON:

- A
**base unit**is used to measure one type of*physical quantities*(*e.g.*`meter`

is a base unit for measuring length). - A
**system of units**is a*set of base units used together*. For example, there are seven base units in the International System of Units (SI): meter (length), kilogram (mass), second (time), ampere (current), kelvin (temperature), mole (amount of substance) and candela (luminous intensity). - A
**scaled base unit**is a*multiple of a base unit*(a power of ten). For example,`nanometer`

is a scaled version of`meter`

. - The
**scale**of a scaled base unit is the corresponding power of ten,*e.g.*the scale of`nanometer`

is`-9`

, relative to the`meter`

. - An
**exponentiated unit**is a*power of a unit*, such as`nanometer^2`

. - The
**exponent**of an exponentiated unit is the corresponding exponent,*e.g.*the exponent of`nanometer^2`

is`2`

. **Derived units**are*products of exponentiated units*. For instance,`newton`

is defined as`kg.m.s^-2`

, while`nanonewton`

is defined in SAMSON as`yg.pm.fs^-2`

(`yoctogram.picometer.femtosecond^-2`

), for reasons detailed below.

SAMSON uses scales to avoid loss of precision when dealing with typical quantities encountered in nanosciences. For example, internally, `nanometer`

is an instance of a template type parameterized by the scale `-9`

, which stores a value (as a `double`

) in nanometers.

Internally, SAMSON uses the international system of units (SI), but is able to perform conversion to and from other units (*e.g.* convert kilocalories per mole to zeptojoules).

Quantities are declared in typical C++ fashion, for example using types defined in the SAMSON SDK:

SBQuantity::angstrom l; // l is a length expressed in angstroms

SBQuantity::zeptojoule e; // e is an energy expressed in zeptojoules

SBQuantity::dimensionless d; // d is a dimensionless quantity

SAMSON has default type definitions (*via* typedefs) for common dimensions. For example, the following two statements are equivalent:

SBQuantity::zeptojoule e1(10); // e1 is equal to 10 zeptojoules

SBQuantity::energy e2(10); // e2 is equal to 10 zeptojoules

Please refer to this section for the list of default types.

There is no implicit conversion from C++ types (*e.g.* `double`

) to SAMSON quantities, in order to help developers avoid mistakes:

SBQuantity::angstrom d1 = 10; // error, does not compile

SBQuantity::angstrom d2(10); // OK, d2 is equal to 10 angstroms

SAMSON automatically converts between compatible units in the same system, or between different systems when conversions have been defined:

When units are incompatible, an error is detected at compilation time. This *automatic dimensional analysis* helps developers manipulate physical quantities correctly:

SBQuantity::energy w1 = f/d; // error, does not compile

SBQuantity::energy w2 = f*d; // OK, w2 = 1000 zeptojoules

Typical operations are possible through overloaded operators:

SBQuantity::energy k = 0.5*m*v*v; // k = 0.5 zeptojoules

Note that **operations are only defined for units that belong to the same system** (SI, atomic units, etc.), so that conversions have to be performed before applying operations between quantities expressed in different systems:

SBQuantity::kcalPerMol e(1); // e = 1 kilocalorie per mole

SBQuantity::pm l(1); // l = 1 picometer

SBQuantity::nanonewton f1 = e/l; // error, incompatible systems

For convenience, many usual mathematical functions have been overloaded for quantities, *e.g.*:

SBQuantity::energy a(-1.0); // a = -1 zeptojoule

SBQuantity::energy b = abs(a); // b = 1 zeptojoule

SBQuantity::dimensionless x(-2.0); // x = -2

SBQuantity::area d(9); // d = 9 picometer^2

Note that some functions only compile for dimensionless quantities (*e.g.* `exp`

, `log`

, `cos`

, `sin`

, etc.).

All overloaded functions have the same syntax as their regular C++ counterpart, except for `pow`

and `root`

, which use a template syntax:

SBQuantity::length a(2.0); // a = 2 picometers

SBQuantity::squareLength b = pow<2>(a); // b = 4 picometer^2

SBQuantity::length c = root<2>(b); // c = 2 picometers

Numerous units have been predefined in SAMSON (see the documentation of SBDQuantity). However, when a new type is required, templates may be used to form it through inversions, products, divisions, powers and roots:

// a is expressed in inverse moles

SBQuantityInverse<SBQuantity::mole>::Type a;

// b is expressed in moles.seconds

SBQuantityProduct2<SBQuantity::mole, SBQuantity::second>::Type b;

// c is expressed in grams per mole

SBQuantityInverse<SBQuantity::mole>::Type> >::Type c;

// d is expressed in grams per mole

SBQuantityDivision<SBQuantity::gram, SBQuantity::mole>::Type d;

// e is expressed in picometer^6

SBQuantityPower<6, SBQuantity::picometer>::Type e;

// f is expressed in angstroms

SBQuantityRoot<3, SBQuantity::cubicAngstrom>::Type f;

For convenience, templates have been defined for products of up to seven units (SBQuantityProduct2, ..., SBQuantityProduct7), *e.g.*:

// a is expressed in moles.seconds.grams

SBQuantityProduct3<SBQuantity::mole, SBQuantity::second,SBQuantity::gram>::Type a;

Of course, typedefs may be used to help declare variables:

// gramPerMole is a new unit

SBQuantityInverse<SBQuantity::mole>::Type> >::Type gramPerMole;

gramPerMole a; // a is expressed in grams per mole

Note that products and divisions have the following limitation: they must involve units within the same systems and, if two unit types have non-zero exponents for a given base unit, then the associated scales must be the same. It is thus acceptable to declare:

// f is in force units

SBQuantityDivision<SBQuantity::energy, SBQuantity::length>::Type f;

since both `SBQuantity::energy`

and `SBQuantity::length`

involve picometers (scale -12), but the following is incorrect:

// this is incorrect

SBQuantityDivision<SBQuantity::energy, SBQuantity::angstrom>::Type f;

since the calculation involves two different scales: picometers in the energy (scale -12), and angstroms (scale -10).

- Atomic units (AU)
- Dalton
- Electronvolt
- KilocaloriePerMole

It will often be useful to make new units based on existing units. For example, assume you want to define

When integrating existing code as SAMSON Elements you can define your own unit systems and units.

SAMSON has a list of default types, for common dimensions. For example, instead of declaring a length as follows:

SBQuantity::nanometer l1; // l1 is a length

it might be preferable to write:

SBQuantity::length l2; // l2 is a length

These dimensions are typedefs for units that are natural in nanoscience, when expressed in the international system of units. For example, `length`

is a typedef for `picometer`

, so that, in the example above, `l1`

and `l2`

have *different types* (but conversions are possible). As a result, when *defining* a variable (*i.e.* when assigning a value to it), it is strongly encouraged to use units instead of dimensions:

// unclear and risky (the definition of length could change)

SBQuantity::length l1(10);

// OK (even if the definition of length would change)

SBQuantity::length l2 = SBQuantity::angstrom(10);

Here is the list of default types defined in SAMSON.

`SBQuantity::length`

==`SBQuantity::picometer`

`SBQuantity::mass`

==`SBQuantity::yoctogram`

`SBQuantity::time`

==`SBQuantity::femtosecond`

`SBQuantity::intensity`

==`SBQuantity::nanoampere`

`SBQuantity::temperature`

==`SBQuantity::kelvin`

`SBQuantity::amountOfSubstance`

==`SBQuantity::mole`

`SBQuantity::luminousIntensity`

==`SBQuantity::candela`

There are also inverse, square, inverse square base units defined, e.g.:

`SBQuantity::inverseLength`

`SBQuantity::squareLength`

`SBQuantity::inverseSquareLength`

`SBQuantity::cubicLength`

`SBQuantity::inverseCubicLength`

`SBQuantity::inverseMass`

`SBQuantity::inverseTime`

`SBQuantity::squareTime`

- etc.

`SBQuantity::distance`

==`SBQuantity::length`

`SBQuantity::inverseDistance`

==`SBQuantity::inverseLength`

`SBQuantity::squareDistance`

==`SBQuantity::squareLength`

`SBQuantity::inverseSquareDistance`

==`SBQuantity::inverseSquareLength`

`SBQuantity::cubicDistance`

==`SBQuantity::cubicLength`

`SBQuantity::inverseCubicDistance`

==`SBQuantity::inverseCubicLength`

`SBQuantity::electricCharge`

`SBQuantity::voltage`

`SBQuantity::electricField`

`SBQuantity::magneticDensity`

`SBQuantity::angularVelocity`

==`SBQuantity::inverseTime`

`SBQuantity::angularAcceleration`

==`SBQuantity::inverseSquareTime`

`SBQuantity::pressure`

`SBQuantity::lengthMass`

`SBQuantity::inverseLengthInverseMass`

`SBQuantity::area`

==`SBQuantity::squareLength`

`SBQuantity::inverseArea`

==`SBQuantity::inverseSquareLength`

`SBQuantity::volume`

==`SBQuantity::cubicLength`

`SBQuantity::inverseVolume`

==`SBQuantity::inverseCubicLength`

`SBQuantity::position`

==`SBQuantity::length`

`SBQuantity::velocity`

`SBQuantity::acceleration`

`SBQuantity::force`

`SBQuantity::energy`

`SBQuantity::inverseForce`

`SBQuantity::lengthPerForce`

`SBQuantity::forcePerLength`

`SBQuantity::energyPerSquareLength`

`SBQuantity::momentum`

`SBQuantity::inverseMomentum`

`SBQuantity::momentOfInertia`

`SBQuantity::inverseMomentOfInertia`

`SBQuantity::electronDensity`

Here is the list of defined vector dimensions, and their corresponding types:

`SBVector3`

:`SBPhysicalVector3<SBQuantity::dimensionless>`

`SBPicometerPerSecond3`

:`SBPhysicalVector3<SBQuantity::picometerPerSecond>`

`SBRadian3`

:`SBPhysicalVector3<SBQuantity::radian>`

`SBRadianPerSecond3`

:`SBPhysicalVector3<SBQuantity::radianPerSecond>`

`SBLength3`

:`SBPhysicalVector3<SBQuantity::length>`

`SBInverseLength3`

:`SBPhysicalVector3<SBQuantity::inverseLength>`

`SBSquareLength3`

:`SBPhysicalVector3<SBQuantity::squareLength>`

`SBPosition3`

:`SBPhysicalVector3<SBQuantity::position>`

`SBVelocity3`

:`SBPhysicalVector3<SBQuantity::velocity>`

`SBAcceleration3`

:`SBPhysicalVector3<SBQuantity::acceleration>`

`SBEnergy3`

:`SBPhysicalVector3<SBQuantity::energy>`

`SBTorque3`

:`SBPhysicalVector3<SBQuantity::energy>`

`SBForce3`

:`SBPhysicalVector3<SBQuantity::force>`

`SBMomentum3`

:`SBPhysicalVector3<SBQuantity::momentum>`

`SBInverseMomentum3`

:`SBPhysicalVector3<inverseMomentum>`

- See also
- SBDTypePhysicalVector3

Here is the list of defined spatial vector dimensions, and their corresponding types:

`SBVector6`

:`SBPhysicalVector6<SBQuantity::dimensionless, SBQuantity::dimensionless>`

`SBForce6`

:`SBPhysicalVector6<SBQuantity::energy, SBQuantity::force>`

`SBVelocity6`

:`SBPhysicalVector6<SBQuantity::inverseTime, SBQuantity::velocity>`

`SBAcceleration6`

:`SBPhysicalVector6<SBQuantity::inverseSquareTime, SBQuantity::acceleration>`

- See also
- SBDTypePhysicalVector6

Here is the list of defined interval dimensions, and their corresponding types:

`SBInterval`

:`SBDTypePhysicalInterval<SBQuantity::dimensionless>`

`SBLengthInterval`

:`SBDTypePhysicalInterval<SBQuantity::length>`

`SBSquareLengthInterval`

:`SBDTypePhysicalInterval<SBQuantity::squareLength>`

`SBPositionInterval`

:`SBDTypePhysicalInterval<SBQuantity::position>`

`SBVelocityInterval`

:`SBDTypePhysicalInterval<SBQuantity::velocity>`

`SBAccelerationInterval`

:`SBDTypePhysicalInterval<SBQuantity::acceleration>`

`SBEnergyInterval`

:`SBDTypePhysicalInterval<SBQuantity::energy>`

`SBForceInterval`

:`SBDTypePhysicalInterval<SBQuantity::force>`

`SBMomentumInterval`

:`SBDTypePhysicalInterval<SBQuantity::momentum>`

- See also
- SBDTypePhysicalInterval

Here is the list of defined interval vector dimensions, and their corresponding types:

`SBIAVector3`

:`SBDTypePhysicalIAVector3<SBQuantity::dimensionless>`

`SBIARadian3`

:`SBDTypePhysicalIAVector3<SBQuantity::radian>`

`SBIARadianPerSecond3`

:`SBDTypePhysicalIAVector3<SBQuantity::radianPerSecond>`

`SBIAPosition3`

:`SBDTypePhysicalIAVector3<SBQuantity::picometer>`

`SBIAPosition3`

:`SBDTypePhysicalIAVector3<SBQuantity::picometer>`

`SBIAVelocity3`

:`SBDTypePhysicalIAVector3<SBQuantity::picometerPerFemtosecond>`

`SBIAAcceleration3`

:`SBDTypePhysicalIAVector3<SBQuantity::picometerPerSquareFemtosecond>`

`SBIAForce3`

:`SBDTypePhysicalIAVector3<SBQuantity::nanonewton>`

`SBIAMomentum3`

:`SBDTypePhysicalIAVector3<SBQuantity::yoctogramPicometerPerFemtosecond>`

- See also
- SBDTypePhysicalIAVector3

Here is the list of defined 3x3 matrix dimensions, and their corresponding types:

`SBMatrix33`

:`SBPhysicalMatrix33<SBQuantity::dimensionless>`

`SBMass33`

:`SBPhysicalMatrix33<SBQuantity::mass>`

`SBInverseMass33`

:`SBPhysicalMatrix33<SBQuantity::inverseMass>`

`SBInertiaTensor33`

:`SBPhysicalMatrix33<SBQuantity::momentOfInertia>`

`SBInverseInertiaTensor33`

:`SBPhysicalMatrix33<SBQuantity::inverseMomentOfInertia>`

- See also
- SBDTypePhysicalMatrix33

Here is the list of defined 6x6 spatial matrix dimensions, and their corresponding types:

`SBMatrix66`

- dimensionless`SBInertia66`

`SBInverseInertia66`

- See also
- SBDTypePhysicalMatrix66