Skip to content

Commit

Permalink
Update the UnitRelations.json (#1453)
Browse files Browse the repository at this point in the history
As per my comments from #1200 here are the proposed modifications to the
operators:
- [x] adding an `Inverse` relation between `Density` and
`SpecificVolume` (replacing the existing multiplication)
- [x] adding standard multiplication for `MolarEnergy.JoulePerMole *
AmountOfSubstance.Mole` (returning `Energy.Joule`)
- [x] adding standard multiplication for `Illuminance.Lux *
Area.SquareMeter` (returning `LuminousFlux.Lumen`)
- [x] `TemperatureDelta.Kelvin *
CoefficientOfThermalExpansion.PerKelvin` now returns a `Ratio` (instead
of a `double`)
- [x] added the `-- NoInferredDivision` to the
`KinematicViscosity.SquareMeterPerSecond * Duration.Second` operator (as
the opposite of the relation was `Area / Duration` ->
`KinematicViscosity` 😏 )
- [x] added the `-- NoInferredDivision` to the `Area.SquareMeter *
ReciprocalArea.InverseSquareMeter` operator (as the opposite of the
relation was `Ratio / Area` -> `InverseArea` does not appear intuitive )
- [x] change the multiplication units (using the `BaseUnit`) for the
`Mass.Kilogram = AmountOfSubstance.Mole * MolarMass.KilogramPerMole`
- [x] change the multiplication units (using the `BaseUnit`) for the
`AmountOfSubstance.Mole = MolarFlow.MolePerSecond * Duration.Second`

I've included tests for **_all_** operators from the affected classes
(_most operators, introduced with the `UnitRelations.json` were never
covered by tests_).

PS There are still many operators not covered by tests, but I'd rather
finish them later (_hopefully once we no longer have to worry about
rounding errors_).

---------

Co-authored-by: Andreas Gullberg Larsen <[email protected]>
  • Loading branch information
lipchev and angularsen authored Dec 15, 2024
1 parent 17e3bfc commit ef739cd
Show file tree
Hide file tree
Showing 30 changed files with 436 additions and 129 deletions.
14 changes: 8 additions & 6 deletions Common/UnitRelations.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
[
"1 = Area.SquareMeter * ReciprocalArea.InverseSquareMeter",
"1 = Density.KilogramPerCubicMeter * SpecificVolume.CubicMeterPerKilogram",
"1 = ElectricResistivity.OhmMeter * ElectricConductivity.SiemensPerMeter",
"1 = Length.Meter * ReciprocalLength.InverseMeter",
"Acceleration.MeterPerSecondSquared = Jerk.MeterPerSecondCubed * Duration.Second",
"AmountOfSubstance.Kilomole = MolarFlow.KilomolePerSecond * Duration.Second",
"AmountOfSubstance.Mole = MolarFlow.MolePerSecond * Duration.Second",
"AmountOfSubstance.Mole = Molarity.MolePerCubicMeter * Volume.CubicMeter",
"Angle.Radian = RotationalSpeed.RadianPerSecond * Duration.Second",
"Area.SquareMeter = KinematicViscosity.SquareMeterPerSecond * Duration.Second",
"Area.SquareMeter = KinematicViscosity.SquareMeterPerSecond * Duration.Second -- NoInferredDivision",
"Area.SquareMeter = Length.Meter * Length.Meter",
"Area.SquareMeter = Volume.CubicMeter * ReciprocalLength.InverseMeter",
"AreaMomentOfInertia.MeterToTheFourth = Volume.CubicMeter * Length.Meter",
"double = Density.KilogramPerCubicMeter * SpecificVolume.CubicMeterPerKilogram",
"double = SpecificEnergy.JoulePerKilogram * BrakeSpecificFuelConsumption.KilogramPerJoule",
"double = TemperatureDelta.Kelvin * CoefficientOfThermalExpansion.PerKelvin",
"DynamicViscosity.NewtonSecondPerMeterSquared = Density.KilogramPerCubicMeter * KinematicViscosity.SquareMeterPerSecond",
"ElectricCharge.AmpereHour = ElectricCurrent.Ampere * Duration.Hour",
"ElectricCurrent.Ampere = ElectricCurrentGradient.AmperePerSecond * Duration.Second",
"ElectricPotential.Volt = ElectricCurrent.Ampere * ElectricResistance.Ohm",
"Energy.Joule = ElectricPotential.Volt * ElectricCharge.Coulomb",
"Energy.Joule = EnergyDensity.JoulePerCubicMeter * Volume.CubicMeter",
"Energy.Joule = MolarEnergy.JoulePerMole * AmountOfSubstance.Mole",
"Energy.Joule = Power.Watt * Duration.Second",
"Energy.Joule = SpecificEnergy.JoulePerKilogram * Mass.Kilogram",
"Energy.Joule = TemperatureDelta.Kelvin * Entropy.JoulePerKelvin",
Expand All @@ -35,8 +35,9 @@
"Length.Meter = Speed.MeterPerSecond * Duration.Second",
"Length.Meter = Volume.CubicMeter * ReciprocalArea.InverseSquareMeter",
"LinearDensity.KilogramPerMeter = Area.SquareMeter * Density.KilogramPerCubicMeter",
"LuminousFlux.Lumen = Illuminance.Lux * Area.SquareMeter",
"LuminousIntensity.Candela = Luminance.CandelaPerSquareMeter * Area.SquareMeter",
"Mass.Gram = AmountOfSubstance.Mole * MolarMass.GramPerMole",
"Mass.Kilogram = AmountOfSubstance.Mole * MolarMass.KilogramPerMole",
"Mass.Kilogram = AreaDensity.KilogramPerSquareMeter * Area.SquareMeter",
"Mass.Kilogram = Density.KilogramPerCubicMeter * Volume.CubicMeter",
"Mass.Kilogram = LinearDensity.KilogramPerMeter * Length.Meter",
Expand All @@ -62,7 +63,8 @@
"Pressure.NewtonPerSquareMeter = ForcePerLength.NewtonPerMeter * ReciprocalLength.InverseMeter",
"Pressure.Pascal = PressureChangeRate.PascalPerSecond * Duration.Second",
"Pressure.Pascal = SpecificWeight.NewtonPerCubicMeter * Length.Meter",
"Ratio.DecimalFraction = Area.SquareMeter * ReciprocalArea.InverseSquareMeter",
"Ratio.DecimalFraction = Area.SquareMeter * ReciprocalArea.InverseSquareMeter -- NoInferredDivision",
"Ratio.DecimalFraction = TemperatureDelta.Kelvin * CoefficientOfThermalExpansion.PerKelvin -- NoInferredDivision",
"ReciprocalArea.InverseSquareMeter = ReciprocalLength.InverseMeter * ReciprocalLength.InverseMeter",
"ReciprocalLength.InverseMeter = Length.Meter * ReciprocalArea.InverseSquareMeter",
"RotationalStiffness.NewtonMeterPerRadian = RotationalStiffnessPerLength.NewtonMeterPerRadianPerMeter * Length.Meter",
Expand Down
49 changes: 41 additions & 8 deletions UnitsNet.Tests/CustomCode/AmountOfSubstanceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ public void NumberOfParticlesInTwoMolesIsDoubleAvogadroConstant()

[Theory]
[InlineData(10, AmountOfSubstanceUnit.Mole,
KnownQuantities.MolarMassOfOxygen, MolarMassUnit.GramPerMole,
10 * KnownQuantities.MolarMassOfOxygen, MassUnit.Gram)] // 10 Moles of Oxygen weight 10 times as much as 1 Mole of Oxygen (MolarMass)
KnownQuantities.MolarMassOfOxygen, MolarMassUnit.GramPerMole,
10 * KnownQuantities.MolarMassOfOxygen, MassUnit.Gram)] // 10 Moles of Oxygen weight 10 times as much as 1 Mole of Oxygen (MolarMass)
public void MassFromAmountOfSubstanceAndMolarMass(
double amountOfSubstanceValue, AmountOfSubstanceUnit amountOfSubstanceUnit,
double molarMassValue, MolarMassUnit molarMassUnit,
Expand All @@ -83,9 +83,9 @@ public void MassFromAmountOfSubstanceAndMolarMass(

[Theory]
[InlineData(5, MassUnit.Gram,
KnownQuantities.MolarMassHClInGramsPerMole, MolarMassUnit.GramPerMole,
1.2, VolumeUnit.Liter,
0.1142805, MolarityUnit.MolePerLiter)] // molarity(HCl) = 5g / (1.2L * 36.46) = 0.114 mol/l = 0.114 M
KnownQuantities.MolarMassHClInGramsPerMole, MolarMassUnit.GramPerMole,
1.2, VolumeUnit.Liter,
0.1142805, MolarityUnit.MolePerLiter)] // molarity(HCl) = 5g / (1.2L * 36.46) = 0.114 mol/l = 0.114 M
public void MolarityFromComponentMassAndSolutionVolume(
double componentMassValue, MassUnit componentMassUnit,
double componentMolarMassValue, MolarMassUnit componentMolarMassUnit,
Expand All @@ -104,9 +104,9 @@ public void MolarityFromComponentMassAndSolutionVolume(

[Theory]
[InlineData(5, MassUnit.Gram,
KnownQuantities.MolarMassHClInGramsPerMole, MolarMassUnit.GramPerMole,
0.1142805, MolarityUnit.MolePerLiter,
1.2, VolumeUnit.Liter)] // 1.2 L of solution required for obtaining 0.1142805 Moles/L from 5g HCl
KnownQuantities.MolarMassHClInGramsPerMole, MolarMassUnit.GramPerMole,
0.1142805, MolarityUnit.MolePerLiter,
1.2, VolumeUnit.Liter)] // 1.2 L of solution required for obtaining 0.1142805 Moles/L from 5g HCl
public void VolumeSolutionFromComponentMassAndDesiredConcentration(
double componentMassValue, MassUnit componentMassUnit,
double componentMolarMassValue, MolarMassUnit componentMolarMassUnit,
Expand All @@ -122,5 +122,38 @@ public void VolumeSolutionFromComponentMassAndDesiredConcentration(

AssertEx.EqualTolerance(expectedSolutionVolumeValue, volumeSolution.As(expectedSolutionVolumeUnit), tolerence);
}

[Fact]
public void From_Mass_And_MolarMass_ReturnsTheMassDividedByTheMolarMass()
{
var mass = Mass.From(10, MassUnit.Gram);
var molarMass = MolarMass.From(2, MolarMassUnit.GramPerMole);
var expectedAmountOfSubstance = AmountOfSubstance.From(5, AmountOfSubstanceUnit.Mole);

var amountOfSubstance = AmountOfSubstance.FromMass(mass, molarMass);

Assert.Equal(expectedAmountOfSubstance, amountOfSubstance);
}

[Fact]
public void Multiplying_AmountOfSubstance_By_MolarEnergy_ReturnsEnergy()
{
Energy energy = AmountOfSubstance.FromMoles(5) * MolarEnergy.FromJoulesPerMole(10);
Assert.Equal(Energy.FromJoules(50), energy);
}

[Fact]
public void Dividing_AmountOfSubstance_By_MolarFlow_Returns_Duration()
{
var duration = AmountOfSubstance.FromMoles(10) / MolarFlow.FromMolesPerSecond(2);
Assert.Equal(Duration.FromSeconds(5), duration);
}

[Fact]
public void Dividing_AmountOfSubstance_By_Duration_Returns_MolarFlow()
{
MolarFlow molarFlow = AmountOfSubstance.FromMoles(10) / Duration.FromSeconds(5);
Assert.Equal(MolarFlow.FromMolesPerSecond(2), molarFlow);
}
}
}
56 changes: 56 additions & 0 deletions UnitsNet.Tests/CustomCode/AreaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,61 @@ public void AreaTimesReciprocalAreaEqualsRatio()
Ratio ratio = Area.FromSquareMeters(0.5) * ReciprocalArea.FromInverseSquareMeters(10);
Assert.Equal(5.0, ratio.Value);
}

