Beispiel #1
0
            public static void Compute(Vector[] coords, out double energy, out double forceij, out double springij, double epsij, double rmin)
            {
                /// !V(Lennard-Jones) = Eps,i,j[(Rmin,i,j/ri,j)**12 - 2(Rmin,i,j/ri,j)**6]
                /// !epsilon: kcal/mole, Eps,i,j = sqrt(eps,i * eps,j)
                /// !Rmin/2: A, Rmin,i,j = Rmin/2,i + Rmin/2,j
                ///
                /// V(r) =           epsij * r0^12 * rij^-12         -        2 * epsij * r0^6 * rij^-6
                ///      =           epsij * (r0  /  rij)^12         -        2 * epsij * (r0  / rij)^6
                /// F(r) =     -12 * epsij * r0^12 * rij^-13         -     -6*2 * epsij * r0^6 * rij^-7
                ///      =     -12 * epsij * (r0  /  rij)^12 / rij   -     -6*2 * epsij * (r0  / rij)^6 / rij
                /// K(r) = -13*-12 * epsij * r0^12 * rij^-14         -  -7*-6*2 * epsij * r0^6 * rij^-8
                ///      = -13*-12 * epsij * (r0  /  rij)^12 / rij^2 -  -7*-6*2 * epsij * (r0  / rij)^6 / rij^2
                double rij         = (coords[1] - coords[0]).Dist;
                double rij2        = rij * rij;
                double rmin_rij    = rmin / rij;
                double rmin_rij_2  = rmin_rij * rmin_rij;
                double rmin_rij_6  = rmin_rij_2 * rmin_rij_2 * rmin_rij_2;
                double rmin_rij_12 = rmin_rij_6 * rmin_rij_6;

                energy   = epsij * rmin_rij_12 - 2 * epsij * rmin_rij_6;
                forceij  = (-12) * epsij * rmin_rij_12 / rij - (-6 * 2) * epsij * rmin_rij_6 / rij;
                springij = (-13 * -12) * epsij * rmin_rij_12 / rij2 - (-7 * -6 * 2) * epsij * rmin_rij_6 / rij2;
                HDebug.AssertIf(forceij > 0, rmin < rij); // positive force => attractive
                HDebug.AssertIf(forceij < 0, rij < rmin); // negative force => repulsive
            }
Beispiel #2
0
 public Nonbonded FindNonbonded(string type0, ITextLogger logger)
 {
     if (_FindNonbonded.ContainsKey(type0) == false)
     {
         Nonbonded found = null;
         foreach (Nonbonded nonbonded in nonbondeds)
         {
             if (nonbonded.types[0] == type0)
             {
                 if (found != null)
                 {
                     bool writelog = ((found.epsilon != nonbonded.epsilon) ||
                                      (found.Rmin2 != nonbonded.Rmin2) ||
                                      (found.eps_14 != nonbonded.eps_14) ||
                                      (found.Rmin2_14 != nonbonded.Rmin2_14));
                     if (writelog)
                     {
                         logger.Log(string.Format("Nonbonded params of {0}-(eps {1}, rmin2 {2}, esp_14 {3}, rmin2_14 {4}) is replaced to ({5}, {6}, {7}, {8})",
                                                  type0, found.epsilon, found.Rmin2, found.eps_14, found.Rmin2_14,
                                                  nonbonded.epsilon, nonbonded.Rmin2, nonbonded.eps_14, nonbonded.Rmin2_14));
                     }
                 }
                 found = nonbonded;
             }
         }
         HDebug.Assert(found != null);
         HDebug.AssertIf(double.IsNaN(found.Rmin2) == false, found.Rmin2 > 0);
         HDebug.AssertIf(double.IsNaN(found.Rmin2_14) == false, found.Rmin2_14 > 0);
         _FindNonbonded.Add(type0, found);
     }
     return(_FindNonbonded[type0]);
 }
Beispiel #3
0
            public static void Compute(Vector[] coords, out double energy, out double force01, out double spring01, double Kb, double b0)
            {
                /// BONDS
                /// !V(bond) = Kb(b - b0)**2
                ///
                ///      p0 ---------- p1
                ///     (+) --→   ←-- (+)
                /// ←-- (-)           (-) --→
                ///
                ///     V        = Kb ( b - b0 ) ^ 2
                ///   d_V / d_b  = 2 Kb ( b - b0 )
                ///  d2_V / d_b2 = 2 Kb
                ///
                ///     b        = b1 + t
                ///   d_b / d_t  = 1
                ///  d2_b / d_t2 = 0
                ///
                /// energy = V
                ///        = Kb ( b - b0 ) ^ 2
                ///
                /// force  = d_V / d_t
                ///        = {d_V / d_b      } * {d_b / d_t}
                ///        = {2 Kb ( b - b0 )} * { 1       }
                ///        =  2 Kb ( b - b0 )
                ///
                /// spring = d_V2 / d2_t
                ///        = d_(d_V / d_t) / d_t
                ///        = d_({d_V / d_b } * {d_b / d_t}) / d_t
                ///        =   {d_{d_V / d_b } / d_t}        *      {d_b / d_t}
                ///          +    {d_V / d_b }               *   {d_{d_b / d_t} / d_t}
                ///        =     {d2_V / d_b2}*{d_b / d_t}   *      {d_b / d_t}
                ///          +    {d_V / d_b }               *     {d2_b / d_t2}
                ///        = {d2_V / d_b2}*{d_b / d_t}*{d_b / d_t}      +      {d_V / d_b    }*{d2_b / d_t2}
                ///        = {2 Kb       }*{ 1       }*{ 1       }      +      {2 Kb (b - b0)}*{ 0         }
                ///        =  2 Kb
                ///////////////////////////////////////////////////////////////////////////////
                Vector pos1 = coords[0];
                Vector pos2 = coords[1];
                double b    = (pos1 - pos2).Dist;

                HDebug.Assert(b != 0, double.IsNaN(b) == false, double.IsInfinity(b) == false);
                energy   = Kb * (b - b0) * (b - b0);
                force01  = 2 * Kb * (b - b0);
                spring01 = 2 * Kb;
                HDebug.AssertIf(force01 > 0, b0 < b); // positive force => attractive
                HDebug.AssertIf(force01 < 0, b < b0); // negative force => repulsive
            }
Beispiel #4
0
            public static void Compute(Vector[] coords, out double energy, out double forceij, out double springij, double pchij, double ee)
            {
                /// !V(Lennard-Jones) = Eps,i,j[(Rmin,i,j/ri,j)**12 - 2(Rmin,i,j/ri,j)**6]
                /// !epsilon: kcal/mole, Eps,i,j = sqrt(eps,i * eps,j)
                /// !Rmin/2: A, Rmin,i,j = Rmin/2,i + Rmin/2,j
                ///
                /// V(rij) =           (332 * pchij / ee) * rij^-1
                /// F(rij) = (   -1) * (332 * pchij / ee) * rij^-2
                /// K(rij) = (-2*-1) * (332 * pchij / ee) * rij^-3
                double rij  = (coords[1] - coords[0]).Dist;
                double rij2 = rij * rij;
                double rij3 = rij * rij2;

                energy   = (332 * pchij / ee) / rij;
                forceij  = (-1) * (332 * pchij / ee) / rij2;
                springij = (-2 * -1) * (332 * pchij / ee) / rij3;
                HDebug.AssertIf(forceij > 0, pchij < 0); // positive force => attractive
                HDebug.AssertIf(forceij < 0, pchij > 0); // negative force => repulsive
            }
Beispiel #5
0
        public static void GetBFactor(Top topol, Eigenvec eigenvec, out string[] name, out int[] resSeq, out double[] BFactor
                                      , bool ignoreNegativeEigval = true
                                      )
        {
            List <Gromacs.Top.Atom> atoms = topol.GetAtoms();

            name    = new string[atoms.Count];
            resSeq  = new int[atoms.Count];
            BFactor = new double[atoms.Count];
            for (int i = 0; i < atoms.Count; i++)
            {
                name[i]   = atoms[i].atom;
                resSeq[i] = atoms[i].resnr;

                int count_lambda_0 = 0;
                foreach (var frame in eigenvec.frames)
                {
                    if (frame.lambda != 0)
                    {
                        continue;
                    }
                    if (frame.step <= 6)
                    {
                        HDebug.Assert(frame.step == frame.frameidx);
                        continue;
                    }
                    count_lambda_0++;
                    Vector[] eigvec = frame.x;
                    double   eigval = frame.time;
                    HDebug.AssertIf(eigval < 0, Math.Abs(eigval) < 0.00001);
                    if (ignoreNegativeEigval)
                    {
                        if (eigval < 0)
                        {
                            continue;
                        }
                    }
                    HDebug.Assert(BFactor.Length == eigvec.Length);
                    BFactor[i] += LinAlg.VtV(eigvec[i], eigvec[i]) / eigval;
                }
            }
        }
Beispiel #6
0
        public static int[] ListBondedDistFrom(this IList <Atom> atoms, IList <Atom> froms)
        {
            // build graph
            Graph <Atom, Bond> bondedgraph = atoms.BuildBondedGraph();

            // build dijkstra
            Graph <Atom, Bond> .Dijkstra.Elem[] elems;
            {
                Dictionary <Graph <Atom, Bond> .Node, double> source2initdist = new Dictionary <Graph <Atom, Bond> .Node, double>();
                foreach (var from in froms)
                {
                    Graph <Atom, Bond> .Node fromnode = bondedgraph.GetNode(from);
                    source2initdist.Add(fromnode, 0);
                }
                Dictionary <Graph <Atom, Bond> .Edge, double> edge_dist = new Dictionary <Graph <Atom, Bond> .Edge, double>();
                foreach (var edge in bondedgraph.Edges)
                {
                    edge_dist.Add(edge, 1);
                }
                elems = Graph <Atom, Bond> .Dijkstra.BuildMinSum(bondedgraph, source2initdist, edge_dist, IsTarget : null);
            }

            // build distances
            int[] dists;
            {
                int maxdist = -1;
                dists = new int[atoms.Count];
                for (int i = 0; i < atoms.Count; i++)
                {
                    Atom atom = atoms[i];
                    var  node = bondedgraph.GetNode(atom);
                    var  path = Graph.Dijkstra.GetPathNode(elems, node);
                    dists[i] = path.Length - 1; // this include "CA" atom, and the distance of "CA" itself is 0.
                    HDebug.Assert(dists[i] >= 0);
                    HDebug.AssertIf(atom.AtomName.Trim() == "CA", dists[i] == 0);
                    maxdist = Math.Max(maxdist, dists[i]);
                }
            }

            return(dists);
        }
