Physical Quantities  v1.0.0
C++ library of physical quantities, physical models, and units of measure for scientific computing. https://github.com/acodcha/phq
Physical Quantities

Physical Quantities (PhQ) is a C++ library of physical quantities, physical models, and units of measure for scientific computing.

Example:

PhQ::Velocity velocity{{6.0, -3.0, 2.0}, PhQ::Unit::Speed::MetrePerSecond};
PhQ::Speed speed = velocity.Magnitude();
std::cout << "Speed: " << speed << std::endl;
// Speed: 7.00000000000000000 m/s
PhQ::Direction direction = velocity.Direction();
std::cout << "Direction: " << direction << std::endl;
// Direction: (0.857142857142857095, -0.428571428571428548, 0.285714285714285698)
PhQ::Displacement displacement = velocity * time;
std::cout << "Displacement: " << displacement.Print(PhQ::Unit::Length::Centimetre) << std::endl;
// Displacement: (1.80000000000000000e+04, -9000.00000000000000, 6000.00000000000000) cm
std::string Print() const
Prints this physical quantity as a string. This physical quantity's value is expressed in its standar...
Three-dimensional Euclidean direction vector. Contains three components in Cartesian coordinates: x,...
Definition: Direction.hpp:115
constexpr Direction()
Default constructor. Initializes a direction to the zero vector.
Definition: Direction.hpp:118
Three-dimensional Euclidean displacement vector. Contains three components in Cartesian coordinates: ...
Scalar velocity component or magnitude of a velocity vector. For a three-dimensional Euclidean veloci...
Definition: Speed.hpp:100
Time. Can represent either a point in time, a time duration, or a period. For the inverse of time,...
Definition: Time.hpp:172
Three-dimensional Euclidean velocity vector. Contains three components in Cartesian coordinates: x,...
Definition: Velocity.hpp:55
@ Centimetre
Centimetre (cm) length unit.
@ Minute
Minute (min) time unit.
@ MetrePerSecond
Metre per second (m/s) speed unit.

If you have ever made a unit conversion error, or if you have ever asked yourself questions such as "what is the correct unit of mass density in the foot-pound-second system?", "how do I compute a stress field given a strain field?", or "what is a slug unit?", then this library is for you!

  • Physical quantities have no memory overhead compared to using raw floating-point numbers to represent the same data.
  • Mathematical operations between physical quantities have no runtime overhead compared to using raw floating-point numbers to perform the same operations.
  • Unit conversions are handled automatically when physical quantities are constructed, so physical quantities are guaranteed to always be in a consistent state. No more unit conversion errors!
  • Physical models enable tedious mathematical computations involving physical quantities to be performed easily. No more tensor-vector multiplication errors when computing stresses!
  • Unit systems allow scientific data to be expressed in several consistent systems of units for use across applications. Never again will you accidentally use pounds when you should have used slugs!

The Physical Quantities library is hosted at https://github.com/acodcha/phq and its documentation is hosted at https://acodcha.github.io/phq-docs.

Requirements

The Physical Quantities library requires the following packages:

  • C++ Compiler: A C++ compiler with support for the C++17 standard or any more recent standard is needed. Any recent C++ compiler will do, such as GCC or Clang. On Ubuntu, install GCC with sudo apt install g++ or Clang with sudo apt install clang.
  • CMake or Bazel: Either the CMake build system or the Bazel build system is required.
    • CMake: On Ubuntu, install CMake with sudo apt install cmake. Visit https://cmake.org for alternative means of installation.
    • Bazel: Follow the instructions at https://bazel.build/install to install Bazel on your system.

(Back to Top)

Configuration

The Physical Quantities library can be configured with either the CMake build system or the Bazel build system.

(Back to Top)

Configuration: CMake

To use this library in one of your CMake C++ projects, add the following code to your project's CMakeLists.txt file:

set(CMAKE_CXX_STANDARD 17) # Or any more recent C++ standard.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FetchContent)
find_package(PhQ CONFIG QUIET)
if(PhQ_FOUND)
message(STATUS "The PhQ library was found at ${PhQ_CONFIG}")
else()
FetchContent_Declare(
GIT_REPOSITORY https://github.com/acodcha/phq.git
GIT_TAG main
) # You can also use a specific version such as v1.0.0 instead of the main branch.
FetchContent_MakeAvailable(PhQ)
message(STATUS "The PhQ library was fetched from https://github.com/acodcha/phq.git")
endif()
[...]
target_link_libraries(your_target_name [your_other_options] PhQ)
Namespace that encompasses all of the Physical Quantities library's content.

The above code first checks whether the Physical Quantities library is installed on your system (see the Installation section). If found, the library is linked to your target. Otherwise, the library is automatically downloaded from its GitHub repository and linked to your target.

Once this is done, simply include this library's C++ headers in your project's C++ source files, such as #include <PhQ/Position.hpp> for the PhQ::Position class. The PhQ:: namespace encapsulates all of the Physical Quantities library's contents.

(Back to Configuration)

Configuration: Bazel

To use this library in one of your Bazel C++ projects, do the following.

Add the following code to your project's WORKSPACE.bazel file:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "PhQ",
remote = "https://github.com/acodcha/phq.git",
branch = "main",
)
# Alternatively, you can use a version tag instead of a branch, such as: tag = "v1.0.0"

The above code automatically downloads the Physical Quantities library and makes it available to your Bazel targets.

Next, add the following code to your project's BUILD.bazel file:

cc_library(
name = "your_library_name",
hdrs = [
"your_library_header_file_1.hpp",
"your_library_header_file_2.hpp",
],
srcs = [
"your_library_source_file_1.cpp",
"your_library_source_file_2.cpp",
],
deps = [
":your_other_dependency_1",
":your_other_dependency_2",
"@PhQ//:Position",
"@PhQ//:ConstitutiveModel/ElasticIsotropicSolid",
],
copts = [
"-your-other-parameters",
"-std=c++17", # Or any more recent C++ standard.
],
)

The above code adds the dependencies for the PhQ::Position and PhQ::ConstitutiveModel::ElasticIsotropicSolid classes to your Bazel C++ library.

Finally, simply include this library's C++ headers in your project's C++ source files, such as #include <PhQ/Position.hpp> for the PhQ::Position class. The PhQ:: namespace encapsulates all of this library's contents.

(Back to Configuration)

Usage

This section contains basic usage information of the Physical Quantities library; see the Documentation section for the full documentation.

(Back to Top)

Usage: Basics

Physical quantities are constructed from a value and a unit and support standard arithmetic operations. For example:

PhQ::Temperature average = 0.5 * (low + high);
std::cout << "Average: " << average.Print(PhQ::Unit::Temperature::Celsius) << std::endl;
// Average: 15.0000000000000000 °C
std::string Print() const
Prints this physical quantity as a string. This physical quantity's value is expressed in its standar...
Temperature. For a temperature difference, see PhQ::TemperatureDifference. For the gradient of temper...
Definition: Temperature.hpp:41
@ Celsius
Degree Celsius (°C) temperature unit.
@ Fahrenheit
Degree Fahrenheit (°F) temperature unit.

The above example creates two temperature quantities, computes their average, and prints the result.

Physical quantities support the float, double, and long double floating-point numeric types. A physical quantity's type is inferred from its constructor arguments and can also be explicitly specified. If no type is explicitly specified and the default constructor is used, the double type is used by default. For example:

// Defaults to PhQ::Area<double>.
PhQ::Area area_double;
// PhQ::Area<float> is inferred from the constructor argument.
// PhQ::Area<long double> is explicitly specified.
PhQ::Area<long double> area_long_double;
area_long_double = {4.56L, PhQ::Unit::Area::SquareFoot};
// Casts a PhQ::Area<long double> to a PhQ::Area<double>.
// The underlying value is cast from long double to double.
area_double = area_long_double;
Surface area or cross-sectional area. Can also represent a scalar component of a vector area or the m...
Definition: Area.hpp:71
@ Hectare
Hectare (ha) area unit.
@ SquareFoot
Square foot (ft^2) area unit.

For performance reasons, physical quantities are constructed with uninitialized values by default. Alternatively, the Zero() static method can be used to zero-initialize a physical quantity. For example:

