Skip to content

Commit

Permalink
Add concentration nits (mixtures/solutions) (#646)
Browse files Browse the repository at this point in the history
* Concentration Units (mixtures/solutions)

Added the following Concentration Units:
- MassConcentration: SI = kg/m3, typically mg/l
- VolumeConcentration : dimensionless, typically %
- MassFraction: SI = kg/kg, typically mg/kg

Modified the existing Molarity unit:
- Some operations that were originally based on the Density units now use the MassConcentration units instead (Note: despite the fact that they share the same measurement units- the Density is a distnct QuantyType from the MassConcentration)
- Removed all operators involving Molarity from the Density units

Defined some basic operations that were missing from the AmountOfSubstance/MolarMass/Mass units

Defined the triangular operations involving Mass/Molar/Volume concentrations (& the corresponding component's Density & MolarMass)

All unit tests included most were defined by actual chemists(which I AM NOT).
Note: one of the tests (QuantityIFormattableTests.VFormatEqualsValueToString)- was failing on my machine- it passes if I add CultureInfo.CurrentUICulture to the value.ToString() - as I presume was the intended behavior

* updated uppercase 'L' & BaseUnits in json

- updated liter abbreviations for g/l, g/dl, g/ml & kg/l to uppercase 'L'  (TODO Density?)
- added base units to all units in MassConcentration & Molarity (TODO Density?)

* BaseUnits, Obsolete methods & cosmetics

- corrected the BaseUnits for MassConcentration
- marked the invalid methods from Molarity/Density as Obsolete (were previously omitted)
- some cosmetic changes to the Unit Tests

* Removed Molarity.Molar as redundant (added abbreviation instead)

- MolesPerLiter: fixed the BaseUnits (default) to Deimeter/Mole
- Molar: removed in favor of using the alternative abbreviation 'M"
- MolarityTests - OneMilliMolarFromStringParsedCorrectly skipped while awaiting fix for #344

* Added a KnownQuantities class

- added a KnownQuantities class with a few constants that were used in multiple tests
- replaced the usages in MassConcentrationTests MolarityTests * VolumeConcentrationTests

* Testing with Theory + InlineData

- converted two of the MassConcentration tests to using Theory + InlineData

* Tests refactoring (Theory + InlineData)

- removed BaseUnits from GramPerDeciliter(not exact + overlap), kept it in GramPerLiter (as exact & non-overlapping), also kept it for GramPerMilliliter(exact + overlapping) because I thought it would be useful to have at least one such case for future testing
- moved the Mass/MolarMass operator to the Mass class (removing the MolarMass.extra)
- all tests refactored using Theory + Inline Data
- moved one or two tests to the appropriate .Test file
- removed a few redundant tests

* Make single line act-statements in tests
  • Loading branch information
lipchev authored and angularsen committed Apr 21, 2019
1 parent 7b8a36d commit b834a1c
Show file tree
Hide file tree
Showing 40 changed files with 8,892 additions and 43 deletions.
238 changes: 238 additions & 0 deletions Common/UnitDefinitions/MassConcentration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
{
"Name": "MassConcentration",
"BaseUnit": "KilogramPerCubicMeter",
"XmlDoc": "In chemistry, the mass concentration ρi (or γi) is defined as the mass of a constituent mi divided by the volume of the mixture V",
"XmlDocRemarks": "https://en.wikipedia.org/wiki/Mass_concentration_(chemistry)",
"BaseDimensions": {
"M": 1,
"L": -3
},
"Units": [
{
"SingularName": "GramPerCubicMillimeter",
"PluralName": "GramsPerCubicMillimeter",
"BaseUnits": {
"M": "Gram",
"L": "Millimeter"
},
"FromUnitToBaseFunc": "x/1e-6",
"FromBaseToUnitFunc": "x*1e-6",
"Prefixes": [ "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/mm³" ]
}
]
},
{
"SingularName": "GramPerCubicCentimeter",
"PluralName": "GramsPerCubicCentimeter",
"BaseUnits": {
"M": "Gram",
"L": "Centimeter"
},
"FromUnitToBaseFunc": "x/1e-3",
"FromBaseToUnitFunc": "x*1e-3",
"Prefixes": [ "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/cm³" ]
}
]
},
{
"SingularName": "GramPerCubicMeter",
"PluralName": "GramsPerCubicMeter",
"BaseUnits": {
"M": "Gram",
"L": "Meter"
},
"FromUnitToBaseFunc": "x/1e3",
"FromBaseToUnitFunc": "x*1e3",
"Prefixes": [ "Kilo", "Milli", "Micro" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/m³" ]
},
{
"Culture": "ru-RU",
"Abbreviations": [ "г/м³" ]
}
]
},
{
"SingularName": "GramPerMilliliter",
"PluralName": "GramsPerMilliliter",
"BaseUnits": {
"M": "Gram",
"L": "Centimeter"
},
"FromUnitToBaseFunc": "x/1e-3",
"FromBaseToUnitFunc": "x*1e-3",
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/mL" ]
}
]
},
{
"SingularName": "GramPerDeciliter",
"PluralName": "GramsPerDeciliter",
"FromUnitToBaseFunc": "x/1e-1",
"FromBaseToUnitFunc": "x*1e-1",
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/dL" ]
}
]
},
{
"SingularName": "GramPerLiter",
"PluralName": "GramsPerLiter",
"BaseUnits": {
"M": "Gram",
"L": "Decimeter"
},
"FromUnitToBaseFunc": "x",
"FromBaseToUnitFunc": "x",
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci", "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/L"]
}
]
},
{
"SingularName": "TonnePerCubicMillimeter",
"PluralName": "TonnesPerCubicMillimeter",
"BaseUnits": {
"M": "Tonne",
"L": "Millimeter"
},
"FromUnitToBaseFunc": "x/1e-12",
"FromBaseToUnitFunc": "x*1e-12",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "t/mm³" ]
}
]
},
{
"SingularName": "TonnePerCubicCentimeter",
"PluralName": "TonnesPerCubicCentimeter",
"BaseUnits": {
"M": "Tonne",
"L": "Centimeter"
},
"FromUnitToBaseFunc": "x/1e-9",
"FromBaseToUnitFunc": "x*1e-9",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "t/cm³" ]
}
]
},
{
"SingularName": "TonnePerCubicMeter",
"PluralName": "TonnesPerCubicMeter",
"BaseUnits": {
"M": "Tonne",
"L": "Meter"
},
"FromUnitToBaseFunc": "x/0.001",
"FromBaseToUnitFunc": "x*0.001",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "t/m³" ]
}
]
},
{
"SingularName": "PoundPerCubicInch",
"PluralName": "PoundsPerCubicInch",
"BaseUnits": {
"M": "Pound",
"L": "Inch"
},
"FromUnitToBaseFunc": "x/3.6127298147753e-5",
"FromBaseToUnitFunc": "x*3.6127298147753e-5",
"Prefixes": [ "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "lb/in³" ],
"AbbreviationsWithPrefixes": [ "kip/in³" ]
}
]
},
{
"SingularName": "PoundPerCubicFoot",
"PluralName": "PoundsPerCubicFoot",
"BaseUnits": {
"M": "Pound",
"L": "Foot"
},
"FromUnitToBaseFunc": "x/0.062427961",
"FromBaseToUnitFunc": "x*0.062427961",
"Prefixes": [ "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "lb/ft³" ],
"AbbreviationsWithPrefixes": [ "kip/ft³" ]
}
]
},
{
"SingularName": "SlugPerCubicFoot",
"PluralName": "SlugsPerCubicFoot",
"BaseUnits": {
"M": "Slug",
"L": "Foot"
},
"FromUnitToBaseFunc": "x*515.378818",
"FromBaseToUnitFunc": "x*0.00194032033",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "slug/ft³" ]
}
]
},
{
"SingularName": "PoundPerUSGallon",
"PluralName": "PoundsPerUSGallon",
"FromUnitToBaseFunc": "x*1.19826427e2",
"FromBaseToUnitFunc": "x/1.19826427e2",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "ppg (U.S.)" ]
}
]
},
{
"SingularName": "PoundPerImperialGallon",
"PluralName": "PoundsPerImperialGallon",
"FromUnitToBaseFunc": "x*9.9776398e1",
"FromBaseToUnitFunc": "x/9.9776398e1",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "ppg (imp.)" ]
}
]
}
]
}
106 changes: 106 additions & 0 deletions Common/UnitDefinitions/MassFraction.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"Name": "MassFraction",
"BaseUnit": "DecimalFraction",
"XmlDoc": "The mass fraction is defined as the mass of a constituent divided by the total mass of the mixture.",
"XmlDocRemarks": "https://en.wikipedia.org/wiki/Mass_fraction_(chemistry)",
"Units": [
{
"SingularName": "DecimalFraction",
"PluralName": "DecimalFractions",
"FromUnitToBaseFunc": "x",
"FromBaseToUnitFunc": "x",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "" ]
}
]
},
{
"SingularName": "GramPerGram",
"PluralName": "GramsPerGram",
"FromUnitToBaseFunc": "x",
"FromBaseToUnitFunc": "x",
"Prefixes": [ "Nano", "Micro", "Milli", "Centi", "Deci", "Deca", "Hecto", "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/g" ]
}
]
},
{
"SingularName": "GramPerKilogram",
"PluralName": "GramsPerKilogram",
"FromUnitToBaseFunc": "x/1e3",
"FromBaseToUnitFunc": "x*1e3",
"Prefixes": [ "Nano", "Micro", "Milli", "Centi", "Deci", "Deca", "Hecto", "Kilo" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "g/kg" ]
}
]
},
{
"SingularName": "Percent",
"PluralName": "Percent",
"FromUnitToBaseFunc": "x/1e2",
"FromBaseToUnitFunc": "x*1e2",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "%", "% (w/w)" ]
}
]
},
{
"SingularName": "PartPerThousand",
"PluralName": "PartsPerThousand",
"FromUnitToBaseFunc": "x/1e3",
"FromBaseToUnitFunc": "x*1e3",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "" ]
}
]
},
{
"SingularName": "PartPerMillion",
"PluralName": "PartsPerMillion",
"FromUnitToBaseFunc": "x/1e6",
"FromBaseToUnitFunc": "x*1e6",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "ppm" ]
}
]
},
{
"SingularName": "PartPerBillion",
"PluralName": "PartsPerBillion",
"FromUnitToBaseFunc": "x/1e9",
"FromBaseToUnitFunc": "x*1e9",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "ppb" ]
}
]
},
{
"SingularName": "PartPerTrillion",
"PluralName": "PartsPerTrillion",
"FromUnitToBaseFunc": "x/1e12",
"FromBaseToUnitFunc": "x*1e12",
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "ppt" ]
}
]
}
]
}
10 changes: 9 additions & 1 deletion Common/UnitDefinitions/Molarity.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
{
"SingularName": "MolesPerCubicMeter",
"PluralName": "MolesPerCubicMeter",
"BaseUnits": {
"L": "Meter",
"N": "Mole"
},
"FromUnitToBaseFunc": "x",
"FromBaseToUnitFunc": "x",
"Prefixes": [],
Expand All @@ -24,13 +28,17 @@
{
"SingularName": "MolesPerLiter",
"PluralName": "MolesPerLiter",
"BaseUnits": {
"L": "Decimeter",
"N": "Mole"
},
"FromUnitToBaseFunc": "x/1e-3",
"FromBaseToUnitFunc": "x*1e-3",
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci" ],
"Localization": [
{
"Culture": "en-US",
"Abbreviations": [ "mol/L" ]
"Abbreviations": [ "mol/L", "M"]
}
]
}
Expand Down
Loading

0 comments on commit b834a1c

Please sign in to comment.