CCL Home Page
Up Directory CCL write_mm2
/*============================================================================*/
/* FILENAME: WRITE_MM2.C (WRITE_MM2.O)
/* PURPOSE: TO WRITE OUT THE CURRENT GEOMETRY AS AN MM2 INPUT FILE.
/* WRITTEN: M.V.GRIESHABER
/* MODIFICATIONS:
/*	22 JULY 1993 MVG (INCREASED RUN TIME TO MAX LIMIT).
/*	12 JULY 1993 MVG (CORRECTED SOME MM3 ONLY ATOM TYPES).
/*	8 FEBRUARY 1993 MVG (EXTENDED SYBYL ATOM TYPES, NEW MM3 TYPES).
/*============================================================================*/

#include "utility.h"
#include "newgeo.h"

#define MAX_RINGS 100			/* MAX RINGS IN A MOLECULE. */
#define MAX_CONNECTED_ATOM_LISTS 20	/* ONE LIST PER LINE. */
#define MAX_ATTACHED_ATOM_LISTS 20	/* REALLY ONLY ONE LIST, BUT SPREAD ACROSS THIS MANY LINES. */
#define MAX_ATOMS_PER_LIST 16		/* REALLY MAX ATOMS NUMBERS PER LINE. */
#define TERMINATION_ENERGY 0.00008	/* OPTIMIZATION TERMINATION (KCAL/MOLE). */
#define MM2_LONE_PAIR_TYPE 20		/* FOR AUTO ADD OF LONE PAIRS. */
#define MM2_LONE_PAIR_RADIUS 0.6	/* FOR AUTO ADD OF LONE PAIRS. */

typedef struct				/* DEFINE A LIST OF ATOMS. */
   {
   int natoms;				/* NUMBER OF ATOMS IN LIST. */
   int atoms[MAX_ATOMS];		/* ATOM INDEX. */
   } ATOM_LIST;

int nrings;				/* NUMBER OF RINGS IN LIST. */
ATOM_LIST rings[MAX_RINGS];		/* UNIQUE RINGS IN MOLECULE. */

int ring_candidate_atom[MAX_ATOMS];	/* T/F: CONSIDER ATOM IN RING SEARCH. */
int ring_check_atom[MAX_ATOMS];		/* T/F: CHECK ATOM FOR RING. */