PhQ::Angle<> angle; // Uninitialized.
angle = {45.0, PhQ::Unit::Angle::Degree};
Plane angle between two lines or dihedral angle between two planes.
Definition: Angle.hpp:130
Mach number of a fluid flow. Measures the local compressibility of a fluid flow. Represents the ratio...
Definition: MachNumber.hpp:42
static constexpr MachNumber< NumericType > Zero()
Statically creates a Mach number of zero.
Definition: MachNumber.hpp:84
Three-dimensional Euclidean position vector. Contains three components in Cartesian coordinates: x,...
Definition: Position.hpp:50
static constexpr Position< NumericType > Zero()
Statically creates a position vector of zero.
Definition: Position.hpp:106
@ Degree
Degree (deg) angle unit.

Physical quantities can be constructed statically with the Create static method. For example:

std::cout << "Power: " << power << std::endl;
// Power: 5000.000000 W
Power. Time rate of change of energy or energy transfer rate; see PhQ::Energy, PhQ::Time,...
Definition: Power.hpp:51

Physical quantities are implemented efficiently with no memory overhead compared to using raw floating-point numbers to represent the same data. For example:

assert(sizeof(volume) == sizeof(double));
PhQ::Position<float> position{{-1.11F, 2.22F, -3.33F}, PhQ::Unit::Length::Mile};
assert(sizeof(position) == 3 * sizeof(float));
Volume. For the time rate of change of volume, see PhQ::VolumeRate; see also PhQ::Time and PhQ::Frequ...
Definition: Volume.hpp:62
@ Mile
Mile (mi) length unit.
@ Litre
Litre (L) volume unit.

The only circumstance in which the Physical Quantities library throws an exception is a memory allocation failure due to running out of memory on your system when instantiating a new C++ object. In this case, C++ throws a std::bad_alloc exception.

If maintaining a strong exception guarantee is a concern, use try and catch blocks when instantiating new objects to handle this exception. Other than this case, the Physical Quantities library does not throw exceptions. Where applicable, this library's functions and methods are marked noexcept.

(Back to Usage)

Usage: Vectors and Tensors

Physical quantities' values can be scalars, vectors, or dyadic tensors. Vectors and dyadic tensors are defined in three-dimensional Euclidean space and use Cartesian coordinates. For example:

PhQ::HeatFlux heat_flux{{-200.0, // x
300.0, // y
-600.0}, // z
heat_flux /= 7.0;
PhQ::ScalarHeatFlux magnitude = heat_flux.Magnitude();
std::cout << "Magnitude: " << magnitude.Print() << std::endl;
// Magnitude: 100.000000000000000 W/m^2
Three-dimensional Euclidean heat flux vector. Contains three components in Cartesian coordinates: x,...
Definition: HeatFlux.hpp:50
Scalar heat flux component or magnitude of a heat flux vector. For a three-dimensional Euclidean heat...
@ WattPerSquareMetre
Watt per square metre (W/m^2) energy flux unit.

The above example creates a heat flux of (-200, 300, -600) W/m^2, divides it by 7, and computes and prints its magnitude, which results in 100 W/m^2.

Two-dimensional planar vectors in the XY plane are also supported. For example:

PhQ::PlanarForce planar_force{{-300.0, // x
400.0}, // y
planar_force *= 2.0;
PhQ::ScalarForce magnitude = planar_force.Magnitude();
std::cout << "Magnitude: " << magnitude.Print(PhQ::Unit::Force::Pound) << std::endl;
// Magnitude: 1000.00000000000000 lbf
Two-dimensional Euclidean force vector in the XY plane. Contains two components in Cartesian coordina...
Definition: PlanarForce.hpp:50
Scalar force component or magnitude of a force vector. For a three-dimensional Euclidean force vector...
Definition: ScalarForce.hpp:66
@ Pound
Pound (lbf) force unit.

The above example creates a planar force of (-300, 400) lbf, doubles it, computes its magnitude, and prints the magnitude in pounds, which results in 1,000 lbf.

The components of dyadic tensors are listed in alphabetical order: xx, xy, xz, yx, yy, yz, zx, zy, and zz. Some dyadic tensor physical quantities are symmetric while others are asymmetric. Symmetric dyadic tensors only need to specify their upper triangular components: xx, xy, xz, yy, yz, and zz. For example:

PhQ::Stress stress{{32.0, // xx
-4.0, // xy = yx
-2.0, // xz = zx
16.0, // yy
-1.0, // yz = zy
8.0}, // zz
assert(stress.Value().xy() == stress.Value().yx());
std::cout << "Equivalent von Mises stress: " << stress.VonMises() << std::endl;
// Equivalent von Mises stress: 2.26053091109146290e+07 Pa
Three-dimensional Euclidean Cauchy stress symmetric dyadic tensor. Contains six components in Cartesi...
Definition: Stress.hpp:50
@ Megapascal
Megapascal (MPa) pressure unit.

The above example creates a stress tensor, asserts that it is symmetric, and computes and prints its equivalent von Mises stress.

(Back to Usage)

Usage: Operations

Meaningful arithmetic operations between different physical quantities are supported via operator overloading. Mathematical operations between physical quantities are implemented efficiently with no runtime overhead compared to using raw floating-point numbers to represent the same data. For example:

PhQ::Velocity velocity{{50.0, -10.0, 20.0}, PhQ::Unit::Speed::MetrePerSecond};
PhQ::Acceleration acceleration = velocity / time;
std::cout << "Acceleration: " << acceleration << std::endl;
// Acceleration: (5.00000000000000000, -1.00000000000000000, 2.00000000000000000) m/s^2
Three-dimensional Euclidean acceleration vector. Contains three components in Cartesian coordinates: ...
@ Second
Second (s) time unit.

The above example creates a velocity of (50, -10, 20) m/s and a time of 10 s, then divides the velocity by the time to produce an acceleration of (5, -1, 2) m/s^2.

Similarly, other meaningful mathematical operations are supported via member methods. For example:

PhQ::Displacement displacement{{0.0, 6.0, 0.0}, PhQ::Unit::Length::Inch};
PhQ::Length length = displacement.Magnitude();
PhQ::Direction direction = displacement.Direction();
std::cout << "Length and direction: " << length << " and " << direction << std::endl;
// Length and direction: 0.152399999999999980 m and (0, 1.00000000000000000, 0)
PhQ::Displacement other_displacement{{0.0, 0.0, -3.0}, PhQ::Unit::Length::Foot};
PhQ::Angle angle{displacement, other_displacement};
std::cout << "Angle: " << angle.Print(PhQ::Unit::Angle::Degree) << std::endl;
// Angle: 90.0000000000000000 deg
Length< NumericType > Magnitude() const
Returns the magnitude of this displacement vector.
PhQ::Direction< NumericType > Direction() const
Returns the direction of this displacement vector.
Length, distance, or physical size. Can also represent a scalar component or magnitude of a position ...
Definition: Length.hpp:111
@ Foot
Foot (ft) length unit.
@ Inch
Inch (in) length unit.

The above example creates a displacement of (0, 6, 0) in, computes and prints its magnitude and direction, then creates a second displacement of (0, 0, -3) ft, and computes and prints the angle between the two displacements, which is 90 deg.

Physical quantities define the standard comparison operators (==, !=, <, >, <=, and >=) and specialize the std::hash function object such that they can be used in standard containers such as std::set, std::unordered_set, std::map, and std::unordered_map. For example:

assert(PhQ::MachNumber(0.8) == PhQ::MachNumber(0.8));
assert(PhQ::ReynoldsNumber(5000.0) > PhQ::ReynoldsNumber(200.0));
std::set<PhQ::AngularSpeed<>> angular_speed_set{
}; // Uses the less-than comparison operator (<).
std::unordered_set<PhQ::StaticPressure<>> static_pressure_unordered_set{
}; // Uses std::hash<PhQ::StaticPressure<>>.
Reynolds number of a fluid flow. Measures the local turbulence of a fluid flow. Represents the ratio ...
Static pressure. Pressure of a fluid at rest. Not to be confused with dynamic pressure,...
@ Kilopascal
Kilopascal (kPa) pressure unit.
@ Bar
Bar (bar) pressure unit.
AngularSpeed
Angular speed units.
@ RevolutionPerMinute
Revolution per minute (rev/min) angular speed unit.
@ RadianPerSecond
Radian per second (rad/s) angular speed unit.

The Physical Quantities library checks for divisions by zero in certain critical internal arithmetic operations. For example, PhQ::Direction carefully checks for the zero vector case when normalizing its magnitude, and PhQ::Dyad and PhQ::SymmetricDyad carefully check for a zero determinant when computing their inverse.

However, in general, divisions by zero can occur during arithmetic operations between physical quantities. For example, PhQ::Length<>::Zero() / PhQ::Time<>::Zero() results in a PhQ::Speed with a value of "not-a-number" (NaN). C++ uses the IEEE 754 floating-point arithmetic standard such that divisions by zero result in inf, -inf, or NaN. If any of these special cases are a concern, use try and catch blocks or standard C++ utilities such as std::isfinite.

Similarly, floating-point overflows and underflows can occur during arithmetic operations between physical quantities. If this is a concern, query the status of the C++ floating-point environment with std::fetestexcept.

(Back to Usage)

Usage: Units

The Physical Quantities library handles unit conversions automatically, and all unit conversions are exact to within floating-point arithmetic precision.

When a physical quantity object is constructed, its value is immediately converted to the standard unit of measure in the standard system of units: the metre-kilogram-second-kelvin (m·kg·s·K) system. This way, all physical quantities maintain their values in a consistent system of units. This approach greatly minimizes the number of unit conversions during program execution; when arithmetic operations are performed between physical quantities, no unit conversion is needed.

The only other instances where a physical quantity undergoes a unit conversion is when its value is expressed in a different unit of measure or when the physical quantity itself is printed as a string expressed in a different unit of measure. These cases are illustrated in the following examples.

A physical quantity's value can be expressed in any unit of measure through its Value method. For example:

double standard_value = mass.Value();
std::string_view standard_abbreviation = PhQ::Abbreviation(standard_unit);
std::cout << "Mass: " << standard_value << " " << standard_abbreviation << std::endl;
// Mass: 4.53592 kg
std::string_view other_abbreviation = PhQ::Abbreviation(other_unit);
double other_value = mass.Value(other_unit);
std::cout << "Mass: " << other_value << " " << other_abbreviation << std::endl;
// Mass: 4535.92 g
static constexpr Unit::Mass Unit()
Standard unit of measure for this physical quantity. This physical quantity's value is stored interna...
Mass. For the time rate of change of mass, see PhQ::MassRate; see also PhQ::Time and PhQ::Frequency.
Definition: Mass.hpp:100
Mass
Mass units.
Definition: Mass.hpp:53
@ Pound
Pound (lbm) mass unit.
@ Gram
Gram (g) mass unit.
std::string_view Abbreviation(const Enumeration enumeration)
Returns the abbreviation of a given enumeration value. For example, PhQ::Abbreviation(PhQ::Unit::Time...
Definition: Base.hpp:89

The above example creates a 10 lbm mass and prints its value as 4.535924 kg and 4535.924 g.

A physical quantity can be expressed in any unit of measure through its Print method. For example:

std::string standard = frequency.Print();
std::string kilohertz = frequency.Print(PhQ::Unit::Frequency::Kilohertz);
std::cout << "Frequency: " << standard << " = " << kilohertz << std::endl;
// Frequency: 1234.56789000000003 Hz = 1.23456789000000011 kHz
Frequency. Inverse of a time duration. See also PhQ::Time.
Definition: Frequency.hpp:40
@ Kilohertz
Kilohertz (kHz) frequency unit.
@ Hertz
Hertz (Hz) frequency unit.

The above example creates a 1234.56789 Hz frequency and prints it both in hertz and in kilohertz.

Unit conversions can also be performed directly on raw floating-point numbers through the PhQ::Convert, PhQ::ConvertInPlace, and PhQ::ConvertStatically functions, which take one or more floating-point values, an original unit, and a new unit. For example:

std::vector<double> values = {10.0, 20.0, 30.0, 40.0};
for (const double value : values) {
std::cout << value << std::endl;
}
// 7.37562
// 14.7512
// 22.1269
// 29.5025
@ Joule
Joule (J) energy unit.
@ FootPound
Foot-pound (ft·lbf) energy unit.
void ConvertInPlace(NumericType &value, const Unit original_unit, const Unit new_unit)
Converts a value expressed in a given unit of measure to a new unit of measure. The conversion is per...
Definition: Unit.hpp:128

The above example converts a collection of values from joules to foot-pounds. The same results can also be achieved using physical quantities instead of raw floating-point values. For example:

const std::vector<PhQ::Energy<>> energies{
};
for (const PhQ::Energy& energy : energies) {
std::cout << energy.Value(PhQ::Unit::Energy::FootPound) << std::endl;
}
// 7.37562
// 14.7512
// 22.1269
// 29.5025
Energy physical quantity. Can represent any kind of energy, such as kinetic energy,...
Definition: Energy.hpp:73

In general, when it comes to unit conversions, it is simpler to use the Value or Print member methods of physical quantities rather than to explicitly invoke conversion functions.

(Back to Usage)

Usage: Unit Systems

Internally, physical quantities store their values in the metre-kilogram-second-kelvin (m·kg·s·K) system. Unit conversions are performed automatically when physical quantity objects are constructed. Other common systems of units of measure are also defined:

  • Metre-kilogram-second-kelvin (m·kg·s·K) system
  • Millimetre-gram-second-kelvin (mm·g·s·K) system
  • Foot-pound-second-rankine (ft·lbf·s·°R) system
  • Inch-pound-second-rankine (in·lbf·s·°R) system

Data can be expressed in the consistent units of any of these unit systems. The unit of measure of a given type that corresponds to a given system of units can be obtained with the PhQ::ConsistentUnit function. For example:

PhQ::Unit::SpecificEnergy consistent_unit = PhQ::ConsistentUnit<PhQ::Unit::SpecificEnergy>(system);
std::cout << consistent_unit << std::endl;
// ft·lbf/slug
double value = specific_energy.Value(consistent_unit);
std::cout << value << std::endl;
// 107.639
Mass-specific energy. Energy per unit mass; see PhQ::Energy and PhQ::Mass.
SpecificEnergy
Mass-specific energy units.
@ JoulePerKilogram
Joule per kilogram (J/kg) specific energy unit.
UnitSystem
Systems of units of measure. All units of measure in a unit system are standard units of measure....
Definition: UnitSystem.hpp:43
@ FootPoundSecondRankine
Foot-pound-second-rankine (ft·lbf·s·°R) system.

The above example obtains the consistent unit of mass-specific energy in the foot-pound-second-rankine (ft·lbf·s·°R) system, creates a mass-specific energy of 10 J/kg, and expresses this mass-specific energy in the consistent unit.

Given a unit, it is also possible to obtain its related system of units, if any, with the PhQ::RelatedUnitSystem function. For example:

std::optional<PhQ::UnitSystem> optional_system = PhQ::RelatedUnitSystem(unit);
assert(optional_system.has_value());
std::cout << optional_system.value() << std::endl;
// ft·lbf·s·°R
@ Slug
Slug (slug) mass unit.
std::optional< UnitSystem > RelatedUnitSystem(const Unit &unit)
Returns the unit system, if any, that corresponds to a given unit, or std::nullptr otherwise....
Definition: UnitSystem.hpp:229

The above example obtains the system of units related to the slug mass unit, which is the foot-pound-second-rankine (ft·lbf·s·°R) system.

However, not all units of measure have a corresponding system of units. For example:

std::optional<PhQ::UnitSystem> optional_system = PhQ::RelatedUnitSystem(unit);
assert(!optional_system.has_value());

The above example shows that the pound (lbm) mass unit does not relate to any particular system of units.

(Back to Usage)

Usage: Models

Some physical models and related operations are supported. Physical models allow complex mathematical calculations to be performed easily. For example:

const std::unique_ptr<const ConstitutiveModel> constitutive_model =
std::make_unique<const ConstitutiveModel::ElasticIsotropicSolid<double>>(
PhQ::Strain<double> strain{32.0, // xx
-4.0, // xy
-2.0, // xz
16.0, // yy
-1.0, // yz
8.0}; // zz
PhQ::Stress<double> stress = constitutive_model->Stress(strain);
std::cout << stress << std::endl;
// (4.54489164086687305e+12, -2.10526315789473663e+11, -1.05263157894736832e+11;
// 3.70278637770897803e+12, -5.26315789473684158e+10; 3.28173374613003076e+12) Pa
Poisson's ratio of a deformable solid material. Measures the deformation of a deformable solid materi...
Three-dimensional Euclidean strain symmetric dyadic tensor. Contains six components in Cartesian coor...
Definition: Strain.hpp:68
Stress()=default
Default constructor. Constructs a stress tensor with an uninitialized value.
Young's modulus of elasticity of a deformable solid material. A measure of a deformable solid materia...
@ Gigapascal
Gigapascal (GPa) pressure unit.

The above example creates an elastic isotropic solid constitutive model from a Young's modulus and a Poisson's ratio, and then uses it to compute the stress tensor resulting from a given strain tensor.

(Back to Usage)

Usage: Dimensions

Seven independent base physical dimensions form the physical dimension set of any unit of measure or physical quantity. These seven independent base physical dimensions are: time (T), length (L), mass (M), electric current (I), temperature (Θ), amount of substance (N), and luminous intensity (J). Units of measure that share the same physical dimension set are of the same type and can be converted between one another.

For example, the metre per second and the mile per hour are both units of measure that have the same physical dimension set of T^(-1)·L, which is the physical dimension set of speed, so these two units of measure can be converted between one another.

On the other hand, the kilogram per cubic metre is a unit of measure with physical dimension set L^(-3)·M, which is the physical dimension set of mass density, so this unit of measure cannot be converted to either the metre per second or the mile per hour, which have a different physical dimension set.

The Physical Quantities library organizes units of measure into types, where each type roughly corresponds to a given physical dimension set.

The physical dimension set of a unit of measure can be obtained with the PhQ::RelatedDimensions global variable. For example:

const PhQ::Dimensions dimensions = PhQ::RelatedDimensions<Unit::HeatCapacity>;
assert(dimensions.Time() == PhQ::Dimension::Time(-2));
assert(dimensions.Length() == PhQ::Dimension::Length(2));
assert(dimensions.Mass() == PhQ::Dimension::Mass(1));
assert(dimensions.Temperature() == PhQ::Dimension::Temperature(-1));
std::cout << "Dimensions: " << dimensions << std::endl;
// Dimensions: T^(-2)·L^2·M·Θ^(-1)
Base physical dimension of electric current. Typically denoted "I". One of seven independent base phy...
Base physical dimension of length. Typically denoted "L". One of seven independent base physical dime...
Definition: Length.hpp:40
Base physical dimension of luminous intensity. Typically denoted "J". One of seven independent base p...
Base physical dimension of mass. Typically denoted "M". One of seven independent base physical dimens...
Definition: Mass.hpp:40
Base physical dimension of amount of substance. Typically denoted "N". One of seven independent base ...
Base physical dimension of temperature. Typically denoted "Θ". One of seven independent base physical...
Definition: Temperature.hpp:40
Base physical dimension of time. Typically denoted "T". One of seven independent base physical dimens...
Definition: Time.hpp:40
Physical dimension set of a unit of measure or physical quantity. Composed of the seven independent b...
Definition: Dimensions.hpp:49
constexpr const Dimension::Temperature & Temperature() const noexcept
Base physical dimension of temperature of this physical dimension set.
Definition: Dimensions.hpp:104
constexpr const Dimension::ElectricCurrent & ElectricCurrent() const noexcept
Base physical dimension of electric current of this physical dimension set.
Definition: Dimensions.hpp:99
constexpr const Dimension::SubstanceAmount & SubstanceAmount() const noexcept
Base physical dimension of amount of substance of this physical dimension set.
Definition: Dimensions.hpp:109
constexpr const Dimension::Length & Length() const noexcept
Base physical dimension of length of this physical dimension set.
Definition: Dimensions.hpp:89
constexpr const Dimension::Mass & Mass() const noexcept
Base physical dimension of mass of this physical dimension set.
Definition: Dimensions.hpp:94
constexpr const Dimension::Time & Time() const noexcept
Base physical dimension of time of this physical dimension set.
Definition: Dimensions.hpp:84
constexpr const Dimension::LuminousIntensity & LuminousIntensity() const noexcept
Base physical dimension of luminous intensity of this physical dimension set.
Definition: Dimensions.hpp:114

The above example obtains the physical dimension set of heat capacity, which is T^(-2)·L^2·M·Θ^(-1).

The physical dimension set of a physical quantity is simply the physical dimension set of its unit of measure and can be obtained with the Dimensions method. For example:

assert(dimensions.Time() == PhQ::Dimension::Time(0));
assert(dimensions.Length() == PhQ::Dimension::Length(-3));
assert(dimensions.Mass() == PhQ::Dimension::Mass(1));
assert(dimensions.Temperature() == PhQ::Dimension::Temperature(0));
std::cout << "Dimensions: " << dimensions << std::endl;
// Dimensions: L^(-3)·M
static constexpr const PhQ::Dimensions & Dimensions()
Physical dimension set of this physical quantity.

The above example obtains the physical dimension set of mass density, which is L^(-3)·M.

(Back to Usage)

Documentation

The full documentation of the Physical Quantities library is hosted here, at https://acodcha.github.io/phq-docs:

Alternatively, the documentation can be built locally on your system. Doing so requires the following additional package:

Clone the Physical Quantities library's repository and build its documentation with:

git clone git@github.com:acodcha/phq.git PhQ
cd PhQ
doxygen Doxyfile

This builds HTML documentation pages in the PhQ/docs/html/ directory. Browse the documentation by opening the PhQ/docs/html/index.html file in a web browser.

(Back to Top)

Installation

If using the CMake build system, the Physical Quantities library can optionally be installed on your system to conveniently use it in your CMake projects. Alternatively, see the Configuration section for other methods of use.

Clone this library's repository, configure it, and install it with:

git clone git@github.com:acodcha/phq.git PhQ
cd PhQ
mkdir build
cd build
cmake ..
sudo make install

This is a header-only library, so no compilation is needed. On most systems, the above code installs this library's headers to /usr/local/include/PhQ and writes configuration files to /usr/local/share/PhQ. You can uninstall the library by simply deleting these directories.

(Back to Top)

Testing

The Physical Quantities library is automatically tested whenever it is updated.

Testing can optionally be performed locally on your system. Doing so requires the following additional package:

Testing instructions differ depending on your build system.

If using the CMake build system, you can manually test the Physical Quantities library on your system with:

git clone git@github.com:acodcha/phq.git PhQ
cd PhQ
mkdir build
cd build
cmake .. -DTEST_PHQ_LIBRARY=ON
make --jobs=16
make test

If using the Bazel build system, you can manually test the Physical Quantities library on your system with:

git clone git@github.com:acodcha/phq.git PhQ
cd PhQ
bazel build //:all
bazel test //:all

(Back to Top)

Coverage

Code coverage (also known as test coverage) measures the extent to which a library's source code is covered by its tests. The Physical Quantities library currently has 100% coverage.

The Physical Quantities library's code coverage can optionally be computed locally on your system. Doing so requires the following additional package:

In addition to these requirements, code coverage computation also requires the CMake build system and either the GCC C++ compiler or the Clang C++ compiler; see the Requirements section for more information on these.

Compute the Physical Quantities library's code coverage with:

git clone git@github.com:acodcha/phq.git PhQ
cd PhQ
mkdir build
cd build
cmake .. -D PHYSICAL_QUANTITIES_PHQ_COVERAGE=ON
make --jobs=16
./bin/all_tests && make coverage

This generates an HTML report in the PhQ/coverage/ directory. Browse the report by opening the PhQ/coverage/index.html file in a web browser.

(Back to Top)

License

Copyright © 2020-2024 Alexandre Coderre-Chabot

Physical Quantities (PhQ) is a C++ library of physical quantities, physical models, and units of measure for scientific computing.

The Physical Quantities library is hosted at https://github.com/acodcha/phq and its documentation is hosted at https://acodcha.github.io/phq-docs. Physical Quantities is authored by Alexandre Coderre-Chabot (https://github.com/acodcha) and licensed under the MIT License; see the license file or https://mit-license.org.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

  • The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  • THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

(Back to Top)