Beispiel #7
0
            public static ValueTuple <double, double> GetFijKij(double a, double b, double c, double K0, double T0, double fij_sign = +1, double kij_sign0 = +1, double kij_sign1 = +1)
            {
                ///   +
                ///   |\
                ///   | \
                /// a |  \ c
                ///   |   \
                ///   |T   \
                ///   +-----+
                ///      b
                ///
                /// V                   =   K0 (T - T0)^2
                /// F =           dV/dT = 2 K0 (T - T0)
                /// K = (d^2 V)/(d T^2) = 2 K0
                /// return {  dV/dc,  (d^2 V)/(d c^2)  }
                double a2 = a * a;
                double b2 = b * b;
                double c2 = c * c; double c4 = c2 * c2;
                double ab = a * b;  double ab2 = ab * ab;

                double T       = acos((a2 + b2 - c2) / (2 * ab));                                         // θ               = acos⁡((a^2+b^2-c^2)/2ab)
                double V       = K0 * (T - T0) * (T - T0);                                                // V               =  K0 ( θ - θ0 )^2
                double dV_dT   = 2 * K0 * (T - T0);                                                       // ∂V/∂θ           = 2K0 ( θ - θ0 )
                double d2V_dT2 = 2 * K0;                                                                  // (∂^2 V)/(∂θ^2 ) = 2K0
                double dT_dc   = 2 * c / sqrt((4 * ab2) - pow(a2 + b2 - c2, 2));                          // ∂θ/∂c           = 2c/√((2ab)^2-(a^2+b^2-c^2 )^2 )
                double d2T_dc2 = 2 * (c4 - pow(a2 - b2, 2)) / pow((4 * ab2) - pow(a2 + b2 - c2, 2), 1.5); // (∂^2 θ)/(∂c^2 ) = 2(c^4-(a^2-b^2 )^2 )/((2ab)^2-(a^2+b^2-c^2 )^2 )^1.5
                double dV_dc   = 2 * K0 * (T - T0) * 2 * c / sqrt((4 * ab2) - pow(a2 + b2 - c2, 2));      // ∂V/∂c           = 2K0(θ-θ0 ) ⋅ 2c/√((2ab)^2-(a^2+b^2-c^2 )^2 )
                double d2V_dc2 = kij_sign0 * (2 * K0 * 4 * c2 / ((4 * ab2) - pow(a2 + b2 - c2, 2)))       // (∂^2 V)/(∂c^2 ) = {2K_0⋅(4c^2)/((2ab)^2-(a^2+b^2-c^2 )^2 )}
                                 + kij_sign1 * (2 * K0 * (T - T0) * 2 * (c4 - pow(a2 - b2, 2))            //                 + {2K_0 (θ-θ_0 )⋅2(c^4-(a^2-b^2 )^2 )
                                                / pow((4 * ab2) - pow(a2 + b2 - c2, 2), 1.5)              //                    /((2ab)^2-(a^2+b^2-c^2 )^2 )^1.5 }
                                                );
                double fij = dV_dc;
                double kij = d2V_dc2;

                HDebug.AssertIf(fij > 0, T0 < T); // positive force => attractive
                HDebug.AssertIf(fij < 0, T < T0); // negative force => repulsive
                return(new ValueTuple <double, double>(fij, kij));
            }
Beispiel #8
0
        static double GetPotentialUpdated_ProbToCheckWithGetPotential = 0;//1;//0.1;
        public double GetPotentialUpdated(List <ForceField.IForceField> frcflds
                                          , double?energy0, Vector[] coords0, Vector[] forces0
                                          , Vector[] coords, Vector[] forces
                                          , ref Nonbondeds_v1 nonbondeds
                                          )
        {
            if (GetPotentialUpdated_SelfTestDo == true)
            #region selftest
            {
                GetPotentialUpdated_SelfTest(frcflds, energy0, coords0, forces0, coords, forces);
            }
            #endregion

            bool[] updated = new bool[size];
            if ((energy0 == null) || (nonbondeds == null))
            {
                HDebug.AssertIf(energy0 == null, coords0 == null);
                HDebug.AssertIf(energy0 == null, forces0 == null);
                energy0 = 0;
                coords0 = null;
                forces0 = null;
                for (int i = 0; i < size; i++)
                {
                    forces[i] = new double[3];
                }
                for (int i = 0; i < size; i++)
                {
                    updated[i] = true;
                }
            }
            else
            {
                HDebug.Assert(size == coords0.Length);
                HDebug.Assert(size == forces0.Length);
                HDebug.Assert(size == coords.Length);
                HDebug.Assert(size == forces.Length);
                for (int i = 0; i < size; i++)
                {
                    forces[i] = forces0[i].Clone();
                }

                int countskip = 0;
                //double[] dist2s = new double[size];
                //for(int i=0; i<size; i++)
                //    dist2s[i] = (coords0[i] - coords[i]).Dist2;
                //int[] idxsorted = dist2s.IdxSorted();
                //for(int i=0; i<size; i++)
                //    updated[i] = (dist2s[i] > (0.000001*0.000001));
                //for(int i=size/2; i<size; i++)
                //    updated[idxsorted[i]] = true;
                for (int i = 0; i < size; i++)
                {
                    updated[i] = (coords0[i] != coords[i]);
                }
                for (int i = 0; i < size; i++)
                {
                    countskip += (updated[i] == false) ? 1 : 0;
                }
                if ((size - countskip) * 10 > size)
                {
                    energy0 = 0;
                    coords0 = null;
                    forces0 = null;
                    for (int i = 0; i < size; i++)
                    {
                        forces[i] = new double[3];
                    }
                    for (int i = 0; i < size; i++)
                    {
                        updated[i] = true;
                    }
                }
                System.Console.Write(" countskip({0:000}) ", countskip);
            }
            Vector[] dforces = GetVectorsZero();

            double denergy = 0;
            denergy += GetPotentialUpdated_ComputeCustomsBond(frcflds, updated, 0, coords0, coords, dforces);
            denergy += GetPotentialUpdated_ComputeCustomsAngle(frcflds, updated, 0, coords0, coords, dforces);
            denergy += GetPotentialUpdated_ComputeCustomsDihedral(frcflds, updated, 0, coords0, coords, dforces);
            denergy += GetPotentialUpdated_ComputeCustomsImproper(frcflds, updated, 0, coords0, coords, dforces);
            denergy += GetPotentialUpdated_ComputeCustomsNonbonded(frcflds, updated, 0, coords0, coords, dforces, ref nonbondeds);
            //energy += GetPotentialUpdated_ComputeCustomsCustoms  (frcflds, updated, 0, coords0, forces0, coords, forces);

            double energy = energy0.Value + denergy;
            for (int i = 0; i < size; i++)
            {
                forces[i] += dforces[i];
            }

            #region commented from threading
            //Nonbondeds lnonbondeds = nonbondeds;
            //
            //double energy = energy0.Value;
            //
            //object lockobj = new object();
            //System.Threading.Tasks.ParallelOptions parallelOptions = new ParallelOptions();
            ////parallelOptions.MaxDegreeOfParallelism = 1;
            //Parallel.ForEach(compunits_bonded, parallelOptions, delegate(GetForcesCompUnit compunit)
            //{
            //    if(compunit == null)
            //    {
            //        // in the first iteration, collect nonbonded components
            //        GetForces_CollectCompUnitNonbonded(frcflds, updated, coords0, coords, ref lnonbondeds, compunits_nonbonded);
            //    }
            //    else
            //    {
            //        Triple<double, int[], Vector[]> denergy_idx_dforces = compunit.Compute(coords0, coords);
            //        double   denergy = denergy_idx_dforces.first;
            //        int[]    idx     = denergy_idx_dforces.second;
            //        Vector[] dforces = denergy_idx_dforces.third;
            //        Debug.Assert(idx.Length == dforces.Length);
            //        lock(lockobj)
            //        {
            //            energy += denergy;
            //            for(int i=0; i<idx.Length; i++)
            //                forces[idx[i]] += dforces[i];
            //        }
            //    }
            //});
            //nonbondeds = lnonbondeds;
            //Parallel.ForEach(compunits_nonbonded, parallelOptions, delegate(GetForcesCompUnit compunit)
            //{
            //    Triple<double, int[], Vector[]> denergy_idx_dforces = compunit.Compute(coords0, coords);
            //    double   denergy = denergy_idx_dforces.first;
            //    int[]    idx     = denergy_idx_dforces.second;
            //    Vector[] dforces = denergy_idx_dforces.third;
            //    Debug.Assert(idx.Length == dforces.Length);
            //    lock(lockobj)
            //    {
            //        energy += denergy;
            //        for(int i=0; i<idx.Length; i++)
            //            forces[idx[i]] += dforces[i];
            //    }
            //});
            #endregion

            if (HDebug.IsDebuggerAttachedWithProb(GetPotentialUpdated_ProbToCheckWithGetPotential))
            #region check force with GetPotential(...)
            {
                //Vector[] _forces0  = GetVectorsZero();
                //Matrix   _hessian0 = null;
                //double   _energy0  = GetPotential(frcflds, coords0, ref _forces0, ref _hessian0, new Dictionary<string,object>());
                //Debug.AssertTolerance(0.00000001, energy0 - _energy0);
                //Debug.AssertTolerance(0.00000001, Vector.Sub(forces0, _forces0));

                Vector[]    _forces  = GetVectorsZero();
                MatrixByArr _hessian = null;
                double      _energy  = GetPotential(frcflds, coords, ref _forces, ref _hessian, new Dictionary <string, object>());
                HDebug.AssertTolerance(0.00000001, energy - _energy);
                HDebug.AssertToleranceVector(0.00000001, Vector.Sub(forces, _forces));
            }
            #endregion

            //if(cache != null)
            //{
            //    if(cache.ContainsKey("energy_bonds     ") == false) cache.Add("energy_bonds     ", 0); cache["energy_bonds     "] = energy_bonds     ;
            //    if(cache.ContainsKey("energy_angles    ") == false) cache.Add("energy_angles    ", 0); cache["energy_angles    "] = energy_angles    ;
            //    if(cache.ContainsKey("energy_dihedrals ") == false) cache.Add("energy_dihedrals ", 0); cache["energy_dihedrals "] = energy_dihedrals ;
            //    if(cache.ContainsKey("energy_impropers ") == false) cache.Add("energy_impropers ", 0); cache["energy_impropers "] = energy_impropers ;
            //    if(cache.ContainsKey("energy_nonbondeds") == false) cache.Add("energy_nonbondeds", 0); cache["energy_nonbondeds"] = energy_nonbondeds;
            //    if(cache.ContainsKey("energy_customs   ") == false) cache.Add("energy_customs   ", 0); cache["energy_customs   "] = energy_customs   ;
            //}
            return(energy);
        }
Beispiel #9
0
            public static void Compute(Vector[] coords, out double energy, out double force02, out double spring02,
                                       double Ktheta, double Theta0, double Kub, double S0)
            {
                Func <double, double>         sqrt = Math.Sqrt;
                Func <double, double>         acos = Math.Acos;
                Func <double, double, double> pow  = Math.Pow;
                /// ANGLES
                /// !V(angle) = Ktheta(Theta - Theta0)**2
                /// !V(Urey-Bradley) = Kub(S - S0)**2          // ignore this term here...
                ///
                ///             p1
                ///            /θ \ 
                ///           /    \ 
                ///          b      c
                ///         /        \ 
                ///        /          \ 
                ///      p0 ----a----- p2
                ///     (+) --→   ←-- (+)
                /// ←-- (-)           (-) --→
                ///
                ///     V        =   Kθ ( θ - θ0 ) ^ 2
                ///   d_V / d_θ  = 2 Kθ ( θ - θ0 )
                ///  d2_V / d_θ2 = 2 Kθ
                ///
                ///     θ        = acos( (b^2 + c^2 - a^2)/(2*b*c) )
                ///              = acos( (b2  + c2  - a2 )/(2*b*c) )
                ///              = acos( cosθ )                        ⇐ cosθ = (b^2 + c^2 - a^2)/(2*b*c)
                ///   d_θ / d_a  = a / (b c sqrt(1 - cosθ2))           ⇐ cosθ2 = cosθ * cosθ
                ///  d2_θ / d_a2 = {a2/(b2 c2)} * {-cosθ / sqrt(1 - cosθ2)^3} + {1/(b c sqrt(1 - cosθ2))}
                ///
                /// energy = V
                /// force  = d_V / d_a
                ///        = {d_V / d_θ} * {d_θ / d_a}
                /// spring = d_V2 / d2_a
                ///        = d_(d_V / d_a) / d_a
                ///        = d_({d_V / d_θ } * {d_θ / d_a}) / d_a
                ///        =   {d_{d_V / d_θ } / d_a}        *      {d_θ / d_a}
                ///          +    {d_V / d_θ }               *   {d_{d_θ / d_a} / d_a}
                ///        =     {d2_V / d_θ2}*{d_θ / d_a}   *      {d_θ / d_a}
                ///          +    {d_V / d_θ }               *     {d2_θ / d_a2}
                ///        = {d2_V / d_θ2}*{d_θ / d_a}*{d_θ / d_a}      +      {d_V / d_θ}*{d2_θ / d_a2}
                ///////////////////////////////////////////////////////////////////////////////
                Vector p0 = coords[0];
                Vector p1 = coords[1];
                Vector p2 = coords[2];
                double a = (p0 - p2).Dist; double a2 = a * a;
                double b = (p0 - p1).Dist; double b2 = b * b;
                double c = (p1 - p2).Dist; double c2 = c * c;
                double KA = Ktheta;
                double A0 = Theta0;
                double cosA = (b2 + c2 - a2) / (2 * b * c); double cosA2 = cosA * cosA;
                double A       = acos(cosA);
                double dA_da   = a / (b * c * sqrt(1 - cosA2));
                double d2A_da2 = (a2 / (b2 * c2)) * (-cosA / pow(sqrt(1 - cosA2), 3)) + (1 / (b * c * sqrt(1 - cosA2)));
                double V       = KA * (A - A0) * (A - A0);
                double dV_dA   = 2 * KA * (A - A0);
                double d2V_dA2 = 2 * KA;

                energy   = V;
                force02  = dV_dA * dA_da;
                spring02 = d2V_dA2 * dA_da * dA_da + dV_dA * d2A_da2;
                HDebug.AssertIf(force02 > 0, A0 < A); // positive force => attractive
                HDebug.AssertIf(force02 < 0, A < A0); // negative force => repulsive
            }
