示例#1
0
                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);
                }
示例#2
0
                //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);
                }
示例#3
0
                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);
                }