int write_mm2_input(geometry_type,outfile)
/*============================================================================*/
/* PURPOSE: TO WRITE OUT THE CURRENT GEOMETRY AS AN MM2 OR MM3 INPUT FILE.
*/
   int geometry_type;		/* SPECIFIES MM2 OR MM3 TYPE FILE. */
   FILE *outfile;		/* MM2 FORMAT OUTPUT. */
   {
   int target_atom;		/* ATOM TO LOOK FOR. */
   int current_atom;		/* ATOM WE ARE PRESENTLY AT. */
   int previous_atom;		/* ATOM WE WERE PREVIOUSLY AT. */
   ATOM_LIST path;		/* PATH FOLLOWED DURING SEARCH. */
   int natom;			/* WHICH ATOM. */
   int aromatics_exist;		/* T/F: WHETHER AROMATIC ATOMS EXIST IN MOLECULE. */
   int nlone_pairs;		/* TOTAL ADD_LONE_PAIRS FLAGS. */
   int nconnected_atom_lists;	/* TOTAL CONNECTED ATOM LISTS. */
   int connected_atom_lists[MAX_CONNECTED_ATOM_LISTS][MAX_ATOMS_PER_LIST];
   int nattached_atoms;		/* TOTAL ATTACHED ATOMS IN MOLECULE. */
   int attached_atom_lists[MAX_ATTACHED_ATOM_LISTS][MAX_ATOMS_PER_LIST];
   char line[150];		/* MULTIPURPOSE STRING. */
   char default_title[100];	/* DEFAULT TITLE. */
   int nlist;			/* WHICH LIST. */
   int status;			/* RETURN STATUS FROM USER INTERFACE ROUTINES. */
   struct
      {
      int atom_type;		/* MM2 ATOM TYPE. */
      int aromatic;		/* T/F: AROMATIC ATOM TYPE. */
      int add_lone_pairs;	/* T/F: WHETHER TO AUTO ADD LONE PAIRS. */
      } mm2_data[MAX_ATOMS];	/* SAVED VALUES FROM MM2_ATOM_TYPE ROUTINE. */

   void find_rings();		/* FIND RINGS FROM CURRENT TO TARGET ATOM. */
   void mark_ring_atoms();	/* DETERMINE WHICH ATOMS TO CONSIDER FOR RINGS. */
   void filter_atom_type();	/* FILTER SPECIFIED ATOM TYPE. */

   /* FILTER OUT LONE PAIRS (AUTOMATICALLY ADDED AS NEEDED) AND DUMMY ATOMS. */
   /* WARN USER IF ANY DUMMY ATOMS WERE DELETED. */
   filter_atom_type("LP");
   for (natom=0; natom0) fprintf(outfile,"%5d",connected_atom_lists[nlist][natom]);
         else fprintf(outfile,"     ");
         }
      fprintf(outfile,"\n");
      }

   /* LINE 4 (ATTACHED ATOM LIST). */
   for (nlist=0; nlist<((nattached_atoms*2-1)/MAX_ATOMS_PER_LIST)+1; nlist++)
      {
      for (natom=0; natom0) fprintf(outfile,"%5d",attached_atom_lists[nlist][natom]);
         else fprintf(outfile,"     ");
         }
      fprintf(outfile,"\n");
      }

   /* LINE 5 (COORDINATES). */
   for (natom=0; natom=3 BONDS. */

   /* TO START, ASSUME ALL ATOMS ARE BOTH "RING" AND "RING CHECK" CANDIDATES. */
   for (natom=0; natom0)
      {
      /* HAVE A (POSSIBLY UNIQUE) RING, LOG IT. */
      log_ring(path);
      }
   else if (already_visited(current_atom,path))
      {
      /* ALREADY VISITED THIS ATOM, CAN'T CROSS PATH SO NO FURTHER ACTION. */
      }
   else
      {
      /* FOLLOW EACH BOND THAT IS AVAILABLE FROM THE CURRENT ATOM. */
      for (nbond=0; nbond3)
               mm2_type=60;	/* MM3 ONLY: P(V). */
            else
               mm2_type=25;	/* PHOSPHINE. */
            break;

         case 13:		/* SYBYL TYPE H (HYDROGEN). */
            if (connected_to("5",index,-1) || connected_to("6",index,-1) || connected_to("19",index,-1))
               mm2_type=23;	/* AMINE. */
            else if (connected_to("28",index,-1))
               mm2_type=28;	/* AMIDE. */
            else if (connected_to("31",index,-1))
               mm2_type=48;	/* AMMONIUM. */
            else if (connected_to("8 2 9",index,-1))
               mm2_type=24;	/* ACID. */
            else if (connected_to("8 2",index,-1))
               mm2_type=73;	/* ENOL. */
            else if (connected_to("8",index,-1))
               mm2_type=21;	/* ALCOHOL. */
            else if (geometry_type==TYPE_MM3_INPUT &&
               (connected_to("10",index,-1) || connected_to("18",index,-1) ||
               connected_to("29",index,-1) || connected_to("30",index,-1)))
               mm2_type=44;	/* MM3 ONLY: THIOL. */
            else
               mm2_type=5;	/* PLAIN HYDROGEN. */
            break;

         case 14:		/* SYBYL TYPE Br (BROMINE). */
            mm2_type=13;	/* BROMINE. */
            break;

         case 15:		/* SYBYL TYPE Cl (CHLORINE). */
            mm2_type=12;	/* CHLORINE. */
            break;

         case 16:		/* SYBYL TYPE F (FLUORINE). */
            mm2_type=11;	/* FLUORINE. */
            break;

         case 17:		/* SYBYL TYPE I (IODINE). */
            mm2_type=14;	/* IODINE. */
            break;

         case 18:		/* SYBYL TYPE S.2 (SP2 SULFUR). */
            if (in_non_c3_ring(5,index))
               {
               mm2_type=42;	/* THIOPHENE. */
               *set_aromatic_flag=TRUE;
               }
            else if (connected_to("2",index,-1) && intco[index].bond_cnt==1)
               mm2_type=17;	/* THIOCARBONYL SULFUR. */
            else
               mm2_type=15;	/* SP3 SULFUR. */
            break;

         case 19:		/* SYBYL TYPE N.pl3 (PLANAR TRIGONAL NITROGEN). */
            if (in_non_c3_ring(5,index) || in_non_c3_ring(6,index))
               {
               if (intco[index].bond_cnt==3)
                  {
                  mm2_type=40;	/* PYROLE NITROGEN. */
                  *set_aromatic_flag=TRUE;
                  }
               else
                  {
                  mm2_type=37;	/* PYRIDINE NITROGEN. */
                  *set_aromatic_flag=TRUE;
                  *add_lone_pairs=TRUE;
                  }
               }
            else if (connected_to("9",index,-1)==2)
               mm2_type=46;	/* NITRO. */
            else if (geometry_type==TYPE_MM3_INPUT &&
               (connected_to("6",index,-1) || connected_to("11",index,-1) || connected_to("19",index,-1)))
               {
               if (connected_to("8",index,-1))
                  mm2_type=109;	/* AZOXY NITROGEN. */
               else
                  mm2_type=107;	/* AZO NITROGEN. */
               }
            else
               {
               mm2_type=8;	/* SP3 NITROGEN. */
               *add_lone_pairs=TRUE;
               }
            break;

         case 20:		/* SYBYL TYPE LP (LONE PAIR). */
            /* ALL LONE PAIRS WERE INITIALLY DELETED AND REPLACED AS NEEDED. */
            mm2_type=99;	/* THIS CASE SHOULD NEVER BE EXECUTED. */
            break;

         case 21:		/* SYBYL TYPE Na (SODIUM). */
         case 22:		/* SYBYL TYPE K (POTASSIUM). */
         case 23:		/* SYBYL TYPE Ca (CALCIUM). */
         case 24:		/* SYBYL TYPE Li (LITHIUM). */
         case 25:		/* SYBYL TYPE Al (ALUMINUM). */
            /* NO CORRESPONDING MM2 TYPE. */
            printf("Warning: Atom #%d (SYBYL type %d) has no corresponding MM2 atom type.\n",index+1,intco[index].source_type);
            printf("         MM2 type 99 has been used; manual editing of file is required.\n");
            mm2_type=99;
            break;

         case 26:		/* SYBYL TYPE Du (DUMMY). */
            /* ALL DUMMIES WERE PREVIOUSLY DELETED. */
            mm2_type=99;	/* THIS CASE SHOULD NEVER BE EXECUTED. */
            break;

         case 27:		/* SYBYL TYPE Si (SILICON). */
            mm2_type=19;	/* SILANE. */
            break;

         case 28:		/* SYBYL TYPE N.am (AMIDE NITROGEN). */
            mm2_type=9;		/* AMIDE. */
            break;

         case 29:		/* SYBYL TYPE S.O (SULFOXIDE). */
            mm2_type=17;	/* SULFOXIDE. */
            break;

         case 30:		/* SYBYL TYPE S.O2 (SULFONE). */
            mm2_type=18;	/* SULFONE. */
            break;

         case 31:		/* SYBYL TYPE N.4 (AMMONIUM). */
            mm2_type=39;	/* AMMONIUM. */
            break;

         case 32:		/* SYBYL TYPE O.co2 (CARBOXYLATE). */
            mm2_type=47;	/* CARBOXYLATE. */
            break;

         case 33:		/* SYBYL TYPE C.cat (CARBOCATION). */
            mm2_type=30;	/* CARBOCATION. */
            break;

         case 906:		/* SYBYL TYPE Co.oh (COBALT). */
            mm2_type=66;	/* COBALT (III). */
            break;

         case 910:		/* SYBYL TYPE Fe (IRON). */
            mm2_type=62;	/* IRON (III). */
            break;

         case 911:		/* SYBYL TYPE Ni (NICKEL). */
            mm2_type=63;	/* NICKEL (II). */
            break;

         case 915:		/* SYBYL TYPE Ge (GERMANIUM). */
            mm2_type=31;	/* GERMANIUM. */
            break;

         case 917:		/* SYBYL TYPE Se (SELENIUM). */
            mm2_type=34;	/* SELENIUM. */
            break;

         case 918:		/* SYBYL TYPE Kr (KRYPTON). */
            mm2_type=54;	/* KRYPTON. */
            break;

         case 931:		/* SYBYL TYPE Sn (TIN). */
            mm2_type=32;	/* TIN. */
            break;

         case 933:		/* SYBYL TYPE Te (TELLURIUM). */
            mm2_type=35;	/* TELLURIUM. */
            break;

         case 934:		/* SYBYL TYPE Xe (XENON). */
            mm2_type=55;	/* XENON. */
            break;

         case 948:		/* SYBYL TYPE Pb (LEAD). */
            mm2_type=33;	/* LEAD. */
            break;

         case 984:		/* SYBYL TYPE He (HELIUM). */
            mm2_type=51;	/* HELIUM. */
            break;

         case 987:		/* SYBYL TYPE Ne (NEON). */
            mm2_type=52;	/* NEON. */
            break;

         case 988:		/* SYBYL TYPE Mg (MAGNESIUM). */
            mm2_type=59;	/* MAGNESIUM. */
            break;

         case 990:		/* SYBYL TYPE Ar (ARGON). */
            mm2_type=53;	/* ARGON. */
            break;

         default:		/* UNKNOWN SYBYL ATOM TYPE. */
            printf("Warning: Atom #%d (SYBYL type %d) is an unknown SYBYL atom type.\n",index+1,intco[index].source_type);
            printf("         MM2/MM3 type 99 has been used; manual editing of file is required.\n");
            mm2_type=99;
            break;
         }
         return(mm2_type);
      }
   else
      {
      /* DO A CRUDE CONVERSION FROM A NON SYBYL SOURCE TYPE TO MM2 ATOM TYPE. */
      printf("Error: Non SYBYL source type to MM2/MM3 conversion not yet implemented.\n");
      return(-1);
      }
   }