Beispiel #10
0
            public static Universe Build(Tinker.Xyz xyz, Tinker.Prm prm, Pdb pdb
                                         , double?tolCoordPdbXyz // 0.002 for default distance
                                                                 //    (0.001 * sqrt(3) = 0.0017321, which is the largest tolerance between pdb and xyz)
                                                                 // null  for not ordering by distance;
                                         )
            {
                Universe univ = new Universe();

                Dictionary <int, Prm.Atom>                            prm_id2atom      = prm.atoms.ToIdDictionary();
                Dictionary <int, Prm.Vdw>                             prm_cls2vdw      = prm.vdws.ToClassDictionary();
                Dictionary <int, Prm.Vdw14>                           prm_cls2vdw14    = prm.vdw14s.ToClassDictionary();
                Dictionary <Tuple <int, int>, Prm.Bond>               prm_cls2bond     = prm.bonds.ToClassDictionary();
                Dictionary <Tuple <int, int, int>, Prm.Angle>         prm_cls2angle    = prm.angles.ToClassDictionary();
                Dictionary <Tuple <int, int, int>, Prm.Ureybrad>      prm_cls2ureybrad = prm.ureybrads.ToClassDictionary();
                Dictionary <Tuple <int, int, int, int>, Prm.Improper> prm_cls2improper = prm.impropers.ToClassDictionary();
                Dictionary <Tuple <int, int, int, int>, Prm.Torsion>  prm_cls2torsion  = prm.torsions.ToClassDictionary();
                Dictionary <int, Prm.Charge>                          prm_id2charge    = prm.charges.ToIdDictionary();

                Prm.Biotype[] prm_biotypes = prm.biotypes;

                Xyz.Atom[] xyz_atoms = xyz.atoms;
                Pdb.Atom[] pdb_atoms = (pdb != null) ? pdb.atoms : null;
                Dictionary <int, Xyz.Atom> xyz_id2atom = xyz_atoms.ToIdDictionary();

                KDTree.KDTree <Tuple <int, Pdb.Atom> > coord2pdbatom = null;
                {
                    if (pdb_atoms != null)
                    {
                        coord2pdbatom = new KDTree.KDTree <Tuple <int, Pdb.Atom> >(3);
                        for (int ia = 0; ia < pdb_atoms.Length; ia++)
                        {
                            Pdb.Atom pdb_atom = pdb_atoms[ia];
                            Vector   coord    = pdb_atom.coord;
                            coord2pdbatom.insert(coord.ToArray(), new Tuple <int, Pdb.Atom>(ia, pdb_atom));
                        }
                    }
                }

                Atoms atoms = new Atoms(univ);

                /// Debug.Assert(pdb.atoms.Length == top_atoms.Count);
                for (int i = 0; i < xyz_atoms.Length; i++)
                {
                    Xyz.Atom xyz_atom = xyz_atoms[i];
                    Pdb.Atom pdb_atom = null; // = (pdb_atoms != null) ? (pdb_atoms[i]) : null;
                    if (coord2pdbatom != null)
                    {
                        Vector xyz_coord = xyz_atom.Coord;
                        Tuple <int, Pdb.Atom> ia_atom = coord2pdbatom.nearest(xyz_coord);
                        Vector pdb_coord = ia_atom.Item2.coord;
                        if (tolCoordPdbXyz == null)
                        {
                            pdb_atom = pdb_atoms[i];
                        }
                        else
                        {
                            if ((xyz_coord - pdb_coord).Dist < tolCoordPdbXyz)
                            {
                                pdb_atom = ia_atom.Item2;
                            }
                            else
                            {
                                //HDebug.Assert(false);
                                pdb_atom = null;
                            }
                        }
                    }
                    if (pdb_atom != null)
                    {
                        string pdb_atom_type = pdb_atom.element.Trim();
                        string xyz_atom_type = xyz_atom.AtomType.Trim();
                        if (HDebug.IsDebuggerAttached && pdb_atom_type.Length > 0)   // sometimes element is blank: " "
                        {
                            HDebug.AssertIf(pdb_atom_type[0] == xyz_atom_type[0]);
                        }
                        if (tolCoordPdbXyz != null)
                        {
                            HDebug.AssertTolerance(tolCoordPdbXyz.Value, xyz_atom.Coord - pdb_atom.coord);
                        }
                    }
                    //if(pdb_atom != null) Debug.Assert(xyz_atom.Id == pdb_atom.serial);

                    HDebug.Assert(i + 1 == xyz_atom.Id);
                    Prm.Atom   prm_atom   = prm_id2atom  [xyz_atom.AtomId];
                    Prm.Charge prm_charge = prm_id2charge[xyz_atom.AtomId];
                    Prm.Vdw    prm_vdw    = null;
                    Prm.Vdw14  prm_vdw14  = null;
                    if (prm_cls2vdw.ContainsKey(prm_atom.Class))
                    {
                        prm_vdw = prm_cls2vdw  [prm_atom.Class];
                    }
                    if (prm_cls2vdw14.ContainsKey(prm_atom.Class))
                    {
                        prm_vdw14 = prm_cls2vdw14[prm_atom.Class];
                    }

                    if (pdb_atom != null)
                    {
                        if (pdb_atom.element.Trim() != "")
                        {
                            if (pdb_atom.element.Trim() != prm_atom.AtomElem)
                            {
                                throw new Exception();
                            }
                        }
                    }

                    Atom uatom = new Atom(AtomId: xyz_atom.Id
                                          , AtomName: ((pdb_atom != null) ? (pdb_atom.name.Trim()) : ("?" + prm_atom.Type))     /// fix later
                                          , AtomType: prm_atom.Type
                                          , AtomElem: prm_atom.AtomElem
                                          , ResidueId: ((pdb_atom != null) ? (pdb_atom.resSeq) : (-1))                          /// fix later
                                          , ResidueName: ((pdb_atom != null) ? (pdb_atom.resName.Trim()) : ("?res"))            /// fix later
                                          , Charge: prm_charge.pch
                                          , Mass: prm_atom.Mass
                                          , epsilon: ((prm_vdw != null) ? prm_vdw.Epsilon    :          0)
                                          , Rmin2: ((prm_vdw != null) ? prm_vdw.Rmin2      :          0)
                                          , eps_14: ((prm_vdw14 != null) ? prm_vdw14.Eps_14   : double.NaN)
                                          , Rmin2_14: ((prm_vdw14 != null) ? prm_vdw14.Rmin2_14 : double.NaN)
                                          , sources: new object[] { xyz_atom, pdb_atom, prm_atom, prm_charge }
                                          );

                    uatom.Coord = xyz_atom.Coord;
                    atoms.Add(uatom);
                }


                // bonds
                Bonds bonds;

                {
                    Dictionary <Tuple <Atom, Atom>, Bond> lbonds = new Dictionary <Tuple <Atom, Atom>, Bond>();
                    for (int i = 0; i < xyz_atoms.Length; i++)
                    {
                        int  id0   = xyz_atoms[i].Id; HDebug.Assert(id0 == i + 1);
                        int  atm0  = xyz_atoms[i].AtomId;
                        int  cls0  = prm_id2atom[atm0].Class;
                        Atom atom0 = atoms[id0 - 1]; HDebug.Assert(atom0.AtomId == id0);

                        Tuple <int, int> cls;
                        foreach (int id1 in xyz_atoms[i].BondedIds)
                        {
                            int  atm1  = xyz_id2atom[id1].AtomId;
                            int  cls1  = prm_id2atom[atm1].Class;
                            Atom atom1 = atoms[id1 - 1]; HDebug.Assert(atom1.AtomId == id1);
                            HashSet <Prm.Bond> bondtypes = new HashSet <Prm.Bond>();
                            Atom[]             iatom     = null;
                            cls = new Tuple <int, int>(cls0, cls1); if (prm_cls2bond.ContainsKey(cls))
                            {
                                bondtypes.Add(prm_cls2bond[cls]); iatom = new Atom[] { atom0, atom1 };
                            }
                            cls = new Tuple <int, int>(cls1, cls0); if (prm_cls2bond.ContainsKey(cls))
                            {
                                bondtypes.Add(prm_cls2bond[cls]); iatom = new Atom[] { atom1, atom0 };
                            }
                            HDebug.Assert(bondtypes.Count == 1);
                            if (bondtypes.Count >= 1)
                            {
                                Prm.Bond bondtype = bondtypes.Last();
                                HDebug.Assert(bondtype != null);

                                // sort atom id, in order to avoid duplication of bonds such that (0,1) and (1,0)
                                if (iatom.First().ID > iatom.Last().ID)
                                {
                                    iatom = iatom.Reverse().ToArray();
                                }

                                var  key  = new Tuple <Atom, Atom>(iatom[0], iatom[1]);
                                Bond bond = new Bond(iatom[0], iatom[1], bondtype.Kb, bondtype.b0, bondtype);
                                if (lbonds.ContainsKey(key) == false)
                                {
                                    lbonds.Add(key, bond);
                                }
                                else
                                {
                                    HDebug.Assert(bond.Kb == lbonds[key].Kb);
                                    HDebug.Assert(bond.b0 == lbonds[key].b0);
                                }
                            }
                        }
                    }
                    bonds = new Bonds();
                    foreach (Bond bond in lbonds.Values)
                    {
                        HDebug.Assert(bond.atoms.Length == 2);
                        HDebug.Assert(bond.atoms[0].ID < bond.atoms[1].ID);
                        bonds.Add(bond);
                        Atom atom0 = bond.atoms[0];
                        Atom atom1 = bond.atoms[1];
                        atom0.Bonds.Add(bond); atom0.Inter123.Add(atom1); atom0.Inter12.Add(atom1);
                        atom1.Bonds.Add(bond); atom1.Inter123.Add(atom0); atom1.Inter12.Add(atom0);
                    }
                }

                HashSet <Atom>[] inter12 = new HashSet <Atom> [xyz_atoms.Length];
                HashSet <Tuple <Atom, Atom>     >[]   inter123  = new HashSet <Tuple <Atom, Atom>     > [xyz_atoms.Length];
                HashSet <Tuple <Atom, Atom, Atom> >[] inter1234 = new HashSet <Tuple <Atom, Atom, Atom> > [xyz_atoms.Length];
                {
                    HDebug.Assert(xyz_atoms.Length == atoms.Count);
                    foreach (Atom atom in atoms)
                    {
                        inter12  [atom.ID] = new HashSet <Atom>(atom.Inter12);
                        inter123 [atom.ID] = new HashSet <Tuple <Atom, Atom>      >();
                        inter1234[atom.ID] = new HashSet <Tuple <Atom, Atom, Atom> >();
                    }

                    // build inter123 and inter1234
                    for (int i = 0; i < xyz_atoms.Length; i++)
                    {
                        Atom atom0 = atoms[i];
                        HDebug.Assert(atom0.ID == i);
                        foreach (Atom atom1 in inter12[atom0.ID])
                        {
                            HDebug.Assert(atom0 != atom1);
                            foreach (Atom atom2 in inter12[atom1.ID])
                            {
                                HDebug.Assert(atom1 != atom2);
                                if (atom0 == atom2)
                                {
                                    continue;
                                }
                                inter123[atom0.ID].Add(new Tuple <Atom, Atom>(atom1, atom2));
                                foreach (Atom atom3 in inter12[atom2.ID])
                                {
                                    HDebug.Assert(atom2 != atom3);
                                    if (atom0 == atom2)
                                    {
                                        continue;
                                    }
                                    if (atom0 == atom3)
                                    {
                                        continue;
                                    }
                                    if (atom1 == atom3)
                                    {
                                        continue;
                                    }
                                    inter1234[atom0.ID].Add(new Tuple <Atom, Atom, Atom>(atom1, atom2, atom3));
                                }
                            }
                        }
                    }
                }

                // angles
                Angles angles;
                {
                    Dictionary <Tuple <Atom, Atom, Atom>, Angle> langles = new Dictionary <Tuple <Atom, Atom, Atom>, Angle>();
                    foreach (Atom atom0 in atoms)
                    {
                        int id0  = xyz_atoms[atom0.ID].Id; HDebug.Assert(id0 == atom0.ID + 1);
                        int atm0 = xyz_atoms[atom0.ID].AtomId;
                        int cls0 = prm_id2atom[atm0].Class;

                        foreach (var atom123 in inter123[atom0.ID])
                        {
                            Atom atom1 = atom123.Item1; int atm1 = xyz_atoms[atom1.ID].AtomId; int cls1 = prm_id2atom[atm1].Class;
                            Atom atom2 = atom123.Item2; int atm2 = xyz_atoms[atom2.ID].AtomId; int cls2 = prm_id2atom[atm2].Class;

                            Tuple <int, int, int> cls;
                            Atom[] iatom = null;
                            HashSet <Prm.Angle>    angs = new HashSet <Prm.Angle>();
                            HashSet <Prm.Ureybrad> urbs = new HashSet <Prm.Ureybrad>();
                            cls = new Tuple <int, int, int>(cls0, cls1, cls2); if (prm_cls2angle.ContainsKey(cls))
                            {
                                angs.Add(prm_cls2angle[cls]); iatom = new Atom[] { atom0, atom1, atom2 };
                            }
                            if (prm_cls2ureybrad.ContainsKey(cls))
                            {
                                urbs.Add(prm_cls2ureybrad[cls]);
                            }
                            cls = new Tuple <int, int, int>(cls2, cls1, cls0); if (prm_cls2angle.ContainsKey(cls))
                            {
                                angs.Add(prm_cls2angle[cls]); iatom = new Atom[] { atom2, atom1, atom0 };
                            }
                            if (prm_cls2ureybrad.ContainsKey(cls))
                            {
                                urbs.Add(prm_cls2ureybrad[cls]);
                            }
                            HDebug.Assert(angs.Count == 1);
                            HDebug.Assert(urbs.Count <= angs.Count);
                            if (angs.Count >= 1)
                            {
                                Prm.Angle ang = angs.Last();
                                HDebug.Assert(ang != null);
                                Prm.Ureybrad urb = null;
                                if (urbs.Count >= 1)
                                {
                                    urb = urbs.Last();
                                }

                                // sort atom id, in order to avoid duplication of bonds such that (0,1) and (1,0)
                                if (iatom.First().ID > iatom.Last().ID)
                                {
                                    iatom = iatom.Reverse().ToArray();
                                }

                                var   key   = new Tuple <Atom, Atom, Atom>(iatom[0], iatom[1], iatom[2]);
                                Angle angle = new Angle(iatom[0], iatom[1], iatom[2]
                                                        , Ktheta: ang.Ktheta
                                                        , Theta0: ang.Theta0
                                                        , Kub: ((urb != null) ? urb.Kub : 0)
                                                        , S0: ((urb != null) ? urb.S0  : 0)
                                                        , sources: new object[] { ang, urb }
                                                        );
                                if (langles.ContainsKey(key) == false)
                                {
                                    langles.Add(key, angle);
                                }
                                else
                                {
                                    HDebug.Assert(langles[key].Ktheta == angle.Ktheta
                                                  , langles[key].Theta0 == angle.Theta0
                                                  , langles[key].Kub == angle.Kub
                                                  , langles[key].S0 == angle.S0
                                                  );
                                }
                            }
                        }
                    }
                    angles = new Angles();
                    foreach (Angle angle in langles.Values)
                    {
                        HDebug.Assert(angle.atoms.Length == 3);
                        HDebug.Assert(angle.atoms[0].ID < angle.atoms[2].ID);
                        angles.Add(angle);
                        Atom atom0 = angle.atoms[0];
                        Atom atom1 = angle.atoms[1];
                        Atom atom2 = angle.atoms[2];
                        atom0.Angles.Add(angle); atom0.Inter123.Add(atom1); atom0.Inter123.Add(atom2);
                        atom1.Angles.Add(angle); atom1.Inter123.Add(atom2); atom1.Inter123.Add(atom0);
                        atom2.Angles.Add(angle); atom2.Inter123.Add(atom0); atom2.Inter123.Add(atom1);
                    }
                }

                // dihedrals
                Dihedrals dihedrals;
                {
                    Dictionary <Tuple <Atom, Atom, Atom, Atom>, List <Dihedral> > ldihedrals = new Dictionary <Tuple <Atom, Atom, Atom, Atom>, List <Dihedral> >();
                    foreach (Atom atom0 in atoms)
                    {
                        int id0  = xyz_atoms[atom0.ID].Id; HDebug.Assert(id0 == atom0.ID + 1);
                        int atm0 = xyz_atoms[atom0.ID].AtomId;
                        int cls0 = prm_id2atom[atm0].Class;

                        Tuple <int, int, int, int> cls;
                        foreach (var atom1234 in inter1234[atom0.ID])
                        {
                            Atom atom1 = atom1234.Item1; int atm1 = xyz_atoms[atom1.ID].AtomId; int cls1 = prm_id2atom[atm1].Class;
                            Atom atom2 = atom1234.Item2; int atm2 = xyz_atoms[atom2.ID].AtomId; int cls2 = prm_id2atom[atm2].Class;
                            Atom atom3 = atom1234.Item3; int atm3 = xyz_atoms[atom3.ID].AtomId; int cls3 = prm_id2atom[atm3].Class;

                            HashSet <Prm.Torsion> tors = new HashSet <Prm.Torsion>();
                            Atom[] iatom = null;
                            cls = new Tuple <int, int, int, int>(cls0, cls1, cls2, cls3); if (prm_cls2torsion.ContainsKey(cls))
                            {
                                tors.Add(prm_cls2torsion[cls]); iatom = new Atom[] { atom0, atom1, atom2, atom3 };
                            }
                            cls = new Tuple <int, int, int, int>(cls3, cls2, cls1, cls0); if (prm_cls2torsion.ContainsKey(cls))
                            {
                                tors.Add(prm_cls2torsion[cls]); iatom = new Atom[] { atom3, atom2, atom1, atom0 };
                            }
                            HDebug.Assert(tors.Count == 1);
                            if (tors.Count >= 1)
                            {
                                // sort atom id, in order to avoid duplication of bonds such that (0,1) and (1,0)
                                if (iatom.First().ID > iatom.Last().ID)
                                {
                                    iatom = iatom.Reverse().ToArray();
                                }

                                var key = new Tuple <Atom, Atom, Atom, Atom>(iatom[0], iatom[1], iatom[2], iatom[3]);
                                if (ldihedrals.ContainsKey(key) == false)
                                {
                                    ldihedrals.Add(key, new List <Dihedral>());

                                    Prm.Torsion tor = tors.Last();
                                    foreach (var tordat in tor.GetListData())
                                    {
                                        Dihedral dihedral = new Dihedral(iatom[0], iatom[1], iatom[2], iatom[3]
                                                                         , Kchi: tordat.Kchi
                                                                         , n: tordat.n
                                                                         , delta: tordat.delta
                                                                         , sources: new object[] { tor }
                                                                         );
                                        ldihedrals[key].Add(dihedral);
                                        HDebug.Assert(dihedral.n != 0);
                                    }
                                }
                                else
                                {
                                    // do not check its contents because ...
                                }
                            }
                        }
                    }
                    dihedrals = new Dihedrals();
                    foreach (var ldihedral in ldihedrals.Values)
                    {
                        foreach (Dihedral dihedral in ldihedral)
                        {
                            HDebug.Assert(dihedral.atoms.Length == 4);
                            HDebug.Assert(dihedral.atoms[0].ID < dihedral.atoms[3].ID);
                            dihedrals.Add(dihedral);
                            dihedral.atoms[0].Dihedrals.Add(dihedral);
                            dihedral.atoms[1].Dihedrals.Add(dihedral);
                            dihedral.atoms[2].Dihedrals.Add(dihedral);
                            dihedral.atoms[3].Dihedrals.Add(dihedral);
                        }
                    }
                }

                // impropers
                Impropers impropers = new Impropers();

                {
                    Dictionary <Tuple <Atom, Atom, Atom, Atom>, Improper> limpropers = new Dictionary <Tuple <Atom, Atom, Atom, Atom>, Improper>();
                    foreach (Atom atom0 in atoms)
                    {
                        ///       ####################################
                        ///       ##                                ##
                        ///       ##  Improper Dihedral Parameters  ##
                        ///       ##                                ##
                        ///       ####################################
                        ///
                        ///    ##################################################################
                        ///    ##                                                              ##
                        ///    ##  Following CHARMM style, the improper for a trigonal atom    ##
                        ///    ##  D bonded to atoms A, B and C could be input as improper     ##
                        ///    ##  dihedral angle D-A-B-C. The actual angle computed by the    ##
                        ///    ##  program is then literally the dihedral D-A-B-C, which will  ##
                        ///    ##  always have as its ideal value zero degrees. In general     ##
                        ///    ##  D-A-B-C is different from D-B-A-C; the order of the three   ##
                        ///    ##  peripheral atoms matters. In the original CHARMM parameter  ##
                        ///    ##  files, the trigonal atom is often listed last; ie, as       ##
                        ///    ##  C-B-A-D instead of D-A-B-C.                                 ##
                        ///    ##                                                              ##
                        ///    ##  Some of the improper angles are "double counted" in the     ##
                        ///    ##  CHARMM protein parameter set. Since TINKER uses only one    ##
                        ///    ##  improper parameter per site, we have doubled these force    ##
                        ///    ##  constants in the TINKER version of the CHARMM parameters.   ##
                        ///    ##  Symmetric parameters, which are the origin of the "double   ##
                        ///    ##  counted" CHARMM values, are handled in the TINKER package   ##
                        ///    ##  by assigning all symmetric states and using the TINKER      ##
                        ///    ##  force constant divided by the symmetry number.              ##
                        ///    ##                                                              ##
                        ///    ##  ...                                                         ##
                        ///    ##################################################################

                        int id0  = xyz_atoms[atom0.ID].Id; HDebug.Assert(id0 == atom0.ID + 1);
                        int atm0 = xyz_atoms[atom0.ID].AtomId;
                        int cls0 = prm_id2atom[atm0].Class;

                        bool bAtom0InImpropers = false;
                        foreach (var cls in prm_cls2improper.Keys)
                        {
                            if (cls.Item1 == cls0)
                            {
                                bAtom0InImpropers = true;
                            }
                        }
                        if (bAtom0InImpropers == false)
                        {
                            continue;
                        }

                        Atom[] bondeds0 = inter12[atom0.ID].ToArray();
                        if (bondeds0.Length < 3)
                        {
                            continue;
                        }
                        for (int i = 0; i < bondeds0.Length - 2; i++)
                        {
                            Atom atom1 = bondeds0[i];
                            int  atm1  = xyz_atoms[atom1.ID].AtomId;
                            int  cls1  = prm_id2atom[atm1].Class;
                            for (int j = i + 1; j < bondeds0.Length - 1; j++)
                            {
                                Atom atom2 = bondeds0[j];
                                int  atm2  = xyz_atoms[atom2.ID].AtomId;
                                int  cls2  = prm_id2atom[atm2].Class;
                                for (int k = j + 1; k < bondeds0.Length; k++)
                                {
                                    Atom atom3 = bondeds0[k];
                                    int  atm3  = xyz_atoms[atom3.ID].AtomId;
                                    int  cls3  = prm_id2atom[atm3].Class;

                                    Tuple <int, int, int, int> cls;
                                    HashSet <Prm.Improper>     imps = new HashSet <Prm.Improper>();
                                    Atom[] iatom = null;
                                    cls = new Tuple <int, int, int, int>(cls0, cls1, cls2, cls3); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom0, atom1, atom2, atom3 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls3, cls2, cls1, cls0); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom3, atom2, atom1, atom0 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls0, cls1, cls3, cls2); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom0, atom1, atom3, atom2 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls2, cls3, cls1, cls0); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom2, atom3, atom1, atom0 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls0, cls2, cls1, cls3); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom0, atom2, atom1, atom3 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls3, cls1, cls2, cls0); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom3, atom1, atom2, atom0 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls0, cls2, cls3, cls1); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom0, atom2, atom3, atom1 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls1, cls3, cls2, cls0); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom1, atom3, atom2, atom0 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls0, cls3, cls1, cls2); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom0, atom3, atom1, atom2 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls2, cls1, cls3, cls0); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom2, atom1, atom3, atom0 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls0, cls3, cls2, cls1); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom0, atom3, atom2, atom1 };
                                    }
                                    cls = new Tuple <int, int, int, int>(cls1, cls2, cls3, cls0); if (prm_cls2improper.ContainsKey(cls))
                                    {
                                        imps.Add(prm_cls2improper[cls]); iatom = new Atom[] { atom1, atom2, atom3, atom0 };
                                    }
                                    HDebug.Assert(imps.Count <= 1); // for example, H-C-HHH has C-HHH connectivity but it is not improper...
                                                                    // so imps.count <= 1
                                    if (imps.Count >= 1)
                                    {
                                        Prm.Improper imp = imps.Last(); // because iatoms contains the last case only.

                                        ///////////////////////////////////////////////////////////////////////////////////////
                                        // This bug was raised by Jae-Kyun Song at 2016-04-01                                //
                                        // In 1AAC, (1501,C)-(1503,NC2)-(1502,NC2)-(1500,NC2) is reordered                   //
                                        //       as (1500,NC2)-(1502,NC2)-(1503,NC2)-(1501,C)                                //
                                        // This bug was originally copied from dihedral code that is added to prevent adding //
                                        // duplicated interactions such as 1-2-3-4 and 4-3-2-1.                              //
                                        ///////////////////////////////////////////////////////////////////////////////////////
                                        /// old code
                                        //  // sort atom id, in order to avoid duplication of bonds such that (0,1) and (1,0)
                                        //  if(iatom.First().ID > iatom.Last().ID)
                                        //      iatom = iatom.Reverse().ToArray();
                                        //  var key = new Tuple<Atom, Atom, Atom, Atom>(iatom[0], iatom[1], iatom[2], iatom[3]);
                                        ///////////////////////////////////////////////////////////////////////////////////////
                                        /// new code
                                        Tuple <Atom, Atom, Atom, Atom> key;
                                        {
                                            Atom   key0   = iatom[0];
                                            Atom[] key123 = (new Atom[] { iatom[1], iatom[2], iatom[3] }).SortByIDs();
                                            key = new Tuple <Atom, Atom, Atom, Atom>(key0, key123[0], key123[1], key123[2]);
                                        }
                                        ///////////////////////////////////////////////////////////////////////////////////////

                                        Improper improper = new Improper(iatom[0], iatom[1], iatom[2], iatom[3]
                                                                         , Kpsi: imp.Kpsi
                                                                         , psi0: imp.psi0
                                                                         , sources: new object[] { imp }
                                                                         );

                                        if (limpropers.ContainsKey(key) == false)
                                        {
                                            limpropers.Add(key, improper);
                                        }
                                        else
                                        {
                                            HDebug.Assert(limpropers[key].Kpsi == improper.Kpsi
                                                          , limpropers[key].psi0 == improper.psi0
                                                          );
                                        }
                                    }
                                }
                            }
                        }
                    }
                    foreach (var improper in limpropers.Values)
                    {
                        HDebug.Assert(improper.atoms.Length == 4);
                        //HDebug.Assert(improper.atoms[0].ID < improper.atoms[3].ID);
                        impropers.Add(improper);
                        improper.atoms[0].Impropers.Add(improper);
                        improper.atoms[1].Impropers.Add(improper);
                        improper.atoms[2].Impropers.Add(improper);
                        improper.atoms[3].Impropers.Add(improper);
                    }
                }

                // 1-4 interactions
                for (int i = 0; i < atoms.Count; i++)
                {
                    HashSet <Atom> Inter14 = new HashSet <Atom>();
                    BuildInter1toN(atoms[i], 4, Inter14); // find all atoms for 1-4 interaction
                    Inter14.Remove(atoms[i]);             // remove self
                    foreach (Atom atom in atoms[i].Inter123)
                    {
                        Inter14.Remove(atom);             // remove all 1-2, 1-3 interactions
                    }
                    atoms[i].Inter14 = Inter14;
                }
                Nonbonded14s nonbonded14s = new Nonbonded14s();

                nonbonded14s.Build(atoms);

                //// nonbondeds
                //// do not make this list in advance, because it depends on the atom positions
                //Nonbondeds nonbondeds = new Nonbondeds();
                //nonbondeds.Build(atoms);


                //Universe univ = new Universe();
                univ.pdb = pdb;
                univ.refs.Add("xyz", xyz);
                univ.refs.Add("prm", prm);
                univ.refs.Add("pdb", pdb);
                univ.atoms     = atoms;
                univ.bonds     = bonds;
                univ.angles    = angles;
                univ.dihedrals = dihedrals;
                univ.impropers = impropers;
                //univ.nonbondeds   = nonbondeds  ;  // do not make this list in advance, because it depends on the atom positions
                univ.nonbonded14s = nonbonded14s;

                HDebug.Assert(univ.Verify());
                if (HDebug.False)
                {
                    List <Tuple <double, string, Bond> > lbnds = new List <Tuple <double, string, Bond> >();
                    foreach (Bond bnd in bonds)
                    {
                        lbnds.Add(new Tuple <double, string, Bond>(bnd.Kb
                                                                   , bnd.atoms[0].AtomType + "-" + bnd.atoms[1].AtomType
                                                                   , bnd));
                    }
                    lbnds = lbnds.HSelectByIndex(lbnds.HListItem1().HIdxSorted().Reverse().ToArray()).ToList();
                    double avgKb = lbnds.HListItem1().Average();

                    List <Tuple <double, string, Angle> > langs   = new List <Tuple <double, string, Angle> >();
                    List <Tuple <double, string, Angle> > langubs = new List <Tuple <double, string, Angle> >();
                    foreach (Angle ang in angles)
                    {
                        langs.Add(new Tuple <double, string, Angle>(ang.Ktheta
                                                                    , ang.atoms[0].AtomType + "-" + ang.atoms[1].AtomType + "-" + ang.atoms[2].AtomType
                                                                    , ang));
                        if (ang.Kub != 0)
                        {
                            langubs.Add(new Tuple <double, string, Angle>(ang.Kub
                                                                          , ang.atoms[0].AtomType + "-" + ang.atoms[1].AtomType + "-" + ang.atoms[2].AtomType
                                                                          , ang));
                        }
                    }
                    langs   = langs.HSelectByIndex(langs.HListItem1().HIdxSorted().Reverse().ToArray()).ToList();
                    langubs = langubs.HSelectByIndex(langubs.HListItem1().HIdxSorted().Reverse().ToArray()).ToList();
                    double avgKtheta = langs.HListItem1().Average();
                    double avgKub    = langubs.HListItem1().Average();

                    List <Tuple <double, string, Improper> > limps = new List <Tuple <double, string, Improper> >();
                    foreach (Improper imp in impropers)
                    {
                        limps.Add(new Tuple <double, string, Improper>(imp.Kpsi
                                                                       , imp.atoms[0].AtomType + "-" + imp.atoms[1].AtomType + "-" + imp.atoms[2].AtomType + "-" + imp.atoms[3].AtomType
                                                                       , imp));
                    }
                    limps = limps.HSelectByIndex(limps.HListItem1().HIdxSorted().Reverse().ToArray()).ToList();
                    double avgKpsi = limps.HListItem1().Average();

                    List <Tuple <double, string, Dihedral> > ldihs = new List <Tuple <double, string, Dihedral> >();
                    foreach (Dihedral dih in dihedrals)
                    {
                        ldihs.Add(new Tuple <double, string, Dihedral>(dih.Kchi
                                                                       , dih.atoms[0].AtomType + "-" + dih.atoms[1].AtomType + "-" + dih.atoms[2].AtomType + "-" + dih.atoms[3].AtomType
                                                                       , dih));
                    }
                    ldihs = ldihs.HSelectByIndex(ldihs.HListItem1().HIdxSorted().Reverse().ToArray()).ToList();
                    double avgKchi = ldihs.HListItem1().Average();
                }
                return(univ);
            }
            public static HKijFij GetKijFijNbnd(bool vdW, bool elec
                                                , Vector coordi, double ri0, double qi, double ei
                                                , Vector coordj, double rj0, double qj, double ej
                                                , double D // dielectric constant: 80 for general (solvent), 1 for Tinker (NMA)
                                                )
            {
                /// http://www.ks.uiuc.edu/Training/Tutorials/science/forcefield-tutorial/forcefield-html/node5.html
                /// http://www.charmmtutorial.org/index.php/The_Energy_Function
                ///
                /// NONBONDED
                ///
                /// charmm : V_nbnd   = epsilon_ij (              (r0ij / rij)^12  -       2  * (r0ij / rij)^6 )   +           (qi*qj)/(epsilon*rij)
                ///                   = epsilon_ij (             r0ij^12 * rij^-12 -       2  * r0ij^6 * rij^-6)   +           (qi*qj/epsilon) * rij^-1
                ///          frc_nbnd = epsilon_ij (       -12 * r0ij^12 * rij^-13 -   (-6*2) * r0ij^6 * rij^-7)   +      (-1)*(qi*qj/epsilon) * rij^-2
                ///                   = epsilon_ij (      -12  * r0ij^12 * rij^-13 +       12 * r0ij^6 * rij^-7)   +        -1*(qi*qj/epsilon) * rij^-2
                ///          spr_nbnd = epsilon_ij ( (-12*-13) * r0ij^12 * rij^-14 -(-6*-7*2) * r0ij^6 * rij^-8)   +   (-1*-2)*(qi*qj/epsilon) * rij^-3
                ///                   = epsilon_ij (      156  * r0ij^12 * rij^-14 +       84 * r0ij^6 * rij^-8)   +         2*(qi*qj/epsilon) * rij^-3
                ///
                /// V(Lennard-Jones) = Eps,i,j[(Rmin,i,j/ri,j)**12 - 2(Rmin,i,j/ri,j)**6]
                ///
                /// epsilon: kcal/mole, Eps,i,j = sqrt(eps,i * eps,j)
                /// Rmin/2: A, Rmin,i,j = Rmin/2,i + Rmin/2,j
                ///
                /// atom  ignored    epsilon      Rmin/2   ignored   eps,1-4       Rmin/2,1-4
                ///
                /// V(electrostatic) : V(i,j) = (qi*qj)/(epsilon*rij)
                ///                           = 332*qi*qj/r_ij/D
                ///                    Where D is dielectric constant, for proteins. D is normally 80. (see equation (13) in the following pdf file).
                ///                    http://pharmacy.ucsd.edu/labs/gilson/ce_www1a.pdf
                ///                    epsilon = D/332
                HDebug.AssertIf(elec, (double.IsNaN(D) == false) && (double.IsInfinity(D) == false));

                // electric: conversion from electron**2/Angstrom to Kcal/mol
                double electric;

                electric = 332.063709;  // tinker pmpb.c line 570
                electric = 332.05382;   // tinker pmpb.c line 716
                electric = 332.063709;  // tinker pmpb.c line 851
                // units.f line 53      : c     coulomb     conversion from electron**2/Ang to kcal/mole
                // units.f line 82      :       parameter (coulomb=332.063714d0)
                // initprm.f line 272   :       electric = coulomb
                electric = 332.063714;
                // chgpot.f line 16     : c     dielec     dielectric constant for electrostatic interactions
                // initprm.f line 273   :       dielec = 1.0d0
                double dielec = 1.0;

                double rij  = (coordi - coordj).Dist;
                double r0ij = (ri0 + rj0);
                double qij  = qi * qj;
                double eij  = Math.Sqrt(ei * ej);
                double eps  = D / 332;

                double Kvdw = eij * (-12 * -13) * Math.Pow(r0ij / rij, 12) / (rij * rij)
                              - eij * (-6 * -7 * 2) * Math.Pow(r0ij / rij, 6) / (rij * rij);
                double Kelec = 2 * (qij / eps) / (rij * rij * rij);

                double Fvdw = eij * (-12) * Math.Pow(r0ij / rij, 12) / rij
                              - eij * (-6 * 2) * Math.Pow(r0ij / rij, 6) / rij;
                double Felec = (-1) * (qij / eps) / (rij * rij);
                double Evdw  = eij * (1) * Math.Pow(r0ij / rij, 12)
                               - eij * (2) * Math.Pow(r0ij / rij, 6);
                double Eelec = (1) * (qij / eps) / (rij);

                double ee         = D;
                double Kvdw_stem  = eij; //Math.Sqrt(atom0.epsilon * atom1.epsilon)
                double Kelec_stem = (332.0 / 60.0 * qij / ee / r0ij);

                //Debug.Assert(Kvdw + Kelec >= 0);
                double Kij = 0;
                double Fij = 0;

                if (vdW)
                {
                    Kij += Kvdw; Fij += Fvdw;
                }
                if (elec)
                {
                    Kij += Kelec; Fij += Felec;
                }

                //double pweng = Evdw + Eelec;
                //double pwfrc = Fvdw + Felec;
                //double pwspr = Kij;

                return(new HKijFij {
                    Kij = Kij, Fij = Fij
                });
            }