[Fact]
public void AreaTimesIlluminanceEqualsLuminousFlux()
{
LuminousFlux luminousFlux = Area.FromSquareMeters(5) * Illuminance.FromLux(10);
Assert.Equal(LuminousFlux.FromLumens(50), luminousFlux);
}

[Fact]
public void AreaTimesLuminanceEqualsLuminousIntensity()
{
LuminousIntensity luminousIntensity = Area.FromSquareMeters(5) * Luminance.FromCandelasPerSquareMeter(10);
Assert.Equal(LuminousIntensity.FromCandela(50), luminousIntensity);
}

[Fact]
public void AreaTimesSpecificWeightEqualsForcePerLength()
{
ForcePerLength forcePerLength = Area.FromSquareMeters(20) * SpecificWeight.FromNewtonsPerCubicMeter(2000);
Assert.Equal(ForcePerLength.FromNewtonsPerMeter(40000), forcePerLength);
}

[Fact]
public void AreaTimesReciprocalLengthEqualsLength()
{
Length length = Area.FromSquareMeters(20) * ReciprocalLength.FromInverseMeters(5);
Assert.Equal(Length.FromMeters(100), length);
}

[Fact]
public void AreaTimesAreaDensityEqualsMass()
{
Mass mass = Area.FromSquareMeters(2) * AreaDensity.FromKilogramsPerSquareMeter(10);
Assert.Equal(Mass.FromKilograms(20), mass);
}

