278 lines
9.1 KiB
Nix
278 lines
9.1 KiB
Nix
{ core, physical, ... }:
|
|
let
|
|
inherit(core) debug list number set string type;
|
|
inherit(physical) formatValue;
|
|
|
|
fullTable
|
|
= set.map (symbol: value: value // { inherit symbol; } )
|
|
{
|
|
# Period 1
|
|
H = { dalton = 1.0080; };
|
|
He = { dalton = 4.0026; };
|
|
|
|
# Period 2
|
|
Li = { dalton = 6.94; };
|
|
Be = { dalton = 9.0122; };
|
|
B = { dalton = 10.81; };
|
|
C = { dalton = 12.011; };
|
|
N = { dalton = 14.007; };
|
|
O = { dalton = 15.999; };
|
|
F = { dalton = 18.998; };
|
|
Ne = { dalton = 20.180; };
|
|
|
|
# Period 3
|
|
Na = { dalton = 22.990; };
|
|
Mg = { dalton = 24.305; };
|
|
Al = { dalton = 26.982; };
|
|
Si = { dalton = 28.085; };
|
|
P = { dalton = 30.974; };
|
|
S = { dalton = 32.06; };
|
|
Cl = { dalton = 35.45; };
|
|
Ar = { dalton = 39.948; };
|
|
|
|
# Period 4
|
|
K = { dalton = 39.098; };
|
|
Ca = { dalton = 40.078; };
|
|
Sc = { dalton = 44.956; };
|
|
Ti = { dalton = 47.867; };
|
|
V = { dalton = 50.942; };
|
|
Cr = { dalton = 51.996; };
|
|
Mn = { dalton = 54.938; };
|
|
Fe = { dalton = 55.845; };
|
|
Co = { dalton = 58.933; };
|
|
Ni = { dalton = 58.693; };
|
|
Cu = { dalton = 63.546; };
|
|
Zn = { dalton = 65.380; };
|
|
Ga = { dalton = 69.723; };
|
|
Ge = { dalton = 72.630; };
|
|
As = { dalton = 74.922; };
|
|
Se = { dalton = 78.971; };
|
|
Br = { dalton = 79.904; };
|
|
Kr = { dalton = 83.798; };
|
|
|
|
# Period 5
|
|
Rb = { dalton = 85.468; };
|
|
Sr = { dalton = 87.620; };
|
|
Y = { dalton = 88.906; };
|
|
Zr = { dalton = 91.224; };
|
|
Nb = { dalton = 92.906; };
|
|
Mo = { dalton = 95.950; };
|
|
Tc = { dalton = 97.4; };
|
|
Ru = { dalton = 101.07; };
|
|
Rh = { dalton = 102.91; };
|
|
Pd = { dalton = 106.42; };
|
|
Ag = { dalton = 107.87; };
|
|
Cd = { dalton = 112.41; };
|
|
In = { dalton = 114.82; };
|
|
Sn = { dalton = 118.71; };
|
|
Sb = { dalton = 121.76; };
|
|
Te = { dalton = 127.60; };
|
|
I = { dalton = 126.90; };
|
|
Xe = { dalton = 131.29; };
|
|
|
|
# Period 6
|
|
Cs = { dalton = 132.91; };
|
|
Ba = { dalton = 137.33; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
# = { dalton = ; };
|
|
Pb = { dalton = 207.20; };
|
|
Bi = { dalton = 208.98; };
|
|
Po = { dalton = 209.98; };
|
|
At = { dalton = 210; };
|
|
Rn = { dalton = 222; };
|
|
|
|
# Period 7
|
|
};
|
|
tableOfMasses = set.mapValues ( value: value.dalton ) fullTable;
|
|
|
|
normaliseMolecularFormula
|
|
= let
|
|
addElements
|
|
= { ... } @ elements:
|
|
previous:
|
|
count:
|
|
type.matchPrimitiveOrPanic previous
|
|
{
|
|
set
|
|
= set.fold
|
|
(
|
|
{ ... } @ elements:
|
|
name:
|
|
previous:
|
|
elements
|
|
// {
|
|
${name} = previous * count + ( elements.${name} or 0 );
|
|
}
|
|
)
|
|
elements
|
|
previous;
|
|
string
|
|
= elements
|
|
// {
|
|
${previous} = ( elements.${previous} or 0 ) + count;
|
|
};
|
|
null = elements;
|
|
};
|
|
getSymbol = foo: foo.symbol or foo;
|
|
parse
|
|
= { elements, previous } @ this:
|
|
token:
|
|
type.matchPrimitiveOrPanic token
|
|
{
|
|
int
|
|
= if previous != null
|
|
then
|
|
{
|
|
elements = addElements elements previous token;
|
|
previous = null;
|
|
}
|
|
else
|
|
debug.panic [ "normaliseMolecularFormula" "parse" ] "Unexpected Number!";
|
|
list
|
|
= {
|
|
elements = addElements elements previous 1;
|
|
previous = normalise token;
|
|
};
|
|
set
|
|
= {
|
|
elements = addElements elements previous 1;
|
|
previous = getSymbol token;
|
|
};
|
|
string
|
|
= {
|
|
elements = addElements elements previous 1;
|
|
previous = token;
|
|
};
|
|
};
|
|
defaultState
|
|
= {
|
|
elements = { };
|
|
previous = null;
|
|
};
|
|
finalise = { elements, previous }: addElements elements previous 1;
|
|
normalise
|
|
= this:
|
|
finalise ( list.fold parse defaultState this );
|
|
in
|
|
this: finalise (parse defaultState this);
|
|
|
|
calculateMassOfFormula
|
|
= formula:
|
|
debug.debug "calculateMassOfFormula"
|
|
{
|
|
text = "Molecular Formula";
|
|
data = formula;
|
|
}
|
|
(
|
|
type.matchPrimitiveOrPanic formula
|
|
{
|
|
null = null;
|
|
set
|
|
= set.fold
|
|
(
|
|
state:
|
|
symbol:
|
|
count:
|
|
( state + count * ( tableOfMasses.${symbol} or (debug.panic "calculateMassOfFormula" "Unknown symbol: ${symbol}")) )
|
|
)
|
|
0
|
|
formula;
|
|
}
|
|
);
|
|
|
|
formatMolecularFormula
|
|
= { ... } @ formula:
|
|
list.fold
|
|
(
|
|
result:
|
|
symbol:
|
|
let
|
|
count = formula.${symbol} or 0;
|
|
in
|
|
if count == 0
|
|
then
|
|
result
|
|
else if count == 1
|
|
then
|
|
"${result}${symbol}"
|
|
else
|
|
"${result}${symbol}${string count}"
|
|
)
|
|
""
|
|
(
|
|
if formula.C or 0 == 0
|
|
then
|
|
set.names fullTable
|
|
else
|
|
[
|
|
"C" "H"
|
|
"Ag" "Al" "Ar" "As" "At" "B" "Ba" "Be" "Bi" "Br" "Ca" "Cd" "Cl" "Co"
|
|
"Cr" "Cs" "Cu" "F" "Fe" "Ga" "Ge" "He" "I" "In" "K" "Kr" "Li" "Mg"
|
|
"Mn" "Mo" "N" "Na" "Nb" "Ne" "Ni" "O" "P" "Pb" "Pd" "Po" "Rb" "Rh"
|
|
"Rn" "Ru" "S" "Sb" "Sc" "Se" "Si" "Sn" "Sr" "Tc" "Te" "Ti" "V" "Xe"
|
|
"Y" "Zn" "Zr"
|
|
]
|
|
);
|
|
|
|
mapAnalysis
|
|
= { formula, ... } @ substance:
|
|
{ ... } @ gotElements:
|
|
if gotElements != { }
|
|
then
|
|
let
|
|
formula' = normaliseMolecularFormula formula;
|
|
format
|
|
= elements:
|
|
string.concatWith ", "
|
|
(
|
|
set.mapToList
|
|
(
|
|
symbol:
|
|
value:
|
|
"\\ch{${symbol}}:~${formatValue { inherit value; precision = 2; } "percent"}"
|
|
)
|
|
elements
|
|
);
|
|
calculated
|
|
= let
|
|
mapped = set.map (symbol: value: tableOfMasses.${symbol} * value) formula';
|
|
sum = number.sum (set.values mapped);
|
|
filtered = set.map (symbol: _: mapped.${symbol} or 0.0 ) gotElements;
|
|
calcElements = set.mapValues (value: value / sum * 100.0) filtered;
|
|
in
|
|
format calcElements;
|
|
found = format gotElements;
|
|
in
|
|
[ "Elementar\\-analyse berechnet für \\ch{${formatMolecularFormula formula'}}: ${calculated}; gefunden: ${found}." ]
|
|
else
|
|
[ ];
|
|
in
|
|
{
|
|
inherit normaliseMolecularFormula formatMolecularFormula calculateMassOfFormula;
|
|
inherit mapAnalysis;
|
|
inherit fullTable tableOfMasses;
|
|
}
|