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:
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:
meter
is a base unit for measuring length).nanometer
is a scaled version of meter
.nanometer
is -9
, relative to the meter
.nanometer^2
.nanometer^2
is 2
.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:
SAMSON has default type definitions (via typedefs) for common dimensions. For example, the following two statements are equivalent:
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:
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:
Typical operations are possible through overloaded operators:
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:
For convenience, many usual mathematical functions have been overloaded for quantities, e.g.:
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:
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:
For convenience, templates have been defined for products of up to seven units (SBQuantityProduct2, ..., SBQuantityProduct7), e.g.:
Of course, typedefs may be used to help declare variables:
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).
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 ...
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:
Here is the list of dimensions defined in SAMSON, and their corresponding types:
mass
: yoctogram
inverseMass
: inverseYoctogram
time
: femtosecond
inverseTime
: inverseFemtosecond
inverseSquareTime
: inverseSquareFemtosecond
angularVelocity
: inverseFemtosecond
angularAcceleration
: inverseSquareFemtosecond
length
: picometer
inverseLength
: inversePicometer
lengthMass
: SBQuantityProduct2<length, mass>::Type
inverseLengthMass
: SBQuantityInverse<lengthMass>::Type
squareLength
: squarePicometer
inverseSquareLength
: inverseSquarePicometer
cubicLength
: cubicPicometer
inverseCubicLength
: inverseCubicPicometer
area
: squarePicometer
inverseArea
: inverseSquarePicometer
volume
: cubicPicometer
inverseVolume
: inverseCubicPicometer
position
: picometer
velocity
: picometerPerFemtosecond
acceleration
: picometerPerSquareFemtosecond
force
: nanonewton
energy
: zeptojoule
energyPerSquareLength
: SBQuantityProduct2<energy,SBQuantityInverse<squareLength>::Type>::Type
momentum
: yoctogramPicometerPerFemtosecond
inverseMomentum
: SBQuantityInverse<yoctogramPicometerPerFemtosecond>::Type
momentOfInertia
: yoctogramSquarePicometer
inverseMomentOfInertia
: perYoctogramPerSquarePicometer
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>
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>
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>
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>