[Fact]
public void AreaTimesHeatFluxEqualsPower()
{
Power power = Area.FromSquareMeters(2) * HeatFlux.FromWattsPerSquareMeter(10);
Assert.Equal(Power.FromWatts(20), power);
}

[Fact]
public void AreaTimesForcePerLengthEqualsEqualsTorque()
{
Torque torque = Area.FromSquareMeters(2) * ForcePerLength.FromNewtonsPerMeter(10);
Assert.Equal(Torque.FromNewtonMeters(20), torque);
}

[Fact]
public void AreaDividedByReciprocalLengthEqualsVolume()
{
Volume volume = Area.FromSquareMeters(20) / ReciprocalLength.FromInverseMeters(5);
Assert.Equal(Volume.FromCubicMeters(4), volume);
}
}
}
17 changes: 2 additions & 15 deletions UnitsNet.Tests/CustomCode/CoefficientOfThermalExpansionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,8 @@ public class CoefficientOfThermalExpansionTests : CoefficientOfThermalExpansionT
[Fact]
public void CoefficientOfThermalExpansionTimesTemperatureDelta()
{
double temperatureDeltaDegC = 2.0;
double ctePerDegC = 0.001;
CoefficientOfThermalExpansion cte = CoefficientOfThermalExpansion.FromPerDegreeCelsius(ctePerDegC);
TemperatureDelta dT = TemperatureDelta.FromDegreesCelsius(temperatureDeltaDegC);
AssertEx.EqualTolerance(cte * dT, ctePerDegC * temperatureDeltaDegC, 1e-10);
}