Beispiel #12
0
            public static Tuple <Xyz, Prm> BuildFromNamd(Pdb pdb, Namd.Psf psf, Namd.Prm prm)
            {
                var univ = Universe.BuilderNamd.Build(psf, prm, pdb, null, null);

                /// Atom(Id,Class,Type,Desc,Mass)
                /// * Id   : Vdw(Id,Rmin2,Epsilon)
                ///          Charge(Id,pch)
                ///          Biotype(BioId,Name,Resi,Id)
                /// * Class: Vdw14(Class,Rmin2_14,Eps_14)
                ///          Bond(Class1,Class2,Kb,b0)
                ///          Angle(Class1,Class2,Class3,Ktheta,Theta0)
                ///          Ureybrad(Class1,Class2,Class3,Kub,S0)
                ///          Improper(Class1,Class2,Class3,Class4,Kpsi,psi0)
                ///          Torsion(Class1,Class2,Class3,Class4,Kchi0,delta0,n0,Kchi1,delta1,n1,Kchi2,delta2,n2)
                ///   Type :
                Dictionary <Tuple <string, string, double, double, double, int>, int> key_id = new Dictionary <Tuple <string, string, double, double, double, int>, int>();
                Dictionary <string, int> type_cls = new Dictionary <string, int>();

                Dictionary <int, Prm.Atom>    id_atom    = new Dictionary <int, Prm.Atom>();
                Dictionary <int, Prm.Vdw>     cls_vdw    = new Dictionary <int, Prm.Vdw>();
                Dictionary <int, Prm.Charge>  id_charge  = new Dictionary <int, Prm.Charge>();
                Dictionary <int, Prm.Biotype> id_biotype = new Dictionary <int, Prm.Biotype>();
                Dictionary <int, Prm.Vdw14>   cls_vdw14  = new Dictionary <int, Prm.Vdw14>();

                Dictionary <int, Tuple <string, Vector, int, List <int> > > xyzid_info = new Dictionary <int, Tuple <string, Vector, int, List <int> > >();

                ///                      1                     NH3
                /// ------------------------------------------------------------------------------------------------------------------
                ///      pdb: "ATOM      1  N   GLY A   2      24.776  -0.687  28.652  1.00  0.00      A    N"
                /// namd-psf:    "       1 A    2    GLY  N    NH3   -0.300000       14.0070           0"
                /// namd-prm:                                 "NH3    0.000000  -0.200000     1.850000 ! ALLOW   POL"
                /// tink-xyz:                         "     1  NH3   24.776000   -0.687000   28.652000    65     2     5     6     7"
                /// tink-prm:         "atom         65   26    NH3   "Ammonium Nitrogen"            7    14.007    4"
                foreach (var uatom in univ.atoms)
                {
                    HDebug.Assert(uatom.sources.Length == 3);
                    Pdb.Atom           pdbatom = uatom.sources.HFirstByType(null as Pdb.Atom); HDebug.Assert(pdbatom != null);
                    Namd.Psf.Atom      psfatom = uatom.sources.HFirstByType(null as Namd.Psf.Atom); HDebug.Assert(psfatom != null);
                    Namd.Prm.Nonbonded prmnbnd = uatom.sources.HFirstByType(null as Namd.Prm.Nonbonded); HDebug.Assert(prmnbnd != null);
                    string             name    = psfatom.AtomName.Trim();
                    string             resn    = psfatom.ResidueName.Trim();
                    string             type    = psfatom.AtomType.Trim();
                    double             rmin2   = prmnbnd.Rmin2;
                    double             eps     = prmnbnd.epsilon;
                    double             chrg    = psfatom.Charge;
                    int    valnc = uatom.Bonds.Count;
                    string desc  = string.Format("{0}({1})-{2}", name, type, resn);

                    var key = UnivAtomToTinkKey(uatom);
                    if (key_id.ContainsKey(key) == false)
                    {
                        key_id.Add(key, key_id.Count + 1);
                    }

                    if (type_cls.ContainsKey(type) == false)
                    {
                        type_cls.Add(type, type_cls.Count + 1);
                    }

                    int    tink_id   = key_id[key];
                    int    tink_cls  = type_cls[type];
                    string tink_type = type;

                    if (id_atom.ContainsKey(tink_id) == false)
                    {
                        Prm.Atom tink_atom = Prm.Atom.FromData
                                                 (Id: tink_id
                                                 , Class: tink_cls
                                                 , Type: tink_type
                                                 , Description: desc
                                                 , AtomicNumber: null
                                                 , Mass: psfatom.Mass
                                                 , Valence: valnc
                                                 );
                        id_atom.Add(tink_id, tink_atom);
                    }
                    else
                    {
                        Prm.Atom tink_atom = id_atom[tink_id];
                        tink_id  = tink_atom.Id;
                        tink_cls = tink_atom.Class;
                        HDebug.Exception(tink_atom.Type == tink_type);
                        HDebug.Exception(tink_atom.Description == desc);
                        HDebug.Exception(Math.Abs(tink_atom.Mass - psfatom.Mass) < 0.001);
                        HDebug.Exception(tink_atom.Valence == valnc);
                    }

                    if (cls_vdw.ContainsKey(tink_cls) == false)
                    {
                        Prm.Vdw tink_vdw = Prm.Vdw.FromData
                                               (Class: tink_cls
                                               , Rmin2: prmnbnd.Rmin2
                                               , Epsilon: prmnbnd.epsilon
                                               );
                        cls_vdw.Add(tink_cls, tink_vdw);
                    }
                    else
                    {
                        Prm.Vdw tink_vdw = cls_vdw[tink_cls];
                        HDebug.Exception(tink_vdw.Rmin2 == prmnbnd.Rmin2);
                        HDebug.Exception(tink_vdw.Epsilon == prmnbnd.epsilon);
                    }

                    HDebug.AssertIf(double.IsNaN(prmnbnd.Rmin2_14) == true, double.IsNaN(prmnbnd.eps_14) == true);
                    HDebug.AssertIf(double.IsNaN(prmnbnd.Rmin2_14) == false, double.IsNaN(prmnbnd.eps_14) == false);
                    if (double.IsNaN(prmnbnd.Rmin2_14) == false && double.IsNaN(prmnbnd.eps_14) == false)
                    {
                        if (cls_vdw14.ContainsKey(tink_cls) == false)
                        {
                            Prm.Vdw14 tink_vdw14 = Prm.Vdw14.FromData
                                                       (Class: tink_cls
                                                       , Rmin2_14: prmnbnd.Rmin2_14
                                                       , Eps_14: prmnbnd.eps_14
                                                       );
                            cls_vdw14.Add(tink_cls, tink_vdw14);
                        }
                        else
                        {
                            Prm.Vdw14 tink_vdw14 = cls_vdw14[tink_cls];
                            HDebug.Exception(tink_vdw14.Rmin2_14 == prmnbnd.Rmin2_14);
                            HDebug.Exception(tink_vdw14.Eps_14 == prmnbnd.eps_14);
                        }
                    }
                    else
                    {
                        HDebug.Exception(cls_vdw14.ContainsKey(tink_cls) == false);
                    }

                    if (id_charge.ContainsKey(tink_id) == false)
                    {
                        Prm.Charge tink_charge = Prm.Charge.FromData
                                                     (Id: tink_id
                                                     , pch: psfatom.Charge
                                                     );
                        id_charge.Add(tink_id, tink_charge);
                    }
                    else
                    {
                        Prm.Charge tink_charge = id_charge[tink_id];
                        HDebug.Exception(tink_charge.pch == psfatom.Charge);
                    }

                    if (id_biotype.ContainsKey(tink_id) == false)
                    {
                        Prm.Biotype tink_biotype = Prm.Biotype.FromData
                                                       (BioId: id_biotype.Count + 1
                                                       , Name: name
                                                       , Resn: string.Format("{0}({1})-{2}", name, type, resn)
                                                       , Id: tink_id
                                                       );
                        id_biotype.Add(tink_id, tink_biotype);
                    }
                    else
                    {
                        Prm.Biotype tink_biotype = id_biotype[tink_id];
                        HDebug.Exception(tink_biotype.Name == name);
                        HDebug.Exception(tink_biotype.Resn == string.Format("{0}({1})-{2}", name, type, resn));
                        HDebug.Exception(tink_biotype.Id == tink_id);
                    }

                    var xyzid   = uatom.AtomId;
                    var xyzinfo = new Tuple <string, Vector, int, List <int> >
                                      (tink_type    // AtomType
                                      , uatom.Coord // X, Y, Z
                                      , tink_id     // AtomId
                                      , new List <int>()
                                      );
                    xyzid_info.Add(xyzid, xyzinfo);
                }

                Dictionary <Tuple <int, int>, Prm.Bond> cls_bond = new Dictionary <Tuple <int, int>, Prm.Bond>();

                foreach (var ubond in univ.bonds)
                {
                    var key0 = UnivAtomToTinkKey(ubond.atoms[0]); string type0 = key0.Item2; int cls0 = type_cls[type0];
                    var key1 = UnivAtomToTinkKey(ubond.atoms[1]); string type1 = key1.Item2; int cls1 = type_cls[type1];

                    Tuple <int, int> cls01;
                    if (cls0 < cls1)
                    {
                        cls01 = new Tuple <int, int>(cls0, cls1);
                    }
                    else
                    {
                        cls01 = new Tuple <int, int>(cls1, cls0);
                    }

                    if (cls_bond.ContainsKey(cls01) == false)
                    {
                        Prm.Bond tink_bond01 = Prm.Bond.FromData
                                                   (Class1: cls01.Item1
                                                   , Class2: cls01.Item2
                                                   , Kb: ubond.Kb
                                                   , b0: ubond.b0
                                                   );
                        cls_bond.Add(cls01, tink_bond01);
                    }
                    else
                    {
                        Prm.Bond tink_bond01 = cls_bond[cls01];
                        HDebug.Exception(Math.Abs(tink_bond01.Kb - ubond.Kb) < 0.01);
                        HDebug.Exception(tink_bond01.b0 == ubond.b0);
                    }

                    int xyzid0 = ubond.atoms[0].AtomId;
                    int xyzid1 = ubond.atoms[1].AtomId;
                    xyzid_info[xyzid0].Item4.Add(xyzid1);
                    xyzid_info[xyzid1].Item4.Add(xyzid0);
                }

                Dictionary <Tuple <int, int, int>, Prm.Angle>    cls_angle    = new Dictionary <Tuple <int, int, int>, Prm.Angle>();
                Dictionary <Tuple <int, int, int>, Prm.Ureybrad> cls_ureybrad = new Dictionary <Tuple <int, int, int>, Prm.Ureybrad>();

                foreach (var uangle in univ.angles)
                {
                    var key0 = UnivAtomToTinkKey(uangle.atoms[0]); string type0 = key0.Item2; int cls0 = type_cls[type0];
                    var key1 = UnivAtomToTinkKey(uangle.atoms[1]); string type1 = key1.Item2; int cls1 = type_cls[type1];
                    var key2 = UnivAtomToTinkKey(uangle.atoms[2]); string type2 = key2.Item2; int cls2 = type_cls[type2];

                    Tuple <int, int, int> cls012;
                    if (cls0 < cls2)
                    {
                        cls012 = new Tuple <int, int, int>(cls0, cls1, cls2);
                    }
                    else
                    {
                        cls012 = new Tuple <int, int, int>(cls2, cls1, cls0);
                    }

                    double uangle_Theta0 = 180.0 * uangle.Theta0 / Math.PI;

                    if (cls_angle.ContainsKey(cls012) == false)
                    {
                        Prm.Angle tink_angle012 = Prm.Angle.FromData
                                                      (Class1: cls012.Item1
                                                      , Class2: cls012.Item2
                                                      , Class3: cls012.Item3
                                                      , Ktheta: uangle.Ktheta
                                                      , Theta0: uangle_Theta0
                                                      );
                        cls_angle.Add(cls012, tink_angle012);

                        HDebug.Exception(cls_ureybrad.ContainsKey(cls012) == false);
                        if (uangle.Kub != 0)
                        {
                            Prm.Ureybrad tink_ureybrad = Prm.Ureybrad.FromData
                                                             (Class1: cls012.Item1
                                                             , Class2: cls012.Item2
                                                             , Class3: cls012.Item3
                                                             , Kub: uangle.Kub
                                                             , S0: uangle.S0
                                                             );
                            cls_ureybrad.Add(cls012, tink_ureybrad);
                        }
                    }
                    else
                    {
                        Prm.Angle tink_angle012 = cls_angle[cls012];
                        HDebug.Exception(tink_angle012.Ktheta == uangle.Ktheta);
                        HDebug.Exception(Math.Abs(tink_angle012.Theta0 - uangle_Theta0) < 0.01);

                        if (uangle.Kub != 0)
                        {
                            Prm.Ureybrad tink_ureybrad = cls_ureybrad[cls012];
                            HDebug.Exception(tink_ureybrad.Kub == uangle.Kub);
                            HDebug.Exception(tink_ureybrad.S0 == uangle.S0);
                        }
                        else
                        {
                            HDebug.Exception(cls_ureybrad.ContainsKey(cls012) == false);
                        }
                    }
                }

                Dictionary <Tuple <int, int, int, int>, Prm.Improper> cls_improper = new Dictionary <Tuple <int, int, int, int>, Prm.Improper>();

                foreach (var improper in univ.impropers)
                {
                    var key0 = UnivAtomToTinkKey(improper.atoms[0]); string type0 = key0.Item2; int cls0 = type_cls[type0];
                    var key1 = UnivAtomToTinkKey(improper.atoms[1]); string type1 = key1.Item2; int cls1 = type_cls[type1];
                    var key2 = UnivAtomToTinkKey(improper.atoms[2]); string type2 = key2.Item2; int cls2 = type_cls[type2];
                    var key3 = UnivAtomToTinkKey(improper.atoms[3]); string type3 = key3.Item2; int cls3 = type_cls[type3];

                    Tuple <int, int, int, int> cls0123 = new Tuple <int, int, int, int>(cls0, cls1, cls2, cls3);
                    //if(cls0 < cls2) cls0123 = new Tuple<int, int, int, int>(cls0, cls1, cls2, cls3);
                    //else            cls0123 = new Tuple<int, int, int, int>(cls3, cls2, cls1, cls0);

                    double improper_psi0 = 180.0 * improper.psi0 / Math.PI;

                    if (cls_improper.ContainsKey(cls0123) == false)
                    {
                        Prm.Improper tink_improper = Prm.Improper.FromData
                                                         (Class1: cls0
                                                         , Class2: cls1
                                                         , Class3: cls2
                                                         , Class4: cls3
                                                         , Kpsi: improper.Kpsi
                                                         , psi0: improper_psi0
                                                         );
                        cls_improper.Add(cls0123, tink_improper);
                    }
                    else
                    {
                        Prm.Improper tink_improper = cls_improper[cls0123];
                        HDebug.Exception(tink_improper.Kpsi == improper.Kpsi);
                        HDebug.Exception(Math.Abs(tink_improper.psi0 - improper_psi0) < 0.01);
                    }
                }

                Dictionary <Tuple <int, int, int, int>, List <Universe.Dihedral> > cls_dihedrals = new Dictionary <Tuple <int, int, int, int>, List <Universe.Dihedral> >();

                foreach (var atom in univ.atoms)
                {
                    var inter1234s = atom.ListInterAtom1234();
                    foreach (var inter1234 in inter1234s)
                    {
                        HDebug.Assert(inter1234.Count == 4);
                        var key0 = UnivAtomToTinkKey(inter1234[0]); string type0 = key0.Item2; int cls0 = type_cls[type0];
                        var key1 = UnivAtomToTinkKey(inter1234[1]); string type1 = key1.Item2; int cls1 = type_cls[type1];
                        var key2 = UnivAtomToTinkKey(inter1234[2]); string type2 = key2.Item2; int cls2 = type_cls[type2];
                        var key3 = UnivAtomToTinkKey(inter1234[3]); string type3 = key3.Item2; int cls3 = type_cls[type3];

                        Tuple <int, int, int, int> cls0123 = new Tuple <int, int, int, int>(cls0, cls1, cls2, cls3);
                        Tuple <int, int, int, int> cls3210 = new Tuple <int, int, int, int>(cls3, cls2, cls1, cls0);

                        if (cls_dihedrals.ContainsKey(cls0123) == false)
                        {
                            cls_dihedrals.Add(cls0123, new List <Universe.Dihedral>());
                        }
                        if (cls_dihedrals.ContainsKey(cls3210) == false)
                        {
                            cls_dihedrals.Add(cls3210, new List <Universe.Dihedral>());
                        }
                    }
                }
                foreach (var dihedral in univ.dihedrals)
                {
                    var key0 = UnivAtomToTinkKey(dihedral.atoms[0]); string type0 = key0.Item2; int cls0 = type_cls[type0];
                    var key1 = UnivAtomToTinkKey(dihedral.atoms[1]); string type1 = key1.Item2; int cls1 = type_cls[type1];
                    var key2 = UnivAtomToTinkKey(dihedral.atoms[2]); string type2 = key2.Item2; int cls2 = type_cls[type2];
                    var key3 = UnivAtomToTinkKey(dihedral.atoms[3]); string type3 = key3.Item2; int cls3 = type_cls[type3];

                    Tuple <int, int, int, int> cls0123 = new Tuple <int, int, int, int>(cls0, cls1, cls2, cls3);
                    Tuple <int, int, int, int> cls3210 = new Tuple <int, int, int, int>(cls3, cls2, cls1, cls0);

                    cls_dihedrals[cls0123].Add(dihedral);
                    cls_dihedrals[cls3210].Add(dihedral);
                }
                Dictionary <Tuple <int, int, int, int>, Prm.Torsion> cls_torsion = new Dictionary <Tuple <int, int, int, int>, Prm.Torsion>();

                foreach (var cls0123 in cls_dihedrals.Keys)
                {
                    Universe.Dihedral[] dihedrals = cls_dihedrals[cls0123].ToArray();

                    Dictionary <Tuple <double, double>, List <double> > delta_n_Kchis = new Dictionary <Tuple <double, double>, List <double> >();
                    foreach (var dihedral in dihedrals)
                    {
                        double dihedral_delta = 180.0 * dihedral.delta / Math.PI;
                        var    delta_n        = new Tuple <double, double>(dihedral_delta, dihedral.n);
                        if (delta_n_Kchis.ContainsKey(delta_n) == false)
                        {
                            delta_n_Kchis.Add(delta_n, new List <double>());
                        }
                        delta_n_Kchis[delta_n].Add(dihedral.Kchi);
                    }

                    Tuple <double, double>[] lst_delta_n = delta_n_Kchis.Keys.ToArray();
                    HDebug.Exception(lst_delta_n.Length <= 3);

                    double?Kchi0 = null; if (lst_delta_n.Length >= 1)
                    {
                        Kchi0 = delta_n_Kchis[lst_delta_n[0]].Mean();
                    }
                    double?delta0 = null; if (lst_delta_n.Length >= 1)
                    {
                        delta0 = lst_delta_n[0].Item1;
                    }
                    double?n0 = null; if (lst_delta_n.Length >= 1)
                    {
                        n0 = lst_delta_n[0].Item2;
                    }
                    double?Kchi1 = null; if (lst_delta_n.Length >= 2)
                    {
                        Kchi1 = delta_n_Kchis[lst_delta_n[1]].Mean();
                    }
                    double?delta1 = null; if (lst_delta_n.Length >= 2)
                    {
                        delta1 = lst_delta_n[1].Item1;
                    }
                    double?n1 = null; if (lst_delta_n.Length >= 2)
                    {
                        n1 = lst_delta_n[1].Item2;
                    }
                    double?Kchi2 = null; if (lst_delta_n.Length >= 3)
                    {
                        Kchi2 = delta_n_Kchis[lst_delta_n[2]].Mean();
                    }
                    double?delta2 = null; if (lst_delta_n.Length >= 3)
                    {
                        delta2 = lst_delta_n[2].Item1;
                    }
                    double?n2 = null; if (lst_delta_n.Length >= 3)
                    {
                        n2 = lst_delta_n[2].Item2;
                    }

                    Prm.Torsion tink_torsion = Prm.Torsion.FromData
                                                   (Class1: cls0123.Item1
                                                   , Class2: cls0123.Item2
                                                   , Class3: cls0123.Item3
                                                   , Class4: cls0123.Item4
                                                   , Kchi0: Kchi0
                                                   , delta0: delta0
                                                   , n0: n0
                                                   , Kchi1: Kchi1
                                                   , delta1: delta1
                                                   , n1: n1
                                                   , Kchi2: Kchi2
                                                   , delta2: delta2
                                                   , n2: n2
                                                   );
                    cls_torsion.Add(cls0123, tink_torsion);
                }

                List <string> prmlines;

                #region build lines
                {
                    List <string> lines = new List <string>();
                    lines.Add("");
                    lines.Add("      ##############################");
                    lines.Add("      ##                          ##");
                    lines.Add("      ##  Force Field Definition  ##");
                    lines.Add("      ##                          ##");
                    lines.Add("      ##############################");
                    lines.Add("");
                    lines.Add("");
                    lines.Add("forcefield              CHARMM22");
                    lines.Add("");
                    lines.Add("vdwtype                 LENNARD-JONES");
                    lines.Add("radiusrule              ARITHMETIC");
                    lines.Add("radiustype              R-MIN");
                    lines.Add("radiussize              RADIUS");
                    lines.Add("epsilonrule             GEOMETRIC");
                    lines.Add("vdw-14-scale            1.0");
                    lines.Add("chg-14-scale            1.0");
                    lines.Add("electric                332.0716");
                    lines.Add("dielectric              1.0");
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      #############################");
                    lines.Add("      ##                         ##");
                    lines.Add("      ##  Atom Type Definitions  ##");
                    lines.Add("      ##                         ##");
                    lines.Add("      #############################");
                    lines.Add("");
                    lines.Add("");
                    foreach (int id in id_atom.Keys.ToArray().HSort())
                    {
                        lines.Add(id_atom[id].line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ################################");
                    lines.Add("      ##                            ##");
                    lines.Add("      ##  Van der Waals Parameters  ##");
                    lines.Add("      ##                            ##");
                    lines.Add("      ################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (int cls in cls_vdw.Keys.ToArray().HSort())
                    {
                        lines.Add(cls_vdw[cls].line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ####################################");
                    lines.Add("      ##                                ##");
                    lines.Add("      ##  1-4 Van der Waals Parameters  ##");
                    lines.Add("      ##                                ##");
                    lines.Add("      ####################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (int cls in cls_vdw14.Keys.ToArray().HSort())
                    {
                        lines.Add(cls_vdw14[cls].line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ##################################");
                    lines.Add("      ##                              ##");
                    lines.Add("      ##  Bond Stretching Parameters  ##");
                    lines.Add("      ##                              ##");
                    lines.Add("      ##################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (var bond in cls_bond)
                    {
                        lines.Add(bond.Value.line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ################################");
                    lines.Add("      ##                            ##");
                    lines.Add("      ##  Angle Bending Parameters  ##");
                    lines.Add("      ##                            ##");
                    lines.Add("      ################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (var angle in cls_angle)
                    {
                        lines.Add(angle.Value.line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ###############################");
                    lines.Add("      ##                           ##");
                    lines.Add("      ##  Urey-Bradley Parameters  ##");
                    lines.Add("      ##                           ##");
                    lines.Add("      ###############################");
                    lines.Add("");
                    lines.Add("");
                    foreach (var ureybrad in cls_ureybrad)
                    {
                        lines.Add(ureybrad.Value.line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ####################################");
                    lines.Add("      ##                                ##");
                    lines.Add("      ##  Improper Dihedral Parameters  ##");
                    lines.Add("      ##                                ##");
                    lines.Add("      ####################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (var improper in cls_improper)
                    {
                        lines.Add(improper.Value.line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ############################");
                    lines.Add("      ##                        ##");
                    lines.Add("      ##  Torsional Parameters  ##");
                    lines.Add("      ##                        ##");
                    lines.Add("      ############################");
                    lines.Add("");
                    lines.Add("");
                    foreach (var torsion in cls_torsion)
                    {
                        lines.Add(torsion.Value.line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ########################################");
                    lines.Add("      ##                                    ##");
                    lines.Add("      ##  Atomic Partial Charge Parameters  ##");
                    lines.Add("      ##                                    ##");
                    lines.Add("      ########################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (int id in id_charge.Keys.ToArray().HSort())
                    {
                        lines.Add(id_charge[id].line);
                    }
                    lines.Add("");
                    lines.Add("");
                    lines.Add("      ########################################");
                    lines.Add("      ##                                    ##");
                    lines.Add("      ##  Biopolymer Atom Type Conversions  ##");
                    lines.Add("      ##                                    ##");
                    lines.Add("      ########################################");
                    lines.Add("");
                    lines.Add("");
                    foreach (int id in id_biotype.Keys.ToArray().HSort())
                    {
                        lines.Add(id_biotype[id].line);
                    }
                    lines.Add("");
                    prmlines = lines;
                }
                #endregion

                Dictionary <string, string> atomtype_natomtype;
                {
                    atomtype_natomtype = xyzid_info.Values.ToArray().HListItem1().HToHashSet().HToDictionaryAsKey("");
                    foreach (string atomtype in atomtype_natomtype.Keys.ToArray())
                    {
                        string natomtype = atomtype;
                        if (natomtype.Length > 3)
                        {
                            Dictionary <char, char> map = new Dictionary <char, char>
                            {
                                { '0', '1' }, { '1', '2' }, { '2', '3' }, { '3', '4' }, { '4', '5' },
                                { '5', '6' }, { '6', '7' }, { '7', '8' }, { '8', '9' }, { '9', 'A' },
                                { 'A', 'B' }, { 'B', 'C' }, { 'C', 'D' }, { 'D', 'E' }, { 'E', 'F' },
                                { 'F', 'G' }, { 'G', 'H' }, { 'H', 'I' }, { 'I', 'J' }, { 'J', 'K' },
                                { 'K', 'L' }, { 'L', 'M' }, { 'M', 'N' }, { 'N', 'O' }, { 'O', 'P' },
                                { 'P', 'Q' }, { 'Q', 'R' }, { 'R', 'S' }, { 'S', 'T' }, { 'T', 'U' },
                                { 'U', 'V' }, { 'V', 'W' }, { 'W', 'X' }, { 'X', 'Y' }, { 'Y', 'Z' },
                                { 'Z', '0' },
                            };
                            string temptype = atomtype.Substring(0, 3);
                            foreach (var key in map.Keys.ToArray())
                            {
                                if (map[key] == temptype[2])
                                {
                                    map[key] = ' ';     // marking ending point as ' '
                                }
                            }
                            while (true)
                            {
                                if (temptype[2] == ' ')
                                {
                                    HDebug.Exception();
                                }

                                if ((atomtype_natomtype.ContainsKey(temptype) == false) && (atomtype_natomtype.ContainsValue(temptype) == false))
                                {
                                    natomtype = temptype;
                                    break;
                                }

                                temptype = temptype.Substring(0, 2) + map[temptype[2]];
                            }
                        }
                        atomtype_natomtype[atomtype] = natomtype;
                    }
                }
                List <string> xyzlines;
                {
                    xyzlines = new List <string>();
                    xyzlines.Add(Xyz.Header.FromData(xyzid_info.Count, "", "", "").line);
                    foreach (var xyzid in xyzid_info.Keys.ToArray().HSort())
                    {
                        int    id       = xyzid;
                        string atomtype = xyzid_info[xyzid].Item1;
                        atomtype = atomtype_natomtype[atomtype];
                        double x         = xyzid_info[xyzid].Item2[0];
                        double y         = xyzid_info[xyzid].Item2[1];
                        double z         = xyzid_info[xyzid].Item2[2];
                        int    atomid    = xyzid_info[xyzid].Item3;
                        int[]  bondedids = xyzid_info[xyzid].Item4.ToArray();
                        xyzlines.Add(Xyz.Atom.FromData(id, atomtype, x, y, z, atomid, bondedids).line);
                    }
                }

                {
                    for (int i = 0; i < prmlines.Count; i++)
                    {
                        if (prmlines[i].StartsWith("atom "))
                        {
                            var atom  = Prm.Atom.FromLine(prmlines[i]);
                            var natom = Prm.Atom.FromData
                                            (Id: atom.Id
                                            , Class: atom.Class
                                            , Type: atomtype_natomtype[atom.Type]
                                            , Description: atom.Description
                                            , AtomicNumber: atom.AtomicNumber
                                            , Mass: atom.Mass
                                            , Valence: atom.Valence
                                            );
                            prmlines[i] = natom.line;
                        }
                    }
                }

                Prm tink_prm = Prm.FromLines(prmlines);
                Xyz tink_xyz = Xyz.FromLines(xyzlines);
                return(new Tuple <Xyz, Prm>(tink_xyz, tink_prm));
            }
Beispiel #13
0
        public static void GetPwEnrgFrcSprNbnd(bool vdW, bool elec
                                               , Vector coordi, double ri0, double qi, double ei
                                               , Vector coordj, double rj0, double qj, double ej
                                               , double D // = 80 // dielectric constant
                                               , out double Eij
                                               , out double Fij
                                               , out double Kij
                                               )
        {
            /// http://www.ks.uiuc.edu/Training/Tutorials/science/forcefield-tutorial/forcefield-html/node5.html
            /// http://www.charmmtutorial.org/index.php/The_Energy_Function
            ///
            /// NONBONDED
            ///
            /// charmm : V_nbnd   = epsilon_ij (              (r0ij / rij)^12  -       2  * (r0ij / rij)^6 )   +           (qi*qj)/(epsilon*rij)
            ///                   = epsilon_ij (             r0ij^12 * rij^-12 -       2  * r0ij^6 * rij^-6)   +           (qi*qj/epsilon) * rij^-1
            ///          frc_nbnd = epsilon_ij (       -12 * r0ij^12 * rij^-13 -   (-6*2) * r0ij^6 * rij^-7)   +      (-1)*(qi*qj/epsilon) * rij^-2
            ///          spr_nbnd = epsilon_ij ( (-12*-13) * r0ij^12 * rij^-14 -(-6*-7*2) * r0ij^6 * rij^-8)   +   (-1*-2)*(qi*qj/epsilon) * rij^-3
            ///                   = epsilon_ij (      156  * r0ij^12 * rij^-14 +       84 * r0ij^6 * rij^-8)   +         2*(qi*qj/epsilon) * rij^-3
            ///
            /// V(Lennard-Jones) = Eps,i,j[(Rmin,i,j/ri,j)**12 - 2(Rmin,i,j/ri,j)**6]
            ///
            /// epsilon: kcal/mole, Eps,i,j = sqrt(eps,i * eps,j)
            /// Rmin/2: A, Rmin,i,j = Rmin/2,i + Rmin/2,j
            ///
            /// atom  ignored    epsilon      Rmin/2   ignored   eps,1-4       Rmin/2,1-4
            ///
            /// V(electrostatic) : V(i,j) = (qi*qj)/(epsilon*rij)
            ///                           = 332*qi*qj/r_ij/D
            ///                    Where D is dielectric constant, for proteins. D is normally 80. (see equation (13) in the following pdf file).
            ///                    http://pharmacy.ucsd.edu/labs/gilson/ce_www1a.pdf
            ///                    epsilon = D/332

            double rij2 = (coordi - coordj).Dist2;
            double rij  = Math.Sqrt(rij2);
            double r0ij = (ri0 + rj0);
            double qij  = qi * qj;
            double eij  = Math.Sqrt(ei * ej);
            double eps  = D / 332;

            Eij = 0;
            Fij = 0;
            Kij = 0;
            if (vdW)
            {
                double Evdw = eij * Math.Pow(r0ij / rij, 12) - eij * (2) * Math.Pow(r0ij / rij, 6); Eij += Evdw;
                double Fvdw = eij * (-12) * Math.Pow(r0ij / rij, 12) / rij - eij * (-6 * 2) * Math.Pow(r0ij / rij, 6) / rij; Fij += Fvdw;
                double Kvdw = eij * (-12 * -13) * Math.Pow(r0ij / rij, 12) / rij2 - eij * (-6 * -7 * 2) * Math.Pow(r0ij / rij, 6) / rij2; Kij += Kvdw;
            }
            if (elec)
            {
                double Eelec = (qij / eps) / (rij); Eij += Eelec;
                double Felec = (-1) * (qij / eps) / (rij * rij); Fij += Felec;
                double Kelec = (-2 * -1) * (qij / eps) / (rij * rij2); Kij += Kelec;
                HDebug.AssertIf(qij < 0, Felec > 0); /// attractive, positive pw-force
                HDebug.AssertIf(qij > 0, Felec < 0); /// repulsive , negative pw-force
            }

            if (HDebug.IsDebuggerAttached)
            {
                var KijFij = Hess.HessSpr.GetKijFijNbnd(vdW, elec
                                                        , coordi, ri0, qi, ei
                                                        , coordj, rj0, qj, ej
                                                        , D
                                                        );
                HDebug.AssertTolerance(0.00000001, Kij - KijFij.Kij);
                HDebug.AssertTolerance(0.00000001, Fij - KijFij.Fij);
            }
        }