added Verlet scheme and NxN non-bonded functionality
[alexxy/gromacs.git] / src / gmxlib / mtop_util.c
index adc441209eb725cb9cee92580beeaaa0f8825b72..7ffce2087851cdbc1dc26007f8f425c1de706484 100644 (file)
@@ -89,85 +89,250 @@ int ncg_mtop(const gmx_mtop_t *mtop)
     return ncg;
 }
 
-void gmx_mtop_atomnr_to_atom(const gmx_mtop_t *mtop,int atnr_global,
+void gmx_mtop_remove_chargegroups(gmx_mtop_t *mtop)
+{
+    int mt;
+    t_block *cgs;
+    int i;
+
+    for(mt=0; mt<mtop->nmoltype; mt++)
+    {
+        cgs = &mtop->moltype[mt].cgs;
+        if (cgs->nr < mtop->moltype[mt].atoms.nr)
+        {
+            cgs->nr = mtop->moltype[mt].atoms.nr;
+            srenew(cgs->index,cgs->nr+1);
+            for(i=0; i<cgs->nr+1; i++)
+            {
+                cgs->index[i] = i;
+            }
+        }
+    }
+}
+
+
+typedef struct
+{
+    int a_start;
+    int a_end;
+    int na_mol;
+} mb_at_t;
+
+typedef struct gmx_mtop_atomlookup
+{
+    const gmx_mtop_t *mtop;
+    int     nmb;
+    int     mb_start;
+    mb_at_t *mba;
+} t_gmx_mtop_atomlookup;
+
+
+gmx_mtop_atomlookup_t
+gmx_mtop_atomlookup_init(const gmx_mtop_t *mtop)
+{
+    t_gmx_mtop_atomlookup *alook;
+    int mb;
+    int a_start,a_end,na,na_start=-1;
+
+    snew(alook,1);
+
+    alook->mtop     = mtop;
+    alook->nmb      = mtop->nmolblock;
+    alook->mb_start = 0;
+    snew(alook->mba,alook->nmb);
+
+    a_start = 0;
+    for(mb=0; mb<mtop->nmolblock; mb++)
+    {
+        na    = mtop->molblock[mb].nmol*mtop->molblock[mb].natoms_mol;
+        a_end = a_start + na;
+
+        alook->mba[mb].a_start = a_start;
+        alook->mba[mb].a_end   = a_end;
+        alook->mba[mb].na_mol  = mtop->molblock[mb].natoms_mol;
+
+        /* We start the binary search with the largest block */
+        if (mb == 0 || na > na_start)
+        {
+            alook->mb_start = mb;
+            na_start        = na;
+        }
+
+        a_start = a_end;
+    }
+
+    return alook;
+}
+
+gmx_mtop_atomlookup_t
+gmx_mtop_atomlookup_settle_init(const gmx_mtop_t *mtop)
+{
+     t_gmx_mtop_atomlookup *alook;
+     int mb;
+     int na,na_start=-1;
+
+     alook = gmx_mtop_atomlookup_init(mtop);
+
+     /* Check if the starting molblock has settle */
+     if (mtop->moltype[mtop->molblock[alook->mb_start].type].ilist[F_SETTLE].nr  == 0)
+     {
+         /* Search the largest molblock with settle */
+         alook->mb_start = -1;
+         for(mb=0; mb<mtop->nmolblock; mb++)
+         {
+             if (mtop->moltype[mtop->molblock[mb].type].ilist[F_SETTLE].nr > 0)
+             {
+                 na = alook->mba[mb].a_end - alook->mba[mb].a_start;
+                 if (alook->mb_start == -1 || na > na_start)
+                 {
+                     alook->mb_start = mb;
+                     na_start        = na;
+                 }
+             }
+         }
+
+         if (alook->mb_start == -1)
+         {
+             gmx_incons("gmx_mtop_atomlookup_settle_init called without settles");
+         }
+     }
+
+     return alook;
+}
+
+void
+gmx_mtop_atomlookup_destroy(gmx_mtop_atomlookup_t alook)
+{
+    sfree(alook->mba);
+    sfree(alook);
+}
+
+void gmx_mtop_atomnr_to_atom(const gmx_mtop_atomlookup_t alook,
+                             int atnr_global,
                              t_atom **atom)
 {
-    int mb,a_start,a_end,atnr_mol;
+    int mb0,mb1,mb;
+    int a_start,atnr_mol;
 
+#ifdef DEBUG_MTOP
     if (atnr_global < 0 || atnr_global >= mtop->natoms)
     {
-        gmx_fatal(FARGS,"gmx_mtop_atomnr_to_atom was called with atnr_global=%d which is not in the atom range of this system (%d-%d)",
+        gmx_fatal(FARGS,"gmx_mtop_atomnr_to_moltype was called with atnr_global=%d which is not in the atom range of this system (%d-%d)",
                   atnr_global,0,mtop->natoms-1);
     }
-    
-    mb = -1;
-    a_end = 0;
-    do
+#endif
+
+    mb0 = -1;
+    mb1 = alook->nmb;
+    mb  = alook->mb_start;
+        
+    while (TRUE)
     {
-        mb++;
-        a_start = a_end;
-        a_end = a_start + mtop->molblock[mb].nmol*mtop->molblock[mb].natoms_mol;
+        a_start = alook->mba[mb].a_start;
+        if (atnr_global < a_start)
+        {
+            mb1 = mb;
+        }
+        else if (atnr_global >= alook->mba[mb].a_end)
+        {
+            mb0 = mb;
+        }
+        else
+        {
+            break;
+        }
+        mb = ((mb0 + mb1 + 1)>>1);
     }
-    while (atnr_global >= a_end);
     
-    atnr_mol = (atnr_global - a_start) % mtop->molblock[mb].natoms_mol;
+    atnr_mol = (atnr_global - a_start) % alook->mba[mb].na_mol;
 
-    *atom = &mtop->moltype[mtop->molblock[mb].type].atoms.atom[atnr_mol];
+    *atom = &alook->mtop->moltype[alook->mtop->molblock[mb].type].atoms.atom[atnr_mol];
 }
 
-void gmx_mtop_atomnr_to_ilist(const gmx_mtop_t *mtop,int atnr_global,
+void gmx_mtop_atomnr_to_ilist(const gmx_mtop_atomlookup_t alook,
+                              int atnr_global,
                               t_ilist **ilist_mol,int *atnr_offset)
 {
-    int mb,a_start,a_end,atnr_local;
+    int mb0,mb1,mb;
+    int a_start,atnr_local;
 
+#ifdef DEBUG_MTOP
     if (atnr_global < 0 || atnr_global >= mtop->natoms)
     {
         gmx_fatal(FARGS,"gmx_mtop_atomnr_to_moltype was called with atnr_global=%d which is not in the atom range of this system (%d-%d)",
                   atnr_global,0,mtop->natoms-1);
     }
-    
-    mb = -1;
-    a_end = 0;
-    do
+#endif
+
+    mb0 = -1;
+    mb1 = alook->nmb;
+    mb  = alook->mb_start;
+        
+    while (TRUE)
     {
-        mb++;
-        a_start = a_end;
-        a_end = a_start + mtop->molblock[mb].nmol*mtop->molblock[mb].natoms_mol;
+        a_start = alook->mba[mb].a_start;
+        if (atnr_global < a_start)
+        {
+            mb1 = mb;
+        }
+        else if (atnr_global >= alook->mba[mb].a_end)
+        {
+            mb0 = mb;
+        }
+        else
+        {
+            break;
+        }
+        mb = ((mb0 + mb1 + 1)>>1);
     }
-    while (atnr_global >= a_end);
 
-    *ilist_mol = mtop->moltype[mtop->molblock[mb].type].ilist;
+    *ilist_mol = alook->mtop->moltype[alook->mtop->molblock[mb].type].ilist;
     
-    atnr_local = (atnr_global - a_start) % mtop->molblock[mb].natoms_mol;
+    atnr_local = (atnr_global - a_start) % alook->mba[mb].na_mol;
 
     *atnr_offset = atnr_global - atnr_local;
 }
 
-void gmx_mtop_atomnr_to_molblock_ind(const gmx_mtop_t *mtop,int atnr_global,
+void gmx_mtop_atomnr_to_molblock_ind(const gmx_mtop_atomlookup_t alook,
+                                     int atnr_global,
                                      int *molb,int *molnr,int *atnr_mol)
 {
-    int mb,a_start,a_end;
-    t_atoms *atoms;
+    int mb0,mb1,mb;
+    int a_start;
 
+#ifdef DEBUG_MTOP
     if (atnr_global < 0 || atnr_global >= mtop->natoms)
     {
         gmx_fatal(FARGS,"gmx_mtop_atomnr_to_moltype was called with atnr_global=%d which is not in the atom range of this system (%d-%d)",
                   atnr_global,0,mtop->natoms-1);
     }
-    
-    mb = -1;
-    a_end = 0;
-    do
+#endif
+
+    mb0 = -1;
+    mb1 = alook->nmb;
+    mb  = alook->mb_start;
+        
+    while (TRUE)
     {
-        mb++;
-        a_start = a_end;
-        a_end = a_start + mtop->molblock[mb].nmol*mtop->molblock[mb].natoms_mol;
+        a_start = alook->mba[mb].a_start;
+        if (atnr_global < a_start)
+        {
+            mb1 = mb;
+        }
+        else if (atnr_global >= alook->mba[mb].a_end)
+        {
+            mb0 = mb;
+        }
+        else
+        {
+            break;
+        }
+        mb = ((mb0 + mb1 + 1)>>1);
     }
-    while (atnr_global >= a_end);
 
     *molb  = mb;
-    *molnr = (atnr_global - a_start) / mtop->molblock[mb].natoms_mol;
-    *atnr_mol = atnr_global - a_start - (*molnr)*mtop->molblock[mb].natoms_mol;
+    *molnr = (atnr_global - a_start) / alook->mba[mb].na_mol;
+    *atnr_mol = atnr_global - a_start - (*molnr)*alook->mba[mb].na_mol;
 }
 
 void gmx_mtop_atominfo_global(const gmx_mtop_t *mtop,int atnr_global,