[Fact]
public void TemperatureDeltaTimesCoefficientOfThermalExpansion()
{
double temperatureDeltaDegC = 2.0;
double ctePerDegC = 0.001;
CoefficientOfThermalExpansion cte = CoefficientOfThermalExpansion.FromPerDegreeCelsius(ctePerDegC);
TemperatureDelta dT = TemperatureDelta.FromDegreesCelsius(temperatureDeltaDegC);
AssertEx.EqualTolerance(dT * cte, temperatureDeltaDegC * ctePerDegC, 1e-10);
Ratio expansionRatio = CoefficientOfThermalExpansion.FromPerDegreeCelsius(2) * TemperatureDelta.FromDegreesCelsius(0.001);
Assert.Equal(Ratio.FromDecimalFractions(0.002), expansionRatio);
}
}
}
14 changes: 14 additions & 0 deletions UnitsNet.Tests/CustomCode/DensityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,19 @@ public void DensityTimesAreaEqualsLinearDensity()
LinearDensity linearDensity = Density.FromGramsPerCubicCentimeter(10) * Area.FromSquareCentimeters(2);
Assert.Equal(20, linearDensity.GramsPerCentimeter);
}

[Fact]
public static void DensityTimesVolumeConcentrationEqualsMassConcentration()
{
MassConcentration massConcentration = Density.FromKilogramsPerCubicMeter(20) * VolumeConcentration.FromPercent(50);
Assert.Equal(massConcentration, MassConcentration.FromKilogramsPerCubicMeter(10));
}

