public static MatrixByArr[,] GetJ(Universe univ, Vector[] coords, List <RotableInfo> rotInfos, Func <MatrixByArr, MatrixByArr> fnInv3x3 = null) { if (fnInv3x3 == null) { fnInv3x3 = delegate(MatrixByArr A) { using (new Matlab.NamedLock("GetJ")) { return(LinAlg.Inv3x3(A)); } } } ; MatrixByArr I = GetITa(univ.atoms.ToArray(), coords); MatrixByArr invI = fnInv3x3(I); Vector R = GetRa(univ.atoms.ToArray(), coords); double M = GetMa(univ.atoms.ToArray()); Vector MR = GetMaRa(univ.atoms.ToArray(), coords); MatrixByArr MRx = GetSSMatrix(MR); MatrixByArr MRxt = MRx.Tr(); MatrixByArr III = I - (1.0 / M) * MRx * MRxt; // { MI - 1/M * [MR]x * [MR]x^t } MatrixByArr invIII = fnInv3x3(III); //Vector MMR = GetMaMaRa(univ.atoms.ToArray()); int n = univ.atoms.Count; int m = rotInfos.Count; MatrixByArr[,] J = new MatrixByArr[n, m]; for (int a = 0; a < m; a++) { RotableInfo rotInfo = rotInfos[a]; Vector Ra = GetRa(rotInfo.rotAtoms, coords); double Ma = GetMa(rotInfo.rotAtoms); Vector MaRa = GetMaRa(rotInfo.rotAtoms, coords); MatrixByArr Ia = GetITa(rotInfo.rotAtoms, coords); HDebug.Assert(rotInfo.rotAtoms.Contains(rotInfo.bondedAtom)); Vector sa = coords[rotInfo.bondedAtom.ID]; //Vector Sa = sa * rotInfos[a].rotAtoms.Length; Vector ea; { HashSet <Atom> bondatoms = new HashSet <Atom>(rotInfo.bond.atoms); bondatoms.Remove(rotInfo.bondedAtom); HDebug.Assert(bondatoms.Count == 1); HDebug.Assert(rotInfo.rotAtoms.Contains(bondatoms.First()) == false); ea = (sa - coords[bondatoms.First().ID]).UnitVector(); } Vector Aa; { Vector ea_Rasa = LinAlg.CrossProd3(ea, Ra - sa); Vector IAa = -LinAlg.MV(Ia, ea) + LinAlg.CrossProd3(Ma * R - MaRa, ea_Rasa); Aa = LinAlg.MV(invI, IAa); } { //Vector ea_MaRa_Masa = Vector.CrossProd3(ea, MaRa-Ma*sa); //Vector ea_sa = Vector.CrossProd3(ea, sa); Vector IAa = new double[3]; IAa += -LinAlg.MV(Ia, ea); IAa += LinAlg.CrossProd3(MaRa, LinAlg.CrossProd3(ea, sa)); IAa += LinAlg.CrossProd3(MR, LinAlg.CrossProd3(ea, MaRa - Ma * sa)) / M; Aa = LinAlg.MV(invIII, IAa); } Vector ta = new double[3]; { //Aa = new double[3]; // check "translational Eckart condition" only //ta += (-1/M) * Vector.CrossProd3(Aa, MMR); ta += (-1 / M) * LinAlg.CrossProd3(Aa, MR); ta += (-1 / M) * LinAlg.CrossProd3(ea, MaRa - Ma * sa); } for (int i = 0; i < n; i++) { double mi = univ.atoms[i].Mass; Vector ri = coords[univ.atoms[i].ID]; Vector Jia = new double[3]; //Jia += Vector.CrossProd3(Aa, ri*mi); Jia += LinAlg.CrossProd3(Aa, ri); Jia += ta; J[i, a] = Jia.ToColMatrix(); } foreach (Atom ira in rotInfo.rotAtoms) { int i = ira.ID; Vector ri = coords[univ.atoms[i].ID]; Vector Jia = LinAlg.CrossProd3(ea, ri - sa); J[i, a] += Jia.ToColMatrix(); } //if(Debug.IsDebuggerAttached) //{ // // check Eckart condition // // http://en.wikipedia.org/wiki/Eckart_conditions // ////////////////////////////////////////////////////////////////////// // // 1. translational Eckart condition // // sum{i=1..n}{mi * Jia} = 0 // Vector mJ = EckartConditionTrans(univ, J, a); // Debug.AssertTolerance(0.00000001, mJ); // // 2. rotational Eckart condition // // sum{i=1..n}{mi * r0i x Jia} = 0, // // where 'x' is the cross product // Vector mrJ = EckartConditionRotat(univ, coords, J, a); // Debug.AssertTolerance(0.00000001, mrJ); //} } return(J); }
//public static Vector GetAa(Vector ea, Vector R, Vector Ra, Vector sa, double Ma, Matrix invI, Matrix Ia) //{ // Vector ea_Rasa = Vector.CrossProd3(ea, Ra-sa); // Vector IAa = -Vector.MV(Ia, ea) + Ma * Vector.CrossProd3(R-Ra, ea_Rasa); // Vector Aa = Vector.MV(invI, IAa); // return Aa; //} //public static Vector GetTa(Vector Aa, Vector ea, Vector R, double M, double Ma, Vector Ra, Vector sa) //{ // Vector ta = /*-Vector.CrossProd3(ea, R)*/ - (Ma/M) * Vector.CrossProd3(ea, Ra-sa); // return ta; //} //public static Matrix GetSSMatrix(Vector v) //{ // Debug.Assert(v.Size == 3); // Matrix SS = new double[3, 3]{{ 0, -v[2], v[1] }, // { v[2], 0, -v[0] }, // { -v[1], v[0], 0 }}; // return SS; //} public static MatrixByArr[,] GetJ(Universe univ, Vector[] coords, List <RotableInfo> rotInfos) { double M = GetMa(univ.atoms.ToArray()); Vector R = GetRa(univ.atoms.ToArray(), coords, M); MatrixByArr I = GetITa(univ.atoms.ToArray(), coords, R); MatrixByArr invI = LinAlg.Inv3x3(I); int n = univ.atoms.Count; int m = rotInfos.Count; MatrixByArr[,] J = new MatrixByArr[n, m]; for (int a = 0; a < m; a++) { RotableInfo rotInfo = rotInfos[a]; double Ma = GetMa(rotInfo.rotAtoms); Vector Ra = GetRa(rotInfo.rotAtoms, coords, Ma); MatrixByArr Ia = GetITa(rotInfo.rotAtoms, coords, Ra); HDebug.Assert(rotInfo.rotAtoms.Contains(rotInfo.bondedAtom)); Vector sa = coords[rotInfo.bondedAtom.ID]; //Vector Sa = sa * rotInfos[a].rotAtoms.Length; Vector ea; { HashSet <Atom> bondatoms = new HashSet <Atom>(rotInfo.bond.atoms); bondatoms.Remove(rotInfo.bondedAtom); HDebug.Assert(bondatoms.Count == 1); HDebug.Assert(rotInfo.rotAtoms.Contains(bondatoms.First()) == false); ea = (sa - coords[bondatoms.First().ID]).UnitVector(); } Vector Aa; { Vector IAa = -LinAlg.MV(Ia, ea) + Ma * LinAlg.CrossProd3(R - Ra, LinAlg.CrossProd3(ea, Ra - sa)); Aa = LinAlg.MV(invI, IAa); } Vector ta; { ta = -LinAlg.CrossProd3(Aa, R) - (Ma / M) * LinAlg.CrossProd3(ea, Ra - sa); } for (int i = 0; i < n; i++) { double mi = univ.atoms[i].Mass; Vector ri = coords[univ.atoms[i].ID]; Vector Jia = new double[3]; Jia += LinAlg.CrossProd3(Aa, ri); Jia += ta; J[i, a] = Jia.ToColMatrix(); } foreach (Atom ira in rotInfo.rotAtoms) { int i = ira.ID; Vector ri = coords[univ.atoms[i].ID]; Vector Jia = LinAlg.CrossProd3(ea, ri - sa); J[i, a] += Jia.ToColMatrix(); } //if(Debug.IsDebuggerAttached) //{ // // check Eckart condition // // http://en.wikipedia.org/wiki/Eckart_conditions // ////////////////////////////////////////////////////////////////////// // // 1. translational Eckart condition // // sum{i=1..n}{mi * Jia} = 0 // Vector mJ = new double[3]; // for(int i=0; i<n; i++) // { // double mi = univ.atoms[i].Mass; // Vector Jia = J[i, a].ToVector(); // mJ += mi * Jia; // } // Debug.AssertTolerance(0.00000001, mJ); // ////////////////////////////////////////////////////////////////////// // // 1. rotational Eckart condition // // sum{i=1..n}{mi * r0i x Jia} = 0, // // where 'x' is the cross product // Vector mrJ = new double[3]; // for(int i=0; i<n; i++) // { // double mi = univ.atoms[i].Mass; // Vector ri = coords[univ.atoms[i].ID]; // Vector Jia = J[i, a].ToVector(); // mrJ += mi * Vector.CrossProd3(ri, Jia); // } // Debug.AssertTolerance(0.00000001, mrJ); //} } return(J); }
public unsafe static MatrixByArr GetJ(Universe univ, Vector[] coords, List <RotableInfo> rotInfos) { HDebug.Assert(rotInfos.ListMolecule().HUnion().Length == 1); Dictionary <Universe.Molecule, Dictionary <string, object> > moleMRI = new Dictionary <Universe.Molecule, Dictionary <string, object> >(); int n = univ.atoms.Count; int m = rotInfos.Count; MatrixByArr J = new double[3 * n, m]; double[] _Ja = new double[3 * n]; for (int a = 0; a < m; a++) { var mole = rotInfos[a].mole; if (moleMRI.ContainsKey(rotInfos[a].mole) == false) { double _M = 0; Vector _R = new double[3]; Vector _MR = new double[3]; MatrixByArr _I = new double[3, 3]; GetMaRaMaraITa(mole.atoms.ToArray(), coords, ref _M, ref _R, ref _MR, ref _I); MatrixByArr _invI = LinAlg.Inv3x3(_I); MatrixByArr _MRx = GetSSMatrix(_MR); MatrixByArr _MRxt = _MRx.Tr(); MatrixByArr _III = _I - (1.0 / _M) * _MRx * _MRxt; // { MI - 1/M * [MR]x * [MR]x^t } MatrixByArr _invIII = LinAlg.Inv3x3(_III); moleMRI.Add(mole, new Dictionary <string, object>()); moleMRI[mole].Add("invI", _invI); moleMRI[mole].Add("invIII", _invIII); moleMRI[mole].Add("MR", _MR); moleMRI[mole].Add("R", _R); moleMRI[mole].Add("M", _M); } MatrixByArr invI = moleMRI[mole]["invI"] as MatrixByArr; MatrixByArr invIII = moleMRI[mole]["invIII"] as MatrixByArr; Vector MR = moleMRI[mole]["MR"] as Vector; Vector R = moleMRI[mole]["R"] as Vector; double M = (double)(moleMRI[mole]["M"]); RotableInfo rotInfo = rotInfos[a]; double Ma = 0; Vector Ra = new double[3]; Vector MaRa = new double[3]; MatrixByArr Ia = new double[3, 3]; GetMaRaMaraITa(rotInfo.rotAtoms, coords, ref Ma, ref Ra, ref MaRa, ref Ia); HDebug.Assert(rotInfo.rotAtoms.Contains(rotInfo.bondedAtom)); Vector sa = coords[rotInfo.bondedAtom.ID]; Vector ea; { Atom bondatom = null; HDebug.Assert(rotInfo.bond.atoms.Length == 2); if (rotInfo.bond.atoms[0] == rotInfo.bondedAtom) { bondatom = rotInfo.bond.atoms[1]; } else { bondatom = rotInfo.bond.atoms[0]; } HDebug.Assert(rotInfo.rotAtoms.Contains(bondatom) == false); ea = (sa - coords[bondatom.ID]).UnitVector(); } Vector Aa; { Vector ea_Rasa = LinAlg.CrossProd3(ea, Ra - sa); Vector IAa = -LinAlg.MV(Ia, ea) + LinAlg.CrossProd3(Ma * R - MaRa, ea_Rasa); Aa = LinAlg.MV(invI, IAa); } { //Vector ea_MaRa_Masa = Vector.CrossProd3(ea, MaRa-Ma*sa); //Vector ea_sa = Vector.CrossProd3(ea, sa); Vector IAa = new double[3]; IAa += -LinAlg.MV(Ia, ea); IAa += LinAlg.CrossProd3(MaRa, LinAlg.CrossProd3(ea, sa)); IAa += LinAlg.CrossProd3(MR, LinAlg.CrossProd3(ea, MaRa - Ma * sa)) / M; Aa = LinAlg.MV(invIII, IAa); } Vector ta = new double[3]; { //Aa = new double[3]; // check "translational Eckart condition" only //ta += (-1/M) * Vector.CrossProd3(Aa, MMR); ta += (-1 / M) * LinAlg.CrossProd3(Aa, MR); ta += (-1 / M) * LinAlg.CrossProd3(ea, MaRa - Ma * sa); } fixed(double *Ja = _Ja) { //for(int i=0; i<n; i++) foreach (Atom iaa in mole.atoms) { int i = iaa.ID; double mi = univ.atoms[i].Mass; Vector ri = coords[univ.atoms[i].ID]; Vector Jia = new double[3]; //Jia += Vector.CrossProd3(Aa, ri*mi); Jia += LinAlg.CrossProd3(Aa, ri); Jia += ta; //J[i, a] = Jia.ToColMatrix(); Ja[i * 3 + 0] = Jia[0]; Ja[i * 3 + 2] = Jia[2]; Ja[i * 3 + 1] = Jia[1]; } foreach (Atom ira in rotInfo.rotAtoms) { int i = ira.ID; Vector ri = coords[univ.atoms[i].ID]; Vector Jia = LinAlg.CrossProd3(ea, ri - sa); //J[i, a] += Jia.ToColMatrix(); Ja[i * 3 + 0] += Jia[0]; Ja[i * 3 + 1] += Jia[1]; Ja[i * 3 + 2] += Jia[2]; } //for(int i=0; i<n; i++) foreach (Atom iaa in mole.atoms) { int i = iaa.ID; J[i * 3 + 0, a] = Ja[i * 3 + 0]; J[i * 3 + 1, a] = Ja[i * 3 + 1]; J[i * 3 + 2, a] = Ja[i * 3 + 2]; } } if (HDebug.IsDebuggerAttached) { // check Eckart condition // http://en.wikipedia.org/wiki/Eckart_conditions ////////////////////////////////////////////////////////////////////// // 1. translational Eckart condition // sum{i=1..n}{mi * Jia} = 0 Vector mJ = new double[3]; //for(int i=0; i<n; i++) foreach (Atom iaa in mole.atoms) { int i = iaa.ID; double mi = univ.atoms[i].Mass; //Vector Jia = J[i, a].ToVector(); Vector Jia = new double[3] { J[i * 3 + 0, a], J[i * 3 + 1, a], J[i * 3 + 2, a] }; mJ += mi * Jia; } HDebug.AssertTolerance(0.00000001, mJ); ////////////////////////////////////////////////////////////////////// // 1. rotational Eckart condition // sum{i=1..n}{mi * r0i x Jia} = 0, // where 'x' is the cross product Vector mrJ = new double[3]; //for(int i=0; i<n; i++) foreach (Atom iaa in mole.atoms) { int i = iaa.ID; double mi = univ.atoms[i].Mass; Vector ri = coords[univ.atoms[i].ID]; //Vector Jia = J[i, a].ToVector(); Vector Jia = new double[3] { J[i * 3 + 0, a], J[i * 3 + 1, a], J[i * 3 + 2, a] }; mrJ += mi * LinAlg.CrossProd3(ri, Jia); } HDebug.AssertTolerance(0.0000001, mrJ); } } return(J); }