From a47bd4d3d78239799f12abffc58f7aca86edc21a Mon Sep 17 00:00:00 2001 From: Guillaume Fraux Date: Fri, 1 May 2026 10:44:55 +0200 Subject: [PATCH 1/2] Use electric current instead of charge for dimension analysis This is what the SI system uses --- metatomic-torch/src/units.cpp | 50 ++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/metatomic-torch/src/units.cpp b/metatomic-torch/src/units.cpp index df7d389c..dbc70a83 100644 --- a/metatomic-torch/src/units.cpp +++ b/metatomic-torch/src/units.cpp @@ -26,17 +26,17 @@ * * @subsection dimensions Dimensional Analysis * - * Each unit has an associated 5-element dimension vector [L, T, M, Q, Th] - * representing exponents of Length, Time, Mass, Charge, and Temperature. - * For example: + * Each unit has an associated 5-element dimension vector [L, T, M, I, Θ] + * representing exponents of Length, Time, Mass, Electric current, and + * Temperature. For example: * - Length: [1, 0, 0, 0, 0] * - Energy: [2, -2, 1, 0, 0] (M L^2 T^-2) * - Force: [1, -2, 1, 0, 0] (M L T^-2) * - Pressure: [-1, -2, 1, 0, 0] (M L^-1 T^-2) * * Dimensional compatibility is checked by comparing these vectors with a - * tolerance of 1e-10 to accommodate floating-point accumulation from - * fractional powers. + * tolerance of 1e-10 to accommodate floating-point accumulation from fractional + * powers. * * @subsection conversion Conversion Factor Calculation * @@ -58,14 +58,16 @@ */ /// Dimension indices for the 5-element exponent vector. -/// Order: [Length, Time, Mass, Charge, Temperature] +/// Order: [Length, Time, Mass, Electric Current, Temperature] enum class DimIndex { - LENGTH = 0, - TIME = 1, - MASS = 2, - CHARGE = 3, - TEMPERATURE = 4, - COUNT = 5 // Number of dimensions + LENGTH, + TIME, + MASS, + ELECTRIC_CURRENT, + TEMPERATURE, + // we exclude amount of substance and luminous intensity + + COUNT // Number of dimensions }; /// Physical dimension vector: [Length, Time, Mass, Charge, Temperature] @@ -116,11 +118,27 @@ struct Dimension { return !(*this == other); } + static const char* dim_index_as_string(size_t index) { + switch (index) { + case static_cast(DimIndex::LENGTH): + return "L"; + case static_cast(DimIndex::TIME): + return "T"; + case static_cast(DimIndex::MASS): + return "M"; + case static_cast(DimIndex::ELECTRIC_CURRENT): + return "I"; + case static_cast(DimIndex::TEMPERATURE): + return "T"; + default: + return ""; + } + } + /// Convert dimension to a human-readable string format. /// Output format: "L^2 M T^-2" style (only non-zero exponents shown). /// Exponent 1 is omitted, negative exponents use "^-N" format. std::string to_string() const { - static const char* NAMES[] = {"L", "T", "M", "Q", "Th"}; std::string result; bool first = true; @@ -136,7 +154,7 @@ struct Dimension { } first = false; - result += NAMES[i]; + result += dim_index_as_string(i); // Only show exponent if not 1 or -1 if (std::fabs(v - 1.0) >= 1e-10 && std::fabs(v + 1.0) >= 1e-10) { @@ -169,11 +187,11 @@ struct UnitValue { }; // Dimension constants for readability -// L T M Q Th +// L T M I Θ static const Dimension DIM_LENGTH = {{ 1, 0, 0, 0, 0 }}; static const Dimension DIM_TIME = {{ 0, 1, 0, 0, 0 }}; static const Dimension DIM_MASS = {{ 0, 0, 1, 0, 0 }}; -static const Dimension DIM_CHARGE = {{ 0, 0, 0, 1, 0 }}; +static const Dimension DIM_CHARGE = {{ 0, 1, 0, 1, 0 }}; static const Dimension DIM_TEMPERATURE = {{ 0, 0, 0, 0, 1 }}; static const Dimension DIM_ENERGY = {{ 2, -2, 1, 0, 0 }}; static const Dimension DIM_NONE = {{ 0, 0, 0, 0, 0 }}; From a93f06fba1ae26d4b8d22ecee29e485393b3125f Mon Sep 17 00:00:00 2001 From: Guillaume Fraux Date: Fri, 1 May 2026 10:50:03 +0200 Subject: [PATCH 2/2] Add multiple new units --- docs/src/torch/reference/misc.rst | 12 +++++++++- metatomic-torch/src/units.cpp | 40 ++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/docs/src/torch/reference/misc.rst b/docs/src/torch/reference/misc.rst index f28e2260..1d4b522e 100644 --- a/docs/src/torch/reference/misc.rst +++ b/docs/src/torch/reference/misc.rst @@ -23,6 +23,10 @@ Supported base units Unit expressions are built from the following base units. Matching is case-insensitive, and whitespace is ignored. + +**Temperature**: + ``Kelvin`` (``K``) + **Length**: ``angstrom`` (``A``), ``Bohr``, ``meter`` (``m``), ``centimeter`` (``cm``), ``millimeter`` (``mm``), ``micrometer`` (``um``, ``µm``), ``nanometer`` (``nm``) @@ -35,11 +39,17 @@ case-insensitive, and whitespace is ignored. ``nanosecond`` (``ns``), ``picosecond`` (``ps``), ``femtosecond`` (``fs``) **Mass**: - ``u`` (``Dalton``), ``kilogram`` (``kg``), ``gram`` (``g``), ``electron_mass`` (``m_e``) + ``Dalton`` (``u``), ``kilogram`` (``kg``), ``gram`` (``g``), ``electron_mass`` (``m_e``) **Charge**: ``e``, ``Coulomb`` (``C``) +**Pressure**: + ``Pascal`` (``Pa``), ``kiloPascal`` (``kPa``), ``MegaPascal`` (``MPa``), ``GigaPascal`` (``GPa``), ``bar``, ``atm`` + +**Electric Dipole Moment**: + ``Debye`` (``D``) + **Dimensionless**: ``mol`` diff --git a/metatomic-torch/src/units.cpp b/metatomic-torch/src/units.cpp index dbc70a83..b905639c 100644 --- a/metatomic-torch/src/units.cpp +++ b/metatomic-torch/src/units.cpp @@ -186,15 +186,16 @@ struct UnitValue { Dimension dim; }; -// Dimension constants for readability -// L T M I Θ -static const Dimension DIM_LENGTH = {{ 1, 0, 0, 0, 0 }}; -static const Dimension DIM_TIME = {{ 0, 1, 0, 0, 0 }}; -static const Dimension DIM_MASS = {{ 0, 0, 1, 0, 0 }}; -static const Dimension DIM_CHARGE = {{ 0, 1, 0, 1, 0 }}; -static const Dimension DIM_TEMPERATURE = {{ 0, 0, 0, 0, 1 }}; -static const Dimension DIM_ENERGY = {{ 2, -2, 1, 0, 0 }}; -static const Dimension DIM_NONE = {{ 0, 0, 0, 0, 0 }}; +// Dimension constants for readability L T M I Θ +static const Dimension DIM_LENGTH = {{ 1, 0, 0, 0, 0 }}; +static const Dimension DIM_TIME = {{ 0, 1, 0, 0, 0 }}; +static const Dimension DIM_MASS = {{ 0, 0, 1, 0, 0 }}; +static const Dimension DIM_CHARGE = {{ 0, 1, 0, 1, 0 }}; +static const Dimension DIM_TEMPERATURE = {{ 0, 0, 0, 0, 1 }}; +static const Dimension DIM_ENERGY = {{ 2, -2, 1, 0, 0 }}; +static const Dimension DIM_PRESSURE = {{ -1, -2, 1, 0, 0 }}; +static const Dimension DIM_ELECTRIC_DIPOLE = {{ 1, 1, 0, 1, 0 }}; +static const Dimension DIM_NONE = {{ 0, 0, 0, 0, 0 }}; /// Lowercase a string in place and return it. static std::string to_lower(std::string s) { @@ -212,6 +213,10 @@ static std::string to_lower(std::string s) { /// Case-insensitive lookup: names are lowercased before searching. static const auto BASE_UNITS = std::unordered_map{ + // --- Temperature --- + {"kelvin", {1.0, DIM_TEMPERATURE}}, + {"k", {1.0, DIM_TEMPERATURE}}, + // --- Length --- {"angstrom", {1e-10, DIM_LENGTH}}, {"a", {1e-10, DIM_LENGTH}}, @@ -229,6 +234,7 @@ static const auto BASE_UNITS = std::unordered_map{ {"micrometer", {1e-6, DIM_LENGTH}}, // --- Energy --- + {"electronvolt", {1.602176634e-19, DIM_ENERGY}}, {"ev", {1.602176634e-19, DIM_ENERGY}}, {"mev", {1.602176634e-19 * 1e-3, DIM_ENERGY}}, {"hartree", {4.359744722206048e-18, DIM_ENERGY}}, @@ -269,6 +275,22 @@ static const auto BASE_UNITS = std::unordered_map{ {"coulomb", {1.0, DIM_CHARGE}}, {"c", {1.0, DIM_CHARGE}}, + // --- Pressure --- + {"pa", {1.0, DIM_PRESSURE}}, + {"pascal", {1.0, DIM_PRESSURE}}, + {"kpa", {1e3, DIM_PRESSURE}}, + {"kilopascal", {1e3, DIM_PRESSURE}}, + {"mpa", {1e6, DIM_PRESSURE}}, + {"megapascal", {1e6, DIM_PRESSURE}}, + {"gpa", {1e9, DIM_PRESSURE}}, + {"gigapascal", {1e9, DIM_PRESSURE}}, + {"bar", {100000.0, DIM_PRESSURE}}, + {"atm", {101325.0, DIM_PRESSURE}}, + + // --- Electric dipole moment --- + {"debye", {1/299792458.0 * 1e-21, DIM_ELECTRIC_DIPOLE}}, + {"d", {1/299792458.0 * 1e-21, DIM_ELECTRIC_DIPOLE}}, + // --- Dimensionless --- {"mol", {6.02214076e23, DIM_NONE}},