[Fact]
public static void InverseDensityEqualsSpecificVolume()
{
SpecificVolume specificVolume = Density.FromKilogramsPerCubicMeter(4).Inverse();
Assert.Equal(specificVolume, SpecificVolume.FromCubicMetersPerKilogram(0.25));
}
}
}
30 changes: 29 additions & 1 deletion UnitsNet.Tests/CustomCode/EnergyTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed under MIT No Attribution, see LICENSE file at the root.
// Licensed under MIT No Attribution, see LICENSE file at the root.
// Copyright 2013 Andreas Gullberg Larsen ([email protected]). Maintained at https://github.com/angularsen/UnitsNet.

using System;
Expand Down Expand Up @@ -191,5 +191,33 @@ public void EnergyDividedBySpecificEnergyEqualsMass()
Mass m = Energy.FromJoules(24) / SpecificEnergy.FromJoulesPerKilogram(8);
Assert.Equal(Mass.FromKilograms(3), m);
}

[Fact]
public void EnergyDividedByMolarEnergyEqualsAmountOfSubstance()
{
AmountOfSubstance m = Energy.FromJoules(24) / MolarEnergy.FromJoulesPerMole(8);
Assert.Equal(AmountOfSubstance.FromMoles(3), m);
}

[Fact]
public void EnergyDividedByAmountOfSubstanceEqualsMolarEnergy()
{
MolarEnergy m = Energy.FromJoules(24) / AmountOfSubstance.FromMoles(8);
Assert.Equal(MolarEnergy.FromJoulesPerMole(3), m);
}

[Fact]
public void EnergyDividedByVolumeEqualsEnergyDensity()
{
EnergyDensity m = Energy.FromJoules(24) / Volume.FromCubicMeters(8);
Assert.Equal(EnergyDensity.FromJoulesPerCubicMeter(3), m);
}

[Fact]
public void EnergyDividedByEnergyDensityEqualsVolume()
{
Volume m = Energy.FromJoules(24) / EnergyDensity.FromJoulesPerCubicMeter(8);
Assert.Equal(Volume.FromCubicMeters(3), m);
}
}
}
8 changes: 8 additions & 0 deletions UnitsNet.Tests/CustomCode/IlluminanceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@


using System;
using Xunit;

namespace UnitsNet.Tests.CustomCode
{
Expand All @@ -35,5 +36,12 @@ public class IlluminanceTests : IlluminanceTestsBase
protected override double KiloluxInOneLux => 1E-3;

protected override double MegaluxInOneLux => 1E-6;

[Fact]
public void IlluminanceTimesAreaEqualsLuminousFlux()
{
LuminousFlux luminousFlux = Illuminance.FromLux(10) * Area.FromSquareMeters(5);
Assert.Equal(LuminousFlux.FromLumens(50), luminousFlux);
}
}
}
23 changes: 23 additions & 0 deletions UnitsNet.Tests/CustomCode/LuminousFluxTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,35 @@


using System;
using Xunit;