int in_three_member_ring(index)
/*============================================================================*/
/* PURPOSE: DETERMINE WHETHER OR NOT THE SPECIFIED ATOM IS CONTAINED IN A
/*	THREE MEMBER RING.
*/
   int index;	/* ATOM INDEX. */
   {
   int nring;	/* WHICH RING. */
   int natom;	/* WHICH ATOM. */

   /* EXAMINE EACH THREE MEMBER RING FOR INCLUSION OF INDEX ATOM. */
   for (nring=0; nring0) nconnections+=connected_to(chain,new_atom,current_atom);
         else nconnections++;
         }
      }

   /* RETURN NUMBER OF DIFFERENT SUBPATHS FROM THE CURRENT ATOM THAT MEET */
   /* THE REST OF THE CHAIN ORDER. */
   return(nconnections);
   }

int make_connected_atom_lists(connected_atom_lists)
/*============================================================================*/
/* PURPOSE: CREATE THE "CONNECTED" ATOM LISTS FOR MM2 FROM THE CURRENT MOLECULE.
/*	A "CONNECTED" ATOM IS ANY ATOM WITH AT LEAST TWO BONDS TO IT.  ALL BONDS
/*	IN THE MOLECULE MUST SHOW UP IN THE CONNECTED LISTS (EXCEPT THOSE TO
/*	"ATTACHED" ATOMS).
*/
   int connected_atom_lists[MAX_CONNECTED_ATOM_LISTS][MAX_ATOMS_PER_LIST];
   {
   int natom;			/* WHICH ATOM. */
   int nbond;			/* WHICH BOND. */
   int nlist;			/* WHICH LIST. */
   int first_unused_atom;	/* FIRST ATOM WITH UNUSED BONDS. */
   int bonds_used[MAX_ATOMS][MAX_BONDS_PER_ATOM];	/* T/F; BOND USED IN LIST. */

   void mark_all_attached_atom_bonds();	/* MARK ATTACHED ATOM BONDS AS USED. */
   void make_connected_atom_list();	/* FORM SINGLE CHAIN FROM ROOT ATOM. */

   for (nlist=0; nlist1)
            {
            nlist++;
            connected_atom_lists[nlist][0]=natom+1;	/* INDEX FROM ONE FOR MM2. */
            break;	/* THERE CAN ONLY BE ONE SUCH ATOM. */
            }
         }
      }

   return(nlist+1);	/* RETURN TOTAL NUMBER OF CONNECTION LISTS USED. */
   }

