コード例 #1
0
//----------------------------------------------------------------------
//Keeping this separate from calcLoc for efficiency reasons..
//It's most likely faster to add to a double than fill matrices..
//We also don't need to calculate the ion-ion interaction for this
void Molecular_system::separatedLocal(Sample_point * sample,Array1 <doublevar> & onebody,
    Array2 <doublevar> & twobody)
{
  int nions=sample->ionSize();
  int nelectrons=sample->electronSize();
  onebody.Resize(nelectrons);
  twobody.Resize(nelectrons,nelectrons);
  onebody=0.0; twobody=0.0;
  Array1 <doublevar> R(5);
  sample->updateEIDist();
  sample->updateEEDist();

  for(int e=0; e< nelectrons; e++) {
    for(int i=0; i < nions; i++) {
      sample->getEIDist(e,i, R);
      onebody(e)-=sample->getIonCharge(i)/R(0);
    }
  }
  Array1 <doublevar> R2(5);
  for(int i=0; i< nelectrons; i++) {
    for(int j=i+1; j<nelectrons; j++) {
      sample->getEEDist(i,j,R2);
      twobody(i,j)+= 1/R2(0);
    }
  }

  Array1 <doublevar> pos(3);
  for(int e=0; e< nelectrons; e++) {
    sample->getElectronPos(e,pos);
    for(int d=0; d< 3; d++) 
      onebody(e)-=electric_field(d)*pos(d);
  }
}
コード例 #2
0
void Molecular_system::calcLocWithTestPos(Sample_point * sample,
                                          Array1 <doublevar> & tpos,
                                          Array1 <doublevar> & Vtest) {

  int nions=sample->ionSize();
  int nelectrons=sample->electronSize();
  Vtest.Resize(nelectrons + 1);
  Vtest = 0; 
  Array1 <doublevar> oldpos(3);
  //cout << "Calculating local energy\n";
  sample->getElectronPos(0, oldpos);
  sample->setElectronPosNoNotify(0, tpos);
  
  Array1 <doublevar> R(5);

  sample->updateEIDist();
  sample->updateEEDist();

  for(int i=0; i < nions; i++) {
    sample->getEIDist(0, i, R);
    Vtest(nelectrons)+=-sample->getIonCharge(i)/R(0);
  }
  doublevar dist = 0.0; 
  for(int d=0; d<3; d++)  {
    dist += (oldpos(d) - tpos(d))*(oldpos(d) - tpos(d)); 
  }
  dist = sqrt(dist); 
  Vtest(0) = 1/dist; 
  Array1 <doublevar> R2(5);
  for(int i=1; i< nelectrons; i++) {
    sample->getEEDist(0,i,R2);
    Vtest(i)= 1/R2(0);
  }
  sample->setElectronPosNoNotify(0, oldpos);
  sample->updateEIDist();
  sample->updateEEDist();
  //cout << "elec-elec: " << elecElec << endl;
  //cout << "pot " << pot << endl;

  for(int d=0; d< 3; d++) 
    Vtest(nelectrons) -=electric_field(d)*tpos(d);
}
コード例 #3
0
int Molecular_system::read(vector <string> & words,
                           unsigned int & pos)
{
  nspin.Resize(2);
  unsigned int startpos=pos;
  vector <string> spintxt;
  if(!readsection(words, pos, spintxt, "NSPIN")) {
    error("Need NSPIN in molecular system");
  }
  nspin(0)=atoi(spintxt[0].c_str());
  nspin(1)=atoi(spintxt[1].c_str());

  //restrcit initial walkers to a given range
  vector <string> inirangetxt;
  if(readsection(words, pos=0, inirangetxt, "INIRANGE")) {
    cout << "You are using a range of initial walkers other than default." << endl;
    if(inirangetxt.size()==0){
      error("You want to restrict the range of initial walkers, but you didn't give a range");
    }
    inirange=atof(inirangetxt[0].c_str());
  }
  else {
    inirange=3.0;
  }
  
  //use a bounding box if it's given
  vector <string> boxtxt;
  if(readsection(words, pos=0, boxtxt, "BOUNDING_BOX")) {
    const int ndim=3;
    if(boxtxt.size() != ndim*ndim) {
      error("need ", ndim*ndim," elements in BOUNDING_BOX");
    }
    Array2 <doublevar> latVec(ndim, ndim);
    for(int i=0; i< ndim; i++) {
      for(int j=0; j< ndim; j++) {
        latVec(i,j)=atof(boxtxt[i*ndim+j].c_str());
      }
    }
    Array1 <doublevar> origin(ndim);
    origin=0;
    vector <string> origintxt;
    if(readsection(words, pos=0, origintxt, "ORIGIN")) {
      for(int i=0; i < ndim; i++) origin(i)=atof(origintxt[i].c_str());
    }
    bounding_box.init(latVec);
    bounding_box.setOrigin(origin);
    use_bounding_box=1;
  }
  else {
    use_bounding_box=0;
  }
  
  
  
  ions.read(words, pos=0);
  int natoms=ions.size();
  for(int i=0; i< natoms; i++) {
    atomLabels.push_back(ions.getLabel(i));
  }


  electric_field.Resize(3);
  electric_field=0;
  vector <string> electxt;
  if(readsection(words, pos=0, electxt, "ELECTRIC_FIELD")) { 
    if(electxt.size()!=3) error("ELECTRIC_FIELD must have 3 components");
    for(int d=0; d< 3; d++) {
      electric_field(d)=atof(electxt[d].c_str());
      //cout << "efield " << electric_field(d) << endl;
    }
  }


  //---Pseudopotential
  pos=startpos;
  vector < vector <string> > pseudotext;
  vector <string> pseudotexttmp;
  if(readsection(words, pos, pseudotexttmp, "PSEUDO") != 0) {
    error("PSEUDO should go in the global space");
    pseudotext.push_back(pseudotexttmp);
  }

  //pseudo.read(pseudotext, this);
  return 1;
}
コード例 #4
0
doublevar Molecular_system::calcLoc(Sample_point * sample) {
  int nions=sample->ionSize();
  int nelectrons=sample->electronSize();

  //cout << "Calculating local energy\n";

  Array1 <doublevar> R(5);
  doublevar pot=0;
  
  doublevar elecIon=0;
  sample->updateEIDist();
  sample->updateEEDist();

  for(int e=0; e< nelectrons; e++)
  {
    for(int i=0; i < nions; i++)
    {

      sample->getEIDist(e,i, R);
      elecIon+=sample->getIonCharge(i)/R(0);
    }
  }
  elecIon*=-1;
  pot+=elecIon;

  //cout << "elec-ion: " << elecIon << endl;
  Array1 <doublevar> r1(3), r2(3);
  doublevar IonIon=0;
  for(int i=0; i< nions; i++)
  {
    sample->getIonPos(i,r1);
    //cout << i << "   " << r1(2) << endl;
    for(int j=0; j<i; j++)
    {
      sample->getIonPos(j,r2);
      doublevar r=sqrt( (r1(0)-r2(0))*(r1(0)-r2(0))
                        + (r1(1)-r2(1))*(r1(1)-r2(1))
                        + (r1(2)-r2(2))*(r1(2)-r2(2)));
      IonIon+=sample->getIonCharge(i)*sample->getIonCharge(j)/r;
    }
  }
  pot+=IonIon;
  
  //cout << "Ion-ion: " << IonIon << endl;

  doublevar elecElec=0;
  Array1 <doublevar> R2(5);
  for(int i=0; i< nelectrons; i++)
  {
    for(int j=0; j<i; j++)
    {
      sample->getEEDist(j,i,R2);
      elecElec+= 1/R2(0);
    }
  }
  pot+=elecElec;
  //cout << "elec-elec: " << elecElec << endl;
  //cout << "pot " << pot << endl;

  doublevar fieldPot=0;
  Array1 <doublevar> pos(3);
  for(int e=0; e< nelectrons; e++) {
    sample->getElectronPos(e,pos);
    for(int d=0; d< 3; d++) 
      fieldPot-=electric_field(d)*pos(d);
  }
  for(int i=0; i< nions; i++) {
    sample->getIonPos(i,pos);
    for(int d=0; d< 3; d++) 
      fieldPot+=sample->getIonCharge(i)*electric_field(d)*pos(d);
  }

  pot+=fieldPot;

  return pot;
}
コード例 #5
0
ファイル: ftdock.c プロジェクト: albertsgrc/ftdock-opt
int main( int argc , char *argv[] ) {

  /* index counters */

  int	i ;

  /* Command line options */

  char		*output_file_name ;
  char		*static_file_name ;
  char		*mobile_file_name ;
  int		global_grid_size ;
  int		angle_step ;
  float		surface ;
  float		internal_value ;
  int		electrostatics ;
  int		keep_per_rotation ;
  int 		kept_scores ;
  int		rescue ;
  int		calculate ;
  float		reverse_calculated_one_span ;

  char		*default_global_grid_size ;
  char		*default_angle_step ;
  char		*default_surface ;
  char		*default_internal_value ;
  char		*default_electrostatics ;
  char		*default_keep_per_rotation ;

  /* File stuff */

  FILE		*ftdock_file ;
  char		line_buffer[100] ;
  int		id , id2 , SCscore ;
  float		RPscore ;
  int		x , y , z , z_twist , theta , phi ;

  /* Angles stuff */

  struct Angle	Angles ;
  int		first_rotation , rotation ;

  /* Structures */

  struct Structure	Static_Structure , Mobile_Structure ;
  struct Structure	Origin_Static_Structure , Origin_Mobile_Structure ;
  struct Structure	Rotated_at_Origin_Mobile_Structure ;

  /* Co-ordinates */

  int		xyz , fx , fy , fz , fxyz ;

  /* Grid stuff */

  float		grid_span , one_span ;

  float	*static_grid ;
  float	*mobile_grid ;
  float	*convoluted_grid ;

  float	*static_elec_grid = ( void * ) 0 ;
  float	*mobile_elec_grid = ( void * ) 0 ;
  float	*convoluted_elec_grid = ( void * ) 0 ;

  /* FFTW stuff */

  fftwf_plan	ps, pse, pm, pme, pinvs, pinvse;

  fftwf_complex  *static_fsg ;
  fftwf_complex  *mobile_fsg ;
  fftwf_complex  *multiple_fsg ;

  fftwf_complex  *static_elec_fsg = ( void * ) 0 ;
  fftwf_complex  *mobile_elec_fsg = ( void * ) 0 ;
  fftwf_complex  *multiple_elec_fsg = ( void * ) 0 ;

  /* Scores */

  struct Score	*Scores ;
  float		max_es_value ;

  /* Timing */

  unsigned long tb, ta;
  struct rusage rb, ra;
  struct timeval tvb, tva;

/************/

  /* Its nice to tell people what going on straight away */

  setvbuf( stdout , (char *)NULL , _IONBF , 0 ) ;


  printf( "\n          3D-Dock Suite (March 2001)\n" ) ;
  printf( "          Copyright (C) 1997-2000 Gidon Moont\n" ) ;
  printf( "          This program comes with ABSOLUTELY NO WARRANTY\n" ) ;
  printf( "          for details see license. This program is free software,\n");
  printf( "          and you may redistribute it under certain conditions.\n\n");

  printf( "          Biomolecular Modelling Laboratory\n" ) ;
  printf( "          Imperial Cancer Research Fund\n" ) ;
  printf( "          44 Lincoln's Inn Fields\n" ) ;
  printf( "          London WC2A 3PX\n" ) ;
  printf( "          +44 (0)20 7269 3348\n" ) ;
  printf( "          http://www.bmm.icnet.uk/\n\n" ) ;


  printf( "Starting FTDock (v2.0) global search program\n" ) ;


/************/

  /* Memory allocation */

  if( ( ( output_file_name  = ( char * ) malloc ( 500 * sizeof( char ) ) ) == NULL ) ||
      ( ( static_file_name  = ( char * ) malloc ( 500 * sizeof( char ) ) ) == NULL ) ||
      ( ( mobile_file_name  = ( char * ) malloc ( 500 * sizeof( char ) ) ) == NULL ) ) {
    GENERAL_MEMORY_PROBLEM
  }

/************/

  /* Command Line defaults */

  strcpy( output_file_name , "ftdock_global.dat" ) ;
  strcpy( static_file_name , " --static file name was not provided--" ) ;
  strcpy( mobile_file_name , " --mobile file name was not provided--" ) ;
  global_grid_size = 128 ;
  angle_step = 12 ;
  surface = 1.3 ;
  internal_value = -15 ;
  electrostatics = 1 ;
  keep_per_rotation = 3 ;
  rescue = 0 ;
  calculate = 1 ;
  reverse_calculated_one_span = 0.7 ;

  default_global_grid_size = "(default calculated)" ;
  default_angle_step = "(default)" ;
  default_surface = "(default)" ;
  default_internal_value = "(default)" ;
  default_electrostatics = "(default)" ;
  default_keep_per_rotation = "(default)" ;

  /* Command Line parse */

  for( i = 1 ; i < argc ; i ++ ) {

    if( strcmp( argv[i] , "-out" ) == 0 ) {
      i ++ ;
      if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
        printf( "Bad command line\n" ) ;
        exit( EXIT_FAILURE ) ;
      }
      strcpy( output_file_name , argv[i] ) ;
    } else {
      if( strcmp( argv[i] , "-static" ) == 0 ) {
        i ++ ;
        if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
          printf( "Bad command line\n" ) ;
          exit( EXIT_FAILURE ) ;
        }
        strcpy( static_file_name , argv[i] ) ;
      } else {
        if( strcmp( argv[i] , "-mobile" ) == 0 ) {
          i ++ ;
          if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
            printf( "Bad command line\n" ) ;
            exit( EXIT_FAILURE ) ;
          }
          strcpy( mobile_file_name , argv[i] ) ;
        } else {
          if( strcmp( argv[i] , "-grid" ) == 0 ) {
            i ++ ;
            if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
              printf( "Bad command line\n" ) ;
              exit( EXIT_FAILURE ) ;
            }
            sscanf( argv[i] , "%d" , &global_grid_size ) ;
            if( ( global_grid_size % 2 ) != 0 ) {
              printf( "Grid size must be even\n" ) ;
              exit( EXIT_FAILURE ) ;
            }
            default_global_grid_size = "(user defined)" ;
            calculate = 0 ;
          } else {
            if( strcmp( argv[i] , "-angle_step" ) == 0 ) {
              i ++ ;
              if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                printf( "Bad command line\n" ) ;
                exit( EXIT_FAILURE ) ;
              }
              sscanf( argv[i] , "%d" , &angle_step ) ;
              default_angle_step = "(user defined)" ;
            } else {
              if( strcmp( argv[i] , "-surface" ) == 0 ) {
                i ++ ;
                if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                  printf( "Bad command line\n" ) ;
                  exit( EXIT_FAILURE ) ;
                }
                sscanf( argv[i] , "%f" , &surface ) ;
                default_surface = "(user defined)" ;
              } else {
                if( strcmp( argv[i] , "-internal" ) == 0 ) {
                  i ++ ;
                  if( i == argc ) {
                    printf( "Bad command line\n" ) ;
                    exit( EXIT_FAILURE ) ;
                  }
                  sscanf( argv[i] , "%f" , &internal_value ) ;
                  default_internal_value = "(user defined)" ;
                } else {
                  if( strcmp( argv[i] , "-noelec" ) == 0 ) {
                    electrostatics = 0 ;
                    default_electrostatics = "(user defined)" ;
                  } else {
                    if( strcmp( argv[i] , "-keep" ) == 0 ) {
                      i ++ ;
                      if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                        printf( "Bad command line\n" ) ;
                        exit( EXIT_FAILURE ) ;
                      }
                      sscanf( argv[i] , "%d" , &keep_per_rotation ) ;
                      default_keep_per_rotation = "(user defined)" ;
                    } else {
                      if( strcmp( argv[i] , "-rescue" ) == 0 ) {
                        rescue = 1 ;
                      } else {
                        if( strcmp( argv[i] , "-calculate_grid" ) == 0 ) {
                          i ++ ;
                          if( ( i == argc ) || ( strncmp( argv[i] , "-" , 1 ) == 0 ) ) {
                            printf( "Bad command line\n" ) ;
                            exit( EXIT_FAILURE ) ;
                          }
                          calculate = 1 ;
                          default_global_grid_size = "(user defined calculated)" ;
                          sscanf( argv[i] , "%f" , &reverse_calculated_one_span ) ;
                        } else {
                          printf( "Bad command line\n" ) ;
                          exit( EXIT_FAILURE ) ;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

  }

/************/

  /* Rescue option */

  if( rescue == 1 ) {

    printf( "RESCUE mode\n" ) ;

    if( ( ftdock_file = fopen( "scratch_parameters.dat" , "r" ) ) == NULL ) {
      printf( "Could not open scratch_parameters.dat for reading.\nDying\n\n" ) ;
      exit( EXIT_FAILURE ) ;
    }

    calculate = 0 ;

    default_global_grid_size = "(read from rescue file)" ;
    default_angle_step = "(read from rescue file)" ;
    default_surface = "(read from rescue file)" ;
    default_internal_value = "(read from rescue file)" ;
    default_electrostatics = "(read from rescue file)" ;

    while( fgets( line_buffer , 99 , ftdock_file ) ) {

      if( strncmp( line_buffer , "Static molecule" , 15 ) == 0 ) sscanf( line_buffer , "Static molecule :: %s" , static_file_name ) ;
      if( strncmp( line_buffer , "Mobile molecule" , 15 ) == 0 ) sscanf( line_buffer , "Mobile molecule :: %s" , mobile_file_name ) ;
      if( strncmp( line_buffer , "Output file name" , 16 ) == 0 ) sscanf( line_buffer , "Output file name :: %s" , output_file_name ) ;
      if( strncmp( line_buffer , "Global grid size" , 16 ) == 0 ) sscanf( line_buffer , "Global grid size :: %d" , &global_grid_size ) ;
      if( strncmp( line_buffer , "Global search angle step" , 24 ) == 0 ) sscanf( line_buffer , "Global search angle step :: %d" , &angle_step ) ;
      if( strncmp( line_buffer , "Global surface thickness" , 24 ) == 0 ) sscanf( line_buffer , "Global surface thickness :: %f" , &surface ) ;
      if( strncmp( line_buffer , "Global internal deterrent value" , 31 ) == 0 ) sscanf( line_buffer , "Global internal deterrent value :: %f" , &internal_value ) ;
      if( strncmp( line_buffer , "Electrostatics                     ::     on" , 44 ) == 0 ) electrostatics = 1 ;
      if( strncmp( line_buffer , "Electrostatics                     ::    off" , 44 ) == 0 ) electrostatics = 0 ;
      if( strncmp( line_buffer , "Global keep per rotation" , 25 ) == 0 ) sscanf( line_buffer , "Global keep per rotation :: %d" , &keep_per_rotation ) ;

    }

    fclose( ftdock_file ) ;

    if( ( ftdock_file = fopen( "scratch_scores.dat" , "r" ) ) == NULL ) {
      printf( "Could not open scratch_scores.dat for reading.\nDying\n\n" ) ;
      exit( EXIT_FAILURE ) ;
    }

    char* r = fgets( line_buffer , 99 , ftdock_file ) ;

    while( fgets( line_buffer , 99 , ftdock_file ) ) {

      sscanf( line_buffer , "G_DATA %d " , &first_rotation ) ;

    }

    fclose( ftdock_file ) ;

    first_rotation ++ ;

    printf( "Will be starting from rotation %d\n" , first_rotation ) ;

/************/

  } else {

    first_rotation = 1 ;

  }

/************/

  /* Do these things first so that bad inputs will be caught soonest */

  /* Read in Structures from pdb files */
  Static_Structure = read_pdb_to_structure( static_file_name ) ;
  Mobile_Structure = read_pdb_to_structure( mobile_file_name ) ;

  if( Mobile_Structure.length > Static_Structure.length ) {
    printf( "WARNING\n" ) ;
    printf( "The mobile molecule has more residues than the static\n" ) ;
    printf( "Are you sure you have the correct molecules?\n" ) ;
    printf( "Continuing anyway\n" ) ;
  }

/************/

  /* Get angles */
  Angles = generate_global_angles( angle_step ) ;

  printf( "Total number of rotations is %d\n" , Angles.n ) ;

/************/

  /* Assign charges */

  if( electrostatics == 1 ) {
    printf( "Assigning charges\n" ) ;
    assign_charges( Static_Structure ) ;
    assign_charges( Mobile_Structure ) ;
  }

/************/

  /* Store new structures centered on Origin */

  Origin_Static_Structure = translate_structure_onto_origin( Static_Structure ) ;
  Origin_Mobile_Structure = translate_structure_onto_origin( Mobile_Structure ) ;

  /* Free some memory */

  for( i = 1 ; i <= Static_Structure.length ; i ++ ) {
    free( Static_Structure.Residue[i].Atom ) ;
  }
  free( Static_Structure.Residue ) ;

  for( i = 1 ; i <= Mobile_Structure.length ; i ++ ) {
    free( Mobile_Structure.Residue[i].Atom ) ;
  }
  free( Mobile_Structure.Residue ) ;

/************/

  /* Calculate Grid stuff */

  grid_span = total_span_of_structures( Origin_Static_Structure , Origin_Mobile_Structure ) ;

  if( calculate == 1 ) {
    printf( "Using automatic calculation for grid size\n" ) ;
    global_grid_size = (int)( grid_span / reverse_calculated_one_span ) ;
    if( ( global_grid_size % 2 ) != 0 ) global_grid_size ++ ;
  }

  one_span = grid_span / (float)global_grid_size ;

  printf( "Span = %.3f angstroms\n" , grid_span ) ;
  printf( "Grid size = %d\n" , global_grid_size ) ;
  printf( "Each Grid cube = %.5f angstroms\n" , one_span ) ;

/************/

  /* Memory Allocation */

  if( ( Scores = ( struct Score * ) malloc ( ( keep_per_rotation + 2 ) * sizeof( struct Score ) ) ) == NULL ) {
    GENERAL_MEMORY_PROBLEM
  }

  if(
    ( ( static_grid = ( float * ) malloc
     ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
    ||
    ( ( mobile_grid = ( float * ) malloc
     ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
    ||
    ( ( convoluted_grid = ( float * ) malloc
     ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
    ) {
    printf( "Not enough memory for surface grids\nUse (sensible) smaller grid size\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  static_fsg = ( fftwf_complex * ) static_grid ;
  mobile_fsg = ( fftwf_complex * ) mobile_grid ;
  multiple_fsg = ( fftwf_complex * ) convoluted_grid ;

  if( electrostatics == 1 ) {

    if(
      ( ( static_elec_grid = ( float * ) malloc
       ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
      ||
      ( ( mobile_elec_grid = ( float * ) malloc
       ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
      ||
      ( ( convoluted_elec_grid = ( float * ) malloc
       ( global_grid_size * global_grid_size * ( 2 * ( global_grid_size / 2 + 1 ) ) * sizeof( float ) ) ) == NULL )
      ) {
      printf( "Not enough memory for electrostatic grids\nSwitch off electrostatics or use (sensible) smaller grid size\nDying\n\n" ) ;
      exit( EXIT_FAILURE ) ;
    } else {
      /* all ok */
      printf( "Electrostatics are on\n" ) ;
    }

    static_elec_fsg = ( fftwf_complex * ) static_elec_grid ;
    mobile_elec_fsg = ( fftwf_complex * ) mobile_elec_grid ;
    multiple_elec_fsg = ( fftwf_complex * ) convoluted_elec_grid ;

  }

/************/

  /* Create FFTW plans */

  printf( "Creating plans\n" ) ;
  ps    = fftwf_plan_dft_r2c_3d( global_grid_size , global_grid_size , global_grid_size , static_grid, (fftwf_complex*)static_grid,
                                FFTW_MEASURE) ;
    if( electrostatics == 1 ) {
        pse    = fftwf_plan_dft_r2c_3d( global_grid_size , global_grid_size , global_grid_size , static_elec_grid, (fftwf_complex*)static_elec_grid,
                                     FFTW_MEASURE ) ;
    }

  pm   = fftwf_plan_dft_r2c_3d( global_grid_size , global_grid_size , global_grid_size , mobile_grid, (fftwf_complex*)mobile_grid,
                               FFTW_MEASURE ) ;

    if (electrostatics == 1) {
        pme = fftwf_plan_dft_r2c_3d( global_grid_size , global_grid_size , global_grid_size , mobile_elec_grid, (fftwf_complex*)mobile_elec_grid,
                                     FFTW_MEASURE) ;
    }
  pinvs = fftwf_plan_dft_c2r_3d( global_grid_size , global_grid_size , global_grid_size , multiple_fsg, (float*)multiple_fsg,
                               FFTW_MEASURE ) ;
    if (electrostatics == 1) {
        pinvse = fftwf_plan_dft_c2r_3d( global_grid_size , global_grid_size , global_grid_size , multiple_elec_fsg, (float*)multiple_elec_fsg,
                                     FFTW_MEASURE ) ;
    }

/************/

    getrusage(RUSAGE_SELF, &rb);
    gettimeofday(&tvb, NULL);

  printf( "Setting up Static Structure\n" ) ;

  /* Discretise and surface the Static Structure (need do only once) */
  discretise_structure( Origin_Static_Structure , grid_span , global_grid_size , static_grid ) ;
  printf( "  surfacing grid\n" ) ;
  surface_grid( grid_span , global_grid_size , static_grid , surface , internal_value ) ;

  /* Calculate electic field at all grid nodes (need do only once) */
  if( electrostatics == 1 ) {
    electric_field( Origin_Static_Structure , grid_span , global_grid_size , static_elec_grid ) ;
    electric_field_zero_core( global_grid_size , static_elec_grid , static_grid , internal_value ) ;
  }

  /* Fourier Transform the static grids (need do only once) */
  printf( "  one time forward FFT calculations\n" ) ;
  fftwf_execute(ps);
  if( electrostatics == 1 ) {
    fftwf_execute(pse);
  }

  printf( "  done\n" ) ;

/************/

  /* Store paramaters in case of rescue */

  if( ( ftdock_file = fopen( "scratch_parameters.dat" , "w" ) ) == NULL ) {
    printf( "Could not open scratch_parameters.dat for writing.\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  fprintf( ftdock_file, "\nGlobal Scan\n" ) ;

  fprintf( ftdock_file, "\nCommand line controllable values\n" ) ;
  fprintf( ftdock_file, "Static molecule                    :: %s\n" , static_file_name ) ;
  fprintf( ftdock_file, "Mobile molecule                    :: %s\n" , mobile_file_name ) ;
  fprintf( ftdock_file, "Output file name                   :: %s\n" , output_file_name ) ;
  fprintf( ftdock_file, "\n" ) ;
  fprintf( ftdock_file, "Global grid size                   :: %6d      %s\n" , global_grid_size , default_global_grid_size ) ;
  fprintf( ftdock_file, "Global search angle step           :: %6d      %s\n" , angle_step , default_angle_step ) ;
  fprintf( ftdock_file, "Global surface thickness           :: %9.2f   %s\n" , surface , default_surface ) ;
  fprintf( ftdock_file, "Global internal deterrent value    :: %9.2f   %s\n" , internal_value , default_internal_value ) ;
  if( electrostatics == 1 ) {
    fprintf( ftdock_file, "Electrostatics                     ::     on      %s\n" , default_electrostatics ) ;
  } else {
    fprintf( ftdock_file, "Electrostatics                     ::    off      %s\n" , default_electrostatics ) ;
  }
  fprintf( ftdock_file, "Global keep per rotation           :: %6d      %s\n" , keep_per_rotation , default_keep_per_rotation ) ;

  fprintf( ftdock_file, "\nCalculated values\n" ) ;
  fprintf( ftdock_file, "Global rotations                   :: %6d\n" , Angles.n ) ;
  fprintf( ftdock_file, "Global total span (angstroms)      :: %10.3f\n" , grid_span ) ;
  fprintf( ftdock_file, "Global grid cell span (angstroms)  :: %10.3f\n" , one_span ) ;

  fclose( ftdock_file ) ;

/************/

  /* Main program loop */

  max_es_value = 0 ;

  printf( "Starting main loop through the rotations\n" ) ;

  /* PCA: start comment
     for( rotation = first_rotation ; rotation <= Angles.n ; rotation ++ ) {
   * PCA: end comment
   */
  for( rotation = first_rotation ; rotation <= 10/*Angles.n*/ ; rotation ++ ) {

    printf( "." ) ;

    if( ( rotation % 50 ) == 0 ) printf( "\nRotation number %5d\n" , rotation ) ;

    /* Rotate Mobile Structure */
    Rotated_at_Origin_Mobile_Structure =
     rotate_structure( Origin_Mobile_Structure , (int)Angles.z_twist[rotation] , (int)Angles.theta[rotation] , (int)Angles.phi[rotation] ) ;

    /* Discretise the rotated Mobile Structure */
    discretise_structure( Rotated_at_Origin_Mobile_Structure , grid_span , global_grid_size , mobile_grid ) ;

    /* Electic point charge approximation onto grid calculations ( quicker than filed calculations by a long way! ) */
    if( electrostatics == 1 ) {
      electric_point_charge( Rotated_at_Origin_Mobile_Structure , grid_span , global_grid_size , mobile_elec_grid ) ;
    }

    /* Forward Fourier Transforms */
    fftwf_execute(pm);
    if( electrostatics == 1 ) {
       fftwf_execute(pme);
    }

/************/

    /* Do convolution of the two sets of grids
       convolution is equivalent to multiplication of the complex conjugate of one
       fourier grid with other (raw) one
       hence the sign changes from a normal complex number multiplication
    */

    for( fx = 0 ; fx < global_grid_size ; fx ++ ) {
      for( fy = 0 ; fy < global_grid_size ; fy ++ ) {
        for( fz = 0 ; fz < global_grid_size/2 + 1 ; fz ++ ) {

          fxyz = fz + ( global_grid_size/2 + 1 ) * ( fy + global_grid_size * fx ) ;

          multiple_fsg[fxyz][0] =
           c_re(static_fsg[fxyz]) * c_re(mobile_fsg[fxyz]) + c_im(static_fsg[fxyz]) * c_im(mobile_fsg[fxyz]) ;
          multiple_fsg[fxyz][1] =
           c_im(static_fsg[fxyz]) * c_re(mobile_fsg[fxyz]) - c_re(static_fsg[fxyz]) * c_im(mobile_fsg[fxyz]) ;

          if( electrostatics == 1 ) {
            multiple_elec_fsg[fxyz][0] =
             c_re(static_elec_fsg[fxyz]) * c_re(mobile_elec_fsg[fxyz]) + c_im(static_elec_fsg[fxyz]) * c_im(mobile_elec_fsg[fxyz]) ;
            multiple_elec_fsg[fxyz][1] =
             c_im(static_elec_fsg[fxyz]) * c_re(mobile_elec_fsg[fxyz]) - c_re(static_elec_fsg[fxyz]) * c_im(mobile_elec_fsg[fxyz]) ;
          }

        }
      }
    }

    /* Reverse Fourier Transform */
    fftwf_execute(pinvs);
    if( electrostatics == 1 ) {
        fftwf_execute(pinvse);
    }

/************/

    /* Get best scores */

    for( i = 0 ; i < keep_per_rotation ; i ++ ) {

      Scores[i].score = 0 ;
      Scores[i].rpscore = 0.0 ;
      Scores[i].coord[1] = 0 ;
      Scores[i].coord[2] = 0 ;
      Scores[i].coord[3] = 0 ;

    }

    for( x = 0 ; x < global_grid_size ; x ++ ) {
      fx = x ;
      if( fx > ( global_grid_size / 2 ) ) fx -= global_grid_size ;

      for( y = 0 ; y < global_grid_size ; y ++ ) {
        fy = y ;
        if( fy > ( global_grid_size / 2 ) ) fy -= global_grid_size ;

        for( z = 0 ; z < global_grid_size ; z ++ ) {
          fz = z ;
          if( fz > ( global_grid_size / 2 ) ) fz -= global_grid_size ;

          xyz = z + ( 2 * ( global_grid_size / 2 + 1 ) ) * ( y + global_grid_size * x ) ;

          if( ( electrostatics == 0 ) || ( convoluted_elec_grid[xyz] < 0 ) ) {

            /* Scale factor from FFTs */
            if( (int)convoluted_grid[xyz] != 0 ) {
              convoluted_grid[xyz] /= ( global_grid_size * global_grid_size * global_grid_size ) ;
            }

            if( (int)convoluted_grid[xyz] > Scores[keep_per_rotation-1].score ) {

              i = keep_per_rotation - 2 ;

              while( ( (int)convoluted_grid[xyz] > Scores[i].score ) && ( i >= 0 ) ) {
                Scores[i+1].score    = Scores[i].score ;
                Scores[i+1].rpscore  = Scores[i].rpscore ;
                Scores[i+1].coord[1] = Scores[i].coord[1] ;
                Scores[i+1].coord[2] = Scores[i].coord[2] ;
                Scores[i+1].coord[3] = Scores[i].coord[3] ;
                i -- ;
              }

              Scores[i+1].score    = (int)convoluted_grid[xyz] ;
              if( ( electrostatics != 0 ) && ( convoluted_elec_grid[xyz] < 0.1 ) ) {
                Scores[i+1].rpscore  = (float)convoluted_elec_grid[xyz] ;
              } else {
                Scores[i+1].rpscore  = (float)0 ;
              }
              Scores[i+1].coord[1] = fx ;
              Scores[i+1].coord[2] = fy ;
              Scores[i+1].coord[3] = fz ;

            }

          }

        }
      }
    }

    if( rotation == 1 ) {
      if( ( ftdock_file = fopen( "scratch_scores.dat" , "w" ) ) == NULL ) {
        printf( "Could not open scratch_scores.dat for writing.\nDying\n\n" ) ;
        exit( EXIT_FAILURE ) ;
      }
    } else {
      if( ( ftdock_file = fopen( "scratch_scores.dat" , "a" ) ) == NULL ) {
        printf( "Could not open scratch_scores.dat for writing.\nDying\n\n" ) ;
        exit( EXIT_FAILURE ) ;
      }
    }

    for( i = 0 ; i < keep_per_rotation ; i ++ ) {

      max_es_value = min( max_es_value , Scores[i].rpscore ) ;
      /* PCA: start comment

      fprintf( ftdock_file, "G_DATA %6d   %6d    %7d       %.0f      %4d %4d %4d      %4d%4d%4d\n" ,
                rotation , 0 , Scores[i].score , (float)Scores[i].rpscore , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3 ] ,
                 Angles.z_twist[rotation] , Angles.theta[rotation]  , Angles.phi[rotation] ) ;

       * PCA: Stop comment
       */
      fprintf( stdout, "G_DATA %6d   %6d    %7d       %4d %4d %4d      %4d%4d%4d\n" ,
                rotation , 0 , Scores[i].score , Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3 ] ,
                 Angles.z_twist[rotation] , Angles.theta[rotation]  , Angles.phi[rotation] ) ;

    }

    fclose( ftdock_file ) ;

    /* Free some memory */
    for( i = 1 ; i <= Rotated_at_Origin_Mobile_Structure.length ; i ++ ) {
      free( Rotated_at_Origin_Mobile_Structure.Residue[i].Atom ) ;
    }
    free( Rotated_at_Origin_Mobile_Structure.Residue ) ;

  }

  /* Finished main loop */

/************/

  /* Free the memory */

  fftwf_destroy_plan( ps ) ;
  fftwf_destroy_plan( pse ) ;
  fftwf_destroy_plan( pm ) ;
  fftwf_destroy_plan( pme ) ;
  fftwf_destroy_plan( pinvs ) ;
  fftwf_destroy_plan( pinvse ) ;

  free( static_grid ) ;
  free( mobile_grid ) ;
  free( convoluted_grid ) ;

  if( electrostatics == 1 ) {
    free( static_elec_grid ) ;
    free( mobile_elec_grid ) ;
    free( convoluted_elec_grid ) ;
  }

  for( i = 1 ; i <= Origin_Static_Structure.length ; i ++ ) {
    free( Origin_Static_Structure.Residue[i].Atom ) ;
  }
  free( Origin_Static_Structure.Residue ) ;

  for( i = 1 ; i <= Origin_Mobile_Structure.length ; i ++ ) {
    free( Origin_Mobile_Structure.Residue[i].Atom ) ;
  }
  free( Origin_Mobile_Structure.Residue ) ;

      /* PCA: Finishing programm here*/
      getrusage(RUSAGE_SELF, &ra);
      gettimeofday(&tva, NULL);
      struct timeval usertimea = ra.ru_utime;
      struct timeval systimea  = ra.ru_stime;

      unsigned long long usera = usertimea.tv_sec*1e6 + usertimea.tv_usec;
      unsigned long long sysa  = systimea.tv_sec*1e6  + systimea.tv_usec;

      struct timeval usertimeb = rb.ru_utime;
      struct timeval systimeb  = rb.ru_stime;

      unsigned long long userb = usertimeb.tv_sec*1e6 + usertimeb.tv_usec;
      unsigned long long sysb  = systimeb.tv_sec*1e6  + systimeb.tv_usec;

      unsigned long long user = usera - userb;
      unsigned long long sys = sysa - sysb;
      unsigned long long mem_max = ra.ru_maxrss;

      unsigned long long elapsed = (tva.tv_sec - tvb.tv_sec)*1e6 + (tva.tv_usec - tvb.tv_usec);

      fprintf(stderr, "{ \"elapsed\": %llu, \"user\": %llu, \"sys\": %llu, \"mem_max\": %llu }", elapsed, user, sys, mem_max);

      return 0;
      /* PCA: */


/************/

  /* Read in all the scores */

  printf( "\nReloading all the scores\n" ) ;

  if( ( ftdock_file = fopen( "scratch_scores.dat" , "r" ) ) == NULL ) {
    printf( "Could not open scratch_scores.dat for reading.\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  if( ( Scores = ( struct Score * ) realloc ( Scores , ( 1 + keep_per_rotation ) * Angles.n * sizeof( struct Score ) ) ) == NULL ) {
    printf( "Not enough memory left for storing scores\nProbably keeping too many per rotation\nDying\n\n" ) ;
    exit( EXIT_FAILURE ) ;
  }

  kept_scores = 0 ;

  while( fgets( line_buffer , 99 , ftdock_file ) ) {

    sscanf( line_buffer , "G_DATA %d %d %d %f  %d %d %d  %d %d %d" , &id , &id2 , &SCscore , &RPscore ,
                                                                     &x , &y , &z , &z_twist , &theta , &phi ) ;

    Scores[kept_scores].score    = SCscore ;
    Scores[kept_scores].rpscore  = RPscore ;
    Scores[kept_scores].coord[1] = x ;
    Scores[kept_scores].coord[2] = y ;
    Scores[kept_scores].coord[3] = z ;
    Scores[kept_scores].angle[1] = z_twist ;
    Scores[kept_scores].angle[2] = theta ;
    Scores[kept_scores].angle[3] = phi ;

    kept_scores ++ ;

  }

  fclose( ftdock_file ) ;

  kept_scores -- ;

  qsort_scores( Scores , 0 , kept_scores ) ;

/************/

  /* Writing data file */

  if( ( ftdock_file = fopen( output_file_name , "w" ) ) == NULL ) {
    printf( "Could not open %s for writing.\nDying\n\n" , output_file_name ) ;
    exit( EXIT_FAILURE ) ;
  }

  fprintf( ftdock_file, "FTDOCK data file\n" ) ;

  fprintf( ftdock_file, "\nGlobal Scan\n" ) ;

  fprintf( ftdock_file, "\nCommand line controllable values\n" ) ;
  fprintf( ftdock_file, "Static molecule                    :: %s\n" , static_file_name ) ;
  fprintf( ftdock_file, "Mobile molecule                    :: %s\n" , mobile_file_name ) ;
  fprintf( ftdock_file, "\n" ) ;
  fprintf( ftdock_file, "Global grid size                   :: %6d      %s\n" , global_grid_size , default_global_grid_size ) ;
  fprintf( ftdock_file, "Global search angle step           :: %6d      %s\n" , angle_step , default_angle_step ) ;
  fprintf( ftdock_file, "Global surface thickness           :: %9.2f   %s\n" , surface , default_surface ) ;
  fprintf( ftdock_file, "Global internal deterrent value    :: %9.2f   %s\n" , internal_value , default_internal_value ) ;
  if( electrostatics == 1 ) {
    fprintf( ftdock_file, "Electrostatics                     ::     on      %s\n" , default_electrostatics ) ;
  } else {
    fprintf( ftdock_file, "Electrostatics                     ::    off      %s\n" , default_electrostatics ) ;
  }
  fprintf( ftdock_file, "Global keep per rotation           :: %6d      %s\n" , keep_per_rotation , default_keep_per_rotation ) ;

  fprintf( ftdock_file, "\nCalculated values\n" ) ;
  fprintf( ftdock_file, "Global rotations                   :: %6d\n" , Angles.n ) ;
  fprintf( ftdock_file, "Global total span (angstroms)      :: %10.3f\n" , grid_span ) ;
  fprintf( ftdock_file, "Global grid cell span (angstroms)  :: %10.3f\n" , one_span ) ;

  fprintf( ftdock_file, "\nData\n" ) ;
  fprintf( ftdock_file , "Type       ID    prvID    SCscore        ESratio         Coordinates            Angles\n\n" ) ;

  if( electrostatics == 1 ) {

    for( i = 0 ; i <= min( kept_scores , ( NUMBER_TO_KEEP - 1 ) ) ; i ++ ) {

      fprintf( ftdock_file, "G_DATA %6d   %6d    %7d       %8.3f      %4d %4d %4d      %4d%4d%4d\n" ,
               i + 1 , 0 , Scores[i].score , 100 * ( Scores[i].rpscore / max_es_value ) ,
               Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3] ,
               Scores[i].angle[1] , Scores[i].angle[2] , Scores[i].angle[3] ) ;

    }

  } else {

    for( i = 0 ; i <= min( kept_scores , ( NUMBER_TO_KEEP - 1 ) ) ; i ++ ) {

      fprintf( ftdock_file, "G_DATA %6d   %6d    %7d       %8.3f      %4d %4d %4d      %4d%4d%4d\n" ,
               i + 1 , 0 , Scores[i].score , 0.0 ,
               Scores[i].coord[1] , Scores[i].coord[2] , Scores[i].coord[3] ,
               Scores[i].angle[1] , Scores[i].angle[2] , Scores[i].angle[3] ) ;

    }

  }

  fclose( ftdock_file ) ;

/************/

  printf( "\n\nFinished\n\n" ) ;

  return( 0 ) ;

} /* end main */