namespace UnitsNet.Tests.CustomCode
{
public class LuminousFluxTests : LuminousFluxTestsBase
{
protected override bool SupportsSIUnitSystem => false;
protected override double LumensInOneLumen => 1;

[Fact]
public void LuminousFluxDividedByAreaEqualsIlluminance()
{
var luminousFlux = LuminousFlux.FromLumens(100);
var area = Area.FromSquareMeters(10);

var illuminance = luminousFlux / area;

Assert.Equal(Illuminance.FromLux(10), illuminance);
}

[Fact]
public void LuniousFluxDividedByIlluminanceEqualsArea()
{
var luminousFlux = LuminousFlux.FromLumens(100);
var illuminance = Illuminance.FromLux(10);

var area = luminousFlux / illuminance;

Assert.Equal(Area.FromSquareMeters(10), area);
}
}
}
64 changes: 64 additions & 0 deletions UnitsNet.Tests/CustomCode/MassTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,69 @@ public void AmountOfSubstanceFromMassAndMolarMass(

AssertEx.EqualTolerance(expectedAmountOfSubstanceValue, amountOfSubstance.As(expectedAmountOfSubstanceUnit), tolerence);
}

[Theory]
[InlineData(10, MassUnit.Kilogram,
5, SpecificVolumeUnit.CubicMeterPerKilogram,
50, VolumeUnit.CubicMeter)]
public void Multiplying_Mass_By_SpecificVolume_ReturnsVolume(double massValue, MassUnit massUnit, double specificVolumeValue,
SpecificVolumeUnit specificVolumeUnit, double expectedVolumeValue, VolumeUnit expectedVolumeUnit)
{
var mass = new Mass(massValue, massUnit);
var specificVolume = new SpecificVolume(specificVolumeValue, specificVolumeUnit);
var expectedVolume = new Volume(expectedVolumeValue, expectedVolumeUnit);

Volume volume = mass * specificVolume;

Assert.Equal(expectedVolume, volume);
}

[Theory]
[InlineData(10, MassUnit.Kilogram,
5, MassFlowUnit.KilogramPerSecond,
2, DurationUnit.Second)]
public void Dividing_Mass_By_MassFlow_ReturnsDuration(double massValue, MassUnit massUnit, double massFlowValue,
MassFlowUnit massFlowUnit, double expectedDurationValue, DurationUnit expectedDurationUnit)
{
var mass = new Mass(massValue, massUnit);
var massFlow = new MassFlow(massFlowValue, massFlowUnit);
var expectedDuration = new Duration(expectedDurationValue, expectedDurationUnit);

Duration duration = mass / massFlow;

Assert.Equal(expectedDuration, duration);
}

[Theory]
[InlineData(10, MassUnit.Kilogram,
5, AmountOfSubstanceUnit.Mole,
2, MolarMassUnit.KilogramPerMole)]
public void Dividing_Mass_By_AmountOfSubstance_ReturnsMolarMass(double massValue, MassUnit massUnit, double amountOfSubstanceValue,
AmountOfSubstanceUnit amountOfSubstanceUnit, double expectedMolarMassValue, MolarMassUnit expectedMolarMassUnit)
{
var mass = new Mass(massValue, massUnit);
var amountOfSubstance = new AmountOfSubstance(amountOfSubstanceValue, amountOfSubstanceUnit);
var expectedMolarMass = new MolarMass(expectedMolarMassValue, expectedMolarMassUnit);

MolarMass molarMass = mass / amountOfSubstance;

Assert.Equal(expectedMolarMass, molarMass);
}

[Theory]
[InlineData(10, MassUnit.Kilogram,
5, DensityUnit.KilogramPerCubicMeter,
2, VolumeUnit.CubicMeter)]
public void Dividing_Mass_By_Density_ReturnsVolume(double massValue, MassUnit massUnit, double densityValue,
DensityUnit densityUnit, double expectedVolumeValue, VolumeUnit expectedVolumeUnit)
{
var mass = new Mass(massValue, massUnit);
var density = new Density(densityValue, densityUnit);
var expectedVolume = new Volume(expectedVolumeValue, expectedVolumeUnit);

Volume volume = mass / density;

Assert.Equal(expectedVolume, volume);
}
}
}
Loading

0 comments on commit ef739cd

Please sign in to comment.