/// <summary> /// 吸収係数 /// </summary> /// <param name="elements"></param> /// <param name="index"></param> /// <param name="incidentEnergy"></param> /// <param name="theta"></param> /// <returns></returns> public static double AbsorptionCorrectionFunction(Element[] elements, int index, double incidentEnergy, double theta) { int z = elements[index].Z; XrayLine line = elements[index].Line; XrayLineEdge edge; if (elements[index].Line == XrayLine.Ka || elements[index].Line == XrayLine.Ka1 || elements[index].Line == XrayLine.Ka2) { edge = XrayLineEdge.K; } else { edge = XrayLineEdge.L3; } double mu_rho = 0; double h = 0; for (int i = 0; i < elements.Length; i++) { mu_rho += elements[i].WeightRatio * AtomConstants.MassAbsorption(AtomConstants.CharacteristicXrayEnergy(z, line), elements[i].Z); h += elements[i].WeightRatio * 1.2 * AtomConstants.AtomicWeight(elements[i].Z) / elements[i].Z / elements[i].Z; } double chi = mu_rho / Math.Sin(theta); double ec = AtomConstants.CharacteristicXrayEnergy(z, edge); double sigma = 4.5E5 / (Math.Pow(incidentEnergy, 1.65) - Math.Pow(ec, 1.65)); return((1 + h) / (1 + chi / sigma) / (1 + h * (1 + chi / sigma)));; }
public Element(int atomicNumber, double valence, double molarAbundance = 1, XrayLine line = XrayLine.Ka, double count = 0, double countTime = 1) { Z = atomicNumber; AtomicName = AtomConstants.AtomicName(Z); MolarAbundance = molarAbundance; Valence = valence; // Isotopes = AtomConstants.IsotopeAbundance[Z]; MolarWeight = AtomConstants.AtomicWeight(Z); }
/// <summary> /// 単原子分子のコンストラクタ /// </summary> /// <param name="z">原子番号</param> /// <param name="valence">価数</param> /// <param name="weightRatio">重量比</param> public Molecule(int z, double valence = 0, double weightRatio = 0, double molarAbundance = 0) { if (z != 0) { Element e = new Element(z, 0); Elements = new List <Element>(); Elements.Add(e); e.MolarAbundance = 1; MolarWeight = e.MolarWeight; Valence = valence; WeightRatio = weightRatio; MolarAbundance = molarAbundance; Formula = AtomConstants.AtomicName(z); } }
static Bonds() { var anionNum = new List <int> { 8, 9, 16, 17, 34, 35, 52, 53 }; Anions = anionNum.Select(n => $"{n}: {AtomConstants.AtomicName(n)}").ToList(); var cationNum = new List <int>(); cationNum.AddRange(Enumerable.Range(3, 5)); cationNum.AddRange(Enumerable.Range(11, 5)); cationNum.AddRange(Enumerable.Range(19, 15)); cationNum.AddRange(Enumerable.Range(37, 15)); cationNum.AddRange(Enumerable.Range(55, 20)); Cations = cationNum.Select(n => $"{n}: {AtomConstants.AtomicName(n)}").ToList(); }
/// <summary> /// 連続X線による蛍光励起補正 /// </summary> /// <param name="elements"></param> /// <param name="index"></param> /// <param name="E0"></param> /// <param name="TakeoffAngle"></param> /// <returns></returns> public static double ChontinuousFluorescenceFactor(Element[] elements, int index, double E0, double TakeoffAngle) { int zA = elements[index].Z; XrayLineEdge edgeA = XrayLineEdge.K; XrayLine lineA = XrayLine.Ka; if (elements[index].Line == XrayLine.La1 || elements[index].Line == XrayLine.La2 || elements[index].Line == XrayLine.Lb1 || elements[index].Line == XrayLine.Lb2) { edgeA = XrayLineEdge.L3; lineA = XrayLine.La1; } double EcA = AtomConstants.CharacteristicXrayEnergy(zA, edgeA); double E = AtomConstants.CharacteristicXrayEnergy(zA, elements[index].Line); double c = lineA == XrayLine.Ka ? 4.34E-6 : 3.13E-6; double mu_rhoAAe = AtomConstants.MassAbsorption(EcA, zA); double mu_rhoUnkAe = 0; double mu_rhoUnkA = 0; double zAve = 0; for (int i = 0; i < elements.Length; i++) { mu_rhoUnkAe += elements[i].WeightRatio * AtomConstants.MassAbsorption(EcA, elements[i].Z); mu_rhoUnkA += elements[i].WeightRatio * AtomConstants.MassAbsorption(E, elements[i].Z); zAve += elements[i].WeightRatio * elements[i].Z; } double gamma = AtomConstants.AbsorptionJumpRatio(zA, edgeA); double gammaMinusOnePerGamma = (gamma - 1) / gamma; if (lineA == XrayLine.La1) { gammaMinusOnePerGamma = (gamma - 1) / gamma / AtomConstants.AbsorptionJumpRatio(zA, XrayLineEdge.L2) / AtomConstants.AbsorptionJumpRatio(zA, XrayLineEdge.L1); } double chi = mu_rhoUnkA / Math.Sin(TakeoffAngle); double g = chi / mu_rhoUnkAe; double U0A = E0 / EcA; return(c * elements[index].MolarWeight * zAve * EcA * mu_rhoAAe / mu_rhoUnkAe * gammaMinusOnePerGamma * Math.Log(1 + g * U0A) / g / U0A); }
/// <summary> /// 後方散乱係数 /// </summary> /// <param name="elements"></param> /// <param name="index"></param> /// <param name="incidentEnergy"></param> /// <returns></returns> public static double BackscatteredFactor(Element[] elements, int index, double incidentEnergy) { int z = elements[index].Z; XrayLine line = elements[index].Line; XrayLineEdge edge; if (line == XrayLine.Ka || line == XrayLine.Ka1 || line == XrayLine.Ka2) { edge = XrayLineEdge.K; } else { edge = XrayLineEdge.L3; } double r = 0; for (int i = 0; i < elements.Length; i++) { r += elements[i].WeightRatio * AtomConstants.BackScatteredFactor(AtomConstants.CharacteristicXrayEnergy(z, edge), incidentEnergy, elements[i].Z); } return(r); }
/// <summary> /// Vesta標準のボンドを生成. 入力形式は、原子番号の配列 /// </summary> /// <param name="atomicNumbers"></param> /// <returns></returns> public static Bonds[] GetVestaBonds(IEnumerable <int> atomicNumbers) => GetVestaBonds(atomicNumbers.Select(n => $"{n}: {AtomConstants.AtomicName(n)}"));
public WaveProperty(int xrayElementNumber, XrayLine xrayLine) { Source = WaveSource.Xray; WaveLength = AtomConstants.CharacteristicXrayWavelength(xrayElementNumber, xrayLine); Energy = AtomConstants.CharacteristicXrayWavelength(xrayElementNumber, xrayLine); }
/// <summary> /// 特性X線による蛍光励起補正 /// </summary> /// <param name="elements"></param> /// <param name="index"></param> /// <param name="E0"></param> /// <param name="takeoff"></param> /// <returns></returns> public static double CharacteristicFluorescenceFactor(Element[] elements, int index, double E0, double takeoff) { //まず、被励起X線 A[] と励起X線 B[] の組み合わせを選択 int zA = elements[index].Z; XrayLineEdge edgeA = XrayLineEdge.K; XrayLine lineA = XrayLine.Ka; double energyA = AtomConstants.CharacteristicXrayEnergy(zA, elements[index].Line); if (elements[index].Line == XrayLine.La1 || elements[index].Line == XrayLine.La2 || elements[index].Line == XrayLine.Lb1 || elements[index].Line == XrayLine.Lb2) { edgeA = XrayLineEdge.L3; lineA = XrayLine.La1; } double EcA = AtomConstants.CharacteristicXrayEnergy(zA, edgeA); double fchGamma = 0; double U0A = E0 / EcA; double gamma = AtomConstants.AbsorptionJumpRatio(zA, edgeA); double gammaMinusOnePerGamma = (gamma - 1) / gamma; if (lineA == XrayLine.La1) { gammaMinusOnePerGamma = (gamma - 1) / gamma / AtomConstants.AbsorptionJumpRatio(zA, XrayLineEdge.L2) / AtomConstants.AbsorptionJumpRatio(zA, XrayLineEdge.L1); } double mu_rhoUnkA = 0; for (int k = 0; k < elements.Length; k++) { mu_rhoUnkA += elements[k].WeightRatio * AtomConstants.MassAbsorption(energyA, elements[k].Z); } double sigmaA = 4.5E5 / (Math.Pow(E0, 1.65) - Math.Pow(EcA, 1.65)); for (int i = 0; i < elements.Length; i++) { if (i != index) { int zB = elements[i].Z; double omega = AtomConstantsSub.FluorescentYieldK[zB]; double JAwithoutP = 0.5 * gammaMinusOnePerGamma * omega * AtomConstants.AtomicWeight(zA) / AtomConstants.AtomicWeight(zB); //"Kab": beta = 1.1; "Kb": beta = 0.1; "Lab": beta = 1.4; "Lb": beta = 0.4; 計算効率を上げるため、一度計算したbetaは再利用する. double[] beta = new double[0]; if (betaArray[zB] != null && betaArray[zB].ContainsKey(EcA)) { beta = betaArray[zB][EcA]; } else { if (EcA < AtomConstants.CharacteristicXrayEnergy(zB, XrayLine.La1)) { beta = new[] { 1.1, 1.4 } } ; else if (EcA < AtomConstants.CharacteristicXrayEnergy(zB, XrayLine.Lb1)) { beta = new[] { 1.1, 0.4 } } ; else if (EcA < AtomConstants.CharacteristicXrayEnergy(zB, XrayLine.Ka1)) { beta = new[] { 1.1 } } ; else if (EcA < AtomConstants.CharacteristicXrayEnergy(zB, XrayLine.Kb1)) { beta = new[] { 0.1 } } ; if (betaArray[zB] == null) { betaArray[zB] = new Dictionary <double, double[]>(); } lock (lockObJforBetaArray) betaArray[zB].Add(EcA, beta); } for (int j = 0; j < beta.Length; j++)//j==0ならK系列, j==1ならL系列 { XrayLineEdge edgeB = j == 0 ? XrayLineEdge.K : XrayLineEdge.L3; double EcB = AtomConstants.CharacteristicXrayEnergy(zB, edgeB); double U0B = E0 / EcB; if (E0 > EcB) { double fchCb = elements[i].WeightRatio * beta[j]; double P = 1; if (lineA == XrayLine.Ka && j == 1) { P = 4.2; } else if (lineA == XrayLine.La1 && j == 1) { P = 0.24; } double JA = JAwithoutP * P; double D = Math.Pow((U0B - 1) / (U0A - 1), 1.67); double energyB = j == 0 ? AtomConstants.CharacteristicXrayEnergy(zB, XrayLine.Ka) : AtomConstants.CharacteristicXrayEnergy(zB, XrayLine.La1); double mu_rhoAB = AtomConstants.MassAbsorption(energyB, zA); double mu_rhoUnkB = 0; for (int k = 0; k < elements.Length; k++) { mu_rhoUnkB += elements[k].WeightRatio * AtomConstants.MassAbsorption(energyB, elements[k].Z); } double x = mu_rhoUnkA / mu_rhoUnkB / Math.Sin(takeoff); double gx = Math.Log(1 + x) / x; double y = sigmaA / mu_rhoUnkB; double gy = Math.Log(1 + y) / y; fchGamma += 0.5 * fchCb * JA * D * mu_rhoAB / mu_rhoUnkB * (gx + gy); } } } } return(fchGamma); }
/// <summary> /// 文字列を分解して、化学組成を返す。戻り値は、Dictionary<Key, Value> で、Keyには原子番号、Valueにはモル比 /// </summary> /// <param name="compound"></param> /// <returns></returns> public static Dictionary <int, double> GetFormula(string str) { Dictionary <int, double> formula = new Dictionary <int, double>(); for (int i = 0; i < str.Length; i++) { if (str[i] >= 'A' && str[i] <= 'Z')//一文字目が大文字のとき { int z = 0; if (i + 1 < str.Length && str[i + 1] >= 'a' && str[i + 1] <= 'z')//二文字目が小文字のとき { z = AtomConstants.AtomicNumber(str.Substring(i++, 2)); } else//二文字目が小文字ではないとき { z = AtomConstants.AtomicNumber(str.Substring(i, 1)); } string numStr = ""; while (i + 1 < str.Length && str[i + 1] >= '0' && str[i + 1] <= '9')//次に続く文字が数字の時 { numStr += str[i++ + 1]; } int num = numStr == "" ? 1 : Convert.ToInt32(numStr); if (formula.ContainsKey(z)) { formula[z] += num; } else { formula.Add(z, num); } } if (str[i] == '(') //かっこの始まりが現れたら { int count = 1; for (int j = i + 1; j < str.Length; j++)//対応するかっこの終りをみつける { if (str[j] == '(') { count++; } else if (str[j] == ')') { count--; } if (count == 0)//見つかったら { Dictionary <int, double> temp = GetFormula(str.Substring(i + 1, j - i - 1)); string numStr = ""; while (j + 1 < str.Length && str[j + 1] >= '0' && str[j + 1] <= '9')// ")"のあとが数値だったら { numStr += str[j++ + 1]; } int num = numStr == "" ? 1 : Convert.ToInt32(numStr); foreach (int n in temp.Keys) { if (formula.ContainsKey(n)) { formula[n] += num * temp[n]; } else { formula.Add(n, num * temp[n]); } } i = j; break; } } } } return(formula); }