diff --git a/CLAUDE.md b/CLAUDE.md
index de37b4a..b7d4468 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -52,6 +52,7 @@ These are now baked into the generator and enforced by tests. **Do not reopen wi
2. **Dimensionless and angular quantities have both `Ratio` (V0) and `SignedRatio` (V1) bases.** Ratios that semantically must be non-negative (e.g. `RefractiveIndex`, `MachNumber`, `SpecificGravity`) are V0 overloads of `Ratio`.
3. **Semantic overloads widen implicitly to their base, narrow explicitly from it.** A `Weight` is implicitly a `ForceMagnitude`; the reverse requires `Weight.From(forceMagnitude)` or an explicit cast.
4. **Physical constraints are enforced structurally via the V0 (magnitude) form.** `Vector0` factories run `Vector0Guards.EnsureNonNegative` and throw `ArgumentException` on a negative value. That covers absolute zero (Temperature is V0, so Kelvin must be ≥ 0), non-negative frequency, non-negative absolute pressure, etc. A V0 *overload* can opt into a stricter rule by declaring `physicalConstraints: { "minExclusive": "0" }` in `dimensions.json` (#51); the generator then emits `Vector0Guards.EnsurePositive` and rejects zero too. Used today for `Wavelength`, `Period`, and `HalfLife` — quantities for which zero is unphysical.
+5. **Logarithmic-scale quantities are hand-written companions, not generated dimensions.** Decibel scales (`SoundPressureLevel`, `SoundIntensityLevel`, `SoundPowerLevel`, `DirectionalityIndex`, the audio-engineering `Decibels`) and `PH` don't obey linear arithmetic, so they live as self-contained `readonly record struct`s that convert to and from their linear generated counterparts (`SoundPressure`, `SoundIntensity`, `SoundPower`, `Ratio`, `Concentration`). Adding a new log-scale quantity means writing such a companion, not a `dimensions.json` entry.
### Physical constants
diff --git a/Semantics.Quantities/Acoustics/DirectionalityIndex.cs b/Semantics.Quantities/Acoustics/DirectionalityIndex.cs
new file mode 100644
index 0000000..064ed2a
--- /dev/null
+++ b/Semantics.Quantities/Acoustics/DirectionalityIndex.cs
@@ -0,0 +1,85 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Globalization;
+using System.Numerics;
+
+///
+/// Represents a directivity index (DI) in decibels — how much more intense a
+/// source or receiver is on-axis than its spherical average.
+///
+///
+/// DI = 10·log10(I_axis / I_average). Like all decibel scales it is a
+/// hand-written companion rather than a generated linear quantity.
+///
+/// The floating-point storage type.
+/// The index in decibels.
+public readonly record struct DirectionalityIndex(T Value) : IComparable>
+ where T : struct, INumber
+{
+ /// Gets the index of an omnidirectional source (0 dB).
+ public static DirectionalityIndex Omnidirectional => new(T.Zero);
+
+ ///
+ /// Creates an index from a raw decibel value.
+ ///
+ /// The index in decibels.
+ /// A new .
+ public static DirectionalityIndex FromDecibels(T decibels) => new(decibels);
+
+ ///
+ /// Creates an index from the linear on-axis-to-average intensity ratio using DI = 10·log10(ratio).
+ ///
+ /// The intensity ratio.
+ /// A new .
+ public static DirectionalityIndex FromIntensityRatio(Ratio ratio)
+ {
+ ArgumentNullException.ThrowIfNull(ratio);
+ double linear = double.CreateChecked(ratio.Value);
+ return new(T.CreateChecked(10.0 * Math.Log10(linear)));
+ }
+
+ ///
+ /// Converts this index to the linear intensity ratio using ratio = 10^(DI/10).
+ ///
+ /// The on-axis-to-average intensity .
+ public Ratio ToIntensityRatio()
+ {
+ double db = double.CreateChecked(Value);
+ return Ratio.Create(T.CreateChecked(Math.Pow(10.0, db / 10.0)));
+ }
+
+ ///
+ public int CompareTo(DirectionalityIndex other) => Value.CompareTo(other.Value);
+
+ /// Determines whether one index is less than another.
+ /// The left index.
+ /// The right index.
+ /// if is less than .
+ public static bool operator <(DirectionalityIndex left, DirectionalityIndex right) => left.CompareTo(right) < 0;
+
+ /// Determines whether one index is greater than another.
+ /// The left index.
+ /// The right index.
+ /// if is greater than .
+ public static bool operator >(DirectionalityIndex left, DirectionalityIndex right) => left.CompareTo(right) > 0;
+
+ /// Determines whether one index is less than or equal to another.
+ /// The left index.
+ /// The right index.
+ /// if is less than or equal to .
+ public static bool operator <=(DirectionalityIndex left, DirectionalityIndex right) => left.CompareTo(right) <= 0;
+
+ /// Determines whether one index is greater than or equal to another.
+ /// The left index.
+ /// The right index.
+ /// if is greater than or equal to .
+ public static bool operator >=(DirectionalityIndex left, DirectionalityIndex right) => left.CompareTo(right) >= 0;
+
+ /// Returns a culture-invariant string representation of this index.
+ /// The index formatted with a dB suffix.
+ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Value} dB");
+}
diff --git a/Semantics.Quantities/Acoustics/SoundIntensityLevel.cs b/Semantics.Quantities/Acoustics/SoundIntensityLevel.cs
new file mode 100644
index 0000000..ef56c2d
--- /dev/null
+++ b/Semantics.Quantities/Acoustics/SoundIntensityLevel.cs
@@ -0,0 +1,109 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Globalization;
+using System.Numerics;
+
+///
+/// Represents a sound intensity level (SIL) in decibels relative to the
+/// 10⁻¹² W/m² threshold of hearing.
+///
+///
+/// SIL is a logarithmic power quantity: SIL = 10·log10(I / I₀) with
+/// I₀ = 10⁻¹² W/m². Logarithmic scales are hand-written companions to the
+/// linear generated quantities — see .
+///
+/// The floating-point storage type.
+/// The level in decibels.
+public readonly record struct SoundIntensityLevel(T Value) : IComparable>
+ where T : struct, INumber
+{
+ ///
+ /// Creates a level from a raw decibel value.
+ ///
+ /// The level in dB re 10⁻¹² W/m².
+ /// A new .
+ public static SoundIntensityLevel FromDecibels(T decibels) => new(decibels);
+
+ ///
+ /// Creates a level from a linear sound intensity using SIL = 10·log10(I / I₀).
+ ///
+ /// The sound intensity.
+ /// A new . Zero intensity maps to negative infinity.
+ public static SoundIntensityLevel FromSoundIntensity(SoundIntensity intensity)
+ {
+ ArgumentNullException.ThrowIfNull(intensity);
+ double i = double.CreateChecked(intensity.Value);
+ double i0 = PhysicalConstants.Generic.ReferenceSoundIntensity();
+ return new(T.CreateChecked(10.0 * Math.Log10(i / i0)));
+ }
+
+ ///
+ /// Converts this level to the equivalent linear sound intensity using I = I₀·10^(SIL/10).
+ ///
+ /// The .
+ public SoundIntensity ToSoundIntensity()
+ {
+ double db = double.CreateChecked(Value);
+ double i0 = PhysicalConstants.Generic.ReferenceSoundIntensity();
+ return SoundIntensity.Create(T.CreateChecked(i0 * Math.Pow(10.0, db / 10.0)));
+ }
+
+ /// Adds two levels in decibel space.
+ /// The first level.
+ /// The second level.
+ /// The summed level.
+ public static SoundIntensityLevel operator +(SoundIntensityLevel left, SoundIntensityLevel right) => new(left.Value + right.Value);
+
+ /// Subtracts one level from another in decibel space.
+ /// The level to subtract from.
+ /// The level to subtract.
+ /// The difference level.
+ public static SoundIntensityLevel operator -(SoundIntensityLevel left, SoundIntensityLevel right) => new(left.Value - right.Value);
+
+ /// Adds two levels (friendly alternate for operator +).
+ /// The first level.
+ /// The second level.
+ /// The summed level.
+ public static SoundIntensityLevel Add(SoundIntensityLevel left, SoundIntensityLevel right) => left + right;
+
+ /// Subtracts one level from another (friendly alternate for operator -).
+ /// The level to subtract from.
+ /// The level to subtract.
+ /// The difference level.
+ public static SoundIntensityLevel Subtract(SoundIntensityLevel left, SoundIntensityLevel right) => left - right;
+
+ ///
+ public int CompareTo(SoundIntensityLevel other) => Value.CompareTo(other.Value);
+
+ /// Determines whether one level is less than another.
+ /// The left level.
+ /// The right level.
+ /// if is less than .
+ public static bool operator <(SoundIntensityLevel left, SoundIntensityLevel right) => left.CompareTo(right) < 0;
+
+ /// Determines whether one level is greater than another.
+ /// The left level.
+ /// The right level.
+ /// if is greater than .
+ public static bool operator >(SoundIntensityLevel left, SoundIntensityLevel right) => left.CompareTo(right) > 0;
+
+ /// Determines whether one level is less than or equal to another.
+ /// The left level.
+ /// The right level.
+ /// if is less than or equal to .
+ public static bool operator <=(SoundIntensityLevel left, SoundIntensityLevel right) => left.CompareTo(right) <= 0;
+
+ /// Determines whether one level is greater than or equal to another.
+ /// The left level.
+ /// The right level.
+ /// if is greater than or equal to .
+ public static bool operator >=(SoundIntensityLevel left, SoundIntensityLevel right) => left.CompareTo(right) >= 0;
+
+ /// Returns a culture-invariant string representation of this level.
+ /// The level formatted with a dB SIL suffix.
+ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Value} dB SIL");
+}
diff --git a/Semantics.Quantities/Acoustics/SoundPowerLevel.cs b/Semantics.Quantities/Acoustics/SoundPowerLevel.cs
new file mode 100644
index 0000000..e91b81b
--- /dev/null
+++ b/Semantics.Quantities/Acoustics/SoundPowerLevel.cs
@@ -0,0 +1,109 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Globalization;
+using System.Numerics;
+
+///
+/// Represents a sound power level (SWL) in decibels relative to the 10⁻¹² W
+/// reference sound power.
+///
+///
+/// SWL is a logarithmic power quantity: SWL = 10·log10(P / P₀) with
+/// P₀ = 10⁻¹² W. Logarithmic scales are hand-written companions to the
+/// linear generated quantities — see .
+///
+/// The floating-point storage type.
+/// The level in decibels.
+public readonly record struct SoundPowerLevel(T Value) : IComparable>
+ where T : struct, INumber
+{
+ ///
+ /// Creates a level from a raw decibel value.
+ ///
+ /// The level in dB re 10⁻¹² W.
+ /// A new .
+ public static SoundPowerLevel FromDecibels(T decibels) => new(decibels);
+
+ ///
+ /// Creates a level from a linear sound power using SWL = 10·log10(P / P₀).
+ ///
+ /// The sound power.
+ /// A new . Zero power maps to negative infinity.
+ public static SoundPowerLevel FromSoundPower(SoundPower power)
+ {
+ ArgumentNullException.ThrowIfNull(power);
+ double p = double.CreateChecked(power.Value);
+ double p0 = PhysicalConstants.Generic.ReferenceSoundPower();
+ return new(T.CreateChecked(10.0 * Math.Log10(p / p0)));
+ }
+
+ ///
+ /// Converts this level to the equivalent linear sound power using P = P₀·10^(SWL/10).
+ ///
+ /// The .
+ public SoundPower ToSoundPower()
+ {
+ double db = double.CreateChecked(Value);
+ double p0 = PhysicalConstants.Generic.ReferenceSoundPower();
+ return SoundPower.Create(T.CreateChecked(p0 * Math.Pow(10.0, db / 10.0)));
+ }
+
+ /// Adds two levels in decibel space.
+ /// The first level.
+ /// The second level.
+ /// The summed level.
+ public static SoundPowerLevel operator +(SoundPowerLevel left, SoundPowerLevel right) => new(left.Value + right.Value);
+
+ /// Subtracts one level from another in decibel space.
+ /// The level to subtract from.
+ /// The level to subtract.
+ /// The difference level.
+ public static SoundPowerLevel operator -(SoundPowerLevel left, SoundPowerLevel right) => new(left.Value - right.Value);
+
+ /// Adds two levels (friendly alternate for operator +).
+ /// The first level.
+ /// The second level.
+ /// The summed level.
+ public static SoundPowerLevel Add(SoundPowerLevel left, SoundPowerLevel right) => left + right;
+
+ /// Subtracts one level from another (friendly alternate for operator -).
+ /// The level to subtract from.
+ /// The level to subtract.
+ /// The difference level.
+ public static SoundPowerLevel Subtract(SoundPowerLevel left, SoundPowerLevel right) => left - right;
+
+ ///
+ public int CompareTo(SoundPowerLevel other) => Value.CompareTo(other.Value);
+
+ /// Determines whether one level is less than another.
+ /// The left level.
+ /// The right level.
+ /// if is less than .
+ public static bool operator <(SoundPowerLevel left, SoundPowerLevel right) => left.CompareTo(right) < 0;
+
+ /// Determines whether one level is greater than another.
+ /// The left level.
+ /// The right level.
+ /// if is greater than .
+ public static bool operator >(SoundPowerLevel left, SoundPowerLevel right) => left.CompareTo(right) > 0;
+
+ /// Determines whether one level is less than or equal to another.
+ /// The left level.
+ /// The right level.
+ /// if is less than or equal to .
+ public static bool operator <=(SoundPowerLevel left, SoundPowerLevel right) => left.CompareTo(right) <= 0;
+
+ /// Determines whether one level is greater than or equal to another.
+ /// The left level.
+ /// The right level.
+ /// if is greater than or equal to .
+ public static bool operator >=(SoundPowerLevel left, SoundPowerLevel right) => left.CompareTo(right) >= 0;
+
+ /// Returns a culture-invariant string representation of this level.
+ /// The level formatted with a dB SWL suffix.
+ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Value} dB SWL");
+}
diff --git a/Semantics.Quantities/Acoustics/SoundPressureLevel.cs b/Semantics.Quantities/Acoustics/SoundPressureLevel.cs
new file mode 100644
index 0000000..ab218cb
--- /dev/null
+++ b/Semantics.Quantities/Acoustics/SoundPressureLevel.cs
@@ -0,0 +1,111 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Globalization;
+using System.Numerics;
+
+///
+/// Represents a sound pressure level (SPL) in decibels relative to the 20 µPa
+/// threshold of hearing.
+///
+///
+/// SPL is a logarithmic field quantity: SPL = 20·log10(p / p₀) with
+/// p₀ = 20 µPa. Logarithmic scales don't fit the linear
+/// model (their addition is not linear
+/// addition), so SPL is a hand-written companion that converts to and from the
+/// linear quantity.
+///
+/// The floating-point storage type.
+/// The level in decibels.
+public readonly record struct SoundPressureLevel(T Value) : IComparable>
+ where T : struct, INumber
+{
+ ///
+ /// Creates a level from a raw decibel value.
+ ///
+ /// The level in dB re 20 µPa.
+ /// A new .
+ public static SoundPressureLevel FromDecibels(T decibels) => new(decibels);
+
+ ///
+ /// Creates a level from a linear sound pressure using SPL = 20·log10(p / p₀).
+ ///
+ /// The RMS sound pressure.
+ /// A new . Zero pressure maps to negative infinity.
+ public static SoundPressureLevel FromSoundPressure(SoundPressure pressure)
+ {
+ ArgumentNullException.ThrowIfNull(pressure);
+ double p = double.CreateChecked(pressure.Value);
+ double p0 = PhysicalConstants.Generic.ReferenceSoundPressure();
+ return new(T.CreateChecked(20.0 * Math.Log10(p / p0)));
+ }
+
+ ///
+ /// Converts this level to the equivalent linear sound pressure using p = p₀·10^(SPL/20).
+ ///
+ /// The RMS .
+ public SoundPressure ToSoundPressure()
+ {
+ double db = double.CreateChecked(Value);
+ double p0 = PhysicalConstants.Generic.ReferenceSoundPressure();
+ return SoundPressure.Create(T.CreateChecked(p0 * Math.Pow(10.0, db / 20.0)));
+ }
+
+ /// Adds two levels in decibel space (cascading gains).
+ /// The first level.
+ /// The second level.
+ /// The summed level.
+ public static SoundPressureLevel operator +(SoundPressureLevel left, SoundPressureLevel right) => new(left.Value + right.Value);
+
+ /// Subtracts one level from another in decibel space.
+ /// The level to subtract from.
+ /// The level to subtract.
+ /// The difference level.
+ public static SoundPressureLevel operator -(SoundPressureLevel left, SoundPressureLevel right) => new(left.Value - right.Value);
+
+ /// Adds two levels (friendly alternate for operator +).
+ /// The first level.
+ /// The second level.
+ /// The summed level.
+ public static SoundPressureLevel Add(SoundPressureLevel left, SoundPressureLevel right) => left + right;
+
+ /// Subtracts one level from another (friendly alternate for operator -).
+ /// The level to subtract from.
+ /// The level to subtract.
+ /// The difference level.
+ public static SoundPressureLevel Subtract(SoundPressureLevel left, SoundPressureLevel right) => left - right;
+
+ ///
+ public int CompareTo(SoundPressureLevel other) => Value.CompareTo(other.Value);
+
+ /// Determines whether one level is less than another.
+ /// The left level.
+ /// The right level.
+ /// if is less than .
+ public static bool operator <(SoundPressureLevel left, SoundPressureLevel right) => left.CompareTo(right) < 0;
+
+ /// Determines whether one level is greater than another.
+ /// The left level.
+ /// The right level.
+ /// if is greater than .
+ public static bool operator >(SoundPressureLevel left, SoundPressureLevel right) => left.CompareTo(right) > 0;
+
+ /// Determines whether one level is less than or equal to another.
+ /// The left level.
+ /// The right level.
+ /// if is less than or equal to .
+ public static bool operator <=(SoundPressureLevel left, SoundPressureLevel right) => left.CompareTo(right) <= 0;
+
+ /// Determines whether one level is greater than or equal to another.
+ /// The left level.
+ /// The right level.
+ /// if is greater than or equal to .
+ public static bool operator >=(SoundPressureLevel left, SoundPressureLevel right) => left.CompareTo(right) >= 0;
+
+ /// Returns a culture-invariant string representation of this level.
+ /// The level formatted with a dB SPL suffix.
+ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Value} dB SPL");
+}
diff --git a/Semantics.Quantities/Chemistry/PH.cs b/Semantics.Quantities/Chemistry/PH.cs
new file mode 100644
index 0000000..3f62694
--- /dev/null
+++ b/Semantics.Quantities/Chemistry/PH.cs
@@ -0,0 +1,101 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Globalization;
+using System.Numerics;
+
+///
+/// Represents acidity on the pH scale: pH = −log10([H⁺]) with the
+/// hydrogen-ion activity in mol/L.
+///
+///
+/// pH is a logarithmic scale, so — like the decibel quantities — it is a
+/// hand-written companion that converts to and from the linear
+/// quantity (stored in the SI base mol/m³).
+///
+/// The floating-point storage type.
+/// The pH value.
+public readonly record struct PH(T Value) : IComparable>
+ where T : struct, INumber
+{
+ private const double MolesPerCubicMeterPerMolar = 1000.0;
+
+ /// Gets the pH of pure water at 25 °C (7.0).
+ public static PH Neutral => new(PhysicalConstants.Generic.NeutralPH());
+
+ ///
+ /// Creates a pH from a raw scale value.
+ ///
+ /// The pH value.
+ /// A new .
+ public static PH Create(T value) => new(value);
+
+ ///
+ /// Creates a pH from a hydrogen-ion concentration using pH = −log10([H⁺] in mol/L).
+ ///
+ /// The hydrogen-ion concentration.
+ /// A new .
+ public static PH FromHydrogenConcentration(Concentration hydrogenConcentration)
+ {
+ ArgumentNullException.ThrowIfNull(hydrogenConcentration);
+ double molesPerLiter = double.CreateChecked(hydrogenConcentration.Value) / MolesPerCubicMeterPerMolar;
+ return new(T.CreateChecked(-Math.Log10(molesPerLiter)));
+ }
+
+ ///
+ /// Converts this pH to the equivalent hydrogen-ion concentration using [H⁺] = 10^(−pH) mol/L.
+ ///
+ /// The hydrogen-ion .
+ public Concentration ToHydrogenConcentration()
+ {
+ double ph = double.CreateChecked(Value);
+ double molesPerCubicMeter = Math.Pow(10.0, -ph) * MolesPerCubicMeterPerMolar;
+ return Concentration.Create(T.CreateChecked(molesPerCubicMeter));
+ }
+
+ ///
+ /// Gets the complementary pOH at 25 °C using pOH = 14 − pH.
+ ///
+ /// The pOH as a scale value.
+ public PH ToPOH() => new(T.CreateChecked(14) - Value);
+
+ /// Gets whether this value describes an acid (pH below 7).
+ public bool IsAcidic => Value < PhysicalConstants.Generic.NeutralPH();
+
+ /// Gets whether this value describes a base (pH above 7).
+ public bool IsBasic => Value > PhysicalConstants.Generic.NeutralPH();
+
+ ///
+ public int CompareTo(PH other) => Value.CompareTo(other.Value);
+
+ /// Determines whether one pH is less than another.
+ /// The left pH.
+ /// The right pH.
+ /// if is less than .
+ public static bool operator <(PH left, PH right) => left.CompareTo(right) < 0;
+
+ /// Determines whether one pH is greater than another.
+ /// The left pH.
+ /// The right pH.
+ /// if is greater than .
+ public static bool operator >(PH left, PH right) => left.CompareTo(right) > 0;
+
+ /// Determines whether one pH is less than or equal to another.
+ /// The left pH.
+ /// The right pH.
+ /// if is less than or equal to .
+ public static bool operator <=(PH left, PH right) => left.CompareTo(right) <= 0;
+
+ /// Determines whether one pH is greater than or equal to another.
+ /// The left pH.
+ /// The right pH.
+ /// if is greater than or equal to .
+ public static bool operator >=(PH left, PH right) => left.CompareTo(right) >= 0;
+
+ /// Returns a culture-invariant string representation of this pH.
+ /// The value formatted with a pH prefix.
+ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"pH {Value}");
+}
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs
index accf11b..c2cb704 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.ConversionsGenerator/ConversionConstants.g.cs
@@ -259,6 +259,9 @@ internal static class ConversionConstants{
/// Foot-candle to lux conversion: 1/0.09290304 ≈ 10.7639 lx/fc (exact)
internal const double FootCandleToLux = 10.763910416709722;
+ /// Foot-lambert to candela per square meter: 1/(π·0.09290304) ≈ 3.4263 cd/m² per fL (exact)
+ internal const double FootLambertToCandelaPerSquareMeter = 3.4262590996353905;
+
/// Parts per million to ratio: 1e-6 (exact by definition)
internal const double PartsPerMillionToRatio = 1e-6;
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs
index daf532f..8208494 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.DimensionsGenerator/PhysicalDimensions.g.cs
@@ -56,7 +56,7 @@ public static class PhysicalDimensions{
public static readonly DimensionInfo Density = new("Density", "M L⁻³", new Dictionary { ["mass"] = 1, ["length"] = -3 }, new List { "Density" });
/// Physical dimension: Dimensionless
- public static readonly DimensionInfo Dimensionless = new("Dimensionless", "1", new Dictionary(), new List { "Ratio", "RefractiveIndex", "ReynoldsNumber", "SpecificGravity", "MachNumber", "SignedRatio" });
+ public static readonly DimensionInfo Dimensionless = new("Dimensionless", "1", new Dictionary(), new List { "Ratio", "RefractiveIndex", "ReynoldsNumber", "SpecificGravity", "MachNumber", "SoundAbsorption", "NoiseReductionCoefficient", "SoundTransmissionClass", "SignedRatio", "ReflectionCoefficient" });
/// Physical dimension: DynamicViscosity
public static readonly DimensionInfo DynamicViscosity = new("DynamicViscosity", "M L⁻¹ T⁻¹", new Dictionary { ["mass"] = 1, ["length"] = -1, ["time"] = -1 }, new List { "DynamicViscosity" });
@@ -70,17 +70,26 @@ public static class PhysicalDimensions{
/// Physical dimension: ElectricConductance
public static readonly DimensionInfo ElectricConductance = new("ElectricConductance", "M⁻¹ L⁻² T³ I²", new Dictionary { ["mass"] = -1, ["length"] = -2, ["time"] = 3, ["electricCurrent"] = 2 }, new List { "Conductance", "Admittance" });
+ /// Physical dimension: ElectricConductivity
+ public static readonly DimensionInfo ElectricConductivity = new("ElectricConductivity", "M⁻¹ L⁻³ T³ I²", new Dictionary { ["mass"] = -1, ["length"] = -3, ["time"] = 3, ["electricCurrent"] = 2 }, new List { "ElectricConductivity" });
+
/// Physical dimension: ElectricCurrent
public static readonly DimensionInfo ElectricCurrent = new("ElectricCurrent", "I", new Dictionary { ["electricCurrent"] = 1 }, new List { "CurrentMagnitude", "Current1D", "Current3D" });
/// Physical dimension: ElectricField
public static readonly DimensionInfo ElectricField = new("ElectricField", "M L T⁻³ I⁻¹", new Dictionary { ["mass"] = 1, ["length"] = 1, ["time"] = -3, ["electricCurrent"] = -1 }, new List { "ElectricFieldMagnitude", "ElectricField1D", "ElectricField2D", "ElectricField3D" });
+ /// Physical dimension: ElectricFlux
+ public static readonly DimensionInfo ElectricFlux = new("ElectricFlux", "M L³ T⁻³ I⁻¹", new Dictionary { ["mass"] = 1, ["length"] = 3, ["time"] = -3, ["electricCurrent"] = -1 }, new List { "ElectricFlux" });
+
/// Physical dimension: ElectricPotential
public static readonly DimensionInfo ElectricPotential = new("ElectricPotential", "M L² T⁻³ I⁻¹", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -3, ["electricCurrent"] = -1 }, new List { "VoltageMagnitude", "EMF", "VoltageDrop", "Voltage" });
+ /// Physical dimension: ElectricPowerDensity
+ public static readonly DimensionInfo ElectricPowerDensity = new("ElectricPowerDensity", "M L⁻¹ T⁻³", new Dictionary { ["mass"] = 1, ["length"] = -1, ["time"] = -3 }, new List { "ElectricPowerDensity" });
+
/// Physical dimension: ElectricResistance
- public static readonly DimensionInfo ElectricResistance = new("ElectricResistance", "M L² T⁻³ I⁻²", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -3, ["electricCurrent"] = -2 }, new List { "Resistance" });
+ public static readonly DimensionInfo ElectricResistance = new("ElectricResistance", "M L² T⁻³ I⁻²", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -3, ["electricCurrent"] = -2 }, new List { "Resistance", "Impedance" });
/// Physical dimension: Energy
public static readonly DimensionInfo Energy = new("Energy", "M L² T⁻²", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -2 }, new List { "Energy", "Work", "Heat", "KineticEnergy", "PotentialEnergy", "ThermalEnergy" });
@@ -104,7 +113,7 @@ public static class PhysicalDimensions{
public static readonly DimensionInfo HeatTransferCoefficient = new("HeatTransferCoefficient", "M T⁻³ Θ⁻¹", new Dictionary { ["mass"] = 1, ["time"] = -3, ["temperature"] = -1 }, new List { "HeatTransferCoefficient" });
/// Physical dimension: Illuminance
- public static readonly DimensionInfo Illuminance = new("Illuminance", "J L⁻²", new Dictionary { ["luminousIntensity"] = 1, ["length"] = -2 }, new List { "Illuminance", "Luminance" });
+ public static readonly DimensionInfo Illuminance = new("Illuminance", "J L⁻²", new Dictionary { ["luminousIntensity"] = 1, ["length"] = -2 }, new List { "Illuminance" });
/// Physical dimension: Inductance
public static readonly DimensionInfo Inductance = new("Inductance", "M L² T⁻² I⁻²", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -2, ["electricCurrent"] = -2 }, new List { "Inductance" });
@@ -121,6 +130,12 @@ public static class PhysicalDimensions{
/// Physical dimension: Length
public static readonly DimensionInfo Length = new("Length", "L", new Dictionary { ["length"] = 1 }, new List { "Length", "Width", "Height", "Depth", "Radius", "Diameter", "Distance", "Altitude", "Wavelength", "Thickness", "Perimeter", "Displacement1D", "Offset", "Displacement2D", "Displacement3D", "Position3D", "Translation3D", "Displacement4D" });
+ /// Physical dimension: Loudness
+ public static readonly DimensionInfo Loudness = new("Loudness", "1", new Dictionary(), new List { "Loudness" });
+
+ /// Physical dimension: Luminance
+ public static readonly DimensionInfo Luminance = new("Luminance", "J L⁻²", new Dictionary { ["luminousIntensity"] = 1, ["length"] = -2 }, new List { "Luminance" });
+
/// Physical dimension: LuminousFlux
public static readonly DimensionInfo LuminousFlux = new("LuminousFlux", "J", new Dictionary { ["luminousIntensity"] = 1 }, new List { "LuminousFlux" });
@@ -157,18 +172,30 @@ public static class PhysicalDimensions{
/// Physical dimension: OpticalPower
public static readonly DimensionInfo OpticalPower = new("OpticalPower", "L⁻¹", new Dictionary { ["length"] = -1 }, new List { "OpticalPower" });
+ /// Physical dimension: Permittivity
+ public static readonly DimensionInfo Permittivity = new("Permittivity", "M⁻¹ L⁻³ T⁴ I²", new Dictionary { ["mass"] = -1, ["length"] = -3, ["time"] = 4, ["electricCurrent"] = 2 }, new List { "Permittivity" });
+
/// Physical dimension: Power
- public static readonly DimensionInfo Power = new("Power", "M L² T⁻³", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -3 }, new List { "Power", "HeatFlowRate" });
+ public static readonly DimensionInfo Power = new("Power", "M L² T⁻³", new Dictionary { ["mass"] = 1, ["length"] = 2, ["time"] = -3 }, new List { "Power", "HeatFlowRate", "SoundPower" });
/// Physical dimension: Pressure
- public static readonly DimensionInfo Pressure = new("Pressure", "M L⁻¹ T⁻²", new Dictionary { ["mass"] = 1, ["length"] = -1, ["time"] = -2 }, new List { "Pressure", "Stress", "AtmosphericPressure", "GaugePressure", "BulkModulus", "YoungsModulus", "ShearModulus" });
+ public static readonly DimensionInfo Pressure = new("Pressure", "M L⁻¹ T⁻²", new Dictionary { ["mass"] = 1, ["length"] = -1, ["time"] = -2 }, new List { "Pressure", "Stress", "AtmosphericPressure", "GaugePressure", "BulkModulus", "YoungsModulus", "ShearModulus", "SoundPressure" });
/// Physical dimension: RadioactiveActivity
public static readonly DimensionInfo RadioactiveActivity = new("RadioactiveActivity", "T⁻¹", new Dictionary { ["time"] = -1 }, new List { "RadioactiveActivity" });
+ /// Physical dimension: RateConstant
+ public static readonly DimensionInfo RateConstant = new("RateConstant", "T⁻¹", new Dictionary { ["time"] = -1 }, new List { "RateConstant" });
+
/// Physical dimension: ReactionRate
public static readonly DimensionInfo ReactionRate = new("ReactionRate", "N L⁻³ T⁻¹", new Dictionary { ["amountOfSubstance"] = 1, ["length"] = -3, ["time"] = -1 }, new List { "ReactionRate" });
+ /// Physical dimension: Sensitivity
+ public static readonly DimensionInfo Sensitivity = new("Sensitivity", "M⁻¹ L⁻¹ T² I", new Dictionary { ["mass"] = -1, ["length"] = -1, ["time"] = 2, ["electricCurrent"] = 1 }, new List { "Sensitivity" });
+
+ /// Physical dimension: Sharpness
+ public static readonly DimensionInfo Sharpness = new("Sharpness", "1", new Dictionary(), new List { "Sharpness" });
+
/// Physical dimension: Snap
public static readonly DimensionInfo Snap = new("Snap", "L T⁻⁴", new Dictionary { ["length"] = 1, ["time"] = -4 }, new List { "SnapMagnitude", "Snap1D", "Snap2D", "Snap3D", "Snap4D" });
@@ -187,6 +214,9 @@ public static class PhysicalDimensions{
/// Physical dimension: ThermalExpansion
public static readonly DimensionInfo ThermalExpansion = new("ThermalExpansion", "Θ⁻¹", new Dictionary { ["temperature"] = -1 }, new List { "ThermalExpansionCoefficient" });
+ /// Physical dimension: ThermalResistance
+ public static readonly DimensionInfo ThermalResistance = new("ThermalResistance", "Θ M⁻¹ L⁻² T³", new Dictionary { ["temperature"] = 1, ["mass"] = -1, ["length"] = -2, ["time"] = 3 }, new List { "ThermalResistance" });
+
/// Physical dimension: Time
public static readonly DimensionInfo Time = new("Time", "T", new Dictionary { ["time"] = 1 }, new List { "Duration", "Period", "HalfLife", "TimeConstant", "Latency", "ReverberationTime", "DecayTime" });
@@ -203,7 +233,7 @@ public static class PhysicalDimensions{
public static readonly DimensionInfo VolumetricFlowRate = new("VolumetricFlowRate", "L³ T⁻¹", new Dictionary { ["length"] = 3, ["time"] = -1 }, new List { "VolumetricFlowRate" });
/// Gets a frozen collection of all standard physical dimensions.
- public static IReadOnlySet All = new HashSet([ AbsorbedDose, Acceleration, AcousticImpedance, AmountOfSubstance, AngularAcceleration, AngularDisplacement, AngularJerk, AngularMomentum, AngularVelocity, Area, CatalyticActivity, Concentration, Density, Dimensionless, DynamicViscosity, ElectricCapacitance, ElectricCharge, ElectricConductance, ElectricCurrent, ElectricField, ElectricPotential, ElectricResistance, Energy, Entropy, EquivalentDose, Exposure, Force, Frequency, HeatTransferCoefficient, Illuminance, Inductance, Irradiance, Jerk, KinematicViscosity, Length, LuminousFlux, LuminousIntensity, MagneticFlux, MagneticFluxDensity, Mass, MassFlowRate, MolarEnergy, MolarMass, MomentOfInertia, Momentum, NuclearCrossSection, OpticalPower, Power, Pressure, RadioactiveActivity, ReactionRate, Snap, SpecificHeat, SurfaceTension, Temperature, ThermalConductivity, ThermalExpansion, Time, Torque, Velocity, Volume, VolumetricFlowRate ]);
+ public static IReadOnlySet All = new HashSet([ AbsorbedDose, Acceleration, AcousticImpedance, AmountOfSubstance, AngularAcceleration, AngularDisplacement, AngularJerk, AngularMomentum, AngularVelocity, Area, CatalyticActivity, Concentration, Density, Dimensionless, DynamicViscosity, ElectricCapacitance, ElectricCharge, ElectricConductance, ElectricConductivity, ElectricCurrent, ElectricField, ElectricFlux, ElectricPotential, ElectricPowerDensity, ElectricResistance, Energy, Entropy, EquivalentDose, Exposure, Force, Frequency, HeatTransferCoefficient, Illuminance, Inductance, Irradiance, Jerk, KinematicViscosity, Length, Loudness, Luminance, LuminousFlux, LuminousIntensity, MagneticFlux, MagneticFluxDensity, Mass, MassFlowRate, MolarEnergy, MolarMass, MomentOfInertia, Momentum, NuclearCrossSection, OpticalPower, Permittivity, Power, Pressure, RadioactiveActivity, RateConstant, ReactionRate, Sensitivity, Sharpness, Snap, SpecificHeat, SurfaceTension, Temperature, ThermalConductivity, ThermalExpansion, ThermalResistance, Time, Torque, Velocity, Volume, VolumetricFlowRate ]);
};
@@ -333,6 +363,13 @@ public interface IElectricChargeUnit : IUnit
public interface IElectricConductanceUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the ElectricConductivity dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IElectricConductivityUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the ElectricCurrent dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -347,6 +384,13 @@ public interface IElectricCurrentUnit : IUnit
public interface IElectricFieldUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the ElectricFlux dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IElectricFluxUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the ElectricPotential dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -354,6 +398,13 @@ public interface IElectricFieldUnit : IUnit
public interface IElectricPotentialUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the ElectricPowerDensity dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IElectricPowerDensityUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the ElectricResistance dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -452,6 +503,20 @@ public interface IKinematicViscosityUnit : IUnit
public interface ILengthUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the Loudness dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface ILoudnessUnit : IUnit
+{ }
+
+///
+/// Marker interface implemented by every unit of the Luminance dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface ILuminanceUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the LuminousFlux dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -536,6 +601,13 @@ public interface INuclearCrossSectionUnit : IUnit
public interface IOpticalPowerUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the Permittivity dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IPermittivityUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the Power dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -557,6 +629,13 @@ public interface IPressureUnit : IUnit
public interface IRadioactiveActivityUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the RateConstant dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IRateConstantUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the ReactionRate dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -564,6 +643,20 @@ public interface IRadioactiveActivityUnit : IUnit
public interface IReactionRateUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the Sensitivity dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface ISensitivityUnit : IUnit
+{ }
+
+///
+/// Marker interface implemented by every unit of the Sharpness dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface ISharpnessUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the Snap dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
@@ -606,6 +699,13 @@ public interface IThermalConductivityUnit : IUnit
public interface IThermalExpansionUnit : IUnit
{ }
+///
+/// Marker interface implemented by every unit of the ThermalResistance dimension.
+/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
+///
+public interface IThermalResistanceUnit : IUnit
+{ }
+
///
/// Marker interface implemented by every unit of the Time dimension.
/// Generated quantities use this to make In(...) dimensionally type-safe at compile time.
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs
index 26ffd39..dc001a6 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Area.g.cs
@@ -100,6 +100,10 @@ public record Area : PhysicalQuantity, T>, IVector0, T>
/// Multiplies Area by Pressure to produce ForceMagnitude.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ForceMagnitude operator *(Area left, Pressure right) => Multiply>(left, right);
+///
+ /// Multiplies Area by ElectricFieldMagnitude to produce ElectricFlux.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ElectricFlux operator *(Area left, ElectricFieldMagnitude right) => Multiply>(left, right);
///
/// Multiplies Area by Illuminance to produce LuminousFlux.
///
@@ -112,5 +116,9 @@ public record Area : PhysicalQuantity, T>, IVector0, T>
/// Multiplies Area by Irradiance to produce Power.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Power operator *(Area left, Irradiance right) => Multiply>(left, right);
+///
+ /// Multiplies Area by Luminance to produce LuminousIntensity.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static LuminousIntensity operator *(Area left, Luminance right) => Multiply>(left, right);
};
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs
index 5f62773..ecddd5c 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/Concentration.g.cs
@@ -21,12 +21,19 @@ public record Concentration : PhysicalQuantity, T>, IVector0
public override DimensionInfo Dimension => PhysicalDimensions.Concentration;
///
+ /// Creates a new from a value in MolePerCubicMeter.
+ ///
+ /// The value in MolePerCubicMeter.
+ /// A new instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static Concentration FromMolePerCubicMeter(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+///
/// Creates a new from a value in Molar.
///
/// The value in Molar.
/// A new instance.
/// Thrown when the resulting magnitude would be negative.
- public static Concentration FromMolars(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+ public static Concentration FromMolars(T value) => Create(Vector0Guards.EnsureNonNegative((value * T.CreateChecked(Units.ConversionConstants.MolarToCubicMeter)), nameof(value)));
///
/// Creates a new from a value in Millimolar.
///
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricConductivity.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricConductivity.g.cs
new file mode 100644
index 0000000..b62c221
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricConductivity.g.cs
@@ -0,0 +1,43 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Magnitude (Vector0) quantity for the ElectricConductivity dimension.
+///
+/// The numeric storage type.
+public record ElectricConductivity : PhysicalQuantity, T>, IVector0, T>
+ where T : struct, INumber
+{
+ /// Gets a quantity with value zero.
+ public static ElectricConductivity Zero => Create(T.Zero);
+
+ /// Gets the physical dimension this quantity belongs to.
+ public override DimensionInfo Dimension => PhysicalDimensions.ElectricConductivity;
+
+ ///
+ /// Creates a new from a value in SiemensPerMeter.
+ ///
+ /// The value in SiemensPerMeter.
+ /// A new instance.
+ /// Thrown when the resulting magnitude would be negative.
+ public static ElectricConductivity FromSiemensPerMeter(T value) => Create(Vector0Guards.EnsureNonNegative(value, nameof(value)));
+///
+ /// Converts this quantity's SI-base value to the value in .
+ /// Cross-dimension calls (e.g. passing a non-ElectricConductivity unit) fail at compile time.
+ ///
+ /// The dimensionally-compatible target unit.
+ /// The value expressed in .
+ public T In(global::ktsu.Semantics.Quantities.IElectricConductivityUnit unit) => unit.FromBase(Value);
+///
+ /// Subtracts two ElectricConductivity values, returning the absolute difference as a non-negative ElectricConductivity.
+ /// Magnitude subtraction stays a magnitude (per the unified-vector model).
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ElectricConductivity operator -(ElectricConductivity left, ElectricConductivity right) => Create(T.Abs(left.Quantity - right.Quantity));
+};
+
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFieldMagnitude.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFieldMagnitude.g.cs
index 5f5dc4c..b343741 100644
--- a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFieldMagnitude.g.cs
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFieldMagnitude.g.cs
@@ -43,5 +43,9 @@ public record ElectricFieldMagnitude : PhysicalQuantity
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static VoltageMagnitude operator *(ElectricFieldMagnitude left, Length right) => Multiply>(left, right);
+///
+ /// Multiplies ElectricFieldMagnitude by Area to produce ElectricFlux.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static ElectricFlux operator *(ElectricFieldMagnitude left, Area right) => Multiply>(left, right);
};
diff --git a/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs
new file mode 100644
index 0000000..1292f8c
--- /dev/null
+++ b/Semantics.Quantities/Generated/Semantics.SourceGenerators/Semantics.SourceGenerators.QuantitiesGenerator/ElectricFlux.g.cs
@@ -0,0 +1,51 @@
+// Copyright (c) ktsu.dev
+// All rights reserved.
+// Licensed under the MIT license.
+//
+
+namespace ktsu.Semantics.Quantities;
+
+using System.Numerics;
+
+///
+/// Magnitude (Vector0) quantity for the ElectricFlux dimension.
+///
+/// The numeric storage type.
+public record ElectricFlux : PhysicalQuantity, T>, IVector0, T>
+ where T : struct, INumber