Skip to content

Commit b834a1c

Browse files
lipchevangularsen
authored andcommitted
Add concentration nits (mixtures/solutions) (#646)
* 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
1 parent 7b8a36d commit b834a1c

40 files changed

+8892
-43
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
{
2+
"Name": "MassConcentration",
3+
"BaseUnit": "KilogramPerCubicMeter",
4+
"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",
5+
"XmlDocRemarks": "https://en.wikipedia.org/wiki/Mass_concentration_(chemistry)",
6+
"BaseDimensions": {
7+
"M": 1,
8+
"L": -3
9+
},
10+
"Units": [
11+
{
12+
"SingularName": "GramPerCubicMillimeter",
13+
"PluralName": "GramsPerCubicMillimeter",
14+
"BaseUnits": {
15+
"M": "Gram",
16+
"L": "Millimeter"
17+
},
18+
"FromUnitToBaseFunc": "x/1e-6",
19+
"FromBaseToUnitFunc": "x*1e-6",
20+
"Prefixes": [ "Kilo" ],
21+
"Localization": [
22+
{
23+
"Culture": "en-US",
24+
"Abbreviations": [ "g/mm³" ]
25+
}
26+
]
27+
},
28+
{
29+
"SingularName": "GramPerCubicCentimeter",
30+
"PluralName": "GramsPerCubicCentimeter",
31+
"BaseUnits": {
32+
"M": "Gram",
33+
"L": "Centimeter"
34+
},
35+
"FromUnitToBaseFunc": "x/1e-3",
36+
"FromBaseToUnitFunc": "x*1e-3",
37+
"Prefixes": [ "Kilo" ],
38+
"Localization": [
39+
{
40+
"Culture": "en-US",
41+
"Abbreviations": [ "g/cm³" ]
42+
}
43+
]
44+
},
45+
{
46+
"SingularName": "GramPerCubicMeter",
47+
"PluralName": "GramsPerCubicMeter",
48+
"BaseUnits": {
49+
"M": "Gram",
50+
"L": "Meter"
51+
},
52+
"FromUnitToBaseFunc": "x/1e3",
53+
"FromBaseToUnitFunc": "x*1e3",
54+
"Prefixes": [ "Kilo", "Milli", "Micro" ],
55+
"Localization": [
56+
{
57+
"Culture": "en-US",
58+
"Abbreviations": [ "g/m³" ]
59+
},
60+
{
61+
"Culture": "ru-RU",
62+
"Abbreviations": [ "г/м³" ]
63+
}
64+
]
65+
},
66+
{
67+
"SingularName": "GramPerMilliliter",
68+
"PluralName": "GramsPerMilliliter",
69+
"BaseUnits": {
70+
"M": "Gram",
71+
"L": "Centimeter"
72+
},
73+
"FromUnitToBaseFunc": "x/1e-3",
74+
"FromBaseToUnitFunc": "x*1e-3",
75+
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci" ],
76+
"Localization": [
77+
{
78+
"Culture": "en-US",
79+
"Abbreviations": [ "g/mL" ]
80+
}
81+
]
82+
},
83+
{
84+
"SingularName": "GramPerDeciliter",
85+
"PluralName": "GramsPerDeciliter",
86+
"FromUnitToBaseFunc": "x/1e-1",
87+
"FromBaseToUnitFunc": "x*1e-1",
88+
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci" ],
89+
"Localization": [
90+
{
91+
"Culture": "en-US",
92+
"Abbreviations": [ "g/dL" ]
93+
}
94+
]
95+
},
96+
{
97+
"SingularName": "GramPerLiter",
98+
"PluralName": "GramsPerLiter",
99+
"BaseUnits": {
100+
"M": "Gram",
101+
"L": "Decimeter"
102+
},
103+
"FromUnitToBaseFunc": "x",
104+
"FromBaseToUnitFunc": "x",
105+
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci", "Kilo" ],
106+
"Localization": [
107+
{
108+
"Culture": "en-US",
109+
"Abbreviations": [ "g/L"]
110+
}
111+
]
112+
},
113+
{
114+
"SingularName": "TonnePerCubicMillimeter",
115+
"PluralName": "TonnesPerCubicMillimeter",
116+
"BaseUnits": {
117+
"M": "Tonne",
118+
"L": "Millimeter"
119+
},
120+
"FromUnitToBaseFunc": "x/1e-12",
121+
"FromBaseToUnitFunc": "x*1e-12",
122+
"Localization": [
123+
{
124+
"Culture": "en-US",
125+
"Abbreviations": [ "t/mm³" ]
126+
}
127+
]
128+
},
129+
{
130+
"SingularName": "TonnePerCubicCentimeter",
131+
"PluralName": "TonnesPerCubicCentimeter",
132+
"BaseUnits": {
133+
"M": "Tonne",
134+
"L": "Centimeter"
135+
},
136+
"FromUnitToBaseFunc": "x/1e-9",
137+
"FromBaseToUnitFunc": "x*1e-9",
138+
"Localization": [
139+
{
140+
"Culture": "en-US",
141+
"Abbreviations": [ "t/cm³" ]
142+
}
143+
]
144+
},
145+
{
146+
"SingularName": "TonnePerCubicMeter",
147+
"PluralName": "TonnesPerCubicMeter",
148+
"BaseUnits": {
149+
"M": "Tonne",
150+
"L": "Meter"
151+
},
152+
"FromUnitToBaseFunc": "x/0.001",
153+
"FromBaseToUnitFunc": "x*0.001",
154+
"Localization": [
155+
{
156+
"Culture": "en-US",
157+
"Abbreviations": [ "t/m³" ]
158+
}
159+
]
160+
},
161+
{
162+
"SingularName": "PoundPerCubicInch",
163+
"PluralName": "PoundsPerCubicInch",
164+
"BaseUnits": {
165+
"M": "Pound",
166+
"L": "Inch"
167+
},
168+
"FromUnitToBaseFunc": "x/3.6127298147753e-5",
169+
"FromBaseToUnitFunc": "x*3.6127298147753e-5",
170+
"Prefixes": [ "Kilo" ],
171+
"Localization": [
172+
{
173+
"Culture": "en-US",
174+
"Abbreviations": [ "lb/in³" ],
175+
"AbbreviationsWithPrefixes": [ "kip/in³" ]
176+
}
177+
]
178+
},
179+
{
180+
"SingularName": "PoundPerCubicFoot",
181+
"PluralName": "PoundsPerCubicFoot",
182+
"BaseUnits": {
183+
"M": "Pound",
184+
"L": "Foot"
185+
},
186+
"FromUnitToBaseFunc": "x/0.062427961",
187+
"FromBaseToUnitFunc": "x*0.062427961",
188+
"Prefixes": [ "Kilo" ],
189+
"Localization": [
190+
{
191+
"Culture": "en-US",
192+
"Abbreviations": [ "lb/ft³" ],
193+
"AbbreviationsWithPrefixes": [ "kip/ft³" ]
194+
}
195+
]
196+
},
197+
{
198+
"SingularName": "SlugPerCubicFoot",
199+
"PluralName": "SlugsPerCubicFoot",
200+
"BaseUnits": {
201+
"M": "Slug",
202+
"L": "Foot"
203+
},
204+
"FromUnitToBaseFunc": "x*515.378818",
205+
"FromBaseToUnitFunc": "x*0.00194032033",
206+
"Localization": [
207+
{
208+
"Culture": "en-US",
209+
"Abbreviations": [ "slug/ft³" ]
210+
}
211+
]
212+
},
213+
{
214+
"SingularName": "PoundPerUSGallon",
215+
"PluralName": "PoundsPerUSGallon",
216+
"FromUnitToBaseFunc": "x*1.19826427e2",
217+
"FromBaseToUnitFunc": "x/1.19826427e2",
218+
"Localization": [
219+
{
220+
"Culture": "en-US",
221+
"Abbreviations": [ "ppg (U.S.)" ]
222+
}
223+
]
224+
},
225+
{
226+
"SingularName": "PoundPerImperialGallon",
227+
"PluralName": "PoundsPerImperialGallon",
228+
"FromUnitToBaseFunc": "x*9.9776398e1",
229+
"FromBaseToUnitFunc": "x/9.9776398e1",
230+
"Localization": [
231+
{
232+
"Culture": "en-US",
233+
"Abbreviations": [ "ppg (imp.)" ]
234+
}
235+
]
236+
}
237+
]
238+
}
+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
{
2+
"Name": "MassFraction",
3+
"BaseUnit": "DecimalFraction",
4+
"XmlDoc": "The mass fraction is defined as the mass of a constituent divided by the total mass of the mixture.",
5+
"XmlDocRemarks": "https://en.wikipedia.org/wiki/Mass_fraction_(chemistry)",
6+
"Units": [
7+
{
8+
"SingularName": "DecimalFraction",
9+
"PluralName": "DecimalFractions",
10+
"FromUnitToBaseFunc": "x",
11+
"FromBaseToUnitFunc": "x",
12+
"Localization": [
13+
{
14+
"Culture": "en-US",
15+
"Abbreviations": [ "" ]
16+
}
17+
]
18+
},
19+
{
20+
"SingularName": "GramPerGram",
21+
"PluralName": "GramsPerGram",
22+
"FromUnitToBaseFunc": "x",
23+
"FromBaseToUnitFunc": "x",
24+
"Prefixes": [ "Nano", "Micro", "Milli", "Centi", "Deci", "Deca", "Hecto", "Kilo" ],
25+
"Localization": [
26+
{
27+
"Culture": "en-US",
28+
"Abbreviations": [ "g/g" ]
29+
}
30+
]
31+
},
32+
{
33+
"SingularName": "GramPerKilogram",
34+
"PluralName": "GramsPerKilogram",
35+
"FromUnitToBaseFunc": "x/1e3",
36+
"FromBaseToUnitFunc": "x*1e3",
37+
"Prefixes": [ "Nano", "Micro", "Milli", "Centi", "Deci", "Deca", "Hecto", "Kilo" ],
38+
"Localization": [
39+
{
40+
"Culture": "en-US",
41+
"Abbreviations": [ "g/kg" ]
42+
}
43+
]
44+
},
45+
{
46+
"SingularName": "Percent",
47+
"PluralName": "Percent",
48+
"FromUnitToBaseFunc": "x/1e2",
49+
"FromBaseToUnitFunc": "x*1e2",
50+
"Localization": [
51+
{
52+
"Culture": "en-US",
53+
"Abbreviations": [ "%", "% (w/w)" ]
54+
}
55+
]
56+
},
57+
{
58+
"SingularName": "PartPerThousand",
59+
"PluralName": "PartsPerThousand",
60+
"FromUnitToBaseFunc": "x/1e3",
61+
"FromBaseToUnitFunc": "x*1e3",
62+
"Localization": [
63+
{
64+
"Culture": "en-US",
65+
"Abbreviations": [ "" ]
66+
}
67+
]
68+
},
69+
{
70+
"SingularName": "PartPerMillion",
71+
"PluralName": "PartsPerMillion",
72+
"FromUnitToBaseFunc": "x/1e6",
73+
"FromBaseToUnitFunc": "x*1e6",
74+
"Localization": [
75+
{
76+
"Culture": "en-US",
77+
"Abbreviations": [ "ppm" ]
78+
}
79+
]
80+
},
81+
{
82+
"SingularName": "PartPerBillion",
83+
"PluralName": "PartsPerBillion",
84+
"FromUnitToBaseFunc": "x/1e9",
85+
"FromBaseToUnitFunc": "x*1e9",
86+
"Localization": [
87+
{
88+
"Culture": "en-US",
89+
"Abbreviations": [ "ppb" ]
90+
}
91+
]
92+
},
93+
{
94+
"SingularName": "PartPerTrillion",
95+
"PluralName": "PartsPerTrillion",
96+
"FromUnitToBaseFunc": "x/1e12",
97+
"FromBaseToUnitFunc": "x*1e12",
98+
"Localization": [
99+
{
100+
"Culture": "en-US",
101+
"Abbreviations": [ "ppt" ]
102+
}
103+
]
104+
}
105+
]
106+
}

Common/UnitDefinitions/Molarity.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
{
1212
"SingularName": "MolesPerCubicMeter",
1313
"PluralName": "MolesPerCubicMeter",
14+
"BaseUnits": {
15+
"L": "Meter",
16+
"N": "Mole"
17+
},
1418
"FromUnitToBaseFunc": "x",
1519
"FromBaseToUnitFunc": "x",
1620
"Prefixes": [],
@@ -24,13 +28,17 @@
2428
{
2529
"SingularName": "MolesPerLiter",
2630
"PluralName": "MolesPerLiter",
31+
"BaseUnits": {
32+
"L": "Decimeter",
33+
"N": "Mole"
34+
},
2735
"FromUnitToBaseFunc": "x/1e-3",
2836
"FromBaseToUnitFunc": "x*1e-3",
2937
"Prefixes": [ "Pico", "Nano", "Micro", "Milli", "Centi", "Deci" ],
3038
"Localization": [
3139
{
3240
"Culture": "en-US",
33-
"Abbreviations": [ "mol/L" ]
41+
"Abbreviations": [ "mol/L", "M"]
3442
}
3543
]
3644
}

0 commit comments

Comments
 (0)