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 Extensions (although it is natural when integrating existing source code).
In order to use units types, the SBQuantity.hpp
header should be included:
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.
Definitions#
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 ofmeter
. - The scale of a scaled base unit is the corresponding power of ten, e.g. the scale of
nanometer
is-9
, relative to themeter
. - 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
is2
. - Derived units are products of exponentiated units. For instance,
newton
is defined askg.m.s^-2
, whilenanonewton
is defined in SAMSON asyg.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).
Basic usage#
Declaration and definition#
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
SBQuantity::angstrom d3 = SBQuantity::nm(1); // OK, d3 is equal to 10 angstroms
Conversions#
SAMSON automatically converts between compatible units in the same system, or between different systems when conversions have been defined:
SBQuantity::angstrom d = SBQuantity::nm(1); // d = 10 angstroms
SBQuantity::zJ e = SBQuantity::kcalPerMol(1); // e = 6.94769(...) zeptojoules
When units are incompatible, an error is detected at compilation time. This automatic dimensional analysis helps developers manipulate physical quantities correctly:
SBQuantity::angstrom d = SBQuantity::nm(1); // d = 10 angstroms
SBQuantity::force f = SBQuantity::nanonewton(1); // f = 1 nanonewton
SBQuantity::energy w1 = f/d; // error, does not compile
SBQuantity::energy w2 = f*d; // OK, w2 = 1000 zeptojoules
Operations#
Typical operations are possible through overloaded operators:
SBQuantity::mass m=SBQuantity::yg(1); // m = 1 yoctogram
SBQuantity::velocity v=SBQuantity::pmPerFs(1); // v = 1 pm per femtosecond
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
SBQuantity::nanonewton f2 = (SBQuantity::J)e/l; // OK, e is converted to SI
Mathematical functions#
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::dimensionless y = exp(x); // OK, x is dimensionless
SBQuantity::area d(9); // d = 9 picometer^2
SBQuantity::length e = sqrt(d); // e = 3 picometers
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
Making new units#
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 (SBDQuantityInverse
), products (SBDQuantityProduct2
, etc.), divisions (SBDQuantityDivision
), powers (SBDQuantityPower
), and roots (SBDQuantityRoot
):
// 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
SBQuantityProduct2<SBQuantity::gram,
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
typedef SBQuantityProduct2<
SBQuantity::gram,
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:
since both SBQuantity::energy
and SBQuantity::length
involve picometers (scale -12), but the following is incorrect:
since the calculation involves two different scales: picometers in the energy (scale -12), and angstroms (scale -10).
Defined systems#
SI units (International System of Units)#
The standard SI units.
Non-SI unit systems#
- 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.
Defining new systems#
When integrating existing code as SAMSON Extensions you can define your own unit systems and units.
List of default types#
SAMSON has a list of default types, for common dimensions. For example, instead of declaring a length as follows:
it might be preferable to write:
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);
Default types#
Here is the non-comprehensive list of default types defined in SAMSON. To see all the defined units please check the corresponding headers.
Base types#
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.
Derived types#
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
Vectors#
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
Spatial vectors#
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
Intervals#
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
Interval vectors#
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
Matrices#
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
Spatial matrices#
Here is the list of defined 6x6 spatial matrix dimensions, and their corresponding types:
SBMatrix66
- dimensionlessSBInertia66
SBInverseInertia66
See also