void mark_all_attached_atom_bonds(bonds_used)
/*============================================================================*/
/* PURPOSE: MARK ALL BONDS TO OR FROM AN ATTACHED ATOM (ANY ATOM WITH ONLY ONE
/*	BOND IS AN ATTACHED ATOM) AS USED SO THEY WILL NOT BE CONSIDERED IN
/*	THE SEARCH FOR CONNECTED ATOMS.
*/
   int bonds_used[MAX_ATOMS][MAX_BONDS_PER_ATOM];	/* T/F; BOND USED IN LIST. */
   {
   int natom;			/* WHICH ATOM. */

   void mark_bond_used();	/* MARK BOND AND RECIPROCAL BOND AS USED. */

   for (natom=0; natom= 1 UNUSED BOND. */
   int bonds_used[MAX_ATOMS][MAX_BONDS_PER_ATOM];	/* T/F; BOND USED IN LIST. */
   {
   int natom;			/* WHICH ATOM. */
   int nbond;			/* WHICH BOND. */

   /* SCAN EACH BOND OF EACH ATOM FOR THE FIRST UNUSED BOND. */
   for (natom=0; natom=MAX_ATOMS_PER_LIST) return;	/* LIST IS FULL, STOP HERE. */

   for (nbond=0; nbond MAX_ATOMS_PER_LIST)
            {
            nlist++;	/* FILLED UP ONE LIST, ROLL OVER TO THE NEXT ONE. */
            natoms_in_list=1;
            if (nlist+1 > MAX_ATTACHED_ATOM_LISTS)
               {
               printf("Error: Maximum number of attached atom lists exceeded, file is incorrect.\n");
               return(nlist);	/* TRUNCATE AT THE MAXIMUM. */
               }
            }
         /* ADD ROOT AND ATTACHED ATOM (ADJUST TO INDEX FROM ONE FOR MM2). */
         attached_atom_lists[nlist][(natoms_in_list-1)*2]=intco[natom].bonds[0]+1;
         attached_atom_lists[nlist][(natoms_in_list-1)*2+1]=natom+1;
         }
      }

   return(nattached_atoms);	/* RETURN TOTAL NUMBER OF ATTACHED ATOMS. */
   }

Modified: Fri Feb 11 17:00:00 1994 GMT
Page accessed 1454 times since Sat Apr 17 21:58:51 1999 GMT